[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant-backoffice] 01/03: refactor table, taking out the modal
From: |
gnunet |
Subject: |
[taler-merchant-backoffice] 01/03: refactor table, taking out the modal |
Date: |
Thu, 11 Feb 2021 18:55:35 +0100 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository merchant-backoffice.
commit aa3858a3e35d592377d3fbb23ec862044e99330a
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Feb 11 14:33:25 2021 -0300
refactor table, taking out the modal
---
src/components/auth/LoginPage.tsx | 2 +-
src/routes/instances/{Table.tsx => CardTable.tsx} | 71 +++++++++--------------
src/routes/instances/CreateModal.tsx | 9 ++-
src/routes/instances/DeleteAllModal.tsx | 29 ---------
src/routes/instances/DeleteModal.tsx | 6 +-
src/routes/instances/UpdateModal.tsx | 2 +-
src/routes/instances/View.tsx | 44 +++++++++++---
7 files changed, 72 insertions(+), 91 deletions(-)
diff --git a/src/components/auth/LoginPage.tsx
b/src/components/auth/LoginPage.tsx
index 956e573..616b0cd 100644
--- a/src/components/auth/LoginPage.tsx
+++ b/src/components/auth/LoginPage.tsx
@@ -23,7 +23,7 @@ export default function LoginPage({ onLogIn }: Props): VNode {
<div class="field-body">
<div class="field">
<p class="control is-expanded has-icons-left">
- <input class="input" type="text" placeholder="abcdef"
name="id" value={token} onInput={e => update(e?.currentTarget.value)} />
+ <input class="input" type="text" placeholder="abcdef"
name="id" value={token} onInput={(e): void => update(e?.currentTarget.value)} />
</p>
</div>
</div>
diff --git a/src/routes/instances/Table.tsx b/src/routes/instances/CardTable.tsx
similarity index 59%
rename from src/routes/instances/Table.tsx
rename to src/routes/instances/CardTable.tsx
index e6d1474..31f74a4 100644
--- a/src/routes/instances/Table.tsx
+++ b/src/routes/instances/CardTable.tsx
@@ -1,16 +1,11 @@
import { h, VNode } from "preact";
import { useEffect, useState, StateUpdater } from "preact/hooks";
import { MerchantBackend, WidthId as WithId } from "../../declaration";
-import DeleteModal from './DeleteModal'
-import UpdateModal from './UpdateModal'
-import CreateModal from './CreateModal'
interface Props {
instances: MerchantBackend.Instances.Instance[];
- onCreate: (d: MerchantBackend.Instances.InstanceConfigurationMessage) =>
void;
- onUpdate: (id: string, d:
MerchantBackend.Instances.InstanceReconfigurationMessage) => void;
- onDelete: (id: string) => void;
- onSelect: (id: string | null) => void;
+ onSelect: (id: string | null, action: 'UPDATE' | 'DELETE') => void;
+ onCreate: () => void;
selected: MerchantBackend.Instances.QueryInstancesResponse & WithId |
undefined;
}
@@ -33,28 +28,29 @@ function buildActions(intances:
MerchantBackend.Instances.Instance[], selected:
.map(id => ({ element: id, type: action }))
}
-const EmptyTable = () => <div class="content has-text-grey has-text-centered">
- <p>
- <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px"
/></span>
- </p>
- <p>No instance configured yet, setup one pressing the + button </p>
-</div>
+const EmptyTable = (): VNode => (
+ <div class="content has-text-grey has-text-centered">
+ <p>
+ <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px"
/></span>
+ </p>
+ <p>No instance configured yet, setup one pressing the + button </p>
+ </div>
+)
interface TableProps {
rowSelection: string[];
instances: MerchantBackend.Instances.Instance[];
- onSelect: (id: string | null) => void;
+ onSelect: (id: string | null, action: 'UPDATE' | 'DELETE') => void;
rowSelectionHandler: StateUpdater<string[]>;
- toBeDeletedHandler: StateUpdater<MerchantBackend.Instances.Instance | null>;
}
-const Table = ({ rowSelection, rowSelectionHandler, instances, onSelect,
toBeDeletedHandler }: TableProps): VNode => (
+const Table = ({ rowSelection, rowSelectionHandler, instances, onSelect }:
TableProps): VNode => (
<table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th class="is-checkbox-cell">
<label class="b-checkbox checkbox">
- <input type="checkbox" checked={rowSelection.length ===
instances.length} onClick={e => rowSelectionHandler(rowSelection.length ===
instances.length ? [] : instances.map(i => i.id))} />
+ <input type="checkbox" checked={rowSelection.length ===
instances.length} onClick={(): void => rowSelectionHandler(rowSelection.length
=== instances.length ? [] : instances.map(i => i.id))} />
<span class="check" />
</label>
</th>
@@ -70,7 +66,7 @@ const Table = ({ rowSelection, rowSelectionHandler,
instances, onSelect, toBeDel
return <tr>
<td class="is-checkbox-cell">
<label class="b-checkbox checkbox">
- <input type="checkbox" checked={rowSelection.indexOf(i.id) !=
-1} onClick={e => rowSelectionHandler(toggleSelected(i.id))} />
+ <input type="checkbox" checked={rowSelection.indexOf(i.id) !=
-1} onClick={(): void => rowSelectionHandler(toggleSelected(i.id))} />
<span class="check" />
</label>
</td>
@@ -80,10 +76,10 @@ const Table = ({ rowSelection, rowSelectionHandler,
instances, onSelect, toBeDel
<td >{i.payment_targets}</td>
<td class="is-actions-cell">
<div class="buttons is-right">
- <button class="button is-small is-primary" type="button"
onClick={e => onSelect(i.id)}>
+ <button class="button is-small is-primary" type="button"
onClick={(): void => onSelect(i.id, 'UPDATE')}>
<span class="icon"><i class="mdi mdi-eye" /></span>
</button>
- <button class="button is-small is-danger jb-modal" type="button"
onClick={e => toBeDeletedHandler(i)}>
+ <button class="button is-small is-danger jb-modal" type="button"
onClick={(): void => onSelect(i.id, 'DELETE')}>
<span class="icon"><i class="mdi mdi-trash-can" /></span>
</button>
</div>
@@ -95,35 +91,32 @@ const Table = ({ rowSelection, rowSelectionHandler,
instances, onSelect, toBeDel
</table>)
-export default function CardTable({ instances, onCreate, onDelete, onSelect,
onUpdate, selected }: Props): VNode {
- const [toBeCreated, toBeCreatedHandler] = useState<boolean>(false)
+export default function CardTable({ instances, onCreate, onSelect, selected }:
Props): VNode {
const [actionQueue, actionQueueHandler] = useState<Actions[]>([]);
- const [toBeDeleted, toBeDeletedHandler] =
useState<MerchantBackend.Instances.Instance | null>(null)
-
const [rowSelection, rowSelectionHandler] = useState<string[]>([])
useEffect(() => {
- if (actionQueue.length > 0 && !toBeDeleted && actionQueue[0].type ==
'DELETE') {
- toBeDeletedHandler(actionQueue[0].element)
+ if (actionQueue.length > 0 && !selected && actionQueue[0].type ==
'DELETE') {
+ onSelect(actionQueue[0].element.id, 'DELETE')
actionQueueHandler(actionQueue.slice(1))
}
- }, [actionQueue, toBeDeleted])
+ }, [actionQueue, selected, onSelect])
useEffect(() => {
if (actionQueue.length > 0 && !selected && actionQueue[0].type ==
'UPDATE') {
- onSelect(actionQueue[0].element.id)
+ onSelect(actionQueue[0].element.id, 'UPDATE')
actionQueueHandler(actionQueue.slice(1))
}
- }, [actionQueue, selected])
+ }, [actionQueue, selected, onSelect])
return <div class="card has-table">
<header class="card-header">
<p class="card-header-title"><span class="icon"><i class="mdi
mdi-account-multiple" /></span>Instances</p>
- <button class={rowSelection.length > 0 ? "card-header-icon" :
"card-header-icon is-hidden"} type="button" onClick={e =>
actionQueueHandler(buildActions(instances, rowSelection, 'DELETE'))} >
+ <button class={rowSelection.length > 0 ? "card-header-icon" :
"card-header-icon is-hidden"} type="button" onClick={(): void =>
actionQueueHandler(buildActions(instances, rowSelection, 'DELETE'))} >
<span class="icon"><i class="mdi mdi-trash-can" /></span>
</button>
- <button class="card-header-icon" type="button" onClick={e =>
toBeCreatedHandler(true)}>
+ <button class="card-header-icon" type="button" onClick={onCreate}>
<span class="icon"><i class="mdi mdi-plus" /></span>
</button>
</header>
@@ -131,23 +124,11 @@ export default function CardTable({ instances, onCreate,
onDelete, onSelect, onU
<div class="b-table has-pagination">
<div class="table-wrapper has-mobile-cards">
{instances.length > 0 ?
- <Table instances={instances} onSelect={onSelect}
rowSelection={rowSelection} rowSelectionHandler={rowSelectionHandler}
toBeDeletedHandler={toBeDeletedHandler} /> :
+ <Table instances={instances} onSelect={onSelect}
rowSelection={rowSelection} rowSelectionHandler={rowSelectionHandler} /> :
<EmptyTable />
}
</div>
- {toBeDeleted ? <DeleteModal element={toBeDeleted} onCancel={() =>
toBeDeletedHandler(null)} onConfirm={(i) => {
- onDelete(i.id)
- toBeDeletedHandler(null);
- }} /> : null}
- {selected ? <UpdateModal element={selected} onCancel={() =>
onSelect(null)} onConfirm={(i) => {
- onUpdate(selected.id, i)
- onSelect(null);
- }} /> : null}
- {toBeCreated ? <CreateModal active={toBeCreated} onCancel={() =>
toBeCreatedHandler(false)} onConfirm={(i) => {
- onCreate(i)
- toBeCreatedHandler(false);
- }} /> : null}
</div>
</div>
- </div >
+ </div>
}
\ No newline at end of file
diff --git a/src/routes/instances/CreateModal.tsx
b/src/routes/instances/CreateModal.tsx
index e1b53da..7eff286 100644
--- a/src/routes/instances/CreateModal.tsx
+++ b/src/routes/instances/CreateModal.tsx
@@ -36,7 +36,6 @@ const schema = yup.object().shape({
});
interface Props {
- active: boolean;
onCancel: () => void;
onConfirm: (i: MerchantBackend.Instances.InstanceConfigurationMessage) =>
void;
}
@@ -45,8 +44,8 @@ interface KeyValue {
[key: string]: string;
}
-export default function CreateModal({ active, onCancel, onConfirm }: Props):
VNode {
- const [value, valueHandler] = useState((active || {}) as any)
+export default function CreateModal({ onCancel, onConfirm }: Props): VNode {
+ const [value, valueHandler] = useState({} as any)
const [errors, setErrors] = useState<KeyValue>({})
const submit = (): void => {
@@ -60,7 +59,7 @@ export default function CreateModal({ active, onCancel,
onConfirm }: Props): VNo
}
}
- return <ConfirmModal description="create instance" active={active}
onConfirm={submit} onCancel={onCancel}>
+ return <ConfirmModal description="create instance" active onConfirm={submit}
onCancel={onCancel}>
{Object.keys(schema.fields).map(f => {
const info = schema.fields[f].describe()
@@ -73,7 +72,7 @@ export default function CreateModal({ active, onCancel,
onConfirm }: Props): VNo
<div class="field-body">
<div class="field">
<p class="control is-expanded has-icons-left">
- <input class="input" type="text"
placeholder={info?.meta?.placeholder} readonly={info?.meta?.readonly} name={f}
value={value[f]} onChange={e => valueHandler((prev: any) => ({ ...prev, [f]:
e.currentTarget.value }))} />
+ <input class="input" type="text"
placeholder={info?.meta?.placeholder} readonly={info?.meta?.readonly} name={f}
value={value[f]} onChange={(e): void => valueHandler((prev: any) => ({ ...prev,
[f]: e.currentTarget.value }))} />
{info?.meta?.help}
</p>
{errors[f] ? <p class="help is-danger">{errors[f]}</p> : null}
diff --git a/src/routes/instances/DeleteAllModal.tsx
b/src/routes/instances/DeleteAllModal.tsx
deleted file mode 100644
index 6f81e2c..0000000
--- a/src/routes/instances/DeleteAllModal.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { h, VNode } from "preact";
-import { MerchantBackend } from "../../declaration";
-
-interface Props {
- element: MerchantBackend.Instances.Instance | null;
- onCancel: () => void;
- onConfirm: (i: MerchantBackend.Instances.Instance) => void;
-}
-
-export default function DeleteAllModal({ element, onCancel, onConfirm }:
Props): VNode {
- return <div class={element ? "modal is-active is-clipped" : "modal"}>
- <div class="modal-background jb-modal-close" onClick={e => onCancel()} />
- <div class="modal-card">
- <header class="modal-card-head">
- <p class="modal-card-title">Confirm action</p>
- <button class="delete jb-modal-close" aria-label="close" onClick={e =>
onCancel()} />
- </header>
- <section class="modal-card-body">
- <p>This will permanently delete instance "{element?.name}" with id
<b>{element?.id}</b></p>
- <p>Please confirm this action</p>
- </section>
- <footer class="modal-card-foot">
- <button class="button jb-modal-close" onClick={e => onCancel()}
>Cancel</button>
- <button class="button is-danger jb-modal-close" onClick={element ? e
=> onConfirm(element) : undefined} >Delete</button>
- </footer>
- </div>
- <button class="modal-close is-large jb-modal-close" aria-label="close"
onClick={e => onCancel()} />
- </div>
-}
\ No newline at end of file
diff --git a/src/routes/instances/DeleteModal.tsx
b/src/routes/instances/DeleteModal.tsx
index 98dbfe8..276dab4 100644
--- a/src/routes/instances/DeleteModal.tsx
+++ b/src/routes/instances/DeleteModal.tsx
@@ -1,11 +1,11 @@
import { h, VNode } from "preact";
-import { MerchantBackend } from "../../declaration";
+import { MerchantBackend, WidthId } from "../../declaration";
import ConfirmModal from "./ConfirmModal";
interface Props {
- element: MerchantBackend.Instances.Instance;
+ element: MerchantBackend.Instances.QueryInstancesResponse & WidthId;
onCancel: () => void;
- onConfirm: (i: MerchantBackend.Instances.Instance) => void;
+ onConfirm: (i: MerchantBackend.Instances.QueryInstancesResponse & WidthId)
=> void;
}
export default function DeleteModal({ element, onCancel, onConfirm }: Props):
VNode {
diff --git a/src/routes/instances/UpdateModal.tsx
b/src/routes/instances/UpdateModal.tsx
index d788a91..d729729 100644
--- a/src/routes/instances/UpdateModal.tsx
+++ b/src/routes/instances/UpdateModal.tsx
@@ -66,7 +66,7 @@ export default function UpdateModal({ element, onCancel,
onConfirm }: Props): VN
<input class="input" type="text"
placeholder={info?.meta?.placeholder}
readonly={info?.meta?.readonly}
name={f} value={value[f]}
- onChange={e => valueHandler((prev: any) => ({ ...prev, [f]:
e.currentTarget.value }))} />
+ onChange={(e): void => valueHandler((prev: any) => ({
...prev, [f]: e.currentTarget.value }))} />
{info?.meta?.help}
</p>
{errors[f] ? <p class="help is-danger">{errors[f]}</p> : null}
diff --git a/src/routes/instances/View.tsx b/src/routes/instances/View.tsx
index 95af162..4305564 100644
--- a/src/routes/instances/View.tsx
+++ b/src/routes/instances/View.tsx
@@ -1,6 +1,10 @@
import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
import { MerchantBackend, WidthId } from "../../declaration";
-import Table from './Table';
+import Table from './CardTable';
+import DeleteModal from './DeleteModal'
+import UpdateModal from './UpdateModal'
+import CreateModal from './CreateModal'
interface Props {
instances: MerchantBackend.Instances.Instance[];
@@ -13,6 +17,14 @@ interface Props {
}
export default function View({ instances, isLoading, onCreate, onDelete,
onSelect, onUpdate, selected }: Props): VNode {
+ const [create, setCreate] = useState<boolean>(false)
+ const [action, setAction] = useState<'UPDATE' | 'DELETE' | null>(null)
+
+ const onSelectAction = (id: string | null, action?: 'UPDATE' | 'DELETE'):
void => {
+ onSelect(id)
+ setAction(action || null)
+ }
+
return <div id="app">
<section class="section is-title-bar">
@@ -27,7 +39,8 @@ export default function View({ instances, isLoading,
onCreate, onDelete, onSelec
</div>
</div>
</section>
- <section class={ isLoading ? "hero is-hero-bar" : "hero is-hero-bar
is-loading" }>
+
+ <section class={isLoading ? "hero is-hero-bar" : "hero is-hero-bar
is-loading"}>
<div class="hero-body">
<div class="level">
<div class="level-left">
@@ -42,12 +55,29 @@ export default function View({ instances, isLoading,
onCreate, onDelete, onSelec
</div>
</section>
<section class="section is-main-section">
- <Table instances={instances} onCreate={onCreate}
- onUpdate={onUpdate}
- onDelete={onDelete} onSelect={onSelect}
- selected={selected}
- />
+ <Table instances={instances} onSelect={onSelectAction}
selected={selected} onCreate={(): void => setCreate(true)} />
</section>
+ {selected && action === 'DELETE' ?
+ <DeleteModal element={selected} onCancel={(): void =>
onSelectAction(null)} onConfirm={(i): void => {
+ onDelete(i.id)
+ onSelectAction(null);
+ }}
+ />
+ : null}
+
+ {selected && action === 'UPDATE' ?
+ <UpdateModal element={selected} onCancel={(): void =>
onSelectAction(null)} onConfirm={(i): void => {
+ onUpdate(selected.id, i);
+ onSelectAction(null);
+ }}
+ />
+ : null}
+
+ {create ? <CreateModal onCancel={(): void => setCreate(false)}
onConfirm={(i): void => {
+ onCreate(i)
+ setCreate(false);
+ }} /> : null}
+
</div >
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.