feat(ui): adapt layout for large screens

This commit is contained in:
Denis Gukov 2024-12-14 22:13:45 +05:00
parent f749e28231
commit ba23b56831
No known key found for this signature in database
GPG Key ID: 044381366A5D4731
15 changed files with 254 additions and 184 deletions

View File

@ -585,10 +585,6 @@
</template> </template>
<style lang="scss"> <style lang="scss">
.v-alert__wrapper {
//overflow: auto;
}
.v-dialog > .v-card > .v-card__title { .v-dialog > .v-card > .v-card__title {
flex-wrap: nowrap; flex-wrap: nowrap;
overflow: hidden; overflow: hidden;
@ -649,7 +645,22 @@
height: 64px !important; height: 64px !important;
} }
.v-data-table-header { .v-data-table .v-data-footer {
margin-left: 16px !important;
margin-right: 16px !important;
}
.v-data-table__wrapper {
padding-left: 16px !important;
padding-right: 16px !important;
}
.v-data-table td:first-child {
padding-left: 2px !important;
}
.v-data-table td:last-child {
padding-right: 2px !important;
} }
.v-data-table > .v-data-table__wrapper > table > thead > tr:last-child > th { .v-data-table > .v-data-table__wrapper > table > thead > tr:last-child > th {
@ -657,8 +668,18 @@
white-space: nowrap; white-space: nowrap;
} }
.v-data-table > .v-data-table__wrapper > table > thead > tr {
background: transparent;
&:hover {
background-color: rgba(143, 143, 143, 0.04);
}
}
.v-data-table > .v-data-table__wrapper > table > tbody > tr { .v-data-table > .v-data-table__wrapper > table > tbody > tr {
background: transparent !important; background: transparent !important;
&:hover {
background-color: rgba(143, 143, 143, 0.04) !important;
}
& > td { & > td {
white-space: nowrap; white-space: nowrap;

View File

@ -1,31 +1,35 @@
<template> <template>
<v-tabs show-arrows class="pl-4"> <div>
<v-tab <v-tabs show-arrows class="pl-4">
v-if="projectType === ''" <v-tab
key="history" v-if="projectType === ''"
:to="`/project/${projectId}/history`" key="history"
>{{ $t('history') }} :to="`/project/${projectId}/history`"
</v-tab> >{{ $t('history') }}
</v-tab>
<v-tab key="activity" :to="`/project/${projectId}/activity`">{{ $t('activity') }}</v-tab> <v-tab key="activity" :to="`/project/${projectId}/activity`">{{ $t('activity') }}</v-tab>
<v-tab <v-tab
v-if="canUpdateProject" v-if="canUpdateProject"
key="settings" key="settings"
:to="`/project/${projectId}/settings`" :to="`/project/${projectId}/settings`"
>{{ $t('settings') }} >{{ $t('settings') }}
</v-tab> </v-tab>
<v-tab <v-tab
v-if="projectType === ''" v-if="projectType === ''"
key="runners" key="runners"
:to="`/project/${projectId}/runners`" :to="`/project/${projectId}/runners`"
> >
{{ $t('runners') }} {{ $t('runners') }}
<!-- <v-chip small class="ml-1" color="purple" style="color: white">Pro</v-chip> --> <!-- <v-chip small class="ml-1" color="purple" style="color: white">Pro</v-chip> -->
<v-icon class="ml-1" large color="hsl(348deg, 86%, 61%)">mdi-professional-hexagon</v-icon> <v-icon class="ml-1" large color="hsl(348deg, 86%, 61%)">mdi-professional-hexagon</v-icon>
</v-tab> </v-tab>
</v-tabs> </v-tabs>
<v-divider style="margin-top: -1px;" />
</div>
</template> </template>
<script> <script>
import PermissionsCheck from '@/components/PermissionsCheck'; import PermissionsCheck from '@/components/PermissionsCheck';

View File

@ -16,14 +16,14 @@
:items="tasks" :items="tasks"
:hide-default-footer="hideFooter" :hide-default-footer="hideFooter"
:footer-props="{ itemsPerPageOptions: [20] }" :footer-props="{ itemsPerPageOptions: [20] }"
class="mt-0" class="mt-0 TaskListTable"
> >
<template v-slot:item.id="{ item }"> <template v-slot:item.id="{ item }">
<TaskLink <TaskLink
:task-id="item.id" :task-id="item.id"
:label="'#' + item.id" :label="'#' + item.id"
/> />
<div style="font-size: 14px; line-height: 1;"> <div style="font-size: 14px;">
<span v-if="item.message"> <span v-if="item.message">
<v-icon x-small>mdi-message-outline</v-icon> {{ item.message }} <v-icon x-small>mdi-message-outline</v-icon> {{ item.message }}
</span> </span>
@ -68,6 +68,11 @@
</v-data-table> </v-data-table>
</div> </div>
</template> </template>
<style lang="scss">
.TaskListTable td {
height: 60px !important;
}
</style>
<script> <script>
import axios from 'axios'; import axios from 'axios';
import TaskStatus from '@/components/TaskStatus.vue'; import TaskStatus from '@/components/TaskStatus.vue';

View File

@ -10,3 +10,11 @@ $material-light: (
); );
$tabs-bar-background-color: 'toolbar'; $tabs-bar-background-color: 'toolbar';
:root {
--breakpoint-sm: 600px;
--breakpoint-md: 960px;
--breakpoint-lg: 1264px;
--breakpoint-xl: 1904px;
--nav-drawer-width: 260px;
}

View File

@ -16,6 +16,7 @@
:items="items" :items="items"
class="mt-4" class="mt-4"
:footer-props="{ itemsPerPageOptions: [20] }" :footer-props="{ itemsPerPageOptions: [20] }"
style="max-width: calc(var(--breakpoint-lg) - var(--nav-drawer-width)); margin: auto;"
> >
<template v-slot:item.created="{ item }"> <template v-slot:item.created="{ item }">
{{ item.created | formatDate }} {{ item.created | formatDate }}

View File

@ -47,30 +47,30 @@
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
<v-container class="pa-0"> <v-divider />
<v-data-table
:headers="headers" <v-data-table
:items="items" :headers="headers"
hide-default-footer :items="items"
class="mt-4" hide-default-footer
:items-per-page="Number.MAX_VALUE" class="mt-4"
style="max-width: 800px;" :items-per-page="Number.MAX_VALUE"
> style="max-width: calc(var(--breakpoint-lg) - var(--nav-drawer-width) - 200px); margin: auto;"
<template v-slot:item.name="{ item }"> >
<a @click="editItem(item.id)">{{ item.name }}</a> <template v-slot:item.name="{ item }">
</template> <a @click="editItem(item.id)">{{ item.name }}</a>
<template v-slot:item.actions="{ item }"> </template>
<v-btn-toggle dense :value-comparator="() => false"> <template v-slot:item.actions="{ item }">
<v-btn @click="askDeleteItem(item.id)"> <v-btn-toggle dense :value-comparator="() => false">
<v-icon>mdi-delete</v-icon> <v-btn @click="askDeleteItem(item.id)">
</v-btn> <v-icon>mdi-delete</v-icon>
<v-btn @click="editItem(item.id)"> </v-btn>
<v-icon>mdi-pencil</v-icon> <v-btn @click="editItem(item.id)">
</v-btn> <v-icon>mdi-pencil</v-icon>
</v-btn-toggle> </v-btn>
</template> </v-btn-toggle>
</v-data-table> </template>
</v-container> </v-data-table>
</div> </div>
</template> </template>

View File

@ -17,20 +17,20 @@
:headers="headers" :headers="headers"
:items="items" :items="items"
:footer-props="{ itemsPerPageOptions: [20] }" :footer-props="{ itemsPerPageOptions: [20] }"
class="mt-4" class="mt-4 HistoryTable"
> >
<template v-slot:item.tpl_alias="{ item }"> <template v-slot:item.tpl_alias="{ item }">
<div class="d-flex align-center"> <div class="d-flex align-center">
<v-icon <v-icon
class="mr-3" class="mr-3"
small small
> >
{{ getAppIcon(item.tpl_app) }} {{ getAppIcon(item.tpl_app) }}
</v-icon> </v-icon>
<!-- <v-icon class="mr-3" small>--> <!-- <v-icon class="mr-3" small>-->
<!-- {{ TEMPLATE_TYPE_ICONS[item.tpl_type] }}--> <!-- {{ TEMPLATE_TYPE_ICONS[item.tpl_type] }}-->
<!-- </v-icon>--> <!-- </v-icon>-->
<TaskLink <TaskLink
:task-id="item.id" :task-id="item.id"
@ -46,7 +46,7 @@
</router-link> </router-link>
</div> </div>
<div style="font-size: 14px; line-height: 1;" class="ml-7"> <div style="font-size: 14px;" class="ml-7">
<span v-if="item.message"> <span v-if="item.message">
<v-icon x-small>mdi-message-outline</v-icon> {{ item.message }} <v-icon x-small>mdi-message-outline</v-icon> {{ item.message }}
</span> </span>
@ -93,6 +93,12 @@
</div> </div>
</template> </template>
<style lang="scss">
.HistoryTable td {
height: 60px !important;
}
</style>
<script> <script>
import ItemListPageBase from '@/components/ItemListPageBase'; import ItemListPageBase from '@/components/ItemListPageBase';
import EventBus from '@/event-bus'; import EventBus from '@/event-bus';

View File

@ -45,7 +45,9 @@
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
<div class="px-4 py-3"> <div
class="px-4 py-3"
>
<div class="mb-3 pl-1" v-if="(aliases || []).length === 0">There is no aliases.</div> <div class="mb-3 pl-1" v-if="(aliases || []).length === 0">There is no aliases.</div>
<div v-else v-for="alias of (aliases || [])" :key="alias.id"> <div v-else v-for="alias of (aliases || [])" :key="alias.id">
@ -64,11 +66,14 @@
</v-btn> </v-btn>
</div> </div>
<v-divider />
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 200px); margin: auto;"
> >
<template v-slot:item.name="{ item }"> <template v-slot:item.name="{ item }">
<router-link <router-link
@ -132,18 +137,19 @@ export default {
return [{ return [{
text: this.$i18n.t('name'), text: this.$i18n.t('name'),
value: 'name', value: 'name',
width: '33.33%', width: '40%',
sortable: true, sortable: true,
}, },
{ {
text: this.$i18n.t('template'), text: this.$i18n.t('template'),
value: 'template_id', value: 'template_id',
width: '33.33%', width: '60%',
sortable: true, sortable: true,
}, },
{ {
value: 'actions', value: 'actions',
sortable: false, sortable: false,
width: '0%',
}]; }];
}, },
getItemsUrl() { getItemsUrl() {

View File

@ -82,15 +82,17 @@
</v-list-item> </v-list-item>
</v-list> </v-list>
</v-menu> </v-menu>
</v-toolbar> </v-toolbar>
<v-divider class="hidden-lg-and-down"/>
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
hide-default-footer hide-default-footer
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 200px); margin: auto;"
> >
<template v-slot:item.name="{ item }"> <template v-slot:item.name="{ item }">
<v-icon class="mr-3" small> <v-icon class="mr-3" small>
@ -162,7 +164,7 @@ export default {
return [{ return [{
text: this.$i18n.t('name'), text: this.$i18n.t('name'),
value: 'name', value: 'name',
width: '20%', width: '30%',
}, },
{ {
text: this.$i18n.t('type'), text: this.$i18n.t('type'),
@ -172,12 +174,12 @@ export default {
{ {
text: this.$i18n.t('path'), text: this.$i18n.t('path'),
value: 'inventory', value: 'inventory',
width: '20%', width: '50%',
}, },
{ {
value: 'actions', value: 'actions',
sortable: false, sortable: false,
width: '80%', width: '0%',
}, },
]; ];
}, },

View File

@ -45,41 +45,40 @@
>{{ $t('newKey') }}</v-btn> >{{ $t('newKey') }}</v-btn>
</v-toolbar> </v-toolbar>
<v-container class="pa-0"> <v-divider />
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
hide-default-footer hide-default-footer
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="max-width: 1000px;" style="max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 200px); margin: auto;"
> >
<template v-slot:item.name="{ item }"> <template v-slot:item.name="{ item }">
{{ item.name }} {{ item.name }}
<v-chip <v-chip
color="error" color="error"
v-if="item.empty && item.type !== 'none'" v-if="item.empty && item.type !== 'none'"
small small
style="font-weight: bold;" style="font-weight: bold;"
class="ml-2" class="ml-2"
>{{ $t('empty') }}</v-chip> >{{ $t('empty') }}</v-chip>
</template> </template>
<template v-slot:item.type="{ item }"> <template v-slot:item.type="{ item }">
<code>{{ item.type }}</code> <code>{{ item.type }}</code>
</template> </template>
<template v-slot:item.actions="{ item }"> <template v-slot:item.actions="{ item }">
<v-btn-toggle dense :value-comparator="() => false"> <v-btn-toggle dense :value-comparator="() => false">
<v-btn @click="askDeleteItem(item.id)"> <v-btn @click="askDeleteItem(item.id)">
<v-icon>mdi-delete</v-icon> <v-icon>mdi-delete</v-icon>
</v-btn> </v-btn>
<v-btn @click="editItem(item.id)"> <v-btn @click="editItem(item.id)">
<v-icon>mdi-pencil</v-icon> <v-icon>mdi-pencil</v-icon>
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>
</template> </template>
</v-data-table> </v-data-table>
</v-container>
</div> </div>

View File

@ -44,12 +44,15 @@
>{{ $t('newRepository') }}</v-btn> >{{ $t('newRepository') }}</v-btn>
</v-toolbar> </v-toolbar>
<v-divider />
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
hide-default-footer hide-default-footer
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 100px); margin: auto;"
> >
<template v-slot:item.git_url="{ item }"> <template v-slot:item.git_url="{ item }">
{{ item.git_url }} {{ item.git_url }}

View File

@ -33,7 +33,7 @@
@yes="deleteItem(itemId)" @yes="deleteItem(itemId)"
/> />
<v-toolbar flat > <v-toolbar flat>
<v-app-bar-nav-icon @click="showDrawer()"></v-app-bar-nav-icon> <v-app-bar-nav-icon @click="showDrawer()"></v-app-bar-nav-icon>
<v-toolbar-title>{{ $t('schedule') }}</v-toolbar-title> <v-toolbar-title>{{ $t('schedule') }}</v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
@ -45,12 +45,18 @@
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
<v-divider />
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
hide-default-footer hide-default-footer
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="
max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 200px);
margin: auto;
"
> >
<template v-slot:item.active="{ item }"> <template v-slot:item.active="{ item }">
<v-switch <v-switch

View File

@ -18,70 +18,72 @@
:can-update-project="true" :can-update-project="true"
/> />
<h2 class="ml-7 mt-8 mb-1">General</h2> <div style="margin: auto; max-width: 600px; padding: 0 16px;">
<h2 class="mt-8 mb-1">General</h2>
<v-divider class="mb-8" /> <v-divider class="mb-8" />
<div class="project-settings-form"> <div class="project-settings-form">
<div style="height: 300px;"> <div style="height: 300px;">
<ProjectForm :item-id="projectId" ref="form" @error="onError" @save="onSave"/> <ProjectForm :item-id="projectId" ref="form" @error="onError" @save="onSave"/>
</div>
<div class="text-right">
<v-btn color="primary" @click="saveProject()">{{ $t('save') }}</v-btn>
</div>
</div> </div>
<div class="text-right"> <h2 class="mt-8 mb-1">Danger Zone</h2>
<v-btn color="primary" @click="saveProject()">{{ $t('save') }}</v-btn>
<v-divider class="mb-8" />
<div class="project-backup project-settings-button">
<v-row align="center">
<v-col class="shrink">
<v-btn
color="primary"
@click="backupProject"
:disabled="backupProgress"
min-width="170"
>{{ $t('backup') }}
</v-btn>
<v-progress-linear
v-if="backupProgress"
color="primary accent-4"
indeterminate
rounded
height="36"
style="margin-top: -36px"
></v-progress-linear>
</v-col>
<v-col class="grow">
<div style="font-size: 14px;">
{{ $t('downloadTheProjectBackupFile') }}
</div>
</v-col>
</v-row>
</div>
<div class="project-delete-form project-settings-button">
<v-row align="center">
<v-col class="shrink">
<v-btn
color="error"
min-width="170"
@click="deleteProjectDialog = true"
>{{ $t('deleteProject2') }}
</v-btn>
</v-col>
<v-col class="grow">
<div style="font-size: 14px; color: #ff5252">
{{ $t('onceYouDeleteAProjectThereIsNoGoingBackPleaseBeCer') }}
</div>
</v-col>
</v-row>
</div> </div>
</div>
<h2 class="ml-7 mt-8 mb-1">Danger Zone</h2>
<v-divider class="mb-8" />
<div class="project-backup project-settings-button">
<v-row align="center">
<v-col class="shrink">
<v-btn
color="primary"
@click="backupProject"
:disabled="backupProgress"
min-width="170"
>{{ $t('backup') }}
</v-btn>
<v-progress-linear
v-if="backupProgress"
color="primary accent-4"
indeterminate
rounded
height="36"
style="margin-top: -36px"
></v-progress-linear>
</v-col>
<v-col class="grow">
<div style="font-size: 14px;">
{{ $t('downloadTheProjectBackupFile') }}
</div>
</v-col>
</v-row>
</div>
<div class="project-delete-form project-settings-button">
<v-row align="center">
<v-col class="shrink">
<v-btn
color="error"
min-width="170"
@click="deleteProjectDialog = true"
>{{ $t('deleteProject2') }}
</v-btn>
</v-col>
<v-col class="grow">
<div style="font-size: 14px; color: #ff5252">
{{ $t('onceYouDeleteAProjectThereIsNoGoingBackPleaseBeCer') }}
</div>
</v-col>
</v-row>
</div> </div>
</div> </div>
</template> </template>
@ -89,13 +91,13 @@
@import '~vuetify/src/styles/styles.sass'; @import '~vuetify/src/styles/styles.sass';
.project-settings-form { .project-settings-form {
max-width: 600px; //max-width: 600px;
margin: 30px; margin: 30px 0;
} }
.project-settings-button { .project-settings-button {
//max-width: 400px; //max-width: 400px;
margin: 30px; margin: 30px 0;
@media #{map-get($display-breakpoints, 'sm-and-down')} { @media #{map-get($display-breakpoints, 'sm-and-down')} {
padding: 0 6px; padding: 0 6px;

View File

@ -44,15 +44,19 @@
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
<v-divider />
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="items" :items="items"
hide-default-footer hide-default-footer
class="mt-4" class="mt-4"
:items-per-page="Number.MAX_VALUE" :items-per-page="Number.MAX_VALUE"
style="max-width: calc(var(--breakpoint-xl) - var(--nav-drawer-width) - 200px); margin: auto;"
> >
<template v-slot:item.role="{ item }"> <template v-slot:item.role="{ item }">
<v-select <v-select
hide-details
v-model="item.role" v-model="item.role"
:items="USER_ROLES" :items="USER_ROLES"
item-value="slug" item-value="slug"
@ -60,6 +64,7 @@
:style="{width: '200px'}" :style="{width: '200px'}"
@change="updateProjectUser(item)" @change="updateProjectUser(item)"
v-if="can(USER_PERMISSIONS.manageProjectUsers)" v-if="can(USER_PERMISSIONS.manageProjectUsers)"
class="pt-0 mt-0"
/> />
<div v-else>{{ USER_ROLES.find(r => r.slug === item.role).title }}</div> <div v-else>{{ USER_ROLES.find(r => r.slug === item.role).title }}</div>
</template> </template>
@ -119,19 +124,22 @@ export default {
{ {
text: this.$i18n.t('name'), text: this.$i18n.t('name'),
value: 'name', value: 'name',
width: '50%', width: '40%',
}, },
{ {
text: this.$i18n.t('username'), text: this.$i18n.t('username'),
value: 'username', value: 'username',
width: '30%',
}, },
{ {
text: this.$i18n.t('role'), text: this.$i18n.t('role'),
value: 'role', value: 'role',
width: '30%',
}, },
{ {
value: 'actions', value: 'actions',
sortable: false, sortable: false,
width: '0%',
}]; }];
}, },

View File

@ -27,11 +27,11 @@
</v-dialog> </v-dialog>
<EditTemplateDialog <EditTemplateDialog
v-model="editDialog" v-model="editDialog"
:project-id="projectId" :project-id="projectId"
:item-app="itemApp" :item-app="itemApp"
item-id="new" item-id="new"
@save="loadItems()" @save="loadItems()"
></EditTemplateDialog> ></EditTemplateDialog>
<NewTaskDialog <NewTaskDialog
@ -88,10 +88,10 @@
<v-divider v-if="isAdmin && appsMixin.activeAppIds.length > 0"/> <v-divider v-if="isAdmin && appsMixin.activeAppIds.length > 0"/>
<v-list-item <v-list-item
v-if="isAdmin" v-if="isAdmin"
key="other" key="other"
link link
href="/apps" href="/apps"
> >
<v-list-item-icon> <v-list-item-icon>
<v-icon>mdi-cogs</v-icon> <v-icon>mdi-cogs</v-icon>
@ -127,6 +127,8 @@
</v-btn> </v-btn>
</v-tabs> </v-tabs>
<v-divider style="margin-top: -1px;"/>
<v-data-table <v-data-table
hide-default-footer hide-default-footer
class="mt-4 templates-table" class="mt-4 templates-table"
@ -148,9 +150,9 @@
{{ getAppIcon(item.app) }} {{ getAppIcon(item.app) }}
</v-icon> </v-icon>
<!-- <v-icon class="mr-3" small>--> <!-- <v-icon class="mr-3" small>-->
<!-- {{ TEMPLATE_TYPE_ICONS[item.type] }}--> <!-- {{ TEMPLATE_TYPE_ICONS[item.type] }}-->
<!-- </v-icon>--> <!-- </v-icon>-->
<router-link <router-link
:to="viewId :to="viewId
@ -196,7 +198,7 @@
:tooltip="item.last_task.message" :tooltip="item.last_task.message"
/> />
<div style="color: gray; font-size: 14px;"> <div style="color: gray; font-size: 14px;">
{{ $t('by', {user_name: item.last_task.user_name }) }} {{ $t('by', {user_name: item.last_task.user_name}) }}
</div> </div>
</div> </div>
</template> </template>
@ -269,10 +271,7 @@ import TaskStatus from '@/components/TaskStatus.vue';
import socket from '@/socket'; import socket from '@/socket';
import NewTaskDialog from '@/components/NewTaskDialog.vue'; import NewTaskDialog from '@/components/NewTaskDialog.vue';
import { import { TEMPLATE_TYPE_ACTION_TITLES, TEMPLATE_TYPE_ICONS } from '@/lib/constants';
TEMPLATE_TYPE_ACTION_TITLES,
TEMPLATE_TYPE_ICONS,
} from '@/lib/constants';
import EditTemplateDialog from '@/components/EditTemplateDialog.vue'; import EditTemplateDialog from '@/components/EditTemplateDialog.vue';
import AppsMixin from '@/components/AppsMixin'; import AppsMixin from '@/components/AppsMixin';