first, last -> name

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-10-01 14:28:52 +02:00
parent d41af86109
commit 2cd37973a8
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
26 changed files with 869 additions and 944 deletions

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ import { encode } from 'jwt-simple'
import { Client } from 'minio'
import { initWorkspace } from './workspace'
import contact from '@anticrm/contact'
import contact, { combineName } from '@anticrm/contact'
const mongodbUri = process.env.MONGO_URL
if (mongodbUri === undefined) {
@ -107,10 +107,11 @@ program
const contrib = await createContributingClient(url.href)
const txop = new TxOperations(contrib, core.account.System)
const name = combineName(account.first, account.last)
console.log('create user in target workspace...')
const employee = await txop.createDoc(contact.class.Employee, contact.space.Employee, {
firstName: account.first,
lastName: account.last,
name,
city: 'Mountain View',
channels: []
})
@ -119,8 +120,7 @@ program
await txop.createDoc(contact.class.EmployeeAccount, core.space.Model, {
email,
employee,
firstName: account.first,
lastName: account.last
name
})
contrib.close()

File diff suppressed because it is too large Load Diff

View File

@ -52,18 +52,9 @@ export class TContact extends TDoc implements Contact {
@Model(contact.class.Person, contact.class.Contact)
@UX('Person' as IntlString)
export class TPerson extends TContact implements Person {
@Prop(TypeString(), 'First name' as IntlString)
@Prop(TypeString(), 'Name' as IntlString)
@Index(IndexKind.FullText)
firstName!: string
@Prop(TypeString(), 'Last name' as IntlString)
lastName!: string
// @Prop(TypeString(), 'Email' as IntlString)
// email!: string
// @Prop(TypeString(), 'Phone' as IntlString)
// phone!: string
name!: string
@Prop(TypeString(), 'City' as IntlString)
city!: string
@ -81,8 +72,7 @@ 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
name!: string
}
export function createModel (builder: Builder): void {

View File

@ -24,8 +24,7 @@ export function createDemo (builder: Builder): void {
const rosamund = generateId()
builder.createDoc(contact.class.Employee, contact.space.Employee, {
firstName: 'Rosamund',
lastName: 'Chen',
name: 'Chen,Rosamund',
city: 'Mountain View',
channels: []
}, rosamund)
@ -33,13 +32,11 @@ export function createDemo (builder: Builder): void {
builder.createDoc(contact.class.EmployeeAccount, core.space.Model, {
email: 'rosamund@hc.engineering',
employee: rosamund as any,
firstName: 'Rosamund',
lastName: 'Chen'
name: 'Chen,Rosamund'
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
firstName: 'Andrey',
lastName: 'P.',
name: 'P.,Andrey',
title: 'Chief Architect',
city: 'Monte Carlo',
channels: [
@ -52,8 +49,7 @@ export function createDemo (builder: Builder): void {
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
firstName: 'Marina',
lastName: 'M.',
name: 'M.,Marina',
title: 'Chief Designer',
city: 'Los Angeles',
channels: [
@ -66,8 +62,7 @@ export function createDemo (builder: Builder): void {
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
firstName: 'Alex',
lastName: 'P.',
name: 'P.,Alex',
title: 'Frontend Engineer',
city: 'Krasnodar, Russia',
channels: [

View File

@ -22,7 +22,7 @@
import Avatar from './Avatar.svelte'
import { TimeSince } from '@anticrm/ui'
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
export let comment: Comment
@ -38,7 +38,7 @@
<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><TimeSince value={comment.modifiedOn}/></span></div>
<div class="header">{#if employee}{formatName(employee.name)}{/if}<span><TimeSince value={comment.modifiedOn}/></span></div>
<div class="text"><MessageViewer message={comment.message} /></div>
</div>
</div>

View File

@ -23,7 +23,7 @@
import IconAvatar from './icons/Avatar.svelte'
import type { Ref, Class } from '@anticrm/core'
import type { Person } from '@anticrm/contact'
import { formatName, Person } from '@anticrm/contact'
export let _class: Ref<Class<Person>>
export let title: IntlString
@ -72,7 +72,7 @@
<div class="selectUser">
<div class="title"><Label label={title} /></div>
<div class="caption-color">
{#if selected}{selected.firstName + ' ' + selected.lastName}{:else}<Label label={'Not selected'} />{/if}
{#if selected}{formatName(selected.name)}{:else}<Label label={'Not selected'} />{/if}
</div>
</div>
</div>

View File

@ -16,7 +16,7 @@
<script lang="ts">
import Avatar from './Avatar.svelte'
import type { Person } from '@anticrm/contact'
import { formatName, Person } from '@anticrm/contact'
export let value: Person
export let subtitle: string | undefined = undefined
@ -27,7 +27,7 @@
<Avatar {size} />
<div class="flex-col user-info">
{#if subtitle}<div class="subtitle">{subtitle}</div>{/if}
<div class="title">{value.firstName + ' ' + value.lastName}</div>
<div class="title">{formatName(value.name)}</div>
</div>
</div>

View File

@ -19,7 +19,7 @@
import { Editor } from '@tiptap/core'
import { onMount } from 'svelte'
import type { FindResult, Doc, Ref } from '@anticrm/core'
import type { Person } from '@anticrm/contact'
import { formatName, Person } from '@anticrm/contact'
import contact from '@anticrm/contact'
import { getClient, UserInfo } from '@anticrm/presentation'
import { EditStylish, IconSearch } from '@anticrm/ui'
@ -45,7 +45,7 @@ export function onKeyDown(ev: KeyboardEvent) {
if (ev.key === 'Enter') {
const person = items[selected]
if (person) {
command({id: person._id, label: person.firstName + ' ' + person.lastName})
command({id: person._id, label: formatName(person.name)})
return true
} else
return false

View File

@ -67,7 +67,7 @@ onMount(() => {
suggestion: {
items: async query => {
const persons = await client.findAll(contact.class.Person, {})
return persons.filter(person => person.firstName.includes(query))
return persons.filter(person => person.name.includes(query))
},
render: () => {
let component: any

View File

@ -15,6 +15,7 @@
<script lang="ts">
import type { Person } from '@anticrm/contact'
import { formatName } from '@anticrm/contact'
import { Avatar } from '@anticrm/presentation'
interface IMessage {
@ -30,7 +31,7 @@
<div class="flex-nowrap">
<div class="avatar"><Avatar size={'medium'} /></div>
<div class="flex-col-stretch message">
<div class="header">{user.firstName} {user.lastName}<span>{message.createDate}</span></div>
<div class="header">{formatName(user.name)}<span>{message.createDate}</span></div>
<div class="text">{message.text}</div>
</div>
</div>

View File

@ -1,29 +0,0 @@
<!--
// 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 { Grid } from '@anticrm/ui'
import Comment from './Comment.svelte'
</script>
<Grid column={1} rowGap={1.5}>
<Comment user={{firstName: 'Tim', lastName: 'Ferris'}}
message={{createDate: Date.now(), text: 'The Dark Lord has Nine. But we have One, mightier than they: the White Rider. Hero has passed through the fire and the abyss, and they shall fear him. mightier than they: the White Rider. Hero has passed through the fire and the abyss, and they shall fear him.'}}
/>
<Comment user={{firstName: 'Rosamund', lastName: 'Chen'}}
message={{createDate: Date.now(), text: 'The Dark Lord has Nine. But we have One, mightier than they: the White Rider. Hero has passed through the fire and the abyss, and they shall fear him. mightier than they: the White Rider. Hero has passed through the fire and the abyss, and they shall fear him.'}}
/>
</Grid>

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { getResource } from '@anticrm/platform'
import type { Person } from '@anticrm/contact'
import { formatName, Person } from '@anticrm/contact'
import { Avatar, getClient } from '@anticrm/presentation'
import { showPopup } from '@anticrm/ui'
import view from '@anticrm/view'
@ -36,7 +36,7 @@ async function onClick() {
<div class="flex-row-center user-container" on:click={onClick}>
<Avatar size={'x-small'} />
<div class="overflow-label user">{value.firstName + ' ' + value.lastName}</div>
<div class="overflow-label user">{formatName(value.name)}</div>
</div>
<style lang="scss">

View File

@ -43,8 +43,7 @@ export interface Contact extends Doc {
* @public
*/
export interface Person extends Contact {
firstName: string
lastName: string
name: string
// email: string
// phone: string
city: string
@ -68,8 +67,37 @@ export interface Employee extends Person {
*/
export interface EmployeeAccount extends Account {
employee: Ref<Employee>
firstName: string
lastName: string
name: string
}
const SEP = ','
/**
* @public
*/
export function combineName (first: string, last: string): string {
return last + SEP + first
}
/**
* @public
*/
export function getFirstName (name: string): string {
return name.substring(name.indexOf(SEP) + 1)
}
/**
* @public
*/
export function getLastName (name: string): string {
return name.substring(0, name.indexOf(SEP))
}
/**
* @public
*/
export function formatName (name: string): string {
return getFirstName(name) + ' ' + getLastName(name)
}
/**

View File

@ -17,7 +17,7 @@
<script lang="ts">
import { TextArea, EditBox, Dialog, Tabs, Section, Grid, IconFile } from '@anticrm/ui'
import { AttributeEditor, getClient, CommentViewer } from '@anticrm/presentation'
import { AttributeEditor, getClient } from '@anticrm/presentation'
import type { Candidate } from '@anticrm/recruit'
import Address from './icons/Address.svelte'

View File

@ -15,7 +15,7 @@
<script lang="ts">
import { ScrollBox } from '@anticrm/ui'
import Card from './Card.svelte'
import Card from './Card.svelte.txt'
import CardEmpty from './CardEmpty.svelte'
interface Person {

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import type { Ref, Space, Doc } from '@anticrm/core'
import DialogHeader from './DialogHeader.svelte'
import DialogHeader from './DialogHeader.svelte.txt'
import { getClient } from '@anticrm/presentation'

View File

@ -19,7 +19,7 @@
import { TextArea, EditBox, Dialog, Tabs, Section, Grid, IconFile } from '@anticrm/ui'
import Address from './icons/Address.svelte'
import Attachment from './icons/Attachment.svelte'
import DialogHeader from './DialogHeader.svelte'
import DialogHeader from './DialogHeader.svelte.txt'
import { getClient } from '@anticrm/presentation'

View File

@ -39,16 +39,16 @@
import Bond from '../../img/bond.png'
import equals from 'deep-equal'
import { combineName } from '@anticrm/contact';
export let space: Ref<Space>
let _space = space
const object: Candidate = {
lastName: '',
firstName: '',
city: ''
} as Candidate
let firstName = ''
let lastName = ''
const object: Candidate = {} as Candidate
let resume = {} as {
name: string
@ -63,8 +63,7 @@
async function createCandidate() {
const candidate: Data<Candidate> = {
firstName: object.firstName,
lastName: object.lastName,
name: combineName(firstName, lastName),
title: object.title,
city: object.city,
channels: object.channels,
@ -137,7 +136,7 @@
<Card label={'Create Candidate'}
okLabel={'Save'}
okAction={createCandidate}
canSave={object.firstName.length > 0 && object.lastName.length > 0}
canSave={firstName.length > 0 && lastName.length > 0}
spaceClass={recruit.class.Candidates}
spaceLabel={'Talent Pool'}
spacePlaceholder={'Select pool'}
@ -172,8 +171,8 @@
</div>
<div class="flex-col">
<div class="name"><EditBox placeholder="John" maxWidth="9.5rem" bind:value={object.firstName}/></div>
<div class="name"><EditBox placeholder="Appleseed" maxWidth="9.5rem" bind:value={object.lastName}/></div>
<div class="name"><EditBox placeholder="John" maxWidth="9.5rem" bind:value={firstName}/></div>
<div class="name"><EditBox placeholder="Appleseed" maxWidth="9.5rem" bind:value={lastName}/></div>
<div class="title"><EditBox placeholder="Title" maxWidth="9.5rem" bind:value={object.title}/></div>
<div class="city"><EditBox placeholder="Location" maxWidth="9.5rem" bind:value={object.city}/></div>
<!-- <div class="flex resume">

View File

@ -22,7 +22,6 @@
import { getClient, createQuery, Channels, AttributeEditor, PDFViewer } from '@anticrm/presentation'
import { Panel } from '@anticrm/panel'
import type { Candidate, Applicant } 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'
@ -32,6 +31,7 @@
import chunter from '@anticrm/chunter'
import recruit from '../plugin'
import { formatName } from '@anticrm/contact';
export let _id: Ref<Applicant>
let object: Applicant
@ -59,7 +59,7 @@
</script>
{#if object !== undefined && candidate !== undefined}
<Panel icon={Contact} title={candidate.firstName + ' ' + candidate.lastName} {object} on:close={() => { dispatch('close') }}>
<Panel icon={Contact} title={formatName(candidate.name)} {object} on:close={() => { dispatch('close') }}>
<!-- <svelte:fragment slot="subtitle">
<div class="flex-between flex-reverse" style="width: 100%">
<Channels value={object.channels}/>
@ -73,7 +73,7 @@
<Avatar />
</div>
<div class="flex-col">
<div class="name">{candidate.firstName} {candidate.lastName}</div>
<div class="name">{formatName(candidate.name)}</div>
<div class="title">For {getVacancyName()}</div>
<div class="city">at Cisco</div>
</div>

View File

@ -22,7 +22,6 @@
import { getClient, createQuery, Channels, AttributeEditor, PDFViewer } 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'
@ -32,14 +31,18 @@
import chunter from '@anticrm/chunter'
import recruit from '../plugin'
import { combineName, formatName, getFirstName, getLastName } from '@anticrm/contact'
export let _id: Ref<Candidate>
let object: Candidate
let firstName = ''
let lastName = ''
const client = getClient()
const query = createQuery()
$: query.query(recruit.class.Candidate, { _id }, result => { object = result[0] })
$: query.query(recruit.class.Candidate, { _id }, result => { object = result[0]; firstName = getFirstName(result[0].name); lastName = getLastName(result[0].name)})
const dispatch = createEventDispatcher()
@ -48,10 +51,18 @@
client.updateDoc(recruit.class.Candidate, object.space, object._id, { channels: result })
}
function firstNameChange() {
client.updateDoc(recruit.class.Candidate, object.space, object._id, { name: combineName(firstName, getLastName(object.name)) })
}
function lastNameChange() {
client.updateDoc(recruit.class.Candidate, object.space, object._id, { name: combineName(getFirstName(object.name), lastName) })
}
</script>
{#if object !== undefined}
<Panel icon={Contact} title={object.firstName + ' ' + object.lastName} {object} on:close={() => { dispatch('close') }}>
<Panel icon={Contact} title={formatName(object.name)} {object} on:close={() => { dispatch('close') }}>
<svelte:fragment slot="subtitle">
<div class="flex-between flex-reverse" style="width: 100%">
<Channels value={object.channels}/>
@ -65,8 +76,8 @@
<Avatar />
</div>
<div class="flex-col">
<div class="name"><AttributeEditor maxWidth="20rem" _class={recruit.class.Candidate} {object} key="firstName"/></div>
<div class="name"><AttributeEditor maxWidth="20rem" _class={recruit.class.Candidate} {object} key="lastName"/></div>
<div class="name"><EditBox placeholder="John" maxWidth="20rem" bind:value={firstName} on:change={ firstNameChange }/></div>
<div class="name"><EditBox placeholder="Appleseed" maxWidth="20rem" bind:value={lastName} on:change={ lastNameChange }/></div>
<div class="title"><AttributeEditor maxWidth="20rem" _class={recruit.class.Candidate} {object} key="title"/></div>
<div class="city"><AttributeEditor maxWidth="20rem" _class={recruit.class.Candidate} {object} key="city"/></div>
</div>

View File

@ -23,6 +23,7 @@
import EditApplication from './EditApplication.svelte'
import { AttachmentPresenter } from '@anticrm/chunter-resources'
import { formatName } from '@anticrm/contact'
export let object: WithLookup<Applicant>
export let draggable: boolean
@ -45,7 +46,7 @@
</div>
</div>
<div class="flex-col">
<div class="name" on:click={showCandidate}>{object.$lookup?.candidate?.firstName} {object.$lookup?.candidate?.lastName}</div>
<div class="name" on:click={showCandidate}>{formatName(object.$lookup?.candidate?.name)}</div>
<div class="city">{object.$lookup?.candidate?.city}</div>
<div class="tags">
<div class="tag" on:click={showApplication}><Label label={'Application'} /></div>

View File

@ -20,7 +20,6 @@ import CreateCandidates from './components/CreateCandidates.svelte'
import CreateCandidate from './components/CreateCandidate.svelte'
import CreateApplication from './components/CreateApplication.svelte'
import EditCandidate from './components/EditCandidate.svelte'
import CandidateGeneral from './components/CandidateGeneral.svelte'
import Attachments from './components/Attachments.svelte'
import KanbanCard from './components/KanbanCard.svelte'
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
@ -42,7 +41,6 @@ export default async () => ({
CreateCandidate,
CreateApplication,
EditCandidate,
CandidateGeneral,
Attachments,
KanbanCard,
ApplicationPresenter,

File diff suppressed because it is too large Load Diff