Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

💾 Storage Management hinzugefügt #681

Merged
merged 23 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
48b1de3
Added import/export options to the config.js controller
gnmyt May 20, 2024
f6a91b4
Added import/export options to the speedtests.js controller
gnmyt May 20, 2024
1d04eed
Updated the config.js routes to use the new validation system
gnmyt May 20, 2024
5b8d3a1
Implemented new routes in the storage.js
gnmyt May 20, 2024
64b09e3
Renamed /api/export -> /api/storage
gnmyt May 20, 2024
ae3669a
Fixed a design bug in the LatestTest styles.sass
gnmyt May 20, 2024
7ec9392
Added the donation link to the index.jsx
gnmyt May 20, 2024
cb7f24b
Fixed a bug in the styles default.sass
gnmyt May 20, 2024
1a5ab55
Added toasts to the LanguageDialog.jsx
gnmyt May 20, 2024
3d8cedf
Updated the LanguageDialog styles.sass
gnmyt May 20, 2024
f243c12
Removed the exportOptions from the options.js util
gnmyt May 20, 2024
c9a57ed
Updated the infos.jsx util
gnmyt May 20, 2024
b974cbe
Implemented toasts in the ProviderDialog.jsx
gnmyt May 20, 2024
ae1f069
Created the Configuration.jsx tab
gnmyt May 20, 2024
5079914
Created the Speedtests.jsx tab
gnmyt May 20, 2024
9eb79cf
Created the StorageDialog.jsx component
gnmyt May 20, 2024
97623eb
Created the StorageDialog index.js
gnmyt May 20, 2024
72634ef
Created the StorageDialog styles.sass
gnmyt May 20, 2024
54b6933
Added mobile optimization to the DataHelper styles.sass
gnmyt May 20, 2024
b479ba5
Added mobile optimization to the WelcomeDialog styles.sass
gnmyt May 20, 2024
4ebc681
Automatically set the previous config values if updated
gnmyt May 20, 2024
92cd878
Implemented the storage dialog into the DropdownComponent.jsx
gnmyt May 20, 2024
d4bd2de
Added new translations
gnmyt May 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions client/public/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"dropdown": {
"settings": "Settings",
"changes_applied": "Your changes have been saved.",
"language_changed": "The language has been changed.",
"provider_changed": "The provider has been changed.",
"view_changed": "The view has been changed.",
"changes_unsaved": "Your changes were not applied. Check your input.",
"invalid": "Input invalid",
Expand All @@ -55,7 +57,7 @@
"password": "Change password",
"cron": "Set frequency",
"time": "Set period",
"export": "Export tests",
"storage": "Manage storage",
"pause_tests": "Pause tests",
"resume_tests": "Resume tests",
"language": "Change language",
Expand All @@ -78,10 +80,6 @@
"rare": "Rarely (every 3 hours)",
"really_rare": "Very rarely (every 6 hours)"
},
"export": {
"json": "JSON file",
"csv": "CSV file"
},
"level": {
"no_access": "No Access",
"read_access": "Read-only Access"
Expand All @@ -107,7 +105,6 @@
"cron_rules": "Cron rule",
"cron_next_test": "Next Test:",
"time_title": "Show tests of the last ...",
"export_title": "Export speedtests",
"download": "Download",
"pause_title": "Pause speedtests for...",
"hours": "Hours",
Expand All @@ -130,6 +127,33 @@
"description": "This feature is still in beta. If you find any bugs, please report them <Link>here</Link>."
}
},
"storage": {
"speedtests": "Speedtests",
"configuration": "Configuration",
"stored_tests": "Stored tests",
"tests": "Tests",
"export_tests": "Export tests",
"tests_exported": "The tests have been exported",
"csv": "CSV",
"json": "JSON",
"import_tests": "Import tests",
"tests_imported": "The tests have been imported",
"import_error": "An error occurred while importing the tests",
"export": "Export",
"import": "Import",
"clear_history": "Clear history",
"history_cleared": "The history has been cleared",
"delete": "Delete",
"confirm_delete": "Yes, delete",
"export_settings": "Export settings",
"import_settings": "Import settings",
"factory_reset": "Factory reset",
"factory_reset_completed": "The factory reset has been completed",
"reset": "Reset",
"confirm_reset": "Yes, reset",
"settings_exported": "The settings have been exported",
"settings_imported": "The settings have been imported"
},
"latest": {
"ping": "Ping",
"ping_unit": "ms",
Expand All @@ -140,7 +164,7 @@
"before": "before"
},
"info": {
"credits": "<Link>MySpeed</Link> is provided by GNMYT and uses the <CLILink>Speedtest CLI</CLILink> from Ookla.",
"credits": "<MSpeed>MySpeed</MSpeed> is a open source project provided by GNMYT. Leave a star on <Github>GitHub</Github> or <Donate>donate</Donate> to support the project.",
"recommendations_error": "You have to do at least 10 tests to get an average. It doesn't matter if the tests were done manually or automatically.",
"recommendations_info": "Based on the last 10 tests, it was found that the optimal ping was <Bold>{{ping}} ms</Bold>, the download at <Bold>{{down}} Mbps</Bold> and the upload at <Bold>{{up}} Mbps</Bold>. It is best to orientate yourself on your internet contract and only adopt it if it matches that.",
"update": "An update to version {{version}} is available. See <Changes>the changes</Changes> and <DLLink>download the update</DLLink>.",
Expand Down
23 changes: 7 additions & 16 deletions client/src/common/components/Dropdown/DropdownComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
faCircleNodes,
faClock,
faClose,
faFileExport,
faChartSimple,
faGear,
faGlobeEurope,
Expand All @@ -18,15 +17,15 @@ import {
faPlay,
faWandMagicSparkles,
faCheck,
faExclamationTriangle, faSliders
faExclamationTriangle, faSliders, faHardDrive
} from "@fortawesome/free-solid-svg-icons";
import {ConfigContext} from "@/common/contexts/Config";
import {StatusContext} from "@/common/contexts/Status";
import {InputDialogContext} from "@/common/contexts/InputDialog";
import {SpeedtestContext} from "@/common/contexts/Speedtests";
import {baseRequest, downloadRequest, jsonRequest, patchRequest, postRequest} from "@/common/utils/RequestUtil";
import {baseRequest, jsonRequest, patchRequest, postRequest} from "@/common/utils/RequestUtil";
import {creditsInfo, recommendationsInfo} from "@/common/components/Dropdown/utils/infos";
import {exportOptions, levelOptions, selectOptions, timeOptions} from "@/common/components/Dropdown/utils/options";
import {levelOptions, selectOptions, timeOptions} from "@/common/components/Dropdown/utils/options";
import {parseCron, stringifyCron} from "@/common/components/Dropdown/utils/utils";
import {t} from "i18next";
import ViewDialog from "@/common/components/ViewDialog";
Expand All @@ -36,6 +35,7 @@ import {NodeContext} from "@/common/contexts/Node";
import {IntegrationDialog} from "@/common/components/IntegrationDialog";
import LanguageDialog from "@/common/components/LanguageDialog";
import ProviderDialog from "@/common/components/ProviderDialog";
import StorageDialog from "@/common/components/StorageDialog";

let icon;

Expand Down Expand Up @@ -66,6 +66,7 @@ function DropdownComponent() {
const [showIntegrationDialog, setShowIntegrationDialog] = useState(false);
const [showLanguageDialog, setShowLanguageDialog] = useState(false);
const [showProviderDialog, setShowProviderDialog] = useState(false);
const [showStorageDialog, setShowStorageDialog] = useState(false);
const ref = useRef();

useEffect(() => {
Expand Down Expand Up @@ -192,17 +193,6 @@ function DropdownComponent() {
});
}

function exportDialog() {
setDialog({
select: true,
title: t("update.export_title"),
buttonText: t("update.download"),
value: "json",
selectOptions: exportOptions(),
onSuccess: value => downloadRequest("/export/" + value)
});
}

const togglePause = () => {
if (!status.paused) {
setDialog({
Expand All @@ -228,9 +218,9 @@ function DropdownComponent() {
{run: recommendedSettings, icon: faWandMagicSparkles, text: t("dropdown.recommendations")},
{hr: true, key: 1},
{run: () => setShowProviderDialog(true), icon: faSliders, text: t("dropdown.change_provider")},
{run: () => setShowStorageDialog(true), icon: faHardDrive, text: t("dropdown.storage")},
{run: updatePassword, icon: faKey, text: t("dropdown.password"), previewHidden: true},
{run: updateCron, icon: faClock, text: t("dropdown.cron")},
{run: exportDialog, icon: faFileExport, text: t("dropdown.export")},
{run: togglePause, icon: status.paused ? faPlay : faPause, text: t("dropdown." + (status.paused ? "resume_tests" : "pause_tests"))},
{run: () => setShowIntegrationDialog(true), icon: faCircleNodes, text: t("dropdown.integrations")},
{hr: true, key: 2},
Expand All @@ -247,6 +237,7 @@ function DropdownComponent() {
{showIntegrationDialog && <IntegrationDialog onClose={() => setShowIntegrationDialog(false)}/>}
{showLanguageDialog && <LanguageDialog onClose={() => setShowLanguageDialog(false)}/>}
{showProviderDialog && <ProviderDialog onClose={() => setShowProviderDialog(false)}/>}
{showStorageDialog && <StorageDialog onClose={() => setShowStorageDialog(false)}/>}
<div className="dropdown dropdown-invisible" id="dropdown" ref={ref}>
<div className="dropdown-content">
<h2>{t("dropdown.settings")}</h2>
Expand Down
8 changes: 4 additions & 4 deletions client/src/common/components/Dropdown/utils/infos.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {WEB_URL} from "@/index";
import {DONATION_URL, PROJECT_URL, WEB_URL} from "@/index";
import {Trans} from "react-i18next";
const CLI_URL = "https://www.speedtest.net/apps/cli";

export const creditsInfo = () => <Trans components={{Link: <a href={WEB_URL} target="_blank" />,
CLILink: <a href={CLI_URL} target="_blank"/>}}>info.credits</Trans>

export const creditsInfo = () => <Trans components={{MSpeed: <a href={WEB_URL} target="_blank" />,
Github: <a href={PROJECT_URL} target="_blank" />, Donate: <a href={DONATION_URL} target="_blank" />}}>info.credits</Trans>

export const recommendationsInfo = (ping, down, up) => <Trans components={{Bold: <span className="dialog-value" />}}
values={{ping, down, up}}>info.recommendations_info</Trans>
5 changes: 0 additions & 5 deletions client/src/common/components/Dropdown/utils/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,4 @@ export const selectOptions = () => ({
"0 * * * *": t("options.cron.default"),
"0 0,3,6,9,12,15,18,21 * * *": t("options.cron.rare"),
"0 0,6,12,18 * * *": t("options.cron.really_rare")
});

export const exportOptions = () => ({
json: t("options.export.json"),
csv: t("options.export.csv")
});
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import {DialogContext, DialogProvider} from "@/common/contexts/Dialog";
import {t, changeLanguage} from "i18next";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faClose} from "@fortawesome/free-solid-svg-icons";
import {faClose, faGlobe} from "@fortawesome/free-solid-svg-icons";
import "./styles.sass";
import {languages} from "@/i18n";
import {useContext, useState} from "react";
import {ToastNotificationContext} from "@/common/contexts/ToastNotification";

export const Dialog = () => {
const [selectedLanguage, setSelectedLanguage] = useState(localStorage.getItem("language") || "en");
const updateToast = useContext(ToastNotificationContext);
const close = useContext(DialogContext);

const updateLanguage = () => {
changeLanguage(selectedLanguage);
updateToast(t('dropdown.language_changed'), "green", faGlobe);
close();
}

Expand Down
2 changes: 2 additions & 0 deletions client/src/common/components/LanguageDialog/styles.sass
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
cursor: pointer
transition: background-color 0.3s
border-radius: 0.5rem
border: 2px solid $darker-gray

&:hover
background-color: $darker-gray
Expand All @@ -37,6 +38,7 @@
.language-selected
background-color: $light-gray
color: $white
border: 2px solid $light-gray

&:hover
background-color: $light-gray
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {DialogContext, DialogProvider} from "@/common/contexts/Dialog";
import {t} from "i18next";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faClose} from "@fortawesome/free-solid-svg-icons";
import {faCheck, faClose} from "@fortawesome/free-solid-svg-icons";
import "./styles.sass";
import React, {useContext, useEffect, useState} from "react";
import OoklaImage from "./assets/img/ookla.webp";
Expand All @@ -10,6 +10,7 @@ import CloudflareImage from "./assets/img/cloudflare.webp";
import {jsonRequest, patchRequest} from "@/common/utils/RequestUtil";
import {Trans} from "react-i18next";
import {ConfigContext} from "@/common/contexts/Config";
import {ToastNotificationContext} from "@/common/contexts/ToastNotification";

export const providers = [
{id: "ookla", name: "Ookla", image: OoklaImage},
Expand All @@ -21,6 +22,7 @@ export const providers = [
export const Dialog = () => {
const close = useContext(DialogContext);
const [config, reloadConfig] = useContext(ConfigContext);
const updateToast = useContext(ToastNotificationContext);
const [provider, setProvider] = useState(config.provider || "ookla");

const [licenseAccepted, setLicenseAccepted] = useState(false);
Expand Down Expand Up @@ -61,6 +63,7 @@ export const Dialog = () => {
}

reloadConfig();
updateToast(t('dropdown.provider_changed'), "green", faCheck);

close();
}
Expand Down
69 changes: 69 additions & 0 deletions client/src/common/components/StorageDialog/StorageDialog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import "./styles.sass";
import React, {useContext, useEffect, useState} from "react";
import {DialogContext, DialogProvider} from "@/common/contexts/Dialog";
import {t} from "i18next";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faClose, faDatabase, faGauge, faScrewdriverWrench} from "@fortawesome/free-solid-svg-icons";
import Speedtests from "./tabs/Speedtests";
import Configuration from "./tabs/Configuration";
import {jsonRequest} from "@/common/utils/RequestUtil";

const Dialog = () => {
const close = useContext(DialogContext);
const [storageSize, setStorageSize] = useState({size: 0, testCount: 0});

const [currentTab, setCurrentTab] = useState(1);

useEffect(() => {
jsonRequest("/storage").then((res) => {
setStorageSize(res);
});
}, []);

return (
<>
<div className="dialog-header">
<h4 className="dialog-text">{t("dropdown.storage")}</h4>
<FontAwesomeIcon icon={faClose} className="dialog-text dialog-icon" onClick={() => close()}/>
</div>
<div className="storage-dialog">
<div className="storage-options">
<div className="storage-top">
<div className={"storage-tab" + (1 === currentTab ? " storage-item-active" : "")}
onClick={() => setCurrentTab(1)}>
<FontAwesomeIcon icon={faGauge}/>
<p>{t("storage.speedtests")}</p>
</div>
<div className={"storage-tab" + (2 === currentTab ? " storage-item-active" : "")}
onClick={() => setCurrentTab(2)}>
<FontAwesomeIcon icon={faScrewdriverWrench}/>
<p>{t("storage.configuration")}</p>
</div>

</div>
<div className="storage-bottom">
<div className="storage-tab reset-cursor">
<FontAwesomeIcon icon={faDatabase}/>
<p>{Math.round(storageSize.size / 1024)} KB</p>
</div>
</div>
</div>

<div className="storage-manager">
{currentTab === 1 && <Speedtests tests={storageSize.testCount}/>}
{currentTab === 2 && <Configuration/>}
</div>


</div>
</>
);
}

export const StorageDialog = ({onClose}) => {
return (
<DialogProvider close={onClose}>
<Dialog/>
</DialogProvider>
)
}
1 change: 1 addition & 0 deletions client/src/common/components/StorageDialog/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {StorageDialog as default} from "./StorageDialog";
Loading