diff --git a/dev/dev-notes.md b/dev/dev-notes.md
index 2c5d87f3a64e..121368e1194c 100644
--- a/dev/dev-notes.md
+++ b/dev/dev-notes.md
@@ -46,3 +46,5 @@ General
- Improved documentation
- Fixed hot-reloading development environment - [grssmnn](https://github.com/grssmnn)
- Added Confirmation component to deleting recipes - [zackbcom](https://github.com/zackbcom)
+- Added Persistent storage to vuex - [zackbcom](https://github.com/zackbcom)
+- Updated Theme backend - [zackbcom](https://github.com/zackbcom)
diff --git a/frontend/package.json b/frontend/package.json
index 17dfefb37958..cd9550c3be2d 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -17,7 +17,8 @@
"vue-html-to-paper": "^1.3.1",
"vue-router": "^3.4.9",
"vuetify": "^2.4.1",
- "vuex": "^3.6.0"
+ "vuex": "^3.6.0",
+ "vuex-persistedstate": "^4.0.0-beta.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 11b321b41192..533c394c7c67 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -37,6 +37,7 @@ import Menu from "./components/UI/Menu";
import SearchHeader from "./components/UI/SearchHeader";
import AddRecipe from "./components/AddRecipe";
import SnackBar from "./components/UI/SnackBar";
+import Vuetify from "./plugins/vuetify";
export default {
name: "App",
@@ -54,8 +55,9 @@ export default {
},
mounted() {
- this.$store.dispatch("initCookies");
+ this.$store.dispatch("initTheme");
this.$store.dispatch("requestRecentRecipes");
+ this.darkModeSystemCheck();
this.darkModeAddEventListener();
},
@@ -63,16 +65,25 @@ export default {
search: false
}),
methods: {
+ /**
+ * Checks if 'system' is set for dark mode and then sets the corrisponding value for vuetify
+ */
+ darkModeSystemCheck() {
+ if (this.$store.getters.getDarkMode === "system")
+ Vuetify.framework.theme.dark = window.matchMedia(
+ "(prefers-color-scheme: dark)"
+ ).matches;
+ },
/**
* This will monitor the OS level darkmode and call to update dark mode.
*/
darkModeAddEventListener() {
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
-
darkMediaQuery.addEventListener("change", () => {
- this.$store.commit("setDarkMode", "system");
+ this.darkModeSystemCheck();
});
},
+
toggleSearch() {
if (this.search === true) {
this.search = false;
diff --git a/frontend/src/components/Admin/Theme.vue b/frontend/src/components/Admin/Theme.vue
index 28f441bbcc8a..057d80195c8d 100644
--- a/frontend/src/components/Admin/Theme.vue
+++ b/frontend/src/components/Admin/Theme.vue
@@ -11,10 +11,10 @@
Default to system
@@ -48,7 +48,7 @@
:items="availableThemes"
item-text="name"
return-object
- v-model="activeTheme"
+ v-model="selectedTheme"
@change="themeSelected"
:rules="[v => !!v || 'Theme is required']"
required
@@ -73,42 +73,45 @@
-
+
-
+
-
+
@@ -118,7 +121,9 @@
- Save Theme
+
+ Save Colors and Apply Theme
+
@@ -139,62 +144,80 @@ export default {
},
data() {
return {
- activeTheme: {},
- darkMode: "system",
+ selectedTheme: {},
+ selectedDarkMode: "system",
availableThemes: []
};
},
async mounted() {
this.availableThemes = await api.themes.requestAll();
- this.activeTheme = this.$store.getters.getActiveTheme;
- this.darkMode = this.$store.getters.getDarkMode;
+ this.selectedTheme = this.$store.getters.getActiveTheme;
+ this.selectedDarkMode = this.$store.getters.getDarkMode;
},
methods: {
+ /**
+ * Open the delete confirmation.
+ */
deleteSelectedThemeValidation() {
if (this.$refs.form.validate()) {
- if (this.activeTheme.name === "default") {
+ if (this.selectedTheme.name === "default") {
// Notify User Can't Delete Default
- } else if (this.activeTheme !== {}) {
+ } else if (this.selectedTheme !== {}) {
this.$refs.deleteThemeConfirm.open();
}
}
},
+ /**
+ * Delete the selected Theme
+ */
async deleteSelectedTheme() {
- api.themes.delete(this.activeTheme.name);
- this.availableThemes = await api.themes.requestAll();
- //Change to default if deleting current theme.
+ //Delete Theme from DB
+ await api.themes.delete(this.selectedTheme.name);
+ //Get the new list of available from DB
+ this.availableThemes = await api.themes.requestAll();
+ console.log("themes", this.availableThemes);
+
+ //Change to default if deleting current theme.
if (
!this.availableThemes.some(
- theme => theme.name === this.activeTheme.name
+ theme => theme.name === this.selectedTheme.name
)
) {
- this.$store.commit("setActiveTheme", null);
- this.activeTheme = this.$store.getters.getActiveTheme;
+ console.log("hit");
+ await this.$store.dispatch("resetTheme");
+ this.selectedTheme = this.$store.getters.getActiveTheme;
}
},
+ /**
+ * Create the new Theme and select it.
+ */
async appendTheme(newTheme) {
- api.themes.create(newTheme);
+ await api.themes.create(newTheme);
this.availableThemes.push(newTheme);
- this.activeTheme = newTheme;
- },
- themeSelected() {
- console.log("this.activeTheme", this.activeTheme);
+ this.selectedTheme = newTheme;
},
- setDarkMode() {
- this.$store.commit("setDarkMode", this.darkMode);
+ themeSelected() {
+ //TODO Revamp Theme selection.
+ //console.log("this.activeTheme", this.selectedTheme);
+ },
+
+ setStoresDarkMode() {
+ this.$store.commit("setDarkMode", this.selectedDarkMode);
},
/**
* This will save the current colors and make the selected theme live.
*/
async saveThemes() {
if (this.$refs.form.validate()) {
- this.$store.commit("setActiveTheme", this.activeTheme);
- this.$store.dispatch("initCookies");
- api.themes.update(this.activeTheme.name, this.activeTheme);
- } else;
+ this.$store.commit("setTheme", this.selectedTheme);
+ await api.themes.update(
+ this.selectedTheme.name,
+ this.selectedTheme.colors
+ );
+ }
}
}
};
diff --git a/frontend/src/store/modules/userSettings.js b/frontend/src/store/modules/userSettings.js
new file mode 100644
index 000000000000..005e403f369c
--- /dev/null
+++ b/frontend/src/store/modules/userSettings.js
@@ -0,0 +1,70 @@
+
+import api from "../../api";
+import Vuetify from "../../plugins/vuetify";
+
+const state = {
+ activeTheme: {},
+ darkMode: 'system'
+
+};
+
+const mutations = {
+ setTheme(state, payload) {
+ Vuetify.framework.theme.themes.dark = payload.colors;
+ Vuetify.framework.theme.themes.light = payload.colors;
+ state.activeTheme = payload;
+ },
+ setDarkMode(state, payload) {
+ let isDark;
+
+ if (payload === 'system') {
+ //Get System Preference from browser
+ const darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+ isDark = darkMediaQuery.matches;
+ }
+ else if (payload === 'dark')
+ isDark = true;
+ else if (payload === 'light')
+ isDark = false;
+
+ if (isDark !== null) {
+ Vuetify.framework.theme.dark = isDark;
+ state.darkMode = payload;
+ }
+ },
+};
+
+const actions = {
+ async resetTheme({ commit }) {
+ const defaultTheme = await api.themes.requestByName("default");
+ if (defaultTheme.colors) {
+ Vuetify.framework.theme.themes.dark = defaultTheme.colors;
+ Vuetify.framework.theme.themes.light = defaultTheme.colors;
+ commit('setTheme', defaultTheme)
+ }
+ },
+
+ async initTheme({ dispatch, getters }) {
+ //If theme is empty resetTheme
+ if (Object.keys(getters.getActiveTheme).length === 0) {
+ await dispatch('resetTheme')
+ }
+ else {
+ Vuetify.framework.theme.themes.dark = getters.getActiveTheme.colors;
+ Vuetify.framework.theme.themes.light = getters.getActiveTheme.colors;
+ }
+ },
+
+}
+
+const getters = {
+ getActiveTheme: (state) => state.activeTheme,
+ getDarkMode: (state) => state.darkMode
+}
+
+export default {
+ state,
+ mutations,
+ actions,
+ getters
+}
\ No newline at end of file
diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js
index ae4d6aadc1b2..ca1a5efe61ea 100644
--- a/frontend/src/store/store.js
+++ b/frontend/src/store/store.js
@@ -1,11 +1,16 @@
import Vue from "vue";
import Vuex from "vuex";
import api from "../api";
-import Vuetify from "../plugins/vuetify";
+import createPersistedState from "vuex-persistedstate";
+import userSettings from "./modules/userSettings";
Vue.use(Vuex);
const store = new Vuex.Store({
+ plugins: [createPersistedState()],
+ modules: {
+ userSettings
+ },
state: {
// Snackbar
snackActive: false,
@@ -15,41 +20,6 @@ const store = new Vuex.Store({
// All Recipe Data Store
recentRecipes: [],
allRecipes: [],
-
- // Site Settings
- darkMode: 'system',
- activeTheme: {
- name: 'default',
- colors: {
- primary: "#E58325",
- accent: "#00457A",
- secondary: "#973542",
- success: "#5AB1BB",
- info: "#4990BA",
- warning: "#FF4081",
- error: "#EF5350",
- }
- },
- themes: {
- light: {
- primary: "#E58325",
- accent: "#00457A",
- secondary: "#973542",
- success: "#5AB1BB",
- info: "#4990BA",
- warning: "#FF4081",
- error: "#EF5350",
- },
- dark: {
- primary: "#E58325",
- accent: "#00457A",
- secondary: "#973542",
- success: "#5AB1BB",
- info: "#4990BA",
- warning: "#FF4081",
- error: "#EF5350",
- },
- },
},
mutations: {
@@ -65,65 +35,9 @@ const store = new Vuex.Store({
setRecentRecipes(state, payload) {
state.recentRecipes = payload;
},
-
- setDarkMode(state, payload) {
- let isDark;
- state.darkMode = payload;
- Vue.$cookies.set("darkMode", payload);
-
-
- if (payload === 'system') {
- //Get System Preference from browser
- const darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
- isDark = darkMediaQuery.matches;
- }
- else if (payload === 'dark')
- isDark = true;
- else
- isDark = false;
-
- Vuetify.framework.theme.dark = isDark;
- },
-
- setActiveTheme(state, payload) {
- state.activeTheme = payload;
- Vue.$cookies.set("activeTheme", payload);
-
- const themes = payload ? { dark: payload.colors, light: payload.colors } : null
- console.log("themes", themes)
- state.themes = themes;
- Vue.$cookies.set("themes", themes);
- Vuetify.framework.theme.themes = themes;
- },
},
actions: {
- async initCookies() {
- //TODO if has no value set to default.
- if (!Vue.$cookies.isKey("themes") || !Vue.$cookies.isKey("activeTheme")) {
- const DEFAULT_THEME = await api.themes.requestByName("default");
- Vue.$cookies.set("themes", {
- light: DEFAULT_THEME.colors,
- dark: DEFAULT_THEME.colors,
- });
- Vue.$cookies.set("activeTheme", {
- name: DEFAULT_THEME.name,
- colors: DEFAULT_THEME.colors
- });
- }
-
- this.commit("setActiveTheme", Vue.$cookies.get("activeTheme"));
-
- //https://csabaszabo.dev/blog/dark-mode-for-website-with-nuxtjs-and-vuetify/
- //https://github.com/settings/appearance
-
-
- // Dark Mode
- if (!Vue.$cookies.isKey("darkMode")) {
- Vue.$cookies.set("darkMode", 'system');
- }
- this.commit("setDarkMode", Vue.$cookies.get("darkMode"));
- },
async requestRecentRecipes() {
const keys = [
@@ -147,11 +61,6 @@ const store = new Vuex.Store({
getSnackType: (state) => state.snackType,
getRecentRecipes: (state) => state.recentRecipes,
-
- // Site Settings
- getDarkMode: (state) => state.darkMode,
- getThemes: (state) => state.themes,
- getActiveTheme: (state) => state.activeTheme
},
});