1
0
Fork 0

Rework how KeyValueView works.

This commit is contained in:
Kitteh 2021-05-25 09:27:02 +01:00
parent 4b3eb6b3c6
commit caadfef359
2 changed files with 118 additions and 85 deletions

View file

@ -1,9 +1,9 @@
import { Component, JSX, render } from "preact";
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
import { Page } from "../../../types/Page";
import { SecretTitleElement } from "../SecretTitleElement";
import { getCapabilities } from "../../../api/sys/getCapabilities";
import { getSecret } from "../../../api/kv/getSecret";
import { Component, JSX, render } from "preact";
import { sortedObjectMap } from "../../../utils";
import { undeleteSecret } from "../../../api/kv/undeleteSecret";
import Prism from "prismjs";
@ -80,15 +80,14 @@ export class KeyValueSecretPage extends Page {
// On kv-v2, secrets can be deleted temporarily with the ability to restore
// Do not show any buttons when the secret is deleted.
let secretIsDeleted = secretInfo == null && this.state.secretMountType == "kv-v2";
const secretIsDeleted = secretInfo == null && this.state.secretMountType == "kv-v2";
render(
<div>
<p id="buttonsBlock">
{
// Delete Button
!secretIsDeleted &&
caps.includes("delete") && (
!secretIsDeleted && caps.includes("delete") && (
<button
class="uk-button uk-button-danger"
onClick={async () => {
@ -115,37 +114,31 @@ export class KeyValueSecretPage extends Page {
</button>
)
}
{
!secretIsDeleted &&
caps.includes("update") && this.state.secretVersion == null && (
<button
class="uk-button uk-button-primary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
}}
>
{i18next.t("kv_secret_edit_btn")}
</button>
)}
{
!secretIsDeleted &&
this.state.secretMountType == "kv-v2" && (
<button
class="uk-button uk-button-secondary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_VERSIONS");
}}
>
{i18next.t("kv_secret_versions_btn")}
</button>
)}
{!secretIsDeleted && caps.includes("update") && this.state.secretVersion == null && (
<button
class="uk-button uk-button-primary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
}}
>
{i18next.t("kv_secret_edit_btn")}
</button>
)}
{!secretIsDeleted && this.state.secretMountType == "kv-v2" && (
<button
class="uk-button uk-button-secondary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_VERSIONS");
}}
>
{i18next.t("kv_secret_versions_btn")}
</button>
)}
</p>
{!secretIsDeleted &&
<KVSecretVew kvData={secretInfo} />
}
{!secretIsDeleted && <KVSecretVew kvData={secretInfo} />}
{secretIsDeleted &&
{secretIsDeleted && (
<>
<p>{i18next.t("kv_secret_deleted_text")}</p>
<button
@ -163,8 +156,7 @@ export class KeyValueSecretPage extends Page {
{i18next.t("kv_secret_restore_btn")}
</button>
</>
}
)}
</div>,
this.router.pageContentElement,
);

View file

@ -1,11 +1,101 @@
import { Component, JSX, render } from "preact";
import { DoesNotExistError } from "../../../types/internalErrors";
import { Page } from "../../../types/Page";
import { SecretTitleElement } from "../SecretTitleElement";
import { getSecrets } from "../../../api/kv/getSecrets";
import { render } from "preact";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
export type KVKeysListProps = {
page: Page;
};
type KVKeysListState =
| {
dataLoaded: false;
}
| {
dataLoaded: true;
keys: string[];
};
export class KVKeysList extends Component<KVKeysListProps, KVKeysListState> {
constructor() {
super();
this.state = {
dataLoaded: false,
};
}
loadData(): void {
void getSecrets(
this.props.page.state.baseMount,
this.props.page.state.secretMountType,
this.props.page.state.secretPath,
)
.then((keys) => {
this.setState({
dataLoaded: true,
keys: keys,
});
})
.catch((e: Error) => {
// getSecrets also 404's on no keys so dont go all the way back.
if (e == DoesNotExistError) {
if (this.props.page.state.secretPath.length != 0) {
void this.props.page.goBack();
return;
} else {
this.setState({
dataLoaded: true,
keys: null,
});
}
} else {
setErrorText(e.message);
}
});
return;
}
componentDidMount(): void {
if (!this.state.dataLoaded) {
this.loadData();
}
}
render(): JSX.Element {
if (!this.state.dataLoaded) {
return <p>{i18next.t("content_loading")}</p>;
}
if (this.state.keys == null) {
return <p>{i18next.t("kv_view_none_here_text")}</p>;
}
return (
<ul class="uk-nav uk-nav-default">
{...this.state.keys.map((secret) => (
<li>
<a
onClick={async () => {
const page = this.props.page;
if (secret.endsWith("/")) {
page.state.pushSecretPath(secret);
await page.router.changePage("KEY_VALUE_VIEW");
} else {
page.state.secretItem = secret;
await page.router.changePage("KEY_VALUE_SECRET");
}
}}
>
{secret}
</a>
</li>
))}
</ul>
);
}
}
export class KeyValueViewPage extends Page {
constructor() {
super();
@ -34,59 +124,10 @@ export class KeyValueViewPage extends Page {
</button>
</div>
{this.state.secretMountType == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
<div id="secretsList" />
<KVKeysList page={this} />
</>,
this.router.pageContentElement,
);
let res: string[];
try {
res = await getSecrets(
this.state.baseMount,
this.state.secretMountType,
this.state.secretPath,
);
} catch (e: unknown) {
const error = e as Error;
if (error == DoesNotExistError) {
// getSecrets also 404's on no keys so dont go all the way back.
if (this.state.secretPath.length != 0) {
return this.goBack();
} else {
render(
<p>{i18next.t("kv_view_none_here_text")}</p>,
document.querySelector("#secretsList"),
);
}
} else {
setErrorText(error.message);
return;
}
}
render(
<ul class="uk-nav uk-nav-default">
{...res.map((secret) => (
<li>
<a
onClick={async () => {
if (secret.endsWith("/")) {
this.state.pushSecretPath(secret);
await this.router.changePage("KEY_VALUE_VIEW");
} else {
this.state.secretItem = secret;
await this.router.changePage("KEY_VALUE_SECRET");
}
}}
>
{secret}
</a>
</li>
))}
</ul>,
document.querySelector("#secretsList"),
);
}
async renderPageTitle(): Promise<void> {