diff --git a/tests/integration/project_workflow_test.go b/tests/integration/project_workflow_test.go
index 64458292a8..72de6bed08 100644
--- a/tests/integration/project_workflow_test.go
+++ b/tests/integration/project_workflow_test.go
@@ -442,5 +442,5 @@ func TestProjectWorkflowPermissions(t *testing.T) {
session2 := loginUser(t, user2.Name)
req = NewRequest(t, "POST",
fmt.Sprintf("/%s/%s/projects/%d/workflows/%d/delete?_csrf=%s", user.Name, repo.Name, project.ID, workflow.ID, GetUserCSRFToken(t, session2)))
- session2.MakeRequest(t, req, http.StatusForbidden)
+ session2.MakeRequest(t, req, http.StatusNotFound) // we use 404 to avoid leaking existence
}
diff --git a/web_src/js/components/LabelSelector.vue b/web_src/js/components/LabelSelector.vue
new file mode 100644
index 0000000000..5a86453239
--- /dev/null
+++ b/web_src/js/components/LabelSelector.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+ {{ placeholder }}
+
+
+ {{ labels.find(l => String(l.id) === labelId)?.name }}
+
+
+
+
+
+
+
+
+ None
+
+ {{ label.name }}
+
+
+
+
+
diff --git a/web_src/js/components/projects/ProjectWorkflow.vue b/web_src/js/components/projects/ProjectWorkflow.vue
index 26af654e7e..5d2a993732 100644
--- a/web_src/js/components/projects/ProjectWorkflow.vue
+++ b/web_src/js/components/projects/ProjectWorkflow.vue
@@ -3,7 +3,7 @@ import {onMounted, onUnmounted, useTemplateRef, computed, ref, nextTick, watch}
import {createWorkflowStore} from './WorkflowStore.ts';
import {svg} from '../../svg.ts';
import {confirmModal} from '../../features/comp/ConfirmModal.ts';
-import {fomanticQuery} from '../../modules/fomantic/base.ts';
+import LabelSelector from '../LabelSelector.vue';
const elRoot = useTemplateRef('elRoot');
@@ -464,57 +464,6 @@ const getWorkflowDisplayName = (item: any, _index: any) => {
return `${baseName} #${sameTypeIndex + 1}`;
};
-// Toggle label selection for add_labels, remove_labels, or filter_labels
-const toggleLabel = (type: string, labelId: any) => {
- let labels;
- if (type === 'filter_labels') {
- labels = store.workflowFilters.labels;
- } else {
- labels = (store.workflowActions as any)[type];
- }
- const index = labels.indexOf(labelId);
- if (index > -1) {
- labels.splice(index, 1);
- } else {
- labels.push(labelId);
- }
-};
-
-// Calculate text color based on background color for better contrast
-const getLabelTextColor = (hexColor: any) => {
- if (!hexColor) return '#000';
- // Remove # if present
- const color = hexColor.replace('#', '');
- // Convert to RGB
- const r = parseInt(color.substring(0, 2), 16);
- const g = parseInt(color.substring(2, 4), 16);
- const b = parseInt(color.substring(4, 6), 16);
- // Calculate relative luminance
- const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
- // Return black for light backgrounds, white for dark backgrounds
- return luminance > 0.5 ? '#000' : '#fff';
-};
-
-// Initialize Fomantic UI dropdowns for label selection
-const initLabelDropdowns = async () => {
- await nextTick();
- const dropdowns = elRoot.value?.querySelectorAll('.ui.dropdown');
- if (dropdowns) {
- dropdowns.forEach((dropdown) => {
- fomanticQuery(dropdown).dropdown({
- action: 'nothing', // Don't hide on selection for multiple selection
- fullTextSearch: true,
- });
- });
- }
-};
-
-// Watch for edit mode changes to initialize dropdowns
-watch(isInEditMode, async (newVal) => {
- if (newVal) {
- await initLabelDropdowns();
- }
-});
const getCurrentDraftKey = () => {
if (!store.selectedWorkflow) return null;
@@ -861,44 +810,12 @@ onUnmounted(() => {
-
-
-
-
- {{ locale.anyLabel }}
-
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
-
-
-
-
- Any labels
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
+
@@ -926,86 +843,20 @@ onUnmounted(() => {
-
-
-
-
- Select labels...
-
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
-
-
-
-
- None
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
+
-
-
-
-
- Select labels...
-
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
-
-
-
-
- None
-
- {{ store.projectLabels.find(l => String(l.id) === labelId)?.name }}
-
-
+
@@ -1414,48 +1265,6 @@ onUnmounted(() => {
height: auto;
}
-.form-check {
- display: block;
- min-height: 1.5rem;
- padding-left: 1.5em;
- margin-bottom: 0.125rem;
-}
-
-.form-check input[type="checkbox"] {
- float: left;
- margin-left: -1.5em;
-}
-
-/* Label selector styles */
-.label-dropdown.ui.dropdown .menu > .item.active,
-.label-dropdown.ui.dropdown .menu > .item.selected {
- background: var(--color-active);
- font-weight: normal;
-}
-
-.label-dropdown.ui.dropdown .menu > .item .ui.label {
- margin: 0;
-}
-
-.label-dropdown.ui.dropdown > .text > .ui.label {
- margin: 0.125rem;
-}
-
-.ui.labels {
- display: flex;
- flex-wrap: wrap;
- gap: 0.5rem;
- align-items: center;
-}
-
-.ui.labels .ui.label {
- margin: 0;
-}
-
-.text-muted {
- color: var(--color-text-light-2);
-}
-
/* Column select styling */
.column-select {
width: 100%;