feat(admin): add route templates to editor

This commit is contained in:
RhenCloud 2026-08-03 08:16:34 +08:00
parent d6c15a32cd
commit a001efea5f
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
4 changed files with 178 additions and 1 deletions

View file

@ -619,6 +619,39 @@ main {
color: var(--faint);
}
.templates {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.template-chip {
padding: 5px 12px;
background: var(--surface-2);
border: 1px solid var(--border-strong);
border-radius: 999px;
color: var(--muted);
font-family: var(--ui);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition:
border-color 0.15s,
color 0.15s,
background 0.15s;
}
.template-chip:hover {
border-color: var(--accent);
color: var(--accent);
}
.template-chip.active {
background: var(--accent-dim);
border-color: var(--accent);
color: var(--accent);
}
.field input[type="text"] {
width: 100%;
padding: 10px 12px;

View file

@ -10,6 +10,24 @@
<button class="icon-btn" :title="t('routeEditor.close')" @click="close"></button>
</div>
<form class="editor-body" @submit.prevent="save">
<div v-if="!isEdit" class="field">
<label
>{{ t("routeEditor.templates") }}
<span class="lbl-note">{{ t("routeEditor.templatesNote") }}</span></label
>
<div class="templates">
<button
v-for="tmpl in ROUTE_TEMPLATES"
:key="tmpl.id"
type="button"
class="template-chip"
:class="{ active: form.id === tmpl.id }"
@click="applyTemplate(tmpl)"
>
{{ t(tmpl.nameKey) }}
</button>
</div>
</div>
<div class="field">
<label>{{ t("routeEditor.name") }}</label>
<input
@ -139,7 +157,7 @@
<script setup lang="ts">
import { reactive, watch } from "vue";
import type { Filter, Route, RouteTarget } from "~/types";
import { FILTER_TYPES, fmtMatch } from "~/types";
import { FILTER_TYPES, ROUTE_TEMPLATES, fmtMatch } from "~/types";
interface FilterForm extends Filter {
matchText: string;
@ -199,6 +217,19 @@ function addFilter(): void {
filterError.value = "";
}
function applyTemplate(tmpl: (typeof ROUTE_TEMPLATES)[number]): void {
form.id = tmpl.id;
form.name = t(tmpl.nameKey);
form.filters = tmpl.filters.map((f) => ({
...f,
matchText: fmtMatch(f.match),
})) as FilterForm[];
form.targets = [blankTarget()];
filterError.value = "";
targetError.value = "";
formError.value = "";
}
function addTarget(): void {
form.targets.push(blankTarget());
targetError.value = "";

View file

@ -46,6 +46,21 @@ const en: Dict = {
"routeEditor.editTitle": "Edit route",
"routeEditor.newTitle": "New route",
"routeEditor.close": "Close",
"routeEditor.templates": "Templates",
"routeEditor.templatesNote": "(click to prefill filters)",
"templates.push": "Push",
"templates.pullRequest": "Pull Request",
"templates.issues": "Issues",
"templates.release": "Release",
"templates.workflow": "Workflow",
"templates.checks": "Check Suite",
"templates.deployment": "Deployment",
"templates.comments": "Comments",
"templates.reviews": "Review",
"templates.starFork": "Star / Fork",
"templates.createDelete": "Create / Delete",
"templates.member": "Member",
"templates.commitComment": "Commit Comment",
"routeEditor.name": "Name",
"routeEditor.namePlaceholder": "My Route",
"routeEditor.id": "ID",
@ -186,6 +201,21 @@ const zh: Dict = {
"routeEditor.editTitle": "编辑路由",
"routeEditor.newTitle": "新建路由",
"routeEditor.close": "关闭",
"routeEditor.templates": "模板",
"routeEditor.templatesNote": "(点击可预填过滤器)",
"templates.push": "推送",
"templates.pullRequest": "拉取请求",
"templates.issues": "议题",
"templates.release": "发布",
"templates.workflow": "工作流",
"templates.checks": "检查套件",
"templates.deployment": "部署",
"templates.comments": "评论",
"templates.reviews": "评审",
"templates.starFork": "星标 / 复刻",
"templates.createDelete": "创建 / 删除",
"templates.member": "协作者",
"templates.commitComment": "提交评论",
"routeEditor.name": "名称",
"routeEditor.namePlaceholder": "我的路由",
"routeEditor.id": "ID",

View file

@ -38,6 +38,89 @@ export interface Me {
groups: Group[];
}
export interface RouteTemplate {
id: string;
nameKey: string;
filters: Filter[];
}
export const ROUTE_TEMPLATES: RouteTemplate[] = [
{
id: "push-events",
nameKey: "templates.push",
filters: [{ type: "event", match: "push" }],
},
{
id: "pull-requests",
nameKey: "templates.pullRequest",
filters: [
{ type: "event", match: "pull_request" },
{ type: "action", match: ["opened", "synchronize", "reopened", "closed"] },
],
},
{
id: "issues",
nameKey: "templates.issues",
filters: [
{ type: "event", match: "issues" },
{ type: "action", match: ["opened", "edited", "closed", "reopened"] },
],
},
{
id: "releases",
nameKey: "templates.release",
filters: [
{ type: "event", match: "release" },
{ type: "action", match: ["published"] },
],
},
{
id: "workflows",
nameKey: "templates.workflow",
filters: [{ type: "event", match: ["workflow_job", "workflow_run"] }],
},
{
id: "checks",
nameKey: "templates.checks",
filters: [{ type: "event", match: ["check_suite", "check_run"] }],
},
{
id: "deployments",
nameKey: "templates.deployment",
filters: [{ type: "event", match: "deployment" }],
},
{
id: "comments",
nameKey: "templates.comments",
filters: [{ type: "event", match: ["issue_comment", "pull_request_review_comment"] }],
},
{
id: "reviews",
nameKey: "templates.reviews",
filters: [{ type: "event", match: "pull_request_review" }],
},
{
id: "star-fork",
nameKey: "templates.starFork",
filters: [{ type: "event", match: ["star", "fork"] }],
},
{
id: "create-delete",
nameKey: "templates.createDelete",
filters: [{ type: "event", match: ["create", "delete"] }],
},
{
id: "members",
nameKey: "templates.member",
filters: [{ type: "event", match: "member" }],
},
{
id: "commit-comments",
nameKey: "templates.commitComment",
filters: [{ type: "event", match: "commit_comment" }],
},
];
export const FILTER_TYPES = ["event", "repo", "actor", "action", "branch", "keyword"] as const;
export const FILTER_LABELS: Record<string, string> = {