mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-03 20:15:52 +01:00
183 lines
5.5 KiB
TypeScript
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;
|