Skip to content

Commit

Permalink
feat: add localization, fix: picker store
Browse files Browse the repository at this point in the history
  • Loading branch information
mnenie committed Feb 8, 2025
1 parent 896e075 commit 01eae5a
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 100 deletions.
4 changes: 2 additions & 2 deletions apps/client/src/modules/workflows/components/FlowCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ onConnect(addEdges)
<template #node-trigger="triggerNodeProps">
<TriggerNode v-bind="triggerNodeProps" />
</template>
<template #node-special="specialNodeProps">
<template #node-default="specialNodeProps">
<SpecialNode v-bind="specialNodeProps" />
</template>
<HandlersPanel @change-layout="layoutGraph" />
<Background :gap="15" :color="patternColor" :variant="backgroundVariant" />
<div v-if="!nodes.length" class="flex items-center gap-2 absolute top-1/2 left-1/2 translate-x--1/2 translate-y--1/2 text-neutral-400 dark:text-neutral-400">
<Icon icon="hugeicons:drag-02" />
<p class="text-default">
Перетащите первую сюда ноду
{{ $t('workflow.empty') }}
</p>
</div>
</VueFlow>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, watch } from 'vue'
import { computed } from 'vue'
import { Handle, Position, useVueFlow } from '@vue-flow/core'
import { Icon } from '@iconify/vue'
import { storeToRefs } from 'pinia'
Expand All @@ -9,29 +9,22 @@ import type { NodeProps } from '@vue-flow/core'
const props = defineProps<NodeProps>()
const pickerStore = usePickerStore()
const { selectedNode, target, isSettingsOpen } = storeToRefs(pickerStore)
const { selectedNode, target } = storeToRefs(pickerStore)
const name = computed(() => props.data.label ? props.data.label : props.data.title)
const isThisNode = computed(() => props.id === selectedNode.value?.id)
const { updateNodeData, nodesDraggable } = useVueFlow()
const { nodesDraggable } = useVueFlow()
async function onNodeSelect() {
if (nodesDraggable.value) {
isSettingsOpen.value = true
pickerStore.selectNode(props.id, {
type: 'trigger',
data: props.data,
})
}
}
watch(selectedNode, (newNode) => {
if (newNode && newNode.id === props.id) {
updateNodeData(props.id, newNode.data)
}
})
</script>

<template>
Expand All @@ -43,42 +36,42 @@ watch(selectedNode, (newNode) => {
>
<div
class="w-full flex items-center justify-between p-2 py-0.5 border border-neutral-200 dark:border-neutral-700 border-b-none rounded-lg rounded-b-none bg-neutral-50 dark:bg-#2e2e2e"
:class="isThisNode && 'border-dashed !border-blue-300'"
:class="isThisNode && '!border-blue-300 dark:!border-blue-800'"
>
<div class="flex items-center gap-1.5">
<Icon icon="fluent-mdl2:processing-run" class="w-3.5 h-3.5 text-neutral-600 dark:text-neutral-300" />
<span class="text-default text-neutral-600 dark:text-neutral-300 whitespace-nowrap">
Триггер
{{ $t('workflow.nodes.items[0].title') }}
</span>
</div>
</div>
<div
class="p-2 border border-neutral-200 dark:border-neutral-700 rounded-lg rounded-t-none bg-white dark:bg-#2e2e2e w-280px"
:class="isThisNode && 'border-dashed !border-l-blue-300 !border-r-blue-300 !border-b-blue-300'"
:class="isThisNode && '!border-l-blue-300 !border-r-blue-300 !border-b-blue-300 dark:(!border-l-blue-800 !border-r-blue-800 !border-b-blue-800)'"
>
<div class="flex items-center gap-2 w-full">
<div class="!bg-blue-100 dark:!bg-blue-900/30 !text-blue-500 border-blue-800 p-2 rounded-lg">
<Icon :icon="data.icon" />
</div>
<div class="flex flex-col gap-0.5 w-[84%]">
<div class="flex items-center gap-2">
<span class="text-default text-neutral-900 dark:text-neutral-300 whitespace-nowrap">
<span class="text-default text-neutral-900 dark:text-neutral-200 whitespace-nowrap">
{{ name }}
</span>
<div
v-if="!data.actions"
v-tooltip="{ content: 'Задайте действия', triggers: ['hover'], placement: 'top' }"
class="flex items-center justify-center bg-red-100 rounded-full w-3.5 h-3.5"
class="flex items-center justify-center bg-red-100 rounded-full w-3.5 h-3.5 dark:bg-red-900/40"
>
<Icon icon="ion:alert" class="w-3 h-3 text-red-800 dark:text-neutral-300" />
<Icon icon="ion:alert" class="w-3 h-3 text-red-800 dark:text-red-400" />
</div>
</div>
<span class="text-small truncate text-neutral-600 dark:text-neutral-500 whitespace-nowrap">
<span class="text-small truncate text-neutral-600 dark:text-neutral-300 whitespace-nowrap">
{{ data.description }}
</span>
</div>
</div>
</div>
<Handle type="source" :position="Position.Bottom" class="p-1 !bg-white !border-blue-400" />
<Handle type="source" :position="Position.Bottom" class="p-1 !bg-white !border-blue-400 dark:!bg-#2e2e2e" />
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const { workflow } = storeToRefs(workflowsStore)
const pickerStore = usePickerStore()
const { isPickerOpen } = storeToRefs(pickerStore)
const panelTitle = computed(() => isPickerOpen.value ? 'Закрыть панель' : 'Открыть панель')
const panelTitle = computed(() => isPickerOpen.value ? 'close' : 'open')
const panelIcon = computed(() => isPickerOpen.value ? 'lucide:x' : 'lucide:menu')
function updateCheckedStatus() {
Expand All @@ -26,9 +26,9 @@ function updateCheckedStatus() {
<div class="flex items-center gap-2">
<UiButton variant="secondary" class="shadow-none" @click="isPickerOpen = !isPickerOpen">
<Icon :icon="panelIcon" class="text-neutral-800 dark:text-neutral-300" />
{{ panelTitle }}
{{ $t(`workflow.panel.${panelTitle}`) }}
</UiButton>
<UiButton variant="dashed" class="shadow-none !text-#266df0 border border-dashed border-neutral-200 dark:border-neutral-700">
<UiButton variant="dashed" class="shadow-none border border-dashed border-neutral-200 dark:border-neutral-700">
<Icon icon="mingcute:play-fill" />
{{ $t('workflow.actions', 2) }}
</UiButton>
Expand Down
20 changes: 12 additions & 8 deletions apps/client/src/modules/workflows/components/picker/DocLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ import { UiButton } from '@/shared/ui'

<template>
<div class="flex items-start flex-col gap-2 w-full">
<span class="text-small text-neutral-500 fw500">Полезные ссылки</span>
<span class="text-small text-neutral-500 dark:text-neutral-400">
{{ $t('workflow.nodes.links') }}
</span>
<UiButton
as="a"
href="https://github.com/mnenie/jenda"
target="_blank"
variant="ghost"
class="cursor-pointer self-end items-start flex w-full flex-col !h-unset gap-1 p-1.2 border border-neutral-200 dark:border-neutral-700 rounded-lg"
variant="outline"
class="cursor-pointer self-end items-start flex w-full flex-col !h-unset gap-1 p-1.5 border shadow-none dark:bg-neutral-800 rounded-lg"
>
<div class="flex items-center justify-center gap-2">
<div class="flex items-center justify-center bg-neutral-100 rounded-full p-1">
<Icon icon="lucide:book" class="w-3.5 h-3.5 text-neutral-500" />
<div class="flex items-center justify-center rounded-full p-1.2 bg-neutral-100 border border-neutral-200 dark:(bg-#2e2e2e border-neutral-700/60)">
<Icon icon="lucide:book" class="w-3.5 h-3.5 text-neutral-500 dark:text-neutral-300" />
</div>
<span class="text-default text-neutral-700 fw500 dark:text-neutral-400">Документация</span>
<span class="text-default text-neutral-700 fw500 dark:text-neutral-200">
{{ $t('workflow.nodes.docs.title') }}
</span>
</div>
<span class="text-small text-neutral-500 dark:text-neutral-400">
Now that you are no longer receiving V1 events
<span class="text-small text-neutral-500 dark:text-neutral-300">
{{ $t('workflow.nodes.docs.description') }}
</span>
</UiButton>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ const { onDragStart } = useDragAndDrop()
<UiButton
variant="dashed"
size="lg"
class="w-full flex items-center !h-unset gap-2 justify-start gap-2.5 px-1.5 py-1.5 rounded-xl shadow-none cursor-default"
class="w-full flex items-center !h-unset gap-2 justify-start gap-2.5 px-1 py-1 rounded-xl shadow-none cursor-default"
:draggable="true"
@dragstart="onDragStart($event, node.type!, node.data)"
>
<div class="flex items-center justify-center p-1 bg-neutral-100 border border-neutral-200 dark:bg-#2e2e2e rounded-lg">
<div class="flex items-center justify-center p-1 bg-neutral-100 border border-neutral-200 dark:(bg-#2e2e2e border-neutral-700/60) rounded-lg">
<Icon :icon="node.data.icon" class="w-4 h-4 text-neutral-800 dark:text-neutral-300" />
</div>
<div class="flex flex-col gap-0.5 items-start">
<span>{{ node.data.title }}</span>
<span class="text-default text-neutral-900 dark:text-neutral-200">{{ node.data.title }}</span>
</div>
</UiButton>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { UiAlert } from '@/shared/ui'
</script>

<template>
<UiAlert variant="warning" class="border-yellow-100 justify-start mb-4 px-2">
<div class="flex items-start gap-2.5 text-yellow-900">
<UiAlert variant="warning" class="border-yellow-100 dark:border-none flex justify-start mb-5 px-2">
<div class="flex items-start gap-2.5 text-yellow-900 dark:text-yellow-500">
<Icon icon="jam:alert" class="min-w-4 min-h-4 mt-1" />
<div class="flex flex-col gap-1">
<span class="text-default">
Expand Down
54 changes: 41 additions & 13 deletions apps/client/src/modules/workflows/components/picker/PickerPanel.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,72 @@
<script setup lang="ts">
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import { usePickerStore } from '../../stores/picker'
import { nodes } from '../../utils/constants/picker'
import { nodes as record } from '../../utils/constants/picker'
import NodeElement from './NodeElement.vue'
import DocLink from './DocLink.vue'
import NodesAlert from './NodesAlert.vue'
import type { Node } from '@vue-flow/core'
import type { PickerNode } from '../../types'
import { UiSheet, UiSheetContent } from '@/shared/ui'
const pickerStore = usePickerStore()
const { isPickerOpen } = storeToRefs(pickerStore)
const { tm, t } = useI18n()
const nodesLocalized = computed((): PickerNode[] => {
const arr = tm('workflow.nodes.items') as Record<string, Node['data']>
return Object.values(record)
.flat()
.map((node, idx) => ({
...node,
data: {
...node.data,
...arr[idx],
},
}))
})
const _node = computed(() => (n: PickerNode) => {
return nodesLocalized.value.find(node => node.data.icon === n.data.icon)
})
</script>

<template>
<UiSheet :open="isPickerOpen" :modal="false">
<UiSheetContent
side="left"
class="!max-w-320px absolute p-2.5 pb-1.5"
class="!max-w-320px absolute px-3 pt-3 pb-1.5"
:portal="false"
>
<div class="flex flex-col h-full w-full transition-all duration-700">
<div class="flex items-center gap-1 justify-between mb-3">
<div class="flex items-center gap-1 justify-between mb-4">
<div class="flex flex-col gap-0.5">
<div class="flex items-center justify-between">
<h3 class="text-default fw500">
Все ноды
{{ t('workflow.nodes.title') }}
</h3>
</div>
<span class="text-default text-neutral-500 dark:text-neutral-400">
тут можно выбрать основные ноды
{{ t('workflow.nodes.description') }}
</span>
</div>
</div>
<NodesAlert />
<div class="h-full flex flex-col justify-between w-full">
<div class="flex flex-col gap-2.5">
<NodeElement
v-for="node, idx in nodes"
:key="idx"
:node="node"
/>
<div class="flex flex-col gap-6">
<div v-for="nodes, section in record" :key="section" class="flex flex-col gap-2">
<span class="text-neutral-500 dark:text-neutral-400 text-small capitalize text-ellipsis whitespace-nowrap overflow-hidden">
{{ t(`workflow.nodes.${section}`) }}
</span>
<div class="flex flex-col gap-2.5">
<NodeElement
v-for="(node, idx) in nodes"
:key="idx"
:node="_node(node)!"
/>
</div>
</div>
</div>
</div>
<DocLink />
Expand Down
10 changes: 5 additions & 5 deletions apps/client/src/modules/workflows/stores/picker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ref, shallowRef, watchEffect } from 'vue'
import { ref, shallowRef } from 'vue'
import { defineStore } from 'pinia'
import { onClickOutside } from '@vueuse/core'
import { onClickOutside, watchDebounced } from '@vueuse/core'
import type { PickerNode, SelectedPickerNode } from '../types/picker'

export const usePickerStore = defineStore('picker', () => {
Expand All @@ -21,14 +21,14 @@ export const usePickerStore = defineStore('picker', () => {
}

onClickOutside(target, () => {
clearSelection()
selectedNode.value = null
}, { ignore: [panel] })

watchEffect(() => {
watchDebounced(selectedNode, () => {
if (!selectedNode.value) {
isSettingsOpen.value = false
}
})
}, { debounce: 10 })

return {
isPickerOpen,
Expand Down
Loading

0 comments on commit 01eae5a

Please sign in to comment.