From 20b4ce5446d313c33f50d9f96a21347e2a074ec6 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 3 Sep 2025 16:24:42 -0700 Subject: [PATCH] improvements --- models/project/workflows.go | 87 ++++---- options/locale/locale_en-US.ini | 5 +- routers/web/projects/workflows.go | 15 +- services/projects/workflow_notifier.go | 2 +- .../components/projects/ProjectWorkflow.vue | 192 ++++++++++++++++-- .../js/components/projects/WorkflowStore.ts | 77 ++++++- 6 files changed, 304 insertions(+), 74 deletions(-) diff --git a/models/project/workflows.go b/models/project/workflows.go index 675b164b24..4bfba3a61d 100644 --- a/models/project/workflows.go +++ b/models/project/workflows.go @@ -16,27 +16,25 @@ import ( type WorkflowEvent string const ( + WorkflowEventItemOpened WorkflowEvent = "item_opened" WorkflowEventItemAddedToProject WorkflowEvent = "item_added_to_project" WorkflowEventItemReopened WorkflowEvent = "item_reopened" WorkflowEventItemClosed WorkflowEvent = "item_closed" + WorkflowEventItemColumnChanged WorkflowEvent = "item_column_changed" WorkflowEventCodeChangesRequested WorkflowEvent = "code_changes_requested" WorkflowEventCodeReviewApproved WorkflowEvent = "code_review_approved" WorkflowEventPullRequestMerged WorkflowEvent = "pull_request_merged" - WorkflowEventAutoArchiveItems WorkflowEvent = "auto_archive_items" - WorkflowEventAutoAddToProject WorkflowEvent = "auto_add_to_project" - WorkflowEventAutoCloseIssue WorkflowEvent = "auto_close_issue" ) var workflowEvents = []WorkflowEvent{ + WorkflowEventItemOpened, WorkflowEventItemAddedToProject, WorkflowEventItemReopened, WorkflowEventItemClosed, + WorkflowEventItemColumnChanged, WorkflowEventCodeChangesRequested, WorkflowEventCodeReviewApproved, WorkflowEventPullRequestMerged, - WorkflowEventAutoArchiveItems, - WorkflowEventAutoAddToProject, - WorkflowEventAutoCloseIssue, } func GetWorkflowEvents() []WorkflowEvent { @@ -45,24 +43,22 @@ func GetWorkflowEvents() []WorkflowEvent { func (we WorkflowEvent) LangKey() string { switch we { + case WorkflowEventItemOpened: + return "projects.workflows.event.item_opened" case WorkflowEventItemAddedToProject: return "projects.workflows.event.item_added_to_project" case WorkflowEventItemReopened: return "projects.workflows.event.item_reopened" case WorkflowEventItemClosed: return "projects.workflows.event.item_closed" + case WorkflowEventItemColumnChanged: + return "projects.workflows.event.item_column_changed" case WorkflowEventCodeChangesRequested: return "projects.workflows.event.code_changes_requested" case WorkflowEventCodeReviewApproved: return "projects.workflows.event.code_review_approved" case WorkflowEventPullRequestMerged: return "projects.workflows.event.pull_request_merged" - case WorkflowEventAutoArchiveItems: - return "projects.workflows.event.auto_archive_items" - case WorkflowEventAutoAddToProject: - return "projects.workflows.event.auto_add_to_project" - case WorkflowEventAutoCloseIssue: - return "projects.workflows.event.auto_close_issue" default: return string(we) } @@ -70,24 +66,22 @@ func (we WorkflowEvent) LangKey() string { func (we WorkflowEvent) UUID() string { switch we { + case WorkflowEventItemOpened: + return "item_opened" case WorkflowEventItemAddedToProject: return "item_added_to_project" case WorkflowEventItemReopened: return "item_reopened" case WorkflowEventItemClosed: return "item_closed" + case WorkflowEventItemColumnChanged: + return "item_column_changed" case WorkflowEventCodeChangesRequested: return "code_changes_requested" case WorkflowEventCodeReviewApproved: return "code_review_approved" case WorkflowEventPullRequestMerged: return "pull_request_merged" - case WorkflowEventAutoArchiveItems: - return "auto_archive_items" - case WorkflowEventAutoAddToProject: - return "auto_add_to_project" - case WorkflowEventAutoCloseIssue: - return "auto_close_issue" default: return string(we) } @@ -96,20 +90,21 @@ func (we WorkflowEvent) UUID() string { type WorkflowFilterType string const ( - WorkflowFilterTypeScope WorkflowFilterType = "scope" // issue, pull_request, etc. + WorkflowFilterTypeIssueType WorkflowFilterType = "issue_type" // issue, pull_request, etc. ) type WorkflowFilter struct { Type WorkflowFilterType - Value string // e.g., "issue", "pull_request", etc. + Value string // e.g., "issue", "pull_request", etc. depends on the filter type definition } type WorkflowActionType string const ( - WorkflowActionTypeColumn WorkflowActionType = "column" // add the item to the project's column - WorkflowActionTypeLabel WorkflowActionType = "label" // choose one or more labels - WorkflowActionTypeClose WorkflowActionType = "close" // close the issue + WorkflowActionTypeColumn WorkflowActionType = "column" // add the item to the project's column + WorkflowActionTypeAddLabels WorkflowActionType = "add_labels" // choose one or more labels + WorkflowActionTypeRemoveLabels WorkflowActionType = "remove_labels" // choose one or more labels + WorkflowActionTypeClose WorkflowActionType = "close" // close the issue ) type WorkflowAction struct { @@ -119,48 +114,44 @@ type WorkflowAction struct { // WorkflowEventCapabilities defines what filters and actions are available for each event type WorkflowEventCapabilities struct { - AvailableFilters []string `json:"available_filters"` + AvailableFilters []WorkflowFilterType `json:"available_filters"` AvailableActions []WorkflowActionType `json:"available_actions"` } // GetWorkflowEventCapabilities returns the capabilities for each workflow event func GetWorkflowEventCapabilities() map[WorkflowEvent]WorkflowEventCapabilities { return map[WorkflowEvent]WorkflowEventCapabilities{ + WorkflowEventItemOpened: { + AvailableFilters: []WorkflowFilterType{WorkflowFilterTypeIssueType}, // issue, pull_request + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels}, + }, WorkflowEventItemAddedToProject: { - AvailableFilters: []string{"scope"}, // issue, pull_request - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{WorkflowFilterTypeIssueType}, // issue, pull_request + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, }, WorkflowEventItemReopened: { - AvailableFilters: []string{"scope"}, - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{WorkflowFilterTypeIssueType}, + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, }, WorkflowEventItemClosed: { - AvailableFilters: []string{"scope"}, - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{WorkflowFilterTypeIssueType}, + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, + }, + WorkflowEventItemColumnChanged: { + AvailableFilters: []WorkflowFilterType{WorkflowFilterTypeIssueType}, + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels, WorkflowActionTypeClose}, }, WorkflowEventCodeChangesRequested: { - AvailableFilters: []string{}, // only applies to pull requests - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{}, // only applies to pull requests + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, }, WorkflowEventCodeReviewApproved: { - AvailableFilters: []string{}, // only applies to pull requests - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{}, // only applies to pull requests + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, }, WorkflowEventPullRequestMerged: { - AvailableFilters: []string{}, // only applies to pull requests - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel, WorkflowActionTypeClose}, - }, - WorkflowEventAutoArchiveItems: { - AvailableFilters: []string{"scope"}, - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn}, - }, - WorkflowEventAutoAddToProject: { - AvailableFilters: []string{"scope"}, - AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeLabel}, - }, - WorkflowEventAutoCloseIssue: { - AvailableFilters: []string{}, // only applies to issues - AvailableActions: []WorkflowActionType{WorkflowActionTypeClose, WorkflowActionTypeLabel}, + AvailableFilters: []WorkflowFilterType{}, // only applies to pull requests + AvailableActions: []WorkflowActionType{WorkflowActionTypeColumn, WorkflowActionTypeAddLabels, WorkflowActionTypeRemoveLabels}, }, } } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 40795046a4..f29d9f0946 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3904,15 +3904,14 @@ type-3.display_name = Organization Project enter_fullscreen = Fullscreen workflows = Workflows exit_fullscreen = Exit Fullscreen +workflows.event.item_opened = Item opened workflows.event.item_added_to_project = Item added to project workflows.event.item_reopened = Item reopened workflows.event.item_closed = Item closed +workflows.event.item_column_changed = Item column changed workflows.event.code_changes_requested = Code changes requested workflows.event.code_review_approved = Code review approved workflows.event.pull_request_merged = Pull request merged -workflows.event.auto_archive_items = Auto archive items -workflows.event.auto_add_to_project = Auto add to project -workflows.event.auto_close_issue = Auto close issue [git.filemode] changed_filemode = %[1]s → %[2]s diff --git a/routers/web/projects/workflows.go b/routers/web/projects/workflows.go index 72ec5a9ec1..3906ba72b3 100644 --- a/routers/web/projects/workflows.go +++ b/routers/web/projects/workflows.go @@ -68,12 +68,23 @@ func convertFormToActions(formActions map[string]any) []project_model.WorkflowAc ActionValue: strValue, }) } - case "labels": + case "add_labels": if labels, ok := value.([]string); ok && len(labels) > 0 { for _, label := range labels { if label != "" { actions = append(actions, project_model.WorkflowAction{ - ActionType: project_model.WorkflowActionTypeLabel, + ActionType: project_model.WorkflowActionTypeAddLabels, + ActionValue: label, + }) + } + } + } + case "remove_labels": + if labels, ok := value.([]string); ok && len(labels) > 0 { + for _, label := range labels { + if label != "" { + actions = append(actions, project_model.WorkflowAction{ + ActionType: project_model.WorkflowActionTypeRemoveLabels, ActionValue: label, }) } diff --git a/services/projects/workflow_notifier.go b/services/projects/workflow_notifier.go index 9de28d005f..96a9d1a7f7 100644 --- a/services/projects/workflow_notifier.go +++ b/services/projects/workflow_notifier.go @@ -89,7 +89,7 @@ func (m *workflowNotifier) IssueChangeStatus(ctx context.Context, doer *user_mod func fireIssueWorkflow(ctx context.Context, workflow *project_model.Workflow, issue *issues_model.Issue) { for _, filter := range workflow.WorkflowFilters { switch filter.Type { - case project_model.WorkflowFilterTypeScope: + case project_model.WorkflowFilterTypeIssueType: values := strings.Split(filter.Value, ",") if !(slices.Contains(values, "issue") && !issue.IsPull) || (slices.Contains(values, "pull") && issue.IsPull) { return diff --git a/web_src/js/components/projects/ProjectWorkflow.vue b/web_src/js/components/projects/ProjectWorkflow.vue index f40c3e5e06..61179a43ab 100644 --- a/web_src/js/components/projects/ProjectWorkflow.vue +++ b/web_src/js/components/projects/ProjectWorkflow.vue @@ -1,5 +1,5 @@