2021-08-24 18:29:37 +02:00
|
|
|
/*
|
|
|
|
This file is part of TALER
|
|
|
|
(C) 2016 GNUnet e.V.
|
|
|
|
|
|
|
|
TALER is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
TALER 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
2022-03-14 19:20:32 +01:00
|
|
|
import * as utils from "@gnu-taler/taler-util";
|
2021-11-15 15:18:58 +01:00
|
|
|
import {
|
|
|
|
ProviderInfo,
|
|
|
|
ProviderPaymentStatus,
|
|
|
|
ProviderPaymentType,
|
|
|
|
} from "@gnu-taler/taler-wallet-core";
|
2021-11-16 17:59:53 +01:00
|
|
|
import { Fragment, h, VNode } from "preact";
|
2021-08-24 18:29:37 +02:00
|
|
|
import { ErrorMessage } from "../components/ErrorMessage";
|
2022-02-23 19:18:37 +01:00
|
|
|
import { Loading } from "../components/Loading";
|
|
|
|
import { LoadingError } from "../components/LoadingError";
|
2021-11-15 15:18:58 +01:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
ButtonDestructive,
|
|
|
|
ButtonPrimary,
|
|
|
|
PaymentStatus,
|
|
|
|
SmallLightText,
|
|
|
|
} from "../components/styled";
|
2021-11-16 17:59:53 +01:00
|
|
|
import { Time } from "../components/Time";
|
2022-03-14 19:20:32 +01:00
|
|
|
import { useTranslationContext } from "../context/translation";
|
2021-11-19 18:51:27 +01:00
|
|
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
|
|
|
import * as wxApi from "../wxApi";
|
2021-08-24 18:29:37 +02:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
pid: string;
|
|
|
|
onBack: () => void;
|
|
|
|
}
|
|
|
|
|
2021-11-19 18:51:27 +01:00
|
|
|
export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
|
2022-03-14 19:20:32 +01:00
|
|
|
const { i18n } = useTranslationContext();
|
2021-11-19 18:51:27 +01:00
|
|
|
async function getProviderInfo(): Promise<ProviderInfo | null> {
|
|
|
|
//create a first list of backup info by currency
|
|
|
|
const status = await wxApi.getBackupInfo();
|
|
|
|
|
|
|
|
const providers = status.providers.filter(
|
|
|
|
(p) => p.syncProviderBaseUrl === providerURL,
|
|
|
|
);
|
|
|
|
return providers.length ? providers[0] : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const state = useAsyncAsHook(getProviderInfo);
|
|
|
|
|
|
|
|
if (!state) {
|
2022-02-23 19:18:37 +01:00
|
|
|
return <Loading />;
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
2021-11-19 18:51:27 +01:00
|
|
|
if (state.hasError) {
|
|
|
|
return (
|
2022-02-23 19:18:37 +01:00
|
|
|
<LoadingError
|
|
|
|
title={
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>
|
2022-02-23 19:18:37 +01:00
|
|
|
There was an error loading the provider detail for "{providerURL}"
|
2022-02-23 19:44:14 +01:00
|
|
|
</i18n.Translate>
|
2022-02-23 19:18:37 +01:00
|
|
|
}
|
|
|
|
error={state}
|
|
|
|
/>
|
2021-11-19 18:51:27 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-11-15 15:18:58 +01:00
|
|
|
return (
|
|
|
|
<ProviderView
|
2022-02-23 19:18:37 +01:00
|
|
|
url={providerURL}
|
2021-11-19 18:51:27 +01:00
|
|
|
info={state.response}
|
|
|
|
onSync={async () => wxApi.syncOneProvider(providerURL)}
|
2022-02-01 17:26:56 +01:00
|
|
|
onDelete={async () => wxApi.removeProvider(providerURL).then(onBack)}
|
2021-11-15 15:18:58 +01:00
|
|
|
onBack={onBack}
|
|
|
|
onExtend={() => {
|
|
|
|
null;
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ViewProps {
|
2022-02-23 19:18:37 +01:00
|
|
|
url: string;
|
|
|
|
info: ProviderInfo | null;
|
2021-08-24 18:29:37 +02:00
|
|
|
onDelete: () => void;
|
|
|
|
onSync: () => void;
|
|
|
|
onBack: () => void;
|
|
|
|
onExtend: () => void;
|
|
|
|
}
|
|
|
|
|
2021-11-15 15:18:58 +01:00
|
|
|
export function ProviderView({
|
|
|
|
info,
|
2022-02-23 19:18:37 +01:00
|
|
|
url,
|
2021-11-15 15:18:58 +01:00
|
|
|
onDelete,
|
|
|
|
onSync,
|
|
|
|
onBack,
|
|
|
|
onExtend,
|
|
|
|
}: ViewProps): VNode {
|
2022-03-14 19:20:32 +01:00
|
|
|
const { i18n } = useTranslationContext();
|
2022-02-23 19:18:37 +01:00
|
|
|
if (info === null) {
|
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
<section>
|
|
|
|
<p>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>
|
|
|
|
There is not known provider with url "{url}".
|
|
|
|
</i18n.Translate>
|
2022-02-23 19:18:37 +01:00
|
|
|
</p>
|
|
|
|
</section>
|
|
|
|
<footer>
|
|
|
|
<Button onClick={onBack}>
|
2022-02-23 19:44:14 +01:00
|
|
|
< <i18n.Translate>Back</i18n.Translate>
|
2022-02-23 19:18:37 +01:00
|
|
|
</Button>
|
|
|
|
<div />
|
|
|
|
</footer>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
const lb = info.lastSuccessfulBackupTimestamp;
|
2021-11-15 15:18:58 +01:00
|
|
|
const isPaid =
|
|
|
|
info.paymentStatus.type === ProviderPaymentType.Paid ||
|
|
|
|
info.paymentStatus.type === ProviderPaymentType.TermsChanged;
|
2021-08-24 18:29:37 +02:00
|
|
|
return (
|
2021-11-19 18:51:27 +01:00
|
|
|
<Fragment>
|
2021-08-24 20:16:11 +02:00
|
|
|
<Error info={info} />
|
2021-08-24 18:29:37 +02:00
|
|
|
<header>
|
2021-11-15 15:18:58 +01:00
|
|
|
<h3>
|
|
|
|
{info.name}{" "}
|
|
|
|
<SmallLightText>{info.syncProviderBaseUrl}</SmallLightText>
|
|
|
|
</h3>
|
|
|
|
<PaymentStatus color={isPaid ? "rgb(28, 184, 65)" : "rgb(202, 60, 60)"}>
|
|
|
|
{isPaid ? "Paid" : "Unpaid"}
|
|
|
|
</PaymentStatus>
|
2021-08-24 18:29:37 +02:00
|
|
|
</header>
|
|
|
|
<section>
|
2021-11-15 15:18:58 +01:00
|
|
|
<p>
|
2022-02-23 19:18:37 +01:00
|
|
|
<b>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Last backup</i18n.Translate>:
|
2022-02-23 19:18:37 +01:00
|
|
|
</b>{" "}
|
|
|
|
<Time timestamp={lb} format="dd MMMM yyyy" />
|
2021-11-15 15:18:58 +01:00
|
|
|
</p>
|
|
|
|
<ButtonPrimary onClick={onSync}>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Back up</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</ButtonPrimary>
|
|
|
|
{info.terms && (
|
|
|
|
<Fragment>
|
|
|
|
<p>
|
2022-02-23 19:18:37 +01:00
|
|
|
<b>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Provider fee</i18n.Translate>:
|
2022-02-23 19:18:37 +01:00
|
|
|
</b>{" "}
|
|
|
|
{info.terms && info.terms.annualFee}{" "}
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>per year</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</p>
|
|
|
|
</Fragment>
|
|
|
|
)}
|
2022-03-14 19:20:32 +01:00
|
|
|
<p>{descriptionByStatus(info.paymentStatus, i18n)}</p>
|
2021-11-15 15:18:58 +01:00
|
|
|
<ButtonPrimary disabled onClick={onExtend}>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Extend</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</ButtonPrimary>
|
2021-08-24 18:29:37 +02:00
|
|
|
|
2021-11-15 15:18:58 +01:00
|
|
|
{info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
|
|
|
|
<div>
|
|
|
|
<p>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
terms has changed, extending the service will imply accepting
|
|
|
|
the new terms of service
|
2022-02-23 19:44:14 +01:00
|
|
|
</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</p>
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
2021-11-16 17:59:53 +01:00
|
|
|
<td> </td>
|
2021-11-15 15:18:58 +01:00
|
|
|
<td>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>old</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</td>
|
|
|
|
<td> -></td>
|
|
|
|
<td>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>new</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<td>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>fee</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</td>
|
|
|
|
<td>{info.paymentStatus.oldTerms.annualFee}</td>
|
|
|
|
<td>-></td>
|
|
|
|
<td>{info.paymentStatus.newTerms.annualFee}</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>storage</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</td>
|
|
|
|
<td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
|
|
|
|
<td>-></td>
|
|
|
|
<td>{info.paymentStatus.newTerms.storageLimitInMegabytes}</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
)}
|
2021-08-24 18:29:37 +02:00
|
|
|
</section>
|
|
|
|
<footer>
|
2021-11-15 15:18:58 +01:00
|
|
|
<Button onClick={onBack}>
|
2022-02-23 19:44:14 +01:00
|
|
|
< <i18n.Translate>back</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</Button>
|
2021-08-24 18:29:37 +02:00
|
|
|
<div>
|
2021-11-15 15:18:58 +01:00
|
|
|
<ButtonDestructive onClick={onDelete}>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Remove provider</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</ButtonDestructive>
|
2021-08-24 18:29:37 +02:00
|
|
|
</div>
|
|
|
|
</footer>
|
2021-11-19 18:51:27 +01:00
|
|
|
</Fragment>
|
2021-11-15 15:18:58 +01:00
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
|
2021-11-16 17:59:53 +01:00
|
|
|
function Error({ info }: { info: ProviderInfo }): VNode {
|
2022-03-14 19:20:32 +01:00
|
|
|
const { i18n } = useTranslationContext();
|
2021-08-24 18:29:37 +02:00
|
|
|
if (info.lastError) {
|
2022-02-23 19:18:37 +01:00
|
|
|
return (
|
|
|
|
<ErrorMessage
|
2022-02-23 19:44:14 +01:00
|
|
|
title={
|
|
|
|
<i18n.Translate>This provider has reported an error</i18n.Translate>
|
|
|
|
}
|
2022-02-23 19:18:37 +01:00
|
|
|
description={info.lastError.hint}
|
|
|
|
/>
|
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
if (info.backupProblem) {
|
|
|
|
switch (info.backupProblem.type) {
|
|
|
|
case "backup-conflicting-device":
|
2021-11-15 15:18:58 +01:00
|
|
|
return (
|
|
|
|
<ErrorMessage
|
|
|
|
title={
|
|
|
|
<Fragment>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
There is conflict with another backup from{" "}
|
|
|
|
<b>{info.backupProblem.otherDeviceId}</b>
|
2022-02-23 19:44:14 +01:00
|
|
|
</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</Fragment>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
case "backup-unreadable":
|
2022-02-23 19:18:37 +01:00
|
|
|
return (
|
2022-02-23 19:44:14 +01:00
|
|
|
<ErrorMessage
|
|
|
|
title={<i18n.Translate>Backup is not readable</i18n.Translate>}
|
|
|
|
/>
|
2022-02-23 19:18:37 +01:00
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
default:
|
2021-11-15 15:18:58 +01:00
|
|
|
return (
|
|
|
|
<ErrorMessage
|
|
|
|
title={
|
|
|
|
<Fragment>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
Unknown backup problem: {JSON.stringify(info.backupProblem)}
|
2022-02-23 19:44:14 +01:00
|
|
|
</i18n.Translate>
|
2021-11-15 15:18:58 +01:00
|
|
|
</Fragment>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
}
|
2021-11-16 17:59:53 +01:00
|
|
|
return <Fragment />;
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
|
2022-03-14 19:20:32 +01:00
|
|
|
function descriptionByStatus(
|
|
|
|
status: ProviderPaymentStatus,
|
|
|
|
i18n: typeof utils.i18n,
|
|
|
|
): VNode {
|
2021-08-24 18:29:37 +02:00
|
|
|
switch (status.type) {
|
|
|
|
case ProviderPaymentType.Paid:
|
|
|
|
case ProviderPaymentType.TermsChanged:
|
2021-11-15 15:18:58 +01:00
|
|
|
if (status.paidUntil.t_ms === "never") {
|
2022-02-23 19:18:37 +01:00
|
|
|
return (
|
|
|
|
<span>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>service paid</i18n.Translate>
|
2022-02-23 19:18:37 +01:00
|
|
|
</span>
|
|
|
|
);
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
2021-11-16 17:59:53 +01:00
|
|
|
return (
|
|
|
|
<Fragment>
|
2022-02-23 19:18:37 +01:00
|
|
|
<b>
|
2022-02-23 19:44:14 +01:00
|
|
|
<i18n.Translate>Backup valid until</i18n.Translate>:
|
2022-02-23 19:18:37 +01:00
|
|
|
</b>{" "}
|
2021-11-16 17:59:53 +01:00
|
|
|
<Time timestamp={status.paidUntil} format="dd MMM yyyy" />
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
|
2021-08-24 18:29:37 +02:00
|
|
|
case ProviderPaymentType.Unpaid:
|
|
|
|
case ProviderPaymentType.InsufficientBalance:
|
|
|
|
case ProviderPaymentType.Pending:
|
2021-11-16 17:59:53 +01:00
|
|
|
return <span />;
|
2021-08-24 18:29:37 +02:00
|
|
|
}
|
|
|
|
}
|