mirror of
https://github.com/Lissy93/dashy.git
synced 2025-07-22 13:14:58 +02:00
✨ Adds ability to edit pageInfo through the UI
This commit is contained in:
parent
a48024e59c
commit
8147f40e9c
@ -193,6 +193,7 @@
|
|||||||
"edit-mode-name": "Edit Mode",
|
"edit-mode-name": "Edit Mode",
|
||||||
"edit-mode-subtitle": "You are in Edit Mode",
|
"edit-mode-subtitle": "You are in Edit Mode",
|
||||||
"edit-mode-description": "This means you can make modifications to your config, and preview the results, but until you save, none of your changes will be preserved.",
|
"edit-mode-description": "This means you can make modifications to your config, and preview the results, but until you save, none of your changes will be preserved.",
|
||||||
|
"save-stage-btn": "Save",
|
||||||
"export": {
|
"export": {
|
||||||
"export-title": "Export Config",
|
"export-title": "Export Config",
|
||||||
"copy-clipboard-btn": "Copy to Clipboard",
|
"copy-clipboard-btn": "Copy to Clipboard",
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
@click="click ? click() : () => null"
|
@click="click ? click() : () => null"
|
||||||
:disabled="disabled"
|
|
||||||
:class="disallow ? 'disallowed': ''"
|
:class="disallow ? 'disallowed': ''"
|
||||||
|
:type="type || 'button'"
|
||||||
|
:disabled="disabled"
|
||||||
|
v-tooltip="hoverText"
|
||||||
|
:title="tooltip"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<slot name="text"></slot>
|
<slot name="text"></slot>
|
||||||
@ -15,10 +18,21 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'Button',
|
name: 'Button',
|
||||||
props: {
|
props: {
|
||||||
text: String,
|
text: String, // The text to be displayed in the button
|
||||||
click: Function,
|
click: Function, // Function to call when clicked
|
||||||
disabled: Boolean,
|
disabled: Boolean, // If true, button cannot be clicked
|
||||||
disallow: Boolean,
|
disallow: Boolean, // Show not-allowed cursor when true
|
||||||
|
type: String, // The html button type attribute
|
||||||
|
tooltip: String, // Text to be displayed on hover
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/* If tooltip prop specified, then return config for v-tooltip */
|
||||||
|
hoverText() {
|
||||||
|
const content = this.tooltip;
|
||||||
|
const trigger = 'hover focus';
|
||||||
|
const delay = { show: 350, hide: 100 };
|
||||||
|
return (content) ? { content, trigger, delay } : undefined;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -12,8 +12,11 @@
|
|||||||
<div class="edit-banner-section empty-space"></div>
|
<div class="edit-banner-section empty-space"></div>
|
||||||
<!-- Save Buttons -->
|
<!-- Save Buttons -->
|
||||||
<div class="edit-banner-section save-buttons-container">
|
<div class="edit-banner-section save-buttons-container">
|
||||||
<p class="section-sub-title">Config Saving Options</p>
|
<p class="section-sub-title">
|
||||||
|
{{ $t('interactive-editor.config-save-methods-subheading') }}
|
||||||
|
</p>
|
||||||
<Button
|
<Button
|
||||||
|
:click="openExportConfigMenu"
|
||||||
v-tooltip="tooltip($t('interactive-editor.export-config-tooltip'))"
|
v-tooltip="tooltip($t('interactive-editor.export-config-tooltip'))"
|
||||||
>
|
>
|
||||||
{{ $t('interactive-editor.export-config-btn') }}
|
{{ $t('interactive-editor.export-config-btn') }}
|
||||||
@ -41,8 +44,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Open Modal Buttons -->
|
<!-- Open Modal Buttons -->
|
||||||
<div class="edit-banner-section edit-site-config-buttons">
|
<div class="edit-banner-section edit-site-config-buttons">
|
||||||
<p class="section-sub-title">Edit Site Data</p>
|
<p class="section-sub-title">
|
||||||
|
{{ $t('interactive-editor.edit-site-data-subheading') }}
|
||||||
|
</p>
|
||||||
<Button
|
<Button
|
||||||
|
:click="openEditPageInfo"
|
||||||
v-tooltip="tooltip($t('interactive-editor.edit-page-info-tooltip'))"
|
v-tooltip="tooltip($t('interactive-editor.edit-page-info-tooltip'))"
|
||||||
>
|
>
|
||||||
{{ $t('interactive-editor.edit-page-info-btn') }}
|
{{ $t('interactive-editor.edit-page-info-btn') }}
|
||||||
@ -55,12 +61,16 @@
|
|||||||
<AppConfigIcon />
|
<AppConfigIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Modals for editing appConfig + pageInfo -->
|
||||||
|
<EditPageInfo />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Button from '@/components/FormElements/Button';
|
import Button from '@/components/FormElements/Button';
|
||||||
import StoreKeys from '@/utils/StoreMutations';
|
import StoreKeys from '@/utils/StoreMutations';
|
||||||
|
import { modalNames } from '@/utils/defaults';
|
||||||
|
import EditPageInfo from '@/components/InteractiveEditor/EditPageInfo';
|
||||||
|
|
||||||
import SaveLocallyIcon from '@/assets/interface-icons/interactive-editor-save-locally.svg';
|
import SaveLocallyIcon from '@/assets/interface-icons/interactive-editor-save-locally.svg';
|
||||||
import SaveToDiskIcon from '@/assets/interface-icons/interactive-editor-save-disk.svg';
|
import SaveToDiskIcon from '@/assets/interface-icons/interactive-editor-save-disk.svg';
|
||||||
@ -73,6 +83,7 @@ export default {
|
|||||||
name: 'EditModeSaveMenu',
|
name: 'EditModeSaveMenu',
|
||||||
components: {
|
components: {
|
||||||
Button,
|
Button,
|
||||||
|
EditPageInfo,
|
||||||
SaveLocallyIcon,
|
SaveLocallyIcon,
|
||||||
SaveToDiskIcon,
|
SaveToDiskIcon,
|
||||||
ExportIcon,
|
ExportIcon,
|
||||||
@ -88,6 +99,14 @@ export default {
|
|||||||
tooltip(content) {
|
tooltip(content) {
|
||||||
return { content, trigger: 'hover focus', delay: 250 };
|
return { content, trigger: 'hover focus', delay: 250 };
|
||||||
},
|
},
|
||||||
|
openExportConfigMenu() {
|
||||||
|
this.$modal.show(modalNames.EXPORT_CONFIG_MENU);
|
||||||
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, true);
|
||||||
|
},
|
||||||
|
openEditPageInfo() {
|
||||||
|
this.$modal.show(modalNames.EDIT_PAGE_INFO);
|
||||||
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, true);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -159,5 +178,16 @@ div.edit-mode-bottom-banner {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Set colors for buttons */
|
||||||
|
.edit-banner-section button {
|
||||||
|
color: var(--interactive-editor-color);
|
||||||
|
border-color: var(--interactive-editor-color);
|
||||||
|
background: var(--interactive-editor-background);
|
||||||
|
&:hover {
|
||||||
|
color: var(--interactive-editor-background);
|
||||||
|
border-color: var(--interactive-editor-color);
|
||||||
|
background: var(--interactive-editor-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
96
src/components/InteractiveEditor/EditPageInfo.vue
Normal file
96
src/components/InteractiveEditor/EditPageInfo.vue
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<modal
|
||||||
|
:name="modalName"
|
||||||
|
:resizable="true"
|
||||||
|
width="50%"
|
||||||
|
height="80%"
|
||||||
|
classes="dashy-modal edit-page-info"
|
||||||
|
@closed="modalClosed"
|
||||||
|
>
|
||||||
|
<div class="edit-page-info-inner">
|
||||||
|
<h3>{{ $t('interactive-editor.edit-page-info-btn') }}</h3>
|
||||||
|
<FormSchema
|
||||||
|
:schema="schema"
|
||||||
|
v-model="formData"
|
||||||
|
@submit.prevent="saveToState"
|
||||||
|
class="page-info-form"
|
||||||
|
name="pageInfoForm"
|
||||||
|
>
|
||||||
|
<Button type="submit">
|
||||||
|
{{ $t('interactive-editor.save-stage-btn') }}
|
||||||
|
<SaveIcon />
|
||||||
|
</button>
|
||||||
|
</FormSchema>
|
||||||
|
</div>
|
||||||
|
</modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FormSchema from '@formschema/native';
|
||||||
|
import DashySchema from '@/utils/ConfigSchema';
|
||||||
|
import StoreKeys from '@/utils/StoreMutations';
|
||||||
|
import { modalNames } from '@/utils/defaults';
|
||||||
|
import Button from '@/components/FormElements/Button';
|
||||||
|
import SaveIcon from '@/assets/interface-icons/save-config.svg';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'EditPageInfo',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {},
|
||||||
|
schema: DashySchema.properties.pageInfo,
|
||||||
|
modalName: modalNames.EDIT_PAGE_INFO,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {},
|
||||||
|
components: {
|
||||||
|
FormSchema,
|
||||||
|
Button,
|
||||||
|
SaveIcon,
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.formData = this.pageInfo;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
pageInfo() {
|
||||||
|
return this.$store.getters.pageInfo;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/* When form submitteed, update VueX store with new pageInfo, and close modal */
|
||||||
|
saveToState() {
|
||||||
|
this.$store.commit(StoreKeys.UPDATE_PAGE_INFO, this.formData);
|
||||||
|
this.$modal.hide(this.modalName);
|
||||||
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, false);
|
||||||
|
this.$store.commit(StoreKeys.SET_EDIT_MODE, true);
|
||||||
|
},
|
||||||
|
/* Called when modal manually closed, updates state to allow searching again */
|
||||||
|
modalClosed() {
|
||||||
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '@/styles/style-helpers.scss';
|
||||||
|
@import '@/styles/media-queries.scss';
|
||||||
|
|
||||||
|
.edit-page-info-inner {
|
||||||
|
padding: 1rem;
|
||||||
|
background: var(--interactive-editor-background);
|
||||||
|
color: var(--interactive-editor-color);
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
@extend .scroll-bar;
|
||||||
|
h3 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
.page-info-form {
|
||||||
|
@extend .schema-form;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -15,6 +15,7 @@ const {
|
|||||||
SET_LANGUAGE,
|
SET_LANGUAGE,
|
||||||
UPDATE_ITEM,
|
UPDATE_ITEM,
|
||||||
SET_EDIT_MODE,
|
SET_EDIT_MODE,
|
||||||
|
UPDATE_PAGE_INFO,
|
||||||
} = Keys;
|
} = Keys;
|
||||||
|
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
@ -77,6 +78,11 @@ const store = new Vuex.Store({
|
|||||||
});
|
});
|
||||||
state.config = newConfig;
|
state.config = newConfig;
|
||||||
},
|
},
|
||||||
|
[UPDATE_PAGE_INFO](state, newPageInfo) {
|
||||||
|
const newConfig = state.config;
|
||||||
|
newConfig.pageInfo = newPageInfo;
|
||||||
|
state.config = newConfig;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
/* Called when app first loaded. Reads config and sets state */
|
/* Called when app first loaded. Reads config and sets state */
|
||||||
|
@ -637,7 +637,7 @@ html[data-theme='material-dark'] {
|
|||||||
|
|
||||||
--config-settings-background: #131a1f;
|
--config-settings-background: #131a1f;
|
||||||
--config-settings-color: #41e2ed;
|
--config-settings-color: #41e2ed;
|
||||||
--interactive-editor-background: #131a1f;
|
--interactive-editor-background: #242a2f;
|
||||||
--interactive-editor-background-darker: #131a1f;
|
--interactive-editor-background-darker: #131a1f;
|
||||||
--interactive-editor-color: #41e2ed;
|
--interactive-editor-color: #41e2ed;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
@import '@/styles/media-queries.scss';
|
||||||
|
|
||||||
/* Fancy scrollbar */
|
/* Fancy scrollbar */
|
||||||
.scroll-bar {
|
.scroll-bar {
|
||||||
@ -58,6 +59,52 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Form elements in the auto-schema form */
|
||||||
|
.schema-form {
|
||||||
|
fieldset {
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
> div {
|
||||||
|
border-bottom: 1px dashed var(--primary);
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
label {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div[data-fs-wrapper] {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
@include tablet-down {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-style: italic;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
min-width: 15rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
margin: 0.5rem auto;
|
||||||
|
font-size: 1rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--primary);
|
||||||
|
background: var(--background);;
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 1px 1px 6px var(--config-settings-color);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Single-style helpers */
|
/* Single-style helpers */
|
||||||
.bold { font-weight: bold; }
|
.bold { font-weight: bold; }
|
||||||
|
@ -9,16 +9,19 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"title": {
|
"title": {
|
||||||
|
"title": "Title",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Title and heading for the app"
|
"description": "Title and heading for the app"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
|
"title": "Description",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Sub-title, displayed in header"
|
"description": "Sub-title, displayed in header"
|
||||||
},
|
},
|
||||||
"navLinks": {
|
"navLinks": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"maxItems": 6,
|
"maxItems": 6,
|
||||||
|
"title": "Navigation Links",
|
||||||
"description": "Quick access links, displayed in header",
|
"description": "Quick access links, displayed in header",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -38,9 +41,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"footerText": {
|
"footerText": {
|
||||||
|
"title": "Footer Text",
|
||||||
|
"description": "Content to display within the global page footer",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"logo": {
|
"logo": {
|
||||||
|
"title": "App Logo",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path to an optional image asset, to be displayed in the header",
|
"description": "Path to an optional image asset, to be displayed in the header",
|
||||||
"pattern": "^(http|/)",
|
"pattern": "^(http|/)",
|
||||||
|
@ -4,8 +4,9 @@ const KEY_NAMES = [
|
|||||||
'UPDATE_CONFIG',
|
'UPDATE_CONFIG',
|
||||||
'SET_MODAL_OPEN',
|
'SET_MODAL_OPEN',
|
||||||
'SET_LANGUAGE',
|
'SET_LANGUAGE',
|
||||||
'UPDATE_ITEM',
|
|
||||||
'SET_EDIT_MODE',
|
'SET_EDIT_MODE',
|
||||||
|
'UPDATE_ITEM',
|
||||||
|
'UPDATE_PAGE_INFO',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Convert array of key names into an object, and export
|
// Convert array of key names into an object, and export
|
||||||
|
@ -123,6 +123,10 @@ module.exports = {
|
|||||||
ABOUT_APP: 'ABOUT_APP',
|
ABOUT_APP: 'ABOUT_APP',
|
||||||
LANG_SWITCHER: 'LANG_SWITCHER',
|
LANG_SWITCHER: 'LANG_SWITCHER',
|
||||||
EDIT_ITEM: 'EDIT_ITEM',
|
EDIT_ITEM: 'EDIT_ITEM',
|
||||||
|
EDIT_SECTION: 'EDIT_SECTION',
|
||||||
|
EDIT_PAGE_INFO: 'EDIT_PAGE_INFO',
|
||||||
|
EDIT_APP_CONFIG: 'EDIT_APP_CONFIG',
|
||||||
|
EXPORT_CONFIG_MENU: 'EXPORT_CONFIG_MENU',
|
||||||
},
|
},
|
||||||
/* Key names for the top-level objects in conf.yml */
|
/* Key names for the top-level objects in conf.yml */
|
||||||
topLevelConfKeys: {
|
topLevelConfKeys: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user