1
0
Эх сурвалжийг харах

feat(newtab): add data schema

Ahmad Kholid 3 жил өмнө
parent
commit
f15b41a50a

+ 1 - 0
.eslintrc.js

@@ -29,6 +29,7 @@ module.exports = {
   },
   // add your custom rules here
   rules: {
+    'func-names': 'off',
     'import/extensions': [
       'error',
       'always',

+ 18 - 0
src/assets/css/style.css

@@ -0,0 +1,18 @@
+.list-item-transition {
+  transition: all 0.4s ease;
+}
+
+.list-leave-active {
+  position: absolute;
+  width: 100%;
+}
+
+.list-enter-from,
+.list-leave-to {
+  opacity: 0;
+}
+
+.list-enter-from,
+.list-enter-from {
+  transform: translateY(30px);
+}

+ 1 - 1
src/components/newtab/workflow/WorkflowCard.vue

@@ -59,7 +59,7 @@ const props = defineProps({
     default: true,
   },
 });
-defineEmits(['delete']);
+defineEmits(['delete', 'rename']);
 
 const formatDate = () => dayjs(props.workflow.createdAt).fromNow();
 </script>

+ 56 - 17
src/components/newtab/workflow/WorkflowDetailsCard.vue

@@ -15,13 +15,13 @@
         <v-remixicon class="-ml-1 mr-1" name="riPlayLine" />
         Execute
       </ui-button>
-      <ui-button icon class="text-red-500">
+      <ui-button icon>
         <v-remixicon name="riDeleteBin7Line" />
       </ui-button>
     </div>
     <ui-tabs v-model="state.activeTab" fill class="m-4">
       <ui-tab value="tasks">Tasks</ui-tab>
-      <ui-tab value="data-schema">Data Schema</ui-tab>
+      <ui-tab value="data-schema">Data Columns</ui-tab>
     </ui-tabs>
     <ui-tab-panels
       v-model="state.activeTab"
@@ -42,15 +42,8 @@
           <template #item="{ element }">
             <div
               :title="element.name"
-              class="
-                cursor-move
-                select-none
-                group
-                p-4
-                rounded-lg
-                bg-input
-                transition
-              "
+              style="cursor: grab"
+              class="select-none group p-4 rounded-lg bg-input transition"
             >
               <v-remixicon :name="element.icon" size="24" class="mb-3" />
               <p class="leading-tight text-overflow">
@@ -60,25 +53,71 @@
           </template>
         </draggable>
       </ui-tab-panel>
-      <ui-tab-panel value="data-schema">
-        <p>sss</p>
+      <ui-tab-panel value="data-schema" class="pt-1">
+        <div class="mb-4 space-y-2">
+          <transition-group name="list">
+            <div
+              v-for="(item, index) in state.dataSchema"
+              :key="index"
+              class="flex items-center list-item-transition"
+            >
+              <ui-input
+                v-model="state.dataSchema[index]"
+                class="mr-4"
+                placeholder="Column name"
+              />
+              <button @click="state.dataSchema.splice(index, 1)">
+                <v-remixicon name="riDeleteBin7Line" />
+              </button>
+            </div>
+          </transition-group>
+        </div>
+        <ui-button variant="accent" @click="state.dataSchema.push('')">
+          Add column
+        </ui-button>
       </ui-tab-panel>
     </ui-tab-panels>
   </ui-card>
 </template>
 <script setup>
-import { shallowReactive } from 'vue';
+/* eslint-disable no-undef */
+import { reactive, watch } from 'vue';
 import Draggable from 'vuedraggable';
 import { tasks } from '@/utils/shared';
+import { debounce } from '@/utils/helper';
 
-/* eslint-disable-next-line */
-defineEmits(['dragstart', 'dragend']);
+const props = defineProps({
+  workflow: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const emit = defineEmits(['dragstart', 'dragend', 'update-workflow']);
 
 const taskList = Object.keys(tasks)
   .map((id) => ({ id, isNewTask: true, ...tasks[id] }))
   .sort((a, b) => (a.name > b.name ? 1 : -1));
 
-const state = shallowReactive({
+const state = reactive({
+  dataSchema: [],
   activeTab: 'tasks',
 });
+
+watch(
+  () => props.workflow.id,
+  () => {
+    const data = props.workflow.dataSchema;
+
+    state.dataSchema = Array.isArray(data) ? data : Object.values(data);
+  },
+  { immediate: true }
+);
+watch(
+  () => state.dataSchema,
+  debounce((value) => {
+    const uniqueData = [...new Set(value)];
+    emit('update-workflow', uniqueData);
+  }, 500),
+  { deep: true }
+);
 </script>

+ 12 - 3
src/components/newtab/workflow/WorkflowTask.vue

@@ -40,8 +40,13 @@
     </div>
     <transition-expand>
       <template v-if="show">
-        <div class="pb-2 px-4">
-          {{ task.type }}
+        <div class="pb-2 pr-4 pl-12 max-w-lg">
+          <ui-input
+            :model-value="task.name"
+            placeholder="Task name"
+            class="w-full"
+            @change="updateTask({ name: $event || currentTask.task })"
+          />
         </div>
       </template>
     </transition-expand>
@@ -59,8 +64,12 @@ const props = defineProps({
     default: () => ({}),
   },
 });
-defineEmits(['delete']);
+const emit = defineEmits(['delete', 'update']);
 
 const show = ref(false);
 const currentTask = computed(() => tasks[props.task.type]);
+
+function updateTask(data) {
+  emit('update', props.task.id, data);
+}
 </script>

+ 1 - 0
src/models/workflow.js

@@ -13,6 +13,7 @@ class Workflow extends Model {
       name: this.string(''),
       icon: this.string('riGlobalLine'),
       data: this.attr(null),
+      dataSchema: this.attr([]),
       lastRunAt: this.number(),
       createdAt: this.number(),
       tasks: this.hasMany(Task, 'workflowId'),

+ 1 - 0
src/newtab/index.js

@@ -6,6 +6,7 @@ import compsUi from '../lib/comps-ui';
 import vRemixicon, { icons } from '../lib/v-remixicon';
 import '../assets/css/tailwind.css';
 import '../assets/css/fonts.css';
+import '../assets/css/style.css';
 
 createApp(App)
   .use(router)

+ 24 - 36
src/newtab/pages/workflows/[id].vue

@@ -2,20 +2,15 @@
   <div class="flex items-start">
     <workflow-details-card
       class="mr-6"
+      :workflow="workflow"
       @dragstart="showEmptyState = false"
       @dragend="showEmptyState = true"
+      @update-workflow="updateWorkflowSchema"
     />
     <div class="flex-1 relative">
-      <div class="flex items-center justify-between mb-6">
-        <h1 class="text-xl font-semibold">Tasks</h1>
-        <ui-input
-          v-model="query"
-          placeholder="Search..."
-          prepend-icon="riSearch2Line"
-        />
-      </div>
+      <h1 class="font-semibold text-xl mb-4">Tasks</h1>
       <div
-        v-if="workflowTasks.length === 0 && showEmptyState"
+        v-if="tasks.length === 0 && showEmptyState"
         class="text-center absolute w-full mt-20"
       >
         <div class="inline-block p-6 rounded-lg mb-4 bg-box-transparent">
@@ -38,6 +33,7 @@
               :task="element"
               class="list-item-transition"
               @delete="deleteTask"
+              @update="updateTask"
             />
           </template>
         </draggable>
@@ -57,12 +53,9 @@ import WorkflowTask from '@/components/newtab/workflow/WorkflowTask.vue';
 const route = useRoute();
 const router = useRouter();
 
-const query = ref('');
 const showEmptyState = ref(true);
 
-const workflowTasks = computed(() =>
-  Task.query().where('workflowId', route.params.id).orderBy('order').get()
-);
+const workflow = computed(() => Workflow.find(route.params.id));
 const tasks = computed({
   set(value) {
     const newTasks = value.map((item, index) => {
@@ -70,7 +63,7 @@ const tasks = computed({
 
       if (item.isNewTask) {
         task = {
-          name: item.name,
+          name: '',
           type: item.id,
           createdAt: Date.now(),
           workflowId: route.params.id,
@@ -85,15 +78,29 @@ const tasks = computed({
     Task.insertOrUpdate({ data: newTasks });
   },
   get() {
-    return workflowTasks.value.filter(({ name }) =>
-      name.toLocaleLowerCase().includes(query.value.toLocaleLowerCase())
-    );
+    return Task.query()
+      .where('workflowId', route.params.id)
+      .orderBy('order')
+      .get();
   },
 });
 
 function deleteTask({ id }) {
   Task.delete(id);
 }
+function updateTask(id, data) {
+  Task.update({
+    where: id,
+    data,
+  });
+}
+function updateWorkflowSchema(data) {
+  console.log(data, route.params.id);
+  Workflow.update({
+    where: route.params.id,
+    data: { dataSchema: data },
+  });
+}
 
 onMounted(() => {
   const isWorkflowExists = Workflow.query()
@@ -113,23 +120,4 @@ onMounted(() => {
 .ghost-task:not(.workflow-task) * {
   display: none;
 }
-
-.list-item-transition {
-  transition: all 0.4s ease;
-}
-
-.list-leave-active {
-  position: absolute;
-  width: 100%;
-}
-
-.list-enter-from,
-.list-leave-to {
-  opacity: 0;
-}
-
-.list-enter-from,
-.list-enter-from {
-  transform: translateY(30px);
-}
 </style>