Ver código fonte

Merge pull request #312 from pawelmalak/feature

Version 2.2.2
pawelmalak 3 anos atrás
pai
commit
baac78021a

+ 2 - 0
.dev/build_latest.sh

@@ -0,0 +1,2 @@
+docker build -t pawelmalak/flame -t "pawelmalak/flame:$1" -f .docker/Dockerfile "$2" \
+  && docker push pawelmalak/flame && docker push "pawelmalak/flame:$1"

+ 6 - 0
.dev/build_multiarch.sh

@@ -0,0 +1,6 @@
+docker buildx build \
+  --platform linux/arm/v7,linux/arm64,linux/amd64 \
+  -f .docker/Dockerfile.multiarch \
+  -t pawelmalak/flame:multiarch \
+  -t "pawelmalak/flame:multiarch$1" \
+  --push "$2"

+ 1 - 1
.docker/Dockerfile

@@ -27,4 +27,4 @@ EXPOSE 5005
 ENV NODE_ENV=production
 ENV PASSWORD=flame_password
 
-CMD ["node", "server.js"]
+CMD ["sh", "-c", "chown -R node /app/data && node server.js"]

+ 1 - 1
.docker/Dockerfile.multiarch

@@ -28,4 +28,4 @@ EXPOSE 5005
 ENV NODE_ENV=production
 ENV PASSWORD=flame_password
 
-CMD ["node", "server.js"]
+CMD ["sh", "-c", "chown -R node /app/data && node server.js"]

+ 1 - 1
.env

@@ -1,5 +1,5 @@
 PORT=5005
 NODE_ENV=development
-VERSION=2.2.1
+VERSION=2.2.2
 PASSWORD=flame_password
 SECRET=e02eb43d69953658c6d07311d6313f2d4467672cb881f96b29368ba1f3f4da4b

+ 1 - 2
.gitignore

@@ -1,5 +1,4 @@
 node_modules
 data
 public
-!client/public
-build.sh
+!client/public

+ 7 - 0
CHANGELOG.md

@@ -1,3 +1,10 @@
+### v2.2.2 (2022-03-21)
+- Added option to get user location directly from the app ([#287](https://github.com/pawelmalak/flame/issues/287))
+- Fixed bug with local search not working when using prefix ([#289](https://github.com/pawelmalak/flame/issues/289))
+- Fixed bug with app description not updating when using custom icon ([#310](https://github.com/pawelmalak/flame/issues/310))
+- Changed permissions to some files and directories created by Flame
+- Changed some of the settings tabs
+
 ### v2.2.1 (2022-01-08)
 - Local search will now include app descriptions ([#266](https://github.com/pawelmalak/flame/issues/266))
 - Fixed bug with unsupported characters in local search [#279](https://github.com/pawelmalak/flame/issues/279))

+ 1 - 1
client/.env

@@ -1 +1 @@
-REACT_APP_VERSION=2.2.1
+REACT_APP_VERSION=2.2.2

+ 2 - 0
client/src/components/Apps/AppForm/AppForm.tsx

@@ -64,7 +64,9 @@ export const AppForm = ({ modalHandler }: Props): JSX.Element => {
       if (customIcon) {
         data.append('icon', customIcon);
       }
+
       data.append('name', formData.name);
+      data.append('description', formData.description);
       data.append('url', formData.url);
       data.append('isPublic', `${formData.isPublic ? 1 : 0}`);
 

+ 1 - 1
client/src/components/Apps/AppTable/AppTable.tsx

@@ -94,7 +94,7 @@ export const AppTable = (props: Props): JSX.Element => {
         ) : (
           <p>
             Custom order is disabled. You can change it in the{' '}
-            <Link to="/settings/interface">settings</Link>
+            <Link to="/settings/general">settings</Link>
           </p>
         )}
       </Message>

+ 1 - 1
client/src/components/Bookmarks/Table/CategoryTable.tsx

@@ -102,7 +102,7 @@ export const CategoryTable = ({ openFormForUpdating }: Props): JSX.Element => {
         ) : (
           <p>
             Custom order is disabled. You can change it in the{' '}
-            <Link to="/settings/interface">settings</Link>
+            <Link to="/settings/general">settings</Link>
           </p>
         )}
       </Message>

+ 1 - 2
client/src/components/SearchBar/SearchBar.tsx

@@ -69,8 +69,7 @@ export const SearchBar = (props: Props): JSX.Element => {
     );
 
     if (isLocal) {
-      // no additional encoding required for local search
-      setLocalSearch(inputRef.current.value);
+      setLocalSearch(search);
     }
 
     if (e.code === 'Enter' || e.code === 'NumpadEnter') {

+ 0 - 0
client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.module.css → client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.module.css


+ 0 - 0
client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx → client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.tsx


+ 0 - 0
client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx → client/src/components/Settings/GeneralSettings/CustomQueries/QueriesForm.tsx


+ 106 - 35
client/src/components/Settings/SearchSettings/SearchSettings.tsx → client/src/components/Settings/GeneralSettings/GeneralSettings.tsx

@@ -3,7 +3,7 @@ import { useState, useEffect, FormEvent, ChangeEvent, Fragment } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 
 // Typescript
-import { Query, SearchForm } from '../../../interfaces';
+import { Query, GeneralForm } from '../../../interfaces';
 
 // Components
 import { CustomQueries } from './CustomQueries/CustomQueries';
@@ -12,7 +12,7 @@ import { CustomQueries } from './CustomQueries/CustomQueries';
 import { Button, SettingsHeadline, InputGroup } from '../../UI';
 
 // Utils
-import { inputHandler, searchSettingsTemplate } from '../../../utility';
+import { inputHandler, generalSettingsTemplate } from '../../../utility';
 
 // Data
 import { queries } from '../../../utility/searchQueries.json';
@@ -22,16 +22,20 @@ import { State } from '../../../store/reducers';
 import { bindActionCreators } from 'redux';
 import { actionCreators } from '../../../store';
 
-export const SearchSettings = (): JSX.Element => {
-  const { loading, customQueries, config } = useSelector(
-    (state: State) => state.config
-  );
+export const GeneralSettings = (): JSX.Element => {
+  const {
+    config: { loading, customQueries, config },
+    bookmarks: { categories },
+  } = useSelector((state: State) => state);
 
   const dispatch = useDispatch();
-  const { updateConfig } = bindActionCreators(actionCreators, dispatch);
+  const { updateConfig, sortApps, sortCategories, sortBookmarks } =
+    bindActionCreators(actionCreators, dispatch);
 
   // Initial state
-  const [formData, setFormData] = useState<SearchForm>(searchSettingsTemplate);
+  const [formData, setFormData] = useState<GeneralForm>(
+    generalSettingsTemplate
+  );
 
   // Get config
   useEffect(() => {
@@ -46,6 +50,16 @@ export const SearchSettings = (): JSX.Element => {
 
     // Save settings
     await updateConfig(formData);
+
+    // Sort entities with new settings
+    if (formData.useOrdering !== config.useOrdering) {
+      sortApps();
+      sortCategories();
+
+      for (let { id } of categories) {
+        sortBookmarks(id);
+      }
+    }
   };
 
   // Input handler
@@ -53,7 +67,7 @@ export const SearchSettings = (): JSX.Element => {
     e: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
     options?: { isNumber?: boolean; isBool?: boolean }
   ) => {
-    inputHandler<SearchForm>({
+    inputHandler<GeneralForm>({
       e,
       options,
       setStateHandler: setFormData,
@@ -63,40 +77,70 @@ export const SearchSettings = (): JSX.Element => {
 
   return (
     <Fragment>
-      {/* GENERAL SETTINGS */}
       <form
         onSubmit={(e) => formSubmitHandler(e)}
         style={{ marginBottom: '30px' }}
       >
+        {/* === GENERAL OPTIONS === */}
         <SettingsHeadline text="General" />
+        {/* SORT TYPE */}
         <InputGroup>
-          <label htmlFor="defaultSearchProvider">Default search provider</label>
+          <label htmlFor="useOrdering">Sorting type</label>
           <select
-            id="defaultSearchProvider"
-            name="defaultSearchProvider"
-            value={formData.defaultSearchProvider}
+            id="useOrdering"
+            name="useOrdering"
+            value={formData.useOrdering}
             onChange={(e) => inputChangeHandler(e)}
           >
-            {[...queries, ...customQueries].map((query: Query, idx) => {
-              const isCustom = idx >= queries.length;
+            <option value="createdAt">By creation date</option>
+            <option value="name">Alphabetical order</option>
+            <option value="orderId">Custom order</option>
+          </select>
+        </InputGroup>
 
-              return (
-                <option key={idx} value={query.prefix}>
-                  {isCustom && '+'} {query.name}
-                </option>
-              );
-            })}
+        {/* === APPS OPTIONS === */}
+        <SettingsHeadline text="Apps" />
+        {/* PIN APPS */}
+        <InputGroup>
+          <label htmlFor="pinAppsByDefault">
+            Pin new applications by default
+          </label>
+          <select
+            id="pinAppsByDefault"
+            name="pinAppsByDefault"
+            value={formData.pinAppsByDefault ? 1 : 0}
+            onChange={(e) => inputChangeHandler(e, { isBool: true })}
+          >
+            <option value={1}>True</option>
+            <option value={0}>False</option>
           </select>
         </InputGroup>
 
+        {/* APPS OPPENING */}
         <InputGroup>
-          <label htmlFor="searchSameTab">
-            Open search results in the same tab
+          <label htmlFor="appsSameTab">Open applications in the same tab</label>
+          <select
+            id="appsSameTab"
+            name="appsSameTab"
+            value={formData.appsSameTab ? 1 : 0}
+            onChange={(e) => inputChangeHandler(e, { isBool: true })}
+          >
+            <option value={1}>True</option>
+            <option value={0}>False</option>
+          </select>
+        </InputGroup>
+
+        {/* === BOOKMARKS OPTIONS === */}
+        <SettingsHeadline text="Bookmarks" />
+        {/* PIN CATEGORIES */}
+        <InputGroup>
+          <label htmlFor="pinCategoriesByDefault">
+            Pin new categories by default
           </label>
           <select
-            id="searchSameTab"
-            name="searchSameTab"
-            value={formData.searchSameTab ? 1 : 0}
+            id="pinCategoriesByDefault"
+            name="pinCategoriesByDefault"
+            value={formData.pinCategoriesByDefault ? 1 : 0}
             onChange={(e) => inputChangeHandler(e, { isBool: true })}
           >
             <option value={1}>True</option>
@@ -104,12 +148,15 @@ export const SearchSettings = (): JSX.Element => {
           </select>
         </InputGroup>
 
+        {/* BOOKMARKS OPPENING */}
         <InputGroup>
-          <label htmlFor="hideSearch">Hide search bar</label>
+          <label htmlFor="bookmarksSameTab">
+            Open bookmarks in the same tab
+          </label>
           <select
-            id="hideSearch"
-            name="hideSearch"
-            value={formData.hideSearch ? 1 : 0}
+            id="bookmarksSameTab"
+            name="bookmarksSameTab"
+            value={formData.bookmarksSameTab ? 1 : 0}
             onChange={(e) => inputChangeHandler(e, { isBool: true })}
           >
             <option value={1}>True</option>
@@ -117,12 +164,36 @@ export const SearchSettings = (): JSX.Element => {
           </select>
         </InputGroup>
 
+        {/* SEARCH SETTINGS */}
+        <SettingsHeadline text="Search" />
         <InputGroup>
-          <label htmlFor="disableAutofocus">Disable search bar autofocus</label>
+          <label htmlFor="defaultSearchProvider">Default search provider</label>
           <select
-            id="disableAutofocus"
-            name="disableAutofocus"
-            value={formData.disableAutofocus ? 1 : 0}
+            id="defaultSearchProvider"
+            name="defaultSearchProvider"
+            value={formData.defaultSearchProvider}
+            onChange={(e) => inputChangeHandler(e)}
+          >
+            {[...queries, ...customQueries].map((query: Query, idx) => {
+              const isCustom = idx >= queries.length;
+
+              return (
+                <option key={idx} value={query.prefix}>
+                  {isCustom && '+'} {query.name}
+                </option>
+              );
+            })}
+          </select>
+        </InputGroup>
+
+        <InputGroup>
+          <label htmlFor="searchSameTab">
+            Open search results in the same tab
+          </label>
+          <select
+            id="searchSameTab"
+            name="searchSameTab"
+            value={formData.searchSameTab ? 1 : 0}
             onChange={(e) => inputChangeHandler(e, { isBool: true })}
           >
             <option value={1}>True</option>

+ 3 - 3
client/src/components/Settings/Settings.tsx

@@ -16,7 +16,7 @@ import { WeatherSettings } from './WeatherSettings/WeatherSettings';
 import { UISettings } from './UISettings/UISettings';
 import { AppDetails } from './AppDetails/AppDetails';
 import { StyleSettings } from './StyleSettings/StyleSettings';
-import { SearchSettings } from './SearchSettings/SearchSettings';
+import { GeneralSettings } from './GeneralSettings/GeneralSettings';
 import { DockerSettings } from './DockerSettings/DockerSettings';
 import { ProtectedRoute } from '../Routing/ProtectedRoute';
 
@@ -59,8 +59,8 @@ export const Settings = (): JSX.Element => {
               component={WeatherSettings}
             />
             <ProtectedRoute
-              path="/settings/search"
-              component={SearchSettings}
+              path="/settings/general"
+              component={GeneralSettings}
             />
             <ProtectedRoute path="/settings/interface" component={UISettings} />
             <ProtectedRoute

+ 40 - 103
client/src/components/Settings/UISettings/UISettings.tsx

@@ -7,28 +7,22 @@ import { bindActionCreators } from 'redux';
 import { actionCreators } from '../../../store';
 
 // Typescript
-import { OtherSettingsForm } from '../../../interfaces';
+import { UISettingsForm } from '../../../interfaces';
 
 // UI
 import { InputGroup, Button, SettingsHeadline } from '../../UI';
 
 // Utils
-import { otherSettingsTemplate, inputHandler } from '../../../utility';
+import { uiSettingsTemplate, inputHandler } from '../../../utility';
 
 export const UISettings = (): JSX.Element => {
-  const {
-    config: { loading, config },
-    bookmarks: { categories },
-  } = useSelector((state: State) => state);
+  const { loading, config } = useSelector((state: State) => state.config);
 
   const dispatch = useDispatch();
-  const { updateConfig, sortApps, sortCategories, sortBookmarks } =
-    bindActionCreators(actionCreators, dispatch);
+  const { updateConfig } = bindActionCreators(actionCreators, dispatch);
 
   // Initial state
-  const [formData, setFormData] = useState<OtherSettingsForm>(
-    otherSettingsTemplate
-  );
+  const [formData, setFormData] = useState<UISettingsForm>(uiSettingsTemplate);
 
   // Get config
   useEffect(() => {
@@ -46,16 +40,6 @@ export const UISettings = (): JSX.Element => {
 
     // Update local page title
     document.title = formData.customTitle;
-
-    // Sort entities with new settings
-    if (formData.useOrdering !== config.useOrdering) {
-      sortApps();
-      sortCategories();
-
-      for (let { id } of categories) {
-        sortBookmarks(id);
-      }
-    }
   };
 
   // Input handler
@@ -63,7 +47,7 @@ export const UISettings = (): JSX.Element => {
     e: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
     options?: { isNumber?: boolean; isBool?: boolean }
   ) => {
-    inputHandler<OtherSettingsForm>({
+    inputHandler<UISettingsForm>({
       e,
       options,
       setStateHandler: setFormData,
@@ -88,6 +72,36 @@ export const UISettings = (): JSX.Element => {
         />
       </InputGroup>
 
+      {/* === SEARCH OPTIONS === */}
+      <SettingsHeadline text="Search" />
+      {/* HIDE SEARCHBAR */}
+      <InputGroup>
+        <label htmlFor="hideSearch">Hide search bar</label>
+        <select
+          id="hideSearch"
+          name="hideSearch"
+          value={formData.hideSearch ? 1 : 0}
+          onChange={(e) => inputChangeHandler(e, { isBool: true })}
+        >
+          <option value={1}>True</option>
+          <option value={0}>False</option>
+        </select>
+      </InputGroup>
+
+      {/* AUTOFOCUS SEARCHBAR */}
+      <InputGroup>
+        <label htmlFor="disableAutofocus">Disable search bar autofocus</label>
+        <select
+          id="disableAutofocus"
+          name="disableAutofocus"
+          value={formData.disableAutofocus ? 1 : 0}
+          onChange={(e) => inputChangeHandler(e, { isBool: true })}
+        >
+          <option value={1}>True</option>
+          <option value={0}>False</option>
+        </select>
+      </InputGroup>
+
       {/* === HEADER OPTIONS === */}
       <SettingsHeadline text="Header" />
       {/* HIDE HEADER */}
@@ -160,8 +174,8 @@ export const UISettings = (): JSX.Element => {
           onChange={(e) => inputChangeHandler(e)}
         />
         <span>
-          Greetings must be separated with semicolon. Only 4 messages can be
-          used
+          Greetings must be separated with semicolon. All 4 messages must be
+          filled, even if they are the same
         </span>
       </InputGroup>
 
@@ -193,85 +207,8 @@ export const UISettings = (): JSX.Element => {
         <span>Names must be separated with semicolon</span>
       </InputGroup>
 
-      {/* === BEAHVIOR OPTIONS === */}
-      <SettingsHeadline text="App Behavior" />
-      {/* PIN APPS */}
-      <InputGroup>
-        <label htmlFor="pinAppsByDefault">
-          Pin new applications by default
-        </label>
-        <select
-          id="pinAppsByDefault"
-          name="pinAppsByDefault"
-          value={formData.pinAppsByDefault ? 1 : 0}
-          onChange={(e) => inputChangeHandler(e, { isBool: true })}
-        >
-          <option value={1}>True</option>
-          <option value={0}>False</option>
-        </select>
-      </InputGroup>
-
-      {/* PIN CATEGORIES */}
-      <InputGroup>
-        <label htmlFor="pinCategoriesByDefault">
-          Pin new categories by default
-        </label>
-        <select
-          id="pinCategoriesByDefault"
-          name="pinCategoriesByDefault"
-          value={formData.pinCategoriesByDefault ? 1 : 0}
-          onChange={(e) => inputChangeHandler(e, { isBool: true })}
-        >
-          <option value={1}>True</option>
-          <option value={0}>False</option>
-        </select>
-      </InputGroup>
-
-      {/* SORT TYPE */}
-      <InputGroup>
-        <label htmlFor="useOrdering">Sorting type</label>
-        <select
-          id="useOrdering"
-          name="useOrdering"
-          value={formData.useOrdering}
-          onChange={(e) => inputChangeHandler(e)}
-        >
-          <option value="createdAt">By creation date</option>
-          <option value="name">Alphabetical order</option>
-          <option value="orderId">Custom order</option>
-        </select>
-      </InputGroup>
-
-      {/* APPS OPPENING */}
-      <InputGroup>
-        <label htmlFor="appsSameTab">Open applications in the same tab</label>
-        <select
-          id="appsSameTab"
-          name="appsSameTab"
-          value={formData.appsSameTab ? 1 : 0}
-          onChange={(e) => inputChangeHandler(e, { isBool: true })}
-        >
-          <option value={1}>True</option>
-          <option value={0}>False</option>
-        </select>
-      </InputGroup>
-
-      {/* BOOKMARKS OPPENING */}
-      <InputGroup>
-        <label htmlFor="bookmarksSameTab">Open bookmarks in the same tab</label>
-        <select
-          id="bookmarksSameTab"
-          name="bookmarksSameTab"
-          value={formData.bookmarksSameTab ? 1 : 0}
-          onChange={(e) => inputChangeHandler(e, { isBool: true })}
-        >
-          <option value={1}>True</option>
-          <option value={0}>False</option>
-        </select>
-      </InputGroup>
-
-      {/* === MODULES OPTIONS === */}
-      <SettingsHeadline text="Modules" />
+      {/* === SECTIONS OPTIONS === */}
+      <SettingsHeadline text="Sections" />
       {/* HIDE APPS */}
       <InputGroup>
         <label htmlFor="hideApps">Hide applications</label>

+ 15 - 9
client/src/components/Settings/WeatherSettings/WeatherSettings.tsx

@@ -82,6 +82,19 @@ export const WeatherSettings = (): JSX.Element => {
     });
   };
 
+  // Get user location
+  const getLocation = () => {
+    window.navigator.geolocation.getCurrentPosition(
+      ({ coords: { latitude, longitude } }) => {
+        setFormData({
+          ...formData,
+          lat: latitude,
+          long: longitude,
+        });
+      }
+    );
+  };
+
   return (
     <form onSubmit={(e) => formSubmitHandler(e)}>
       <SettingsHeadline text="API" />
@@ -120,15 +133,8 @@ export const WeatherSettings = (): JSX.Element => {
           step="any"
           lang="en-150"
         />
-        <span>
-          You can use
-          <a
-            href="https://www.latlong.net/convert-address-to-lat-long.html"
-            target="blank"
-          >
-            {' '}
-            latlong.net
-          </a>
+        <span onClick={getLocation}>
+          <a href="#">Click to get current location</a>
         </span>
       </InputGroup>
 

+ 6 - 6
client/src/components/Settings/settings.json

@@ -6,18 +6,18 @@
       "authRequired": false
     },
     {
-      "name": "Weather",
-      "dest": "/settings/weather",
+      "name": "General",
+      "dest": "/settings/general",
       "authRequired": true
     },
     {
-      "name": "Search",
-      "dest": "/settings/search",
+      "name": "Interface",
+      "dest": "/settings/interface",
       "authRequired": true
     },
     {
-      "name": "Interface",
-      "dest": "/settings/interface",
+      "name": "Weather",
+      "dest": "/settings/weather",
       "authRequired": true
     },
     {

+ 2 - 2
client/src/components/UI/Forms/InputGroup/InputGroup.module.css

@@ -23,7 +23,7 @@
 
 .InputGroup span {
   font-size: 12px;
-  color: var(--color-primary)
+  color: var(--color-primary);
 }
 
 .InputGroup span a {
@@ -37,4 +37,4 @@
 .InputGroup textarea {
   resize: none;
   height: 50vh;
-}
+}

+ 9 - 9
client/src/interfaces/Forms.ts

@@ -8,29 +8,29 @@ export interface WeatherForm {
   weatherData: WeatherData;
 }
 
-export interface SearchForm {
-  hideSearch: boolean;
+export interface GeneralForm {
   defaultSearchProvider: string;
   searchSameTab: boolean;
-  disableAutofocus: boolean;
+  pinAppsByDefault: boolean;
+  pinCategoriesByDefault: boolean;
+  useOrdering: string;
+  appsSameTab: boolean;
+  bookmarksSameTab: boolean;
 }
 
-export interface OtherSettingsForm {
+export interface UISettingsForm {
   customTitle: string;
-  pinAppsByDefault: boolean;
-  pinCategoriesByDefault: boolean;
   hideHeader: boolean;
   hideApps: boolean;
   hideCategories: boolean;
-  useOrdering: string;
-  appsSameTab: boolean;
-  bookmarksSameTab: boolean;
   useAmericanDate: boolean;
   greetingsSchema: string;
   daySchema: string;
   monthSchema: string;
   showTime: boolean;
   hideDate: boolean;
+  hideSearch: boolean;
+  disableAutofocus: boolean;
 }
 
 export interface DockerSettingsForm {

+ 4 - 4
client/src/types/ConfigFormData.ts

@@ -1,14 +1,14 @@
 import {
   DockerSettingsForm,
-  OtherSettingsForm,
-  SearchForm,
+  UISettingsForm,
+  GeneralForm,
   ThemeSettingsForm,
   WeatherForm,
 } from '../interfaces';
 
 export type ConfigFormData =
   | WeatherForm
-  | SearchForm
+  | GeneralForm
   | DockerSettingsForm
-  | OtherSettingsForm
+  | UISettingsForm
   | ThemeSettingsForm;

+ 11 - 11
client/src/utility/templateObjects/settingsTemplate.ts

@@ -1,21 +1,16 @@
 import {
   DockerSettingsForm,
-  OtherSettingsForm,
-  SearchForm,
+  UISettingsForm,
+  GeneralForm,
   ThemeSettingsForm,
   WeatherForm,
 } from '../../interfaces';
 
-export const otherSettingsTemplate: OtherSettingsForm = {
+export const uiSettingsTemplate: UISettingsForm = {
   customTitle: document.title,
-  pinAppsByDefault: true,
-  pinCategoriesByDefault: true,
   hideHeader: false,
   hideApps: false,
   hideCategories: false,
-  useOrdering: 'createdAt',
-  appsSameTab: false,
-  bookmarksSameTab: false,
   useAmericanDate: false,
   greetingsSchema: 'Good evening!;Good afternoon!;Good morning!;Good night!',
   daySchema: 'Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday',
@@ -23,6 +18,8 @@ export const otherSettingsTemplate: OtherSettingsForm = {
     'January;February;March;April;May;June;July;August;September;October;November;December',
   showTime: false,
   hideDate: false,
+  hideSearch: false,
+  disableAutofocus: false,
 };
 
 export const weatherSettingsTemplate: WeatherForm = {
@@ -33,11 +30,14 @@ export const weatherSettingsTemplate: WeatherForm = {
   weatherData: 'cloud',
 };
 
-export const searchSettingsTemplate: SearchForm = {
-  hideSearch: false,
+export const generalSettingsTemplate: GeneralForm = {
   searchSameTab: false,
   defaultSearchProvider: 'l',
-  disableAutofocus: false,
+  pinAppsByDefault: true,
+  pinCategoriesByDefault: true,
+  useOrdering: 'createdAt',
+  appsSameTab: false,
+  bookmarksSameTab: false,
 };
 
 export const dockerSettingsTemplate: DockerSettingsForm = {