mirror of https://github.com/Lissy93/dashy.git
Implemented a workspace feature
This commit is contained in:
parent
f5ecdb4459
commit
3a22283f3c
|
@ -68,6 +68,7 @@ export default {
|
|||
<style lang="scss">
|
||||
@import '@/styles/global-styles.scss';
|
||||
@import '@/styles/color-palette.scss';
|
||||
@import '@/styles/dimensions.scss';
|
||||
@import '@/styles/color-themes.scss';
|
||||
@import '@/styles/typography.scss';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="item-icon">
|
||||
<i v-if="iconType === 'font-awesome'" :class="`${icon} ${size}`" ></i>
|
||||
<img v-else-if="icon" :src="iconPath" @error="imageNotFound"
|
||||
:class="`tile-icon ${size} ${broken ? 'broken' : ''}`"
|
||||
|
@ -98,9 +98,16 @@ export default {
|
|||
|
||||
<style lang="scss">
|
||||
.tile-icon {
|
||||
width: 60px;
|
||||
width: 2rem;
|
||||
// filter: var(--item-icon-transform);
|
||||
border-radius: var(--curve-factor);
|
||||
&.broken { display: none; }
|
||||
&.small {
|
||||
width: 1.5rem;
|
||||
}
|
||||
&.large {
|
||||
width: 3rem;
|
||||
}
|
||||
}
|
||||
i.fas, i.fab, i.far, i.fal, i.fad {
|
||||
font-size: 2rem;
|
||||
|
|
|
@ -54,6 +54,7 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
/* Sets the theme, by updating data-theme attribute on the html tag */
|
||||
setLocalTheme(newTheme) {
|
||||
const htmlTag = document.getElementsByTagName('html')[0];
|
||||
if (htmlTag.hasAttribute('data-theme')) htmlTag.removeAttribute('data-theme');
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
<template>
|
||||
<nav class="side-bar">
|
||||
<div v-for="(section, index) in sections" :key="index">
|
||||
<SideBarItem class="item" :icon="section.icon" :title="section.title" />
|
||||
<div @click="openSection(index)" class="side-bar-item-container">
|
||||
<SideBarItem
|
||||
class="item"
|
||||
:icon="section.icon"
|
||||
:title="section.name"
|
||||
/>
|
||||
</div>
|
||||
<transition name="slide">
|
||||
<SideBarSection
|
||||
v-if="isOpen[index]"
|
||||
:items="section.items"
|
||||
@launch-app="launchApp"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
@ -9,6 +22,7 @@
|
|||
<script>
|
||||
|
||||
import SideBarItem from '@/components/Workspace/SideBarItem.vue';
|
||||
import SideBarSection from '@/components/Workspace/SideBarSection.vue';
|
||||
|
||||
export default {
|
||||
name: 'SideBar',
|
||||
|
@ -16,13 +30,29 @@ export default {
|
|||
props: {
|
||||
sections: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isOpen: new Array(this.sections.length).fill(false),
|
||||
};
|
||||
},
|
||||
components: {
|
||||
SideBarItem,
|
||||
SideBarSection,
|
||||
},
|
||||
methods: {
|
||||
/* Toggles the section clicked, and closes all other sections */
|
||||
openSection(index) {
|
||||
this.isOpen = this.isOpen.map((val, ind) => (ind !== index ? false : !val));
|
||||
},
|
||||
launchApp(url) {
|
||||
this.$emit('launch-app', url);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@import '@/styles/media-queries.scss';
|
||||
@import '@/styles/style-helpers.scss';
|
||||
|
||||
|
@ -33,11 +63,28 @@ nav.side-bar {
|
|||
background: var(--side-bar-background);
|
||||
color: var(--side-bar-color);
|
||||
height: 100%;
|
||||
width: 3rem;
|
||||
width: var(--side-bar-width);
|
||||
text-align: center;
|
||||
overflow: auto;
|
||||
@extend .scroll-bar;
|
||||
.side-bar-item-container {
|
||||
z-index: 5;
|
||||
}
|
||||
.item:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--side-bar-color);
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-leave-active,
|
||||
.slide-enter-active {
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
.slide-enter {
|
||||
transform: translate(0, -80%);
|
||||
}
|
||||
.slide-leave-to {
|
||||
transform: translate(0, -80%);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="side-bar-item">
|
||||
<Icon v-if="icon" :icon="icon" size="small" />
|
||||
<p v-else>{{ title }}</p>
|
||||
<div @click="itemClicked()"
|
||||
:class="`side-bar-item ${icon ? 'w-icon' : 'text-only'}`" v-tooltip="tooltip">
|
||||
<Icon v-if="icon" :icon="icon" size="small" :url="url" />
|
||||
<p class="small-title" v-else>{{ title }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Icon from '@/components/LinkItems/ItemIcon.vue';
|
||||
import Defaults from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
name: 'SideBarItem',
|
||||
|
@ -16,21 +16,30 @@ export default {
|
|||
props: {
|
||||
icon: String,
|
||||
title: String,
|
||||
},
|
||||
mounted() {
|
||||
this.initiateFontAwesome();
|
||||
url: String,
|
||||
click: Function,
|
||||
},
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
methods: {
|
||||
initiateFontAwesome() {
|
||||
const fontAwesomeScript = document.createElement('script');
|
||||
const faKey = this.config.appConfig.fontAwesomeKey || Defaults.fontAwesomeKey;
|
||||
fontAwesomeScript.setAttribute('src', `https://kit.fontawesome.com/${faKey}.js`);
|
||||
document.head.appendChild(fontAwesomeScript);
|
||||
itemClicked() {
|
||||
if (this.url) this.$emit('launch-app', this.url);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tooltip: {
|
||||
disabled: !this.title,
|
||||
content: this.title,
|
||||
trigger: 'hover focus',
|
||||
hideOnTargetClick: true,
|
||||
html: false,
|
||||
placement: 'right-start',
|
||||
delay: { show: 800, hide: 1000 },
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -42,6 +51,14 @@ div.side-bar-item {
|
|||
color: var(--side-bar-color);
|
||||
background: var(--side-bar-background);
|
||||
text-align: center;
|
||||
&.text-only {
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
p.small-title {
|
||||
margin: 0.1rem auto;
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="sub-side-bar">
|
||||
<div v-for="(item, index) in items" :key="index">
|
||||
<SideBarItem
|
||||
class="item"
|
||||
:icon="item.icon"
|
||||
:title="item.title"
|
||||
:url="item.url"
|
||||
@launch-app="launchApp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import SideBarItem from '@/components/Workspace/SideBarItem.vue';
|
||||
|
||||
export default {
|
||||
name: 'SideBarSection',
|
||||
inject: ['config'],
|
||||
props: {
|
||||
items: Array,
|
||||
},
|
||||
components: {
|
||||
SideBarItem,
|
||||
},
|
||||
methods: {
|
||||
launchApp(url) {
|
||||
this.$emit('launch-app', url);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/media-queries.scss';
|
||||
@import '@/styles/style-helpers.scss';
|
||||
|
||||
div.sub-side-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--side-bar-background-lighter);
|
||||
border-radius: var(--curve-factor);
|
||||
margin: 0.2rem;
|
||||
color: var(--side-bar-color);
|
||||
text-align: center;
|
||||
z-index: 3;
|
||||
.item:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--side-bar-color);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -20,9 +20,9 @@ export default {
|
|||
|
||||
iframe {
|
||||
position: absolute;
|
||||
left: 3rem;
|
||||
height: calc(100% - 6.3rem);
|
||||
width: calc(100% - 3rem);
|
||||
left: var(--side-bar-width);
|
||||
height: calc(100% - var(--header-height));
|
||||
width: calc(100% - var(--side-bar-width));
|
||||
border: none;
|
||||
background: white;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="work-space">
|
||||
<SideBar :sections="sections" />
|
||||
<SideBar :sections="sections" @launch-app="launchApp" />
|
||||
<WebContent :url="url" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -9,11 +9,13 @@
|
|||
|
||||
import SideBar from '@/components/Workspace/SideBar';
|
||||
import WebContent from '@/components/Workspace/WebContent';
|
||||
import Defaults, { localStorageKeys } from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
name: 'Workspace',
|
||||
props: {
|
||||
sections: Array,
|
||||
appConfig: Object,
|
||||
},
|
||||
data: () => ({
|
||||
url: '',
|
||||
|
@ -22,6 +24,27 @@ export default {
|
|||
SideBar,
|
||||
WebContent,
|
||||
},
|
||||
methods: {
|
||||
launchApp(url) {
|
||||
this.url = url;
|
||||
},
|
||||
setTheme() {
|
||||
const theme = localStorage[localStorageKeys.THEME] || this.confTheme || Defaults.theme;
|
||||
const htmlTag = document.getElementsByTagName('html')[0];
|
||||
if (htmlTag.hasAttribute('data-theme')) htmlTag.removeAttribute('data-theme');
|
||||
htmlTag.setAttribute('data-theme', theme);
|
||||
},
|
||||
initiateFontAwesome() {
|
||||
const fontAwesomeScript = document.createElement('script');
|
||||
const faKey = this.appConfig.fontAwesomeKey || Defaults.fontAwesomeKey;
|
||||
fontAwesomeScript.setAttribute('src', `https://kit.fontawesome.com/${faKey}.js`);
|
||||
document.head.appendChild(fontAwesomeScript);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setTheme();
|
||||
this.initiateFontAwesome();
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue