Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(editor): Add loading skeletons to Executions list page #6184

Merged
merged 9 commits into from
May 9, 2023
50 changes: 23 additions & 27 deletions packages/editor-ui/src/components/ExecutionFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -162,39 +162,35 @@ onBeforeMount(() => {
data-test-id="execution-filter-badge"
>{{ countSelectedFilterProps }}</n8n-badge
>
{{ $locale.baseText('executionsList.filters') }}
{{ locale.baseText('executionsList.filters') }}
</n8n-button>
</template>
<div data-test-id="execution-filter-form">
<div v-if="workflows?.length" :class="$style.group">
<label for="execution-filter-workflows">{{
$locale.baseText('workflows.heading')
}}</label>
<label for="execution-filter-workflows">{{ locale.baseText('workflows.heading') }}</label>
<n8n-select
id="execution-filter-workflows"
v-model="vModel.workflowId"
:placeholder="$locale.baseText('executionsFilter.selectWorkflow')"
:placeholder="locale.baseText('executionsFilter.selectWorkflow')"
size="medium"
filterable
data-test-id="executions-filter-workflows-select"
>
<div class="ph-no-capture">
<n8n-option
v-for="item in workflows"
:key="item.id"
v-for="(item, idx) in props.workflows"
:key="idx"
:label="item.name"
:value="item.id"
/>
</div>
</n8n-select>
</div>
<div v-if="showTags" :class="$style.group">
<label for="execution-filter-tags">{{
$locale.baseText('workflows.filters.tags')
}}</label>
<label for="execution-filter-tags">{{ locale.baseText('workflows.filters.tags') }}</label>
<TagsDropdown
id="execution-filter-tags"
:placeholder="$locale.baseText('workflowOpen.filterWorkflows')"
:placeholder="locale.baseText('workflowOpen.filterWorkflows')"
:currentTagIds="filter.tags"
:createEnabled="false"
@update="onTagsChange"
Expand All @@ -203,35 +199,35 @@ onBeforeMount(() => {
</div>
<div :class="$style.group">
<label for="execution-filter-status">{{
$locale.baseText('executionsList.status')
locale.baseText('executionsList.status')
}}</label>
<n8n-select
id="execution-filter-status"
v-model="vModel.status"
:placeholder="$locale.baseText('executionsFilter.selectStatus')"
:placeholder="locale.baseText('executionsFilter.selectStatus')"
size="medium"
filterable
data-test-id="executions-filter-status-select"
>
<n8n-option
v-for="item in statuses"
:key="item.id"
v-for="(item, idx) in statuses"
:key="idx"
:label="item.name"
:value="item.id"
/>
</n8n-select>
</div>
<div :class="$style.group">
<label for="execution-filter-start-date">{{
$locale.baseText('executionsFilter.start')
locale.baseText('executionsFilter.start')
}}</label>
<div :class="$style.dates">
<el-date-picker
id="execution-filter-start-date"
type="datetime"
v-model="vModel.startDate"
:format="DATE_TIME_MASK"
:placeholder="$locale.baseText('executionsFilter.startDate')"
:placeholder="locale.baseText('executionsFilter.startDate')"
data-test-id="executions-filter-start-date-picker"
/>
<span :class="$style.divider">to</span>
Expand All @@ -240,7 +236,7 @@ onBeforeMount(() => {
type="datetime"
v-model="vModel.endDate"
:format="DATE_TIME_MASK"
:placeholder="$locale.baseText('executionsFilter.endDate')"
:placeholder="locale.baseText('executionsFilter.endDate')"
data-test-id="executions-filter-end-date-picker"
/>
</div>
Expand All @@ -254,19 +250,19 @@ onBeforeMount(() => {
target="_blank"
href="https://docs.n8n.io/workflows/executions/custom-executions-data/"
>
{{ $locale.baseText('executionsFilter.customData.docsTooltip.link') }}
{{ locale.baseText('executionsFilter.customData.docsTooltip.link') }}
</a>
</template>
</i18n>
</template>
<span :class="$style.label">
{{ $locale.baseText('executionsFilter.savedData') }}
{{ locale.baseText('executionsFilter.savedData') }}
<n8n-icon :class="$style.tooltipIcon" icon="question-circle" size="small" />
</span>
</n8n-tooltip>
<div :class="$style.subGroup">
<label for="execution-filter-saved-data-key">{{
$locale.baseText('executionsFilter.savedDataKey')
locale.baseText('executionsFilter.savedDataKey')
}}</label>
<n8n-tooltip :disabled="isAdvancedExecutionFilterEnabled" placement="top">
<template #content>
Expand All @@ -276,7 +272,7 @@ onBeforeMount(() => {
href="#"
@click.prevent="goToUpgrade"
data-test-id="executions-filter-view-plans-link"
>{{ $locale.baseText('executionsFilter.customData.inputTooltip.link') }}</a
>{{ locale.baseText('executionsFilter.customData.inputTooltip.link') }}</a
>
</template>
</i18n>
Expand All @@ -287,21 +283,21 @@ onBeforeMount(() => {
type="text"
size="medium"
:disabled="!isAdvancedExecutionFilterEnabled"
:placeholder="$locale.baseText('executionsFilter.savedDataKeyPlaceholder')"
:placeholder="locale.baseText('executionsFilter.savedDataKeyPlaceholder')"
:value="filter.metadata[0]?.key"
@input="onFilterMetaChange(0, 'key', $event)"
data-test-id="execution-filter-saved-data-key-input"
/>
</n8n-tooltip>
<label for="execution-filter-saved-data-value">{{
$locale.baseText('executionsFilter.savedDataValue')
locale.baseText('executionsFilter.savedDataValue')
}}</label>
<n8n-tooltip :disabled="isAdvancedExecutionFilterEnabled" placement="top">
<template #content>
<i18n tag="span" path="executionsFilter.customData.inputTooltip">
<template #link>
<a href="#" @click.prevent="goToUpgrade">{{
$locale.baseText('executionsFilter.customData.inputTooltip.link')
locale.baseText('executionsFilter.customData.inputTooltip.link')
}}</a>
</template>
</i18n>
Expand All @@ -312,7 +308,7 @@ onBeforeMount(() => {
type="text"
size="medium"
:disabled="!isAdvancedExecutionFilterEnabled"
:placeholder="$locale.baseText('executionsFilter.savedDataValuePlaceholder')"
:placeholder="locale.baseText('executionsFilter.savedDataValuePlaceholder')"
:value="filter.metadata[0]?.value"
@input="onFilterMetaChange(0, 'value', $event)"
data-test-id="execution-filter-saved-data-value-input"
Expand All @@ -328,7 +324,7 @@ onBeforeMount(() => {
text
data-test-id="executions-filter-reset-button"
>
{{ $locale.baseText('executionsFilter.reset') }}
{{ locale.baseText('executionsFilter.reset') }}
</n8n-button>
</div>
</n8n-popover>
Expand Down
41 changes: 34 additions & 7 deletions packages/editor-ui/src/components/ExecutionsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
<div :class="$style.execListHeader">
<n8n-heading tag="h1" size="2xlarge">{{ this.pageTitle }}</n8n-heading>
<div :class="$style.execListHeaderControls">
<n8n-loading v-if="isMounting" :class="$style.filterLoader" variant="custom" />
<el-checkbox
v-else
class="mr-xl"
v-model="autoRefresh"
@change="handleAutoRefreshToggle"
data-test-id="execution-auto-refresh-checkbox"
>
{{ $locale.baseText('executionsList.autoRefresh') }}
</el-checkbox>
<execution-filter :workflows="workflows" @filterChanged="onFilterChanged" />
<execution-filter
v-show="!isMounting"
:workflows="workflows"
@filterChanged="onFilterChanged"
/>
</div>
</div>

Expand All @@ -30,7 +36,12 @@
data-test-id="select-all-executions-checkbox"
/>

<table :class="$style.execTable">
<div v-if="isMounting">
<n8n-loading :class="$style.tableLoader" variant="custom" />
<n8n-loading :class="$style.tableLoader" variant="custom" />
<n8n-loading :class="$style.tableLoader" variant="custom" />
</div>
<table v-else :class="$style.execTable">
<thead>
<tr>
<th>
Expand Down Expand Up @@ -210,7 +221,7 @@
</table>

<div
v-if="!combinedExecutions.length"
v-if="!combinedExecutions.length && !isMounting && !isDataLoading"
:class="$style.loadedAll"
data-test-id="execution-list-empty"
>
Expand All @@ -231,7 +242,11 @@
data-test-id="load-more-button"
/>
</div>
<div v-else :class="$style.loadedAll" data-test-id="execution-all-loaded">
<div
v-else-if="!isMounting && !isDataLoading"
:class="$style.loadedAll"
data-test-id="execution-all-loaded"
>
{{ $locale.baseText('executionsList.loadedAll') }}
</div>
</div>
Expand Down Expand Up @@ -300,6 +315,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
},
data() {
return {
isMounting: true,
finishedExecutions: [] as IExecutionsSummary[],
finishedExecutionsCount: 0,
finishedExecutionsCountEstimated: false,
Expand All @@ -326,7 +342,6 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
},
async created() {
await this.loadWorkflows();
//await this.refreshData();
this.handleAutoRefreshToggle();

this.$externalHooks().run('executionsList.openDialog');
Expand Down Expand Up @@ -480,10 +495,11 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
this.allExistingSelected = false;
Vue.set(this, 'selectedItems', {});
},
onFilterChanged(filter: ExecutionFilterType) {
async onFilterChanged(filter: ExecutionFilterType) {
this.filter = filter;
this.refreshData();
await this.refreshData();
this.handleClearSelection();
this.isMounting = false;
},
handleActionItemClick(commandData: { command: string; execution: IExecutionsSummary }) {
if (['currentlySaved', 'original'].includes(commandData.command)) {
Expand Down Expand Up @@ -1134,4 +1150,15 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
margin: 0 0 var(--spacing-s) var(--spacing-s);
color: var(--color-danger);
}

.filterLoader {
width: 220px;
height: 32px;
}

.tableLoader {
width: 100%;
height: 48px;
margin-bottom: var(--spacing-2xs);
}
</style>