improvements

pull/30205/head
Lunny Xiao 2025-09-04 10:01:53 +07:00
parent 6411e212af
commit 990d8000fd
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
2 changed files with 69 additions and 30 deletions

@ -221,7 +221,7 @@ func CreateWorkflow(ctx context.Context, wf *Workflow) error {
} }
func UpdateWorkflow(ctx context.Context, wf *Workflow) error { func UpdateWorkflow(ctx context.Context, wf *Workflow) error {
_, err := db.GetEngine(ctx).ID(wf.ID).Update(wf) _, err := db.GetEngine(ctx).ID(wf.ID).Cols("workflow_filters", "workflow_actions").Update(wf)
return err return err
} }

@ -12,11 +12,37 @@ const props = defineProps({
const store = createWorkflowStore(props); const store = createWorkflowStore(props);
const editMode = ref(false); // Track edit state directly on workflow objects
const previousSelection = ref(null); // Store previous selection for cancel functionality const previousSelection = ref(null);
// Helper to check if current workflow is in edit mode
const isInEditMode = computed(() => {
if (!store.selectedWorkflow) return false;
// Unconfigured workflows (id === 0) are always in edit mode
if (store.selectedWorkflow.id === 0) {
return true;
}
// Configured workflows use the _isEditing flag
return store.selectedWorkflow._isEditing || false;
});
// Helper to set edit mode for current workflow
const setEditMode = (enabled) => {
if (store.selectedWorkflow) {
if (enabled) {
store.selectedWorkflow._isEditing = true;
} else {
delete store.selectedWorkflow._isEditing;
}
}
};
// Store previous selection for cancel functionality
const toggleEditMode = () => { const toggleEditMode = () => {
if (editMode.value) { if (isInEditMode.value) {
// Canceling edit mode // Canceling edit mode
if (previousSelection.value) { if (previousSelection.value) {
// If there was a previous selection, return to it // If there was a previous selection, return to it
@ -38,15 +64,15 @@ const toggleEditMode = () => {
} }
previousSelection.value = null; previousSelection.value = null;
} }
setEditMode(false);
} else { } else {
// Entering edit mode - store current selection // Entering edit mode - store current selection
previousSelection.value = { previousSelection.value = {
selectedItem: store.selectedItem, selectedItem: store.selectedItem,
selectedWorkflow: store.selectedWorkflow ? {...store.selectedWorkflow} : null selectedWorkflow: store.selectedWorkflow ? {...store.selectedWorkflow} : null
}; };
setEditMode(true);
} }
editMode.value = !editMode.value;
}; };
const toggleWorkflowStatus = async () => { const toggleWorkflowStatus = async () => {
@ -101,7 +127,7 @@ const deleteWorkflow = async () => {
// Clear previous selection and exit edit mode // Clear previous selection and exit edit mode
previousSelection.value = null; previousSelection.value = null;
editMode.value = false; setEditMode(false);
}; };
const selectWorkflowEvent = async (event) => { const selectWorkflowEvent = async (event) => {
@ -141,7 +167,7 @@ const saveWorkflow = async () => {
// Clear previous selection after successful save // Clear previous selection after successful save
previousSelection.value = null; previousSelection.value = null;
editMode.value = false; setEditMode(false);
}; };
const isWorkflowConfigured = (event) => { const isWorkflowConfigured = (event) => {
@ -197,7 +223,7 @@ const workflowList = computed(() => {
const createNewWorkflow = (baseEventType, capabilities, displayName) => { const createNewWorkflow = (baseEventType, capabilities, displayName) => {
// Store current selection before creating new workflow // Store current selection before creating new workflow
if (!editMode.value) { if (!isInEditMode.value) {
previousSelection.value = { previousSelection.value = {
selectedItem: store.selectedItem, selectedItem: store.selectedItem,
selectedWorkflow: store.selectedWorkflow ? {...store.selectedWorkflow} : null selectedWorkflow: store.selectedWorkflow ? {...store.selectedWorkflow} : null
@ -222,7 +248,7 @@ const createNewWorkflow = (baseEventType, capabilities, displayName) => {
// For unconfigured events, use the base event type as selected item for UI consistency // For unconfigured events, use the base event type as selected item for UI consistency
store.selectedItem = baseEventType; store.selectedItem = baseEventType;
store.resetWorkflowData(); store.resetWorkflowData();
editMode.value = true; // Auto-enter edit mode for new workflows // Unconfigured workflows are always in edit mode by default
}; };
const cloneWorkflow = (sourceWorkflow) => { const cloneWorkflow = (sourceWorkflow) => {
@ -263,7 +289,7 @@ const cloneWorkflow = (sourceWorkflow) => {
// Load the source workflow's data into the form // Load the source workflow's data into the form
store.loadWorkflowData(sourceWorkflow.event_id); store.loadWorkflowData(sourceWorkflow.event_id);
editMode.value = true; // Auto-enter edit mode for cloned workflows // Cloned workflows (id: 0) are always in edit mode by default
// Update URL for cloned workflow // Update URL for cloned workflow
const newUrl = `${props.projectLink}/workflows/${tempId}`; const newUrl = `${props.projectLink}/workflows/${tempId}`;
@ -281,8 +307,8 @@ const selectWorkflowItem = async (item) => {
selectTimeout = null; selectTimeout = null;
}, 300); }, 300);
editMode.value = false; // Reset edit mode when switching workflows
previousSelection.value = null; // Clear previous selection when manually selecting previousSelection.value = null; // Clear previous selection when manually selecting
// Don't reset edit mode when switching - each workflow keeps its own state
// Wait for DOM update to prevent conflicts // Wait for DOM update to prevent conflicts
await nextTick(); await nextTick();
@ -291,9 +317,21 @@ const selectWorkflowItem = async (item) => {
// This is a configured workflow, select it // This is a configured workflow, select it
await selectWorkflowEvent(item); await selectWorkflowEvent(item);
} else { } else {
// This is an unconfigured event, create new workflow // This is an unconfigured event - check if we already have a workflow object for it
createNewWorkflow(item.base_event_type, item.capabilities, item.display_name); const existingWorkflow = store.workflowEvents.find(w =>
// Update URL for new workflow w.id === 0 &&
(w.base_event_type === item.base_event_type || w.workflow_event === item.base_event_type)
);
if (existingWorkflow) {
// We already have an unconfigured workflow for this event type, select it
await selectWorkflowEvent(existingWorkflow);
} else {
// This is truly a new unconfigured event, create new workflow
createNewWorkflow(item.base_event_type, item.capabilities, item.display_name);
}
// Update URL for workflow
const newUrl = `${props.projectLink}/workflows/${item.base_event_type}`; const newUrl = `${props.projectLink}/workflows/${item.base_event_type}`;
window.history.pushState({eventId: item.base_event_type}, '', newUrl); window.history.pushState({eventId: item.base_event_type}, '', newUrl);
} }
@ -404,7 +442,6 @@ onMounted(async () => {
store.selectedItem = props.eventID; store.selectedItem = props.eventID;
store.selectedWorkflow = selectedEvent; store.selectedWorkflow = selectedEvent;
await store.loadWorkflowData(props.eventID); await store.loadWorkflowData(props.eventID);
editMode.value = false;
} else { } else {
// Check if eventID matches a base event type (unconfigured workflow) // Check if eventID matches a base event type (unconfigured workflow)
const items = workflowList.value; const items = workflowList.value;
@ -541,29 +578,31 @@ onUnmounted(() => {
<h2> <h2>
<i class="settings icon"/> <i class="settings icon"/>
{{ store.selectedWorkflow.display_name }} {{ store.selectedWorkflow.display_name }}
<span v-if="store.selectedWorkflow.id > 0 && !editMode" <span v-if="store.selectedWorkflow.id > 0 && !isInEditMode"
class="workflow-status" class="workflow-status"
:class="store.selectedWorkflow.enabled ? 'status-enabled' : 'status-disabled'"> :class="store.selectedWorkflow.enabled ? 'status-enabled' : 'status-disabled'">
{{ store.selectedWorkflow.enabled ? 'Enabled' : 'Disabled' }} {{ store.selectedWorkflow.enabled ? 'Enabled' : 'Disabled' }}
</span> </span>
</h2> </h2>
<p v-if="editMode">Configure automated actions for this workflow</p> <p v-if="store.selectedWorkflow.id === 0">Configure automated actions for this workflow</p>
<p v-else-if="isInEditMode">Configure automated actions for this workflow</p>
<p v-else>View workflow configuration</p> <p v-else>View workflow configuration</p>
</div> </div>
<div class="editor-actions-header"> <div class="editor-actions-header">
<!-- Edit/Cancel Button --> <!-- Edit/Cancel Button (only for configured workflows) -->
<button <button
v-if="store.selectedWorkflow && store.selectedWorkflow.id > 0"
class="btn" class="btn"
:class="editMode ? 'btn-outline-secondary' : 'btn-primary'" :class="isInEditMode ? 'btn-outline-secondary' : 'btn-primary'"
@click="toggleEditMode" @click="toggleEditMode"
> >
<i :class="editMode ? 'times icon' : 'edit icon'"/> <i :class="isInEditMode ? 'times icon' : 'edit icon'"/>
{{ editMode ? 'Cancel' : 'Edit' }} {{ isInEditMode ? 'Cancel' : 'Edit' }}
</button> </button>
<!-- Enable/Disable Button (only for configured workflows) --> <!-- Enable/Disable Button (only for configured workflows) -->
<button <button
v-if="store.selectedWorkflow && store.selectedWorkflow.id > 0 && !editMode" v-if="store.selectedWorkflow && store.selectedWorkflow.id > 0 && !isInEditMode"
class="btn" class="btn"
:class="store.selectedWorkflow.enabled ? 'btn-outline-danger' : 'btn-success'" :class="store.selectedWorkflow.enabled ? 'btn-outline-danger' : 'btn-success'"
@click="toggleWorkflowStatus" @click="toggleWorkflowStatus"
@ -575,7 +614,7 @@ onUnmounted(() => {
<!-- Clone Button (only for configured workflows) --> <!-- Clone Button (only for configured workflows) -->
<button <button
v-if="store.selectedWorkflow && store.selectedWorkflow.id > 0 && !editMode" v-if="store.selectedWorkflow && store.selectedWorkflow.id > 0 && !isInEditMode"
class="btn btn-outline-secondary" class="btn btn-outline-secondary"
@click="cloneWorkflow(store.selectedWorkflow)" @click="cloneWorkflow(store.selectedWorkflow)"
title="Clone this workflow" title="Clone this workflow"
@ -587,7 +626,7 @@ onUnmounted(() => {
</div> </div>
<div class="editor-content"> <div class="editor-content">
<div class="form" :class="{ 'readonly': !editMode }"> <div class="form" :class="{ 'readonly': !isInEditMode }">
<div class="field"> <div class="field">
<label>When</label> <label>When</label>
<div class="segment"> <div class="segment">
@ -604,7 +643,7 @@ onUnmounted(() => {
<div class="field" v-if="hasFilter('issue_type')"> <div class="field" v-if="hasFilter('issue_type')">
<label>Apply to</label> <label>Apply to</label>
<select <select
v-if="editMode" v-if="isInEditMode"
class="form-select" class="form-select"
v-model="store.workflowFilters.issue_type" v-model="store.workflowFilters.issue_type"
> >
@ -628,7 +667,7 @@ onUnmounted(() => {
<div class="field" v-if="hasAction('column')"> <div class="field" v-if="hasAction('column')">
<label>Move to column</label> <label>Move to column</label>
<select <select
v-if="editMode" v-if="isInEditMode"
class="form-select" class="form-select"
v-model="store.workflowActions.column" v-model="store.workflowActions.column"
> >
@ -645,7 +684,7 @@ onUnmounted(() => {
<div class="field" v-if="hasAction('label')"> <div class="field" v-if="hasAction('label')">
<label>Add labels</label> <label>Add labels</label>
<select <select
v-if="editMode" v-if="isInEditMode"
class="form-select" class="form-select"
v-model="store.workflowActions.labels" v-model="store.workflowActions.labels"
multiple multiple
@ -662,7 +701,7 @@ onUnmounted(() => {
</div> </div>
<div class="field" v-if="hasAction('close')"> <div class="field" v-if="hasAction('close')">
<div v-if="editMode" class="form-check"> <div v-if="isInEditMode" class="form-check">
<input type="checkbox" v-model="store.workflowActions.closeIssue" id="close-issue"> <input type="checkbox" v-model="store.workflowActions.closeIssue" id="close-issue">
<label for="close-issue">Close issue</label> <label for="close-issue">Close issue</label>
</div> </div>
@ -677,7 +716,7 @@ onUnmounted(() => {
</div> </div>
<!-- Fixed bottom actions (only show in edit mode) --> <!-- Fixed bottom actions (only show in edit mode) -->
<div v-if="editMode" class="editor-actions"> <div v-if="isInEditMode" class="editor-actions">
<button class="btn btn-primary" @click="saveWorkflow" :disabled="store.saving"> <button class="btn btn-primary" @click="saveWorkflow" :disabled="store.saving">
<i class="save icon"/> <i class="save icon"/>
Save Workflow Save Workflow