Skip to content

Commit

Permalink
feat: add workflows paramters popup
Browse files Browse the repository at this point in the history
  • Loading branch information
Kholid060 committed Aug 6, 2022
1 parent d4a70a3 commit d4cc437
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 16 deletions.
9 changes: 0 additions & 9 deletions src/background/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
registerWorkflowTrigger,
} from '../utils/workflowTrigger';
import WorkflowState from './WorkflowState';
import CollectionEngine from './collectionEngine';
import WorkflowEngine from './workflowEngine/engine';
import blocksHandler from './workflowEngine/blocksHandler';
import WorkflowLogger from './WorkflowLogger';
Expand Down Expand Up @@ -589,14 +588,6 @@ message.on('get:tab-screenshot', (options) =>
browser.tabs.captureVisibleTab(options)
);

message.on('collection:execute', (collection) => {
const engine = new CollectionEngine(collection, {
states: workflow.states,
logger: workflow.logger,
});
engine.init();
});

message.on('workflow:execute', (workflowData, sender) => {
if (workflowData.includeTabId) {
if (!workflowData.options) workflowData.options = {};
Expand Down
28 changes: 28 additions & 0 deletions src/background/workflowEngine/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,34 @@ class WorkflowEngine {
return;
}

const checkParams = this.options?.checkParams ?? true;
const hasParams = triggerBlock.data.parameters?.length > 0;
if (checkParams && hasParams) {
this.eventListeners = {};

const paramUrl = browser.runtime.getURL('params.html');
const tabs = await browser.tabs.query({});
const paramTab = tabs.find((tab) => tab.url?.includes(paramUrl));

if (paramTab) {
browser.tabs.sendMessage(paramTab.id, {
name: 'workflow:params',
data: this.workflow,
});

browser.windows.update(paramTab.windowId, { focused: true });
} else {
browser.windows.create({
type: 'popup',
width: 480,
url: browser.runtime.getURL(
`/params.html?workflowId=${this.workflow.id}`
),
});
}
return;
}

this.triggerBlockId = triggerBlock.id;

this.blocks = nodes.reduce((acc, node) => {
Expand Down
8 changes: 2 additions & 6 deletions src/components/newtab/workflow/edit/EditTrigger.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,8 @@
title="Parameters"
content-class="max-w-2xl"
>
<p class="leading-tight">
These parameters will be used when the workflow is executed from the
command palette
</p>
<ul
class="space-y-2 mt-2 overflow-auto scroll"
class="space-y-2 mt-2 pb-1 overflow-auto scroll"
style="max-height: calc(100vh - 15rem)"
>
<li
Expand Down Expand Up @@ -122,7 +118,7 @@ function updateData(value) {
}
function addParameter() {
state.parameters.push({
name: 'Param',
name: 'param',
type: 'string',
placeholder: 'Text',
});
Expand Down
2 changes: 1 addition & 1 deletion src/content/commandPalette/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ function clearParamsState() {
function sendExecuteCommand(workflow, options = {}) {
const workflowData = {
...workflow,
options,
includeTabId: true,
options: { ...options, checkParams: false },
};
sendMessage('workflow:execute', workflowData, 'background');
Expand Down
191 changes: 191 additions & 0 deletions src/params/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<template>
<div class="w-full flex flex-col h-full max-w-lg mx-auto dark:text-gray-100">
<nav class="flex items-center w-full p-4 border-b mb-4">
<span class="p-1 rounded-full bg-box-transparent dark:bg-none">
<img src="@/assets/svg/logo.svg" class="w-10" />
</span>
<p class="font-semibold text-lg ml-4">Automa</p>
</nav>
<div class="px-4 pb-4 flex-1 overflow-auto scroll">
<p class="text-gray-600 my-4 dark:text-gray-200">
Input these workflows parameters before it runs.
</p>
<ui-expand
v-for="(workflow, index) in sortedWorkflows"
:key="index"
:model-value="true"
append-icon
header-class="flex items-center text-left p-4 w-full rounded-lg"
class="bg-white mb-4 dark:bg-gray-800 rounded-lg"
>
<template #header>
<ui-img
v-if="workflow.data.icon?.startsWith('http')"
:src="workflow.data.icon"
class="overflow-hidden rounded-lg"
style="height: 40px; width: 40px"
alt="Can not display"
/>
<span v-else class="p-2 rounded-lg bg-box-transparent">
<v-remixicon :name="workflow.data.icon" />
</span>
<div class="ml-4 flex-1 ml-2 overflow-hidden">
<p
class="text-overflow leading-tight mr-4 text-gray-600 dark:text-gray-200"
>
{{ workflow.data.name }}
</p>
<p class="leading-tight text-overflow">
{{ workflow.data.description }}
</p>
</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>
<div class="flex items-center mt-6">
<p>{{ dayjs(workflow.addedDate).fromNow() }}</p>
<div class="flex-grow" />
<ui-button class="mr-4" @click="deleteWorkflow(index)">
Cancel
</ui-button>
<ui-button variant="accent" @click="runWorkflow(index, workflow)">
<v-remixicon name="riPlayLine" class="mr-2 -ml-1" />
Run
</ui-button>
</div>
</div>
</ui-expand>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from 'vue';
import browser from 'webextension-polyfill';
import dayjs from '@/lib/dayjs';
import { useTheme } from '@/composable/theme';
const theme = useTheme();
theme.init();
const workflows = ref([]);
const sortedWorkflows = computed(() =>
workflows.value.slice().sort((a, b) => b.addedDate - a.addedDate)
);
const flattenTeamWorkflows = (items) => Object.values(Object.values(items)[0]);
async function findWorkflow(workflowId) {
if (!workflowId) return null;
if (workflowId.startsWith('team')) {
const { teamWorkflows } = await browser.storage.local.get('teamWorkflows');
if (!teamWorkflows) return null;
const teamWorkflowsArr = flattenTeamWorkflows(teamWorkflows);
return teamWorkflowsArr.find((item) => item.id === workflowId);
}
const { workflows: localWorkflows, workflowHosts } =
await browser.storage.local.get(['workflows', 'workflowHosts']);
let workflow = Array.isArray(localWorkflows)
? localWorkflows.find(({ id }) => id === workflowId)
: localWorkflows[workflowId];
if (!workflow) {
workflow = Object.values(workflowHosts || {}).find(
({ hostId }) => hostId === workflowId
);
if (workflow) workflow.id = workflow.hostId;
}
return workflow;
}
function deleteWorkflow(index) {
workflows.value.splice(index, 1);
if (workflows.value.length === 0) {
window.close();
}
}
async function addWorkflow(workflowId) {
try {
const workflow =
typeof workflowId === 'string'
? await findWorkflow(workflowId)
: workflowId;
const triggerBlock = workflow.drawflow.nodes.find(
(node) => node.label === 'trigger'
);
if (!triggerBlock) return;
const params = triggerBlock.data.parameters.map((param) => ({
...param,
value: '',
inputType: param.type === 'string' ? 'text' : 'number',
}));
workflows.value.push({
params,
data: workflow,
addedDate: Date.now(),
});
} catch (error) {
console.error(error);
}
}
function runWorkflow(index, { data, params }) {
const getParamVal = {
string: (str) => str,
number: (num) => (Number.isNaN(+num) ? 0 : +num),
};
const variables = params.reduce((acc, param) => {
const value = getParamVal[param.type](param.value);
acc[param.name] = value;
return acc;
}, {});
const payload = {
...data,
options: {
checkParams: false,
data: { variables },
},
};
browser.runtime
.sendMessage({
name: 'background--workflow:execute',
data: payload,
})
.then(() => {
deleteWorkflow(index);
});
}
browser.runtime.onMessage.addListener(({ name, data }) => {
if (name !== 'workflow:params') return;
addWorkflow(data);
});
onMounted(() => {
const query = new URLSearchParams(window.location.search);
const workflowId = query.get('workflowId');
if (workflowId) addWorkflow(workflowId);
});
</script>
11 changes: 11 additions & 0 deletions src/params/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>

<body>
<div id="app" class="scroll"></div>
</body>
</html>
11 changes: 11 additions & 0 deletions src/params/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createApp } from 'vue';
import App from './App.vue';
import compsUi from '../lib/compsUi';
import vRemixicon, { icons } from '../lib/vRemixicon';
import '../assets/css/tailwind.css';
import '../assets/css/fonts.css';
import '../assets/css/flow.css';

createApp(App).use(compsUi).use(vRemixicon, icons).mount('#app');

if (module.hot) module.hot.accept();
7 changes: 7 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const options = {
entry: {
newtab: path.join(__dirname, 'src', 'newtab', 'index.js'),
popup: path.join(__dirname, 'src', 'popup', 'index.js'),
params: path.join(__dirname, 'src', 'params', 'index.js'),
background: path.join(__dirname, 'src', 'background', 'index.js'),
contentScript: path.join(__dirname, 'src', 'content', 'index.js'),
recordWorkflow: path.join(
Expand Down Expand Up @@ -196,6 +197,12 @@ const options = {
chunks: ['popup'],
cache: false,
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'params', 'index.html'),
filename: 'params.html',
chunks: ['params'],
cache: false,
}),
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
Expand Down

0 comments on commit d4cc437

Please sign in to comment.