فهرست منبع

Added user themes section to Theme settings

Paweł Malak 3 سال پیش
والد
کامیت
48e28b9abd

+ 7 - 0
client/src/components/Settings/Themer/ThemeBuilder/ThemeBuilder.module.css

@@ -0,0 +1,7 @@
+.ThemeBuilder {
+  margin-bottom: 30px;
+}
+
+.Buttons button:not(:last-child) {
+  margin-right: 10px;
+}

+ 20 - 2
client/src/components/Settings/Themer/ThemeBuilder/ThemeBuilder.tsx

@@ -1,3 +1,21 @@
-export const ThemeBuilder = (): JSX.Element => {
-  return <h1>theme builder</h1>;
+import { Theme } from '../../../../interfaces';
+import { Button } from '../../../UI';
+import { ThemeGrid } from '../ThemeGrid/ThemeGrid';
+import classes from './ThemeBuilder.module.css';
+
+interface Props {
+  themes: Theme[];
+}
+
+export const ThemeBuilder = ({ themes }: Props): JSX.Element => {
+  return (
+    <div className={classes.ThemeBuilder}>
+      <ThemeGrid themes={themes} />
+
+      <div className={classes.Buttons}>
+        <Button>Create new theme</Button>
+        {themes.length && <Button>Edit user themes</Button>}
+      </div>
+    </div>
+  );
 };
 };

+ 18 - 8
client/src/components/Settings/Themer/Themer.tsx

@@ -15,13 +15,17 @@ import { ThemeGrid } from './ThemeGrid/ThemeGrid';
 
 
 // Other
 // Other
 import { State } from '../../../store/reducers';
 import { State } from '../../../store/reducers';
-import { inputHandler, themeSettingsTemplate } from '../../../utility';
+import {
+  inputHandler,
+  parseThemeToPAB,
+  themeSettingsTemplate,
+} from '../../../utility';
 
 
 export const Themer = (): JSX.Element => {
 export const Themer = (): JSX.Element => {
   const {
   const {
     auth: { isAuthenticated },
     auth: { isAuthenticated },
     config: { loading, config },
     config: { loading, config },
-    theme: { themes },
+    theme: { themes, userThemes },
   } = useSelector((state: State) => state);
   } = useSelector((state: State) => state);
 
 
   const dispatch = useDispatch();
   const dispatch = useDispatch();
@@ -44,7 +48,7 @@ export const Themer = (): JSX.Element => {
     e.preventDefault();
     e.preventDefault();
 
 
     // Save settings
     // Save settings
-    await updateConfig(formData);
+    await updateConfig({ ...formData });
   };
   };
 
 
   // Input handler
   // Input handler
@@ -65,8 +69,14 @@ export const Themer = (): JSX.Element => {
       <SettingsHeadline text="App themes" />
       <SettingsHeadline text="App themes" />
       {!themes.length ? <Spinner /> : <ThemeGrid themes={themes} />}
       {!themes.length ? <Spinner /> : <ThemeGrid themes={themes} />}
 
 
-      {/* <SettingsHeadline text="User themes" />
-      <ThemeBuilder /> */}
+      {!userThemes.length ? (
+        isAuthenticated && 'auth and empty'
+      ) : (
+        <Fragment>
+          <SettingsHeadline text="User themes" />
+          <ThemeBuilder themes={userThemes} />
+        </Fragment>
+      )}
 
 
       {isAuthenticated && (
       {isAuthenticated && (
         <form onSubmit={formSubmitHandler}>
         <form onSubmit={formSubmitHandler}>
@@ -79,9 +89,9 @@ export const Themer = (): JSX.Element => {
               value={formData.defaultTheme}
               value={formData.defaultTheme}
               onChange={(e) => inputChangeHandler(e)}
               onChange={(e) => inputChangeHandler(e)}
             >
             >
-              {themes.map((theme: Theme, idx) => (
-                <option key={idx} value={theme.name}>
-                  {theme.name}
+              {[...themes, ...userThemes].map((theme: Theme, idx) => (
+                <option key={idx} value={parseThemeToPAB(theme.colors)}>
+                  {theme.isCustom && '+'} {theme.name}
                 </option>
                 </option>
               ))}
               ))}
             </select>
             </select>

+ 1 - 0
client/src/interfaces/Theme.ts

@@ -7,4 +7,5 @@ export interface ThemeColors {
 export interface Theme {
 export interface Theme {
   name: string;
   name: string;
   colors: ThemeColors;
   colors: ThemeColors;
+  isCustom: boolean;
 }
 }

+ 13 - 1
client/src/store/reducers/theme.ts

@@ -1,13 +1,16 @@
 import { Action } from '../actions';
 import { Action } from '../actions';
 import { ActionType } from '../action-types';
 import { ActionType } from '../action-types';
 import { Theme } from '../../interfaces/Theme';
 import { Theme } from '../../interfaces/Theme';
+import { arrayPartition } from '../../utility';
 
 
 interface ThemeState {
 interface ThemeState {
   themes: Theme[];
   themes: Theme[];
+  userThemes: Theme[];
 }
 }
 
 
 const initialState: ThemeState = {
 const initialState: ThemeState = {
   themes: [],
   themes: [],
+  userThemes: [],
 };
 };
 
 
 export const themeReducer = (
 export const themeReducer = (
@@ -16,7 +19,16 @@ export const themeReducer = (
 ): ThemeState => {
 ): ThemeState => {
   switch (action.type) {
   switch (action.type) {
     case ActionType.fetchThemes: {
     case ActionType.fetchThemes: {
-      return { themes: action.payload };
+      const [themes, userThemes] = arrayPartition<Theme>(
+        action.payload,
+        (e) => !e.isCustom
+      );
+
+      return {
+        ...state,
+        themes,
+        userThemes,
+      };
     }
     }
 
 
     default:
     default:

+ 11 - 0
client/src/utility/arrayPartition.ts

@@ -0,0 +1,11 @@
+export const arrayPartition = <T>(
+  arr: T[],
+  isValid: (e: T) => boolean
+): T[][] => {
+  let pass: T[] = [];
+  let fail: T[] = [];
+
+  arr.forEach((e) => (isValid(e) ? pass : fail).push(e));
+
+  return [pass, fail];
+};

+ 1 - 0
client/src/utility/index.ts

@@ -13,3 +13,4 @@ export * from './decodeToken';
 export * from './applyAuth';
 export * from './applyAuth';
 export * from './escapeRegex';
 export * from './escapeRegex';
 export * from './parseTheme';
 export * from './parseTheme';
+export * from './arrayPartition';

+ 5 - 3
utils/Logger.js

@@ -1,6 +1,6 @@
 class Logger {
 class Logger {
   log(message, level = 'INFO') {
   log(message, level = 'INFO') {
-    console.log(`[${this.generateTimestamp()}] [${level}] ${message}`)
+    console.log(`[${this.generateTimestamp()}] [${level}] ${message}`);
   }
   }
 
 
   generateTimestamp() {
   generateTimestamp() {
@@ -20,7 +20,9 @@ class Logger {
     // Timezone
     // Timezone
     const tz = -d.getTimezoneOffset() / 60;
     const tz = -d.getTimezoneOffset() / 60;
 
 
-    return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}.${miliseconds} UTC${tz >= 0 ? '+' + tz : tz}`;
+    return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}.${miliseconds} UTC${
+      tz >= 0 ? '+' + tz : tz
+    }`;
   }
   }
 
 
   parseDate(date, ms = false) {
   parseDate(date, ms = false) {
@@ -36,4 +38,4 @@ class Logger {
   }
   }
 }
 }
 
 
-module.exports = Logger;
+module.exports = Logger;

+ 30 - 15
utils/init/initialFiles.json

@@ -46,7 +46,8 @@
               "background": "#1a1a1a",
               "background": "#1a1a1a",
               "primary": "#FFFDEA",
               "primary": "#FFFDEA",
               "accent": "#5c5c5c"
               "accent": "#5c5c5c"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "gazette",
             "name": "gazette",
@@ -54,7 +55,8 @@
               "background": "#F2F7FF",
               "background": "#F2F7FF",
               "primary": "#000000",
               "primary": "#000000",
               "accent": "#5c5c5c"
               "accent": "#5c5c5c"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "espresso",
             "name": "espresso",
@@ -62,7 +64,8 @@
               "background": "#21211F",
               "background": "#21211F",
               "primary": "#D1B59A",
               "primary": "#D1B59A",
               "accent": "#4E4E4E"
               "accent": "#4E4E4E"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "cab",
             "name": "cab",
@@ -70,7 +73,8 @@
               "background": "#F6D305",
               "background": "#F6D305",
               "primary": "#1F1F1F",
               "primary": "#1F1F1F",
               "accent": "#424242"
               "accent": "#424242"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "cloud",
             "name": "cloud",
@@ -78,7 +82,8 @@
               "background": "#f1f2f0",
               "background": "#f1f2f0",
               "primary": "#35342f",
               "primary": "#35342f",
               "accent": "#37bbe4"
               "accent": "#37bbe4"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "lime",
             "name": "lime",
@@ -86,7 +91,8 @@
               "background": "#263238",
               "background": "#263238",
               "primary": "#AABBC3",
               "primary": "#AABBC3",
               "accent": "#aeea00"
               "accent": "#aeea00"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "white",
             "name": "white",
@@ -94,7 +100,8 @@
               "background": "#ffffff",
               "background": "#ffffff",
               "primary": "#222222",
               "primary": "#222222",
               "accent": "#dddddd"
               "accent": "#dddddd"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "tron",
             "name": "tron",
@@ -102,7 +109,8 @@
               "background": "#242B33",
               "background": "#242B33",
               "primary": "#EFFBFF",
               "primary": "#EFFBFF",
               "accent": "#6EE2FF"
               "accent": "#6EE2FF"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "blues",
             "name": "blues",
@@ -110,7 +118,8 @@
               "background": "#2B2C56",
               "background": "#2B2C56",
               "primary": "#EFF1FC",
               "primary": "#EFF1FC",
               "accent": "#6677EB"
               "accent": "#6677EB"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "passion",
             "name": "passion",
@@ -118,7 +127,8 @@
               "background": "#f5f5f5",
               "background": "#f5f5f5",
               "primary": "#12005e",
               "primary": "#12005e",
               "accent": "#8e24aa"
               "accent": "#8e24aa"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "chalk",
             "name": "chalk",
@@ -126,7 +136,8 @@
               "background": "#263238",
               "background": "#263238",
               "primary": "#AABBC3",
               "primary": "#AABBC3",
               "accent": "#FF869A"
               "accent": "#FF869A"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "paper",
             "name": "paper",
@@ -134,7 +145,8 @@
               "background": "#F8F6F1",
               "background": "#F8F6F1",
               "primary": "#4C432E",
               "primary": "#4C432E",
               "accent": "#AA9A73"
               "accent": "#AA9A73"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "neon",
             "name": "neon",
@@ -142,7 +154,8 @@
               "background": "#091833",
               "background": "#091833",
               "primary": "#EFFBFF",
               "primary": "#EFFBFF",
               "accent": "#ea00d9"
               "accent": "#ea00d9"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "pumpkin",
             "name": "pumpkin",
@@ -150,7 +163,8 @@
               "background": "#2d3436",
               "background": "#2d3436",
               "primary": "#EFFBFF",
               "primary": "#EFFBFF",
               "accent": "#ffa500"
               "accent": "#ffa500"
-            }
+            },
+            "isCustom": false
           },
           },
           {
           {
             "name": "onedark",
             "name": "onedark",
@@ -158,7 +172,8 @@
               "background": "#282c34",
               "background": "#282c34",
               "primary": "#dfd9d6",
               "primary": "#dfd9d6",
               "accent": "#98c379"
               "accent": "#98c379"
-            }
+            },
+            "isCustom": false
           }
           }
         ]
         ]
       },
       },

+ 30 - 15
utils/init/themes.json

@@ -6,7 +6,8 @@
         "background": "#1a1a1a",
         "background": "#1a1a1a",
         "primary": "#FFFDEA",
         "primary": "#FFFDEA",
         "accent": "#5c5c5c"
         "accent": "#5c5c5c"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "gazette",
       "name": "gazette",
@@ -14,7 +15,8 @@
         "background": "#F2F7FF",
         "background": "#F2F7FF",
         "primary": "#000000",
         "primary": "#000000",
         "accent": "#5c5c5c"
         "accent": "#5c5c5c"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "espresso",
       "name": "espresso",
@@ -22,7 +24,8 @@
         "background": "#21211F",
         "background": "#21211F",
         "primary": "#D1B59A",
         "primary": "#D1B59A",
         "accent": "#4E4E4E"
         "accent": "#4E4E4E"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "cab",
       "name": "cab",
@@ -30,7 +33,8 @@
         "background": "#F6D305",
         "background": "#F6D305",
         "primary": "#1F1F1F",
         "primary": "#1F1F1F",
         "accent": "#424242"
         "accent": "#424242"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "cloud",
       "name": "cloud",
@@ -38,7 +42,8 @@
         "background": "#f1f2f0",
         "background": "#f1f2f0",
         "primary": "#35342f",
         "primary": "#35342f",
         "accent": "#37bbe4"
         "accent": "#37bbe4"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "lime",
       "name": "lime",
@@ -46,7 +51,8 @@
         "background": "#263238",
         "background": "#263238",
         "primary": "#AABBC3",
         "primary": "#AABBC3",
         "accent": "#aeea00"
         "accent": "#aeea00"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "white",
       "name": "white",
@@ -54,7 +60,8 @@
         "background": "#ffffff",
         "background": "#ffffff",
         "primary": "#222222",
         "primary": "#222222",
         "accent": "#dddddd"
         "accent": "#dddddd"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "tron",
       "name": "tron",
@@ -62,7 +69,8 @@
         "background": "#242B33",
         "background": "#242B33",
         "primary": "#EFFBFF",
         "primary": "#EFFBFF",
         "accent": "#6EE2FF"
         "accent": "#6EE2FF"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "blues",
       "name": "blues",
@@ -70,7 +78,8 @@
         "background": "#2B2C56",
         "background": "#2B2C56",
         "primary": "#EFF1FC",
         "primary": "#EFF1FC",
         "accent": "#6677EB"
         "accent": "#6677EB"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "passion",
       "name": "passion",
@@ -78,7 +87,8 @@
         "background": "#f5f5f5",
         "background": "#f5f5f5",
         "primary": "#12005e",
         "primary": "#12005e",
         "accent": "#8e24aa"
         "accent": "#8e24aa"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "chalk",
       "name": "chalk",
@@ -86,7 +96,8 @@
         "background": "#263238",
         "background": "#263238",
         "primary": "#AABBC3",
         "primary": "#AABBC3",
         "accent": "#FF869A"
         "accent": "#FF869A"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "paper",
       "name": "paper",
@@ -94,7 +105,8 @@
         "background": "#F8F6F1",
         "background": "#F8F6F1",
         "primary": "#4C432E",
         "primary": "#4C432E",
         "accent": "#AA9A73"
         "accent": "#AA9A73"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "neon",
       "name": "neon",
@@ -102,7 +114,8 @@
         "background": "#091833",
         "background": "#091833",
         "primary": "#EFFBFF",
         "primary": "#EFFBFF",
         "accent": "#ea00d9"
         "accent": "#ea00d9"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "pumpkin",
       "name": "pumpkin",
@@ -110,7 +123,8 @@
         "background": "#2d3436",
         "background": "#2d3436",
         "primary": "#EFFBFF",
         "primary": "#EFFBFF",
         "accent": "#ffa500"
         "accent": "#ffa500"
-      }
+      },
+      "isCustom": false
     },
     },
     {
     {
       "name": "onedark",
       "name": "onedark",
@@ -118,7 +132,8 @@
         "background": "#282c34",
         "background": "#282c34",
         "primary": "#dfd9d6",
         "primary": "#dfd9d6",
         "accent": "#98c379"
         "accent": "#98c379"
-      }
+      },
+      "isCustom": false
     }
     }
   ]
   ]
 }
 }