Browse Source

feat: add workflow note

Ahmad Kholid 3 years ago
parent
commit
7f81988c52

+ 121 - 0
src/components/newtab/shared/SharedWysiwyg.vue

@@ -1,6 +1,90 @@
 <template>
   <div class="wysiwyg-editor">
     <slot v-if="editor" name="prepend" :editor="editor" />
+    <div
+      v-if="editor"
+      class="p-2 rounded-lg backdrop-blur flex items-center sticky top-0 z-50 bg-box-transparent space-x-1 mb-2"
+    >
+      <button
+        :class="{
+          'bg-box-transparent text-primary': editor.isActive('heading', {
+            level: 1,
+          }),
+        }"
+        title="Heading 1"
+        class="editor-menu-btn hoverable"
+        @click="editor.commands.toggleHeading({ level: 1 })"
+      >
+        <v-remixicon name="riH1" />
+      </button>
+      <button
+        :class="{
+          'bg-box-transparent text-primary': editor.isActive('heading', {
+            level: 2,
+          }),
+        }"
+        title="Heading 2"
+        class="editor-menu-btn hoverable"
+        @click="editor.commands.toggleHeading({ level: 2 })"
+      >
+        <v-remixicon name="riH2" />
+      </button>
+      <span
+        class="w-px h-5 bg-gray-300 dark:bg-gray-600"
+        style="margin: 0 12px"
+      ></span>
+      <button
+        v-for="item in menuItems"
+        :key="item.id"
+        :title="item.name"
+        :class="{
+          'bg-box-transparent text-primary': editor.isActive(item.id),
+        }"
+        class="editor-menu-btn hoverable"
+        @click="editor.chain().focus()[item.action]().run()"
+      >
+        <v-remixicon :name="item.icon" />
+      </button>
+      <span
+        class="w-px h-5 bg-gray-300 dark:bg-gray-600"
+        style="margin: 0 12px"
+      ></span>
+      <button
+        :class="{
+          'bg-box-transparent text-primary': editor.isActive('blockquote'),
+        }"
+        title="Blockquote"
+        class="editor-menu-btn hoverable"
+        @click="editor.commands.toggleBlockquote()"
+      >
+        <v-remixicon name="riDoubleQuotesL" />
+      </button>
+      <button
+        title="Insert image"
+        class="editor-menu-btn hoverable"
+        @click="insertImage(editor)"
+      >
+        <v-remixicon name="riImageLine" />
+      </button>
+      <button
+        :class="{
+          'bg-box-transparent text-primary': editor.isActive('link'),
+        }"
+        title="Link"
+        class="editor-menu-btn hoverable"
+        @click="setLink(editor)"
+      >
+        <v-remixicon name="riLinkM" />
+      </button>
+      <button
+        v-show="editor.isActive('link')"
+        title="Remove link"
+        class="editor-menu-btn hoverable"
+        @click="editor.commands.unsetLink()"
+      >
+        <v-remixicon name="riLinkUnlinkM" />
+      </button>
+    </div>
     <editor-content :editor="editor" />
     <slot name="append" />
   </div>
@@ -35,6 +119,43 @@ const props = defineProps({
 const emit = defineEmits(['update:modelValue', 'count', 'change']);
 
 const editor = shallowRef(null);
+const menuItems = [
+  { id: 'bold', name: 'Bold', icon: 'riBold', action: 'toggleBold' },
+  { id: 'italic', name: 'Italic', icon: 'riItalic', action: 'toggleItalic' },
+  {
+    id: 'strike',
+    name: 'Strikethrough',
+    icon: 'riStrikethrough2',
+    action: 'toggleStrike',
+  },
+];
+
+function setLink() {
+  const previousUrl = editor.value.getAttributes('link').href;
+  const url = window.prompt('URL', previousUrl);
+
+  if (url === null) return;
+
+  if (url === '') {
+    editor.value.chain().focus().extendMarkRange('link').unsetLink().run();
+
+    return;
+  }
+
+  editor.value
+    .chain()
+    .focus()
+    .extendMarkRange('link')
+    .setLink({ href: url, target: '_blank' })
+    .run();
+}
+function insertImage() {
+  const url = window.prompt('URL');
+
+  if (url) {
+    editor.value.chain().focus().setImage({ src: url }).run();
+  }
+}
 
 watch(
   () => props.modelValue,

+ 0 - 123
src/components/newtab/workflow/WorkflowShare.vue

@@ -74,92 +74,6 @@
         class="prose prose-zinc dark:prose-invert max-w-none content-editor p-4 bg-box-transparent rounded-lg relative"
         @count="state.contentLength = $event"
       >
-        <template #prepend="{ editor }">
-          <div
-            class="p-2 rounded-lg backdrop-blur flex items-center sticky top-0 z-50 bg-box-transparent space-x-1 mb-2"
-          >
-            <button
-              :class="{
-                'bg-box-transparent text-primary': editor.isActive('heading', {
-                  level: 1,
-                }),
-              }"
-              title="Heading 1"
-              class="editor-menu-btn hoverable"
-              @click="editor.commands.toggleHeading({ level: 1 })"
-            >
-              <v-remixicon name="riH1" />
-            </button>
-            <button
-              :class="{
-                'bg-box-transparent text-primary': editor.isActive('heading', {
-                  level: 2,
-                }),
-              }"
-              title="Heading 2"
-              class="editor-menu-btn hoverable"
-              @click="editor.commands.toggleHeading({ level: 2 })"
-            >
-              <v-remixicon name="riH2" />
-            </button>
-            <span
-              class="w-px h-5 bg-gray-300 dark:bg-gray-600"
-              style="margin: 0 12px"
-            ></span>
-            <button
-              v-for="item in menuItems"
-              :key="item.id"
-              :title="item.name"
-              :class="{
-                'bg-box-transparent text-primary': editor.isActive(item.id),
-              }"
-              class="editor-menu-btn hoverable"
-              @click="editor.chain().focus()[item.action]().run()"
-            >
-              <v-remixicon :name="item.icon" />
-            </button>
-            <span
-              class="w-px h-5 bg-gray-300 dark:bg-gray-600"
-              style="margin: 0 12px"
-            ></span>
-            <button
-              :class="{
-                'bg-box-transparent text-primary':
-                  editor.isActive('blockquote'),
-              }"
-              title="Blockquote"
-              class="editor-menu-btn hoverable"
-              @click="editor.commands.toggleBlockquote()"
-            >
-              <v-remixicon name="riDoubleQuotesL" />
-            </button>
-            <button
-              title="Insert image"
-              class="editor-menu-btn hoverable"
-              @click="insertImage(editor)"
-            >
-              <v-remixicon name="riImageLine" />
-            </button>
-            <button
-              :class="{
-                'bg-box-transparent text-primary': editor.isActive('link'),
-              }"
-              title="Link"
-              class="editor-menu-btn hoverable"
-              @click="setLink(editor)"
-            >
-              <v-remixicon name="riLinkM" />
-            </button>
-            <button
-              v-show="editor.isActive('link')"
-              title="Remove link"
-              class="editor-menu-btn hoverable"
-              @click="editor.commands.unsetLink()"
-            >
-              <v-remixicon name="riLinkUnlinkM" />
-            </button>
-          </div>
-        </template>
         <template #append>
           <p
             class="text-sm text-gray-600 dark:text-gray-200 absolute bottom-2 right-2"
@@ -197,17 +111,6 @@ const toast = useToast();
 const userStore = useUserStore();
 const sharedWorkflowStore = useSharedWorkflowStore();
 
-const menuItems = [
-  { id: 'bold', name: 'Bold', icon: 'riBold', action: 'toggleBold' },
-  { id: 'italic', name: 'Italic', icon: 'riItalic', action: 'toggleItalic' },
-  {
-    id: 'strike',
-    name: 'Strikethrough',
-    icon: 'riStrikethrough2',
-    action: 'toggleStrike',
-  },
-];
-
 const state = reactive({
   contentLength: 0,
   isPublishing: false,
@@ -263,32 +166,6 @@ async function publishWorkflow() {
     state.isPublishing = false;
   }
 }
-function setLink(editor) {
-  const previousUrl = editor.getAttributes('link').href;
-  const url = window.prompt('URL', previousUrl);
-
-  if (url === null) return;
-
-  if (url === '') {
-    editor.chain().focus().extendMarkRange('link').unsetLink().run();
-
-    return;
-  }
-
-  editor
-    .chain()
-    .focus()
-    .extendMarkRange('link')
-    .setLink({ href: url, target: '_blank' })
-    .run();
-}
-function insertImage(editor) {
-  const url = window.prompt('URL');
-
-  if (url) {
-    editor.chain().focus().setImage({ src: url }).run();
-  }
-}
 
 watch(
   () => state.workflow,

+ 26 - 5
src/components/newtab/workflow/editor/EditorLocalActions.vue

@@ -1,9 +1,14 @@
 <template>
-  <ui-card
-    v-if="!workflow.isProtected"
-    padding="p-1"
-    class="flex items-center pointer-events-auto"
-  >
+  <ui-card padding="p-1 pointer-events-auto mr-4">
+    <button
+      v-tooltip.group="'Workflow note'"
+      class="hoverable p-2 rounded-lg"
+      @click="state.showNoteModal = true"
+    >
+      <v-remixicon name="riFileEditLine" />
+    </button>
+  </ui-card>
+  <ui-card padding="p-1" class="flex items-center pointer-events-auto">
     <ui-popover>
       <template #trigger>
         <button
@@ -168,6 +173,20 @@
       </ui-button>
     </div>
   </ui-modal>
+  <ui-modal
+    v-model="state.showNoteModal"
+    title="Workflow note"
+    content-class="max-w-2xl"
+  >
+    <shared-wysiwyg
+      :model-value="workflow.content || ''"
+      :limit="1000"
+      class="bg-box-transparent p-4 rounded-lg overflow-auto scroll"
+      placeholder="Write note here..."
+      style="max-height: calc(100vh - 12rem); min-height: 400px"
+      @change="updateWorkflow({ content: $event }, true)"
+    />
+  </ui-modal>
 </template>
 <script setup>
 import { reactive, computed } from 'vue';
@@ -186,6 +205,7 @@ import { useShortcut, getShortcut } from '@/composable/shortcut';
 import { parseJSON } from '@/utils/helper';
 import { exportWorkflow, convertWorkflow } from '@/utils/workflowData';
 import { registerWorkflowTrigger } from '@/utils/workflowTrigger';
+import SharedWysiwyg from '@/components/newtab/shared/SharedWysiwyg.vue';
 
 const props = defineProps({
   isDataChanged: {
@@ -220,6 +240,7 @@ const shortcuts = useShortcut([
 ]);
 
 const state = reactive({
+  showNoteModal: false,
   isUploadingHost: false,
 });
 const renameState = reactive({

+ 1 - 2
src/content/blocksHandler/handlerLink.js

@@ -10,8 +10,7 @@ async function link(block) {
   markElement(element, block);
 
   const url = element.href;
-
-  if (url) window.location.href = url;
+  if (url) window.open(url, '_self');
 
   return url;
 }

+ 7 - 3
src/newtab/pages/workflows/[id].vue

@@ -91,7 +91,7 @@
               </button>
               <ui-card padding="p-0 ml-2 undo-redo">
                 <button
-                  v-tooltip="
+                  v-tooltip.group="
                     `${t('workflow.undo')} (${
                       shortcut['action:undo'].readable
                     })`
@@ -103,7 +103,7 @@
                   <v-remixicon name="riArrowGoBackLine" />
                 </button>
                 <button
-                  v-tooltip="
+                  v-tooltip.group="
                     `${t('workflow.redo')} (${
                       shortcut['action:redo'].readable
                     })`
@@ -186,8 +186,9 @@ import { useShortcut, getShortcut } from '@/composable/shortcut';
 import { getWorkflowPermissions } from '@/utils/workflowData';
 import { tasks } from '@/utils/shared';
 import { fetchApi } from '@/utils/api';
-import { debounce, parseJSON, throttle } from '@/utils/helper';
+import { useGroupTooltip } from '@/composable/groupTooltip';
 import { useCommandManager } from '@/composable/commandManager';
+import { debounce, parseJSON, throttle } from '@/utils/helper';
 import browser from 'webextension-polyfill';
 import dbStorage from '@/db/storage';
 import DroppedNode from '@/utils/editor/DroppedNode';
@@ -209,6 +210,8 @@ let editorCommands = null;
 const executeCommandTimeout = null;
 const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 7);
 
+useGroupTooltip();
+
 const { t } = useI18n();
 const store = useStore();
 const route = useRoute();
@@ -861,6 +864,7 @@ watch(
 watch(
   () => route.params.id,
   (value, oldValue) => {
+    if (route.name !== 'workflows-details') return;
     if (value && oldValue && value !== oldValue) {
       window.location.reload();
     }

+ 1 - 0
src/stores/workflow.js

@@ -17,6 +17,7 @@ const defaultWorkflow = (data = null, options = {}) => {
     name: '',
     icon: 'riGlobalLine',
     folderId: null,
+    content: null,
     connectedTable: null,
     drawflow: {
       edges: [],