]> git.localhorst.tv Git - alttp.git/commitdiff
save, load, reset
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 29 May 2025 15:17:19 +0000 (17:17 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 29 May 2025 15:17:19 +0000 (17:17 +0200)
resources/js/components/common/Icon.js
resources/js/components/zootr/MixedPoolsTracker.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index 84c6d11fb7a57e19f65fba4742c79f63e4999b4c..ff676c1ffa795fda36f298b2dc91cdf883f9a416 100644 (file)
@@ -70,6 +70,7 @@ Icon.HASH = makePreset('HashIcon', 'hashtag');
 Icon.INFO = makePreset('Info', 'circle-info');
 Icon.INVERT = makePreset('InvertIcon', 'circle-half-stroke');
 Icon.LANGUAGE = makePreset('LanguageIcon', 'language');
+Icon.LOAD = makePreset('LoadIcon', 'upload');
 Icon.LOCKED = makePreset('LockedIcon', 'lock');
 Icon.LOGOUT = makePreset('LogoutIcon', 'sign-out-alt');
 Icon.MENU = makePreset('MenuIcon', 'bars');
@@ -85,7 +86,9 @@ Icon.PROTOCOL = makePreset('ProtocolIcon', 'file-alt');
 Icon.RACETIME = makePreset('RacetimeIcon', 'stopwatch');
 Icon.REJECT = makePreset('RejectIcon', 'square-xmark');
 Icon.REMOVE = makePreset('RemoveIcon', 'square-xmark');
+Icon.RESET = makePreset('ResetIcon', 'rotate-left');
 Icon.RESULT = makePreset('ResultIcon', 'clock');
+Icon.SAVE = makePreset('SaveIcon', 'download');
 Icon.SECOND_PLACE = makePreset('SecondPlaceIcon', 'medal');
 Icon.SETTINGS = makePreset('SettingsIcon', 'cog');
 Icon.SLASH = makePreset('SlashIcon', 'slash');
index ea5bf1f0dddcae97560b3c91f1daf6d16c388c9c..0c1e82fb841d12d95d203f742534c185cc77b696 100644 (file)
@@ -1,6 +1,11 @@
 import FuzzySearch from 'fuzzy-search';
 import PropTypes from 'prop-types';
 import React from 'react';
+import { Button } from 'react-bootstrap';
+import { useTranslation } from 'react-i18next';
+import toastr from 'toastr';
+
+import Icon from '../common/Icon';
 
 const AREAS = [
        {
@@ -2824,6 +2829,8 @@ MapAnnotation.propTypes = {
 };
 
 const MixedPoolsTracker = () => {
+       const { t } = useTranslation();
+
        const [connections, setConnections] = React.useState({});
        const [dragging, setDragging] = React.useState(null);
 
@@ -2983,8 +2990,72 @@ const MixedPoolsTracker = () => {
                return ans;
        }, [connections]);
 
+       const save = React.useCallback(() => {
+               try {
+                       const dump = JSON.stringify({ connections });
+                       localStorage.setItem('zootr.mixed-pools-tracker-save', dump);
+                       toastr.success(t('general.saveSuccess'));
+               } catch (e) {
+                       toastr.error(t('general.saveError'));
+                       console.error(e);
+               }
+       }, [connections, t]);
+
+       const load = React.useCallback(() => {
+               try {
+                       const dump = localStorage.getItem('zootr.mixed-pools-tracker-save');
+                       if (!dump) {
+                               toastr.error(t('general.loadError'));
+                               return;
+                       }
+                       const { connections } = JSON.parse(dump);
+                       if (connections) {
+                               setConnections(connections);
+                       }
+                       toastr.success(t('general.loadSuccess'));
+               } catch (e) {
+                       toastr.error(t('general.loadError'));
+                       console.error(e);
+               }
+       }, [setConnections, t]);
+
+       const reset = React.useCallback(() => {
+               try {
+                       setConnections({});
+                       toastr.success(t('general.resetSuccess'));
+               } catch (e) {
+                       toastr.error(t('general.resetError'));
+               }
+       }, [setConnections, t]);
+
        return <CONTEXT.Provider value={context}>
                <div className="mixed-pools-tracker">
+                       <div className="menu-bar button-bar">
+                               <Button
+                                       onClick={save}
+                                       size="sm"
+                                       title={t('button.save')}
+                                       variant="outline-secondary"
+                               >
+                                       <Icon.SAVE title="" />
+                               </Button>
+                               <Button
+                                       onClick={load}
+                                       size="sm"
+                                       title={t('button.load')}
+                                       variant="outline-secondary"
+                               >
+                                       <Icon.LOAD title="" />
+                               </Button>
+                               <Button
+                                       onClick={reset}
+                                       size="sm"
+                                       title={t('button.reset')}
+                                       variant="outline-secondary"
+                               >
+                                       <Icon.RESET title="" />
+                               </Button>
+                       </div>
                        <div className="columns">
                                {superGroups.map((sg) =>
                                        <div className="column" key={sg.key}>
index 0daccf92ace9bf96cfd240b84601522b9d01f3cc..a656acc28a89a27b06f33ce79f018cb382e6c40a 100644 (file)
@@ -78,6 +78,7 @@ export default {
                        generate: 'Generieren',
                        help: 'Hilfe',
                        invert: 'Umkehren',
+                       load: 'Laden',
                        login: 'Login',
                        logout: 'Logout',
                        new: 'Neu',
@@ -87,6 +88,7 @@ export default {
                        playPause: 'Play/Pause',
                        protocol: 'Protokoll',
                        remove: 'Entfernen',
+                       reset: 'Zurücksetzen',
                        retry: 'Neu versuchen',
                        save: 'Speichern',
                        search: 'Suche',
@@ -238,13 +240,19 @@ export default {
                        anonymous: 'Anonym',
                        appDescription: 'Turniere und Tutorials für The Legend of Zelda: A Link to the Past Randomizer',
                        appName: 'ALttP',
-                       pleaseSelect: 'Bitte wählen',
                        languages: {
                                de: 'Deutsch',
                                en: 'Englisch',
                                es: 'Spanisch',
                                fr: 'Französisch',
                        },
+                       loadError: 'Fehler beim Laden',
+                       loadSuccess: 'Geladen',
+                       pleaseSelect: 'Bitte wählen',
+                       resetError: 'Fehler beim Zurücksetzen',
+                       resetSuccess: 'Zurückgesetzt',
+                       saveError: 'Fehler beim Speichern',
+                       saveSuccess: 'Gespeichert',
                },
                icon: {
                        AddIcon: 'Hinzufügen',
index 6ef3cd233da9c0b948eb998c84093662389d2a75..9fe8dbc1528d495cb3aca791aafb386c9f1a6c1f 100644 (file)
@@ -78,6 +78,7 @@ export default {
                        generate: 'Generate',
                        help: 'Help',
                        invert: 'Invert',
+                       load: 'Load',
                        login: 'Login',
                        logout: 'Logout',
                        new: 'New',
@@ -87,6 +88,7 @@ export default {
                        playPause: 'Play/Pause',
                        protocol: 'Protocol',
                        remove: 'Remove',
+                       reset: 'Reset',
                        retry: 'Retry',
                        save: 'Save',
                        search: 'Search',
@@ -238,13 +240,19 @@ export default {
                        anonymous: 'Anonym',
                        appDescription: 'Tournaments and tutorials for The Legend of Zelda: A Link to the Past Randomizer',
                        appName: 'ALttP',
-                       pleaseSelect: 'Please select',
                        languages: {
                                de: 'German',
                                en: 'English',
                                es: 'Spanish',
                                fr: 'French',
                        },
+                       loadError: 'Error loading',
+                       loadSuccess: 'Loading successful',
+                       pleaseSelect: 'Please select',
+                       resetError: 'Error resetting',
+                       resetSuccess: 'Reset successful',
+                       saveError: 'Error saving',
+                       saveSuccess: 'Saved successfully',
                },
                icon: {
                        AddIcon: 'Add',