pretty
This commit is contained in:
parent
c34e71cf3d
commit
b4bad2deaf
@ -19,10 +19,10 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentChildren, h, VNode } from 'preact';
|
import { ComponentChildren, h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef } from 'preact/hooks';
|
import { useLayoutEffect, useRef } from "preact/hooks";
|
||||||
// import { LoadingModal } from "../modal";
|
// import { LoadingModal } from "../modal";
|
||||||
import { useAsync } from '../hooks/async';
|
import { useAsync } from "../hooks/async";
|
||||||
// import { Translate } from "../../i18n";
|
// import { Translate } from "../../i18n";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -44,20 +44,16 @@ export function AsyncButton({
|
|||||||
|
|
||||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (grabFocus)
|
if (grabFocus) buttonRef.current?.focus();
|
||||||
buttonRef.current?.focus();
|
|
||||||
|
|
||||||
}, [grabFocus]);
|
}, [grabFocus]);
|
||||||
|
|
||||||
// if (isSlow) {
|
// if (isSlow) {
|
||||||
// return <LoadingModal onCancel={cancel} />;
|
// return <LoadingModal onCancel={cancel} />;
|
||||||
// }
|
// }
|
||||||
if (isLoading)
|
if (isLoading) return <button class="button">Loading...</button>;
|
||||||
return <button class="button">Loading...</button>;
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span data-tooltip={rest['data-tooltip']} style={{ marginLeft: 5 }}>
|
<span data-tooltip={rest["data-tooltip"]} style={{ marginLeft: 5 }}>
|
||||||
<button {...rest} ref={buttonRef} onClick={request} disabled={disabled}>
|
<button {...rest} ref={buttonRef} onClick={request} disabled={disabled}>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useRef, useState } from 'preact/hooks';
|
import { useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
@ -23,12 +23,11 @@ export function FileButton(props: Props): VNode {
|
|||||||
</button>
|
</button>
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
style={{ display: 'none' }}
|
style={{ display: "none" }}
|
||||||
type="file"
|
type="file"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const f: FileList | null = e.currentTarget.files;
|
const f: FileList | null = e.currentTarget.files;
|
||||||
if (!f || f.length != 1)
|
if (!f || f.length != 1) return props.onChange(undefined);
|
||||||
return props.onChange(undefined);
|
|
||||||
|
|
||||||
console.log(f);
|
console.log(f);
|
||||||
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
||||||
@ -39,7 +38,7 @@ export function FileButton(props: Props): VNode {
|
|||||||
return f[0].arrayBuffer().then((b) => {
|
return f[0].arrayBuffer().then((b) => {
|
||||||
const content = new Uint8Array(b).reduce(
|
const content = new Uint8Array(b).reduce(
|
||||||
(data, byte) => data + String.fromCharCode(byte),
|
(data, byte) => data + String.fromCharCode(byte),
|
||||||
'',
|
"",
|
||||||
);
|
);
|
||||||
return props.onChange({
|
return props.onChange({
|
||||||
content,
|
content,
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
|
|
||||||
export interface Notification {
|
export interface Notification {
|
||||||
message: string;
|
message: string;
|
||||||
@ -27,7 +27,7 @@ export interface Notification {
|
|||||||
type: MessageType;
|
type: MessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS';
|
export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
notifications: Notification[];
|
notifications: Notification[];
|
||||||
@ -36,16 +36,16 @@ interface Props {
|
|||||||
|
|
||||||
function messageStyle(type: MessageType): string {
|
function messageStyle(type: MessageType): string {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'INFO':
|
case "INFO":
|
||||||
return 'message is-info';
|
return "message is-info";
|
||||||
case 'WARN':
|
case "WARN":
|
||||||
return 'message is-warning';
|
return "message is-warning";
|
||||||
case 'ERROR':
|
case "ERROR":
|
||||||
return 'message is-danger';
|
return "message is-danger";
|
||||||
case 'SUCCESS':
|
case "SUCCESS":
|
||||||
return 'message is-success';
|
return "message is-success";
|
||||||
default:
|
default:
|
||||||
return 'message';
|
return "message";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useEffect, useRef } from 'preact/hooks';
|
import { useEffect, useRef } from "preact/hooks";
|
||||||
import qrcode from 'qrcode-generator';
|
import qrcode from "qrcode-generator";
|
||||||
|
|
||||||
export function QR({ text }: { text: string }): VNode {
|
export function QR({ text }: { text: string }): VNode {
|
||||||
const divRef = useRef<HTMLDivElement>(null);
|
const divRef = useRef<HTMLDivElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const qr = qrcode(0, 'L');
|
const qr = qrcode(0, "L");
|
||||||
qr.addData(text);
|
qr.addData(text);
|
||||||
qr.make();
|
qr.make();
|
||||||
if (divRef.current)
|
if (divRef.current)
|
||||||
@ -33,14 +33,14 @@ export function QR({ text }: { text: string }): VNode {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: "100%",
|
||||||
display: 'flex',
|
display: "flex",
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
alignItems: 'left',
|
alignItems: "left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{ width: '50%', minWidth: 200, maxWidth: 300 }}
|
style={{ width: "50%", minWidth: 200, maxWidth: 300 }}
|
||||||
ref={divRef}
|
ref={divRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { format, subYears } from 'date-fns';
|
import { format, subYears } from "date-fns";
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
import { DatePicker } from '../picker/DatePicker';
|
import { DatePicker } from "../picker/DatePicker";
|
||||||
|
|
||||||
export interface DateInputProps {
|
export interface DateInputProps {
|
||||||
label: string;
|
label: string;
|
||||||
@ -16,13 +16,11 @@ export interface DateInputProps {
|
|||||||
export function DateInput(props: DateInputProps): VNode {
|
export function DateInput(props: DateInputProps): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (props.grabFocus)
|
if (props.grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [props.grabFocus]);
|
}, [props.grabFocus]);
|
||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
|
|
||||||
const value = props.bind[0] || '';
|
const value = props.bind[0] || "";
|
||||||
const [dirty, setDirty] = useState(false);
|
const [dirty, setDirty] = useState(false);
|
||||||
const showError = dirty && props.error;
|
const showError = dirty && props.error;
|
||||||
|
|
||||||
@ -43,12 +41,10 @@ export function DateInput(props: DateInputProps): VNode {
|
|||||||
<p class="control">
|
<p class="control">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class={showError ? 'input is-danger' : 'input'}
|
class={showError ? "input is-danger" : "input"}
|
||||||
value={value}
|
value={value}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter' && props.onConfirm)
|
if (e.key === "Enter" && props.onConfirm) props.onConfirm();
|
||||||
props.onConfirm()
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onInput={(e) => {
|
onInput={(e) => {
|
||||||
const text = e.currentTarget.value;
|
const text = e.currentTarget.value;
|
||||||
@ -81,7 +77,7 @@ export function DateInput(props: DateInputProps): VNode {
|
|||||||
closeFunction={() => setOpened(false)}
|
closeFunction={() => setOpened(false)}
|
||||||
dateReceiver={(d) => {
|
dateReceiver={(d) => {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
const v = format(d, 'yyyy-MM-dd');
|
const v = format(d, "yyyy-MM-dd");
|
||||||
props.bind[1](v);
|
props.bind[1](v);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
export interface TextInputProps {
|
export interface TextInputProps {
|
||||||
label: string;
|
label: string;
|
||||||
@ -14,9 +14,7 @@ export interface TextInputProps {
|
|||||||
export function EmailInput(props: TextInputProps): VNode {
|
export function EmailInput(props: TextInputProps): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (props.grabFocus)
|
if (props.grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [props.grabFocus]);
|
}, [props.grabFocus]);
|
||||||
const value = props.bind[0];
|
const value = props.bind[0];
|
||||||
const [dirty, setDirty] = useState(false);
|
const [dirty, setDirty] = useState(false);
|
||||||
@ -37,18 +35,16 @@ export function EmailInput(props: TextInputProps): VNode {
|
|||||||
required
|
required
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
type="email"
|
type="email"
|
||||||
class={showError ? 'input is-danger' : 'input'}
|
class={showError ? "input is-danger" : "input"}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter' && props.onConfirm)
|
if (e.key === "Enter" && props.onConfirm) props.onConfirm();
|
||||||
props.onConfirm()
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onInput={(e) => {
|
onInput={(e) => {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
props.bind[1]((e.target as HTMLInputElement).value);
|
props.bind[1]((e.target as HTMLInputElement).value);
|
||||||
}}
|
}}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
style={{ display: 'block' }}
|
style={{ display: "block" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showError && <p class="help is-danger">{props.error}</p>}
|
{showError && <p class="help is-danger">{props.error}</p>}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
@ -42,9 +42,7 @@ export interface FileInputProps {
|
|||||||
export function FileInput(props: FileInputProps): VNode {
|
export function FileInput(props: FileInputProps): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (props.grabFocus)
|
if (props.grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [props.grabFocus]);
|
}, [props.grabFocus]);
|
||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
@ -56,9 +54,7 @@ export function FileInput(props: FileInputProps): VNode {
|
|||||||
<div class="icon is-small ">
|
<div class="icon is-small ">
|
||||||
<i class="mdi mdi-folder" />
|
<i class="mdi mdi-folder" />
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>{props.label}</span>
|
||||||
{props.label}
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
{props.tooltip && (
|
{props.tooltip && (
|
||||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||||
@ -69,15 +65,14 @@ export function FileInput(props: FileInputProps): VNode {
|
|||||||
<div class="control">
|
<div class="control">
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
style={{ display: 'none' }}
|
style={{ display: "none" }}
|
||||||
type="file"
|
type="file"
|
||||||
// name={String(name)}
|
// name={String(name)}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const f: FileList | null = e.currentTarget.files;
|
const f: FileList | null = e.currentTarget.files;
|
||||||
if (!f || f.length != 1)
|
if (!f || f.length != 1) return props.onChange(undefined);
|
||||||
return props.onChange(undefined);
|
|
||||||
|
|
||||||
console.log(f)
|
console.log(f);
|
||||||
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
||||||
setSizeError(true);
|
setSizeError(true);
|
||||||
return props.onChange(undefined);
|
return props.onChange(undefined);
|
||||||
@ -87,10 +82,14 @@ export function FileInput(props: FileInputProps): VNode {
|
|||||||
const b64 = btoa(
|
const b64 = btoa(
|
||||||
new Uint8Array(b).reduce(
|
new Uint8Array(b).reduce(
|
||||||
(data, byte) => data + String.fromCharCode(byte),
|
(data, byte) => data + String.fromCharCode(byte),
|
||||||
'',
|
"",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return props.onChange({content: `data:${f[0].type};base64,${b64}`, name: f[0].name, type: f[0].type});
|
return props.onChange({
|
||||||
|
content: `data:${f[0].type};base64,${b64}`,
|
||||||
|
name: f[0].name,
|
||||||
|
type: f[0].type,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -18,19 +18,17 @@
|
|||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
import emptyImage from '../../assets/empty.png';
|
import emptyImage from "../../assets/empty.png";
|
||||||
import { TextInputProps } from './TextInput';
|
import { TextInputProps } from "./TextInput";
|
||||||
|
|
||||||
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
export function ImageInput(props: TextInputProps): VNode {
|
export function ImageInput(props: TextInputProps): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (props.grabFocus)
|
if (props.grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [props.grabFocus]);
|
}, [props.grabFocus]);
|
||||||
|
|
||||||
const value = props.bind[0];
|
const value = props.bind[0];
|
||||||
@ -59,13 +57,12 @@ export function ImageInput(props: TextInputProps): VNode {
|
|||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
ref={image}
|
ref={image}
|
||||||
style={{ display: 'none' }}
|
style={{ display: "none" }}
|
||||||
type="file"
|
type="file"
|
||||||
name={String(name)}
|
name={String(name)}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const f: FileList | null = e.currentTarget.files;
|
const f: FileList | null = e.currentTarget.files;
|
||||||
if (!f || f.length != 1)
|
if (!f || f.length != 1) return onChange(emptyImage);
|
||||||
return onChange(emptyImage);
|
|
||||||
|
|
||||||
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
|
||||||
setSizeError(true);
|
setSizeError(true);
|
||||||
@ -76,7 +73,7 @@ export function ImageInput(props: TextInputProps): VNode {
|
|||||||
const b64 = btoa(
|
const b64 = btoa(
|
||||||
new Uint8Array(b).reduce(
|
new Uint8Array(b).reduce(
|
||||||
(data, byte) => data + String.fromCharCode(byte),
|
(data, byte) => data + String.fromCharCode(byte),
|
||||||
'',
|
"",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return onChange(`data:${f[0].type};base64,${b64}` as any);
|
return onChange(`data:${f[0].type};base64,${b64}` as any);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
export interface TextInputProps {
|
export interface TextInputProps {
|
||||||
label: string;
|
label: string;
|
||||||
@ -14,9 +14,7 @@ export interface TextInputProps {
|
|||||||
export function PhoneNumberInput(props: TextInputProps): VNode {
|
export function PhoneNumberInput(props: TextInputProps): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (props.grabFocus)
|
if (props.grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [props.grabFocus]);
|
}, [props.grabFocus]);
|
||||||
const value = props.bind[0];
|
const value = props.bind[0];
|
||||||
const [dirty, setDirty] = useState(false);
|
const [dirty, setDirty] = useState(false);
|
||||||
@ -36,18 +34,16 @@ export function PhoneNumberInput(props: TextInputProps): VNode {
|
|||||||
value={value}
|
value={value}
|
||||||
type="tel"
|
type="tel"
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
class={showError ? 'input is-danger' : 'input'}
|
class={showError ? "input is-danger" : "input"}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter' && props.onConfirm)
|
if (e.key === "Enter" && props.onConfirm) props.onConfirm();
|
||||||
props.onConfirm()
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onInput={(e) => {
|
onInput={(e) => {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
props.bind[1]((e.target as HTMLInputElement).value);
|
props.bind[1]((e.target as HTMLInputElement).value);
|
||||||
}}
|
}}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
style={{ display: 'block' }}
|
style={{ display: "block" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showError && <p class="help is-danger">{props.error}</p>}
|
{showError && <p class="help is-danger">{props.error}</p>}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useLayoutEffect, useRef, useState } from 'preact/hooks';
|
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
export interface TextInputProps {
|
export interface TextInputProps {
|
||||||
inputType?: 'text' | 'number' | 'multiline' | 'password';
|
inputType?: "text" | "number" | "multiline" | "password";
|
||||||
label: string;
|
label: string;
|
||||||
grabFocus?: boolean;
|
grabFocus?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@ -16,13 +16,11 @@ export interface TextInputProps {
|
|||||||
const TextInputType = function ({ inputType, grabFocus, ...rest }: any): VNode {
|
const TextInputType = function ({ inputType, grabFocus, ...rest }: any): VNode {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (grabFocus)
|
if (grabFocus) inputRef.current?.focus();
|
||||||
inputRef.current?.focus();
|
|
||||||
|
|
||||||
}, [grabFocus]);
|
}, [grabFocus]);
|
||||||
|
|
||||||
return inputType === 'multiline' ? (
|
return inputType === "multiline" ? (
|
||||||
<textarea {...rest} rows={5} ref={inputRef} style={{ height: 'unset' }} />
|
<textarea {...rest} rows={5} ref={inputRef} style={{ height: "unset" }} />
|
||||||
) : (
|
) : (
|
||||||
<input {...rest} type={inputType} ref={inputRef} />
|
<input {...rest} type={inputType} ref={inputRef} />
|
||||||
);
|
);
|
||||||
@ -49,17 +47,15 @@ export function TextInput(props: TextInputProps): VNode {
|
|||||||
grabFocus={props.grabFocus}
|
grabFocus={props.grabFocus}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
class={showError ? 'input is-danger' : 'input'}
|
class={showError ? "input is-danger" : "input"}
|
||||||
onKeyPress={(e: any) => {
|
onKeyPress={(e: any) => {
|
||||||
if (e.key === 'Enter' && props.onConfirm)
|
if (e.key === "Enter" && props.onConfirm) props.onConfirm();
|
||||||
props.onConfirm();
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onInput={(e: any) => {
|
onInput={(e: any) => {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
props.bind[1]((e.target as HTMLInputElement).value);
|
props.bind[1]((e.target as HTMLInputElement).value);
|
||||||
}}
|
}}
|
||||||
style={{ display: 'block' }}
|
style={{ display: "block" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showError && <p class="help is-danger">{props.error}</p>}
|
{showError && <p class="help is-danger">{props.error}</p>}
|
||||||
|
@ -19,23 +19,23 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode, Fragment } from 'preact';
|
import { h, VNode, Fragment } from "preact";
|
||||||
import { useCallback, useEffect, useState } from 'preact/hooks';
|
import { useCallback, useEffect, useState } from "preact/hooks";
|
||||||
import langIcon from '../../assets/icons/languageicon.svg';
|
import langIcon from "../../assets/icons/languageicon.svg";
|
||||||
import { useTranslationContext } from '../../context/translation';
|
import { useTranslationContext } from "../../context/translation";
|
||||||
import { strings as messages } from '../../i18n/strings';
|
import { strings as messages } from "../../i18n/strings";
|
||||||
|
|
||||||
type LangsNames = {
|
type LangsNames = {
|
||||||
[P in keyof typeof messages]: string;
|
[P in keyof typeof messages]: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const names: LangsNames = {
|
const names: LangsNames = {
|
||||||
es: 'Español [es]',
|
es: "Español [es]",
|
||||||
en: 'English [en]',
|
en: "English [en]",
|
||||||
fr: 'Français [fr]',
|
fr: "Français [fr]",
|
||||||
de: 'Deutsch [de]',
|
de: "Deutsch [de]",
|
||||||
sv: 'Svenska [sv]',
|
sv: "Svenska [sv]",
|
||||||
it: 'Italiano [it]',
|
it: "Italiano [it]",
|
||||||
};
|
};
|
||||||
|
|
||||||
function getLangName(s: keyof LangsNames | string): string {
|
function getLangName(s: keyof LangsNames | string): string {
|
||||||
@ -47,36 +47,38 @@ function getLangName(s: keyof LangsNames | string): string {
|
|||||||
export function LangSelectorLikePy(): VNode {
|
export function LangSelectorLikePy(): VNode {
|
||||||
const [updatingLang, setUpdatingLang] = useState(false);
|
const [updatingLang, setUpdatingLang] = useState(false);
|
||||||
const { lang, changeLanguage } = useTranslationContext();
|
const { lang, changeLanguage } = useTranslationContext();
|
||||||
const [hidden, setHidden] = useState(true)
|
const [hidden, setHidden] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function bodyKeyPress(event:KeyboardEvent) {
|
function bodyKeyPress(event: KeyboardEvent) {
|
||||||
if (event.code === 'Escape')
|
if (event.code === "Escape") setHidden(true);
|
||||||
setHidden(true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
function bodyOnClick(event:Event) {
|
function bodyOnClick(event: Event) {
|
||||||
setHidden(true);
|
setHidden(true);
|
||||||
}
|
}
|
||||||
document.body.addEventListener('click', bodyOnClick)
|
document.body.addEventListener("click", bodyOnClick);
|
||||||
document.body.addEventListener('keydown', bodyKeyPress as any)
|
document.body.addEventListener("keydown", bodyKeyPress as any);
|
||||||
return () => {
|
return () => {
|
||||||
document.body.removeEventListener('keydown', bodyKeyPress as any)
|
document.body.removeEventListener("keydown", bodyKeyPress as any);
|
||||||
document.body.removeEventListener('click', bodyOnClick)
|
document.body.removeEventListener("click", bodyOnClick);
|
||||||
}
|
};
|
||||||
},[])
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<button name="language" onClick={(ev) => {
|
<button
|
||||||
setHidden(h => !h);
|
name="language"
|
||||||
ev.stopPropagation();
|
onClick={(ev) => {
|
||||||
}}>
|
setHidden((h) => !h);
|
||||||
|
ev.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
{getLangName(lang)}
|
{getLangName(lang)}
|
||||||
</button>
|
</button>
|
||||||
<div id="lang" class={hidden ? 'hide' : ''}>
|
<div id="lang" class={hidden ? "hide" : ""}>
|
||||||
<div style="position: relative; overflow: visible;">
|
<div style="position: relative; overflow: visible;">
|
||||||
<div
|
<div
|
||||||
class="nav"
|
class="nav"
|
||||||
style="position: absolute; max-height: 60vh; overflow-y: scroll">
|
style="position: absolute; max-height: 60vh; overflow-y: scroll"
|
||||||
|
>
|
||||||
{Object.keys(messages)
|
{Object.keys(messages)
|
||||||
.filter((l) => l !== lang)
|
.filter((l) => l !== lang)
|
||||||
.map((l) => (
|
.map((l) => (
|
||||||
@ -88,7 +90,8 @@ export function LangSelectorLikePy(): VNode {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeLanguage(l);
|
changeLanguage(l);
|
||||||
setUpdatingLang(false);
|
setUpdatingLang(false);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{getLangName(l)}
|
{getLangName(l)}
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import logo from '../../assets/logo.jpeg';
|
import logo from "../../assets/logo.jpeg";
|
||||||
import { LangSelectorLikePy as LangSelector } from './LangSelector';
|
import { LangSelectorLikePy as LangSelector } from "./LangSelector";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onMobileMenu: () => void;
|
onMobileMenu: () => void;
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { Translate } from '../../i18n';
|
import { Translate } from "../../i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
mobile?: boolean;
|
mobile?: boolean;
|
||||||
@ -28,9 +28,9 @@ interface Props {
|
|||||||
|
|
||||||
export function Sidebar({ mobile }: Props): VNode {
|
export function Sidebar({ mobile }: Props): VNode {
|
||||||
// const config = useConfigContext();
|
// const config = useConfigContext();
|
||||||
const config = { version: 'none' };
|
const config = { version: "none" };
|
||||||
// FIXME: add replacement for __VERSION__ with the current version
|
// FIXME: add replacement for __VERSION__ with the current version
|
||||||
const process = { env: { __VERSION__: '0.0.0' } };
|
const process = { env: { __VERSION__: "0.0.0" } };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside class="aside is-placed-left is-expanded">
|
<aside class="aside is-placed-left is-expanded">
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentChildren, Fragment, h, VNode } from 'preact';
|
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||||
import Match from 'preact-router/match';
|
import Match from "preact-router/match";
|
||||||
import { useEffect, useState } from 'preact/hooks';
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { NavigationBar } from './NavigationBar';
|
import { NavigationBar } from "./NavigationBar";
|
||||||
import { Sidebar } from './SideBar';
|
import { Sidebar } from "./SideBar";
|
||||||
|
|
||||||
interface MenuProps {
|
interface MenuProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -47,7 +47,7 @@ export function Menu({ title }: MenuProps): VNode {
|
|||||||
return (
|
return (
|
||||||
<WithTitle title={titleWithSubtitle}>
|
<WithTitle title={titleWithSubtitle}>
|
||||||
<div
|
<div
|
||||||
class={mobileOpen ? 'has-aside-mobile-expanded' : ''}
|
class={mobileOpen ? "has-aside-mobile-expanded" : ""}
|
||||||
onClick={() => setMobileOpen(false)}
|
onClick={() => setMobileOpen(false)}
|
||||||
>
|
>
|
||||||
<NavigationBar
|
<NavigationBar
|
||||||
@ -82,11 +82,11 @@ export function NotificationCard({
|
|||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
<article
|
<article
|
||||||
class={
|
class={
|
||||||
n.type === 'ERROR'
|
n.type === "ERROR"
|
||||||
? 'message is-danger'
|
? "message is-danger"
|
||||||
: n.type === 'WARN'
|
: n.type === "WARN"
|
||||||
? 'message is-warning'
|
? "message is-warning"
|
||||||
: 'message is-info'
|
: "message is-info"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div class="message-header">
|
<div class="message-header">
|
||||||
@ -132,4 +132,4 @@ export interface Notification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ValueOrFunction<T> = T | ((p: T) => T);
|
export type ValueOrFunction<T> = T | ((p: T) => T);
|
||||||
export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS';
|
export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS";
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, Component } from 'preact';
|
import { h, Component } from "preact";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
closeFunction?: () => void;
|
closeFunction?: () => void;
|
||||||
@ -37,36 +37,36 @@ interface State {
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
const monthArrShortFull = [
|
const monthArrShortFull = [
|
||||||
'January',
|
"January",
|
||||||
'February',
|
"February",
|
||||||
'March',
|
"March",
|
||||||
'April',
|
"April",
|
||||||
'May',
|
"May",
|
||||||
'June',
|
"June",
|
||||||
'July',
|
"July",
|
||||||
'August',
|
"August",
|
||||||
'September',
|
"September",
|
||||||
'October',
|
"October",
|
||||||
'November',
|
"November",
|
||||||
'December',
|
"December",
|
||||||
];
|
];
|
||||||
|
|
||||||
const monthArrShort = [
|
const monthArrShort = [
|
||||||
'Jan',
|
"Jan",
|
||||||
'Feb',
|
"Feb",
|
||||||
'Mar',
|
"Mar",
|
||||||
'Apr',
|
"Apr",
|
||||||
'May',
|
"May",
|
||||||
'Jun',
|
"Jun",
|
||||||
'Jul',
|
"Jul",
|
||||||
'Aug',
|
"Aug",
|
||||||
'Sep',
|
"Sep",
|
||||||
'Oct',
|
"Oct",
|
||||||
'Nov',
|
"Nov",
|
||||||
'Dec',
|
"Dec",
|
||||||
];
|
];
|
||||||
|
|
||||||
const dayArr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
const dayArr = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||||
|
|
||||||
const yearArr: number[] = [];
|
const yearArr: number[] = [];
|
||||||
|
|
||||||
@ -83,10 +83,10 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
dayClicked(e: any) {
|
dayClicked(e: any) {
|
||||||
const element = e.target; // the actual element clicked
|
const element = e.target; // the actual element clicked
|
||||||
|
|
||||||
if (element.innerHTML === '') return false; // don't continue if <span /> empty
|
if (element.innerHTML === "") return false; // don't continue if <span /> empty
|
||||||
|
|
||||||
// get date from clicked element (gets attached when rendered)
|
// get date from clicked element (gets attached when rendered)
|
||||||
const date = new Date(element.getAttribute('data-value'));
|
const date = new Date(element.getAttribute("data-value"));
|
||||||
|
|
||||||
// update the state
|
// update the state
|
||||||
this.setState({ currentDate: date });
|
this.setState({ currentDate: date });
|
||||||
@ -140,7 +140,6 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
displayedMonth: this.state.displayedMonth - 1,
|
displayedMonth: this.state.displayedMonth - 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,15 +155,13 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
displayedMonth: this.state.displayedMonth + 1,
|
displayedMonth: this.state.displayedMonth + 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the selected month (gets fired when clicking on the date string)
|
* Display the selected month (gets fired when clicking on the date string)
|
||||||
*/
|
*/
|
||||||
displaySelectedMonth() {
|
displaySelectedMonth() {
|
||||||
if (this.state.selectYearMode)
|
if (this.state.selectYearMode) this.toggleYearSelector();
|
||||||
this.toggleYearSelector();
|
|
||||||
else {
|
else {
|
||||||
if (!this.state.currentDate) return false;
|
if (!this.state.currentDate) return false;
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -194,7 +191,7 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
this.passDateToParent(this.state.currentDate);
|
this.passDateToParent(this.state.currentDate);
|
||||||
}
|
}
|
||||||
passDateToParent(date: Date) {
|
passDateToParent(date: Date) {
|
||||||
if (typeof this.props.dateReceiver === 'function')
|
if (typeof this.props.dateReceiver === "function")
|
||||||
this.props.dateReceiver(date);
|
this.props.dateReceiver(date);
|
||||||
this.closeDatePicker();
|
this.closeDatePicker();
|
||||||
}
|
}
|
||||||
@ -229,22 +226,18 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { currentDate, displayedMonth, displayedYear, selectYearMode } =
|
||||||
currentDate,
|
this.state;
|
||||||
displayedMonth,
|
|
||||||
displayedYear,
|
|
||||||
selectYearMode,
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div class={`datePicker ${this.props.opened && 'datePicker--opened'}`}>
|
<div class={`datePicker ${this.props.opened && "datePicker--opened"}`}>
|
||||||
<div class="datePicker--titles">
|
<div class="datePicker--titles">
|
||||||
<h3
|
<h3
|
||||||
style={{
|
style={{
|
||||||
color: selectYearMode
|
color: selectYearMode
|
||||||
? 'rgba(255,255,255,.87)'
|
? "rgba(255,255,255,.87)"
|
||||||
: 'rgba(255,255,255,.57)',
|
: "rgba(255,255,255,.57)",
|
||||||
}}
|
}}
|
||||||
onClick={this.toggleYearSelector}
|
onClick={this.toggleYearSelector}
|
||||||
>
|
>
|
||||||
@ -253,12 +246,12 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
<h2
|
<h2
|
||||||
style={{
|
style={{
|
||||||
color: !selectYearMode
|
color: !selectYearMode
|
||||||
? 'rgba(255,255,255,.87)'
|
? "rgba(255,255,255,.87)"
|
||||||
: 'rgba(255,255,255,.57)',
|
: "rgba(255,255,255,.57)",
|
||||||
}}
|
}}
|
||||||
onClick={this.displaySelectedMonth}
|
onClick={this.displaySelectedMonth}
|
||||||
>
|
>
|
||||||
{dayArr[currentDate.getDay()]},{' '}
|
{dayArr[currentDate.getDay()]},{" "}
|
||||||
{monthArrShort[currentDate.getMonth()]} {currentDate.getDate()}
|
{monthArrShort[currentDate.getMonth()]} {currentDate.getDate()}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -267,7 +260,7 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
<nav>
|
<nav>
|
||||||
<span onClick={this.displayPrevMonth} class="icon">
|
<span onClick={this.displayPrevMonth} class="icon">
|
||||||
<i
|
<i
|
||||||
style={{ transform: 'rotate(180deg)' }}
|
style={{ transform: "rotate(180deg)" }}
|
||||||
class="mdi mdi-forward"
|
class="mdi mdi-forward"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@ -284,7 +277,7 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
{!selectYearMode && (
|
{!selectYearMode && (
|
||||||
<div class="datePicker--calendar">
|
<div class="datePicker--calendar">
|
||||||
<div class="datePicker--dayNames">
|
<div class="datePicker--dayNames">
|
||||||
{['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((day, i) => (
|
{["S", "M", "T", "W", "T", "F", "S"].map((day, i) => (
|
||||||
<span key={i}>{day}</span>
|
<span key={i}>{day}</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -309,8 +302,8 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
<span
|
<span
|
||||||
key={day.day}
|
key={day.day}
|
||||||
class={
|
class={
|
||||||
(day.today ? 'datePicker--today ' : '') +
|
(day.today ? "datePicker--today " : "") +
|
||||||
(selected ? 'datePicker--selected' : '')
|
(selected ? "datePicker--selected" : "")
|
||||||
}
|
}
|
||||||
disabled={!day.date}
|
disabled={!day.date}
|
||||||
data-value={day.date}
|
data-value={day.date}
|
||||||
@ -328,7 +321,7 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
{(this.props.years || yearArr).map((year) => (
|
{(this.props.years || yearArr).map((year) => (
|
||||||
<span
|
<span
|
||||||
key={year}
|
key={year}
|
||||||
class={year === displayedYear ? 'selected' : ''}
|
class={year === displayedYear ? "selected" : ""}
|
||||||
onClick={this.changeDisplayedYear}
|
onClick={this.changeDisplayedYear}
|
||||||
>
|
>
|
||||||
{year}
|
{year}
|
||||||
@ -343,7 +336,7 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
class="datePicker--background"
|
class="datePicker--background"
|
||||||
onClick={this.closeDatePicker}
|
onClick={this.closeDatePicker}
|
||||||
style={{
|
style={{
|
||||||
display: this.props.opened ? 'block' : 'none',
|
display: this.props.opened ? "block" : "none",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -351,6 +344,4 @@ export class DatePicker extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 2010; i <= now.getFullYear() + 10; i++)
|
for (let i = 2010; i <= now.getFullYear() + 10; i++) yearArr.push(i);
|
||||||
yearArr.push(i);
|
|
||||||
|
|
||||||
|
@ -19,16 +19,16 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, FunctionalComponent } from 'preact';
|
import { h, FunctionalComponent } from "preact";
|
||||||
import { useState } from 'preact/hooks';
|
import { useState } from "preact/hooks";
|
||||||
import { DurationPicker as TestedComponent } from './DurationPicker';
|
import { DurationPicker as TestedComponent } from "./DurationPicker";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Picker/Duration',
|
title: "Components/Picker/Duration",
|
||||||
component: TestedComponent,
|
component: TestedComponent,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
onCreate: { action: 'onCreate' },
|
onCreate: { action: "onCreate" },
|
||||||
goBack: { action: 'goBack' },
|
goBack: { action: "goBack" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from 'preact';
|
import { h, VNode } from "preact";
|
||||||
import { useState } from 'preact/hooks';
|
import { useState } from "preact/hooks";
|
||||||
import { useTranslator } from '../../i18n';
|
import { useTranslator } from "../../i18n";
|
||||||
import '../../scss/DurationPicker.scss';
|
import "../../scss/DurationPicker.scss";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
hours?: boolean;
|
hours?: boolean;
|
||||||
@ -129,9 +129,9 @@ function InputNumber({
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
width: 50,
|
width: 50,
|
||||||
border: 'none',
|
border: "none",
|
||||||
fontSize: 'inherit',
|
fontSize: "inherit",
|
||||||
background: 'inherit',
|
background: "inherit",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -157,7 +157,7 @@ function DurationColumn({
|
|||||||
<div class="rdp-cell" key={value - 2}>
|
<div class="rdp-cell" key={value - 2}>
|
||||||
{onDecrease && (
|
{onDecrease && (
|
||||||
<button
|
<button
|
||||||
style={{ width: '100%', textAlign: 'center', margin: 5 }}
|
style={{ width: "100%", textAlign: "center", margin: 5 }}
|
||||||
onClick={onDecrease}
|
onClick={onDecrease}
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@ -167,7 +167,7 @@ function DurationColumn({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div class="rdp-cell" key={value - 1}>
|
<div class="rdp-cell" key={value - 1}>
|
||||||
{value > min ? toTwoDigitString(value - 1) : ''}
|
{value > min ? toTwoDigitString(value - 1) : ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="rdp-cell rdp-center" key={value}>
|
<div class="rdp-cell rdp-center" key={value}>
|
||||||
{onChange ? (
|
{onChange ? (
|
||||||
@ -182,13 +182,13 @@ function DurationColumn({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rdp-cell" key={value + 1}>
|
<div class="rdp-cell" key={value + 1}>
|
||||||
{value < max ? toTwoDigitString(value + 1) : ''}
|
{value < max ? toTwoDigitString(value + 1) : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rdp-cell" key={value + 2}>
|
<div class="rdp-cell" key={value + 2}>
|
||||||
{onIncrease && (
|
{onIncrease && (
|
||||||
<button
|
<button
|
||||||
style={{ width: '100%', textAlign: 'center', margin: 5 }}
|
style={{ width: "100%", textAlign: "center", margin: 5 }}
|
||||||
onClick={onIncrease}
|
onClick={onIncrease}
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@ -204,8 +204,7 @@ function DurationColumn({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toTwoDigitString(n: number) {
|
function toTwoDigitString(n: number) {
|
||||||
if (n < 10)
|
if (n < 10) return `0${n}`;
|
||||||
return `0${n}`;
|
|
||||||
|
|
||||||
return `${n}`;
|
return `${n}`;
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createContext, h, VNode } from 'preact';
|
import { createContext, h, VNode } from "preact";
|
||||||
import { useContext, useEffect } from 'preact/hooks';
|
import { useContext, useEffect } from "preact/hooks";
|
||||||
import { useLang } from '../hooks/index.js';
|
import { useLang } from "../hooks/index.js";
|
||||||
import * as jedLib from 'jed';
|
import * as jedLib from "jed";
|
||||||
import { strings } from '../i18n/strings.js';
|
import { strings } from "../i18n/strings.js";
|
||||||
|
|
||||||
interface Type {
|
interface Type {
|
||||||
lang: string;
|
lang: string;
|
||||||
@ -31,7 +31,7 @@ interface Type {
|
|||||||
changeLanguage: (l: string) => void;
|
changeLanguage: (l: string) => void;
|
||||||
}
|
}
|
||||||
const initial = {
|
const initial = {
|
||||||
lang: 'en',
|
lang: "en",
|
||||||
handler: null,
|
handler: null,
|
||||||
changeLanguage: () => {
|
changeLanguage: () => {
|
||||||
/**
|
/**
|
||||||
@ -55,15 +55,12 @@ export const TranslationProvider = ({
|
|||||||
children,
|
children,
|
||||||
forceLang,
|
forceLang,
|
||||||
}: Props): VNode => {
|
}: Props): VNode => {
|
||||||
|
|
||||||
const [lang, changeLanguage] = useLang(initial);
|
const [lang, changeLanguage] = useLang(initial);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (forceLang)
|
if (forceLang) changeLanguage(forceLang);
|
||||||
changeLanguage(forceLang);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
console.log('lang store', strings);
|
console.log("lang store", strings);
|
||||||
const handler = new jedLib.Jed(strings[lang] || strings['en']);
|
const handler = new jedLib.Jed(strings[lang] || strings["en"]);
|
||||||
return h(Context.Provider, {
|
return h(Context.Provider, {
|
||||||
value: { lang, handler, changeLanguage },
|
value: { lang, handler, changeLanguage },
|
||||||
children,
|
children,
|
||||||
|
10
packages/demobank-ui/src/declaration.d.ts
vendored
10
packages/demobank-ui/src/declaration.d.ts
vendored
@ -1,20 +1,20 @@
|
|||||||
declare module '*.css' {
|
declare module "*.css" {
|
||||||
const mapping: Record<string, string>;
|
const mapping: Record<string, string>;
|
||||||
export default mapping;
|
export default mapping;
|
||||||
}
|
}
|
||||||
declare module '*.svg' {
|
declare module "*.svg" {
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
declare module '*.jpeg' {
|
declare module "*.jpeg" {
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
declare module '*.png' {
|
declare module "*.png" {
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
declare module 'jed' {
|
declare module "jed" {
|
||||||
const x: any;
|
const x: any;
|
||||||
export = x;
|
export = x;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
import { useState } from 'preact/hooks';
|
import { useState } from "preact/hooks";
|
||||||
// import { cancelPendingRequest } from "./backend";
|
// import { cancelPendingRequest } from "./backend";
|
||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
@ -51,9 +51,9 @@ export function useAsync<T>(
|
|||||||
}, tooLong);
|
}, tooLong);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('calling async', args);
|
console.log("calling async", args);
|
||||||
const result = await fn(...args);
|
const result = await fn(...args);
|
||||||
console.log('async back', result);
|
console.log("async back", result);
|
||||||
setData(result);
|
setData(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError(error);
|
setError(error);
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
/**
|
/**
|
||||||
* Imports
|
* Imports
|
||||||
*/
|
*/
|
||||||
import { ComponentChild, ComponentChildren, h, Fragment, VNode } from 'preact';
|
import { ComponentChild, ComponentChildren, h, Fragment, VNode } from "preact";
|
||||||
|
|
||||||
import { useTranslationContext } from '../context/translation';
|
import { useTranslationContext } from "../context/translation";
|
||||||
|
|
||||||
export function useTranslator() {
|
export function useTranslator() {
|
||||||
const ctx = useTranslationContext();
|
const ctx = useTranslationContext();
|
||||||
@ -46,12 +46,10 @@ export function useTranslator() {
|
|||||||
* Convert template strings to a msgid
|
* Convert template strings to a msgid
|
||||||
*/
|
*/
|
||||||
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
||||||
let s = '';
|
let s = "";
|
||||||
for (let i = 0; i < stringSeq.length; i++) {
|
for (let i = 0; i < stringSeq.length; i++) {
|
||||||
s += stringSeq[i];
|
s += stringSeq[i];
|
||||||
if (i < stringSeq.length - 1)
|
if (i < stringSeq.length - 1) s += `%${i + 1}$s`;
|
||||||
s += `%${i + 1}$s`;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -64,12 +62,11 @@ interface TranslateSwitchProps {
|
|||||||
function stringifyChildren(children: ComponentChildren): string {
|
function stringifyChildren(children: ComponentChildren): string {
|
||||||
let n = 1;
|
let n = 1;
|
||||||
const ss = (children instanceof Array ? children : [children]).map((c) => {
|
const ss = (children instanceof Array ? children : [children]).map((c) => {
|
||||||
if (typeof c === 'string')
|
if (typeof c === "string") return c;
|
||||||
return c;
|
|
||||||
|
|
||||||
return `%${n++}$s`;
|
return `%${n++}$s`;
|
||||||
});
|
});
|
||||||
const s = ss.join('').replace(/ +/g, ' ').trim();
|
const s = ss.join("").replace(/ +/g, " ").trim();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,13 +94,9 @@ function getTranslatedChildren(
|
|||||||
const placeholderChildren = Array<ComponentChild>();
|
const placeholderChildren = Array<ComponentChild>();
|
||||||
for (let i = 0; i < childArray.length; i++) {
|
for (let i = 0; i < childArray.length; i++) {
|
||||||
const x = childArray[i];
|
const x = childArray[i];
|
||||||
if (x === undefined)
|
if (x === undefined) continue;
|
||||||
continue;
|
else if (typeof x === "string") continue;
|
||||||
else if (typeof x === 'string')
|
else placeholderChildren.push(x);
|
||||||
continue;
|
|
||||||
else
|
|
||||||
placeholderChildren.push(x);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
const result = Array<ComponentChild>();
|
const result = Array<ComponentChild>();
|
||||||
for (let i = 0; i < tr.length; i++)
|
for (let i = 0; i < tr.length; i++)
|
||||||
@ -157,18 +150,15 @@ export function TranslateSwitch({ children, target }: TranslateSwitchProps) {
|
|||||||
if (children)
|
if (children)
|
||||||
(children instanceof Array ? children : [children]).forEach(
|
(children instanceof Array ? children : [children]).forEach(
|
||||||
(child: any) => {
|
(child: any) => {
|
||||||
if (child.type === TranslatePlural)
|
if (child.type === TranslatePlural) plural = child;
|
||||||
plural = child;
|
|
||||||
|
|
||||||
if (child.type === TranslateSingular)
|
|
||||||
singular = child;
|
|
||||||
|
|
||||||
|
if (child.type === TranslateSingular) singular = child;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!singular || !plural) {
|
if (!singular || !plural) {
|
||||||
console.error('translation not found');
|
console.error("translation not found");
|
||||||
return h('span', {}, ['translation not found']);
|
return h("span", {}, ["translation not found"]);
|
||||||
}
|
}
|
||||||
singular.props.target = target;
|
singular.props.target = target;
|
||||||
plural.props.target = target;
|
plural.props.target = target;
|
||||||
|
@ -15,458 +15,207 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*eslint quote-props: ["error", "consistent"]*/
|
/*eslint quote-props: ["error", "consistent"]*/
|
||||||
export const strings: {[s: string]: any} = {};
|
export const strings: { [s: string]: any } = {};
|
||||||
|
|
||||||
strings['de'] = {
|
strings["de"] = {
|
||||||
'domain': 'messages',
|
domain: "messages",
|
||||||
'locale_data': {
|
locale_data: {
|
||||||
'messages': {
|
messages: {
|
||||||
'days': [
|
days: [""],
|
||||||
''
|
hours: [""],
|
||||||
],
|
minutes: [""],
|
||||||
'hours': [
|
seconds: [""],
|
||||||
''
|
Clear: [""],
|
||||||
],
|
Logout: [""],
|
||||||
'minutes': [
|
"Demo Bank": [""],
|
||||||
''
|
"Go back": [""],
|
||||||
],
|
"Wire transfer": [""],
|
||||||
'seconds': [
|
"Transfer money to another account of this bank:": [""],
|
||||||
''
|
"Want to try the raw payto://-format?": [""],
|
||||||
],
|
"Transfer money via the Payto system:": [""],
|
||||||
'Clear': [
|
"payto address": [""],
|
||||||
''
|
Confirm: [""],
|
||||||
],
|
"Confirm Withdrawal": [""],
|
||||||
'Logout': [
|
"Waiting the bank to create the operaion...": [""],
|
||||||
''
|
"This withdrawal was aborted!": [""],
|
||||||
],
|
"Withdraw to a Taler Wallet": [""],
|
||||||
'Demo Bank': [
|
"You can use this QR code to withdraw to your mobile wallet:": [""],
|
||||||
''
|
"this link": [""],
|
||||||
],
|
Abort: [""],
|
||||||
'Go back': [
|
"Start withdrawal": [""],
|
||||||
''
|
"Withdraw Money into a Taler wallet": [""],
|
||||||
],
|
"Amount to withdraw": [""],
|
||||||
'Wire transfer': [
|
"Please login!": [""],
|
||||||
''
|
Login: [""],
|
||||||
],
|
"Register to the euFin bank!": [""],
|
||||||
'Transfer money to another account of this bank:': [
|
"Registration form": [""],
|
||||||
''
|
Register: [""],
|
||||||
],
|
Date: [""],
|
||||||
'Want to try the raw payto://-format?': [
|
Amount: [""],
|
||||||
''
|
Counterpart: [""],
|
||||||
],
|
Subject: [""],
|
||||||
'Transfer money via the Payto system:': [
|
"Username or account label '%1$s' not found. Won't login.": [""],
|
||||||
''
|
"Wrong credentials given.": [""],
|
||||||
],
|
"Account information could not be retrieved.": [""],
|
||||||
'payto address': [
|
"Close wire transfer": [""],
|
||||||
''
|
"Close Taler withdrawal": [""],
|
||||||
],
|
"Bank account balance:": [""],
|
||||||
'Confirm': [
|
"Latest transactions:": [""],
|
||||||
''
|
"Transfer money manually": [""],
|
||||||
],
|
"List of public accounts was not found.": [""],
|
||||||
'Confirm Withdrawal': [
|
"List of public accounts could not be retrieved.": [""],
|
||||||
''
|
"History of public accounts": [""],
|
||||||
],
|
"Page has a problem: logged in but backend state is lost.": [""],
|
||||||
'Waiting the bank to create the operaion...': [
|
"Welcome to the euFin bank!": [""],
|
||||||
''
|
"": {
|
||||||
],
|
domain: "messages",
|
||||||
'This withdrawal was aborted!': [
|
plural_forms: "nplurals=2; plural=(n != 1);",
|
||||||
''
|
lang: "de",
|
||||||
],
|
},
|
||||||
'Withdraw to a Taler Wallet': [
|
},
|
||||||
''
|
},
|
||||||
],
|
|
||||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'this link': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Abort': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Start withdrawal': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Withdraw Money into a Taler wallet': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Amount to withdraw': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Please login!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Login': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Register to the euFin bank!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Registration form': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Register': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Date': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Amount': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Counterpart': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Subject': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Wrong credentials given.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Account information could not be retrieved.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Close wire transfer': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Close Taler withdrawal': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Bank account balance:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Latest transactions:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Transfer money manually': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'List of public accounts was not found.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'List of public accounts could not be retrieved.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'History of public accounts': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Page has a problem: logged in but backend state is lost.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Welcome to the euFin bank!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'': {
|
|
||||||
'domain': 'messages',
|
|
||||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
|
||||||
'lang': 'de'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
strings['en'] = {
|
strings["en"] = {
|
||||||
'domain': 'messages',
|
domain: "messages",
|
||||||
'locale_data': {
|
locale_data: {
|
||||||
'messages': {
|
messages: {
|
||||||
'days': [
|
days: ["days"],
|
||||||
'days'
|
hours: ["hours"],
|
||||||
|
minutes: ["minutes"],
|
||||||
|
seconds: ["seconds"],
|
||||||
|
Clear: [""],
|
||||||
|
Logout: [""],
|
||||||
|
"Demo Bank": [""],
|
||||||
|
"Go back": ["Go back"],
|
||||||
|
"Wire transfer": [""],
|
||||||
|
"Transfer money to another account of this bank:": [""],
|
||||||
|
"Want to try the raw payto://-format?": [""],
|
||||||
|
"Transfer money via the Payto system:": [""],
|
||||||
|
"payto address": [""],
|
||||||
|
Confirm: [""],
|
||||||
|
"Confirm Withdrawal": ["Confirm withdrawal"],
|
||||||
|
"Waiting the bank to create the operaion...": [""],
|
||||||
|
"This withdrawal was aborted!": [""],
|
||||||
|
"Withdraw to a Taler Wallet": ["Charge Taler wallet"],
|
||||||
|
"You can use this QR code to withdraw to your mobile wallet:": [""],
|
||||||
|
"this link": [""],
|
||||||
|
Abort: [""],
|
||||||
|
"Start withdrawal": ["Start withdrawal"],
|
||||||
|
"Withdraw Money into a Taler wallet": ["Charge Taler wallet"],
|
||||||
|
"Amount to withdraw": ["Amount to withdraw"],
|
||||||
|
"Please login!": [""],
|
||||||
|
Login: [""],
|
||||||
|
"Register to the euFin bank!": [""],
|
||||||
|
"Registration form": [""],
|
||||||
|
Register: [""],
|
||||||
|
Date: [""],
|
||||||
|
Amount: [""],
|
||||||
|
Counterpart: [""],
|
||||||
|
Subject: [""],
|
||||||
|
"Username or account label '%1$s' not found. Won't login.": [""],
|
||||||
|
"Wrong credentials given.": [""],
|
||||||
|
"Account information could not be retrieved.": [""],
|
||||||
|
"Close wire transfer": [""],
|
||||||
|
"Close Taler withdrawal": ["Close Taler withdrawal"],
|
||||||
|
"Bank account balance:": [""],
|
||||||
|
"Latest transactions:": [""],
|
||||||
|
"Transfer money manually": [""],
|
||||||
|
"List of public accounts was not found.": [""],
|
||||||
|
"List of public accounts could not be retrieved.": [""],
|
||||||
|
"History of public accounts": [""],
|
||||||
|
"Page has a problem: logged in but backend state is lost.": [
|
||||||
|
"Page has a problem: logged in but backend state is lost.",
|
||||||
],
|
],
|
||||||
'hours': [
|
"Welcome to the euFin bank!": [
|
||||||
'hours'
|
"Welcome to euFin bank: Taler+IBAN now possible!",
|
||||||
],
|
],
|
||||||
'minutes': [
|
"": {
|
||||||
'minutes'
|
domain: "messages",
|
||||||
],
|
plural_forms: "nplurals=2; plural=(n != 1);",
|
||||||
'seconds': [
|
lang: "en",
|
||||||
'seconds'
|
},
|
||||||
],
|
},
|
||||||
'Clear': [
|
},
|
||||||
''
|
|
||||||
],
|
|
||||||
'Logout': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Demo Bank': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Go back': [
|
|
||||||
'Go back'
|
|
||||||
],
|
|
||||||
'Wire transfer': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Transfer money to another account of this bank:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Want to try the raw payto://-format?': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Transfer money via the Payto system:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'payto address': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Confirm': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Confirm Withdrawal': [
|
|
||||||
'Confirm withdrawal'
|
|
||||||
],
|
|
||||||
'Waiting the bank to create the operaion...': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'This withdrawal was aborted!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Withdraw to a Taler Wallet': [
|
|
||||||
'Charge Taler wallet'
|
|
||||||
],
|
|
||||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'this link': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Abort': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Start withdrawal': [
|
|
||||||
'Start withdrawal'
|
|
||||||
],
|
|
||||||
'Withdraw Money into a Taler wallet': [
|
|
||||||
'Charge Taler wallet'
|
|
||||||
],
|
|
||||||
'Amount to withdraw': [
|
|
||||||
'Amount to withdraw'
|
|
||||||
],
|
|
||||||
'Please login!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Login': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Register to the euFin bank!': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Registration form': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Register': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Date': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Amount': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Counterpart': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Subject': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Wrong credentials given.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Account information could not be retrieved.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Close wire transfer': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Close Taler withdrawal': [
|
|
||||||
'Close Taler withdrawal'
|
|
||||||
],
|
|
||||||
'Bank account balance:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Latest transactions:': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Transfer money manually': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'List of public accounts was not found.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'List of public accounts could not be retrieved.': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'History of public accounts': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Page has a problem: logged in but backend state is lost.': [
|
|
||||||
'Page has a problem: logged in but backend state is lost.'
|
|
||||||
],
|
|
||||||
'Welcome to the euFin bank!': [
|
|
||||||
'Welcome to euFin bank: Taler+IBAN now possible!'
|
|
||||||
],
|
|
||||||
'': {
|
|
||||||
'domain': 'messages',
|
|
||||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
|
||||||
'lang': 'en'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
strings['it'] = {
|
strings["it"] = {
|
||||||
'domain': 'messages',
|
domain: "messages",
|
||||||
'locale_data': {
|
locale_data: {
|
||||||
'messages': {
|
messages: {
|
||||||
'days': [
|
days: [""],
|
||||||
''
|
hours: [""],
|
||||||
|
minutes: [""],
|
||||||
|
seconds: [""],
|
||||||
|
Clear: ["Cancella"],
|
||||||
|
Logout: [""],
|
||||||
|
"Demo Bank": ["Banca 'demo'"],
|
||||||
|
"Go back": ["Indietro"],
|
||||||
|
"Wire transfer": ["Bonifico"],
|
||||||
|
"Transfer money to another account of this bank:": [
|
||||||
|
"Trasferisci fondi a un altro conto di questa banca:",
|
||||||
],
|
],
|
||||||
'hours': [
|
"Want to try the raw payto://-format?": [
|
||||||
''
|
"Prova il trasferimento tramite il formato Payto!",
|
||||||
],
|
],
|
||||||
'minutes': [
|
"Transfer money via the Payto system:": [
|
||||||
''
|
"Effettua un bonifico tramite il sistema Payto:",
|
||||||
],
|
],
|
||||||
'seconds': [
|
"payto address": ["indirizzo Payto"],
|
||||||
''
|
Confirm: ["Conferma"],
|
||||||
|
"Confirm Withdrawal": ["Conferma il ritiro"],
|
||||||
|
"Waiting the bank to create the operaion...": [
|
||||||
|
"La banca sta creando l'operazione...",
|
||||||
],
|
],
|
||||||
'Clear': [
|
"This withdrawal was aborted!": ["Questo ritiro è stato annullato!"],
|
||||||
'Cancella'
|
"Withdraw to a Taler Wallet": ["Ritira contante nel portafoglio Taler"],
|
||||||
|
"You can use this QR code to withdraw to your mobile wallet:": [
|
||||||
|
"Usa questo codice QR per ritirare contante nel tuo wallet:",
|
||||||
],
|
],
|
||||||
'Logout': [
|
"this link": ["questo link"],
|
||||||
''
|
Abort: ["Annulla"],
|
||||||
|
"Start withdrawal": ["Ritira contante"],
|
||||||
|
"Withdraw Money into a Taler wallet": [
|
||||||
|
"Ritira contante nel portafoglio Taler",
|
||||||
],
|
],
|
||||||
'Demo Bank': [
|
"Amount to withdraw": ["Somma da ritirare"],
|
||||||
'Banca \'demo\''
|
"Please login!": ["Accedi!"],
|
||||||
|
Login: ["Accedi"],
|
||||||
|
"Register to the euFin bank!": ["Apri un conto in banca euFin!"],
|
||||||
|
"Registration form": ["Registrazione"],
|
||||||
|
Register: ["Registrati"],
|
||||||
|
Date: [""],
|
||||||
|
Amount: ["Somma"],
|
||||||
|
Counterpart: ["Controparte"],
|
||||||
|
Subject: ["Causale"],
|
||||||
|
"Username or account label '%1$s' not found. Won't login.": [
|
||||||
|
"L'utente '%1$s' non esiste. Login impossibile",
|
||||||
],
|
],
|
||||||
'Go back': [
|
"Wrong credentials given.": ["Credenziali invalide."],
|
||||||
'Indietro'
|
"Account information could not be retrieved.": [
|
||||||
|
"Impossibile ricevere le informazioni relative al conto.",
|
||||||
],
|
],
|
||||||
'Wire transfer': [
|
"Close wire transfer": ["Chiudi il bonifico"],
|
||||||
'Bonifico'
|
"Close Taler withdrawal": ["Chiudi il ritiro Taler"],
|
||||||
|
"Bank account balance:": ["Bilancio:"],
|
||||||
|
"Latest transactions:": ["Ultime transazioni:"],
|
||||||
|
"Transfer money manually": ["Effettua un bonifico"],
|
||||||
|
"List of public accounts was not found.": [
|
||||||
|
"Lista conti pubblici non trovata.",
|
||||||
],
|
],
|
||||||
'Transfer money to another account of this bank:': [
|
"List of public accounts could not be retrieved.": [
|
||||||
'Trasferisci fondi a un altro conto di questa banca:'
|
"Lista conti pubblici non pervenuta.",
|
||||||
],
|
],
|
||||||
'Want to try the raw payto://-format?': [
|
"History of public accounts": ["Storico dei conti pubblici"],
|
||||||
'Prova il trasferimento tramite il formato Payto!'
|
"Page has a problem: logged in but backend state is lost.": [
|
||||||
|
"Stato inconsistente: accesso utente effettuato ma stato con server perso.",
|
||||||
],
|
],
|
||||||
'Transfer money via the Payto system:': [
|
"Welcome to the euFin bank!": ["Benvenuti in banca euFin!"],
|
||||||
'Effettua un bonifico tramite il sistema Payto:'
|
"": {
|
||||||
],
|
domain: "messages",
|
||||||
'payto address': [
|
plural_forms: "nplurals=2; plural=(n != 1);",
|
||||||
'indirizzo Payto'
|
lang: "it",
|
||||||
],
|
},
|
||||||
'Confirm': [
|
},
|
||||||
'Conferma'
|
},
|
||||||
],
|
|
||||||
'Confirm Withdrawal': [
|
|
||||||
'Conferma il ritiro'
|
|
||||||
],
|
|
||||||
'Waiting the bank to create the operaion...': [
|
|
||||||
'La banca sta creando l\'operazione...'
|
|
||||||
],
|
|
||||||
'This withdrawal was aborted!': [
|
|
||||||
'Questo ritiro è stato annullato!'
|
|
||||||
],
|
|
||||||
'Withdraw to a Taler Wallet': [
|
|
||||||
'Ritira contante nel portafoglio Taler'
|
|
||||||
],
|
|
||||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
|
||||||
'Usa questo codice QR per ritirare contante nel tuo wallet:'
|
|
||||||
],
|
|
||||||
'this link': [
|
|
||||||
'questo link'
|
|
||||||
],
|
|
||||||
'Abort': [
|
|
||||||
'Annulla'
|
|
||||||
],
|
|
||||||
'Start withdrawal': [
|
|
||||||
'Ritira contante'
|
|
||||||
],
|
|
||||||
'Withdraw Money into a Taler wallet': [
|
|
||||||
'Ritira contante nel portafoglio Taler'
|
|
||||||
],
|
|
||||||
'Amount to withdraw': [
|
|
||||||
'Somma da ritirare'
|
|
||||||
],
|
|
||||||
'Please login!': [
|
|
||||||
'Accedi!'
|
|
||||||
],
|
|
||||||
'Login': [
|
|
||||||
'Accedi'
|
|
||||||
],
|
|
||||||
'Register to the euFin bank!': [
|
|
||||||
'Apri un conto in banca euFin!'
|
|
||||||
],
|
|
||||||
'Registration form': [
|
|
||||||
'Registrazione'
|
|
||||||
],
|
|
||||||
'Register': [
|
|
||||||
'Registrati'
|
|
||||||
],
|
|
||||||
'Date': [
|
|
||||||
''
|
|
||||||
],
|
|
||||||
'Amount': [
|
|
||||||
'Somma'
|
|
||||||
],
|
|
||||||
'Counterpart': [
|
|
||||||
'Controparte'
|
|
||||||
],
|
|
||||||
'Subject': [
|
|
||||||
'Causale'
|
|
||||||
],
|
|
||||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
|
||||||
'L\'utente \'%1$s\' non esiste. Login impossibile'
|
|
||||||
],
|
|
||||||
'Wrong credentials given.': [
|
|
||||||
'Credenziali invalide.'
|
|
||||||
],
|
|
||||||
'Account information could not be retrieved.': [
|
|
||||||
'Impossibile ricevere le informazioni relative al conto.'
|
|
||||||
],
|
|
||||||
'Close wire transfer': [
|
|
||||||
'Chiudi il bonifico'
|
|
||||||
],
|
|
||||||
'Close Taler withdrawal': [
|
|
||||||
'Chiudi il ritiro Taler'
|
|
||||||
],
|
|
||||||
'Bank account balance:': [
|
|
||||||
'Bilancio:'
|
|
||||||
],
|
|
||||||
'Latest transactions:': [
|
|
||||||
'Ultime transazioni:'
|
|
||||||
],
|
|
||||||
'Transfer money manually': [
|
|
||||||
'Effettua un bonifico'
|
|
||||||
],
|
|
||||||
'List of public accounts was not found.': [
|
|
||||||
'Lista conti pubblici non trovata.'
|
|
||||||
],
|
|
||||||
'List of public accounts could not be retrieved.': [
|
|
||||||
'Lista conti pubblici non pervenuta.'
|
|
||||||
],
|
|
||||||
'History of public accounts': [
|
|
||||||
'Storico dei conti pubblici'
|
|
||||||
],
|
|
||||||
'Page has a problem: logged in but backend state is lost.': [
|
|
||||||
'Stato inconsistente: accesso utente effettuato ma stato con server perso.'
|
|
||||||
],
|
|
||||||
'Welcome to the euFin bank!': [
|
|
||||||
'Benvenuti in banca euFin!'
|
|
||||||
],
|
|
||||||
'': {
|
|
||||||
'domain': 'messages',
|
|
||||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
|
||||||
'lang': 'it'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,14 +16,20 @@
|
|||||||
@author Sebastian Javier Marchano
|
@author Sebastian Javier Marchano
|
||||||
-->
|
-->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="has-aside-left has-aside-mobile-transition has-navbar-fixed-top has-aside-expanded">
|
<html
|
||||||
|
lang="en"
|
||||||
|
class="has-aside-left has-aside-mobile-transition has-navbar-fixed-top has-aside-expanded"
|
||||||
|
>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
|
||||||
<link rel="icon" href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn3//3ryn/795Tf/WrpP/2LCW/8B6T//w4Nb///////Pn4P+/d0v/9u3n/+7d0v/EhV7//v///+HDr//fxLD/zph2/+TJt//8/Pv/woBX//Lm3f/y5dz/v3hN//bu6f/JjGn/4sW0///////Df1j/8OLZ//v6+P+/elH/+vj1//jy7f+/elL//////+zYzP/Eg13//////967p//MlHT/wn5X///////v4Nb/yY1s///////jw7H/06KG////////////z5t9/+fNvf//////x4pn//Pp4v/8+vn/w39X/8WEX///////5s/A/9CbfP//////27Oc/9y2n////////////9itlf/gu6f//////86Vdf/r2Mz//////8SCXP/Df1j//////+7d0v/KkG7//////+HBrf/VpYr////////////RnoH/5sq6///////Ii2n/8ubf//39/P/Cf1j/xohk/+bNvv//////wn5W//Tq4//58/D/wHxV//7+/f/59fH/v3xU//39/P/w4Nf/xIFb///////hw7H/yo9t/+/f1f/AeU3/+/n2/+nSxP/FhmD//////9qzm//Upon/4MSx/96+qf//////xINc/+3bz//48e3/v3hN//Pn3///////6M+//752S//gw6//06aK/8J+VP/kzLr/zZd1/8OCWv/q18r/17KZ/9Ooi//fv6r/v3dK/+vWyP///////v39///////27un/1aeK/9Opjv/m1cf/1KCC/9a0nP/n08T/0Jx8/82YdP/QnHz/16yR//jx7P///////v39///////+/f3///7+///////+//7//v7+///////+/v7//v/+/////////////////////////v7//v79///////////////////+/v/+/Pv//v39///+/v/+/Pv///7+//7+/f/+/Pv//v39//79/P/+/Pv///7+////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" />
|
<link
|
||||||
|
rel="icon"
|
||||||
|
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn3//3ryn/795Tf/WrpP/2LCW/8B6T//w4Nb///////Pn4P+/d0v/9u3n/+7d0v/EhV7//v///+HDr//fxLD/zph2/+TJt//8/Pv/woBX//Lm3f/y5dz/v3hN//bu6f/JjGn/4sW0///////Df1j/8OLZ//v6+P+/elH/+vj1//jy7f+/elL//////+zYzP/Eg13//////967p//MlHT/wn5X///////v4Nb/yY1s///////jw7H/06KG////////////z5t9/+fNvf//////x4pn//Pp4v/8+vn/w39X/8WEX///////5s/A/9CbfP//////27Oc/9y2n////////////9itlf/gu6f//////86Vdf/r2Mz//////8SCXP/Df1j//////+7d0v/KkG7//////+HBrf/VpYr////////////RnoH/5sq6///////Ii2n/8ubf//39/P/Cf1j/xohk/+bNvv//////wn5W//Tq4//58/D/wHxV//7+/f/59fH/v3xU//39/P/w4Nf/xIFb///////hw7H/yo9t/+/f1f/AeU3/+/n2/+nSxP/FhmD//////9qzm//Upon/4MSx/96+qf//////xINc/+3bz//48e3/v3hN//Pn3///////6M+//752S//gw6//06aK/8J+VP/kzLr/zZd1/8OCWv/q18r/17KZ/9Ooi//fv6r/v3dK/+vWyP///////v39///////27un/1aeK/9Opjv/m1cf/1KCC/9a0nP/n08T/0Jx8/82YdP/QnHz/16yR//jx7P///////v39///////+/f3///7+///////+//7//v7+///////+/v7//v/+/////////////////////////v7//v79///////////////////+/v/+/Pv//v39///+/v/+/Pv///7+//7+/f/+/Pv//v39//79/P/+/Pv///7+////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
/>
|
||||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
|
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -15,24 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { h } from 'preact';
|
|
||||||
import Profile from './index';
|
|
||||||
|
|
||||||
|
import { h } from "preact";
|
||||||
|
import Profile from "./index";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Profile/View',
|
title: "Profile/View",
|
||||||
component: Profile,
|
component: Profile,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
onSelect: { action: 'onSelect' },
|
onSelect: { action: "onSelect" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Empty = (a: any) => <Profile {...a} />;
|
export const Empty = (a: any) => <Profile {...a} />;
|
||||||
Empty.args = {
|
Empty.args = {
|
||||||
instances: []
|
instances: [],
|
||||||
}
|
};
|
||||||
|
|
||||||
|
@ -135,9 +135,9 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
// there's probably a better way to do this, but wanted to try out CSS grid
|
// there's probably a better way to do this, but wanted to try out CSS grid
|
||||||
grid-template-columns: calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(
|
grid-template-columns:
|
||||||
100% / 7
|
calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
|
||||||
) calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: var(--secondary-text-color-dark);
|
color: var(--secondary-text-color-dark);
|
||||||
@ -151,9 +151,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
grid-template-columns: calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(
|
grid-template-columns:
|
||||||
100% / 7
|
calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
|
||||||
) calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: var(--primary-text-color-dark);
|
color: var(--primary-text-color-dark);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.navcontainer:not(.default-navcontainer) {
|
.navcontainer:not(.default-navcontainer) {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.abort-button {
|
.abort-button {
|
||||||
@ -17,8 +17,8 @@ div.pages-list {
|
|||||||
|
|
||||||
.login-div,
|
.login-div,
|
||||||
.register-div {
|
.register-div {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.page-number {
|
a.page-number {
|
||||||
@ -42,55 +42,55 @@ input[type="number"]::-webkit-inner-spin-button {
|
|||||||
|
|
||||||
/* This CSS code styles the tab */
|
/* This CSS code styles the tab */
|
||||||
.tab {
|
.tab {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout {
|
.logout {
|
||||||
float: right;
|
float: right;
|
||||||
border: 20px;
|
border: 20px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab button {
|
.tab button {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
color: black;
|
color: black;
|
||||||
float: left;
|
float: left;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 18px 19px;
|
padding: 18px 19px;
|
||||||
border: 2px solid #c1c1c1;
|
border: 2px solid #c1c1c1;
|
||||||
transition: 0.5s;
|
transition: 0.5s;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab button:hover {
|
.tab button:hover {
|
||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
border: 2px solid #c1c1c1;
|
border: 2px solid #c1c1c1;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab button.active {
|
.tab button.active {
|
||||||
background-color: orange;
|
background-color: orange;
|
||||||
border: 2px solid #c1c1c1;
|
border: 2px solid #c1c1c1;
|
||||||
color: black;
|
color: black;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabcontent {
|
.tabcontent {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border: 2px solid #c1c1c1;
|
border: 2px solid #c1c1c1;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabcontent.active {
|
.tabcontent.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="number"] {
|
input[type="number"] {
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
#transfer-fields {
|
#transfer-fields {
|
||||||
@ -115,16 +115,16 @@ input[type="number"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.large-amount {
|
.large-amount {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
}
|
}
|
||||||
|
|
||||||
.currency {
|
.currency {
|
||||||
font-style: oblique;
|
font-style: oblique;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -154,111 +154,108 @@ input {
|
|||||||
|
|
||||||
.register-form > .pure-form,
|
.register-form > .pure-form,
|
||||||
.login-form > .pure-form {
|
.login-form > .pure-form {
|
||||||
background: #4a4a4a;
|
background: #4a4a4a;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding: 16px 16px;
|
padding: 16px 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
.formFieldLabel {
|
.formFieldLabel {
|
||||||
margin: 2px 2px;
|
margin: 2px 2px;
|
||||||
}
|
}
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="password"] {
|
input[type="password"] {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #6a6a6a;
|
background: #6a6a6a;
|
||||||
color: #fefefe;
|
color: #fefefe;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
input[placeholder="Password"][type="password"] {
|
input[placeholder="Password"][type="password"] {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.btn-register,
|
.btn-register,
|
||||||
.btn-login {
|
.btn-login {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
.btn-cancel {
|
.btn-cancel {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.challenge-div {
|
.challenge-div {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.challenge-form > .pure-form {
|
.challenge-form > .pure-form {
|
||||||
background: #4a4a4a;
|
background: #4a4a4a;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding: 16px 16px;
|
padding: 16px 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
.formFieldLabel {
|
.formFieldLabel {
|
||||||
margin: 2px 2px;
|
margin: 2px 2px;
|
||||||
}
|
}
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #6a6a6a;
|
background: #6a6a6a;
|
||||||
color: #fefefe;
|
color: #fefefe;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
.btn-confirm {
|
.btn-confirm {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
.btn-cancel {
|
.btn-cancel {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.wire-transfer-form > .pure-form,
|
.wire-transfer-form > .pure-form,
|
||||||
.payto-form > .pure-form,
|
.payto-form > .pure-form,
|
||||||
.reserve-form > .pure-form {
|
.reserve-form > .pure-form {
|
||||||
background: #4a4a4a;
|
background: #4a4a4a;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding: 16px 16px;
|
padding: 16px 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
.formFieldLabel {
|
.formFieldLabel {
|
||||||
margin: 2px 2px;
|
margin: 2px 2px;
|
||||||
}
|
}
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #6a6a6a;
|
background: #6a6a6a;
|
||||||
color: #fefefe;
|
color: #fefefe;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #2a2a2a;
|
color: #2a2a2a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
scale: 0.7;
|
scale: 0.7;
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Nunito';
|
font-family: "Nunito";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: url(./XRXV3I6Li01BKofINeaE.ttf) format('truetype');
|
src: url(./XRXV3I6Li01BKofINeaE.ttf) format("truetype");
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user