feat(editor): Node creator actions (#4696)

* WIP: Node Actions List UI

* WIP: Recommended Actions and preseting of fields

* WIP: Resource category

* 🎨 Moved actions categorisation to the server

* 🏷️ Add missing INodeAction type

*  Improve SSR categorisation, fix adding of mixed actions

* ♻️ Refactor CategorizedItems to composition api, style fixes

* WIP: Adding multiple nodes

* ♻️ Refactor rest of the NodeCreator component to composition API, conver globalLinkActions to composable

*  Allow actions dragging, fix search and refactor passing of actions to categorized items

* 💄 Fix node actions title

* Migrate to the pinia store, add posthog feature and various fixes

* 🐛 Fix filtering of trigger actions when not merged

* fix: N8N-5439 — Do not use simple node item when at NodeHelperPanel root

* 🐛 Design review fixes

* 🐛 Fix disabling of merged actions

* Fix trigger root filtering

*  Allow for custom node actions parser, introduce hubspot parser

* 🐛 Fix initial node params validation, fix position of second added node

* 🐛 Introduce operations category, removed canvas node names overrride, fix API actions display and prevent dragging of action nodes

*  Prevent NDV auto-open feature flag

* 🐛 Inject recommened action for trigger nodes without actions

* Refactored NodeCreatorNode to Storybook, change filtering of merged nodes for the trigger helper panel, minor fixes

* Improve rendering of app nodes and animation

* Cleanup, any only enable accordion transition on triggerhelperpanel

* Hide node creator scrollbars in Firefox

* Minor styles fixes

* Do not copy the array in rendering method

* Removed unused props

* Fix memory leak

* Fix categorisation of regular nodes with a single resource

* Implement telemetry calls for node actions

* Move categorization to FE

* Fix client side actions categorisation

* Skip custom action show

* Only load tooltip for NodeIcon if necessary

* Fix lodash startCase import

* Remove lodash.startcase

* Cleanup

* Fix node creator autofocus on "tab"

* Prevent posthog getFeatureFlag from crashing

* Debugging preview env search issues

* Remove logs

* Make sure the pre-filled params are update not overwritten

* Get rid of transition in itemiterator

* WIP: Rough version of NodeActions keyboard navigation, replace nodeCreator composable with Pinia store module

* Rewrite to add support for ActionItem to ItemIterator and make CategorizedItems accept items props

* Fix category item counter & cleanup

* Add APIHint to actions search no-result, clean up NodeCreatorNode

* Improve node actions no results message

* Remove logging, fix filtering of recommended placeholder category

* Remove unused NodeActions component and node merging feature falg

* Do not show regular nodes without actions

* Make sure to add manual trigger when adding http node via actions hint

* Fixed api hint footer line height

* Prevent pointer-events od NodeIcon img and remove "this" from template

* Address PR points

* Fix e2e specs

* Make sure canvas ia loaded

* Make sure canvas ia loaded before opening nodeCreator in e2e spec

* Fix flaky workflows tags e2e getter

* Imrpove node creator click outside UX, add manual node to regular nodes added from trigger panel

* Add manual trigger node if dragging regular from trigger panel
This commit is contained in:
OlegIvaniv
2022-12-09 10:56:36 +01:00
committed by GitHub
parent b7c1359090
commit 79fe57dad8
78 changed files with 2498 additions and 1515 deletions

View File

@@ -5,9 +5,8 @@
>
<div class="main-panel">
<trigger-helper-panel
v-if="selectedType === TRIGGER_NODE_FILTER"
:searchItems="searchItems"
@nodeTypeSelected="nodeType => $emit('nodeTypeSelected', nodeType)"
v-if="nodeCreatorStore.selectedType === TRIGGER_NODE_FILTER"
@nodeTypeSelected="$listeners.nodeTypeSelected"
>
<template #header>
<type-selector/>
@@ -15,10 +14,15 @@
</trigger-helper-panel>
<categorized-items
v-else
enable-global-categories-counter
:categorizedItems="categorizedItems"
:categoriesWithNodes="categoriesWithNodes"
:searchItems="searchItems"
:excludedSubcategories="[OTHER_TRIGGER_NODES_SUBCATEGORY]"
:initialActiveCategories="[CORE_NODES_CATEGORY]"
@nodeTypeSelected="nodeType => $emit('nodeTypeSelected', nodeType)"
:allItems="categorizedItems"
@nodeTypeSelected="$listeners.nodeTypeSelected"
@actionsOpen="() => {}"
>
<template #header>
<type-selector />
@@ -28,73 +32,58 @@
</div>
</template>
<script lang="ts">
import { PropType } from 'vue';
<script setup lang="ts">
import { watch, getCurrentInstance, onMounted, onUnmounted } from 'vue';
import { externalHooks } from '@/mixins/externalHooks';
import mixins from 'vue-typed-mixins';
import TriggerHelperPanel from './TriggerHelperPanel.vue';
import { ALL_NODE_FILTER, TRIGGER_NODE_FILTER, OTHER_TRIGGER_NODES_SUBCATEGORY, CORE_NODES_CATEGORY } from '@/constants';
import CategorizedItems from './CategorizedItems.vue';
import TypeSelector from './TypeSelector.vue';
import { INodeCreateElement } from '@/Interface';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows';
import { useNodeCreatorStore } from '@/stores/nodeCreator';
import { useNodeTypesStore } from '@/stores/nodeTypes';
export default mixins(externalHooks).extend({
name: 'NodeCreateList',
components: {
TriggerHelperPanel,
CategorizedItems,
TypeSelector,
},
props: {
searchItems: {
type: Array as PropType<INodeCreateElement[] | null>,
},
},
data() {
return {
CORE_NODES_CATEGORY,
TRIGGER_NODE_FILTER,
ALL_NODE_FILTER,
OTHER_TRIGGER_NODES_SUBCATEGORY,
};
},
computed: {
...mapStores(
useNodeCreatorStore,
useWorkflowsStore,
),
selectedType(): string {
return this.nodeCreatorStore.selectedType;
},
},
watch: {
selectedType(newValue, oldValue) {
this.$externalHooks().run('nodeCreateList.selectedTypeChanged', {
oldValue,
newValue,
});
this.$telemetry.trackNodesPanel('nodeCreateList.selectedTypeChanged', {
old_filter: oldValue,
new_filter: newValue,
workflow_id: this.workflowsStore.workflowId,
});
},
},
mounted() {
this.$externalHooks().run('nodeCreateList.mounted');
// Make sure tabs are visible on mount
this.nodeCreatorStore.showTabs = true;
},
destroyed() {
this.nodeCreatorStore.selectedType = ALL_NODE_FILTER;
this.$externalHooks().run('nodeCreateList.destroyed');
this.$telemetry.trackNodesPanel('nodeCreateList.destroyed', { workflow_id: this.workflowsStore.workflowId });
},
export interface Props {
searchItems?: INodeCreateElement[];
}
withDefaults(defineProps<Props>(), {
searchItems: () => [],
});
const instance = getCurrentInstance();
const { $externalHooks } = new externalHooks();
const { workflowId } = useWorkflowsStore();
const nodeCreatorStore = useNodeCreatorStore();
const { categorizedItems, categoriesWithNodes } = useNodeTypesStore();
watch(() => nodeCreatorStore.selectedType, (newValue, oldValue) => {
$externalHooks().run('nodeCreateList.selectedTypeChanged', {
oldValue,
newValue,
});
instance?.proxy.$telemetry.trackNodesPanel('nodeCreateList.selectedTypeChanged', {
old_filter: oldValue,
new_filter: newValue,
workflow_id: workflowId,
});
});
onMounted(() => {
$externalHooks().run('nodeCreateList.mounted');
// Make sure tabs are visible on mount
nodeCreatorStore.setShowTabs(true);
});
onUnmounted(() => {
nodeCreatorStore.setSelectedType(ALL_NODE_FILTER);
$externalHooks().run('nodeCreateList.destroyed');
instance?.proxy.$telemetry.trackNodesPanel('nodeCreateList.destroyed', { workflow_id: workflowId });
});
</script>
<style lang="scss" scoped>
.container {
height: 100%;