primevue-mirror/apps/showcase/components/layout/AppDesigner.vue

167 lines
6.1 KiB
Vue
Raw Normal View History

2024-11-10 19:16:58 +00:00
<template>
2024-11-14 10:02:52 +00:00
<Drawer
2024-11-22 10:02:06 +00:00
v-model:visible="$appState.designer.active"
2024-11-14 10:02:52 +00:00
position="right"
class="designer !w-screen md:!w-[48rem]"
:modal="false"
:dismissable="false"
@after-show="onShow"
@after-hide="onHide"
:pt="{
header: 'p-5',
content: '!p-5',
footer: '!p-5'
}"
>
2024-12-26 14:41:51 +00:00
<template #header>
<div class="flex items-center gap-2">
<Button v-if="$appState.designer.activeView !== 'dashboard'" variant="text" severity="secondary" rounded type="button" icon="pi pi-chevron-left" @click="openDashboard" />
<span class="font-bold text-xl">{{ viewTitle }}</span>
</div>
</template>
2024-11-10 19:16:58 +00:00
2024-12-26 14:41:51 +00:00
<DesignDashboard v-if="$appState.designer.activeView === 'dashboard'" />
<DesignCreateTheme v-else-if="$appState.designer.activeView === 'create_theme'" />
<DesignEditor v-else-if="$appState.designer.activeView === 'editor'" :deferred="deferredTabs" />
2024-11-10 19:16:58 +00:00
<template #footer>
2024-12-27 20:17:25 +00:00
<DesignEditorFooter v-if="$appState.designer.activeView === 'editor'" />
2024-11-10 19:16:58 +00:00
</template>
</Drawer>
</template>
<script>
2024-12-28 08:59:21 +00:00
import EventBus from '@/app/AppEventBus';
import { $dt, updatePreset } from '@primevue/themes';
2024-11-10 19:16:58 +00:00
export default {
2024-12-28 08:59:21 +00:00
setup() {
const runtimeConfig = useRuntimeConfig();
return {
designerApiBase: runtimeConfig.public.designerApiBase
};
},
2024-11-10 19:16:58 +00:00
provide() {
return {
2024-12-27 20:17:25 +00:00
designerService: {
2024-12-26 14:41:51 +00:00
refreshACTokens: this.refreshACTokens,
2024-12-27 20:17:25 +00:00
saveTheme: this.saveTheme,
2024-12-28 08:59:21 +00:00
downloadTheme: this.downloadTheme,
applyTheme: this.applyTheme
2024-12-26 14:41:51 +00:00
}
2024-11-10 19:16:58 +00:00
};
},
data() {
return {
2024-12-26 14:41:51 +00:00
deferredTabs: true
2024-11-10 19:16:58 +00:00
};
},
methods: {
2024-12-26 14:41:51 +00:00
onShow() {
this.deferredTabs = false;
},
onHide() {
this.deferredTabs = true;
2024-11-12 09:56:37 +00:00
},
2024-12-28 08:59:21 +00:00
async downloadTheme(theme) {
2024-12-28 09:43:15 +00:00
if (!this.$appState.designer.licenseKey) {
this.$toast.add({ severity: 'error', summary: 'Not Available', detail: 'A license is required to download', life: 3000 });
} else {
try {
const response = await $fetch(this.designerApiBase + '/theme/download/' + this.$appState.designer.licenseKey + '/' + theme.t_key, {
responseType: 'blob'
});
2024-12-28 08:59:21 +00:00
2024-12-28 09:43:15 +00:00
if (response.error) {
this.$toast.add({ severity: 'error', summary: 'An Error Occurred', detail: error.message, life: 3000 });
} else {
const blobUrl = window.URL.createObjectURL(response);
const link = document.createElement('a');
2024-12-28 08:59:21 +00:00
2024-12-28 09:43:15 +00:00
link.href = blobUrl;
link.download = theme.t_name + '.zip';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobUrl);
}
} catch (err) {
this.$toast.add({ severity: 'error', summary: 'An Error Occurred', detail: 'Failed to download file', life: 3000 });
2024-12-28 08:59:21 +00:00
}
}
},
async updateTheme(theme) {
const { error } = await $fetch(this.designerApiBase + '/theme/update', {
method: 'POST',
body: {
key: theme.key,
preset: theme.preset,
config: theme.config,
license_key: this.$appState.designer.licenseKey
}
});
if (error) {
this.$toast.add({ severity: 'error', summary: 'An error occured', detail: error.message, life: 3000 });
}
},
applyTheme(theme) {
2024-12-28 09:43:15 +00:00
if (this.$appState.designer.licenseKey) {
this.updateTheme(theme);
}
2024-12-28 08:59:21 +00:00
updatePreset(theme.preset);
EventBus.emit('theme-palette-change');
2024-11-12 12:38:29 +00:00
},
camelCaseToDotCase(name) {
return name.replace(/([a-z])([A-Z])/g, '$1.$2').toLowerCase();
},
generateACTokens(parentPath, obj) {
for (let key in obj) {
if (key === 'dark' || key === 'components') {
continue;
}
if (key === 'primitive' || key === 'semantic' || key === 'colorScheme' || key === 'light' || key === 'extend') {
this.generateACTokens(null, obj[key]);
} else {
if (typeof obj[key] === 'object') {
this.generateACTokens(parentPath ? parentPath + '.' + key : key, obj[key]);
} else {
const regex = /\.\d+$/;
const tokenName = this.camelCaseToDotCase(parentPath ? parentPath + '.' + key : key);
const tokenValue = $dt(tokenName).value;
const isColor = tokenName.includes('color') || tokenName.includes('background') || regex.test(tokenName);
2024-12-26 14:41:51 +00:00
this.$appState.designer.theme.acTokens.push({ token: tokenName, label: '{' + tokenName + '}', variable: $dt(tokenName).variable, value: tokenValue, isColor: isColor });
}
}
}
2024-11-12 23:39:09 +00:00
},
refreshACTokens() {
2024-12-26 14:41:51 +00:00
this.$appState.designer.theme.acTokens = [];
this.generateACTokens(null, this.$appState.designer.theme.preset);
2024-11-13 10:00:37 +00:00
},
2024-12-26 14:41:51 +00:00
openDashboard() {
this.$appState.designer.activeView = 'dashboard';
}
},
computed: {
viewTitle() {
const view = this.$appState.designer.activeView;
if (view === 'dashboard') {
return 'Theme Designer';
} else if (view === 'create_theme') {
return 'Create Theme';
} else if (view === 'editor') {
return this.$appState.designer.theme.name;
2024-11-13 10:00:37 +00:00
}
2024-12-26 14:41:51 +00:00
return null;
2024-11-10 19:16:58 +00:00
}
}
};
</script>