gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]