replace modals with changing page content for better accessability
This commit is contained in:
parent
107c0b6e1b
commit
a03a2655d0
10
package.json
10
package.json
|
@ -13,12 +13,12 @@
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/prismjs": "^1.16.6",
|
"@types/prismjs": "^1.16.6",
|
||||||
"@types/uikit": "^3.3.2",
|
"@types/uikit": "^3.3.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||||
"@typescript-eslint/parser": "^5.9.1",
|
"@typescript-eslint/parser": "^5.10.0",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.3",
|
||||||
"css-loader": "^6.5.1",
|
"css-loader": "^6.5.1",
|
||||||
"css-minimizer-webpack-plugin": "^3.3.1",
|
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||||
"eslint": "^8.6.0",
|
"eslint": "^8.7.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clipboard": "^2.0.8",
|
"clipboard": "^2.0.8",
|
||||||
"codejar": "^3.5.0",
|
"codejar": "^3.5.0",
|
||||||
"core-js": "^3.20.2",
|
"core-js": "^3.20.3",
|
||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"hjson": "^3.2.2",
|
"hjson": "^3.2.2",
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
@import "uikit/src/scss/components/label.scss";
|
@import "uikit/src/scss/components/label.scss";
|
||||||
|
|
||||||
// JavaScript
|
// JavaScript
|
||||||
@import "uikit/src/scss/components/modal.scss";
|
|
||||||
@import "uikit/src/scss/components/slider.scss";
|
@import "uikit/src/scss/components/slider.scss";
|
||||||
@import "uikit/src/scss/components/switcher.scss";
|
@import "uikit/src/scss/components/switcher.scss";
|
||||||
@import "uikit/src/scss/components/notification.scss";
|
@import "uikit/src/scss/components/notification.scss";
|
||||||
|
|
12
src/translations/de.js
vendored
12
src/translations/de.js
vendored
|
@ -16,9 +16,9 @@ module.exports = {
|
||||||
not_implemented: "Noch nicht implementiert",
|
not_implemented: "Noch nicht implementiert",
|
||||||
|
|
||||||
// Copyable Modal
|
// Copyable Modal
|
||||||
copy_modal_download_btn: "Download",
|
copy_box_download_btn: "Download",
|
||||||
copy_modal_copy_btn: "Kopieren",
|
copy_box_copy_btn: "Kopieren",
|
||||||
copy_modal_close_btn: "Schließen",
|
copy_box_close_btn: "Schließen",
|
||||||
|
|
||||||
// Generic Loading Text
|
// Generic Loading Text
|
||||||
content_loading: "Laden..",
|
content_loading: "Laden..",
|
||||||
|
@ -206,7 +206,7 @@ module.exports = {
|
||||||
transit_encrypt_input_placeholder: "Normaler-Text oder base64",
|
transit_encrypt_input_placeholder: "Normaler-Text oder base64",
|
||||||
transit_encrypt_already_encoded_checkbox: "Ist der text schon in base64 verschlüsselt?",
|
transit_encrypt_already_encoded_checkbox: "Ist der text schon in base64 verschlüsselt?",
|
||||||
transit_encrypt_encrypt_btn: "Verschlüsseln",
|
transit_encrypt_encrypt_btn: "Verschlüsseln",
|
||||||
transit_encrypt_encryption_result_modal_title: "Verachlüsselungs ergebnis",
|
transit_encrypt_encryption_result_title: "Verachlüsselungs ergebnis",
|
||||||
|
|
||||||
// Transit Decrypt Page
|
// Transit Decrypt Page
|
||||||
transit_decrypt_title: "Transit Decrypt",
|
transit_decrypt_title: "Transit Decrypt",
|
||||||
|
@ -214,7 +214,7 @@ module.exports = {
|
||||||
transit_decrypt_input_placeholder: "Cyphertext",
|
transit_decrypt_input_placeholder: "Cyphertext",
|
||||||
transit_decrypt_decode_checkbox: "Soll der Text base64 codiert werden?",
|
transit_decrypt_decode_checkbox: "Soll der Text base64 codiert werden?",
|
||||||
transit_decrypt_decrypt_btn: "Entschlüsseln",
|
transit_decrypt_decrypt_btn: "Entschlüsseln",
|
||||||
transit_decrypt_decryption_result_modal_title: "Entschlüsselungs ergebnis",
|
transit_decrypt_decryption_result_title: "Entschlüsselungs ergebnis",
|
||||||
|
|
||||||
// Transit Rewrap Page
|
// Transit Rewrap Page
|
||||||
transit_rewrap_title: "Transit Rewrap",
|
transit_rewrap_title: "Transit Rewrap",
|
||||||
|
@ -223,7 +223,7 @@ module.exports = {
|
||||||
transit_rewrap_latest_version_option_text: "{{version_num}} (neuste)",
|
transit_rewrap_latest_version_option_text: "{{version_num}} (neuste)",
|
||||||
transit_rewrap_input_placeholder: "Cyphertext",
|
transit_rewrap_input_placeholder: "Cyphertext",
|
||||||
transit_rewrap_rewrap_btn: "Rewrap",
|
transit_rewrap_rewrap_btn: "Rewrap",
|
||||||
transit_rewrap_result_modal_title: "Rewrap Result",
|
transit_rewrap_result_title: "Rewrap Result",
|
||||||
|
|
||||||
// Delete Secret Engine Page
|
// Delete Secret Engine Page
|
||||||
delete_secrets_engine_title: "Delete Secret Engine ({{mount}})",
|
delete_secrets_engine_title: "Delete Secret Engine ({{mount}})",
|
||||||
|
|
12
src/translations/en.js
vendored
12
src/translations/en.js
vendored
|
@ -35,9 +35,9 @@ module.exports = {
|
||||||
not_implemented: "Not Yet Implemented",
|
not_implemented: "Not Yet Implemented",
|
||||||
|
|
||||||
// Copyable Modal
|
// Copyable Modal
|
||||||
copy_modal_download_btn: "Download",
|
copy_box_download_btn: "Download",
|
||||||
copy_modal_copy_btn: "Copy",
|
copy_box_copy_btn: "Copy",
|
||||||
copy_modal_close_btn: "Close",
|
copy_box_close_btn: "Close",
|
||||||
|
|
||||||
// Generic Loading Text
|
// Generic Loading Text
|
||||||
content_loading: "Loading..",
|
content_loading: "Loading..",
|
||||||
|
@ -227,14 +227,14 @@ module.exports = {
|
||||||
transit_encrypt_suffix: " (encrypt)",
|
transit_encrypt_suffix: " (encrypt)",
|
||||||
transit_encrypt_input_placeholder: "Plaintext or base64",
|
transit_encrypt_input_placeholder: "Plaintext or base64",
|
||||||
transit_encrypt_already_encoded_checkbox: "Is the data already encoded in base64?",
|
transit_encrypt_already_encoded_checkbox: "Is the data already encoded in base64?",
|
||||||
transit_encrypt_encryption_result_modal_title: "Encryption Result",
|
transit_encrypt_encryption_result_title: "Encryption Result",
|
||||||
|
|
||||||
// Transit Decrypt Page
|
// Transit Decrypt Page
|
||||||
transit_decrypt_title: "Transit Decrypt",
|
transit_decrypt_title: "Transit Decrypt",
|
||||||
transit_decrypt_suffix: " (decrypt)",
|
transit_decrypt_suffix: " (decrypt)",
|
||||||
transit_decrypt_input_placeholder: "Cyphertext",
|
transit_decrypt_input_placeholder: "Cyphertext",
|
||||||
transit_decrypt_decode_checkbox: "Should the plaintext be base64 decoded?",
|
transit_decrypt_decode_checkbox: "Should the plaintext be base64 decoded?",
|
||||||
transit_decrypt_decryption_result_modal_title: "Decryption Result",
|
transit_decrypt_decryption_result_title: "Decryption Result",
|
||||||
|
|
||||||
// Transit Rewrap Page
|
// Transit Rewrap Page
|
||||||
transit_rewrap_title: "Transit Rewrap",
|
transit_rewrap_title: "Transit Rewrap",
|
||||||
|
@ -242,7 +242,7 @@ module.exports = {
|
||||||
transit_rewrap_version_option_text: "{{version_num}}",
|
transit_rewrap_version_option_text: "{{version_num}}",
|
||||||
transit_rewrap_latest_version_option_text: "{{version_num}} (latest)",
|
transit_rewrap_latest_version_option_text: "{{version_num}} (latest)",
|
||||||
transit_rewrap_input_placeholder: "Cyphertext",
|
transit_rewrap_input_placeholder: "Cyphertext",
|
||||||
transit_rewrap_result_modal_title: "Rewrap Result",
|
transit_rewrap_result_title: "Rewrap Result",
|
||||||
|
|
||||||
// Delete Secret Engine Page
|
// Delete Secret Engine Page
|
||||||
delete_secrets_engine_title: "Delete Secret Engine ({{mount}})",
|
delete_secrets_engine_title: "Delete Secret Engine ({{mount}})",
|
||||||
|
|
10
src/translations/fr.js
vendored
10
src/translations/fr.js
vendored
|
@ -14,9 +14,9 @@ module.exports = {
|
||||||
notification_copy_success: "Copié dans le presse-papiers.",
|
notification_copy_success: "Copié dans le presse-papiers.",
|
||||||
|
|
||||||
// Copyable Modal
|
// Copyable Modal
|
||||||
copy_modal_download_btn: "Télécharger",
|
copy_box_download_btn: "Télécharger",
|
||||||
copy_modal_copy_btn: "Copier",
|
copy_box_copy_btn: "Copier",
|
||||||
copy_modal_close_btn: "Fermer",
|
copy_box_close_btn: "Fermer",
|
||||||
|
|
||||||
// Copyable Input Box
|
// Copyable Input Box
|
||||||
copy_input_box_copy_icon_text: "Bouton Copier",
|
copy_input_box_copy_icon_text: "Bouton Copier",
|
||||||
|
@ -140,7 +140,7 @@ module.exports = {
|
||||||
transit_encrypt_input_placeholder: "Texte brut ou base64",
|
transit_encrypt_input_placeholder: "Texte brut ou base64",
|
||||||
transit_encrypt_already_encoded_checkbox: "Les données sont-elles déjà encodées en base64 ?",
|
transit_encrypt_already_encoded_checkbox: "Les données sont-elles déjà encodées en base64 ?",
|
||||||
transit_encrypt_encrypt_btn: "Chiffrer",
|
transit_encrypt_encrypt_btn: "Chiffrer",
|
||||||
transit_encrypt_encryption_result_modal_title: "Résultat chiffré",
|
transit_encrypt_encryption_result_title: "Résultat chiffré",
|
||||||
|
|
||||||
// Transit decrypt Page
|
// Transit decrypt Page
|
||||||
transit_decrypt_title: "Déchiffrement Transit",
|
transit_decrypt_title: "Déchiffrement Transit",
|
||||||
|
@ -148,5 +148,5 @@ module.exports = {
|
||||||
transit_decrypt_input_placeholder: "Message chiffré",
|
transit_decrypt_input_placeholder: "Message chiffré",
|
||||||
transit_decrypt_decode_checkbox: "Est-ce que le texte brut doit être encodé en base64 ?",
|
transit_decrypt_decode_checkbox: "Est-ce que le texte brut doit être encodé en base64 ?",
|
||||||
transit_decrypt_decrypt_btn: "Déchiffrer",
|
transit_decrypt_decrypt_btn: "Déchiffrer",
|
||||||
transit_decrypt_decryption_result_modal_title: "Résultat déchiffré",
|
transit_decrypt_decryption_result_title: "Résultat déchiffré",
|
||||||
};
|
};
|
||||||
|
|
12
src/translations/ru.js
vendored
12
src/translations/ru.js
vendored
|
@ -35,9 +35,9 @@ module.exports = {
|
||||||
not_implemented: "Функция ещё не реализована",
|
not_implemented: "Функция ещё не реализована",
|
||||||
|
|
||||||
// Copyable Modal
|
// Copyable Modal
|
||||||
copy_modal_download_btn: "Загрузить",
|
copy_box_download_btn: "Загрузить",
|
||||||
copy_modal_copy_btn: "Копировать",
|
copy_box_copy_btn: "Копировать",
|
||||||
copy_modal_close_btn: "Закрыть",
|
copy_box_close_btn: "Закрыть",
|
||||||
|
|
||||||
// Generic Loading Text
|
// Generic Loading Text
|
||||||
content_loading: "Загрузка..",
|
content_loading: "Загрузка..",
|
||||||
|
@ -222,14 +222,14 @@ module.exports = {
|
||||||
transit_encrypt_suffix: " (шифр.)",
|
transit_encrypt_suffix: " (шифр.)",
|
||||||
transit_encrypt_input_placeholder: "Текст или base64",
|
transit_encrypt_input_placeholder: "Текст или base64",
|
||||||
transit_encrypt_already_encoded_checkbox: "Данные уже закодированы в base64?",
|
transit_encrypt_already_encoded_checkbox: "Данные уже закодированы в base64?",
|
||||||
transit_encrypt_encryption_result_modal_title: "Результат шифрования",
|
transit_encrypt_encryption_result_title: "Результат шифрования",
|
||||||
|
|
||||||
// Transit Decrypt Page
|
// Transit Decrypt Page
|
||||||
transit_decrypt_title: "Расшифрование Transit",
|
transit_decrypt_title: "Расшифрование Transit",
|
||||||
transit_decrypt_suffix: " (расшифр.)",
|
transit_decrypt_suffix: " (расшифр.)",
|
||||||
transit_decrypt_input_placeholder: "Шифр-текст",
|
transit_decrypt_input_placeholder: "Шифр-текст",
|
||||||
transit_decrypt_decode_checkbox: "Нужно ли раскодировать текст из base64?",
|
transit_decrypt_decode_checkbox: "Нужно ли раскодировать текст из base64?",
|
||||||
transit_decrypt_decryption_result_modal_title: "Результат расшифрования",
|
transit_decrypt_decryption_result_title: "Результат расшифрования",
|
||||||
|
|
||||||
// Transit Rewrap Page
|
// Transit Rewrap Page
|
||||||
transit_rewrap_title: "Перешифрование Transit",
|
transit_rewrap_title: "Перешифрование Transit",
|
||||||
|
@ -237,7 +237,7 @@ module.exports = {
|
||||||
transit_rewrap_version_option_text: "{{version_num}}",
|
transit_rewrap_version_option_text: "{{version_num}}",
|
||||||
transit_rewrap_latest_version_option_text: "{{version_num}} (последняя версия)",
|
transit_rewrap_latest_version_option_text: "{{version_num}} (последняя версия)",
|
||||||
transit_rewrap_input_placeholder: "Шифр-текст",
|
transit_rewrap_input_placeholder: "Шифр-текст",
|
||||||
transit_rewrap_result_modal_title: "Результат перешифрования",
|
transit_rewrap_result_title: "Результат перешифрования",
|
||||||
|
|
||||||
// Delete Secret Engine Page
|
// Delete Secret Engine Page
|
||||||
delete_secrets_engine_title: "Удалить обработчик тайн ({{mount}})",
|
delete_secrets_engine_title: "Удалить обработчик тайн ({{mount}})",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { JSX } from "preact";
|
import { JSX, RefObject } from "preact";
|
||||||
import { route } from "preact-router";
|
import { route } from "preact-router";
|
||||||
|
|
||||||
export type ButtonProps = {
|
export type ButtonProps = {
|
||||||
|
@ -8,6 +8,7 @@ export type ButtonProps = {
|
||||||
route?: string;
|
route?: string;
|
||||||
onClick?: () => unknown;
|
onClick?: () => unknown;
|
||||||
type?: "submit" | null;
|
type?: "submit" | null;
|
||||||
|
buttonRef?: RefObject<HTMLButtonElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Button(props: ButtonProps): JSX.Element {
|
export function Button(props: ButtonProps): JSX.Element {
|
||||||
|
@ -15,6 +16,8 @@ export function Button(props: ButtonProps): JSX.Element {
|
||||||
if (props.route) {
|
if (props.route) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
{...props}
|
||||||
|
ref={props.buttonRef}
|
||||||
class={classes}
|
class={classes}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
route(props.route);
|
route(props.route);
|
||||||
|
@ -26,7 +29,13 @@ export function Button(props: ButtonProps): JSX.Element {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<button class={classes} type={props.type} onClick={props.onClick}>
|
<button
|
||||||
|
{...props}
|
||||||
|
ref={props.buttonRef}
|
||||||
|
class={classes}
|
||||||
|
type={props.type}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
{props.text}
|
{props.text}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,22 +2,26 @@ import { JSX } from "preact";
|
||||||
import Prism from "prismjs";
|
import Prism from "prismjs";
|
||||||
|
|
||||||
export type CodeBlockProps = {
|
export type CodeBlockProps = {
|
||||||
language: string;
|
|
||||||
code: string;
|
code: string;
|
||||||
|
language?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function CodeBlock(props: CodeBlockProps): JSX.Element {
|
export function CodeBlock(props: CodeBlockProps): JSX.Element {
|
||||||
const highlightedCode = Prism.highlight(
|
if (props.language) {
|
||||||
props.code,
|
const highlightedCode = Prism.highlight(
|
||||||
Prism.languages[props.language],
|
props.code,
|
||||||
props.language,
|
Prism.languages[props.language],
|
||||||
);
|
props.language,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<pre
|
<pre
|
||||||
class="code-block language-json line-numbers"
|
class={"code-block " + "language-" + props.language}
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
dangerouslySetInnerHTML={{ __html: highlightedCode }}
|
dangerouslySetInnerHTML={{ __html: highlightedCode }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return <pre class="code-block" dir="ltr" dangerouslySetInnerHTML={{ __html: props.code }} />;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
57
src/ui/elements/CopyableBox.tsx
Normal file
57
src/ui/elements/CopyableBox.tsx
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { Button } from "./Button";
|
||||||
|
import { CodeBlock } from "./CodeBlock";
|
||||||
|
import { Component, JSX, createRef } from "preact";
|
||||||
|
import { addClipboardNotifications } from "../../pageUtils";
|
||||||
|
import ClipboardJS from "clipboard";
|
||||||
|
import FileSaver from "file-saver";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
export type CopyableBoxProps = {
|
||||||
|
title: string;
|
||||||
|
contentString: string;
|
||||||
|
goBack?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class CopyableBox extends Component<CopyableBoxProps> {
|
||||||
|
copyButtonRef = createRef<HTMLButtonElement>();
|
||||||
|
|
||||||
|
saveAsFile(): void {
|
||||||
|
const blob = new Blob([this.props.contentString], {
|
||||||
|
type: "text/plain;charset=utf-8",
|
||||||
|
});
|
||||||
|
FileSaver.saveAs(blob, "result.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
console.log(this.copyButtonRef.current);
|
||||||
|
const clipboard = new ClipboardJS(this.copyButtonRef.current);
|
||||||
|
addClipboardNotifications(clipboard, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h2>{this.props.title}</h2>
|
||||||
|
</div>
|
||||||
|
<CodeBlock code={this.props.contentString} />
|
||||||
|
<p>
|
||||||
|
<Button
|
||||||
|
text={i18next.t("copy_box_download_btn")}
|
||||||
|
color="primary"
|
||||||
|
onClick={() => this.saveAsFile()}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
text={i18next.t("copy_box_copy_btn")}
|
||||||
|
color="primary"
|
||||||
|
buttonRef={this.copyButtonRef}
|
||||||
|
data-clipboard-text={this.props.contentString}
|
||||||
|
/>
|
||||||
|
{this.props.goBack && (
|
||||||
|
<Button text={i18next.t("common_back")} color="secondary" onClick={this.props.goBack} />
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
import { Component, JSX, createRef } from "preact";
|
|
||||||
import { addClipboardNotifications } from "../../pageUtils";
|
|
||||||
import ClipboardJS from "clipboard";
|
|
||||||
import FileSaver from "file-saver";
|
|
||||||
import i18next from "i18next";
|
|
||||||
|
|
||||||
export type CopyableModalProps = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
contentString: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class CopyableModal extends Component<CopyableModalProps, unknown> {
|
|
||||||
ref = createRef();
|
|
||||||
copyButtonRef = createRef<HTMLButtonElement>();
|
|
||||||
|
|
||||||
saveAsFile(): void {
|
|
||||||
const blob = new Blob([this.props.contentString], {
|
|
||||||
type: "text/plain;charset=utf-8",
|
|
||||||
});
|
|
||||||
FileSaver.saveAs(blob, "result.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
const clipboard = new ClipboardJS(this.copyButtonRef.current);
|
|
||||||
addClipboardNotifications(clipboard, 600);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div id={this.props.id} ref={this.ref} class="modal-section" uk-modal>
|
|
||||||
<div class="uk-modal-dialog">
|
|
||||||
<button class="uk-modal-close-default" type="button" uk-close />
|
|
||||||
<div class="uk-modal-header">
|
|
||||||
<h2>{this.props.name}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="uk-modal-body">
|
|
||||||
<pre class="wrap-pre">{this.props.contentString}</pre>
|
|
||||||
</div>
|
|
||||||
<div class="uk-modal-footer uk-text-right">
|
|
||||||
<button
|
|
||||||
class="uk-button uk-button-primary"
|
|
||||||
type="button"
|
|
||||||
onClick={() => this.saveAsFile()}
|
|
||||||
>
|
|
||||||
{i18next.t("copy_modal_download_btn")}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="uk-button uk-button-primary"
|
|
||||||
ref={this.copyButtonRef}
|
|
||||||
type="button"
|
|
||||||
data-clipboard-text={this.props.contentString}
|
|
||||||
>
|
|
||||||
{i18next.t("copy_modal_copy_btn")}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="uk-button uk-button-secondary uk-modal-close"
|
|
||||||
type="button"
|
|
||||||
data-clipboard-text={this.props.contentString}
|
|
||||||
>
|
|
||||||
{i18next.t("copy_modal_close_btn")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Button } from "../../../elements/Button";
|
import { Button } from "../../../elements/Button";
|
||||||
import { Component, render } from "preact";
|
import { Component } from "preact";
|
||||||
import { CopyableModal } from "../../../elements/CopyableModal";
|
import { CopyableBox } from "../../../elements/CopyableBox";
|
||||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||||
import { FileUploadInput } from "../../../elements/FileUploadInput";
|
import { FileUploadInput } from "../../../elements/FileUploadInput";
|
||||||
import { Form } from "../../../elements/Form";
|
import { Form } from "../../../elements/Form";
|
||||||
|
@ -9,41 +9,59 @@ import { Margin } from "../../../elements/Margin";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { fileToBase64 } from "../../../../htmlUtils";
|
import { fileToBase64 } from "../../../../htmlUtils";
|
||||||
import { setErrorText } from "../../../../pageUtils";
|
import { setErrorText } from "../../../../pageUtils";
|
||||||
import UIkit from "uikit";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class TransitDecrypt extends Component<DefaultPageProps> {
|
export class TransitDecrypt extends Component<DefaultPageProps, { plaintext: string }> {
|
||||||
render() {
|
render() {
|
||||||
const baseMount = this.props.matches["baseMount"];
|
const baseMount = this.props.matches["baseMount"];
|
||||||
const secretItem = this.props.matches["secretItem"];
|
const secretItem = this.props.matches["secretItem"];
|
||||||
return (
|
|
||||||
<>
|
const title = (
|
||||||
<SecretTitleElement
|
<SecretTitleElement
|
||||||
type="transit"
|
type="transit"
|
||||||
baseMount={baseMount}
|
baseMount={baseMount}
|
||||||
item={secretItem}
|
item={secretItem}
|
||||||
suffix={i18next.t("transit_decrypt_suffix")}
|
suffix={i18next.t("transit_decrypt_suffix")}
|
||||||
/>
|
/>
|
||||||
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
|
||||||
<Margin>
|
|
||||||
<textarea
|
|
||||||
class="uk-textarea uk-form-width-medium"
|
|
||||||
name="ciphertext"
|
|
||||||
placeholder={i18next.t("transit_decrypt_input_placeholder")}
|
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
<Margin>
|
|
||||||
<FileUploadInput name="ciphertext_file" />
|
|
||||||
</Margin>
|
|
||||||
<InputWithTitle title={i18next.t("transit_decrypt_decode_checkbox")}>
|
|
||||||
<input class="uk-checkbox" name="decodeBase64Checkbox" type="checkbox" />
|
|
||||||
</InputWithTitle>
|
|
||||||
<p class="uk-text-danger" id="errorText" />
|
|
||||||
<Button text={i18next.t("transit_decrypt")} color="primary" type="submit" />
|
|
||||||
<div id="modalAttachmentPoint" />
|
|
||||||
</Form>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!this.state.plaintext) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
||||||
|
<Margin>
|
||||||
|
<textarea
|
||||||
|
class="uk-textarea uk-form-width-medium"
|
||||||
|
name="ciphertext"
|
||||||
|
placeholder={i18next.t("transit_decrypt_input_placeholder")}
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<Margin>
|
||||||
|
<FileUploadInput name="ciphertext_file" />
|
||||||
|
</Margin>
|
||||||
|
<InputWithTitle title={i18next.t("transit_decrypt_decode_checkbox")}>
|
||||||
|
<input class="uk-checkbox" name="decodeBase64Checkbox" type="checkbox" />
|
||||||
|
</InputWithTitle>
|
||||||
|
<p class="uk-text-danger" id="errorText" />
|
||||||
|
<Button text={i18next.t("transit_decrypt")} color="primary" type="submit" />
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<CopyableBox
|
||||||
|
title={i18next.t("transit_decrypt_decryption_result_title")}
|
||||||
|
contentString={this.state.plaintext}
|
||||||
|
goBack={() => {
|
||||||
|
this.setState({ plaintext: null });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSubmit(data: FormData): Promise<void> {
|
async onSubmit(data: FormData): Promise<void> {
|
||||||
|
@ -67,17 +85,11 @@ export class TransitDecrypt extends Component<DefaultPageProps> {
|
||||||
});
|
});
|
||||||
let plaintext = res.plaintext;
|
let plaintext = res.plaintext;
|
||||||
if (decodeBase64 == "on") {
|
if (decodeBase64 == "on") {
|
||||||
|
// Really don't supposed to be doing this...
|
||||||
plaintext = atob(plaintext);
|
plaintext = atob(plaintext);
|
||||||
}
|
}
|
||||||
render(
|
|
||||||
<CopyableModal
|
this.setState({ plaintext: plaintext });
|
||||||
id="transitResultModal"
|
|
||||||
name={i18next.t("transit_decrypt_decryption_result_modal_title")}
|
|
||||||
contentString={plaintext}
|
|
||||||
/>,
|
|
||||||
document.querySelector("#modalAttachmentPoint"),
|
|
||||||
);
|
|
||||||
UIkit.modal(document.querySelector("#transitResultModal")).show();
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
const error = e as Error;
|
const error = e as Error;
|
||||||
setErrorText(`API Error: ${error.message}`);
|
setErrorText(`API Error: ${error.message}`);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Button } from "../../../elements/Button";
|
import { Button } from "../../../elements/Button";
|
||||||
import { Component, render } from "preact";
|
import { Component } from "preact";
|
||||||
import { CopyableModal } from "../../../elements/CopyableModal";
|
import { CopyableBox } from "../../../elements/CopyableBox";
|
||||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||||
import { FileUploadInput } from "../../../elements/FileUploadInput";
|
import { FileUploadInput } from "../../../elements/FileUploadInput";
|
||||||
import { Form } from "../../../elements/Form";
|
import { Form } from "../../../elements/Form";
|
||||||
|
@ -9,41 +9,59 @@ import { Margin } from "../../../elements/Margin";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { fileToBase64 } from "../../../../htmlUtils";
|
import { fileToBase64 } from "../../../../htmlUtils";
|
||||||
import { setErrorText } from "../../../../pageUtils";
|
import { setErrorText } from "../../../../pageUtils";
|
||||||
import UIkit from "uikit";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class TransitEncrypt extends Component<DefaultPageProps> {
|
export class TransitEncrypt extends Component<DefaultPageProps, { ciphertext: string }> {
|
||||||
render() {
|
render() {
|
||||||
const baseMount = this.props.matches["baseMount"];
|
const baseMount = this.props.matches["baseMount"];
|
||||||
const secretItem = this.props.matches["secretItem"];
|
const secretItem = this.props.matches["secretItem"];
|
||||||
return (
|
|
||||||
<>
|
const title = (
|
||||||
<SecretTitleElement
|
<SecretTitleElement
|
||||||
type="transit"
|
type="transit"
|
||||||
baseMount={baseMount}
|
baseMount={baseMount}
|
||||||
item={secretItem}
|
item={secretItem}
|
||||||
suffix={i18next.t("transit_encrypt_suffix")}
|
suffix={i18next.t("transit_encrypt_suffix")}
|
||||||
/>
|
/>
|
||||||
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
|
||||||
<Margin>
|
|
||||||
<textarea
|
|
||||||
class="uk-textarea uk-form-width-medium"
|
|
||||||
name="plaintext"
|
|
||||||
placeholder={i18next.t("transit_encrypt_input_placeholder")}
|
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
<Margin>
|
|
||||||
<FileUploadInput name="plaintext_file" />
|
|
||||||
</Margin>
|
|
||||||
<InputWithTitle title={i18next.t("transit_encrypt_already_encoded_checkbox")}>
|
|
||||||
<input class="uk-checkbox" name="base64Checkbox" type="checkbox" />
|
|
||||||
</InputWithTitle>
|
|
||||||
<p class="uk-text-danger" id="errorText" />
|
|
||||||
<Button text={i18next.t("transit_encrypt")} color="primary" type="submit" />
|
|
||||||
<div id="modalAttachmentPoint" />
|
|
||||||
</Form>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!this.state.ciphertext) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
||||||
|
<Margin>
|
||||||
|
<textarea
|
||||||
|
class="uk-textarea uk-form-width-medium"
|
||||||
|
name="plaintext"
|
||||||
|
placeholder={i18next.t("transit_encrypt_input_placeholder")}
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<Margin>
|
||||||
|
<FileUploadInput name="plaintext_file" />
|
||||||
|
</Margin>
|
||||||
|
<InputWithTitle title={i18next.t("transit_encrypt_already_encoded_checkbox")}>
|
||||||
|
<input class="uk-checkbox" name="base64Checkbox" type="checkbox" />
|
||||||
|
</InputWithTitle>
|
||||||
|
<p class="uk-text-danger" id="errorText" />
|
||||||
|
<Button text={i18next.t("transit_encrypt")} color="primary" type="submit" />
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<CopyableBox
|
||||||
|
title={i18next.t("transit_encrypt_encryption_result_title")}
|
||||||
|
contentString={this.state.ciphertext}
|
||||||
|
goBack={() => {
|
||||||
|
this.setState({ ciphertext: null });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSubmit(data: FormData): Promise<void> {
|
async onSubmit(data: FormData): Promise<void> {
|
||||||
|
@ -66,15 +84,7 @@ export class TransitEncrypt extends Component<DefaultPageProps> {
|
||||||
const res = await this.props.api.transitEncrypt(baseMount, secretItem, {
|
const res = await this.props.api.transitEncrypt(baseMount, secretItem, {
|
||||||
plaintext: plaintext,
|
plaintext: plaintext,
|
||||||
});
|
});
|
||||||
render(
|
this.setState({ ciphertext: res.ciphertext });
|
||||||
<CopyableModal
|
|
||||||
id="transitResultModal"
|
|
||||||
name={i18next.t("transit_encrypt_encryption_result_modal_title")}
|
|
||||||
contentString={res.ciphertext}
|
|
||||||
/>,
|
|
||||||
document.querySelector("#modalAttachmentPoint"),
|
|
||||||
);
|
|
||||||
UIkit.modal(document.querySelector("#transitResultModal")).show();
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
const error = e as Error;
|
const error = e as Error;
|
||||||
setErrorText(`API Error: ${error.message}`);
|
setErrorText(`API Error: ${error.message}`);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Button } from "../../../elements/Button";
|
import { Button } from "../../../elements/Button";
|
||||||
import { Component, render } from "preact";
|
import { Component } from "preact";
|
||||||
import { CopyableModal } from "../../../elements/CopyableModal";
|
import { CopyableBox } from "../../../elements/CopyableBox";
|
||||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||||
import { Form } from "../../../elements/Form";
|
import { Form } from "../../../elements/Form";
|
||||||
import { Margin } from "../../../elements/Margin";
|
import { Margin } from "../../../elements/Margin";
|
||||||
|
@ -8,12 +8,16 @@ import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { TransitKeyType } from "../../../../api/types/transit";
|
import { TransitKeyType } from "../../../../api/types/transit";
|
||||||
import { objectToMap } from "../../../../utils";
|
import { objectToMap } from "../../../../utils";
|
||||||
import { setErrorText } from "../../../../pageUtils";
|
import { setErrorText } from "../../../../pageUtils";
|
||||||
import UIkit from "uikit";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
type versionOption = { version: string; label: string };
|
type versionOption = { version: string; label: string };
|
||||||
|
|
||||||
export class TransitRewrap extends Component<DefaultPageProps, { transitKey: TransitKeyType }> {
|
type TransitRewrapState = {
|
||||||
|
transitKey: TransitKeyType;
|
||||||
|
ciphertext: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class TransitRewrap extends Component<DefaultPageProps, TransitRewrapState> {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const baseMount = this.props.matches["baseMount"];
|
const baseMount = this.props.matches["baseMount"];
|
||||||
const secretItem = this.props.matches["secretItem"];
|
const secretItem = this.props.matches["secretItem"];
|
||||||
|
@ -28,58 +32,76 @@ export class TransitRewrap extends Component<DefaultPageProps, { transitKey: Tra
|
||||||
const baseMount = this.props.matches["baseMount"];
|
const baseMount = this.props.matches["baseMount"];
|
||||||
const secretItem = this.props.matches["secretItem"];
|
const secretItem = this.props.matches["secretItem"];
|
||||||
|
|
||||||
const stringVersions = Array.from(
|
const title = (
|
||||||
objectToMap(this.state.transitKey.keys).keys(),
|
<SecretTitleElement
|
||||||
).reverse() as unknown as string[];
|
type="transit"
|
||||||
|
baseMount={baseMount}
|
||||||
const versions = stringVersions.map((val): number => parseInt(val, 10));
|
item={secretItem}
|
||||||
|
suffix={i18next.t("transit_rewrap_suffix")}
|
||||||
// get the selectable version options in the same
|
/>
|
||||||
// format the official UI uses.
|
|
||||||
// e.g: ["2 (latest)", "1"]
|
|
||||||
|
|
||||||
const options: versionOption[] = versions.map((val): versionOption => {
|
|
||||||
const i18nkey =
|
|
||||||
val == Math.max(...versions)
|
|
||||||
? "transit_rewrap_latest_version_option_text"
|
|
||||||
: "transit_rewrap_version_option_text";
|
|
||||||
return {
|
|
||||||
version: String(val),
|
|
||||||
label: i18next.t(i18nkey, { version_num: String(val) }),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SecretTitleElement
|
|
||||||
type="transit"
|
|
||||||
baseMount={baseMount}
|
|
||||||
item={secretItem}
|
|
||||||
suffix={i18next.t("transit_rewrap_suffix")}
|
|
||||||
/>
|
|
||||||
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
|
||||||
<Margin>
|
|
||||||
<select class="uk-select uk-width-1-2" name="version">
|
|
||||||
{options.map((option) => (
|
|
||||||
<option label={option.label} value={option.version}>
|
|
||||||
{option.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</Margin>
|
|
||||||
<Margin>
|
|
||||||
<textarea
|
|
||||||
class="uk-textarea uk-width-1-2"
|
|
||||||
name="ciphertext"
|
|
||||||
placeholder={i18next.t("transit_rewrap_input_placeholder")}
|
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
<p class="uk-text-danger" id="errorText" />
|
|
||||||
<Button text={i18next.t("transit_rewrap")} color="primary" type="submit" />
|
|
||||||
<div id="modalAttachmentPoint" />
|
|
||||||
</Form>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!this.state.ciphertext) {
|
||||||
|
const stringVersions = Array.from(
|
||||||
|
objectToMap(this.state.transitKey.keys).keys(),
|
||||||
|
).reverse() as unknown as string[];
|
||||||
|
|
||||||
|
const versions = stringVersions.map((val): number => parseInt(val, 10));
|
||||||
|
|
||||||
|
// get the selectable version options in the same
|
||||||
|
// format the official UI uses.
|
||||||
|
// e.g: ["2 (latest)", "1"]
|
||||||
|
|
||||||
|
const options: versionOption[] = versions.map((val): versionOption => {
|
||||||
|
const i18nkey =
|
||||||
|
val == Math.max(...versions)
|
||||||
|
? "transit_rewrap_latest_version_option_text"
|
||||||
|
: "transit_rewrap_version_option_text";
|
||||||
|
return {
|
||||||
|
version: String(val),
|
||||||
|
label: i18next.t(i18nkey, { version_num: String(val) }),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<Form onSubmit={async (data) => await this.onSubmit(data)}>
|
||||||
|
<Margin>
|
||||||
|
<select class="uk-select uk-width-1-2" name="version">
|
||||||
|
{options.map((option) => (
|
||||||
|
<option label={option.label} value={option.version}>
|
||||||
|
{option.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</Margin>
|
||||||
|
<Margin>
|
||||||
|
<textarea
|
||||||
|
class="uk-textarea uk-width-1-2"
|
||||||
|
name="ciphertext"
|
||||||
|
placeholder={i18next.t("transit_rewrap_input_placeholder")}
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<p class="uk-text-danger" id="errorText" />
|
||||||
|
<Button text={i18next.t("transit_rewrap")} color="primary" type="submit" />
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
<CopyableBox
|
||||||
|
title={i18next.t("transit_rewrap_result_title")}
|
||||||
|
contentString={this.state.ciphertext}
|
||||||
|
goBack={() => {
|
||||||
|
this.setState({ ciphertext: null });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSubmit(data: FormData): Promise<void> {
|
async onSubmit(data: FormData): Promise<void> {
|
||||||
|
@ -90,15 +112,7 @@ export class TransitRewrap extends Component<DefaultPageProps, { transitKey: Tra
|
||||||
ciphertext: data.get("ciphertext") as string,
|
ciphertext: data.get("ciphertext") as string,
|
||||||
key_version: parseInt(data.get("version") as string, 10),
|
key_version: parseInt(data.get("version") as string, 10),
|
||||||
});
|
});
|
||||||
render(
|
this.setState({ ciphertext: res.ciphertext });
|
||||||
<CopyableModal
|
|
||||||
id="transitResultModal"
|
|
||||||
name={i18next.t("transit_rewrap_result_modal_title")}
|
|
||||||
contentString={res.ciphertext}
|
|
||||||
/>,
|
|
||||||
document.querySelector("#modalAttachmentPoint"),
|
|
||||||
);
|
|
||||||
UIkit.modal(document.querySelector("#transitResultModal")).show();
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
const error = e as Error;
|
const error = e as Error;
|
||||||
setErrorText(`API Error: ${error.message}`);
|
setErrorText(`API Error: ${error.message}`);
|
||||||
|
|
Loading…
Reference in a new issue