From a56217bb90307982c30c782b740407f1af9dda0c Mon Sep 17 00:00:00 2001
From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
Date: Wed, 8 Dec 2021 15:33:50 +0600
Subject: [PATCH] Table check objects (#568)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
---
 packages/ui/src/components/CheckBox.svelte    | 43 ++++++++++++-----
 .../src/components/TableView.svelte           | 48 +++++++++++++++----
 2 files changed, 69 insertions(+), 22 deletions(-)

diff --git a/packages/ui/src/components/CheckBox.svelte b/packages/ui/src/components/CheckBox.svelte
index 3e4e90bda8..0f3bb70838 100644
--- a/packages/ui/src/components/CheckBox.svelte
+++ b/packages/ui/src/components/CheckBox.svelte
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 -->
-
 <script lang="ts">
   export let checked: boolean = false
   export let symbol: 'check' | 'minus' = 'check'
@@ -21,15 +20,19 @@
 </script>
 
 <label class="checkbox" class:circle class:primary class:checked>
-  <input class="chBox" type="checkbox" bind:checked={checked}>
+  <input class="chBox" type="checkbox" bind:checked on:change />
   <svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
     {#if !circle}
-      <path class="back" class:primary d="M4,0h8c2.2,0,4,1.8,4,4v8c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4C0,1.8,1.8,0,4,0z"/>
+      <path
+        class="back"
+        class:primary
+        d="M4,0h8c2.2,0,4,1.8,4,4v8c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4C0,1.8,1.8,0,4,0z"
+      />
     {/if}
     {#if symbol === 'minus'}
-      <rect class="check" class:primary x="4" y="7.4" width="8" height="1.2"/>
+      <rect class="check" class:primary x="4" y="7.4" width="8" height="1.2" />
     {:else}
-      <polygon class="check" class:primary points="7.3,11.5 4,8.3 5,7.4 7.3,9.7 11.8,5.1 12.7,6.1 "/>
+      <polygon class="check" class:primary points="7.3,11.5 4,8.3 5,7.4 7.3,9.7 11.8,5.1 12.7,6.1 " />
     {/if}
   </svg>
 </label>
@@ -57,23 +60,33 @@
       &:checked + .checkSVG {
         & .back {
           fill: var(--theme-bg-check);
-          &.primary { fill: var(--primary-button-enabled); }
+          &.primary {
+            fill: var(--primary-button-enabled);
+          }
         }
         & .check {
           visibility: visible;
           fill: var(--theme-button-bg-enabled);
-          &.primary { fill: var(--primary-button-color); }
+          &.primary {
+            fill: var(--primary-button-color);
+          }
         }
       }
-      &:not(:disabled) + .checkSVG { cursor: pointer; }
-      &:disabled + .checkSVG { filter: grayscale(70%); }
+      &:not(:disabled) + .checkSVG {
+        cursor: pointer;
+      }
+      &:disabled + .checkSVG {
+        filter: grayscale(70%);
+      }
     }
     .checkSVG {
       width: 1rem;
       height: 1rem;
-      border-radius: .25rem;
+      border-radius: 0.25rem;
 
-      .back { fill: var(--theme-button-bg-hovered); }
+      .back {
+        fill: var(--theme-button-bg-hovered);
+      }
       .check {
         visibility: hidden;
         fill: var(--theme-button-bg-enabled);
@@ -88,10 +101,14 @@
     border: 1px solid var(--theme-bg-focused-color);
     border-radius: 50%;
 
-    &.checked { background-color: var(--theme-bg-check); }
+    &.checked {
+      background-color: var(--theme-bg-check);
+    }
     &.primary {
       border-color: transparent;
-      &.checked { background-color: var(--primary-button-enabled); }
+      &.checked {
+        background-color: var(--primary-button-enabled);
+      }
     }
   }
 </style>
diff --git a/plugins/view-resources/src/components/TableView.svelte b/plugins/view-resources/src/components/TableView.svelte
index 0f1eedf0c0..0448371760 100644
--- a/plugins/view-resources/src/components/TableView.svelte
+++ b/plugins/view-resources/src/components/TableView.svelte
@@ -1,15 +1,15 @@
 <!--
 // Copyright © 2020, 2021 Anticrm Platform Contributors.
 // Copyright © 2021 Hardcore Engineering Inc.
-// 
+//
 // Licensed under the Eclipse Public License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License. You may
 // obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
-// 
+//
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// 
+//
 // See the License for the specific language governing permissions and
 // limitations under the License.
 -->
@@ -58,7 +58,7 @@
   }
 
   const client = getClient()
-  let checking: boolean = false
+  let checked: Set<Ref<Doc>> = new Set<Ref<Doc>>()
 
   const showMenu = (ev: MouseEvent, object: Doc, row: number): void => {
     selectRow = row
@@ -78,6 +78,17 @@
       sortOrder = sortOrder === SortingOrder.Ascending ? SortingOrder.Descending : SortingOrder.Ascending
     }
   }
+
+  function check (id: Ref<Doc>, e: Event) {
+    const target = e.target as HTMLInputElement
+    const value = target.checked
+    if (value) {
+      checked.add(id)
+    } else {
+      checked.delete(id)
+    }
+    checked = checked
+  }
 </script>
 
 {#await buildModel({ client, _class, keys: config, options })}
@@ -91,12 +102,17 @@
             {#each model as attribute, cellHead}
               {#if !cellHead}
                 <th>
-                  <div class="checkCell" class:checkall={checking}>
-                    <CheckBox symbol={'minus'} />
+                  <div class="checkCell" class:checkall={checked.size > 0}>
+                    <CheckBox
+                      symbol={'minus'}
+                      checked={objects.length === checked.size}
+                      on:change={(e) => {
+                        objects.map((o) => check(o._id, e))
+                      }}
+                    />
                   </div>
                 </th>
               {/if}
-
               <th
                 class:sortable={attribute.key}
                 class:sorted={attribute.key === sortKey}
@@ -121,10 +137,19 @@
         {#if objects}
           <tbody>
             {#each objects as object, row (object._id)}
-              <tr class="tr-body" class:checking class:fixed={row === selectRow}>
+              <tr class="tr-body" class:checking={checked.has(object._id)} class:fixed={row === selectRow}>
                 {#each model as attribute, cell}
                   {#if !cell}
-                    <td><div class="checkCell"><CheckBox bind:checked={checking} /></div></td>
+                    <td
+                      ><div class="checkCell">
+                        <CheckBox
+                          checked={checked.has(object._id)}
+                          on:change={(e) => {
+                            check(object._id, e)
+                          }}
+                        />
+                      </div></td
+                    >
                     <td
                       ><div class="firstCell">
                         <svelte:component
@@ -219,6 +244,11 @@
       margin-left: 0.25rem;
       opacity: 0.6;
     }
+    &:hover {
+      .checkCell {
+        visibility: visible;
+      }
+    }
     .checkall {
       visibility: visible;
     }