🚧 A homepage mixin for sharing logic

This commit is contained in:
Alicia Sykes 2021-12-22 21:04:27 +00:00
parent c4134e033b
commit 5194ba2244
4 changed files with 133 additions and 168 deletions

123
src/mixins/HomeMixin.js Normal file
View File

@ -0,0 +1,123 @@
/**
* Mixin for all homepages (default home, minimal home, workspace, etc)
*/
// import ErrorHandler from '@/utils/ErrorHandler';
import Defaults, { localStorageKeys, iconCdns } from '@/utils/defaults';
import { searchTiles } from '@/utils/Search';
const HomeMixin = {
props: {},
computed: {
sections() {
return this.$store.getters.sections;
},
appConfig() {
return this.$store.getters.appConfig;
},
pageInfo() {
return this.$store.getters.pageInfo;
},
isEditMode() {
return this.$store.state.editMode;
},
modalOpen() {
return this.$store.state.modalOpen;
},
},
data: () => ({
searchValue: '',
}),
methods: {
updateModalVisibility(modalState) {
this.$store.commit('SET_MODAL_OPEN', modalState);
},
/* Updates local data with search value, triggered from filter comp */
searching(searchValue) {
this.searchValue = searchValue || '';
},
/* Returns true if there is one or more sections in the config */
checkTheresData(sections) {
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
return (sections && sections.length >= 1) || (localSections && localSections.length >= 1);
},
/* Returns only the tiles that match the users search query */
filterTiles(allTiles) {
if (!allTiles) return [];
return searchTiles(allTiles, this.searchValue);
},
/* Checks if any sections or items use icons from a given CDN */
checkIfIconLibraryNeeded(prefix) {
let isNeeded = false;
if (!this.sections) return false;
this.sections.forEach((section) => {
if (section) {
if (section.icon && section.icon.includes(prefix)) isNeeded = true;
if (section.items) {
section.items.forEach((item) => {
if (item.icon && item.icon.includes(prefix)) isNeeded = true;
});
}
}
});
return isNeeded;
},
/* Checks if any of the icons are Font Awesome glyphs */
checkIfFontAwesomeNeeded() {
let isNeeded = this.checkIfIconLibraryNeeded('fa-');
const currentTheme = localStorage[localStorageKeys.THEME]; // Some themes require FA
if (['material', 'material-dark'].includes(currentTheme)) isNeeded = true;
return isNeeded;
},
/* Injects font-awesome's script tag, only if needed */
initiateFontAwesome() {
if (this.appConfig.enableFontAwesome || this.checkIfFontAwesomeNeeded()) {
const fontAwesomeScript = document.createElement('script');
const faKey = this.appConfig.fontAwesomeKey || Defaults.fontAwesomeKey;
fontAwesomeScript.setAttribute('src', `${iconCdns.fa}/${faKey}.js`);
document.head.appendChild(fontAwesomeScript);
}
},
/* Checks if any of the icons are Material Design Icons */
checkIfMdiNeeded() {
return this.checkIfIconLibraryNeeded('mdi-');
},
/* Injects Material Design Icons, only if needed */
initiateMaterialDesignIcons() {
if (this.checkIfMdiNeeded()) {
const mdiStylesheet = document.createElement('link');
mdiStylesheet.setAttribute('rel', 'stylesheet');
mdiStylesheet.setAttribute('href', iconCdns.mdi);
document.head.appendChild(mdiStylesheet);
}
},
/* Returns true if there is more than 1 sub-result visible during searching */
checkIfResults() {
if (!this.sections) return false;
else {
let itemsFound = true;
this.sections.forEach((section) => {
if (section.widgets && section.widgets.length > 0) itemsFound = false;
if (this.filterTiles(section.items, this.searchValue).length > 0) itemsFound = false;
});
return itemsFound;
}
},
/* If user has a background image, then generate CSS attributes */
getBackgroundImage() {
if (this.appConfig && this.appConfig.backgroundImg) {
return `background: url('${this.appConfig.backgroundImg}');background-size:cover;`;
}
return '';
},
/* Extracts the site name from domain, used for the searching functionality */
getDomainFromUrl(url) {
if (!url) return '';
const urlPattern = /^(?:https?:\/\/)?(?:w{3}\.)?([a-z\d.-]+)\.(?:[a-z.]{2,10})(?:[/\w.-]*)*/;
const domainPattern = url.match(urlPattern);
return domainPattern ? domainPattern[1] : '';
},
},
};
export default HomeMixin;

View File

@ -60,20 +60,20 @@
</template>
<script>
import HomeMixin from '@/mixins/HomeMixin';
import SettingsContainer from '@/components/Settings/SettingsContainer.vue';
import Section from '@/components/LinkItems/Section.vue';
import EditModeSaveMenu from '@/components/InteractiveEditor/EditModeSaveMenu.vue';
import ExportConfigMenu from '@/components/InteractiveEditor/ExportConfigMenu.vue';
import AddNewSection from '@/components/InteractiveEditor/AddNewSectionLauncher.vue';
import { searchTiles } from '@/utils/Search';
import StoreKeys from '@/utils/StoreMutations';
import Defaults, { localStorageKeys, iconCdns, modalNames } from '@/utils/defaults';
import { localStorageKeys, modalNames } from '@/utils/defaults';
import ErrorHandler from '@/utils/ErrorHandler';
import BackIcon from '@/assets/interface-icons/back-arrow.svg';
export default {
name: 'home',
mixins: [HomeMixin],
components: {
SettingsContainer,
EditModeSaveMenu,
@ -83,33 +83,14 @@ export default {
BackIcon,
},
data: () => ({
searchValue: '',
layout: '',
itemSizeBound: '',
addNewSectionOpen: false,
}),
computed: {
sections() {
return this.$store.getters.sections;
},
appConfig() {
return this.$store.getters.appConfig;
},
pageInfo() {
return this.$store.getters.pageInfo;
},
widgets() {
return this.$store.getters.widgets;
},
modalOpen() {
return this.$store.state.modalOpen;
},
singleSectionView() {
return this.findSingleSection(this.$store.getters.sections, this.$route.params.section);
},
isEditMode() {
return this.$store.state.editMode;
},
/* Get class for num columns, if specified by user */
colCount() {
let { colCount } = this.appConfig;
@ -143,31 +124,14 @@ export default {
},
},
methods: {
/* Returns true if there is one or more sections in the config */
checkTheresData(sections) {
const localSections = localStorage[localStorageKeys.CONF_SECTIONS];
return (sections && sections.length >= 1) || (localSections && localSections.length >= 1);
},
/* Updates local data with search value, triggered from filter comp */
searching(searchValue) {
this.searchValue = searchValue || '';
},
/* Clears input field, once a searched item is opened */
finishedSearching() {
this.$refs.filterComp.clearFilterInput();
},
/* Returns only the tiles that match the users search query */
filterTiles(allTiles, searchTerm) {
return searchTiles(allTiles, searchTerm) || [];
},
/* Returns optional section display preferences if available */
getDisplayData(section) {
return !section.displayData ? {} : section.displayData;
},
/* Update data when modal is open (so that key bindings can be disabled) */
updateModalVisibility(modalState) {
this.$store.commit('SET_MODAL_OPEN', modalState);
},
openAddNewSectionMenu() {
this.addNewSectionOpen = true;
this.$modal.show(modalNames.EDIT_SECTION);
@ -209,68 +173,6 @@ export default {
availibleThemes.Default = '#';
return availibleThemes;
},
/* Checks if any sections or items use icons from a given CDN */
checkIfIconLibraryNeeded(prefix) {
let isNeeded = false;
if (!this.sections) return false;
this.sections.forEach((section) => {
if (section && section.items) {
if (section.icon && section.icon.includes(prefix)) isNeeded = true;
section.items.forEach((item) => {
if (item.icon && item.icon.includes(prefix)) isNeeded = true;
});
}
});
return isNeeded;
},
/* Checks if any of the icons are Font Awesome glyphs */
checkIfFontAwesomeNeeded() {
let isNeeded = this.checkIfIconLibraryNeeded('fa-');
const currentTheme = localStorage[localStorageKeys.THEME]; // Some themes require FA
if (['material', 'material-dark'].includes(currentTheme)) isNeeded = true;
return isNeeded;
},
/* Injects font-awesome's script tag, only if needed */
initiateFontAwesome() {
if (this.appConfig.enableFontAwesome || this.checkIfFontAwesomeNeeded()) {
const fontAwesomeScript = document.createElement('script');
const faKey = this.appConfig.fontAwesomeKey || Defaults.fontAwesomeKey;
fontAwesomeScript.setAttribute('src', `${iconCdns.fa}/${faKey}.js`);
document.head.appendChild(fontAwesomeScript);
}
},
/* Checks if any of the icons are Material Design Icons */
checkIfMdiNeeded() {
return this.checkIfIconLibraryNeeded('mdi-');
},
/* Injects Material Design Icons, only if needed */
initiateMaterialDesignIcons() {
if (this.checkIfMdiNeeded()) {
const mdiStylesheet = document.createElement('link');
mdiStylesheet.setAttribute('rel', 'stylesheet');
mdiStylesheet.setAttribute('href', iconCdns.mdi);
document.head.appendChild(mdiStylesheet);
}
},
/* Returns true if there is more than 1 sub-result visible during searching */
checkIfResults() {
if (!this.sections) return false;
else {
let itemsFound = true;
this.sections.forEach((section) => {
if (section.widgets && section.widgets.length > 0) itemsFound = false;
if (this.filterTiles(section.items, this.searchValue).length > 0) itemsFound = false;
});
return itemsFound;
}
},
/* If user has a background image, then generate CSS attributes */
getBackgroundImage() {
if (this.appConfig && this.appConfig.backgroundImg) {
return `background: url('${this.appConfig.backgroundImg}');background-size:cover;`;
}
return '';
},
},
mounted() {
this.initiateFontAwesome();

View File

@ -2,7 +2,7 @@
<div class="minimal-home" :style="getBackgroundImage() + setColumnCount()">
<!-- Buttons for config and home page -->
<div class="minimal-buttons">
<ConfigLauncher @modalChanged="modalChanged" class="config-launcher" />
<ConfigLauncher @modalChanged="updateModalVisibility" class="config-launcher" />
</div>
<!-- Page title and search bar -->
<div class="title-and-search">
@ -50,17 +50,17 @@
</template>
<script>
import HomeMixin from '@/mixins/HomeMixin';
import MinimalSection from '@/components/MinimalView/MinimalSection.vue';
import MinimalHeading from '@/components/MinimalView/MinimalHeading.vue';
import MinimalSearch from '@/components/MinimalView/MinimalSearch.vue';
import { GetTheme, ApplyLocalTheme, ApplyCustomVariables } from '@/utils/ThemeHelper';
import { searchTiles } from '@/utils/Search';
import Defaults, { localStorageKeys } from '@/utils/defaults';
import { localStorageKeys } from '@/utils/defaults';
import ConfigLauncher from '@/components/Settings/ConfigLauncher';
export default {
name: 'home',
mixins: [HomeMixin],
components: {
MinimalSection,
MinimalHeading,
@ -68,24 +68,11 @@ export default {
ConfigLauncher,
},
data: () => ({
searchValue: '',
layout: '',
modalOpen: false, // When true, keybindings are disabled
selectedSection: 0, // The index of currently selected section
tabbedView: true, // By default use tabs, when searching then show all instead
theme: GetTheme(),
}),
computed: {
sections() {
return this.$store.getters.sections;
},
appConfig() {
return this.$store.getters.appConfig;
},
pageInfo() {
return this.$store.getters.pageInfo;
},
},
watch: {
/* When the theme changes, then call the update method */
searchValue() {
@ -96,11 +83,6 @@ export default {
sectionSelected(index) {
this.selectedSection = index;
},
/* Returns true if there is one or more sections in the config */
checkTheresData(sections) {
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
@ -112,51 +94,10 @@ export default {
// Otherwise, return the usuall data from conf.yml
return sections;
},
/* Updates local data with search value, triggered from filter comp */
searching(searchValue) {
this.searchValue = searchValue || '';
},
/* Clears input field, once a searched item is opened */
finishedSearching() {
this.$refs.filterComp.clearMinFilterInput();
},
/* Extracts the site name from domain, used for the searching functionality */
getDomainFromUrl(url) {
if (!url) return '';
const urlPattern = /^(?:https?:\/\/)?(?:w{3}\.)?([a-z\d.-]+)\.(?:[a-z.]{2,10})(?:[/\w.-]*)*/;
const domainPattern = url.match(urlPattern);
return domainPattern ? domainPattern[1] : '';
},
/* Returns only the tiles that match the users search query */
filterTiles(allTiles) {
if (!allTiles) return [];
return searchTiles(allTiles, this.searchValue);
},
/* Update data when modal is open (so that key bindings can be disabled) */
updateModalVisibility(modalState) {
this.modalOpen = modalState;
},
/* Checks if any of the icons are Font Awesome glyphs */
checkIfFontAwesomeNeeded() {
let isNeeded = false;
if (!this.sections) return false;
this.sections.forEach((section) => {
if (section.icon && section.icon.includes('fa-')) isNeeded = true;
section.items.forEach((item) => {
if (item.icon && item.icon.includes('fa-')) isNeeded = true;
});
});
return isNeeded;
},
/* Injects font-awesome's script tag, only if needed */
initiateFontAwesome() {
if (this.appConfig.enableFontAwesome || this.checkIfFontAwesomeNeeded()) {
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);
}
},
/* Returns true if there is more than 1 sub-result visible during searching */
checkIfResults() {
if (!this.sections) return false;
@ -186,12 +127,10 @@ export default {
ApplyCustomVariables(this.theme);
}
},
modalChanged(modalState) {
this.modalOpen = modalState;
},
},
mounted() {
this.initiateFontAwesome();
this.initiateMaterialDesignIcons();
this.applyTheme();
},
};

View File

@ -7,7 +7,7 @@
</template>
<script>
import HomeMixin from '@/mixins/HomeMixin';
import SideBar from '@/components/Workspace/SideBar';
import WebContent from '@/components/Workspace/WebContent';
import MultiTaskingWebComtent from '@/components/Workspace/MultiTaskingWebComtent';
@ -16,6 +16,7 @@ import { GetTheme, ApplyLocalTheme, ApplyCustomVariables } from '@/utils/ThemeHe
export default {
name: 'Workspace',
mixins: [HomeMixin],
data: () => ({
url: '',
GetTheme,