Skip to content

Commit

Permalink
Merge pull request #598 from gnmyt/updates/preview_mode
Browse files Browse the repository at this point in the history
🔍 Demo-Modus hinzugefügt
  • Loading branch information
gnmyt authored Mar 10, 2024
2 parents bf1747b + d07a8eb commit ee03467
Show file tree
Hide file tree
Showing 22 changed files with 209 additions and 39 deletions.
9 changes: 9 additions & 0 deletions client/public/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"language": "Change language",
"view": "Switch view",
"info": "About the project",
"provider": "About the provider",
"integrations": "Integrations"
},
"options": {
Expand Down Expand Up @@ -106,6 +107,7 @@
"running_tooltip": "Speedtest running",
"start_tooltip": "Start speedtest",
"new_update": "Update available",
"download": "Download",
"paused": "Speedtests are currently paused. Please continue them if you want to do one.",
"running": "A speedtest is already running. Please wait a moment.",
"admin_login": "Admin Login",
Expand Down Expand Up @@ -245,6 +247,7 @@
"update_password": "Please update the password of this node",
"password_outdated": "Password outdated",
"password_updated": "The password has been successfully updated",
"preview_active": "Adding and deleting servers is disabled during demo mode.",
"placeholder": {
"name": "MySpeed instance",
"url": "https://your-server.com"
Expand All @@ -265,8 +268,14 @@
"tests_pending": "Test results pending"
}
},
"preview": {
"title": "Demo mode",
"info": "DEMO",
"description": "You are currently in demo mode. Some features are disabled and some settings cannot be changed. If you want to use all features, you can <Link>install MySpeed</Link> on your own server."
},
"integrations": {
"none_active": "This integration is not active. <br/><Bold>Create</Bold>",
"preview_active": "Integrations are disabled during demo mode.",
"display_name": "Integration name",
"create": "Create",
"activity": {
Expand Down
11 changes: 8 additions & 3 deletions client/src/common/components/Dropdown/DropdownComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ 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 {creditsInfo, healthChecksInfo, recommendationsInfo} from "@/common/components/Dropdown/utils/infos";
import {creditsInfo, recommendationsInfo} from "@/common/components/Dropdown/utils/infos";
import {
exportOptions, languageOptions, levelOptions,
selectOptions, timeOptions
Expand Down Expand Up @@ -242,14 +242,16 @@ function DropdownComponent() {

const showCredits = () => setDialog({title: "MySpeed", description: creditsInfo(), buttonText: t("dialog.close")});

const showProviderDetails = () => setDialog({title: t("dropdown.provider"), description: config.previewMessage, buttonText: t("dialog.close")});

const options = [
{run: updatePing, icon: faPingPongPaddleBall, text: t("dropdown.ping")},
{run: updateUpload, icon: faArrowUp, text: t("dropdown.upload")},
{run: updateDownload, icon: faArrowDown, text: t("dropdown.download")},
{run: recommendedSettings, icon: faWandMagicSparkles, text: t("dropdown.recommendations")},
{hr: true, key: 1},
{run: updateServer, icon: faServer, text: t("dropdown.server")},
{run: updatePassword, icon: faKey, text: t("dropdown.password")},
{run: updatePassword, icon: faKey, text: t("dropdown.password"), previewHidden: true},
{run: updateCron, icon: faClock, text: t("dropdown.cron")},
{run: updateTime, icon: faCalendarDays, text: t("dropdown.time"), allowView: true},
{run: exportDialog, icon: faFileExport, text: t("dropdown.export")},
Expand All @@ -258,7 +260,8 @@ function DropdownComponent() {
{hr: true, key: 2},
{run: updateLanguage, icon: faGlobeEurope, text: t("dropdown.language"), allowView: true},
{run: () => setShowViewDialog(true), icon: faChartSimple, allowView: true, text: t("dropdown.view")},
{run: showCredits, icon: faInfo, text: t("dropdown.info"), allowView: true}
{run: showCredits, icon: faInfo, text: t("dropdown.info"), allowView: true, previewHidden: true},
{run: showProviderDetails, icon: faInfo, text: t("dropdown.provider"), previewShown: true}
];

return (
Expand All @@ -270,6 +273,8 @@ function DropdownComponent() {
<h2>{t("dropdown.settings")}</h2>
<div className="dropdown-entries">
{options.map(entry => {
if (entry.previewHidden && config.previewMode) return;
if (entry.previewShown && !config.previewMode) return;
if (!config.viewMode || (config.viewMode && entry.allowView)) {
if (!entry.hr) {
return (<div className="dropdown-item" onClick={() => {
Expand Down
8 changes: 2 additions & 6 deletions client/src/common/components/Dropdown/utils/infos.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import {PROJECT_URL, PROJECT_WIKI} from "@/index";
import {WEB_URL} from "@/index";
import {Trans} from "react-i18next";
const HEALTHCHECKS_URL = "https://healthchecks.io/";
const CLI_URL = "https://www.speedtest.net/apps/cli";

export const healthChecksInfo = () => <Trans components={{HCLink: <a href={HEALTHCHECKS_URL} target="_blank"/>,
WIKILink: <a href={PROJECT_WIKI + "/instructions/settings"} target="_blank"/>}}>info.healthchecks</Trans>

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

export const recommendationsInfo = (ping, down, up) => <Trans components={{Bold: <span className="dialog-value" />}}
Expand Down
25 changes: 23 additions & 2 deletions client/src/common/components/Header/HeaderComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./styles.sass";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {
faCircleArrowUp,
faCircleArrowUp, faDownload,
faGaugeHigh,
faGear,
faLock,
Expand All @@ -18,6 +18,8 @@ import {t} from "i18next";
import {ConfigContext} from "@/common/contexts/Config";
import {LoadingDialog} from "@/common/components/LoadingDialog";
import {NodeContext} from "@/common/contexts/Node";
import {WEB_URL} from "@/index";
import {Trans} from "react-i18next";

function HeaderComponent(props) {
const findNode = useContext(NodeContext)[4];
Expand All @@ -35,6 +37,12 @@ function HeaderComponent(props) {
toggleDropdown(setIcon);
}

const showDemoDialog = () => setDialog({
title: t("preview.title"),
description: <Trans components={{Link: <a href={WEB_URL + "/install"} target="_blank" />}}>preview.description</Trans>,
buttonText: t("dialog.okay")
});

const showPasswordDialog = () => setDialog({
title: t("header.admin_login"),
placeholder: t("dialog.password.placeholder"),
Expand Down Expand Up @@ -70,6 +78,8 @@ function HeaderComponent(props) {
postRequest("/speedtests/run").then(updateTests).then(updateStatus).then(() => setStartedManually(false));
}

const openDownloadPage = () => window.open(WEB_URL + "/install", "_blank");

useEffect(() => {
if (Object.keys(config).length === 0) return;
async function updateVersion() {
Expand All @@ -90,7 +100,13 @@ function HeaderComponent(props) {
<header>
<LoadingDialog isOpen={startedManually}/>
<div className="header-main">
{config.viewMode ? <h2>{t("header.title")}</h2> : <h2 onClick={() => props.showNodePage(true)} className="h2-click"><FontAwesomeIcon icon={faServer} /> {getNodeName()}</h2>}
<div className="header-left">
{config.viewMode && <h2>{t("header.title")}</h2>}
{!config.viewMode && <h2 onClick={() => props.showNodePage(true)} className="h2-click"><FontAwesomeIcon icon={faServer} /> {getNodeName()}</h2>}

{config.previewMode && <h2 className="demo-info" onClick={showDemoDialog}>{t("preview.info")}</h2>}
</div>


<div className="header-right">
{updateAvailable ?
Expand All @@ -113,6 +129,11 @@ function HeaderComponent(props) {
<span className="tooltip">{t("header.admin_login")}</span>
</div> : <></>)}

{(config.previewMode ? <div className="tooltip-element tooltip-bottom">
<FontAwesomeIcon icon={faDownload} className={"header-icon"} onClick={openDownloadPage}/>
<span className="tooltip">{t("header.download")}</span>
</div> : <></>)}

<div className="tooltip-element tooltip-bottom" id="open-header">
<FontAwesomeIcon icon={icon} className="header-icon" onClick={switchDropdown}/>
<span className="tooltip">{t("dropdown.settings")}</span>
Expand Down
62 changes: 50 additions & 12 deletions client/src/common/components/Header/styles.sass
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@import "@/common/styles/colors"

.header-main
margin-top: 2rem
margin-top: 3rem
display: flex
align-items: center
justify-content: space-between
Expand All @@ -16,18 +16,40 @@
.header-main *
font-size: 24pt

.header-main h2
.header-left
margin-left: 10%
display: flex
gap: 1rem
gap: 0.5rem
align-items: center
justify-content: center
overflow: hidden
text-overflow: ellipsis

.demo-info
display: flex
cursor: pointer
align-items: center
justify-content: center
font-size: 14pt
background-color: $dark-gray
color: $green
margin: 0

.header-main h2
padding: 0.5rem 1rem
border-radius: 1rem
margin: 0

.header-main .h2-click
display: flex
gap: 1rem
align-items: center
cursor: pointer
user-select: none

svg
margin-right: 0.3rem

.header-main .h2-click:hover
color: $green-hover
background-color: $dark-gray
Expand All @@ -37,6 +59,8 @@

.header-icon
cursor: pointer
display: flex

transition: all 50ms ease-in-out
width: 30px
height: 30px
Expand Down Expand Up @@ -68,24 +92,38 @@
100%
box-shadow: 0 0 0 0 #CCA92C00

@media (max-width: 460px)
@media screen and (max-width: 650px)
.header-left
flex-direction: column

@media (max-width: 530px)
.header-main
justify-content: center
.header-main div
.header-left div
margin-right: 0
.header-main h2
.header-left .h2-click
margin-left: 0
font-size: 24pt
font-size: 22pt
.header-icon
width: 25px
height: 25px


@media (max-width: 360px)
.header-main h2
font-size: 16pt
@media (max-width: 480px)
.header-left .h2-click
font-size: 14pt
text-overflow: ellipsis
overflow: hidden
.header-left svg
font-size: 14pt
.header-icon
width: 20px
height: 20px
height: 20px

@media screen and (max-width: 365px)
.header-main .h2-click
gap: 0
.header-left svg
margin-right: 0
.demo-info
font-size: 12pt
padding: 0
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import {DialogContext, DialogProvider} from "@/common/contexts/Dialog";
import "./styles.sass";
import React, {useContext, useEffect, useState} from "react";
import {t} from "i18next";
import {faClose} from "@fortawesome/free-solid-svg-icons";
import {faClose, faExclamationTriangle} from "@fortawesome/free-solid-svg-icons";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {jsonRequest} from "@/common/utils/RequestUtil";
import IntegrationItem from "@/common/components/IntegrationDialog/components/IntegrationItem";
import {v4 as uuid} from 'uuid';
import AvailableIntegrations from "./components/AvailableIntegrations";
import IntegrationAddButton from "@/common/components/IntegrationDialog/components/IntegrationAddButton";
import NoIntegrationsTab from "@/common/components/IntegrationDialog/components/NoIntegrationsTab";
import {ConfigContext} from "@/common/contexts/Config";

export const Dialog = ({integrations, active, setActive}) => {
const close = useContext(DialogContext);
const [config] = useContext(ConfigContext);
const [currentTab, setCurrentTab] = useState(integrations[Object.keys(integrations)[0]].name);

const addIntegration = () => setActive([...active, {uuid: uuid(), name: currentTab,
Expand All @@ -31,6 +33,12 @@ export const Dialog = ({integrations, active, setActive}) => {
setCurrentTab={setCurrentTab}/>

<div className="integrations-tab">
{config.previewMode && active.filter(item => item.name === currentTab).length > 0
&& <div className="pr-integration-container">
<FontAwesomeIcon icon={faExclamationTriangle} />
<p>{t("integrations.preview_active")}</p>
</div>}

{active.map((item) => (item.name !== currentTab ? undefined :
<IntegrationItem integration={integrations[currentTab]}
remove={() => deleteIntegration(item.uuid)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import {
faTrashArrowUp
} from "@fortawesome/free-solid-svg-icons";
import "./styles.sass";
import {useEffect, useState} from "react";
import {useContext, useEffect, useState} from "react";
import {ConfigContext} from "@/common/contexts/Config";

export const IntegrationItemHeader = ({integration, displayName, unsavedChanges, changesConfirmed, saveIntegration,
deleteConfirmed, deleteIntegration, open, setOpen, data}) => {
const [lastActivity, setLastActivity] = useState(generateRelativeTime(data.lastActivity));
const [config] = useContext(ConfigContext);

useEffect(() => {
const interval = setInterval(() => {
Expand All @@ -40,11 +42,11 @@ export const IntegrationItemHeader = ({integration, displayName, unsavedChanges,
</div>
</div>
<div className="integration-item-right">
{unsavedChanges && !changesConfirmed && <FontAwesomeIcon icon={faFloppyDisk} onClick={saveIntegration}
{!config.previewMode && unsavedChanges && !changesConfirmed && <FontAwesomeIcon icon={faFloppyDisk} onClick={saveIntegration}
className="integration-green"/>}
{changesConfirmed && <FontAwesomeIcon icon={faCheck} className="icon-green"/>}

{!deleteConfirmed &&
{!config.previewMode && !deleteConfirmed &&
<FontAwesomeIcon icon={faTrash} className="integration-red" onClick={deleteIntegration}/>}
{deleteConfirmed &&
<FontAwesomeIcon icon={faTrashArrowUp} className="integration-red" onClick={deleteIntegration}/>}
Expand Down
15 changes: 15 additions & 0 deletions client/src/common/components/IntegrationDialog/styles.sass
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
overflow-x: clip
width: 70%

.pr-integration-container
display: flex
gap: 0.5rem
align-items: center
justify-content: center
padding: 0.5rem
border-radius: 0.5rem
border: 2px solid $red
color: $red
font-size: 1.25rem

p
margin: 0
font-weight: 500

@media (max-width: 781px)
.integration-dialog
width: 90vw
Expand Down
1 change: 1 addition & 0 deletions client/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ReactDOM from "react-dom/client";
import App from './App';

export const PROJECT_URL = "https://github.com/gnmyt/myspeed";
export const WEB_URL = "https://myspeed.dev";
export const PROJECT_WIKI = "https://docs.myspeed.dev";

const root = ReactDOM.createRoot(document.getElementById('root'));
Expand Down
Loading

0 comments on commit ee03467

Please sign in to comment.