Files
SCM-Manager/scm-ui/ui-webapp/src/repos/containers/ExportRepository.tsx
2024-09-24 09:42:07 +02:00

183 lines
5.5 KiB
TypeScript

/*
* Copyright (c) 2020 - present Cloudogu GmbH
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React, { FC, useEffect, useState } from "react";
import {
Button,
ButtonGroup,
Checkbox,
DateFromNow,
ErrorNotification,
InputField,
Level,
Notification,
Subtitle
} from "@scm-manager/ui-components";
import { useTranslation } from "react-i18next";
import { ExportInfo, Link, Repository } from "@scm-manager/ui-types";
import { useExportInfo, useExportRepository } from "@scm-manager/ui-api";
import styled from "styled-components";
import classNames from "classnames";
const InfoBox = styled.div`
white-space: pre-line;
border-radius: 2px;
border-left: 0.2rem solid;
border-color: var(--scm-info-color);
`;
type Props = {
repository: Repository;
};
const ExportInterruptedNotification = () => {
const [t] = useTranslation("repos");
return <Notification type="warning">{t("export.exportInfo.interrupted")}</Notification>;
};
const ExportInfoBox: FC<{ exportInfo: ExportInfo }> = ({ exportInfo }) => {
const [t] = useTranslation("repos");
return (
<InfoBox className={classNames("my-4", "p-4", "has-background-info-25", "repository-export-info-box")}>
<strong>{t("export.exportInfo.infoBoxTitle")}</strong>
<p>{t("export.exportInfo.exporter", { username: exportInfo.exporterName })}</p>
<p>
{t("export.exportInfo.created")}
<DateFromNow date={exportInfo.created} />
</p>
<br />
<p>{exportInfo.withMetadata ? t("export.exportInfo.repositoryArchive") : t("export.exportInfo.repository")}</p>
{exportInfo.encrypted && (
<>
<br />
<p>{t("export.exportInfo.encrypted")}</p>
</>
)}
</InfoBox>
);
};
const ExportRepository: FC<Props> = ({ repository }) => {
const [t] = useTranslation("repos");
const [compressed, setCompressed] = useState(true);
const [fullExport, setFullExport] = useState(false);
const [encrypt, setEncrypt] = useState(false);
const [password, setPassword] = useState("");
const { isLoading: isLoadingInfo, error: errorInfo, data: exportInfo } = useExportInfo(repository);
const {
isLoading: isLoadingExport,
error: errorExport,
data: exportedInfo,
exportRepository
} = useExportRepository();
useEffect(() => {
if (exportedInfo && exportedInfo?._links.download) {
window.location.href = (exportedInfo?._links.download as Link).href;
}
}, [exportedInfo]);
if (!repository._links.export) {
return null;
}
const renderExportInfo = () => {
if (!exportInfo) {
return null;
}
if (exportInfo.status === "INTERRUPTED") {
return <ExportInterruptedNotification />;
} else {
return <ExportInfoBox exportInfo={exportInfo} />;
}
};
const downloadLink = (exportInfo?._links.download as Link)?.href;
return (
<>
<hr />
<Subtitle subtitle={t("export.subtitle")} />
<ErrorNotification error={errorInfo} />
<ErrorNotification error={errorExport} />
<Notification type="inherit">{t("export.notification")}</Notification>
<Checkbox
checked={fullExport || compressed}
label={t("export.compressed.label")}
onChange={setCompressed}
helpText={t("export.compressed.helpText")}
disabled={fullExport}
/>
{repository?._links?.fullExport && (
<Checkbox
checked={fullExport}
label={t("export.fullExport.label")}
onChange={setFullExport}
helpText={t("export.fullExport.helpText")}
/>
)}
<Checkbox
checked={encrypt}
label={t("export.encrypt.label")}
onChange={setEncrypt}
helpText={t("export.encrypt.helpText")}
/>
{encrypt && (
<div className={classNames("columns", "column", "is-half")}>
<InputField
label={t("export.password.label")}
helpText={t("export.password.helpText")}
value={password}
onChange={setPassword}
type="password"
/>
</div>
)}
{renderExportInfo()}
<Level
right={
<ButtonGroup>
<Button
label={t("export.downloadExportButton")}
icon="download"
link={downloadLink}
color="info"
disabled={isLoadingInfo || isLoadingExport || !downloadLink}
/>
<Button
color="primary"
action={() =>
exportRepository(repository, {
compressed,
password: encrypt ? password : "",
withMetadata: fullExport
})
}
loading={isLoadingInfo || isLoadingExport}
disabled={isLoadingInfo || isLoadingExport}
label={t("export.createExportButton")}
icon="file-export"
/>
</ButtonGroup>
}
/>
</>
);
};
export default ExportRepository;