Displays a tab view in the config modal, with raw YAML for downloading

This commit is contained in:
Alicia Sykes 2021-05-16 18:29:30 +01:00
parent 52bf47d91e
commit 0e9aef3f30
10 changed files with 49 additions and 11 deletions

View File

@ -162,12 +162,13 @@ There are a few self-hosted web apps, that serve a similar purpose to Dashy. Inc
### Credits 🏆 ### Credits 🏆
The app makes use of the following components, kudos to their respective authors And the app itself is built with [Vue.js](https://github.com/vuejs/vue) ![vue-logo](https://i.ibb.co/xqKW6h5/vue-logo.png)
It makes use of the following components, kudos to their respective authors
- [`vue-select`](https://github.com/sagalbot/vue-select) - Dropdown component by @sagalbot - [`vue-select`](https://github.com/sagalbot/vue-select) - Dropdown component by @sagalbot
- [`vue-js-modal`](https://github.com/euvl/vue-js-modal) - Modal component by @euvl - [`vue-js-modal`](https://github.com/euvl/vue-js-modal) - Modal component by @euvl
- [`v-tooltip`](https://github.com/Akryum/v-tooltip) - Tooltip component by @Akryum - [`v-tooltip`](https://github.com/Akryum/v-tooltip) - Tooltip component by @Akryum
- [`vue-material-tabs`](https://github.com/jairoblatt/vue-material-tabs) - Tab view component by @jairoblatt
And the app itself is built with [Vue.js](https://github.com/vuejs/vue) ![vue-logo](https://i.ibb.co/xqKW6h5/vue-logo.png)
### License 📜 ### License 📜

View File

@ -10,11 +10,13 @@
"dependencies": { "dependencies": {
"connect": "^3.7.0", "connect": "^3.7.0",
"register-service-worker": "^1.6.2", "register-service-worker": "^1.6.2",
"remedial": "^1.0.8",
"serve-static": "^1.14.1", "serve-static": "^1.14.1",
"v-tooltip": "^2.1.3", "v-tooltip": "^2.1.3",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-cli-plugin-yaml": "^1.0.2", "vue-cli-plugin-yaml": "^1.0.2",
"vue-js-modal": "^2.0.0-rc.6", "vue-js-modal": "^2.0.0-rc.6",
"vue-material-tabs": "^0.0.7",
"vue-router": "^3.0.3", "vue-router": "^3.0.3",
"vue-select": "^3.11.2" "vue-select": "^3.11.2"
}, },
@ -61,4 +63,4 @@
"> 1%", "> 1%",
"last 2 versions" "last 2 versions"
] ]
} }

View File

@ -100,7 +100,6 @@ export default {
.item { .item {
flex-grow: 1; flex-grow: 1;
position: relative;
color: var(--item-text-color); color: var(--item-text-color);
vertical-align: middle; vertical-align: middle;
margin: 0.5rem; margin: 0.5rem;
@ -116,6 +115,7 @@ export default {
&:hover { &:hover {
box-shadow: var(--item-hover-shadow); box-shadow: var(--item-hover-shadow);
background: var(--item-background-hover); background: var(--item-background-hover);
position: relative;
} }
&:focus { &:focus {
outline: 2px solid var(--primary); outline: 2px solid var(--primary);

View File

@ -99,7 +99,7 @@ export default {
<style lang="scss"> <style lang="scss">
.tile-icon { .tile-icon {
width: 60px; width: 60px;
filter: var(--item-icon-transform); // filter: var(--item-icon-transform);
&.broken { display: none; } &.broken { display: none; }
} }
i.fas, i.fab, i.far, i.fal, i.fad { i.fas, i.fab, i.far, i.fal, i.fad {

View File

@ -5,7 +5,16 @@
<IconSpanner v-tooltip="tooltip('Update configuration locally')" @click="showEditor()" /> <IconSpanner v-tooltip="tooltip('Update configuration locally')" @click="showEditor()" />
</div> </div>
<modal :name="modalName" :resizable="true" width="80%" height="80%"> <modal :name="modalName" :resizable="true" width="80%" height="80%">
<p>Hello</p> <Tabs>
<TabItem name="Edit">
<div class="first-tab">Todo</div>
</TabItem>
<TabItem name="Download">
<div class="second-tab">
<pre>{{this.jsonParser(this.sections)}}</pre>
</div>
</TabItem>
</Tabs>
</modal> </modal>
</div> </div>
</template> </template>
@ -13,6 +22,7 @@
<script> <script>
import IconSpanner from '@/assets/interface-icons/config-editor.svg'; import IconSpanner from '@/assets/interface-icons/config-editor.svg';
import JsonToYaml from '@/utils/JsonToYaml';
export default { export default {
name: 'ConfigEditor', name: 'ConfigEditor',
@ -20,13 +30,14 @@ export default {
return { return {
modalName: 'CONF-EDITOR', modalName: 'CONF-EDITOR',
input: '', input: '',
jsonParser: JsonToYaml,
}; };
}, },
components: { components: {
IconSpanner, IconSpanner,
}, },
props: { props: {
initialConfig: Object, sections: Array,
}, },
methods: { methods: {
showEditor: function show() { showEditor: function show() {

View File

@ -6,7 +6,7 @@
:confTheme="getInitialTheme()" :userThemes="getUserThemes()" /> :confTheme="getInitialTheme()" :userThemes="getUserThemes()" />
<LayoutSelector :displayLayout="displayLayout" @layoutUpdated="updateDisplayLayout"/> <LayoutSelector :displayLayout="displayLayout" @layoutUpdated="updateDisplayLayout"/>
<ItemSizeSelector :iconSize="iconSize" @iconSizeUpdated="updateIconSize" /> <ItemSizeSelector :iconSize="iconSize" @iconSizeUpdated="updateIconSize" />
<ConfigEditor /> <ConfigEditor :sections="sections" />
</div> </div>
<KeyboardShortcutInfo /> <KeyboardShortcutInfo />
</section> </section>
@ -28,6 +28,7 @@ export default {
iconSize: String, iconSize: String,
availableThemes: Object, availableThemes: Object,
appConfig: Object, appConfig: Object,
sections: Array,
}, },
components: { components: {
SearchBar, SearchBar,

View File

@ -3,6 +3,7 @@ import Vue from 'vue';
import VTooltip from 'v-tooltip'; // A Vue directive for Popper.js, tooltip component import VTooltip from 'v-tooltip'; // A Vue directive for Popper.js, tooltip component
import VModal from 'vue-js-modal'; // Modal component import VModal from 'vue-js-modal'; // Modal component
import VSelect from 'vue-select'; // Select dropdown component import VSelect from 'vue-select'; // Select dropdown component
import VTabs from 'vue-material-tabs'; // Tab view component, used on the config page
import App from './App.vue'; import App from './App.vue';
import router from './router'; import router from './router';
@ -10,6 +11,7 @@ import './registerServiceWorker';
Vue.use(VTooltip); Vue.use(VTooltip);
Vue.use(VModal); Vue.use(VModal);
Vue.use(VTabs);
Vue.component('v-select', VSelect); Vue.component('v-select', VSelect);
Vue.config.productionTip = false; Vue.config.productionTip = false;

View File

@ -44,5 +44,6 @@ module.exports = {
COLLAPSE_STATE: 'collapseState', COLLAPSE_STATE: 'collapseState',
ICON_SIZE: 'iconSize', ICON_SIZE: 'iconSize',
THEME: 'theme', THEME: 'theme',
CONF_SECTIONS: 'confSections',
}, },
}; };

View File

@ -9,13 +9,14 @@
:iconSize="itemSizeBound" :iconSize="itemSizeBound"
:availableThemes="getExternalCSSLinks()" :availableThemes="getExternalCSSLinks()"
:appConfig="appConfig" :appConfig="appConfig"
:sections="getSections(sections)"
class="filter-container" class="filter-container"
/> />
<!-- Main content, section for each group of items --> <!-- Main content, section for each group of items -->
<div v-if="checkTheresData(sections)" <div v-if="checkTheresData(sections)"
:class="`item-group-container orientation-${layout} item-size-${itemSizeBound}`"> :class="`item-group-container orientation-${layout} item-size-${itemSizeBound}`">
<ItemGroup <ItemGroup
v-for="(section, index) in sections" v-for="(section, index) in getSections(sections)"
:key="index" :key="index"
:title="section.name" :title="section.name"
:displayData="getDisplayData(section)" :displayData="getDisplayData(section)"
@ -73,7 +74,16 @@ export default {
methods: { methods: {
/* Returns true if there is one or more sections in the config */ /* Returns true if there is one or more sections in the config */
checkTheresData(sections) { checkTheresData(sections) {
return sections && sections.length >= 1; const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
return (sections && sections.length >= 1) || (localSections && localSections.length >= 1);
},
/* Returns sections from local storage if available, otherwise uses the conf.yml */
getSections(sections) {
// If the user has stored sections in local storage, return those
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
if (localSections && localSections.length >= 1) return localSections;
// Otherwise, return the usuall data from conf.yml
return sections;
}, },
/* Updates local data with search value, triggered from filter comp */ /* Updates local data with search value, triggered from filter comp */
searching(searchValue) { searching(searchValue) {

View File

@ -7314,6 +7314,11 @@ relateurl@0.2.x:
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
remedial@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0"
integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==
remove-trailing-separator@^1.0.1: remove-trailing-separator@^1.0.1:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@ -8756,6 +8761,11 @@ vue-loader@^15.9.2:
vue-hot-reload-api "^2.3.0" vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0" vue-style-loader "^4.1.0"
vue-material-tabs@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/vue-material-tabs/-/vue-material-tabs-0.0.7.tgz#5f3fa04ad35384af68582f7c89ad4cecac89207b"
integrity sha512-02X5paTksYKrGvSRpMdkctRO9qhvJFD5VEGxd0xjOX4sYz6mZSAez0Z/+aYf7Z5ziY+eJ9dMQmxaLn9DVKQRJw==
vue-resize@^1.0.1: vue-resize@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-1.0.1.tgz#c120bed4e09938771d622614f57dbcf58a5147ee" resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-1.0.1.tgz#c120bed4e09938771d622614f57dbcf58a5147ee"