From d22b62c3038ee123867175d7b1bbe2078704cbfd Mon Sep 17 00:00:00 2001
From: Alexander Platov <sas_lord@mail.ru>
Date: Sun, 12 Sep 2021 09:45:16 +0300
Subject: [PATCH] First layout Panel (#183)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
---
 packages/panel/package.json                   |  3 +-
 packages/panel/src/components/Panel.svelte    | 45 ++++++++-
 .../ui/src/components/CircleButton.svelte     | 13 ++-
 .../src/components/Attachments copy.svelte    | 79 +++++++++++++++
 .../src/components/Attachments.svelte         | 82 ++++++++++++----
 .../src/components/EditCandidate.svelte       | 97 ++++++++++++++++++-
 6 files changed, 290 insertions(+), 29 deletions(-)
 create mode 100644 plugins/recruit-resources/src/components/Attachments copy.svelte

diff --git a/packages/panel/package.json b/packages/panel/package.json
index 0b6200ddb6..1055f56a7a 100644
--- a/packages/panel/package.json
+++ b/packages/panel/package.json
@@ -20,6 +20,7 @@
   "dependencies": {
     "@anticrm/ui": "~0.6.0",
     "@anticrm/text-editor": "~0.6.0",
-    "svelte": "^3.37.0"
+    "svelte": "^3.37.0",
+    "@anticrm/platform": "~0.6.5"
   }
 }
diff --git a/packages/panel/src/components/Panel.svelte b/packages/panel/src/components/Panel.svelte
index eb9bb73d51..affb416a6f 100644
--- a/packages/panel/src/components/Panel.svelte
+++ b/packages/panel/src/components/Panel.svelte
@@ -17,7 +17,7 @@
 <script lang="ts">
   import type { IntlString, Asset } from '@anticrm/platform'
   import type { AnySvelteComponent } from '@anticrm/ui'
-  // import { ReferenceInput } from '@anticrm/text-editor'
+  import { ReferenceInput } from '@anticrm/text-editor'
   import { IconClose, IconExpand, IconActivity, ScrollBox, Button, Label, Icon } from '@anticrm/ui'
 
   import { createEventDispatcher } from 'svelte'
@@ -44,6 +44,9 @@
       </div>
       <div class="title"><Label {label} /></div>
     </div>
+    {#if $$slots.subtitle}
+      <div class="subtitle"><slot name="subtitle" /></div>
+    {/if}
     <div class="content">
       <ScrollBox vertical stretch><slot /></ScrollBox>
     </div>
@@ -55,8 +58,18 @@
       <div class="title">Activity</div>
     </div>
     <div class="content">
-      <ScrollBox vertical stretch></ScrollBox>
+      <ScrollBox vertical stretch>
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+        <div class="content-bar" />
+      </ScrollBox>
     </div>
+    <div class="ref-input"><ReferenceInput /></div>
   </div>
 
   <div class="tools">
@@ -89,6 +102,7 @@
       height: 4.5rem;
       border-bottom: 1px solid var(--theme-card-divider);
 
+      .icon { opacity: .6; }
       .title {
         flex-grow: 1;
         margin-left: .5rem;
@@ -99,6 +113,14 @@
       }
     }
 
+    .subtitle {
+      display: flex;
+      align-items: center;
+      padding: 0 2rem;
+      height: 3.5rem;
+      border-bottom: 1px solid var(--theme-card-divider);
+    }
+
     .footer {
       flex-shrink: 0;
       display: grid;
@@ -127,11 +149,24 @@
   }
 
   .content {
+    overflow: visible;
     flex-shrink: 0;
     flex-grow: 1;
+
+    display: flex;
+    flex-direction: column;
     padding: 0 2.5rem;
     height: max-content;
   }
+  .ref-input { padding: 1.5rem 2.5rem; }
+  .content-bar {
+    flex-shrink: 0;
+    height: 100px;
+    background-color: rgba(255, 255, 255, .1);
+    border: 1px solid rgba(255, 255, 255, .5);
+    border-radius: 1rem;
+  }
+  .content-bar + .content-bar { margin-top: 1rem; }
 
   .fullSize {
     flex-direction: row;
@@ -143,7 +178,11 @@
     .rightSection {
       background-color: transparent;
       .header { border-bottom: 1px solid var(--theme-card-divider); }
-      .content { background-color: var(--theme-bg-accent-color); }
+      .content {
+        padding-top: 1.5rem;
+        background-color: var(--theme-bg-accent-color);
+      }
+      .ref-input { background-color: var(--theme-bg-accent-color); }
     }
   }
 
diff --git a/packages/ui/src/components/CircleButton.svelte b/packages/ui/src/components/CircleButton.svelte
index 6dc0484ade..b89ce0f82c 100644
--- a/packages/ui/src/components/CircleButton.svelte
+++ b/packages/ui/src/components/CircleButton.svelte
@@ -19,9 +19,10 @@
   import Icon from './Icon.svelte'
 
   export let icon: Asset | AnySvelteComponent
+  export let size: 'small' | 'medium' = 'medium'
 </script>
 
-<div class="icon-button" on:click>
+<div class="icon-button icon-{size}" on:click>
   <div class="content">
     {#if typeof (icon) === 'string'}
       <Icon {icon} size={'small'}/>
@@ -36,8 +37,6 @@
     display: flex;
     justify-content: center;
     align-items: center;
-    width: 2rem;
-    height: 2rem;
     border: 1px solid var(--theme-card-divider);
     border-radius: 50%;
     backdrop-filter: blur(3px);
@@ -51,4 +50,12 @@
     &:hover { border-color: var(--theme-bg-focused-border); }
     &:active { background-color: var(--theme-bg-accent-color); }
   }
+  .icon-small {
+    width: 1.5rem;
+    height: 1.5rem;
+  }
+  .icon-medium {
+    width: 2rem;
+    height: 2rem;
+  }
 </style>
diff --git a/plugins/recruit-resources/src/components/Attachments copy.svelte b/plugins/recruit-resources/src/components/Attachments copy.svelte
new file mode 100644
index 0000000000..03c56b5939
--- /dev/null
+++ b/plugins/recruit-resources/src/components/Attachments copy.svelte	
@@ -0,0 +1,79 @@
+<!--
+// Copyright © 2020 Anticrm Platform Contributors.
+// 
+// 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.
+-->
+
+<script lang="ts">
+  import { ScrollBox, IconAdd } from '@anticrm/ui'
+
+  import type { Doc, Ref, Space } from '@anticrm/core'
+  import { createQuery } from '@anticrm/presentation'
+  import type { Attachment } from '@anticrm/chunter'
+
+  import chunter from '@anticrm/chunter'
+
+  export let object: Doc
+  export let space: Ref<Space>
+
+  let files: Attachment[] = []
+
+  console.log('query space', space)
+
+  const query = createQuery()
+  $: query.query(chunter.class.Attachment, { space }, result => { files = result})
+
+</script>
+
+<ScrollBox vertical>
+  {#each files as file}
+    <div class="item flex-row-center">
+      <div class="flex-center file-icon">pdf</div>
+      <div class="flex-col flex-grow">
+        <div class="overflow-label caption-color">{file.name}</div>
+        <div class="overflow-label file-desc">{file.type}</div>
+      </div>
+    </div>
+  {/each}
+  <div class="item add-file">
+    <button class="add-btn focused-button"><IconAdd size={'small'} /></button>
+    <div class="caption-color">Add attachment</div>
+  </div>
+</ScrollBox>
+
+<style lang="scss">
+  .item {
+    display: flex;
+    align-items: center;
+    padding: .75rem 1rem;
+  }
+  .file-icon, .add-btn {
+    margin-right: 1.25rem;
+    width: 2rem;
+    height: 2rem;
+    border-radius: .5rem;
+  }
+  .file-icon {
+    font-weight: 500;
+    font-size: 0.625rem;
+    line-height: 150%;
+    text-transform: uppercase;
+    color: #fff;
+    background-color: #7C6FCD;
+    border: 1px solid rgba(0, 0, 0, .1);
+  }
+  .file-desc {
+    font-size: 0.75rem;
+    color: var(--theme-content-dark-color);
+  }
+  .item + .add-file, .item + .item { border-top: 1px solid var(--theme-bg-accent-hover); }
+</style>
\ No newline at end of file
diff --git a/plugins/recruit-resources/src/components/Attachments.svelte b/plugins/recruit-resources/src/components/Attachments.svelte
index 03c56b5939..20f38b3d5b 100644
--- a/plugins/recruit-resources/src/components/Attachments.svelte
+++ b/plugins/recruit-resources/src/components/Attachments.svelte
@@ -14,7 +14,7 @@
 -->
 
 <script lang="ts">
-  import { ScrollBox, IconAdd } from '@anticrm/ui'
+  import { CircleButton, IconAdd } from '@anticrm/ui'
 
   import type { Doc, Ref, Space } from '@anticrm/core'
   import { createQuery } from '@anticrm/presentation'
@@ -25,38 +25,81 @@
   export let object: Doc
   export let space: Ref<Space>
 
-  let files: Attachment[] = []
+  let files: Attachment[] = [{ name: 'Application description.pdf', type: 'PDF / 2,5 MB' }, { name: 'Application description.pdf', type: 'PDF / 2,5 MB' }]
 
   console.log('query space', space)
 
   const query = createQuery()
-  $: query.query(chunter.class.Attachment, { space }, result => { files = result})
+  // $: query.query(chunter.class.Attachment, { space }, result => { files = result})
 
 </script>
 
-<ScrollBox vertical>
-  {#each files as file}
-    <div class="item flex-row-center">
-      <div class="flex-center file-icon">pdf</div>
-      <div class="flex-col flex-grow">
-        <div class="overflow-label caption-color">{file.name}</div>
-        <div class="overflow-label file-desc">{file.type}</div>
-      </div>
-    </div>
-  {/each}
-  <div class="item add-file">
-    <button class="add-btn focused-button"><IconAdd size={'small'} /></button>
-    <div class="caption-color">Add attachment</div>
+<div class="attachments-container">
+  <div class="flex-row-center">
+    <span class="title">Attachments</span>
+    <CircleButton icon={IconAdd} size={'small'} />
   </div>
-</ScrollBox>
+  <table class="table-body">
+    <thead>
+      <tr class="tr-head">
+        <th>Attachments (2)</th>
+        <th>Time</th>
+      </tr>
+    </thead>
+    <tbody>
+      {#each files as file}
+        <tr class="tr-body">
+          <td class="item flex-row-center">
+            <div class="flex-center file-icon">pdf</div>
+            <div class="flex-col flex-grow">
+              <div class="overflow-label caption-color">{file.name}</div>
+              <div class="overflow-label file-desc">{file.type}</div>
+            </div>
+          </td>
+          <td>10 / 8</td>
+        </tr>
+      {/each}
+    </tbody>
+  </table>
+</div>
 
 <style lang="scss">
+  .attachments-container {
+    display: flex;
+    flex-direction: column;
+
+    .title {
+      margin-right: .75rem;
+      font-weight: 500;
+      font-size: 1.25rem;
+      color: var(--theme-caption-color);
+    }
+  }
+
+  .table-body {
+    margin-top: .75rem;
+
+    th, td {
+      padding: .75rem 0;
+      text-align: left;
+    }
+    th {
+      font-weight: 500;
+      font-size: .75rem;
+      color: var(--theme-content-dark-color);
+    }
+    td {
+      color: var(--theme-caption-color);
+    }
+    .tr-body { border-top: 1px solid var(--theme-button-border-hovered); }
+  }
+
   .item {
     display: flex;
     align-items: center;
     padding: .75rem 1rem;
   }
-  .file-icon, .add-btn {
+  .file-icon {
     margin-right: 1.25rem;
     width: 2rem;
     height: 2rem;
@@ -68,12 +111,11 @@
     line-height: 150%;
     text-transform: uppercase;
     color: #fff;
-    background-color: #7C6FCD;
+    background-color: var(--primary-button-enabled);
     border: 1px solid rgba(0, 0, 0, .1);
   }
   .file-desc {
     font-size: 0.75rem;
     color: var(--theme-content-dark-color);
   }
-  .item + .add-file, .item + .item { border-top: 1px solid var(--theme-bg-accent-hover); }
 </style>
\ No newline at end of file
diff --git a/plugins/recruit-resources/src/components/EditCandidate.svelte b/plugins/recruit-resources/src/components/EditCandidate.svelte
index cb7c5bdb20..43bbb7054b 100644
--- a/plugins/recruit-resources/src/components/EditCandidate.svelte
+++ b/plugins/recruit-resources/src/components/EditCandidate.svelte
@@ -16,12 +16,16 @@
 <script lang="ts">
   import { createEventDispatcher } from 'svelte'
   import type { Ref, Space, Doc } from '@anticrm/core'
-  import { Tabs } from '@anticrm/ui'
-  import { getClient } from '@anticrm/presentation'
+  import { Tabs, EditBox, Link, showPopup, IconFile as FileIcon } from '@anticrm/ui'
+  import FileUpload from './icons/FileUpload.svelte'
+  import PDFViewer from './PDFViewer.svelte'
+  import { getClient, Channels } from '@anticrm/presentation'
   import { Panel } from '@anticrm/panel'
   import type { Candidate } from '@anticrm/recruit'
   import DialogHeader from './DialogHeader.svelte'
   import Contact from './icons/Contact.svelte'
+  import Avatar from './icons/Avatar.svelte'
+  import Attachments from './Attachments.svelte'
 
   import chunter from '@anticrm/chunter'
   
@@ -97,6 +101,8 @@
     }
   ]
 
+  let inputFile: HTMLInputElement
+
 </script>
 
 <!-- <div class="container">
@@ -107,10 +113,97 @@
 </div> -->
 
 <Panel icon={Contact} label={object.firstName + ' ' + object.lastName} on:save={ save } on:close={() => { dispatch('close') }}>
+  <svelte:fragment slot="subtitle">
+    <div class="flex-row-reverse" style="width: 100%">
+      <Channels value={object.channels} reverse />
+    </div>
+  </svelte:fragment>
+
+  <div class="flex-row-center user-container">
+    <div class="avatar">
+      <div class="border"/>
+      <Avatar />
+    </div>
+    <div class="flex-col">
+      <div class="name"><EditBox placeholder="Name" maxWidth="15rem" bind:value={object.firstName}/></div>
+      <div class="name"><EditBox placeholder="Surname" maxWidth="15rem" bind:value={object.lastName}/></div>
+      <div class="city"><EditBox placeholder="Location" maxWidth="15rem" bind:value={object.city}/></div>
+      <div class="flex resume">
+        {#if resume.id}
+          <Link label={resume.name} href={'#'} icon={FileIcon} on:click={ () => { showPopup(PDFViewer, { file: resume.uuid }, 'right') } }/>
+        {:else}
+          <a href={'#'} on:click={ () => { inputFile.click() } }>Upload resume</a>
+          <input bind:this={inputFile} type="file" name="file" id="file" style="display: none" />
+        {/if}
+      </div>
+    </div>
+  </div>
+
+  <div class="attachments">
+    <Attachments />
+  </div>
 
 </Panel>
 
 <style lang="scss">
+  @import '../../../../packages/theme/styles/mixins.scss';
+
+  .user-container {
+    margin-top: 2.5rem;
+  }
+  .avatar {
+    flex-shrink: 0;
+    overflow: hidden;
+    position: relative;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-right: 1.5rem;
+    width: 6rem;
+    height: 6rem;
+    border-radius: 50%;
+    filter: drop-shadow(0px 14px 44px rgba(28, 23, 22, .8));
+    cursor: pointer;
+
+    &::after {
+      content: '';
+      @include bg-layer(var(--theme-avatar-hover), .5);
+      z-index: -1;
+    }
+    &::before {
+      content: '';
+      @include bg-layer(var(--theme-avatar-bg), .1);
+      backdrop-filter: blur(25px);
+      z-index: -2;
+    }
+    .border {
+      @include bg-fullsize;
+      border: 2px solid var(--theme-avatar-border);
+      border-radius: 50%;
+    }
+  }
+
+  .name {
+    font-weight: 500;
+    font-size: 1.25rem;
+    color: var(--theme-caption-color);
+  }
+  .city {
+    margin: .75rem 0 .125rem;
+    font-weight: 500;
+    font-size: .75rem;
+    color: var(--theme-content-color);
+  }
+  .resume a {
+    font-size: .75rem;
+    color: var(--theme-content-dark-color);
+    &:hover { color: var(--theme-content-color); }
+  }
+
+  .attachments {
+    margin-top: 3.5rem;
+  }
+
   // .container {
   //   display: flex;
   //   flex-direction: column;