Skip to content

Commit

Permalink
Merge pull request #8 from Lissy93/bug-fixes-and-improvments
Browse files Browse the repository at this point in the history
Implements custom CSS editor, customizable item grids, other new features and bug fixes
  • Loading branch information
Lissy93 authored May 31, 2021
2 parents fcb2602 + 0f1227f commit 484a625
Show file tree
Hide file tree
Showing 23 changed files with 375 additions and 55 deletions.
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<img width="800" src="https://i.ibb.co/L8YbNNc/dashy-demo2.gif" alt="Demo">
</p>

![More themes and screens](https://i.ibb.co/M6nyvqW/dashy-options-screen.png)

---

## Running the App 🏃‍♂️
Expand Down Expand Up @@ -96,6 +98,7 @@ All fields are optional, unless otherwise stated.
- `theme`- String: The default theme for first load (you can change this later from the UI)
- `cssThemes` - String[]: An array of custom theme names which can be used in the theme switcher dropdown - _See **theming** below_
- `externalStyleSheet` - String or String[] - Either a URL to an external stylesheet or an array or URLs, which can be applied as themes within the UI
- `customCss` - String: Raw CSS that will be applied to the page. Please minify it first.

**`sections`** - Section[]: (required) An array of sections - _See **`section`** below_

Expand All @@ -104,11 +107,16 @@ All fields are optional, unless otherwise stated.
- `items` - Item[]: (required) An array of items - _See **`item`** below_
- `displayData`: An object with the following fields (all optional)
- `collapsed` - Boolean: If true, the section will be collapsed initially (defaults to `false`)
- `rows` - Int: Number of rows the section should span vertically, e.g. 2 (defaults to `1`)
- `cols` - Int: Number of columns the section should span horizontally, e.g. 2 (defaults to `1`)
- `color` - String: A custom accent color for the section, as a hex code or HTML color (e.g. `#fff`)
- `customStyles` - String: Custom CSS properties that should be applied to that section, e.g. `border: 2px dashed #ff0000;`
- `itemSize` - String: Specify the size for items within this group, either `small`, `medium` or `large`
- `rows` - Int: Number of rows the section should span vertically, e.g. 2 (defaults to `1`)
- `cols` - Int: Number of columns the section should span horizontally, e.g. 2 (defaults to `1`)
- `layout` - Enum: `auto` or `grid`. If `grid` is selected, then the number of items per row can be set
- `itemCountX` - Int: Number of items horizontally (for `layout: grid`)
- `itemCountY` - Int: Number of items vertically (for `layout: grid`)

Note about `rows` and `cols`: These are defined as a proportion of the screen (rather than by number of child items), and is built using [`grid-layout`](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout). For more info, see [this example](https://i.ibb.co/HXRWVRK/how-rows-and-cols-work-in-dashy.png). In order to set the number of items that will display horizontally or vertically within a section, first set `display: grid`, and then specify values for `itemCountX`, and optionally `itemCountY`.

**`item`**
- `title` - String: The text to display on the item
Expand Down Expand Up @@ -174,8 +182,9 @@ This wouldn't have been quite so possible without the following components, kudo
- [`vue-material-tabs`](https://github.com/jairoblatt/vue-material-tabs) - Tab view component by @jairoblatt `MIT`
- [`VJsoneditor`](https://github.com/yansenlei/VJsoneditor) - Interactive JSON editor component by @yansenlei `MIT`
- Forked from [`JsonEditor`](https://github.com/josdejong/jsoneditor) by @josdejong `Apache-2.0 License`
- And using [`ajv`](https://github.com/ajv-validator/ajv) `MIT` JSON schema Validator [`ace`](https://github.com/ajaxorg/ace) `BSD` code editor
- [`vue-toasted`](https://github.com/shakee93/vue-toasted) - Toast notification component by @shakee93 `MIT`
- [`vue-prism-editor`](https://github.com/koca/vue-prism-editor) - Lightweight code editor by @koca `MIT`
- Forked from [`prism.js`](https://github.com/PrismJS/prism) `MIT`

Utils:
- [`crypto-js`](https://github.com/brix/crypto-js) - Encryption implementations by @evanvosberg and community `MIT`
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"axios": "^0.21.1",
"connect": "^3.7.0",
"crypto-js": "^4.0.0",
"highlight.js": "^11.0.0",
"prismjs": "^1.23.0",
"register-service-worker": "^1.6.2",
"remedial": "^1.0.8",
"serve-static": "^1.14.1",
Expand All @@ -20,6 +22,7 @@
"vue-cli-plugin-yaml": "^1.0.2",
"vue-js-modal": "^2.0.0-rc.6",
"vue-material-tabs": "^0.0.7",
"vue-prism-editor": "^1.2.2",
"vue-router": "^3.0.3",
"vue-select": "^3.11.2",
"vue-toasted": "^1.1.28"
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,6 @@
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#000000",
"background_color": "#0b1021",
"theme_color": "#4DBA87"
}
25 changes: 23 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,21 @@ export default {
},
data: () => ({
// pageInfo: this.getPageInfo(conf.pageInfo),
appConfig: conf.appConfig || Defaults.appConfig,
showFooter: Defaults.visibleComponents.footer,
}),
computed: {
pageInfo: function pi() { return this.getPageInfo(conf.pageInfo); },
pageInfo() {
return this.getPageInfo(conf.pageInfo);
},
appConfig() {
if (localStorage[localStorageKeys.APP_CONFIG]) {
return JSON.parse(localStorage[localStorageKeys.APP_CONFIG]);
} else if (conf.appConfig) {
return conf.appConfig;
} else {
return Defaults.appConfig;
}
},
},
methods: {
/* Returns either page info from the config, or default values */
Expand Down Expand Up @@ -53,6 +63,17 @@ export default {
}
return '';
},
injectCustomStyles(usersCss) {
const style = document.createElement('style');
style.textContent = usersCss;
document.head.append(style);
},
},
mounted() {
if (this.appConfig.customCss) {
const cleanedCss = this.appConfig.customCss.replace(/<\/?[^>]+(>|$)/g, '');
this.injectCustomStyles(cleanedCss);
}
},
};
</script>
Expand Down
1 change: 1 addition & 0 deletions src/assets/interface-icons/config-custom-css.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/Configuration/CloudBackupRestore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="section intro">
<h2>Cloud Backup & Restore</h2>
<p class="intro">
Cloud backup and restore is an optional feature, that enabled you to upload your
Cloud backup and restore is an optional feature, that enables you to upload your
config to the internet, and then restore it on any other device or instance of Dashy.
<br><br>
All data is fully end-to-end encrypted with AES, using your password as the key.
Expand Down
79 changes: 78 additions & 1 deletion src/components/Configuration/ConfigContainer.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<Tabs :navAuto="true" name="Add Item" ref="tabView">
<TabItem name="Config">
<TabItem name="Config" class="main-tab">
<div class="main-options-container">
<h2>Configuration Options</h2>
<a href="/conf.yml" download class="hyperlink-wrapper">
Expand All @@ -17,10 +17,25 @@
<MetaDataIcon class="button-icon"/>
Edit Meta Data
</button>
<button class="config-button center" @click="goToCustomCss()">
<CustomCssIcon class="button-icon"/>
Edit Custom CSS
</button>
<button class="config-button center" @click="openCloudSync()">
<CloudIcon class="button-icon"/>
{{backupId ? 'Edit Cloud Sync' : 'Enable Cloud Sync'}}
</button>
<button class="config-button center" @click="resetLocalSettings()">
<DeleteIcon class="button-icon"/>
Reset Local Settings
</button>
<div class="config-note">
<p class="sub-title">Note:</p>
<span>
All changes made here are stored locally. To apply globally, either export your config
into your conf.yml file, or use the cloud backup/ restore feature.
</span>
</div>
</div>
</TabItem>
<TabItem name="Backup Config" class="code-container">
Expand All @@ -38,24 +53,36 @@
<TabItem name="Edit Site Meta">
<EditSiteMeta :config="config" />
</TabItem>
<TabItem name="Custom Styles">
<CustomCssEditor :config="config" initialCss="hello" />
</TabItem>
</Tabs>
</template>

<script>
import hljs from 'highlight.js/lib/core';
import yaml from 'highlight.js/lib/languages/yaml';
import 'highlight.js/styles/mono-blue.css';
import JsonToYaml from '@/utils/JsonToYaml';
import { localStorageKeys, modalNames } from '@/utils/defaults';
import EditSiteMeta from '@/components/Configuration/EditSiteMeta';
import JsonEditor from '@/components/Configuration/JsonEditor';
import CustomCssEditor from '@/components/Configuration/CustomCss';
import DownloadIcon from '@/assets/interface-icons/config-download-file.svg';
import DeleteIcon from '@/assets/interface-icons/config-delete-local.svg';
import EditIcon from '@/assets/interface-icons/config-edit-json.svg';
import MetaDataIcon from '@/assets/interface-icons/config-meta-data.svg';
import CustomCssIcon from '@/assets/interface-icons/config-custom-css.svg';
import CloudIcon from '@/assets/interface-icons/cloud-backup-restore.svg';
export default {
name: 'ConfigContainer',
data() {
return {
jsonParser: JsonToYaml,
backupId: localStorage[localStorageKeys.BACKUP_ID] || '',
};
},
props: {
Expand All @@ -69,10 +96,13 @@ export default {
components: {
EditSiteMeta,
JsonEditor,
CustomCssEditor,
DownloadIcon,
DeleteIcon,
EditIcon,
CloudIcon,
MetaDataIcon,
CustomCssIcon,
},
methods: {
/* Seletcs the edit tab of the tab view */
Expand All @@ -84,6 +114,13 @@ export default {
const itemToSelect = this.$refs.tabView.navItems[3];
this.$refs.tabView.activeTabItem({ tabItem: itemToSelect, byUser: true });
},
goToCustomCss() {
const itemToSelect = this.$refs.tabView.navItems[4];
this.$refs.tabView.activeTabItem({ tabItem: itemToSelect, byUser: true });
},
openCloudSync() {
this.$modal.show(modalNames.CLOUD_BACKUP);
},
copyConfigToClipboard() {
navigator.clipboard.writeText(this.jsonParser(this.config));
// event.target.textContent = 'Copied to clipboard';
Expand All @@ -104,13 +141,20 @@ export default {
}
},
},
mounted() {
hljs.registerLanguage('yaml', yaml);
const highlighted = hljs.highlight(this.jsonParser(this.config), { language: 'yaml' }).value;
document.getElementById('conf-yaml').innerHTML = highlighted;
},
};
</script>

<style scoped lang="scss">
@import '@/styles/style-helpers.scss';
pre {
color: var(--config-code-color);
font-weight: bold !important;
padding: 0.5rem 1rem;
}
Expand Down Expand Up @@ -148,6 +192,12 @@ a.config-button, button.config-button {
div.code-container {
background: var(--config-code-background);
#conf-yaml {
font-family: 'Inconsolata', sans-serif;
.hljs-attr {
font-weight: bold !important;
}
}
.yaml-action-buttons {
position: absolute;
top: 0.5rem;
Expand Down Expand Up @@ -186,7 +236,11 @@ div.code-container {
.tab-item {
overflow-y: auto;
@extend .scroll-bar;
background: var(--config-settings-background);
&.main-tab {
min-height: 500px;
}
}
a.hyperlink-wrapper {
Expand All @@ -205,6 +259,25 @@ a.hyperlink-wrapper {
color: var(--config-settings-color);
}
}
.config-note {
width: 80%;
position: absolute;
bottom: 1rem;
left: 10%;
margin: 0.5rem auto;
padding: 0.5rem 0.75rem;
border: 1px dashed var(--config-settings-color);
border-radius: var(--curve-factor);
text-align: left;
opacity: var(--dimming-factor);
background: var(--config-settings-background);
p.sub-title {
font-weight: bold;
margin: 0;
display: inline;
}
}
</style>

<style lang="scss">
Expand Down Expand Up @@ -235,4 +308,8 @@ a.hyperlink-wrapper {
background: var(--config-settings-color);
}
}
#conf-yaml .hljs-attr {
color: #9c03f5;
}
</style>
88 changes: 88 additions & 0 deletions src/components/Configuration/CustomCss.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<div class="json-editor-outer">
<prism-editor class="my-editor" v-model="customCss" :highlight="highlighter" line-numbers />
<button class="save-button" @click="save()">Save Changes</button>
<p>Note, you will need to refresh the page for your changes to take effect</p>
</div>
</template>

<script>
import { PrismEditor } from 'vue-prism-editor';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-css';
import 'prismjs/themes/prism-funky.css';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { localStorageKeys } from '@/utils/defaults';
export default {
name: 'JsonEditor',
props: {
config: Object,
},
components: {
PrismEditor,
},
data() {
return {
customCss: this.config.appConfig.customCss || '\n\n\n\n\n',
};
},
methods: {
validate(css) {
return css.match(/((?:^\s*)([\w#.@*,:\-.:>,*\s]+)\s*{(?:[\s]*)((?:[A-Za-z\- \s]+[:]\s*['"0-9\w .,/()\-!%]+;?)*)*\s*}(?:\s*))/gmi);
},
save() {
let msg = '';
if (this.validate(this.customCss)) {
const appConfig = { ...this.config.appConfig };
appConfig.customCss = this.customCss;
localStorage.setItem(localStorageKeys.APP_CONFIG, JSON.stringify(appConfig));
msg = 'Changes saved succesfully';
this.inject(this.customCss);
} else {
msg = 'Error - Invalid CSS';
}
this.$toasted.show(msg);
},
inject(userStyles) {
const cleanedCss = userStyles.replace(/<\/?[^>]+(>|$)/g, '');
const style = document.createElement('style');
style.textContent = cleanedCss;
document.head.append(style);
},
highlighter(code) {
return highlight(code, languages.css);
},
},
};
</script>

<style lang="scss">
button.save-button {
padding: 0.5rem 1rem;
margin: 0.25rem auto;
font-size: 1.2rem;
background: var(--config-settings-color);
color: var(--config-settings-background);
border: 1px solid var(--config-settings-background);
border-radius: var(--curve-factor);
cursor: pointer;
&:hover {
background: var(--config-settings-background);
color: var(--config-settings-color);
border-color: var(--config-settings-color);
}
}
.prism-editor-wrapper {
min-height: 200px;
border: 1px solid var(--transparent-70);
border-radius: var(--curve-factor);
width: 90%;
margin: 0.5rem auto;
background: var(--transparent-50);
}
</style>
Loading

0 comments on commit 484a625

Please sign in to comment.