Rework how KeyValueView works.
This commit is contained in:
parent
4b3eb6b3c6
commit
caadfef359
|
@ -1,9 +1,9 @@
|
||||||
|
import { Component, JSX, render } from "preact";
|
||||||
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
|
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
|
||||||
import { Page } from "../../../types/Page";
|
import { Page } from "../../../types/Page";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { getCapabilities } from "../../../api/sys/getCapabilities";
|
import { getCapabilities } from "../../../api/sys/getCapabilities";
|
||||||
import { getSecret } from "../../../api/kv/getSecret";
|
import { getSecret } from "../../../api/kv/getSecret";
|
||||||
import { Component, JSX, render } from "preact";
|
|
||||||
import { sortedObjectMap } from "../../../utils";
|
import { sortedObjectMap } from "../../../utils";
|
||||||
import { undeleteSecret } from "../../../api/kv/undeleteSecret";
|
import { undeleteSecret } from "../../../api/kv/undeleteSecret";
|
||||||
import Prism from "prismjs";
|
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
|
// On kv-v2, secrets can be deleted temporarily with the ability to restore
|
||||||
// Do not show any buttons when the secret is deleted.
|
// 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(
|
render(
|
||||||
<div>
|
<div>
|
||||||
<p id="buttonsBlock">
|
<p id="buttonsBlock">
|
||||||
{
|
{
|
||||||
// Delete Button
|
// Delete Button
|
||||||
!secretIsDeleted &&
|
!secretIsDeleted && caps.includes("delete") && (
|
||||||
caps.includes("delete") && (
|
|
||||||
<button
|
<button
|
||||||
class="uk-button uk-button-danger"
|
class="uk-button uk-button-danger"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
|
@ -115,37 +114,31 @@ export class KeyValueSecretPage extends Page {
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{!secretIsDeleted && caps.includes("update") && this.state.secretVersion == null && (
|
||||||
!secretIsDeleted &&
|
<button
|
||||||
caps.includes("update") && this.state.secretVersion == null && (
|
class="uk-button uk-button-primary"
|
||||||
<button
|
onClick={async () => {
|
||||||
class="uk-button uk-button-primary"
|
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
|
||||||
onClick={async () => {
|
}}
|
||||||
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
|
>
|
||||||
}}
|
{i18next.t("kv_secret_edit_btn")}
|
||||||
>
|
</button>
|
||||||
{i18next.t("kv_secret_edit_btn")}
|
)}
|
||||||
</button>
|
{!secretIsDeleted && this.state.secretMountType == "kv-v2" && (
|
||||||
)}
|
<button
|
||||||
{
|
class="uk-button uk-button-secondary"
|
||||||
!secretIsDeleted &&
|
onClick={async () => {
|
||||||
this.state.secretMountType == "kv-v2" && (
|
await this.router.changePage("KEY_VALUE_VERSIONS");
|
||||||
<button
|
}}
|
||||||
class="uk-button uk-button-secondary"
|
>
|
||||||
onClick={async () => {
|
{i18next.t("kv_secret_versions_btn")}
|
||||||
await this.router.changePage("KEY_VALUE_VERSIONS");
|
</button>
|
||||||
}}
|
)}
|
||||||
>
|
|
||||||
{i18next.t("kv_secret_versions_btn")}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{!secretIsDeleted &&
|
{!secretIsDeleted && <KVSecretVew kvData={secretInfo} />}
|
||||||
<KVSecretVew kvData={secretInfo} />
|
|
||||||
}
|
|
||||||
|
|
||||||
{secretIsDeleted &&
|
{secretIsDeleted && (
|
||||||
<>
|
<>
|
||||||
<p>{i18next.t("kv_secret_deleted_text")}</p>
|
<p>{i18next.t("kv_secret_deleted_text")}</p>
|
||||||
<button
|
<button
|
||||||
|
@ -163,8 +156,7 @@ export class KeyValueSecretPage extends Page {
|
||||||
{i18next.t("kv_secret_restore_btn")}
|
{i18next.t("kv_secret_restore_btn")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
}
|
)}
|
||||||
|
|
||||||
</div>,
|
</div>,
|
||||||
this.router.pageContentElement,
|
this.router.pageContentElement,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,101 @@
|
||||||
|
import { Component, JSX, render } from "preact";
|
||||||
import { DoesNotExistError } from "../../../types/internalErrors";
|
import { DoesNotExistError } from "../../../types/internalErrors";
|
||||||
import { Page } from "../../../types/Page";
|
import { Page } from "../../../types/Page";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { getSecrets } from "../../../api/kv/getSecrets";
|
import { getSecrets } from "../../../api/kv/getSecrets";
|
||||||
import { render } from "preact";
|
|
||||||
import { setErrorText } from "../../../pageUtils";
|
import { setErrorText } from "../../../pageUtils";
|
||||||
import i18next from "i18next";
|
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 {
|
export class KeyValueViewPage extends Page {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -34,59 +124,10 @@ export class KeyValueViewPage extends Page {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{this.state.secretMountType == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
|
{this.state.secretMountType == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
|
||||||
<div id="secretsList" />
|
<KVKeysList page={this} />
|
||||||
</>,
|
</>,
|
||||||
this.router.pageContentElement,
|
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> {
|
async renderPageTitle(): Promise<void> {
|
||||||
|
|
Loading…
Reference in a new issue