Skip to content

Commit

Permalink
feat: put workflows logs in modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Kholid060 committed Nov 24, 2022
1 parent 1824d4d commit 9853860
Show file tree
Hide file tree
Showing 15 changed files with 496 additions and 256 deletions.
10 changes: 8 additions & 2 deletions src/background/BackgroundEventsListeners.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,16 @@ class BackgroundEventsListeners {
BackgroundWorkflowTriggers.contextMenu(event, tab);
}

static onNotificationClicked(notificationId) {
static async onNotificationClicked(notificationId) {
if (notificationId.startsWith('logs')) {
const { 1: logId } = notificationId.split(':');
BackgroundUtils.openDashboard(`/logs/${logId}`);

const [tab] = await browser.tabs.query({
url: browser.runtime.getURL('/newtab.html'),
});
if (!tab) await BackgroundUtils.openDashboard('');

await BackgroundUtils.sendMessageToDashboard('open-logs', { logId });
}
}

Expand Down
58 changes: 58 additions & 0 deletions src/components/newtab/app/AppLogs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<ui-modal
v-model="state.show"
custom-content
content-position="start"
@close="clearState"
>
<ui-card class="w-full mt-8" style="max-width: 1400px; min-height: 600px">
<app-logs-items
v-if="!state.logId"
:workflow-id="state.workflowId"
@select="onSelectLog"
@close="clearState"
/>
<app-logs-item-running
v-else-if="state.runningWorkflow"
:log-id="state.logId"
@close="closeItemPage"
/>
<app-logs-item v-else :log-id="state.logId" @close="closeItemPage" />
</ui-card>
</ui-modal>
</template>
<script setup>
import { reactive } from 'vue';
import emitter from '@/lib/mitt';
import AppLogsItem from './AppLogsItem.vue';
import AppLogsItems from './AppLogsItems.vue';
import AppLogsItemRunning from './AppLogsItemRunning.vue';
const state = reactive({
logId: '',
source: '',
show: false,
workflowId: '',
runningWorkflow: false,
});
emitter.on('ui:logs', (event = {}) => {
Object.assign(state, event);
});
function clearState() {
state.show = false;
state.logId = '';
state.source = '';
state.runningWorkflow = false;
}
function closeItemPage(closeModal = false) {
state.logId = '';
if (closeModal) clearState();
}
function onSelectLog({ id, type }) {
state.runningWorkflow = type === 'running';
state.logId = id;
}
</script>
192 changes: 192 additions & 0 deletions src/components/newtab/app/AppLogsItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<template>
<div v-if="currentLog.id">
<div class="flex items-center">
<button
v-tooltip:bottom="t('workflow.blocks.go-back.name')"
role="button"
class="h-12 px-1 transition mr-2 bg-input rounded-lg dark:text-gray-300 text-gray-600"
@click="$emit('close')"
>
<v-remixicon name="riArrowLeftSLine" />
</button>
<div>
<h1 class="text-2xl max-w-md text-overflow font-semibold">
{{ currentLog.name }}
</h1>
<p class="text-gray-600 dark:text-gray-200">
{{
t(`log.description.text`, {
status: t(
`log.description.status.${currentLog.status || 'success'}`
),
date: dayjs(currentLog.startedAt).format('DD MMM'),
duration: countDuration(currentLog.startedAt, currentLog.endedAt),
})
}}
</p>
</div>
<div class="flex-grow"></div>
<ui-button
v-if="state.workflowExists"
v-tooltip="t('log.goWorkflow')"
icon
class="mr-4"
@click="goToWorkflow"
>
<v-remixicon name="riExternalLinkLine" />
</ui-button>
<ui-button class="text-red-500 dark:text-red-400" @click="deleteLog">
{{ t('common.delete') }}
</ui-button>
</div>
<ui-tabs v-model="state.activeTab" class="mt-4" @change="onTabChange">
<ui-tab v-for="tab in tabs" :key="tab.id" class="mr-4" :value="tab.id">
{{ tab.name }}
</ui-tab>
</ui-tabs>
<ui-tab-panels
:model-value="state.activeTab"
class="mt-4 pb-4 overflow-auto scroll px-2"
style="min-height: 500px; max-height: calc(100vh - 15rem)"
>
<ui-tab-panel value="logs">
<logs-history
:current-log="currentLog"
:ctx-data="ctxData"
:parent-log="parentLog"
/>
</ui-tab-panel>
<ui-tab-panel value="table">
<logs-table :current-log="currentLog" :table-data="tableData" />
</ui-tab-panel>
<ui-tab-panel value="variables">
<logs-variables :current-log="currentLog" />
</ui-tab-panel>
</ui-tab-panels>
</div>
</template>
<script setup>
import { shallowReactive, shallowRef, watch } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import dbLogs from '@/db/logs';
import dayjs from '@/lib/dayjs';
import { useWorkflowStore } from '@/stores/workflow';
import { countDuration, convertArrObjTo2DArr } from '@/utils/helper';
import LogsTable from '@/components/newtab/logs/LogsTable.vue';
import LogsHistory from '@/components/newtab/logs/LogsHistory.vue';
import LogsVariables from '@/components/newtab/logs/LogsVariables.vue';
const props = defineProps({
logId: {
type: String,
default: '',
},
});
const emit = defineEmits(['close']);
const { t } = useI18n();
const router = useRouter();
const workflowStore = useWorkflowStore();
const ctxData = shallowRef({});
const parentLog = shallowRef(null);
const tabs = [
{ id: 'logs', name: t('common.log', 2) },
{ id: 'table', name: t('workflow.table.title') },
{ id: 'variables', name: t('workflow.variables.title', 2) },
];
const state = shallowReactive({
activeTab: 'logs',
workflowExists: false,
});
const tableData = shallowReactive({
converted: false,
body: [],
header: [],
});
const currentLog = shallowRef({
history: [],
data: {
table: [],
variables: {},
},
});
function deleteLog() {
dbLogs.items
.where('id')
.equals(props.logId)
.delete()
.then(() => {
emit('close');
});
}
function goToWorkflow() {
const path = `/workflows/${currentLog.value.workflowId}`;
router.push(path);
emit('close', true);
}
function convertToTableData() {
const data = currentLog.value.data?.table;
if (!data) return;
const [header] = convertArrObjTo2DArr(data);
tableData.converted = true;
tableData.body = data.map((item, index) => ({ ...item, id: index + 1 }));
tableData.header = header.map((name) => ({
text: name,
value: name,
filterable: true,
}));
tableData.header.unshift({ value: 'id', text: '', sortable: false });
}
function onTabChange(value) {
if (value === 'table' && !tableData.converted) {
convertToTableData();
}
}
async function fetchLog() {
if (!props.logId) return;
const logDetail = await dbLogs.items.where('id').equals(props.logId).last();
if (!logDetail) return;
tableData.body = [];
tableData.header = [];
parentLog.value = null;
tableData.converted = false;
const [logCtxData, logHistory, logsData] = await Promise.all(
['ctxData', 'histories', 'logsData'].map((key) =>
dbLogs[key].where('logId').equals(props.logId).last()
)
);
ctxData.value = logCtxData?.data || {};
currentLog.value = {
history: logHistory?.data || [],
data: logsData?.data || {},
...logDetail,
};
state.workflowExists = Boolean(workflowStore.getById(logDetail.workflowId));
const parentLogId = logDetail.collectionLogId || logDetail.parentLog?.id;
if (parentLogId) {
parentLog.value =
(await dbLogs.items.where('id').equals(parentLogId).last()) || null;
}
}
watch(() => props.logId, fetchLog, { immediate: true });
</script>
<style>
.logs-details .cm-editor {
max-height: calc(100vh - 15rem);
}
</style>
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<template>
<div v-if="running" class="container py-8">
<div v-if="running">
<div class="flex items-center">
<button
v-tooltip:bottom="t('workflow.blocks.go-back.name')"
role="button"
class="h-12 px-1 transition mr-2 bg-input rounded-lg dark:text-gray-300 text-gray-600"
@click="$emit('close')"
>
<v-remixicon name="riArrowLeftSLine" />
</button>
<div class="flex-grow overflow-hidden">
<h1 class="text-2xl max-w-md text-overflow font-semibold text-overflow">
{{ running.state.name }}
Expand All @@ -21,6 +29,7 @@
</div>
<div class="mt-8">
<logs-history
:is-running="true"
:current-log="{
history: running.state.logs,
workflowId: running.workflowId,
Expand Down Expand Up @@ -76,7 +85,7 @@
</template>
<script setup>
import { computed, watch, shallowRef, onBeforeUnmount } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { countDuration } from '@/utils/helper';
import { useWorkflowStore } from '@/stores/workflow';
Expand All @@ -85,8 +94,15 @@ import dbLogs from '@/db/logs';
import dayjs from '@/lib/dayjs';
import LogsHistory from '@/components/newtab/logs/LogsHistory.vue';
const props = defineProps({
logId: {
type: String,
default: '',
},
});
const emit = defineEmits(['close']);
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const workflowStore = useWorkflowStore();
Expand All @@ -96,11 +112,12 @@ const interval = setInterval(() => {
}, 1000);
const running = computed(() =>
workflowStore.getAllStates.find(({ id }) => id === route.params.id)
workflowStore.getAllStates.find(({ id }) => id === props.logId)
);
function stopWorkflow() {
stopWorkflowExec(running.value.id);
emit('close');
}
function getBlockPath(blockId) {
const { workflowId, teamId } = running.value;
Expand All @@ -116,16 +133,12 @@ function getBlockPath(blockId) {
watch(
running,
async () => {
if (!route.name.startsWith('logs')) return;
if (!running.value && route.params.id) {
const log = await dbLogs.items
.where('id')
.equals(route.params.id)
.first();
if (!running.value && props.logId) {
const log = await dbLogs.items.where('id').equals(props.logId).first();
let path = '/logs';
if (log) {
path = `/logs/${route.params.id}`;
path = `/logs/${props.logId}`;
}
router.replace(path);
Expand Down
Loading

0 comments on commit 9853860

Please sign in to comment.