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;