chore: update storage components (#1091)

This commit is contained in:
boojack 2023-02-14 22:45:22 +08:00 committed by GitHub
parent 2493bb0fb7
commit 3394380ffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 231 deletions

View File

@ -2,14 +2,16 @@ import { useTranslation } from "react-i18next";
import Icon from "./Icon";
import { generateDialog } from "./Dialog";
import { Button, Input, Typography } from "@mui/joy";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useStorageStore } from "../store/module";
import toastHelper from "./Toast";
type Props = DialogProps;
interface Props extends DialogProps {
storage?: Storage;
}
const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
const { destroy } = props;
const { destroy, storage } = props;
const { t } = useTranslation();
const storageStore = useStorageStore();
const [storageCreate, setStorageCreate] = useState<StorageCreate>({
@ -21,6 +23,13 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
bucket: "",
urlPrefix: "",
});
const isCreating = storage === undefined;
useEffect(() => {
if (storage) {
setStorageCreate({ ...storage });
}
}, []);
const handleCloseBtnClick = () => {
destroy();
@ -42,7 +51,14 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
const handleConfirmBtnClick = async () => {
try {
await storageStore.createStorage(storageCreate);
if (isCreating) {
await storageStore.createStorage(storageCreate);
} else {
await storageStore.patchStorage({
id: storage.id,
...storageCreate,
});
}
} catch (error: any) {
console.error(error);
toastHelper.error(error.response.data.message);
@ -109,7 +125,9 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
return (
<>
<div className="dialog-header-container !w-64">
<p className="title-text">{t("setting.storage-section.create-a-service")}</p>
<p className="title-text">
{isCreating ? t("setting.storage-section.create-a-service") : t("setting.storage-section.update-a-service")}
</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<Icon.X />
</button>
@ -148,7 +166,7 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
Cancel
</Button>
<Button onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
Create
{isCreating ? "Create" : "Update"}
</Button>
</div>
</div>
@ -156,13 +174,14 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
);
};
function showCreateStorageServiceDialog() {
function showCreateStorageServiceDialog(storage?: Storage) {
generateDialog(
{
className: "create-storage-service-dialog",
dialogName: "create-storage-service-dialog",
},
CreateStorageServiceDialog
CreateStorageServiceDialog,
{ storage }
);
}

View File

@ -58,12 +58,6 @@ const SettingDialog: React.FC<Props> = (props: Props) => {
<>
<span className="section-title">{t("common.admin")}</span>
<div className="section-items-container">
<span
onClick={() => handleSectionSelectorItemClick("storage")}
className={`section-item ${state.selectedSection === "storage" ? "selected" : ""}`}
>
<span className="icon-text">🗃</span> {t("setting.storage")}
</span>
<span
onClick={() => handleSectionSelectorItemClick("member")}
className={`section-item ${state.selectedSection === "member" ? "selected" : ""}`}
@ -76,6 +70,12 @@ const SettingDialog: React.FC<Props> = (props: Props) => {
>
<span className="icon-text">🛠</span> {t("setting.system")}
</span>
<span
onClick={() => handleSectionSelectorItemClick("storage")}
className={`section-item ${state.selectedSection === "storage" ? "selected" : ""}`}
>
<span className="icon-text">💾</span> {t("setting.storage")}
</span>
</div>
</>
) : null}

View File

@ -4,8 +4,6 @@ import { useTranslation } from "react-i18next";
import { useGlobalStore, useStorageStore } from "../../store/module";
import * as api from "../../helpers/api";
import showCreateStorageServiceDialog from "../CreateStorageServiceDialog";
import showUpdateStorageServiceDialog from "../UpdateStorageServiceDialog";
import "../../less/settings/storage-section.less";
const StorageSection = () => {
const { t } = useTranslation();
@ -35,29 +33,29 @@ const StorageSection = () => {
const handleStorageServiceUpdate = async (event: React.MouseEvent, storage: Storage) => {
event.preventDefault();
showUpdateStorageServiceDialog(storage);
showCreateStorageServiceDialog(storage);
};
return (
<div className="section-container storage-section-container">
<p className="title-text">{t("setting.storage-section.storage-services-list")}</p>
<div className="section-container">
<div className="mt-4 mb-2 w-full flex flex-row justify-start items-center">
<span className="font-mono text-sm text-gray-400 mr-2">{t("setting.storage-section.storage-services-list")}</span>
<button className="btn-normal px-2 py-0 leading-7" onClick={() => showCreateStorageServiceDialog()}>
{t("common.create")}
</button>
</div>
{storages.map((storage) => (
<label className="form-label selector" key={storage.id}>
<span className="normal-text underline cursor-pointer" onClick={(event) => handleStorageServiceUpdate(event, storage)}>
<label className="w-full my-2 flex flex-row justify-between items-center" key={storage.id}>
<span className="mr-2 text-sm underline cursor-pointer" onClick={(event) => handleStorageServiceUpdate(event, storage)}>
{storage.name}
</span>
<Radio value={storage.id} checked={storageServiceId === storage.id} onChange={handleActiveStorageServiceChanged} />
</label>
))}
<label className="form-label selector">
<span className="normal-text">{t("common.database")}</span>
<label className="w-full my-2 flex flex-row justify-between items-center">
<span className="mr-2 text-sm">{t("common.database")}</span>
<Radio value={0} checked={storageServiceId === 0} onChange={handleActiveStorageServiceChanged} />
</label>
<div className="w-full flex flex-row justify-end items-center mt-2 space-x-2">
<button className="btn-normal" onClick={showCreateStorageServiceDialog}>
{t("setting.storage-section.create-a-service")}
</button>
</div>
</div>
);
};

View File

@ -1,189 +0,0 @@
import { Button, Input, Typography } from "@mui/joy";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import Icon from "./Icon";
import { generateDialog } from "./Dialog";
import { showCommonDialog } from "./Dialog/CommonDialog";
import { useStorageStore } from "../store/module";
import toastHelper from "./Toast";
interface Props extends DialogProps {
storage: StoragePatch;
}
const UpdateStorageServiceDialog: React.FC<Props> = (props: Props) => {
const { storage, destroy } = props;
const { t } = useTranslation();
const storageStore = useStorageStore();
const [storagePatch, setStoragePatch] = useState<StoragePatch>(storage);
const handleCloseBtnClick = () => {
destroy();
};
const allowConfirmAction = () => {
if (
storagePatch.name === "" ||
storagePatch.endPoint === "" ||
storagePatch.region === "" ||
storagePatch.accessKey === "" ||
storagePatch.bucket === "" ||
storagePatch.bucket === ""
) {
return false;
}
return true;
};
const handleConfirmBtnClick = async () => {
try {
await storageStore.patchStorage(storagePatch);
} catch (error: any) {
console.error(error);
toastHelper.error(error.response.data.message);
}
destroy();
};
const handleDeleteBtnClick = async () => {
const warningText = t("setting.storage-section.warning-text");
showCommonDialog({
title: t("setting.storage-section.delete-storage"),
content: warningText,
style: "warning",
dialogName: "delete-storage-dialog",
onConfirm: async () => {
try {
await storageStore.deleteStorageById(storagePatch.id);
} catch (error: any) {
console.error(error);
toastHelper.error(error.response.data.message);
}
destroy();
},
});
};
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const name = event.target.value;
setStoragePatch({
...storagePatch,
name,
});
};
const handleEndPointChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const endPoint = event.target.value;
setStoragePatch({
...storagePatch,
endPoint,
});
};
const handleRegionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const region = event.target.value;
setStoragePatch({
...storagePatch,
region,
});
};
const handleAccessKeyChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const accessKey = event.target.value;
setStoragePatch({
...storagePatch,
accessKey,
});
};
const handleSecretKeyChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const secretKey = event.target.value;
setStoragePatch({
...storagePatch,
secretKey,
});
};
const handleBucketChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const bucket = event.target.value;
setStoragePatch({
...storagePatch,
bucket,
});
};
const handleURLPrefixChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const urlPrefix = event.target.value;
setStoragePatch({
...storagePatch,
urlPrefix,
});
};
return (
<>
<div className="dialog-header-container !w-64">
<p className="title-text">{t("setting.storage-section.update-a-service")}</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<Icon.X />
</button>
</div>
<div className="dialog-content-container">
<Typography className="!mb-1" level="body2">
Name
</Typography>
<Input className="mb-2" placeholder="Name" value={storagePatch.name} onChange={handleNameChange} fullWidth />
<Typography className="!mb-1" level="body2">
EndPoint
</Typography>
<Input className="mb-2" placeholder="EndPoint" value={storagePatch.endPoint} onChange={handleEndPointChange} fullWidth />
<Typography className="!mb-1" level="body2">
Region
</Typography>
<Input className="mb-2" placeholder="Region" value={storagePatch.region} onChange={handleRegionChange} fullWidth />
<Typography className="!mb-1" level="body2">
AccessKey
</Typography>
<Input className="mb-2" placeholder="AccessKey" value={storagePatch.accessKey} onChange={handleAccessKeyChange} fullWidth />
<Typography className="!mb-1" level="body2">
SecretKey
</Typography>
<Input className="mb-2" placeholder="SecretKey" value={storagePatch.secretKey} onChange={handleSecretKeyChange} fullWidth />
<Typography className="!mb-1" level="body2">
Bucket
</Typography>
<Input className="mb-2" placeholder="Bucket" value={storagePatch.bucket} onChange={handleBucketChange} fullWidth />
<Typography className="!mb-1" level="body2">
URLPrefix
</Typography>
<Input className="mb-2" placeholder="URLPrefix" value={storagePatch.urlPrefix} onChange={handleURLPrefixChange} fullWidth />
<div className="mt-2 w-full flex flex-row justify-between items-center space-x-1">
<Button color="danger" onClick={handleDeleteBtnClick}>
Delete
</Button>
<div className="flex justify-end">
<Button variant="plain" color="neutral" onClick={handleCloseBtnClick}>
Cancel
</Button>
<Button onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
Update
</Button>
</div>
</div>
</div>
</>
);
};
function showUpdateStorageServiceDialog(storage: Storage) {
generateDialog(
{
className: "update-storage-service-dialog",
dialogName: "update-storage-service-dialog",
},
UpdateStorageServiceDialog,
{ storage }
);
}
export default showUpdateStorageServiceDialog;

View File

@ -1,14 +0,0 @@
.storage-section-container {
> .title-text {
@apply mt-4 first:mt-1;
}
> .form-label.selector {
@apply mb-2 flex flex-row justify-between items-center;
> .normal-text {
@apply mr-2 text-sm;
}
}
}