Merge branch 'main' of https://github.com/hcengineering/anticrm into add-panel

This commit is contained in:
Alexander Platov 2021-09-11 21:34:56 +03:00
commit f225b726d1
54 changed files with 1053 additions and 829 deletions

43
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,43 @@
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
with:
fetch-depth: 0
# - name: Checking for mis-matching dependencies...
# run: node common/scripts/install-run-rush.js check
# - name: Checking for missing change logs...
# run: node common/scripts/install-run-rush.js change -v
- name: Installing...
run: node common/scripts/install-run-rush.js install
- name: Building...
run: node common/scripts/install-run-rush.js rebuild --verbose
- name: Checking svelte sources...
run: common/scripts/each.sh svelte-check

View File

@ -2,7 +2,7 @@ lockfileVersion: 5.3
specifiers:
'@elastic/elasticsearch': ^7.14.0
'@koa/cors': ~3.1.0
'@koa/cors': ^3.1.0
'@microsoft/api-extractor': ^7.18.4
'@rush-temp/account': file:./projects/account.tgz
'@rush-temp/chunter': file:./projects/chunter.tgz
@ -80,9 +80,10 @@ specifiers:
'@types/express': ^4.17.13
'@types/express-fileupload': ^1.1.7
'@types/heft-jest': ^1.0.2
'@types/koa-bodyparser': ~4.3.3
'@types/koa-router': ~7.4.4
'@types/koa__cors': ~3.0.3
'@types/koa': ^2.13.4
'@types/koa-bodyparser': ^4.3.3
'@types/koa-router': ^7.4.4
'@types/koa__cors': ^3.0.3
'@types/minio': ^7.0.10
'@types/toposort': ^2.0.3
'@types/uuid': ^8.3.1
@ -105,9 +106,9 @@ specifiers:
express-fileupload: ^1.2.1
file-loader: ^6.2.0
intl-messageformat: ^9.7.1
koa: ~2.13.1
koa-bodyparser: ~4.3.0
koa-router: ~10.1.1
koa: ^2.13.1
koa-bodyparser: ^4.3.0
koa-router: ^10.1.1
mini-css-extract-plugin: ^2.2.0
minio: ^7.0.19
node-html-parser: ^4.1.3
@ -209,6 +210,7 @@ dependencies:
'@types/express': 4.17.13
'@types/express-fileupload': 1.1.7
'@types/heft-jest': 1.0.2
'@types/koa': 2.13.4
'@types/koa-bodyparser': 4.3.3
'@types/koa-router': 7.4.4
'@types/koa__cors': 3.0.3
@ -6290,6 +6292,11 @@ packages:
saslprep: 1.0.3
dev: false
/mri/1.1.6:
resolution: {integrity: sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==}
engines: {node: '>=4'}
dev: false
/ms/2.0.0:
resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=}
dev: false
@ -7482,6 +7489,13 @@ packages:
queue-microtask: 1.2.3
dev: false
/sade/1.7.4:
resolution: {integrity: sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==}
engines: {node: '>= 6'}
dependencies:
mri: 1.1.6
dev: false
/safe-buffer/5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: false
@ -8153,6 +8167,35 @@ packages:
supports-color: 7.2.0
dev: false
/svelte-check/2.2.5_635b56cd8c077c5dd126b6e20db90d4b:
resolution: {integrity: sha512-EstDoqxjqWStWELh7Z0qytqUDl/ikdNEr21dveNc4fUDnhnqO2F2jHEufqoNnC3GfBji3GIUHvoXsp/I5lMbCg==}
hasBin: true
peerDependencies:
svelte: ^3.24.0
dependencies:
chalk: 4.1.2
chokidar: 3.4.3
glob: 7.1.7
import-fresh: 3.3.0
minimist: 1.2.5
sade: 1.7.4
source-map: 0.7.3
svelte: 3.42.1
svelte-preprocess: 4.7.4_c407529626dbb58d14a718f48c7fa84c
typescript: 4.3.5
transitivePeerDependencies:
- '@babel/core'
- coffeescript
- less
- node-sass
- postcss
- postcss-load-config
- pug
- sass
- stylus
- sugarss
dev: false
/svelte-dev-helper/1.1.9:
resolution: {integrity: sha1-fRh9tcbNu9ZNdaMvkbiZi94yc8M=}
dev: false
@ -10036,7 +10079,7 @@ packages:
dev: false
file:projects/pod-account.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-LslRQA1JvP/7ifMS9HlLquIlDd1zYoWnm6kA+H4ZTrFySfZ70JVvSTlFffN1cH6IsAPRaEmG0wPX9JrQkSfOCw==, tarball: file:projects/pod-account.tgz}
resolution: {integrity: sha512-RaW5pklTBD+yxSB4u84Yn5+nH/3k1dQqn/TCgVWSOio6INnyuQwFygCBHRwjGupvnuJMC38upU8r3PU99UfZGw==, tarball: file:projects/pod-account.tgz}
id: file:projects/pod-account.tgz
name: '@rush-temp/pod-account'
version: 0.0.0
@ -10432,13 +10475,14 @@ packages:
dev: false
file:projects/ui.tgz_c38cf1a7a413db8918b0b4754c21e4c5:
resolution: {integrity: sha512-nqw2XVY89MoFfK662WYoko9Cu+aLj4f32RjKFdamRPs6ZZRyECkCV3JxAC+d+AYvGEPTLcfQyX2FAHtw94JISA==, tarball: file:projects/ui.tgz}
resolution: {integrity: sha512-0c3Kif2z3qzO+oqkrK7BCL5USvkS4YwBBOzFIFW+RK2fiEeAQJydTYSm8hcgpBHDi1+GhuFKxZt3/ok7HVqBjg==, tarball: file:projects/ui.tgz}
id: file:projects/ui.tgz
name: '@rush-temp/ui'
version: 0.0.0
dependencies:
sass: 1.37.5
svelte: 3.42.1
svelte-check: 2.2.5_635b56cd8c077c5dd126b6e20db90d4b
svelte-loader: 3.1.2_svelte@3.42.1
svelte-preprocess: 4.7.4_c407529626dbb58d14a718f48c7fa84c
transitivePeerDependencies:

37
common/scripts/each.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
#
# 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.
#
set -e
sourceDir=$(dirname "$0")
sourceDir=$(realpath "$sourceDir")
runScript=$sourceDir/install-run-rushx.js
roots=$(node $sourceDir/install-run-rush.js list -f --json | grep "fullPath" | cut -f 2 -d ':' | cut -f 2 -d '"')
for i in $roots
do
pushd ${i}
checkScript=$(cat package.json | grep \"$1\": | wc -l)
if [ $checkScript -gt 0 ]; then
node ${runScript} $@
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Error"
exit $retVal
fi
fi
popd
done

View File

@ -1,4 +1,5 @@
ACCOUNTS_URL=https://ftwm71rwag.execute-api.us-west-2.amazonaws.com/stage/
#ACCOUNTS_URL=https://ftwm71rwag.execute-api.us-west-2.amazonaws.com/stage/
ACCOUNTS_URL=https://account.hc.engineering/
UPLOAD_URL=https://upload.hc.engineering/

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
import { program } from 'commander'
import { MongoClient, Db } from 'mongodb'
import { getAccount, createAccount, assignWorkspace, createWorkspace, ACCOUNT_DB } from '@anticrm/account'
import { getAccount, createAccount, assignWorkspace, createWorkspace, ACCOUNT_DB, dropWorkspace, dropAccount } from '@anticrm/account'
import { createContributingClient } from '@anticrm/contrib'
import core, { TxOperations } from '@anticrm/core'
import { encode } from 'jwt-simple'
@ -118,7 +118,9 @@ program
console.log('create account in target workspace...')
await txop.createDoc(contact.class.EmployeeAccount, core.space.Model, {
email,
employee
employee,
firstName: account.first,
lastName: account.last
})
contrib.close()
@ -146,4 +148,22 @@ program
})
})
program
.command('drop-workspace <name>')
.description('drop workspace')
.action(async (workspace, cmd) => {
return await withDatabase(mongodbUri, async (db) => {
await dropWorkspace(db, workspace)
})
})
program
.command('drop-account <name>')
.description('drop account')
.action(async (email, cmd) => {
return await withDatabase(mongodbUri, async (db) => {
await dropAccount(db, email)
})
})
program.parse(process.argv)

File diff suppressed because it is too large Load Diff

View File

@ -80,6 +80,8 @@ export class TEmployee extends TPerson implements Employee {
@Model(contact.class.EmployeeAccount, core.class.Account)
export class TEmployeeAccount extends TAccount implements EmployeeAccount {
employee!: Ref<Employee>
firstName!: string
lastName!: string
}
export function createModel (builder: Builder): void {

View File

@ -32,7 +32,9 @@ export function createDemo (builder: Builder): void {
builder.createDoc(contact.class.EmployeeAccount, core.space.Model, {
email: 'rosamund@hc.engineering',
employee: rosamund as any
employee: rosamund as any,
firstName: 'Rosamund',
lastName: 'Chen'
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {

View File

@ -108,7 +108,7 @@ export function createModel (builder: Builder): void {
resume: chunter.class.Attachment
}
} as FindOptions<Doc>, // TODO: fix
config: ['', '#' + recruit.component.CreateApplicationPresenter, 'city', '$lookup.resume', 'channels']
config: ['', '#' + recruit.component.CreateApplicationPresenter + '/Action', 'city', '$lookup.resume', 'channels']
})
builder.createDoc(view.class.Viewlet, core.space.Model, {
@ -122,7 +122,7 @@ export function createModel (builder: Builder): void {
state: core.class.State
}
} as FindOptions<Doc>, // TODO: fix
config: ['$lookup.candidate', '$lookup.state', '$lookup.candidate.city', '$lookup.candidate.channels']
config: ['$lookup.candidate', '#' + recruit.component.ApplicationPresenter + '/Application', '$lookup.state', '$lookup.candidate.city', '$lookup.candidate.channels']
})
builder.createDoc(view.class.Viewlet, core.space.Model, {

View File

@ -34,7 +34,8 @@ export default mergeIds(recruitId, recruit, {
CreateApplication: '' as AnyComponent,
EditCandidate: '' as AnyComponent,
KanbanCard: '' as AnyComponent,
CreateApplicationPresenter: '' as AnyComponent
CreateApplicationPresenter: '' as AnyComponent,
ApplicationPresenter: '' as AnyComponent
},
space: {
CandidatesPublic: '' as Ref<Space>

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -27,6 +27,8 @@
export let spaceClass: Ref<Class<Space>>
export let space: Ref<Space>
export let spaceLabel: IntlString
export let spacePlaceholder: IntlString
export let label: IntlString
export let okLabel: IntlString
export let okAction: () => void
@ -44,7 +46,7 @@
<div class="content"><slot /></div>
<div class="flex-col pool" class:shrink={$$slots.contacts}>
<div class="separator" />
<SpaceSelect _class={spaceClass} label={'Title'} placeholder={'Select Project'} bind:value={space} />
<SpaceSelect _class={spaceClass} label={spaceLabel} placeholder={spacePlaceholder} bind:value={space} />
</div>
{#if $$slots.contacts}
<div class="flex-between contacts">

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -10,8 +10,7 @@
"test": "echo 'no tests'",
"lint": "ts-standard src",
"lint:fix": "ts-standard --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && ts-standard --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && ts-standard --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

8
packages/ui/lang/en.json Normal file
View File

@ -0,0 +1,8 @@
{
"string": {
"Cancel": "Cancel",
"Minutes": "{minutes, plural, =0 {less than a minute ago} =1 {a minute ago} other {# minutes ago}}",
"Hours": "{hours, plural, =0 {less than an hour ago} =1 {an hour ago} other {# hours ago}}",
"Days": "{days, plural, =0 {today} =1 {yesterday} other {# days ago}"
}
}

View File

@ -16,7 +16,8 @@
"devDependencies": {
"svelte-loader":"^3.1.2",
"sass":"^1.37.5",
"svelte-preprocess":"^4.7.4"
"svelte-preprocess":"^4.7.4",
"svelte-check": "^2.2.5"
},
"dependencies": {
"@anticrm/platform": "~0.6.5",

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '@anticrm/ui'
import type { AnySvelteComponent } from '../types'
import Spinner from './Spinner.svelte'
import Label from './Label.svelte'
import Icon from './Icon.svelte'
@ -22,7 +22,7 @@
export let label: IntlString
export let primary: boolean = false
export let size: 'small' | 'medium' = 'medium'
export let icon: Asset | AnySvelteComponent | undefined
export let icon: Asset | AnySvelteComponent | undefined = undefined
export let disabled: boolean = false
export let loading: boolean = false
export let transparent: boolean = false

View File

@ -20,7 +20,7 @@
import Add from './icons/Add.svelte'
export let label: IntlString
export let items: Array<Object>
export let items: Array<{description: IntlString, done: boolean}>
= [
{ description: '15 minute phone call', done: true },
{ description: 'Follow up email', done: false },

View File

@ -14,8 +14,8 @@
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '@anticrm/ui'
import type { Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '../types'
import Icon from './Icon.svelte'
export let icon: Asset | AnySvelteComponent

View File

@ -24,6 +24,8 @@
import Button from './Button.svelte'
import Label from './Label.svelte'
import ui from '../plugin'
export let label: IntlString
export let okLabel: IntlString
export let okAction: () => void
@ -42,7 +44,7 @@
</div>
<div class="footer">
<Button label={okLabel} primary />
<Button label={'Cancel'} on:click={() => { dispatch('close') }} />
<Button label={ui.string.Cancel} on:click={() => { dispatch('close') }} />
</div>
</form>
</div>

View File

@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '../types'
import Icon from './Icon.svelte'

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '@anticrm/ui'
import type { AnySvelteComponent } from '../types'
import Icon from './Icon.svelte'
export let label: IntlString

View File

@ -16,19 +16,15 @@
import { popupstore as modal } from '..'
import PopupInstance from './PopupInstance.svelte'
// function close () {
// console.log('closeX')
// function handleKeydown (ev: KeyboardEvent) {
// if (ev.key === 'Escape' && $modal.is) {
// close()
// }
// }
function handleKeydown (ev: KeyboardEvent) {
// if (ev.key === 'Escape' && $modal.is) {
// close()
// }
}
</script>
<svelte:window on:keydown={handleKeydown} />
<!-- <svelte:window on:keydown={handleKeydown} /> -->
{#each $modal as popup, i}
<PopupInstance is={popup.is} props={popup.props} element={popup.element} onClose={popup.onClose} zIndex={(i+1) * 500}/>

View File

@ -22,7 +22,7 @@ import { closePopup } from '..'
export let is: AnyComponent | AnySvelteComponent
export let props: object
export let element: PopupAlignment | undefined
export let onClose: (result: any) => void | undefined
export let onClose: ((result: any) => void) | undefined
export let zIndex: number
let modalHTML: HTMLElement

View File

@ -66,10 +66,10 @@
} else popup.style.left = `${rectT.left}px`
}
const findNode = (el: Node, name: string): any => {
const findNode = (el: HTMLElement, name: string): any => {
while (el.parentNode !== null) {
if (el.classList.contains(name)) return el
el = el.parentNode
el = el.parentNode as HTMLElement
}
return false
}

View File

@ -1,94 +0,0 @@
<!--
// 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 type { AnySvelteComponent, IPopupItem } from '../types'
import Label from './Label.svelte'
import PopupMenu from './PopupMenu.svelte'
import PopupItem from './PopupItem.svelte'
import ActionIcon from './ActionIcon.svelte'
import Close from './icons/Close.svelte'
export let component: AnySvelteComponent | undefined = undefined
export let items: Array<IPopupItem>
export let item: IPopupItem
export let vAlign: 'top' | 'middle' | 'bottom' = 'bottom'
export let hAlign: 'left' | 'center' | 'right' = 'left'
export let margin: number = 1
export let gap: number = .5
let byTitle: boolean = (component) ? false : true
let pressed: boolean = false
</script>
<PopupMenu {vAlign} {hAlign} {margin} bind:show={pressed}>
<button class="btn" slot="trigger" style="margin: {gap/2}px;"
on:click={(event) => {
pressed = !pressed
event.stopPropagation()
}}
>
<div class="title">
{#if byTitle }
<Label label={item.title}/>
{:else}
<svelte:component this={component} {...item.props}/>
{/if}
</div>
<div class="icon"><ActionIcon label={'Remove'} icon={Close} size={'small'} action={async () => { item.selected = false }}/></div>
</button>
{#if byTitle }
<PopupItem bind:title={item.title} selectable bind:selected={item.selected}/>
{:else}
<PopupItem bind:component={component} bind:props={item.props} selectable bind:selected={item.selected}/>
{/if}
{#each items.filter(i => !i.selected) as noItem}
{#if byTitle }
<PopupItem title={noItem.title} selectable bind:selected={noItem.selected} action={async () => {
pressed = false
item.selected = false
}}/>
{:else}
<PopupItem component={component} props={noItem.props} selectable bind:selected={noItem.selected} action={async () => {
pressed = false
item.selected = false
}}/>
{/if}
{/each}
</PopupMenu>
<style lang="scss">
.btn {
justify-content: space-between;
padding: .5rem .75rem;
width: auto;
height: 2.5rem;
background-color: var(--theme-button-bg-pressed);
border: 1px solid var(--theme-bg-accent-color);
border-radius: .75rem;
.title {
flex-grow: 1;
text-align: left;
color: var(--theme-caption-color);
}
.icon {
margin-left: .75rem;
opacity: .8;
}
}
</style>

View File

@ -26,14 +26,14 @@
{#each model as tab, i}
<div class="flex-row-center tab" class:selected={i === selected}
on:click={() => { selected = i }}>
<Label label={model[i].label}/>
<Label label={tab.label}/>
</div>
{/each}
<div class="grow"/>
</div>
{#each model as tab, i}
{#if selected === i}
<Component is = {model[i].component} props={model[i].props}/>
<Component is = {tab.component} props={tab.props}/>
{/if}
{/each}

View File

@ -0,0 +1,48 @@
<!--
// 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.
-->
<script lang="ts">
import { translate } from '@anticrm/platform'
import { ticker } from '..'
import ui from '../plugin'
export let value: number
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
let time: string = ''
async function formatTime(now: number) {
let passed = now - value
if (passed < 0) passed = 0
if (passed < HOUR) {
time = await translate(ui.string.Minutes, { minutes: Math.floor(passed / MINUTE) })
} else if (passed < DAY) {
time = await translate(ui.string.Hours, { hours: Math.floor(passed / HOUR) })
} else {
time = await translate(ui.string.Days, { days: Math.floor(passed / DAY) })
}
}
$: formatTime($ticker)
</script>
{time}

View File

@ -27,7 +27,7 @@
<div
class="tooltip-trigger"
bind:this={triggerHTML}
on:mouseenter={(ev) => {
on:mouseenter={() => {
showTooltip(label, triggerHTML, direction)
}}
on:mouseleave={() => {

View File

@ -1,3 +1,18 @@
<!--
// 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 { getContext } from 'svelte'
import FontSize from './icons/FontSize.svelte'
@ -5,13 +20,11 @@
const { currentFontSize, setFontSize } = getContext('fontsize')
const fontsizes = ['small-font', 'normal-font']
let fsLabel = currentFontSize
let current = fontsizes.indexOf(currentFontSize)
function changeFontSize () {
current++
fsLabel = fontsizes[current % fontsizes.length]
setFontSize(fontsizes[current % fontsizes.length])
}
</script>

View File

@ -16,6 +16,8 @@
import { SvelteComponent } from 'svelte'
import type { AnySvelteComponent, AnyComponent, PopupAlignment, LabelAndProps, TooltipAligment } from './types'
import type { IntlString } from '@anticrm/platform'
import { addStringsLoader } from '@anticrm/platform'
import { uiId } from './plugin'
import Root from './components/internal/Root.svelte'
@ -40,21 +42,21 @@ export { default as Progress } from './components/Progress.svelte'
export { default as Tabs } from './components/Tabs.svelte'
export { default as ScrollBox } from './components/ScrollBox.svelte'
export { default as PopupMenu } from './components/PopupMenu.svelte'
export { default as PopupItem } from './components/PopupItem.svelte'
export { default as SelectItem } from './components/SelectItem.svelte'
// export { default as PopupItem } from './components/PopupItem.svelte'
export { default as TextArea } from './components/TextArea.svelte'
export { default as Section } from './components/Section.svelte'
export { default as DatePicker } from './components/DatePicker.svelte'
export { default as StylishEdit } from './components/StylishEdit.svelte'
export { default as Grid } from './components/Grid.svelte'
export { default as Row } from './components/Row.svelte'
export { default as CheckBoxWithLabel } from './components/CheckBoxWithLabel.svelte'
export { default as CheckBoxList } from './components/CheckBoxList.svelte'
// export { default as CheckBoxWithLabel } from './components/CheckBoxWithLabel.svelte'
// export { default as CheckBoxList } from './components/CheckBoxList.svelte.txt'
export { default as EditWithIcon } from './components/EditWithIcon.svelte'
export { default as Loading } from './components/Loading.svelte'
export { default as Popup } from './components/Popup.svelte'
export { default as CircleButton } from './components/CircleButton.svelte'
export { default as Link } from './components/Link.svelte'
export { default as TimeSince } from './components/TimeSince.svelte'
export { default as IconAdd } from './components/icons/Add.svelte'
export { default as IconClose } from './components/icons/Close.svelte'
@ -71,23 +73,23 @@ export { default as IconActivity } from './components/icons/Activity.svelte'
export * from './utils'
import { writable } from 'svelte/store'
import { writable, readable } from 'svelte/store'
export function createApp (target: HTMLElement): SvelteComponent {
return new Root({ target })
}
interface CompAndProps {
is: AnySvelteComponent | AnyComponent | undefined
is: AnySvelteComponent | AnyComponent
props: any
element?: PopupAlignment
onClose?: (result: any) => void
}
export const store = writable<CompAndProps>({
is: undefined,
props: {},
})
// export const store = writable<CompAndProps>({
// is: undefined,
// props: {},
// })
export const popupstore = writable<CompAndProps[]>([])
@ -118,3 +120,13 @@ export function showTooltip (label: IntlString, element: HTMLElement, direction?
export function closeTooltip (): void {
tooltipstore.set({ label: undefined, element: undefined, direction: undefined })
}
export const ticker = readable(Date.now(), set => {
const interval = setInterval(() => {
set(Date.now())
}, 10000)
})
addStringsLoader(uiId, async (lang: string) => {
return await import(`../lang/${lang}.json`)
})

32
packages/ui/src/plugin.ts Normal file
View File

@ -0,0 +1,32 @@
//
// 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.
//
import type { IntlString, Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
/**
* @public
*/
export const uiId = 'ui' as Plugin
export default plugin(uiId, {
string: {
Cancel: '' as IntlString,
Minutes: '' as IntlString,
Hours: '' as IntlString,
Days: '' as IntlString,
}
})

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -20,29 +20,25 @@
import MessageViewer from '@anticrm/presentation/src/components/MessageViewer.svelte'
import Avatar from '@anticrm/presentation/src/components/Avatar.svelte'
import { TimeSince } from '@anticrm/ui'
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
export let comment: Comment
let employee: Employee | undefined
let employee: EmployeeAccount | undefined
console.log('comment modified by', comment.modifiedBy)
const client = getClient()
client.findOne(contact.class.EmployeeAccount, { _id: comment.modifiedBy as Ref<EmployeeAccount> })
.then(account => client.findOne(contact.class.Employee, { _id: account?.employee }))
.then(result => {
console.log('comment', result)
employee = result
})
client.findOne(contact.class.EmployeeAccount, { _id: comment.modifiedBy as Ref<EmployeeAccount> }).then(account => {employee = account})
</script>
<div class="flex-nowrap">
<div class="avatar"><Avatar size={'medium'} /></div>
<div class="flex-col-stretch message">
<div class="header">{#if employee}{employee.firstName} {employee.lastName}{/if}<span>July 28th</span></div>
<div class="header">{#if employee}{employee.firstName} {employee.lastName}{/if}<span><TimeSince value={comment.modifiedOn}/></span></div>
<div class="text"><MessageViewer message={comment.message} /></div>
</div>
</div>

View File

@ -15,7 +15,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { TextArea, EditBox, Dialog, ToggleWithLabel, Grid, Section, IconToDo, CheckBoxList } from '@anticrm/ui'
import { TextArea, EditBox, Dialog, ToggleWithLabel, Grid, Section, IconToDo } from '@anticrm/ui'
import { getClient } from '@anticrm/presentation'
@ -47,7 +47,7 @@
<TextArea label={chunter.string.ChannelDescription} bind:value={description}/>
<ToggleWithLabel label={chunter.string.MakePrivate} description={chunter.string.MakePrivateDescription}/>
</Grid>
<Section icon={IconToDo} label={`To Do's`}>
<!-- <Section icon={IconToDo} label={`To Do's`}>
<CheckBoxList label={'Add a To Do'} editable />
</Section>
</Section> -->
</Dialog>

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -68,6 +68,8 @@ export interface Employee extends Person {
*/
export interface EmployeeAccount extends Account {
employee: Ref<Employee>
firstName: string
lastName: string
}
/**

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -0,0 +1,26 @@
<!--
// 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.
-->
<script lang="ts">
import type { Applicant } from '@anticrm/recruit'
import { IconFile } from '@anticrm/ui'
export let object: Applicant
</script>
<IconFile size={'small'}/>

View File

@ -58,6 +58,8 @@
okAction={createApplication}
canSave={candidate !== undefined}
spaceClass={recruit.class.Vacancy}
spaceLabel={'Vacancy'}
spacePlaceholder={'Select vacancy'}
bind:space={_space}
on:close={() => { dispatch('close') }}>
<Grid column={1} rowGap={1.75}>

View File

@ -20,14 +20,14 @@
import { Label, showPopup } from '@anticrm/ui'
import CreateApplication from './CreateApplication.svelte'
export let object: Doc
export let value: Doc
let button: HTMLElement
</script>
<div class="flex-center presenter-container" bind:this={button}
on:click={() => { showPopup(CreateApplication, { candidate: object._id, preserveCandidate: true }, button) }}
on:click={() => { showPopup(CreateApplication, { candidate: value._id, preserveCandidate: true }, button) }}
>
<Label label="Create Application" />
</div>

View File

@ -129,6 +129,8 @@
okAction={createCandidate}
canSave={object.firstName.length > 0 && object.lastName.length > 0}
spaceClass={recruit.class.Candidates}
spaceLabel={'Talent Pool'}
spacePlaceholder={'Select pool'}
bind:space={_space}
on:close={() => { dispatch('close') }}>

View File

@ -22,6 +22,7 @@ import CandidateGeneral from './components/CandidateGeneral.svelte'
import Attachments from './components/Attachments.svelte'
import KanbanCard from './components/KanbanCard.svelte'
import CreateApplicationPresenter from './components/CreateApplicationPresenter.svelte'
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
export default async () => ({
component: {
@ -33,6 +34,7 @@ export default async () => ({
CandidateGeneral,
Attachments,
KanbanCard,
CreateApplicationPresenter
CreateApplicationPresenter,
ApplicationPresenter
},
})

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -67,7 +67,7 @@
{#each objects as object (object._id)}
<tr class="tr-body">
{#each model as attribute}
<td><svelte:component this={attribute.presenter} {object} value={getValue(object, attribute.key)}/></td>
<td><svelte:component this={attribute.presenter} value={getValue(object, attribute.key)}/></td>
{/each}
</tr>
{/each}

View File

@ -65,10 +65,11 @@ async function getPresenter(client: Client, _class: Ref<Class<Obj>>, key: string
return getObjectPresenter(client, _class, preserveKey)
} else {
if (key.startsWith('#')) {
const [presenter, label] = key.substring(1).split('/')
return {
key: '',
label: '' as IntlString,
presenter: await getResource(key.substring(1) as AnyComponent)
label: label as IntlString,
presenter: await getResource(presenter as AnyComponent)
}
}
const split = key.split('.')

View File

@ -10,8 +10,7 @@
"test": "jest",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src",
"svelte-check": "svelte-check"
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"svelte-loader":"^3.1.2",

View File

@ -250,6 +250,30 @@ export async function removeWorkspace (db: Db, email: string, workspace: string)
await db.collection(ACCOUNT_COLLECTION).updateOne({ _id: accountId }, { $pull: { workspaces: workspaceId } })
}
/**
* @public
*/
export async function dropWorkspace (db: Db, workspace: string): Promise<void> {
const ws = await getWorkspace(db, workspace)
if (ws === null) {
throw new PlatformError(new Status(Severity.ERROR, accountPlugin.status.WorkspaceNotFound, { workspace }))
}
await db.collection(WORKSPACE_COLLECTION).deleteOne({ _id: ws._id })
await db.collection<Account>(ACCOUNT_COLLECTION).updateMany({ _id: { $in: ws.accounts } }, { $pull: { workspaces: ws._id } })
}
/**
* @public
*/
export async function dropAccount (db: Db, email: string): Promise<void> {
const account = await getAccount(db, email)
if (account === null) {
throw new PlatformError(new Status(Severity.ERROR, accountPlugin.status.AccountNotFound, { account: email }))
}
await db.collection(ACCOUNT_COLLECTION).deleteOne({ _id: account._id })
await db.collection<Workspace>(WORKSPACE_COLLECTION).updateMany({ _id: { $in: account.workspaces } }, { $pull: { accounts: account._id } })
}
function wrap (f: (db: Db, ...args: any[]) => Promise<any>) {
return async function (db: Db, request: Request<any[]>): Promise<Response<any>> {
return await f(db, ...request.params)

File diff suppressed because it is too large Load Diff