diff --git a/.dev/build_latest.sh b/.dev/build_latest.sh new file mode 100644 index 0000000..9621433 --- /dev/null +++ b/.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" \ No newline at end of file diff --git a/.dev/build_multiarch.sh b/.dev/build_multiarch.sh new file mode 100644 index 0000000..ef1e10c --- /dev/null +++ b/.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" \ No newline at end of file diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 701547e..457a387 100644 --- a/.docker/Dockerfile +++ b/.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"] \ No newline at end of file diff --git a/.docker/Dockerfile.multiarch b/.docker/Dockerfile.multiarch index 42f5082..1c4fb20 100644 --- a/.docker/Dockerfile.multiarch +++ b/.docker/Dockerfile.multiarch @@ -28,4 +28,4 @@ EXPOSE 5005 ENV NODE_ENV=production ENV PASSWORD=flame_password -CMD ["node", "server.js"] \ No newline at end of file +CMD ["sh", "-c", "chown -R node /app/data && node server.js"] \ No newline at end of file diff --git a/.env b/.env index d5f54d5..887f01e 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ PORT=5005 NODE_ENV=development -VERSION=2.2.1 +VERSION=2.2.2 PASSWORD=flame_password SECRET=e02eb43d69953658c6d07311d6313f2d4467672cb881f96b29368ba1f3f4da4b \ No newline at end of file diff --git a/.gitignore b/.gitignore index 147804b..d53b3ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules data public -!client/public -build.sh \ No newline at end of file +!client/public \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9502adf..e3d3e1d 100644 --- a/CHANGELOG.md +++ b/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)) diff --git a/client/.env b/client/.env index edd69d9..f31a910 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=2.2.1 \ No newline at end of file +REACT_APP_VERSION=2.2.2 \ No newline at end of file diff --git a/client/src/components/Apps/AppForm/AppForm.tsx b/client/src/components/Apps/AppForm/AppForm.tsx index c2dc07a..a751ad6 100644 --- a/client/src/components/Apps/AppForm/AppForm.tsx +++ b/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}`); diff --git a/client/src/components/Apps/AppTable/AppTable.tsx b/client/src/components/Apps/AppTable/AppTable.tsx index 003e1a7..8279c77 100644 --- a/client/src/components/Apps/AppTable/AppTable.tsx +++ b/client/src/components/Apps/AppTable/AppTable.tsx @@ -94,7 +94,7 @@ export const AppTable = (props: Props): JSX.Element => { ) : (

Custom order is disabled. You can change it in the{' '} - settings + settings

)} diff --git a/client/src/components/Bookmarks/Table/CategoryTable.tsx b/client/src/components/Bookmarks/Table/CategoryTable.tsx index d909cab..5a88097 100644 --- a/client/src/components/Bookmarks/Table/CategoryTable.tsx +++ b/client/src/components/Bookmarks/Table/CategoryTable.tsx @@ -102,7 +102,7 @@ export const CategoryTable = ({ openFormForUpdating }: Props): JSX.Element => { ) : (

Custom order is disabled. You can change it in the{' '} - settings + settings

)} diff --git a/client/src/components/SearchBar/SearchBar.tsx b/client/src/components/SearchBar/SearchBar.tsx index dd0efe4..9920073 100644 --- a/client/src/components/SearchBar/SearchBar.tsx +++ b/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') { diff --git a/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.module.css b/client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.module.css similarity index 100% rename from client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.module.css rename to client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.module.css diff --git a/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx b/client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.tsx similarity index 100% rename from client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx rename to client/src/components/Settings/GeneralSettings/CustomQueries/CustomQueries.tsx diff --git a/client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx b/client/src/components/Settings/GeneralSettings/CustomQueries/QueriesForm.tsx similarity index 100% rename from client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx rename to client/src/components/Settings/GeneralSettings/CustomQueries/QueriesForm.tsx diff --git a/client/src/components/Settings/SearchSettings/SearchSettings.tsx b/client/src/components/Settings/GeneralSettings/GeneralSettings.tsx similarity index 50% rename from client/src/components/Settings/SearchSettings/SearchSettings.tsx rename to client/src/components/Settings/GeneralSettings/GeneralSettings.tsx index 9b057f5..4173c72 100644 --- a/client/src/components/Settings/SearchSettings/SearchSettings.tsx +++ b/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(searchSettingsTemplate); + const [formData, setFormData] = useState( + 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, options?: { isNumber?: boolean; isBool?: boolean } ) => { - inputHandler({ + inputHandler({ e, options, setStateHandler: setFormData, @@ -63,12 +77,95 @@ export const SearchSettings = (): JSX.Element => { return ( - {/* GENERAL SETTINGS */}
formSubmitHandler(e)} style={{ marginBottom: '30px' }} > + {/* === GENERAL OPTIONS === */} + {/* SORT TYPE */} + + + + + + {/* === APPS OPTIONS === */} + + {/* PIN APPS */} + + + + + + {/* APPS OPPENING */} + + + + + + {/* === BOOKMARKS OPTIONS === */} + + {/* PIN CATEGORIES */} + + + + + + {/* BOOKMARKS OPPENING */} + + + + + + {/* SEARCH SETTINGS */} + - - - - - - - - - - diff --git a/client/src/components/Settings/Settings.tsx b/client/src/components/Settings/Settings.tsx index f9f5102..7a297c9 100644 --- a/client/src/components/Settings/Settings.tsx +++ b/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} /> { - 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( - otherSettingsTemplate - ); + const [formData, setFormData] = useState(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, options?: { isNumber?: boolean; isBool?: boolean } ) => { - inputHandler({ + inputHandler({ e, options, setStateHandler: setFormData, @@ -88,6 +72,36 @@ export const UISettings = (): JSX.Element => { /> + {/* === SEARCH OPTIONS === */} + + {/* HIDE SEARCHBAR */} + + + + + + {/* AUTOFOCUS SEARCHBAR */} + + + + + {/* === HEADER OPTIONS === */} {/* HIDE HEADER */} @@ -160,8 +174,8 @@ export const UISettings = (): JSX.Element => { onChange={(e) => inputChangeHandler(e)} /> - 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 @@ -193,85 +207,8 @@ export const UISettings = (): JSX.Element => { Names must be separated with semicolon - {/* === BEAHVIOR OPTIONS === */} - - {/* PIN APPS */} - - - - - - {/* PIN CATEGORIES */} - - - - - - {/* SORT TYPE */} - - - - - - {/* APPS OPPENING */} - - - - - - {/* BOOKMARKS OPPENING */} - - - - - - {/* === MODULES OPTIONS === */} - + {/* === SECTIONS OPTIONS === */} + {/* HIDE APPS */} diff --git a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx index 19ba7d4..a6819d8 100644 --- a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx +++ b/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 (
formSubmitHandler(e)}> @@ -120,15 +133,8 @@ export const WeatherSettings = (): JSX.Element => { step="any" lang="en-150" /> - - You can use - - {' '} - latlong.net - + + Click to get current location diff --git a/client/src/components/Settings/settings.json b/client/src/components/Settings/settings.json index 49f0aee..75f6177 100644 --- a/client/src/components/Settings/settings.json +++ b/client/src/components/Settings/settings.json @@ -6,13 +6,8 @@ "authRequired": false }, { - "name": "Weather", - "dest": "/settings/weather", - "authRequired": true - }, - { - "name": "Search", - "dest": "/settings/search", + "name": "General", + "dest": "/settings/general", "authRequired": true }, { @@ -20,6 +15,11 @@ "dest": "/settings/interface", "authRequired": true }, + { + "name": "Weather", + "dest": "/settings/weather", + "authRequired": true + }, { "name": "Docker", "dest": "/settings/docker", diff --git a/client/src/components/UI/Forms/InputGroup/InputGroup.module.css b/client/src/components/UI/Forms/InputGroup/InputGroup.module.css index 93b74f1..3d67554 100644 --- a/client/src/components/UI/Forms/InputGroup/InputGroup.module.css +++ b/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; -} \ No newline at end of file +} diff --git a/client/src/interfaces/Forms.ts b/client/src/interfaces/Forms.ts index ad3763f..11e2739 100644 --- a/client/src/interfaces/Forms.ts +++ b/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; -} - -export interface OtherSettingsForm { - customTitle: string; pinAppsByDefault: boolean; pinCategoriesByDefault: boolean; - hideHeader: boolean; - hideApps: boolean; - hideCategories: boolean; useOrdering: string; appsSameTab: boolean; bookmarksSameTab: boolean; +} + +export interface UISettingsForm { + customTitle: string; + hideHeader: boolean; + hideApps: boolean; + hideCategories: boolean; useAmericanDate: boolean; greetingsSchema: string; daySchema: string; monthSchema: string; showTime: boolean; hideDate: boolean; + hideSearch: boolean; + disableAutofocus: boolean; } export interface DockerSettingsForm { diff --git a/client/src/types/ConfigFormData.ts b/client/src/types/ConfigFormData.ts index a67d8af..5f1c3e5 100644 --- a/client/src/types/ConfigFormData.ts +++ b/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; diff --git a/client/src/utility/templateObjects/settingsTemplate.ts b/client/src/utility/templateObjects/settingsTemplate.ts index a122830..af3d137 100644 --- a/client/src/utility/templateObjects/settingsTemplate.ts +++ b/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 = {