Implemented a workspace feature

This commit is contained in:
Alicia Sykes 2021-06-17 22:59:56 +01:00
parent f5ecdb4459
commit 3a22283f3c
8 changed files with 171 additions and 21 deletions

View File

@ -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';

View File

@ -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;

View File

@ -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');

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -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>