2023-02-07 11:29:52 +00:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
DataList,
|
|
|
|
DataListAction,
|
|
|
|
DataListCell,
|
|
|
|
DataListItem,
|
|
|
|
DataListItemCells,
|
|
|
|
DataListItemRow,
|
|
|
|
Dropdown,
|
|
|
|
DropdownItem,
|
|
|
|
KebabToggle,
|
|
|
|
PageSection,
|
|
|
|
Spinner,
|
|
|
|
Split,
|
|
|
|
SplitItem,
|
|
|
|
Title,
|
|
|
|
} from "@patternfly/react-core";
|
2023-02-07 12:05:31 +00:00
|
|
|
import { CSSProperties, useState } from "react";
|
|
|
|
import { Trans, useTranslation } from "react-i18next";
|
|
|
|
import { ContinueCancelModal, useAlerts } from "ui-shared";
|
2023-02-07 11:29:52 +00:00
|
|
|
import { deleteCredentials, getCredentials } from "../api/methods";
|
|
|
|
import {
|
|
|
|
CredentialContainer,
|
|
|
|
CredentialMetadataRepresentation,
|
|
|
|
CredentialRepresentation,
|
|
|
|
} from "../api/representations";
|
2023-02-16 15:29:28 +00:00
|
|
|
import { EmptyRow } from "../components/datalist/EmptyRow";
|
2023-02-07 11:29:52 +00:00
|
|
|
import { Page } from "../components/page/Page";
|
2023-06-19 14:59:21 +00:00
|
|
|
import { TFuncKey } from "../i18n";
|
2023-02-07 11:29:52 +00:00
|
|
|
import { keycloak } from "../keycloak";
|
2023-07-19 09:51:39 +00:00
|
|
|
import { formatDate } from "../utils/formatDate";
|
2023-02-07 11:29:52 +00:00
|
|
|
import { usePromise } from "../utils/usePromise";
|
2022-10-10 10:14:19 +00:00
|
|
|
|
2023-02-07 11:29:52 +00:00
|
|
|
type MobileLinkProps = {
|
|
|
|
title: string;
|
|
|
|
onClick: () => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
const MobileLink = ({ title, onClick }: MobileLinkProps) => {
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Dropdown
|
|
|
|
isPlain
|
|
|
|
position="right"
|
|
|
|
toggle={<KebabToggle onToggle={setOpen} />}
|
|
|
|
className="pf-u-display-none-on-lg"
|
|
|
|
isOpen={open}
|
|
|
|
dropdownItems={[
|
|
|
|
<DropdownItem key="1" onClick={onClick}>
|
|
|
|
{title}
|
|
|
|
</DropdownItem>,
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
<Button
|
|
|
|
variant="link"
|
|
|
|
onClick={onClick}
|
|
|
|
className="pf-u-display-none pf-u-display-inline-flex-on-lg"
|
|
|
|
>
|
|
|
|
{title}
|
|
|
|
</Button>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const SigningIn = () => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const { addAlert, addError } = useAlerts();
|
|
|
|
const { login } = keycloak;
|
|
|
|
|
|
|
|
const [credentials, setCredentials] = useState<CredentialContainer[]>();
|
|
|
|
const [key, setKey] = useState(1);
|
|
|
|
const refresh = () => setKey(key + 1);
|
|
|
|
|
|
|
|
usePromise((signal) => getCredentials({ signal }), setCredentials, [key]);
|
|
|
|
|
|
|
|
const credentialRowCells = (
|
2023-07-11 14:03:21 +00:00
|
|
|
credMetadata: CredentialMetadataRepresentation,
|
2023-02-07 11:29:52 +00:00
|
|
|
) => {
|
|
|
|
const credential = credMetadata.credential;
|
|
|
|
const maxWidth = { "--pf-u-max-width--MaxWidth": "300px" } as CSSProperties;
|
|
|
|
const items = [
|
|
|
|
<DataListCell
|
|
|
|
id={`cred-${credMetadata.credential.id}`}
|
|
|
|
key="title"
|
|
|
|
className="pf-u-max-width"
|
|
|
|
style={maxWidth}
|
|
|
|
>
|
|
|
|
{credential.userLabel || t(credential.type as TFuncKey)}
|
|
|
|
</DataListCell>,
|
|
|
|
];
|
|
|
|
|
|
|
|
if (credential.createdDate) {
|
|
|
|
items.push(
|
|
|
|
<DataListCell key={"created" + credential.id}>
|
|
|
|
<Trans i18nKey="credentialCreatedAt">
|
|
|
|
<strong className="pf-u-mr-md"></strong>
|
|
|
|
{{ date: formatDate(new Date(credential.createdDate)) }}
|
|
|
|
</Trans>
|
2023-07-11 14:03:21 +00:00
|
|
|
</DataListCell>,
|
2023-02-07 11:29:52 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return items;
|
|
|
|
};
|
|
|
|
|
|
|
|
const label = (credential: CredentialRepresentation) =>
|
|
|
|
credential.userLabel || t(credential.type as TFuncKey);
|
|
|
|
|
|
|
|
if (!credentials) {
|
|
|
|
return <Spinner />;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Page title={t("signingIn")} description={t("signingInDescription")}>
|
|
|
|
<DataList aria-label="user credential" className="pf-u-mb-xl">
|
|
|
|
{credentials.map((container) => (
|
|
|
|
<PageSection
|
|
|
|
key={container.category}
|
|
|
|
variant="light"
|
|
|
|
className="pf-u-px-0"
|
|
|
|
>
|
|
|
|
<Title headingLevel="h2" size="xl">
|
|
|
|
{t(container.category as TFuncKey)}
|
|
|
|
</Title>
|
|
|
|
<Split className="pf-u-mt-lg pf-u-mb-lg">
|
|
|
|
<SplitItem>
|
|
|
|
<Title headingLevel="h3" size="md" className="pf-u-mb-md">
|
|
|
|
<span className="cred-title pf-u-display-block">
|
|
|
|
{t(container.displayName as TFuncKey)}
|
|
|
|
</span>
|
|
|
|
</Title>
|
|
|
|
{t(container.helptext as TFuncKey)}
|
|
|
|
</SplitItem>
|
|
|
|
{container.createAction && (
|
|
|
|
<SplitItem isFilled>
|
|
|
|
<div className="pf-u-float-right">
|
|
|
|
<MobileLink
|
|
|
|
onClick={() =>
|
|
|
|
login({
|
|
|
|
action: container.createAction,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
title={t("setUpNew", [
|
|
|
|
t(container.displayName as TFuncKey),
|
|
|
|
])}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</SplitItem>
|
|
|
|
)}
|
|
|
|
</Split>
|
|
|
|
|
|
|
|
<DataList aria-label="credential list" className="pf-u-mb-xl">
|
|
|
|
{container.userCredentialMetadatas.length === 0 && (
|
2023-02-16 15:29:28 +00:00
|
|
|
<EmptyRow
|
|
|
|
message={t("notSetUp", [
|
|
|
|
t(container.displayName as TFuncKey),
|
|
|
|
])}
|
|
|
|
/>
|
2023-02-07 11:29:52 +00:00
|
|
|
)}
|
|
|
|
|
|
|
|
{container.userCredentialMetadatas.map((meta) => (
|
|
|
|
<DataListItem key={meta.credential.id}>
|
|
|
|
<DataListItemRow>
|
|
|
|
<DataListItemCells
|
|
|
|
className="pf-u-py-0"
|
|
|
|
dataListCells={[
|
|
|
|
...credentialRowCells(meta),
|
|
|
|
<DataListAction
|
|
|
|
key="action"
|
|
|
|
id={`action-${meta.credential.id}`}
|
|
|
|
aria-label={t("updateCredAriaLabel")}
|
|
|
|
aria-labelledby={`cred-${meta.credential.id}`}
|
|
|
|
>
|
|
|
|
{container.removeable ? (
|
|
|
|
<ContinueCancelModal
|
2023-07-19 11:19:16 +00:00
|
|
|
buttonTitle={t("delete")}
|
2023-02-07 11:29:52 +00:00
|
|
|
modalTitle={t("removeCred", [
|
|
|
|
label(meta.credential),
|
|
|
|
])}
|
2023-07-19 11:19:16 +00:00
|
|
|
continueLabel={t("confirm")}
|
|
|
|
cancelLabel={t("cancel")}
|
|
|
|
buttonVariant="danger"
|
2023-02-07 11:29:52 +00:00
|
|
|
onContinue={async () => {
|
|
|
|
try {
|
|
|
|
await deleteCredentials(meta.credential);
|
2023-03-02 12:54:34 +00:00
|
|
|
addAlert(
|
|
|
|
t("successRemovedMessage", {
|
|
|
|
userLabel: label(meta.credential),
|
2023-07-11 14:03:21 +00:00
|
|
|
}),
|
2023-03-02 12:54:34 +00:00
|
|
|
);
|
2023-02-07 11:29:52 +00:00
|
|
|
refresh();
|
|
|
|
} catch (error) {
|
2023-03-02 12:54:34 +00:00
|
|
|
addError(
|
|
|
|
t("errorRemovedMessage", {
|
|
|
|
userLabel: label(meta.credential),
|
|
|
|
error,
|
2023-07-11 14:03:21 +00:00
|
|
|
}).toString(),
|
2023-03-02 12:54:34 +00:00
|
|
|
);
|
2023-02-07 11:29:52 +00:00
|
|
|
}
|
|
|
|
}}
|
2023-07-19 11:19:16 +00:00
|
|
|
>
|
|
|
|
{t("stopUsingCred", [label(meta.credential)])}
|
|
|
|
</ContinueCancelModal>
|
2023-02-07 11:29:52 +00:00
|
|
|
) : (
|
|
|
|
<Button
|
|
|
|
variant="secondary"
|
|
|
|
onClick={() => {
|
|
|
|
if (container.updateAction)
|
|
|
|
login({ action: container.updateAction });
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{t("update")}
|
|
|
|
</Button>
|
|
|
|
)}
|
|
|
|
</DataListAction>,
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
</DataListItemRow>
|
|
|
|
</DataListItem>
|
|
|
|
))}
|
|
|
|
</DataList>
|
|
|
|
</PageSection>
|
|
|
|
))}
|
|
|
|
</DataList>
|
|
|
|
</Page>
|
|
|
|
);
|
|
|
|
};
|
2022-10-10 10:14:19 +00:00
|
|
|
|
|
|
|
export default SigningIn;
|