mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat: Add more filters to workflows
This commit is contained in:
parent
d7ba206b30
commit
33a4873bc7
|
@ -2237,6 +2237,15 @@
|
||||||
"workflows.search.placeholder": "Search workflows...",
|
"workflows.search.placeholder": "Search workflows...",
|
||||||
"workflows.filters": "Filters",
|
"workflows.filters": "Filters",
|
||||||
"workflows.filters.tags": "Tags",
|
"workflows.filters.tags": "Tags",
|
||||||
|
"workflows.filters.credentials": "Credentials",
|
||||||
|
"workflows.filter.credentialsAndNodes.sectionTitle": "Credentials and nodes",
|
||||||
|
"workflows.filter.urls.sectionTitle": "URLS",
|
||||||
|
"workflows.filters.credentials.placeholder": "Filter by credentials",
|
||||||
|
"workflows.filters.nodeTypes": "Node types",
|
||||||
|
"workflows.filters.nodeTypes.placeholder": "Filter by nodes",
|
||||||
|
"workflows.filters.nodeName": "Node name",
|
||||||
|
"workflows.filters.urlWebhook": "URL Webhook",
|
||||||
|
"workflows.filters.urlHTTPRequest": "URL HTTP Request",
|
||||||
"workflows.filters.status": "Status",
|
"workflows.filters.status": "Status",
|
||||||
"workflows.filters.status.all": "All",
|
"workflows.filters.status.all": "All",
|
||||||
"workflows.filters.status.active": "Active",
|
"workflows.filters.status.active": "Active",
|
||||||
|
|
|
@ -32,6 +32,8 @@ import {
|
||||||
N8nTooltip,
|
N8nTooltip,
|
||||||
} from 'n8n-design-system';
|
} from 'n8n-design-system';
|
||||||
import { pickBy } from 'lodash-es';
|
import { pickBy } from 'lodash-es';
|
||||||
|
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -48,12 +50,19 @@ const telemetry = useTelemetry();
|
||||||
const uiStore = useUIStore();
|
const uiStore = useUIStore();
|
||||||
const tagsStore = useTagsStore();
|
const tagsStore = useTagsStore();
|
||||||
const documentTitle = useDocumentTitle();
|
const documentTitle = useDocumentTitle();
|
||||||
|
const credentialsStore = useCredentialsStore();
|
||||||
|
const nodeTypesStore = useNodeTypesStore();
|
||||||
|
|
||||||
interface Filters {
|
interface Filters {
|
||||||
search: string;
|
search: string;
|
||||||
homeProject: string;
|
homeProject: string;
|
||||||
status: string | boolean;
|
status: string | boolean;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
credentials: string[];
|
||||||
|
nodeTypes: string[];
|
||||||
|
nodeName: string;
|
||||||
|
webhookUrl: string;
|
||||||
|
httpRequestUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatusFilter = {
|
const StatusFilter = {
|
||||||
|
@ -68,6 +77,11 @@ const filters = ref<Filters>({
|
||||||
homeProject: '',
|
homeProject: '',
|
||||||
status: StatusFilter.ALL,
|
status: StatusFilter.ALL,
|
||||||
tags: [],
|
tags: [],
|
||||||
|
credentials: [],
|
||||||
|
nodeTypes: [],
|
||||||
|
nodeName: '',
|
||||||
|
webhookUrl: '',
|
||||||
|
httpRequestUrl: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const readOnlyEnv = computed(() => sourceControlStore.preferences.branchReadOnly);
|
const readOnlyEnv = computed(() => sourceControlStore.preferences.branchReadOnly);
|
||||||
|
@ -200,6 +214,9 @@ const trackCategoryLinkClick = (category: string) => {
|
||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
nodeTypesStore.loadNodeTypesIfNotLoaded(),
|
||||||
|
credentialsStore.fetchAllCredentials(route?.params?.projectId as string | undefined),
|
||||||
|
// credentialsStore.fetchCredentialTypes(false),
|
||||||
usersStore.fetchUsers(),
|
usersStore.fetchUsers(),
|
||||||
workflowsStore.fetchAllWorkflows(route.params?.projectId as string | undefined),
|
workflowsStore.fetchAllWorkflows(route.params?.projectId as string | undefined),
|
||||||
workflowsStore.fetchActiveWorkflows(),
|
workflowsStore.fetchActiveWorkflows(),
|
||||||
|
@ -423,13 +440,14 @@ onMounted(async () => {
|
||||||
size="small"
|
size="small"
|
||||||
color="text-base"
|
color="text-base"
|
||||||
class="mb-3xs"
|
class="mb-3xs"
|
||||||
/>
|
>
|
||||||
<WorkflowTagsDropdown
|
<WorkflowTagsDropdown
|
||||||
:placeholder="i18n.baseText('workflowOpen.filterWorkflows')"
|
:placeholder="i18n.baseText('workflowOpen.filterWorkflows')"
|
||||||
:model-value="filters.tags"
|
:model-value="filters.tags"
|
||||||
:create-enabled="false"
|
:create-enabled="false"
|
||||||
@update:model-value="setKeyValue('tags', $event)"
|
@update:model-value="setKeyValue('tags', $event)"
|
||||||
/>
|
/>
|
||||||
|
</N8nInputLabel>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-s">
|
<div class="mb-s">
|
||||||
<N8nInputLabel
|
<N8nInputLabel
|
||||||
|
@ -438,7 +456,7 @@ onMounted(async () => {
|
||||||
size="small"
|
size="small"
|
||||||
color="text-base"
|
color="text-base"
|
||||||
class="mb-3xs"
|
class="mb-3xs"
|
||||||
/>
|
>
|
||||||
<N8nSelect
|
<N8nSelect
|
||||||
data-test-id="status-dropdown"
|
data-test-id="status-dropdown"
|
||||||
:model-value="filters.status"
|
:model-value="filters.status"
|
||||||
|
@ -453,6 +471,108 @@ onMounted(async () => {
|
||||||
>
|
>
|
||||||
</N8nOption>
|
</N8nOption>
|
||||||
</N8nSelect>
|
</N8nSelect>
|
||||||
|
</N8nInputLabel>
|
||||||
|
</div>
|
||||||
|
<div :class="['mb-xs', $style.sectionTitle]">
|
||||||
|
{{ i18n.baseText('workflows.filter.credentialsAndNodes.sectionTitle') }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-s">
|
||||||
|
<N8nInputLabel
|
||||||
|
:label="i18n.baseText('workflows.filters.credentials')"
|
||||||
|
:bold="false"
|
||||||
|
size="small"
|
||||||
|
color="text-base"
|
||||||
|
class="mb-3xs"
|
||||||
|
>
|
||||||
|
<N8nSelect
|
||||||
|
data-test-id="credentials-filter"
|
||||||
|
:model-value="filters.credentials"
|
||||||
|
:multiple="true"
|
||||||
|
:placeholder="i18n.baseText('workflows.filters.credentials.placeholder')"
|
||||||
|
@update:model-value="setKeyValue('credentials', $event)"
|
||||||
|
>
|
||||||
|
<N8nOption
|
||||||
|
v-for="cred in credentialsStore.allCredentials"
|
||||||
|
:key="cred.id"
|
||||||
|
:label="cred.name"
|
||||||
|
:value="cred.id"
|
||||||
|
>
|
||||||
|
</N8nOption>
|
||||||
|
</N8nSelect>
|
||||||
|
</N8nInputLabel>
|
||||||
|
</div>
|
||||||
|
<div class="mb-s">
|
||||||
|
<N8nInputLabel
|
||||||
|
:label="i18n.baseText('workflows.filters.nodeTypes')"
|
||||||
|
:bold="false"
|
||||||
|
size="small"
|
||||||
|
color="text-base"
|
||||||
|
class="mb-3xs"
|
||||||
|
>
|
||||||
|
<N8nSelect
|
||||||
|
data-test-id="node-types-filter"
|
||||||
|
:model-value="filters.nodeTypes"
|
||||||
|
:multiple="true"
|
||||||
|
:placeholder="i18n.baseText('workflows.filters.nodeTypes.placeholder')"
|
||||||
|
@update:model-value="setKeyValue('nodeTypes', $event)"
|
||||||
|
>
|
||||||
|
<N8nOption
|
||||||
|
v-for="nodeType in nodeTypesStore.allLatestNodeTypes"
|
||||||
|
:key="nodeType.name"
|
||||||
|
:label="nodeType.displayName"
|
||||||
|
:value="nodeType.name"
|
||||||
|
>
|
||||||
|
</N8nOption>
|
||||||
|
</N8nSelect>
|
||||||
|
</N8nInputLabel>
|
||||||
|
</div>
|
||||||
|
<div class="mb-s">
|
||||||
|
<N8nInputLabel
|
||||||
|
:label="i18n.baseText('workflows.filters.nodeName')"
|
||||||
|
:bold="false"
|
||||||
|
size="small"
|
||||||
|
color="text-base"
|
||||||
|
class="mb-3xs"
|
||||||
|
>
|
||||||
|
<N8nInput
|
||||||
|
data-test-id="node-name-filter"
|
||||||
|
:model-value="filters.nodeName"
|
||||||
|
@update:model-value="setKeyValue('nodeName', $event)"
|
||||||
|
/>
|
||||||
|
</N8nInputLabel>
|
||||||
|
</div>
|
||||||
|
<div :class="['mb-xs', $style.sectionTitle]">
|
||||||
|
{{ i18n.baseText('workflows.filter.urls.sectionTitle') }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-s">
|
||||||
|
<N8nInputLabel
|
||||||
|
:label="i18n.baseText('workflows.filters.urlWebhook')"
|
||||||
|
:bold="false"
|
||||||
|
size="small"
|
||||||
|
color="text-base"
|
||||||
|
class="mb-3xs"
|
||||||
|
>
|
||||||
|
<N8nInput
|
||||||
|
data-test-id="url-webhook-filter"
|
||||||
|
:model-value="filters.webhookUrl"
|
||||||
|
@update:model-value="setKeyValue('webhookUrl', $event)"
|
||||||
|
/>
|
||||||
|
</N8nInputLabel>
|
||||||
|
</div>
|
||||||
|
<div class="mb-s">
|
||||||
|
<N8nInputLabel
|
||||||
|
:label="i18n.baseText('workflows.filters.urlHTTPRequest')"
|
||||||
|
:bold="false"
|
||||||
|
size="small"
|
||||||
|
color="text-base"
|
||||||
|
class="mb-3xs"
|
||||||
|
>
|
||||||
|
<N8nInput
|
||||||
|
data-test-id="url-webhook-filter"
|
||||||
|
:model-value="filters.httpRequestUrl"
|
||||||
|
@update:model-value="setKeyValue('httpRequestUrl', $event)"
|
||||||
|
/>
|
||||||
|
</N8nInputLabel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ResourcesListLayout>
|
</ResourcesListLayout>
|
||||||
|
@ -481,6 +601,15 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--color-text-dark);
|
||||||
|
font-size: var(--font-size-3xs);
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
border-bottom: var(--border-base);
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.emptyStateCardIcon {
|
.emptyStateCardIcon {
|
||||||
font-size: 48px;
|
font-size: 48px;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue