Sfoglia il codice sorgente

Merge branch 'business' into dev

Ahmad Kholid 2 anni fa
parent
commit
8c873b4bb2

+ 2 - 0
.gitignore

@@ -29,3 +29,5 @@ getPassKey.js
 /business/prod
 
 .idea
+
+business/prod

+ 3 - 0
business/dev/index.js

@@ -0,0 +1,3 @@
+export default {
+  workflowParameters: {},
+};

+ 4 - 4
package.json

@@ -52,7 +52,7 @@
     "crypto-js": "^4.1.1",
     "css-selector-generator": "^3.6.3",
     "dagre": "^0.8.5",
-    "dayjs": "^1.10.7",
+    "dayjs": "^1.11.5",
     "defu": "^6.0.0",
     "dexie": "^3.2.2",
     "idb": "^7.0.2",
@@ -91,7 +91,7 @@
     "core-js": "^3.23.3",
     "cross-env": "^7.0.3",
     "css-loader": "^6.7.1",
-    "eslint": "^8.21.0",
+    "eslint": "^8.22.0",
     "eslint-config-airbnb-base": "^15.0.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-friendly-formatter": "^4.0.1",
@@ -105,13 +105,13 @@
     "html-webpack-plugin": "^5.5.0",
     "lint-staged": "^13.0.2",
     "mini-css-extract-plugin": "^2.3.0",
-    "postcss": "8.4.14",
+    "postcss": "^8.4.16",
     "postcss-loader": "^7.0.0",
     "prettier": "^2.7.1",
     "simple-git-hooks": "^2.6.1",
     "source-map-loader": "^4.0.0",
     "tailwindcss": "^3.1.6",
-    "terser-webpack-plugin": "^5.3.3",
+    "terser-webpack-plugin": "^5.3.5",
     "vue-loader": "^17.0.0",
     "web-worker": "^1.2.0",
     "webpack": "^5.73.0",

+ 9 - 106
src/components/newtab/workflow/edit/EditTrigger.vue

@@ -26,87 +26,21 @@
         />
       </keep-alive>
     </transition-expand>
-    <ui-button class="mt-4" @click="state.showModal = true">
+    <ui-button class="mt-4" @click="showModal = true">
       <v-remixicon name="riCommandLine" class="mr-2 -ml-1" />
       <span>Parameters</span>
     </ui-button>
-    <ui-modal
-      v-model="state.showModal"
-      title="Parameters"
-      content-class="max-w-4xl"
-    >
-      <div
-        class="overflow-auto scroll"
-        style="max-height: calc(100vh - 15rem); min-height: 200px"
-      >
-        <p
-          v-if="state.parameters.length === 0"
-          class="my-4 text-center text-gray-600 dark:text-gray-200"
-        >
-          No parameters
-        </p>
-        <table v-else class="w-full">
-          <thead>
-            <tr class="text-sm text-left">
-              <th>Name</th>
-              <th>Type</th>
-              <th>Placeholder</th>
-              <th>Default Value</th>
-              <th></th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr v-for="(param, index) in state.parameters" :key="index">
-              <td>
-                <ui-input
-                  :model-value="param.name"
-                  placeholder="Parameter name"
-                  @change="updateParam(index, $event)"
-                />
-              </td>
-              <td>
-                <ui-select v-model="param.type">
-                  <option
-                    v-for="type in paramTypes"
-                    :key="type.id"
-                    :value="type.id"
-                  >
-                    {{ type.name }}
-                  </option>
-                </ui-select>
-              </td>
-              <td>
-                <ui-input
-                  v-model="param.placeholder"
-                  placeholder="A parameter"
-                />
-              </td>
-              <td>
-                <ui-input
-                  v-model="param.defaultValue"
-                  :type="param.type === 'number' ? 'number' : 'text'"
-                  placeholder="NULL"
-                />
-              </td>
-              <td>
-                <ui-button icon @click="state.parameters.splice(index, 1)">
-                  <v-remixicon name="riDeleteBin7Line" />
-                </ui-button>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-      <ui-button variant="accent" class="mt-4" @click="addParameter">
-        Add parameter
-      </ui-button>
+    <ui-modal v-model="showModal" title="Parameters" content-class="max-w-4xl">
+      <edit-workflow-parameters
+        :data="data.parameters"
+        @update="updateData({ parameters: $event })"
+      />
     </ui-modal>
   </div>
 </template>
 <script setup>
-import { reactive, watch } from 'vue';
+import { shallowRef } from 'vue';
 import { useI18n } from 'vue-i18n';
-import cloneDeep from 'lodash.clonedeep';
 import TriggerDate from './Trigger/TriggerDate.vue';
 import TriggerInterval from './Trigger/TriggerInterval.vue';
 import TriggerVisitWeb from './Trigger/TriggerVisitWeb.vue';
@@ -114,6 +48,7 @@ import TriggerContextMenu from './Trigger/TriggerContextMenu.vue';
 import TriggerSpecificDay from './Trigger/TriggerSpecificDay.vue';
 // import TriggerElementChange from './Trigger/TriggerElementChange.vue';
 import TriggerKeyboardShortcut from './Trigger/TriggerKeyboardShortcut.vue';
+import EditWorkflowParameters from './EditWorkflowParameters.vue';
 
 const props = defineProps({
   data: {
@@ -134,44 +69,12 @@ const triggers = {
   'visit-web': TriggerVisitWeb,
   'keyboard-shortcut': TriggerKeyboardShortcut,
 };
-const paramTypes = [
-  { id: 'string', name: 'String' },
-  { id: 'number', name: 'Number' },
-];
 
 const { t } = useI18n();
 
-const state = reactive({
-  showModal: false,
-  parameters: cloneDeep(props.data.parameters || []),
-});
+const showModal = shallowRef(false);
 
 function updateData(value) {
   emit('update:data', { ...props.data, ...value });
 }
-function addParameter() {
-  state.parameters.push({
-    name: 'param',
-    type: 'string',
-    placeholder: 'Text',
-    defaultValue: '',
-  });
-}
-function updateParam(index, value) {
-  state.parameters[index].name = value.replace(/\s/g, '_');
-}
-
-watch(
-  () => state.parameters,
-  (parameters) => {
-    updateData({ parameters });
-  },
-  { deep: true }
-);
 </script>
-<style scoped>
-table th,
-table td {
-  @apply p-1 font-normal;
-}
-</style>

+ 162 - 0
src/components/newtab/workflow/edit/EditWorkflowParameters.vue

@@ -0,0 +1,162 @@
+<template>
+  <div
+    class="overflow-auto scroll"
+    style="max-height: calc(100vh - 15rem); min-height: 200px"
+  >
+    <p
+      v-if="state.parameters.length === 0"
+      class="my-4 text-center text-gray-600 dark:text-gray-200"
+    >
+      No parameters
+    </p>
+    <table v-else class="w-full">
+      <thead>
+        <tr class="text-sm text-left">
+          <th>Name</th>
+          <th>Type</th>
+          <th>Placeholder</th>
+          <th>Default Value</th>
+          <th></th>
+        </tr>
+      </thead>
+      <tbody>
+        <template v-for="(param, index) in state.parameters" :key="index">
+          <tr class="align-top">
+            <td>
+              <ui-input
+                :model-value="param.name"
+                placeholder="Parameter name"
+                @change="updateParam(index, $event)"
+              />
+            </td>
+            <td>
+              <ui-select
+                :model-value="param.type"
+                @change="updateParamType(index, $event)"
+              >
+                <option
+                  v-for="type in paramTypes"
+                  :key="type.id"
+                  :value="type.id"
+                >
+                  {{ type.name }}
+                </option>
+              </ui-select>
+            </td>
+            <td>
+              <ui-input v-model="param.placeholder" placeholder="A parameter" />
+            </td>
+            <td>
+              <component
+                :is="paramTypes[param.type].valueComp"
+                v-if="paramTypes[param.type].valueComp"
+                v-model="param.defaultValue"
+                :param-data="param"
+                max-width="250px"
+              />
+              <ui-input
+                v-else
+                v-model="param.defaultValue"
+                :type="param.type === 'number' ? 'number' : 'text'"
+                placeholder="NULL"
+              />
+            </td>
+            <td>
+              <ui-button icon @click="state.parameters.splice(index, 1)">
+                <v-remixicon name="riDeleteBin7Line" />
+              </ui-button>
+            </td>
+          </tr>
+          <tr v-if="paramTypes[param.type].options">
+            <td colspan="999" style="padding-top: 0">
+              <ui-expand
+                hide-header-icon
+                header-class="flex items-center focus:ring-0 w-full"
+              >
+                <template #header="{ show }">
+                  <v-remixicon
+                    :rotate="show ? 270 : 180"
+                    name="riArrowLeftSLine"
+                    class="mr-2 transition-transform -ml-1"
+                  />
+                  <span>Options</span>
+                </template>
+                <div class="pl-[28px] mt-2 mb-4">
+                  <component
+                    :is="paramTypes[param.type].options"
+                    v-model="param.data"
+                  />
+                </div>
+              </ui-expand>
+            </td>
+          </tr>
+        </template>
+      </tbody>
+    </table>
+  </div>
+  <ui-button variant="accent" class="mt-4" @click="addParameter">
+    Add parameter
+  </ui-button>
+</template>
+<script setup>
+import { reactive, watch } from 'vue';
+import cloneDeep from 'lodash.clonedeep';
+import { workflowParameters } from '@business';
+
+const props = defineProps({
+  data: {
+    type: Array,
+    default: () => [],
+  },
+});
+const emit = defineEmits(['update']);
+
+const paramTypes = {
+  string: {
+    id: 'string',
+    name: 'Input (string)',
+  },
+  number: {
+    id: 'number',
+    name: 'Input (number)',
+  },
+  ...workflowParameters,
+};
+
+const state = reactive({
+  parameters: cloneDeep(props.data || []),
+});
+
+function addParameter() {
+  state.parameters.push({
+    data: {},
+    name: 'param',
+    type: 'string',
+    defaultValue: '',
+    placeholder: 'Text',
+  });
+}
+function updateParam(index, value) {
+  state.parameters[index].name = value.replace(/\s/g, '_');
+}
+function updateParamType(index, type) {
+  const param = state.parameters[index];
+
+  param.type = type;
+  param.data = paramTypes[type].data || {};
+}
+
+watch(
+  () => state.parameters,
+  (parameters) => {
+    emit('update', parameters);
+  },
+  { deep: true }
+);
+</script>
+<style scoped>
+table th,
+table td {
+  @apply p-1 font-normal;
+}
+</style>

+ 28 - 13
src/params/App.vue

@@ -41,18 +41,27 @@
           </div>
         </template>
         <div class="px-4 pb-4">
-          <div class="space-y-2">
-            <ui-input
-              v-for="(param, paramIdx) in workflow.params"
-              :key="paramIdx"
-              v-model="param.value"
-              :type="param.inputType"
-              :label="param.name"
-              :placeholder="param.placeholder"
-              class="w-full"
-              @keyup.enter="runWorkflow(index, workflow)"
-            />
-          </div>
+          <ul class="space-y-2">
+            <li v-for="(param, paramIdx) in workflow.params" :key="paramIdx">
+              <component
+                :is="workflowParameters[param.type].valueComp"
+                v-if="workflowParameters[param.type]"
+                v-model="param.value"
+                :label="param.name"
+                :param-data="param"
+                class="w-full"
+              />
+              <ui-input
+                v-else
+                v-model="param.value"
+                :type="param.inputType"
+                :label="param.name"
+                :placeholder="param.placeholder"
+                class="w-full"
+                @keyup.enter="runWorkflow(index, workflow)"
+              />
+            </li>
+          </ul>
           <div class="flex items-center mt-6">
             <p>{{ dayjs(workflow.addedDate).fromNow() }}</p>
             <div class="flex-grow" />
@@ -72,6 +81,7 @@
 <script setup>
 import { onMounted, ref, computed } from 'vue';
 import browser from 'webextension-polyfill';
+import { workflowParameters } from '@business';
 import dayjs from '@/lib/dayjs';
 import { useTheme } from '@/composable/theme';
 
@@ -150,10 +160,15 @@ function runWorkflow(index, { data, params }) {
   const getParamVal = {
     string: (str) => str,
     number: (num) => (Number.isNaN(+num) ? 0 : +num),
+    default: (value) => value,
   };
 
   const variables = params.reduce((acc, param) => {
-    const value = getParamVal[param.type](param.value || param.defaultValue);
+    const valueFunc =
+      getParamVal[param.type] ||
+      workflowParameters[param.type]?.getValue ||
+      getParamVal.default;
+    const value = valueFunc(param.value || param.defaultValue);
     acc[param.name] = value;
 
     return acc;

+ 1 - 1
tailwind.config.js

@@ -37,7 +37,7 @@ function rem2px(input, fontSize = 16) {
 }
 
 module.exports = {
-  content: ['./src/**/*.{js,jsx,ts,tsx,vue}'],
+  content: ['./src/**/*.{js,jsx,ts,tsx,vue}', './business/**/*.{js,jsx,ts,tsx,vue}'],
   darkMode: 'class', // or 'media' or 'class'
   theme: {
     borderRadius: rem2px(defaultTheme.borderRadius),

+ 1 - 0
webpack.config.js

@@ -14,6 +14,7 @@ const ASSET_PATH = process.env.ASSET_PATH || '/';
 const alias = {
   '@': path.resolve(__dirname, 'src/'),
   secrets: path.join(__dirname, 'secrets.blank.js'),
+  '@business': path.resolve(__dirname, 'business/prod'),
 };
 
 // load the secrets