mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 03:14:40 +03:00
UBER-665: Rename EmployeeAccount->PersonAccount (#3550)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
9acc1b86a0
commit
161d26ebeb
@ -49,7 +49,7 @@ export async function generateIssues (
|
||||
options: IssueOptions
|
||||
): Promise<void> {
|
||||
const connection = await connect(transactorUrl, workspaceId)
|
||||
const accounts = await connection.findAll(contact.class.EmployeeAccount, {})
|
||||
const accounts = await connection.findAll(contact.class.PersonAccount, {})
|
||||
const account = faker.random.arrayElement(accounts)
|
||||
const client = new TxOperations(connection, account._id)
|
||||
const ctx = new MeasureMetricsContext('recruit', {})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import contact, { Channel, Employee, EmployeeAccount, Person } from '@hcengineering/contact'
|
||||
import contact, { Channel, PersonAccount, Person, Employee } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AttachedData,
|
||||
Data,
|
||||
@ -48,9 +48,9 @@ export async function generateContacts (
|
||||
): Promise<void> {
|
||||
const connection = await connect(transactorUrl, workspaceId)
|
||||
|
||||
const accounts = await connection.findAll(contact.class.EmployeeAccount, {})
|
||||
const accounts = await connection.findAll(contact.class.PersonAccount, {})
|
||||
const accountIds = accounts.map((a) => a._id)
|
||||
const emoloyeeIds = accounts.map((a) => a.employee)
|
||||
const emoloyeeIds = accounts.map((a) => a.person as Ref<Employee>)
|
||||
|
||||
const account = faker.random.arrayElement(accounts)
|
||||
|
||||
@ -78,7 +78,7 @@ export async function generateContacts (
|
||||
|
||||
async function genVacansyApplicants (
|
||||
ctx: MeasureContext,
|
||||
accountIds: Ref<EmployeeAccount>[],
|
||||
accountIds: Ref<PersonAccount>[],
|
||||
options: RecruitOptions,
|
||||
i: number,
|
||||
client: TxOperations,
|
||||
|
@ -207,7 +207,7 @@ export async function benchmark (
|
||||
'avg',
|
||||
{},
|
||||
async () =>
|
||||
await monitorConnection?.findAll(contact.class.Employee, {}).then((res) => {
|
||||
await monitorConnection?.findAll(contact.mixin.Employee, {}).then((res) => {
|
||||
const cur = Date.now() - st
|
||||
opTime += cur
|
||||
moment = cur
|
||||
|
@ -76,7 +76,7 @@ export async function cleanWorkspace (
|
||||
if (opt.recruit) {
|
||||
const contacts = await ops.findAll(recruit.mixin.Candidate, {})
|
||||
console.log('removing Talents', contacts.length)
|
||||
const filter = contacts.filter((it) => !hierarchy.isDerived(it._class, contact.class.Employee))
|
||||
const filter = contacts.filter((it) => !hierarchy.isDerived(it._class, contact.mixin.Employee))
|
||||
|
||||
while (filter.length > 0) {
|
||||
const part = filter.splice(0, 100)
|
||||
|
@ -33,7 +33,7 @@ export async function diffWorkspace (mongoUrl: string, workspace: WorkspaceId, r
|
||||
.find<Tx>({
|
||||
objectSpace: core.space.Model,
|
||||
modifiedBy: core.account.System,
|
||||
objectClass: { $ne: contact.class.EmployeeAccount }
|
||||
objectClass: { $ne: contact.class.PersonAccount }
|
||||
})
|
||||
.toArray()
|
||||
|
||||
@ -41,7 +41,7 @@ export async function diffWorkspace (mongoUrl: string, workspace: WorkspaceId, r
|
||||
return (
|
||||
tx.objectSpace === core.space.Model &&
|
||||
tx.modifiedBy === core.account.System &&
|
||||
(tx as any).objectClass !== contact.class.EmployeeAccount
|
||||
(tx as any).objectClass !== contact.class.PersonAccount
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -88,10 +88,10 @@ export class TCard extends TTask implements Card {
|
||||
@Index(IndexKind.FullText)
|
||||
location?: string
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), board.string.Assignee)
|
||||
@Prop(TypeRef(contact.mixin.Employee), board.string.Assignee)
|
||||
declare assignee: Ref<Employee> | null
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), board.string.Members)
|
||||
@Prop(ArrOf(TypeRef(contact.mixin.Employee)), board.string.Members)
|
||||
members?: Ref<Employee>[]
|
||||
|
||||
@Prop(TypeCardCover(), board.string.Cover)
|
||||
|
@ -22,7 +22,7 @@ import contact from '@hcengineering/contact'
|
||||
|
||||
async function migrateCalendars (tx: TxOperations): Promise<void> {
|
||||
const existCalendars = new Set((await tx.findAll(calendar.class.Calendar, {})).map((p) => p._id))
|
||||
const users = await tx.findAll(contact.class.EmployeeAccount, {})
|
||||
const users = await tx.findAll(contact.class.PersonAccount, {})
|
||||
for (const user of users) {
|
||||
if (!existCalendars.has(`${user._id}_calendar` as Ref<Calendar>)) {
|
||||
await tx.createDoc(
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
SavedMessages,
|
||||
ThreadMessage
|
||||
} from '@hcengineering/chunter'
|
||||
import contact, { Employee } from '@hcengineering/contact'
|
||||
import contact, { Person } from '@hcengineering/contact'
|
||||
import type { Account, Class, Doc, Domain, Ref, Space, Timestamp } from '@hcengineering/core'
|
||||
import { IndexKind } from '@hcengineering/core'
|
||||
import {
|
||||
@ -113,8 +113,8 @@ export class TMessage extends TChunterMessage implements Message {
|
||||
|
||||
declare attachedToClass: Ref<Class<Space>>
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), chunter.string.Replies)
|
||||
replies?: Ref<Employee>[]
|
||||
@Prop(ArrOf(TypeRef(contact.class.Person)), chunter.string.Replies)
|
||||
replies?: Ref<Person>[]
|
||||
|
||||
repliesCount?: number
|
||||
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
Contact,
|
||||
ContactsTab,
|
||||
Employee,
|
||||
EmployeeAccount,
|
||||
PersonAccount,
|
||||
GetAvatarUrl,
|
||||
Member,
|
||||
Organization,
|
||||
@ -39,8 +39,11 @@ import {
|
||||
Collection,
|
||||
Hidden,
|
||||
Index,
|
||||
Mixin,
|
||||
Model,
|
||||
Prop,
|
||||
ReadOnly,
|
||||
TypeBoolean,
|
||||
TypeDate,
|
||||
TypeRef,
|
||||
TypeString,
|
||||
@ -153,27 +156,30 @@ export class TStatus extends TAttachedDoc implements Status {
|
||||
dueDate!: Timestamp
|
||||
}
|
||||
|
||||
@Model(contact.class.Employee, contact.class.Person)
|
||||
@Mixin(contact.mixin.Employee, contact.class.Person)
|
||||
@UX(contact.string.Employee, contact.icon.Person, 'EMP', 'name')
|
||||
export class TEmployee extends TPerson implements Employee {
|
||||
active!: boolean
|
||||
@Prop(TypeBoolean(), contact.string.Active)
|
||||
@ReadOnly()
|
||||
@Hidden()
|
||||
active!: boolean
|
||||
|
||||
@Prop(Collection(contact.class.Status), contact.string.Status)
|
||||
@Hidden()
|
||||
statuses?: number
|
||||
|
||||
mergedTo?: Ref<Employee>
|
||||
|
||||
@Prop(TypeString(), contact.string.DisplayName)
|
||||
@Hidden()
|
||||
displayName?: string | null
|
||||
|
||||
@Prop(TypeString(), contact.string.Position)
|
||||
@Hidden()
|
||||
position?: string | null
|
||||
}
|
||||
|
||||
@Model(contact.class.EmployeeAccount, core.class.Account)
|
||||
export class TEmployeeAccount extends TAccount implements EmployeeAccount {
|
||||
employee!: Ref<Employee>
|
||||
mergedTo!: Ref<EmployeeAccount>
|
||||
@Model(contact.class.PersonAccount, core.class.Account)
|
||||
export class TPersonAccount extends TAccount implements PersonAccount {
|
||||
person!: Ref<Person>
|
||||
}
|
||||
|
||||
@Model(contact.class.Organizations, core.class.Space)
|
||||
@ -201,14 +207,14 @@ export function createModel (builder: Builder): void {
|
||||
TOrganization,
|
||||
TOrganizations,
|
||||
TEmployee,
|
||||
TEmployeeAccount,
|
||||
TPersonAccount,
|
||||
TChannel,
|
||||
TStatus,
|
||||
TMember,
|
||||
TContactsTab
|
||||
)
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ObjectFactory, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.ObjectFactory, {
|
||||
component: contact.component.CreateEmployee
|
||||
})
|
||||
|
||||
@ -239,7 +245,7 @@ export function createModel (builder: Builder): void {
|
||||
icon: contact.icon.Person,
|
||||
label: contact.string.Employee,
|
||||
componentProps: {
|
||||
_class: contact.class.Employee,
|
||||
_class: contact.mixin.Employee,
|
||||
icon: contact.icon.Person,
|
||||
label: contact.string.Employee,
|
||||
createLabel: contact.string.CreateEmployee,
|
||||
@ -253,6 +259,9 @@ export function createModel (builder: Builder): void {
|
||||
label: contact.string.Person,
|
||||
componentProps: {
|
||||
_class: contact.class.Person,
|
||||
baseQuery: {
|
||||
[contact.mixin.Employee]: { $exists: false }
|
||||
},
|
||||
icon: contact.icon.Person,
|
||||
label: contact.string.Person,
|
||||
createLabel: contact.string.CreatePerson,
|
||||
@ -337,7 +346,7 @@ export function createModel (builder: Builder): void {
|
||||
baseQuery: {
|
||||
_class: {
|
||||
$in: [contact.class.Person],
|
||||
$nin: [contact.class.Employee]
|
||||
$nin: [contact.mixin.Employee]
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -347,7 +356,7 @@ export function createModel (builder: Builder): void {
|
||||
view.class.Viewlet,
|
||||
core.space.Model,
|
||||
{
|
||||
attachTo: contact.class.Employee,
|
||||
attachTo: contact.mixin.Employee,
|
||||
descriptor: view.viewlet.Table,
|
||||
config: [
|
||||
'',
|
||||
@ -400,7 +409,7 @@ export function createModel (builder: Builder): void {
|
||||
pinned: true
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ObjectEditor, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.ObjectEditor, {
|
||||
editor: contact.component.EditEmployee,
|
||||
pinned: true
|
||||
})
|
||||
@ -418,7 +427,7 @@ export function createModel (builder: Builder): void {
|
||||
editor: contact.component.Members
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ArrayEditor, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.ArrayEditor, {
|
||||
inlineEditor: contact.component.EmployeeArrayEditor
|
||||
})
|
||||
|
||||
@ -450,7 +459,7 @@ export function createModel (builder: Builder): void {
|
||||
inlineEditor: contact.component.PersonEditor
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.AttributeEditor, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.AttributeEditor, {
|
||||
inlineEditor: contact.component.EmployeeEditor
|
||||
})
|
||||
|
||||
@ -466,15 +475,15 @@ export function createModel (builder: Builder): void {
|
||||
encode: contact.function.GetContactLink
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.AttributeFilterPresenter, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.AttributeFilterPresenter, {
|
||||
presenter: contact.component.EmployeeFilterValuePresenter
|
||||
})
|
||||
|
||||
builder.mixin(core.class.Account, core.class.Class, view.mixin.AttributeFilterPresenter, {
|
||||
presenter: contact.component.EmployeeAccountFilterValuePresenter
|
||||
presenter: contact.component.PersonAccountFilterValuePresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.AttributeFilter, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.AttributeFilter, {
|
||||
component: contact.component.EmployeeFilter
|
||||
})
|
||||
|
||||
@ -621,15 +630,15 @@ export function createModel (builder: Builder): void {
|
||||
inlineEditor: contact.component.AccountArrayEditor
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.EmployeeAccount, core.class.Class, view.mixin.ArrayEditor, {
|
||||
builder.mixin(contact.class.PersonAccount, core.class.Class, view.mixin.ArrayEditor, {
|
||||
inlineEditor: contact.component.AccountArrayEditor
|
||||
})
|
||||
|
||||
builder.mixin(core.class.Account, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: contact.component.EmployeeAccountPresenter
|
||||
presenter: contact.component.PersonAccountPresenter
|
||||
})
|
||||
builder.mixin(core.class.Account, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: contact.component.EmployeeAccountRefPresenter
|
||||
presenter: contact.component.PersonAccountRefPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
@ -640,11 +649,11 @@ export function createModel (builder: Builder): void {
|
||||
presenter: contact.component.ContactPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: contact.component.EmployeePresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.SortFuncs, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.SortFuncs, {
|
||||
func: contact.function.EmployeeSort
|
||||
})
|
||||
|
||||
@ -656,11 +665,11 @@ export function createModel (builder: Builder): void {
|
||||
presenter: contact.component.ContactRefPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.AttributePresenter, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: contact.component.EmployeeRefPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.IgnoreActions, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [view.action.Delete]
|
||||
})
|
||||
|
||||
@ -671,7 +680,7 @@ export function createModel (builder: Builder): void {
|
||||
builder.mixin(contact.class.Person, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: []
|
||||
})
|
||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ClassFilters, {
|
||||
builder.mixin(contact.mixin.Employee, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: []
|
||||
})
|
||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.ClassFilters, {
|
||||
@ -737,7 +746,7 @@ export function createModel (builder: Builder): void {
|
||||
active: true
|
||||
},
|
||||
category: contact.category.Contact,
|
||||
target: contact.class.Employee,
|
||||
target: contact.mixin.Employee,
|
||||
input: 'focus',
|
||||
context: {
|
||||
mode: ['context'],
|
||||
@ -757,7 +766,7 @@ export function createModel (builder: Builder): void {
|
||||
active: false
|
||||
},
|
||||
category: contact.category.Contact,
|
||||
target: contact.class.Employee,
|
||||
target: contact.mixin.Employee,
|
||||
input: 'focus',
|
||||
context: {
|
||||
mode: ['context'],
|
||||
@ -773,18 +782,16 @@ export function createModel (builder: Builder): void {
|
||||
{
|
||||
action: view.actionImpl.ShowPopup,
|
||||
actionProps: {
|
||||
component: contact.component.MergeEmployee,
|
||||
component: contact.component.MergePersons,
|
||||
element: 'top',
|
||||
fillProps: {
|
||||
_object: 'value'
|
||||
}
|
||||
},
|
||||
query: {
|
||||
active: false
|
||||
},
|
||||
label: contact.string.MergeEmployee,
|
||||
query: {},
|
||||
label: contact.string.MergePersons,
|
||||
category: contact.category.Contact,
|
||||
target: contact.class.Employee,
|
||||
target: contact.class.Person,
|
||||
input: 'focus',
|
||||
context: {
|
||||
mode: ['context'],
|
||||
@ -792,7 +799,7 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
secured: true
|
||||
},
|
||||
contact.action.MergeEmployee
|
||||
contact.action.MergePersons
|
||||
)
|
||||
|
||||
// Allow to use fuzzy search for mixins
|
||||
|
@ -1,9 +1,11 @@
|
||||
//
|
||||
|
||||
import { TxOperations } from '@hcengineering/core'
|
||||
import { Class, DOMAIN_TX, Doc, Domain, Ref, TxOperations } from '@hcengineering/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import { DOMAIN_COMMENT } from '@hcengineering/model-chunter'
|
||||
import core from '@hcengineering/model-core'
|
||||
import contact from './index'
|
||||
import { DOMAIN_VIEW } from '@hcengineering/model-view'
|
||||
import contact, { DOMAIN_CONTACT } from './index'
|
||||
|
||||
async function createSpace (tx: TxOperations): Promise<void> {
|
||||
const current = await tx.findOne(core.class.Space, {
|
||||
@ -43,14 +45,14 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
||||
}
|
||||
|
||||
async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
const employees = await client.findAll(contact.class.Employee, {})
|
||||
const employees = await client.findAll(contact.mixin.Employee, {})
|
||||
const channels = await client.findAll(contact.class.Channel, {
|
||||
provider: contact.channelProvider.Email,
|
||||
attachedTo: { $in: employees.map((p) => p._id) }
|
||||
})
|
||||
const channelsMap = new Map(channels.map((p) => [p.attachedTo, p]))
|
||||
for (const employee of employees) {
|
||||
const acc = await client.findOne(contact.class.EmployeeAccount, { employee: employee._id })
|
||||
const acc = await client.findOne(contact.class.PersonAccount, { person: employee._id })
|
||||
if (acc === undefined) continue
|
||||
const current = channelsMap.get(employee._id)
|
||||
if (current === undefined) {
|
||||
@ -58,7 +60,7 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
contact.class.Channel,
|
||||
contact.space.Contacts,
|
||||
employee._id,
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
'channels',
|
||||
{
|
||||
provider: contact.channelProvider.Email,
|
||||
@ -74,7 +76,88 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
}
|
||||
|
||||
export const contactOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient): Promise<void> {},
|
||||
async migrate (client: MigrationClient): Promise<void> {
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
objectClass: 'contact:class:EmployeeAccount'
|
||||
},
|
||||
{
|
||||
$rename: { 'attributes.employee': 'attributes.person' },
|
||||
$set: { objectClass: contact.class.PersonAccount }
|
||||
}
|
||||
)
|
||||
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
objectClass: 'contact:class:Employee'
|
||||
},
|
||||
{
|
||||
$set: { objectClass: contact.mixin.Employee }
|
||||
}
|
||||
)
|
||||
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
'tx.attributes.backlinkClass': 'contact:class:Employee'
|
||||
},
|
||||
{
|
||||
$set: { 'tx.attributes.backlinkClass': contact.mixin.Employee }
|
||||
}
|
||||
)
|
||||
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
'tx.attributes.backlinkClass': 'contact:class:Employee'
|
||||
},
|
||||
{
|
||||
$set: { 'tx.attributes.backlinkClass': contact.mixin.Employee }
|
||||
}
|
||||
)
|
||||
|
||||
for (const d of client.hierarchy.domains()) {
|
||||
await client.update(
|
||||
d,
|
||||
{ attachedToClass: 'contact:class:Employee' },
|
||||
{ $set: { attachedToClass: contact.mixin.Employee } }
|
||||
)
|
||||
}
|
||||
await client.update(
|
||||
DOMAIN_COMMENT,
|
||||
{ backlinkClass: 'contact:class:Employee' },
|
||||
{ $set: { backlinkClass: contact.mixin.Employee } }
|
||||
)
|
||||
await client.update(
|
||||
'tags' as Domain,
|
||||
{ targetClass: 'contact:class:Employee' },
|
||||
{ $set: { targetClass: contact.mixin.Employee } }
|
||||
)
|
||||
await client.update(
|
||||
DOMAIN_VIEW,
|
||||
{ filterClass: 'contact:class:Employee' },
|
||||
{ $set: { filterClass: contact.mixin.Employee } }
|
||||
)
|
||||
await client.update(
|
||||
DOMAIN_CONTACT,
|
||||
{
|
||||
_class: 'contact:class:Employee' as Ref<Class<Doc>>
|
||||
},
|
||||
{
|
||||
$rename: {
|
||||
active: `${contact.mixin.Employee as string}.active`,
|
||||
statuses: `${contact.mixin.Employee as string}.statuses`,
|
||||
displayName: `${contact.mixin.Employee as string}.displayName`,
|
||||
position: `${contact.mixin.Employee as string}.position`
|
||||
},
|
||||
$set: {
|
||||
_class: contact.class.Person
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
||||
const tx = new TxOperations(client, core.account.System)
|
||||
await createSpace(tx)
|
||||
|
@ -36,8 +36,8 @@ export default mergeIds(contactId, contact, {
|
||||
OrganizationPresenter: '' as AnyComponent,
|
||||
Contacts: '' as AnyComponent,
|
||||
ContactsTabs: '' as AnyComponent,
|
||||
EmployeeAccountPresenter: '' as AnyComponent,
|
||||
EmployeeAccountRefPresenter: '' as AnyComponent,
|
||||
PersonAccountPresenter: '' as AnyComponent,
|
||||
PersonAccountRefPresenter: '' as AnyComponent,
|
||||
OrganizationEditor: '' as AnyComponent,
|
||||
EmployeePresenter: '' as AnyComponent,
|
||||
EmployeeRefPresenter: '' as AnyComponent,
|
||||
@ -52,13 +52,13 @@ export default mergeIds(contactId, contact, {
|
||||
CreateEmployee: '' as AnyComponent,
|
||||
AccountArrayEditor: '' as AnyComponent,
|
||||
ChannelFilter: '' as AnyComponent,
|
||||
MergeEmployee: '' as AnyComponent,
|
||||
MergePersons: '' as AnyComponent,
|
||||
ActivityChannelMessage: '' as AnyComponent,
|
||||
ChannelPanel: '' as AnyComponent,
|
||||
ActivityChannelPresenter: '' as AnyComponent,
|
||||
EmployeeFilter: '' as AnyComponent,
|
||||
EmployeeFilterValuePresenter: '' as AnyComponent,
|
||||
EmployeeAccountFilterValuePresenter: '' as AnyComponent
|
||||
PersonAccountFilterValuePresenter: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
Persons: '' as IntlString,
|
||||
@ -114,7 +114,7 @@ export default mergeIds(contactId, contact, {
|
||||
action: {
|
||||
KickEmployee: '' as Ref<Action>,
|
||||
DeleteEmployee: '' as Ref<Action>,
|
||||
MergeEmployee: '' as Ref<Action>
|
||||
MergePersons: '' as Ref<Action>
|
||||
},
|
||||
actionImpl: {
|
||||
KickEmployee: '' as ViewAction,
|
||||
|
@ -133,13 +133,13 @@ export class TDocument extends TDoc implements Document {
|
||||
@Hidden()
|
||||
versions!: number
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), document.string.Authors)
|
||||
@Prop(ArrOf(TypeRef(contact.mixin.Employee)), document.string.Authors)
|
||||
authors!: Ref<Employee>[]
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), document.string.Reviewers)
|
||||
@Prop(ArrOf(TypeRef(contact.mixin.Employee)), document.string.Reviewers)
|
||||
reviewers!: Ref<Employee>[]
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), document.string.Approvers)
|
||||
@Prop(ArrOf(TypeRef(contact.mixin.Employee)), document.string.Approvers)
|
||||
approvers!: Ref<Employee>[]
|
||||
|
||||
@Prop(Collection(document.class.DocumentRequest), document.string.Requests)
|
||||
|
@ -43,7 +43,7 @@ import {
|
||||
import attachment from '@hcengineering/model-attachment'
|
||||
import calendar from '@hcengineering/model-calendar'
|
||||
import chunter from '@hcengineering/model-chunter'
|
||||
import contact, { TEmployee, TEmployeeAccount } from '@hcengineering/model-contact'
|
||||
import contact, { TEmployee, TPersonAccount } from '@hcengineering/model-contact'
|
||||
import core, { TAttachedDoc, TDoc, TSpace, TType } from '@hcengineering/model-core'
|
||||
import view, { classPresenter, createAction } from '@hcengineering/model-view'
|
||||
import workbench from '@hcengineering/model-workbench'
|
||||
@ -80,7 +80,7 @@ export class TDepartment extends TSpace implements Department {
|
||||
|
||||
avatar?: string | null
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), hr.string.TeamLead)
|
||||
@Prop(TypeRef(contact.mixin.Employee), hr.string.TeamLead)
|
||||
teamLead!: Ref<Employee> | null
|
||||
|
||||
@Prop(ArrOf(TypeRef(hr.class.DepartmentMember)), contact.string.Members)
|
||||
@ -89,15 +89,15 @@ export class TDepartment extends TSpace implements Department {
|
||||
@Prop(ArrOf(TypeRef(contact.class.Contact)), hr.string.Subscribers)
|
||||
subscribers?: Arr<Ref<Contact>>
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.Employee)), hr.string.Managers)
|
||||
@Prop(ArrOf(TypeRef(contact.mixin.Employee)), hr.string.Managers)
|
||||
managers!: Arr<Ref<Employee>>
|
||||
}
|
||||
|
||||
@Model(hr.class.DepartmentMember, contact.class.EmployeeAccount)
|
||||
@Model(hr.class.DepartmentMember, contact.class.PersonAccount)
|
||||
@UX(contact.string.Employee, hr.icon.HR)
|
||||
export class TDepartmentMember extends TEmployeeAccount implements DepartmentMember {}
|
||||
export class TDepartmentMember extends TPersonAccount implements DepartmentMember {}
|
||||
|
||||
@Mixin(hr.mixin.Staff, contact.class.Employee)
|
||||
@Mixin(hr.mixin.Staff, contact.mixin.Employee)
|
||||
@UX(hr.string.Staff, hr.icon.HR, 'STFF', 'name')
|
||||
export class TStaff extends TEmployee implements Staff {
|
||||
@Prop(TypeRef(hr.class.Department), hr.string.Department)
|
||||
|
@ -78,7 +78,7 @@ export class TLead extends TTask implements Lead {
|
||||
@Index(IndexKind.FullText)
|
||||
title!: string
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), lead.string.Assignee)
|
||||
@Prop(TypeRef(contact.mixin.Employee), lead.string.Assignee)
|
||||
declare assignee: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: task.attribute.State })
|
||||
|
@ -162,7 +162,7 @@ export class TApplicant extends TTask implements Applicant {
|
||||
@Prop(TypeDate(), task.string.StartDate)
|
||||
startDate!: Timestamp | null
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), recruit.string.AssignedRecruiter)
|
||||
@Prop(TypeRef(contact.mixin.Employee), recruit.string.AssignedRecruiter)
|
||||
declare assignee: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeRef(task.class.State), task.string.TaskState, { _id: task.attribute.State })
|
||||
@ -1105,7 +1105,7 @@ export function createModel (builder: Builder): void {
|
||||
actionPopup: view.component.ValueSelector,
|
||||
actionProps: {
|
||||
attribute: 'assignee',
|
||||
_class: contact.class.Employee,
|
||||
_class: contact.mixin.Employee,
|
||||
query: {},
|
||||
placeholder: recruit.string.AssignRecruiter
|
||||
},
|
||||
|
@ -13,7 +13,7 @@ import { generateClassNotificationTypes } from '@hcengineering/model-notificatio
|
||||
export const reviewTableOptions: FindOptions<Review> = {
|
||||
lookup: {
|
||||
attachedTo: recruit.mixin.Candidate,
|
||||
participants: contact.class.Employee,
|
||||
participants: contact.mixin.Employee,
|
||||
company: contact.class.Organization
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
import activity from '@hcengineering/activity'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import type { EmployeeAccount } from '@hcengineering/contact'
|
||||
import type { PersonAccount } from '@hcengineering/contact'
|
||||
import contact from '@hcengineering/contact'
|
||||
import { Domain, IndexKind, Ref, Tx } from '@hcengineering/core'
|
||||
import {
|
||||
@ -48,13 +48,13 @@ export const DOMAIN_REQUEST = 'request' as Domain
|
||||
@Model(request.class.Request, core.class.AttachedDoc, DOMAIN_REQUEST)
|
||||
@UX(request.string.Request, request.icon.Requests)
|
||||
export class TRequest extends TAttachedDoc implements Request {
|
||||
@Prop(ArrOf(TypeRef(contact.class.EmployeeAccount)), request.string.Requested)
|
||||
@Prop(ArrOf(TypeRef(contact.class.PersonAccount)), request.string.Requested)
|
||||
@Index(IndexKind.Indexed)
|
||||
requested!: Ref<EmployeeAccount>[]
|
||||
requested!: Ref<PersonAccount>[]
|
||||
|
||||
@Prop(ArrOf(TypeRef(contact.class.EmployeeAccount)), request.string.Approved)
|
||||
@Prop(ArrOf(TypeRef(contact.class.PersonAccount)), request.string.Approved)
|
||||
@ReadOnly()
|
||||
approved!: Ref<EmployeeAccount>[]
|
||||
approved!: Ref<PersonAccount>[]
|
||||
|
||||
requiredApprovesCount!: number
|
||||
|
||||
@ -64,9 +64,9 @@ export class TRequest extends TAttachedDoc implements Request {
|
||||
|
||||
tx!: Tx
|
||||
|
||||
@Prop(TypeRef(contact.class.EmployeeAccount), request.string.Rejected)
|
||||
@Prop(TypeRef(contact.class.PersonAccount), request.string.Rejected)
|
||||
@ReadOnly()
|
||||
rejected?: Ref<EmployeeAccount>
|
||||
rejected?: Ref<PersonAccount>
|
||||
|
||||
@Prop(Collection(chunter.class.Comment), chunter.string.Comments)
|
||||
comments?: number
|
||||
|
@ -34,10 +34,10 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverCalendar.trigger.OnEmployeeAccountCreate,
|
||||
trigger: serverCalendar.trigger.OnPersonAccountCreate,
|
||||
txMatch: {
|
||||
_class: core.class.TxCreateDoc,
|
||||
objectClass: contact.class.EmployeeAccount
|
||||
objectClass: contact.class.PersonAccount
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -55,12 +55,4 @@ export function createModel (builder: Builder): void {
|
||||
_class: core.class.TxUpdateDoc
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverContact.trigger.OnEmployeeUpdate,
|
||||
txMatch: {
|
||||
objectClass: contact.class.Employee,
|
||||
_class: core.class.TxUpdateDoc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Employee } from '@hcengineering/contact'
|
||||
import type { Employee, Person } from '@hcengineering/contact'
|
||||
import contact from '@hcengineering/contact'
|
||||
import attachment from '@hcengineering/model-attachment'
|
||||
import chunter from '@hcengineering/model-chunter'
|
||||
@ -101,8 +101,8 @@ export class TTask extends TAttachedDoc implements Task {
|
||||
@Hidden()
|
||||
number!: number
|
||||
|
||||
// @Prop(TypeRef(contact.class.Employee), task.string.TaskAssignee)
|
||||
assignee!: Ref<Employee> | null
|
||||
// @Prop(TypeRef(contact.mixin.Employee), task.string.TaskAssignee)
|
||||
assignee!: Ref<Person> | null
|
||||
|
||||
@Prop(TypeDate(), task.string.DueDate, { editor: task.component.DueDateEditor })
|
||||
dueDate!: Timestamp | null
|
||||
@ -126,7 +126,7 @@ export class TTodoItem extends TAttachedDoc implements TodoItem {
|
||||
@Index(IndexKind.FullText)
|
||||
name!: string
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), task.string.TaskAssignee)
|
||||
@Prop(TypeRef(contact.mixin.Employee), task.string.TaskAssignee)
|
||||
assignee!: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeBoolean(), task.string.TaskDone)
|
||||
|
@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import activity from '@hcengineering/activity'
|
||||
import contact, { Employee } from '@hcengineering/contact'
|
||||
import contact, { Employee, Person } from '@hcengineering/contact'
|
||||
import {
|
||||
DOMAIN_MODEL,
|
||||
DateRangeMode,
|
||||
@ -135,7 +135,7 @@ export class TProject extends TSpaceWithStates implements Project {
|
||||
@Prop(TypeRef(tracker.class.IssueStatus), tracker.string.DefaultIssueStatus)
|
||||
defaultIssueStatus!: Ref<IssueStatus>
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.DefaultAssignee)
|
||||
@Prop(TypeRef(contact.mixin.Employee), tracker.string.DefaultAssignee)
|
||||
defaultAssignee!: Ref<Employee>
|
||||
|
||||
declare defaultTimeReportDay: TimeReportDayType
|
||||
@ -183,9 +183,9 @@ export class TIssue extends TTask implements Issue {
|
||||
@ReadOnly()
|
||||
number!: number
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.Assignee)
|
||||
@Prop(TypeRef(contact.class.Person), tracker.string.Assignee)
|
||||
@Index(IndexKind.Indexed)
|
||||
assignee!: Ref<Employee> | null
|
||||
assignee!: Ref<Person> | null
|
||||
|
||||
@Prop(TypeRef(tracker.class.Component), tracker.string.Component, { icon: tracker.icon.Component })
|
||||
@Index(IndexKind.Indexed)
|
||||
@ -256,8 +256,8 @@ export class TIssueTemplate extends TDoc implements IssueTemplate {
|
||||
@Prop(TypeIssuePriority(), tracker.string.Priority)
|
||||
priority!: IssuePriority
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.Assignee)
|
||||
assignee!: Ref<Employee> | null
|
||||
@Prop(TypeRef(contact.class.Person), tracker.string.Assignee)
|
||||
assignee!: Ref<Person> | null
|
||||
|
||||
@Prop(TypeRef(tracker.class.Component), tracker.string.Component)
|
||||
component!: Ref<Component> | null
|
||||
@ -298,7 +298,7 @@ export class TTimeSpendReport extends TAttachedDoc implements TimeSpendReport {
|
||||
@Prop(TypeRef(tracker.class.Issue), tracker.string.Parent)
|
||||
declare attachedTo: Ref<Issue>
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), contact.string.Employee)
|
||||
@Prop(TypeRef(contact.mixin.Employee), contact.string.Employee)
|
||||
employee!: Ref<Employee>
|
||||
|
||||
@Prop(TypeDate(), tracker.string.TimeSpendReportDate)
|
||||
@ -324,7 +324,7 @@ export class TComponent extends TDoc implements Component {
|
||||
@Prop(TypeMarkup(), tracker.string.Description)
|
||||
description?: Markup
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.ComponentLead)
|
||||
@Prop(TypeRef(contact.mixin.Employee), tracker.string.ComponentLead)
|
||||
lead!: Ref<Employee> | null
|
||||
|
||||
@Prop(Collection(chunter.class.Comment), chunter.string.Comments)
|
||||
@ -1584,7 +1584,7 @@ export function createModel (builder: Builder): void {
|
||||
actionPopup: view.component.ValueSelector,
|
||||
actionProps: {
|
||||
attribute: 'assignee',
|
||||
_class: contact.class.Employee,
|
||||
_class: contact.mixin.Employee,
|
||||
query: {},
|
||||
placeholder: tracker.string.AssignTo
|
||||
},
|
||||
@ -2006,7 +2006,7 @@ export function createModel (builder: Builder): void {
|
||||
dividerBefore: true,
|
||||
key: 'lead'
|
||||
},
|
||||
props: { _class: tracker.class.Component, defaultClass: contact.class.Employee, shouldShowLabel: false }
|
||||
props: { _class: tracker.class.Component, defaultClass: contact.mixin.Employee, shouldShowLabel: false }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -279,16 +279,17 @@ async function loadModel (
|
||||
console.log('find' + (lastTxTime >= 0 ? 'full model' : 'model diff'), atxes.length, Date.now() - t)
|
||||
|
||||
// Ignore Employee accounts.
|
||||
function isEmployeeAccount (tx: Tx): boolean {
|
||||
function isPersonAccount (tx: Tx): boolean {
|
||||
return (
|
||||
(tx._class === core.class.TxCreateDoc ||
|
||||
tx._class === core.class.TxUpdateDoc ||
|
||||
tx._class === core.class.TxRemoveDoc) &&
|
||||
(tx as TxCUD<Doc>).objectClass === 'contact:class:EmployeeAccount'
|
||||
((tx as TxCUD<Doc>).objectClass === 'contact:class:PersonAccount' ||
|
||||
(tx as TxCUD<Doc>).objectClass === 'contact:class:Account')
|
||||
)
|
||||
}
|
||||
|
||||
atxes.forEach((tx) => (tx.modifiedBy === core.account.System && !isEmployeeAccount(tx) ? systemTx : userTx).push(tx))
|
||||
atxes.forEach((tx) => (tx.modifiedBy === core.account.System && !isPersonAccount(tx) ? systemTx : userTx).push(tx))
|
||||
|
||||
if (allowedPlugins != null) {
|
||||
fillConfiguration(systemTx, configs)
|
||||
|
@ -227,10 +227,11 @@ export class TxOperations implements Omit<Client, 'notify'> {
|
||||
modifiedBy?: Ref<Account>
|
||||
): Promise<TxResult> {
|
||||
const hierarchy = this.client.getHierarchy()
|
||||
if (hierarchy.isMixin(doc._class)) {
|
||||
const mixClass = Hierarchy.mixinOrClass(doc)
|
||||
if (hierarchy.isMixin(mixClass)) {
|
||||
// TODO: Rework it is wrong, we need to split values to mixin update and original document update if mixed.
|
||||
const baseClass = hierarchy.getBaseClass(doc._class)
|
||||
return this.updateMixin(doc._id, baseClass, doc.space, doc._class, update, modifiedOn, modifiedBy)
|
||||
return this.updateMixin(doc._id, baseClass, doc.space, mixClass, update, modifiedOn, modifiedBy)
|
||||
}
|
||||
if (hierarchy.isDerived(doc._class, core.class.AttachedDoc)) {
|
||||
const adoc = doc as unknown as AttachedDoc
|
||||
|
@ -16,7 +16,6 @@
|
||||
"AccountAlreadyExists": "Account already exists",
|
||||
"WorkspaceRateLimit": "Server is busy, Please wait a bit and try again",
|
||||
"AccountAlreadyConfirmed": "Account already confirmed",
|
||||
"AccountWasMerged": "Account was merged",
|
||||
"WorkspaceAlreadyExists": "Workspace already exists",
|
||||
"ProductIdMismatch": "Product Mismatch"
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
"AccountAlreadyExists": "Аккаунт уже существует",
|
||||
"WorkspaceRateLimit": "Сервер перегружен, Пожалуйста подождите",
|
||||
"AccountAlreadyConfirmed": "Аккаунт уже подтвержден",
|
||||
"AccountWasMerged": "Аккаунт был объединен",
|
||||
"WorkspaceAlreadyExists": "Рабочее пространство уже существует",
|
||||
"ProductIdMismatch": "Продукт не соответсвует"
|
||||
}
|
||||
|
@ -150,7 +150,6 @@ export default plugin(platformId, {
|
||||
InvalidPassword: '' as StatusCode<{ account: string }>,
|
||||
AccountAlreadyExists: '' as StatusCode<{ account: string }>,
|
||||
AccountAlreadyConfirmed: '' as StatusCode<{ account: string }>,
|
||||
AccountWasMerged: '' as StatusCode<{ account: string }>,
|
||||
WorkspaceAlreadyExists: '' as StatusCode<{ workspace: string }>,
|
||||
WorkspaceRateLimit: '' as StatusCode<{ workspace: string }>,
|
||||
ProductIdMismatch: '' as StatusCode<{ productId: string }>
|
||||
|
@ -76,6 +76,7 @@
|
||||
<svelte:component
|
||||
this={editor}
|
||||
readonly={isReadonly}
|
||||
disabled="(isReadonly)"
|
||||
label={attribute?.label}
|
||||
placeholder={attribute?.label}
|
||||
{kind}
|
||||
@ -101,6 +102,7 @@
|
||||
{attributeKey}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
readonly={isReadonly}
|
||||
disabled="(isReadonly)"
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
|
@ -47,6 +47,10 @@
|
||||
export let readonly = false
|
||||
export let disallowDeselect: Ref<Doc>[] | undefined = undefined
|
||||
|
||||
export let filter: (it: Doc) => boolean = () => {
|
||||
return true
|
||||
}
|
||||
|
||||
const created: Doc[] = []
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -75,9 +79,9 @@
|
||||
})
|
||||
if (created.length > 0) {
|
||||
const cmap = new Set(created.map((it) => it._id))
|
||||
objects = [...created, ...result.filter((d) => !cmap.has(d._id))]
|
||||
objects = [...created, ...result.filter((d) => !cmap.has(d._id))].filter(filter)
|
||||
} else {
|
||||
objects = result
|
||||
objects = result.filter(filter)
|
||||
}
|
||||
},
|
||||
{ ...(options ?? {}), limit: 200 }
|
||||
|
@ -48,6 +48,12 @@
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
function correctClass (clName: string): string {
|
||||
if (clName === 'contact:class:Employee') {
|
||||
return 'contact:mixin:Employee'
|
||||
}
|
||||
return clName
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if nodes}
|
||||
@ -121,7 +127,7 @@
|
||||
props={{
|
||||
objectId: node.getAttribute('data-id'),
|
||||
title: node.getAttribute('data-label'),
|
||||
_class: node.getAttribute('data-objectclass'),
|
||||
_class: correctClass(node.getAttribute('data-objectclass')),
|
||||
inline: true
|
||||
}}
|
||||
/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
import type { DisplayTx, TxViewlet } from '@hcengineering/activity'
|
||||
import attachment from '@hcengineering/attachment'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import contact, { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import contact, { Employee, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import core, { AnyAttribute, Class, Doc, Ref, TxCUD, getCurrentAccount } from '@hcengineering/core'
|
||||
import { Asset } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
let viewlet: TxDisplayViewlet | undefined
|
||||
let props: any
|
||||
let account: EmployeeAccount | undefined
|
||||
let account: PersonAccount | undefined
|
||||
let employee: Employee | undefined
|
||||
let model: AttributeModel[] = []
|
||||
let modelIcon: Asset | undefined = undefined
|
||||
@ -97,8 +97,8 @@
|
||||
})
|
||||
|
||||
$: query.query(
|
||||
contact.class.EmployeeAccount,
|
||||
{ _id: tx.tx.modifiedBy as Ref<EmployeeAccount> },
|
||||
contact.class.PersonAccount,
|
||||
{ _id: tx.tx.modifiedBy as Ref<PersonAccount> },
|
||||
(res) => {
|
||||
;[account] = res
|
||||
},
|
||||
@ -107,8 +107,8 @@
|
||||
|
||||
$: account &&
|
||||
employeeQuery.query(
|
||||
contact.class.Employee,
|
||||
{ _id: account.employee },
|
||||
contact.mixin.Employee,
|
||||
{ _id: account.person as Ref<Employee> },
|
||||
(res) => {
|
||||
;[employee] = res
|
||||
},
|
||||
@ -213,7 +213,7 @@
|
||||
<div class="msgactivity-content__title labels-row">
|
||||
<span class={withAvatar ? 'bold' : 'strong'}>
|
||||
{#if employee}
|
||||
{getName(employee)}
|
||||
{getName(client.getHierarchy(), employee)}
|
||||
{:else}
|
||||
<Label label={core.string.System} />
|
||||
{/if}
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { Person, PersonAccount } from '@hcengineering/contact'
|
||||
import core, { Class, getCurrentAccount, Ref, Space } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Label, Loading, navigate, TabList, SearchEdit, getLocation } from '@hcengineering/ui'
|
||||
@ -38,8 +38,8 @@
|
||||
navigate(loc)
|
||||
}
|
||||
export let requestedSpaceClasses: Ref<Class<Space>>[] = []
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
let selectedParticipants: Ref<Employee>[] = [currentUser.employee]
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
let selectedParticipants: Ref<Person>[] = [currentUser.person]
|
||||
let selectedSpaces: Ref<Space>[] = []
|
||||
export let search: string = ''
|
||||
let isLoading = false
|
||||
@ -58,14 +58,14 @@
|
||||
selectedSort_: FileBrowserSortMode,
|
||||
selectedFileTypeId_: string,
|
||||
selectedDateId_: string,
|
||||
selectedParticipants_: Ref<Employee>[],
|
||||
selectedParticipants_: Ref<Person>[],
|
||||
selectedSpaces_: Ref<Space>[]
|
||||
) {
|
||||
isLoading = true
|
||||
|
||||
const nameQuery = searchQuery_ ? { name: { $like: '%' + searchQuery_ + '%' } } : {}
|
||||
|
||||
const accounts = await client.findAll(contact.class.EmployeeAccount, { employee: { $in: selectedParticipants_ } })
|
||||
const accounts = await client.findAll(contact.class.PersonAccount, { person: { $in: selectedParticipants_ } })
|
||||
const senderQuery = accounts.length ? { modifiedBy: { $in: accounts.map((a) => a._id) } } : {}
|
||||
|
||||
let spaceQuery: { space: any }
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import { Class, Ref, Space } from '@hcengineering/core'
|
||||
import { SpaceMultiBoxList } from '@hcengineering/presentation'
|
||||
import { Component, DropdownLabelsIntl } from '@hcengineering/ui'
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
export let requestedSpaceClasses: Ref<Class<Space>>[]
|
||||
export let spaceId: Ref<Space> | undefined
|
||||
export let selectedParticipants: Ref<Employee>[]
|
||||
export let selectedParticipants: Ref<Person>[]
|
||||
export let selectedSpaces: Ref<Space>[]
|
||||
export let selectedDateId: string
|
||||
export let selectedFileTypeId: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||
import chunter, { Comment } from '@hcengineering/chunter'
|
||||
import contact, { Channel, combineName, Contact, EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { Channel, combineName, Contact, Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import core, {
|
||||
Account,
|
||||
AccountRole,
|
||||
@ -489,8 +489,8 @@ interface SyncOptionsExtra {
|
||||
ownerTypeValues: BitrixOwnerType[]
|
||||
commentFieldKeys: string[]
|
||||
allMappings: FindResult<BitrixEntityMapping>
|
||||
allEmployee: FindResult<EmployeeAccount>
|
||||
userList: Map<string, Ref<EmployeeAccount>>
|
||||
allEmployee: FindResult<PersonAccount>
|
||||
userList: Map<string, Ref<PersonAccount>>
|
||||
}
|
||||
|
||||
/**
|
||||
@ -505,7 +505,7 @@ export async function performSynchronization (ops: SyncOptions): Promise<BitrixS
|
||||
|
||||
const commentFieldKeys = Object.keys(commentFields.result)
|
||||
|
||||
const allEmployee = await ops.client.findAll(contact.class.EmployeeAccount, {})
|
||||
const allEmployee = await ops.client.findAll(contact.class.PersonAccount, {})
|
||||
|
||||
const allMappings = await ops.client.findAll<BitrixEntityMapping>(
|
||||
bitrix.class.EntityMapping,
|
||||
@ -519,7 +519,7 @@ export async function performSynchronization (ops: SyncOptions): Promise<BitrixS
|
||||
}
|
||||
)
|
||||
|
||||
const userList = new Map<string, Ref<EmployeeAccount>>()
|
||||
const userList = new Map<string, Ref<PersonAccount>>()
|
||||
|
||||
// Fill all users and create new ones, if required.
|
||||
await synchronizeUsers(userList, ops, allEmployee)
|
||||
@ -764,7 +764,7 @@ async function downloadComments (
|
||||
syncEmails?: boolean
|
||||
},
|
||||
commentFieldKeys: string[],
|
||||
userList: Map<string, Ref<EmployeeAccount>>,
|
||||
userList: Map<string, Ref<PersonAccount>>,
|
||||
ownerTypeValues: BitrixOwnerType[]
|
||||
): Promise<void> {
|
||||
const entityType = ops.mapping.type.replace('crm.', '')
|
||||
@ -887,7 +887,7 @@ async function downloadComments (
|
||||
}
|
||||
|
||||
async function synchronizeUsers (
|
||||
userList: Map<string, Ref<EmployeeAccount>>,
|
||||
userList: Map<string, Ref<PersonAccount>>,
|
||||
ops: {
|
||||
client: TxOperations
|
||||
bitrixClient: BitrixClient
|
||||
@ -900,13 +900,13 @@ async function synchronizeUsers (
|
||||
monitor: (total: number) => void
|
||||
blobProvider?: ((blobRef: { file: string, id: string }) => Promise<Blob | undefined>) | undefined
|
||||
},
|
||||
allEmployee: FindResult<EmployeeAccount>
|
||||
allEmployee: FindResult<PersonAccount>
|
||||
): Promise<void> {
|
||||
let totalUsers = 1
|
||||
let next = 0
|
||||
|
||||
const employeesList = await ops.client.findAll(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{},
|
||||
{
|
||||
lookup: {
|
||||
@ -929,23 +929,25 @@ async function synchronizeUsers (
|
||||
// Try to find from employee
|
||||
employeesList.forEach((it) => {
|
||||
if ((it.$lookup?.channels as Channel[])?.some((q) => q.value === u.EMAIL)) {
|
||||
account = allEmployee.find((qit) => qit.employee === it._id)
|
||||
account = allEmployee.find((qit) => qit.person === it._id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let accountId = account?._id
|
||||
if (accountId === undefined) {
|
||||
const employeeId = await ops.client.createDoc(contact.class.Employee, contact.space.Contacts, {
|
||||
const employeeId = await ops.client.createDoc(contact.class.Person, contact.space.Contacts, {
|
||||
name: combineName(u.NAME, u.LAST_NAME),
|
||||
avatar: u.PERSONAL_PHOTO,
|
||||
active: u.ACTIVE,
|
||||
city: u.PERSONAL_CITY
|
||||
})
|
||||
accountId = await ops.client.createDoc(contact.class.EmployeeAccount, core.space.Model, {
|
||||
await ops.client.createMixin(employeeId, contact.class.Person, contact.space.Contacts, contact.mixin.Employee, {
|
||||
active: u.ACTIVE
|
||||
})
|
||||
accountId = await ops.client.createDoc(contact.class.PersonAccount, core.space.Model, {
|
||||
email: u.EMAIL,
|
||||
name: combineName(u.NAME, u.LAST_NAME),
|
||||
employee: employeeId,
|
||||
person: employeeId,
|
||||
role: AccountRole.User
|
||||
})
|
||||
if (u.EMAIL !== undefined && u.EMAIL !== null) {
|
||||
@ -953,7 +955,7 @@ async function synchronizeUsers (
|
||||
contact.class.Channel,
|
||||
contact.space.Contacts,
|
||||
employeeId,
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
'channels',
|
||||
{
|
||||
provider: contact.channelProvider.Email,
|
||||
@ -963,7 +965,7 @@ async function synchronizeUsers (
|
||||
}
|
||||
await ops.client.createMixin<Doc, BitrixSyncDoc>(
|
||||
employeeId,
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
contact.space.Contacts,
|
||||
bitrix.mixin.BitrixSyncDoc,
|
||||
{
|
||||
@ -973,7 +975,7 @@ async function synchronizeUsers (
|
||||
}
|
||||
)
|
||||
} else if (account != null) {
|
||||
const emp = employees.get(account.employee)
|
||||
const emp = employees.get(account.person as unknown as Ref<Employee>)
|
||||
if (emp !== undefined && !ops.client.getHierarchy().hasMixin(emp, bitrix.mixin.BitrixSyncDoc)) {
|
||||
await ops.client.createMixin<Doc, BitrixSyncDoc>(emp._id, emp._class, emp.space, bitrix.mixin.BitrixSyncDoc, {
|
||||
type: 'employee',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||
import contact, { Channel, EmployeeAccount, Organization } from '@hcengineering/contact'
|
||||
import contact, { Channel, PersonAccount, Organization } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AnyAttribute,
|
||||
AttachedDoc,
|
||||
@ -102,7 +102,7 @@ export async function convert (
|
||||
space: Ref<Space>,
|
||||
fields: BitrixFieldMapping[],
|
||||
rawDocument: any,
|
||||
userList: Map<string, Ref<EmployeeAccount>>,
|
||||
userList: Map<string, Ref<PersonAccount>>,
|
||||
existingDoc: WithLookup<Doc> | undefined,
|
||||
defaultCategories: TagCategory[],
|
||||
allTagElements: TagElement[],
|
||||
|
@ -3,8 +3,8 @@
|
||||
import { Ref } from '@hcengineering/core'
|
||||
|
||||
import contact from '@hcengineering/contact'
|
||||
import board from '../plugin'
|
||||
import { Component } from '@hcengineering/ui'
|
||||
import board from '../plugin'
|
||||
|
||||
export let value: Ref<Employee>[]
|
||||
export let readonly = false
|
||||
|
@ -16,20 +16,20 @@
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { EmployeeBox } from '@hcengineering/contact-resources'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
|
||||
import { MessageBox, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import type { TodoItem } from '@hcengineering/task'
|
||||
import task, { calcRank } from '@hcengineering/task'
|
||||
import {
|
||||
Button,
|
||||
CheckBox,
|
||||
DateRangePresenter,
|
||||
getEventPopupPositionElement,
|
||||
IconAdd,
|
||||
IconDelete,
|
||||
IconMoreH,
|
||||
Progress,
|
||||
showPopup,
|
||||
TextAreaEditor
|
||||
TextAreaEditor,
|
||||
getEventPopupPositionElement,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
import { ContextMenu, HTMLPresenter } from '@hcengineering/view-resources'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Card } from '@hcengineering/board'
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import {
|
||||
TxOperations as Client,
|
||||
TxResult,
|
||||
@ -86,9 +86,9 @@ export function canAddCurrentUser (card: Card): boolean {
|
||||
if (card.members == null) {
|
||||
return true
|
||||
}
|
||||
const employee = (getCurrentAccount() as EmployeeAccount).employee
|
||||
const employee = (getCurrentAccount() as PersonAccount).person
|
||||
|
||||
return !card.members.includes(employee)
|
||||
return !card.members.includes(employee as Ref<Employee>)
|
||||
}
|
||||
|
||||
export function hasCover (card: Card): boolean {
|
||||
@ -100,13 +100,13 @@ export function hasDate (card: Card): boolean {
|
||||
}
|
||||
|
||||
export function addCurrentUser (card: Card, client: Client): Promise<TxResult> | undefined {
|
||||
const employee = (getCurrentAccount() as EmployeeAccount).employee
|
||||
const employee = (getCurrentAccount() as PersonAccount).person
|
||||
|
||||
if (card.members?.includes(employee) === true) {
|
||||
if (card.members?.includes(employee as Ref<Employee>) === true) {
|
||||
return
|
||||
}
|
||||
|
||||
return client.update(card, { $push: { members: employee } })
|
||||
return client.update(card, { $push: { members: employee as Ref<Employee> } })
|
||||
}
|
||||
|
||||
export function archiveCard (card: Card, client: Client): Promise<TxResult> | undefined {
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Calendar, Event, getAllEvents } from '@hcengineering/calendar'
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import {
|
||||
Class,
|
||||
Doc,
|
||||
@ -58,7 +58,7 @@
|
||||
CalendarMode.Year
|
||||
]
|
||||
|
||||
const me = getCurrentAccount() as EmployeeAccount
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
|
||||
const mondayStart = true
|
||||
let mode: CalendarMode = allowedModes.includes(CalendarMode.Days) ? CalendarMode.Days : allowedModes[0]
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Calendar, generateEventId } from '@hcengineering/calendar'
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import { UserBoxList } from '@hcengineering/contact-resources'
|
||||
import { Class, DateRangeMode, Doc, Ref, getCurrentAccount } from '@hcengineering/core'
|
||||
import { Card, getClient } from '@hcengineering/presentation'
|
||||
@ -40,8 +40,8 @@
|
||||
let dueDateRef: DateRangePresenter
|
||||
let allDay = false
|
||||
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
let participants: Ref<Employee>[] = [currentUser.employee]
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
let participants: Ref<Employee>[] = [currentUser.person as Ref<Employee>]
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Calendar, Event, generateEventId } from '@hcengineering/calendar'
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import { UserBoxList } from '@hcengineering/contact-resources'
|
||||
import { Class, DateRangeMode, Doc, Ref, getCurrentAccount } from '@hcengineering/core'
|
||||
import { Card, getClient } from '@hcengineering/presentation'
|
||||
@ -29,8 +29,8 @@
|
||||
let _title = title
|
||||
|
||||
let value: number | null | undefined = null
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
let participants: Ref<Employee>[] = [currentUser.employee]
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
let participants: Ref<Employee>[] = [currentUser.person as Ref<Employee>]
|
||||
const defaultDuration = 30 * 60 * 1000
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { Doc, getCurrentAccount } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Button, showPopup } from '@hcengineering/ui'
|
||||
@ -34,10 +34,10 @@
|
||||
if (isEvent) {
|
||||
showPopup(SaveEventReminder, { objectId: value._id, objectClass: value._class }, ev.target as HTMLElement)
|
||||
} else {
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
const current = await client.findOne(calendar.class.Event, {
|
||||
attachedTo: value._id,
|
||||
participants: currentUser.employee
|
||||
participants: currentUser.person
|
||||
})
|
||||
if (current === undefined) {
|
||||
showPopup(
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Event } from '@hcengineering/calendar'
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { Class, Doc, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Button, deviceOptionsStore as deviceInfo, IconAdd, Label, Scroller, showPopup } from '@hcengineering/ui'
|
||||
@ -26,14 +26,14 @@
|
||||
export let attachedToClass: Ref<Class<Doc>>
|
||||
export let title: string | undefined
|
||||
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
let events: Event[] = []
|
||||
const query = createQuery()
|
||||
$: query.query(
|
||||
calendar.class.Event,
|
||||
{
|
||||
attachedTo,
|
||||
participants: currentUser.employee
|
||||
participants: currentUser.person
|
||||
},
|
||||
(res) => {
|
||||
events = res.filter((p) => p.reminders !== undefined && p.reminders.length > 0)
|
||||
|
@ -20,6 +20,7 @@
|
||||
import calendar from '../plugin'
|
||||
import { showPanel, tooltip } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let value: Person | Person[]
|
||||
export let inline: boolean = false
|
||||
@ -30,15 +31,17 @@
|
||||
async function onClick (p: Person) {
|
||||
showPanel(view.component.EditDoc, p._id, Hierarchy.mixinOrClass(p), 'content')
|
||||
}
|
||||
const client = getClient()
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex persons">
|
||||
{#each persons as p}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="flex-presenter"
|
||||
class:inline-presenter={inline}
|
||||
use:tooltip={{ label: calendar.string.PersonsLabel, props: { name: getName(p) } }}
|
||||
use:tooltip={{ label: calendar.string.PersonsLabel, props: { name: getName(client.getHierarchy(), p) } }}
|
||||
on:click={() => onClick(p)}
|
||||
>
|
||||
<div class="icon">
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { Backlink } from '@hcengineering/chunter'
|
||||
import contact, { EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { PersonAccount } from '@hcengineering/contact'
|
||||
import { Account, Class, Client, Data, Doc, DocumentQuery, Ref, TxOperations } from '@hcengineering/core'
|
||||
import chunter from './plugin'
|
||||
|
||||
export async function getUser (
|
||||
client: Client,
|
||||
user: Ref<EmployeeAccount> | Ref<Account>
|
||||
): Promise<EmployeeAccount | undefined> {
|
||||
return await client.findOne(contact.class.EmployeeAccount, { _id: user as Ref<EmployeeAccount> })
|
||||
user: Ref<PersonAccount> | Ref<Account>
|
||||
): Promise<PersonAccount | undefined> {
|
||||
return await client.findOne(contact.class.PersonAccount, { _id: user as Ref<PersonAccount> })
|
||||
}
|
||||
|
||||
export function getTime (time: number): string {
|
||||
|
@ -43,7 +43,7 @@
|
||||
requestedSpaceClasses: [plugin.class.Channel, plugin.class.DirectMessage]
|
||||
}
|
||||
},
|
||||
{ searchType: SearchType.Contacts, component: EmployeeBrowser, filterClass: contact.class.Employee }
|
||||
{ searchType: SearchType.Contacts, component: EmployeeBrowser, filterClass: contact.mixin.Employee }
|
||||
]
|
||||
</script>
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { getName, Person } from '@hcengineering/contact'
|
||||
import { Avatar } from '@hcengineering/contact-resources'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
interface IMessage {
|
||||
text: string
|
||||
@ -23,12 +24,13 @@
|
||||
|
||||
export let user: Person
|
||||
export let message: IMessage
|
||||
const client = getClient()
|
||||
</script>
|
||||
|
||||
<div class="flex-nowrap">
|
||||
<div class="avatar"><Avatar size={'medium'} /></div>
|
||||
<div class="flex-col-stretch message">
|
||||
<div class="header">{getName(user)}<span>{message.createDate}</span></div>
|
||||
<div class="header">{getName(client.getHierarchy(), user)}<span>{message.createDate}</span></div>
|
||||
<div class="text">{message.text}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -17,10 +17,10 @@
|
||||
import { AttachmentDocList } from '@hcengineering/attachment-resources'
|
||||
import type { Comment } from '@hcengineering/chunter'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import { Avatar, employeeAccountByIdStore, employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import { Avatar, personByIdStore, personAccountByIdStore } from '@hcengineering/contact-resources'
|
||||
import { IdMap, Ref } from '@hcengineering/core'
|
||||
import { MessageViewer } from '@hcengineering/presentation'
|
||||
import { MessageViewer, getClient } from '@hcengineering/presentation'
|
||||
import { Icon, ShowMore, TimeSince } from '@hcengineering/ui'
|
||||
import { LinkPresenter } from '@hcengineering/view-resources'
|
||||
|
||||
@ -28,18 +28,20 @@
|
||||
export let inline: boolean = false
|
||||
export let disabled = false
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const cutId = (str: string): string => {
|
||||
return str.slice(0, 4) + '...' + str.slice(-4)
|
||||
}
|
||||
|
||||
async function getEmployee (
|
||||
value: Comment,
|
||||
employees: IdMap<Employee>,
|
||||
accounts: IdMap<EmployeeAccount>
|
||||
): Promise<Employee | undefined> {
|
||||
const acc = accounts.get(value.modifiedBy as Ref<EmployeeAccount>)
|
||||
employees: IdMap<Person>,
|
||||
accounts: IdMap<PersonAccount>
|
||||
): Promise<Person | undefined> {
|
||||
const acc = accounts.get(value.modifiedBy as Ref<PersonAccount>)
|
||||
if (acc !== undefined) {
|
||||
const emp = employees.get(acc.employee)
|
||||
const emp = employees.get(acc.person)
|
||||
return emp
|
||||
}
|
||||
}
|
||||
@ -76,14 +78,14 @@
|
||||
<span class="content-dark-color">#{cutId(value._id.toString())}</span>
|
||||
{:else}
|
||||
<div class="flex-row-top">
|
||||
{#await getEmployee(value, $employeeByIdStore, $employeeAccountByIdStore) then employee}
|
||||
{#await getEmployee(value, $personByIdStore, $personAccountByIdStore) then employee}
|
||||
<div class="avatar">
|
||||
<Avatar size={'medium'} avatar={employee?.avatar} />
|
||||
</div>
|
||||
<div class="flex-grow flex-col select-text">
|
||||
<div class="header">
|
||||
<div class="fs-title">
|
||||
{#if employee}{getName(employee)}{/if}
|
||||
{#if employee}{getName(client.getHierarchy(), employee)}{/if}
|
||||
</div>
|
||||
<div class="content-dark-color ml-4"><TimeSince value={value.modifiedOn} /></div>
|
||||
</div>
|
||||
|
@ -32,7 +32,7 @@
|
||||
let employeeIds: Ref<Employee>[] = []
|
||||
|
||||
async function createDirectMessage () {
|
||||
const employeeAccounts = await client.findAll(contact.class.EmployeeAccount, { employee: { $in: employeeIds } })
|
||||
const employeeAccounts = await client.findAll(contact.class.PersonAccount, { person: { $in: employeeIds } })
|
||||
|
||||
const accIds = [myAccId, ...employeeAccounts.filter((ea) => ea._id !== myAccId).map((ea) => ea._id)].sort()
|
||||
const existingDms = await client.findAll(chunter.class.DirectMessage, {})
|
||||
|
@ -18,7 +18,7 @@
|
||||
import { getCurrentAccount } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { CombineAvatars } from '@hcengineering/contact-resources'
|
||||
import contact, { EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { PersonAccount } from '@hcengineering/contact'
|
||||
import { SearchEdit, showPanel } from '@hcengineering/ui'
|
||||
import chunter from '../plugin'
|
||||
import { getDmName, navigateToSpecial } from '../utils'
|
||||
@ -42,11 +42,11 @@
|
||||
async function getEmpolyeeIds () {
|
||||
const empAccIds = dm?.members.length !== 1 ? dm?.members.filter((accId) => accId !== myAccId) : dm?.members
|
||||
|
||||
const employeeAccounts = await client.findAll(contact.class.EmployeeAccount, {
|
||||
_id: { $in: empAccIds as Ref<EmployeeAccount>[] }
|
||||
const employeeAccounts = await client.findAll(contact.class.PersonAccount, {
|
||||
_id: { $in: empAccIds as Ref<PersonAccount>[] }
|
||||
})
|
||||
|
||||
return employeeAccounts.map((ea) => ea.employee)
|
||||
return employeeAccounts.map((ea) => ea.person)
|
||||
}
|
||||
|
||||
async function onSpaceEdit (): Promise<void> {
|
||||
@ -62,7 +62,7 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="ac-header__wrap-title" on:click={onSpaceEdit}>
|
||||
<div class="ac-header__icon">
|
||||
<CombineAvatars _class={contact.class.Employee} items={empolyeeIds} size={'x-small'} />
|
||||
<CombineAvatars _class={contact.mixin.Employee} items={empolyeeIds} size={'x-small'} />
|
||||
</div>
|
||||
<span class="ac-header__title">{name}</span>
|
||||
</div>
|
||||
|
@ -16,8 +16,8 @@
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import { AttachmentList, AttachmentRefInput } from '@hcengineering/attachment-resources'
|
||||
import type { ChunterMessage, Message, Reaction } from '@hcengineering/chunter'
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Avatar, employeeByIdStore, EmployeePresenter } from '@hcengineering/contact-resources'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { Avatar, personByIdStore, EmployeePresenter } from '@hcengineering/contact-resources'
|
||||
import { getCurrentAccount, Ref, WithLookup } from '@hcengineering/core'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { getClient, MessageViewer } from '@hcengineering/presentation'
|
||||
@ -46,8 +46,8 @@
|
||||
|
||||
let refInput: AttachmentRefInput
|
||||
|
||||
$: empRef = (message.$lookup?.createBy as EmployeeAccount)?.employee
|
||||
$: employee = empRef !== undefined ? $employeeByIdStore.get(empRef) : undefined
|
||||
$: empRef = (message.$lookup?.createBy as PersonAccount)?.person
|
||||
$: employee = empRef !== undefined ? $personByIdStore.get(empRef) : undefined
|
||||
$: attachments = (message.$lookup?.attachments ?? []) as Attachment[]
|
||||
|
||||
const client = getClient()
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import chunter, { ChunterMessage } from '@hcengineering/chunter'
|
||||
import { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import { Avatar, employeeAccountByIdStore, employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import { Avatar, personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
|
||||
import { IdMap, Ref, Space } from '@hcengineering/core'
|
||||
import { MessageViewer, createQuery } from '@hcengineering/presentation'
|
||||
import { MessageViewer, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { IconClose } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { UnpinMessage } from '../index'
|
||||
@ -11,6 +11,8 @@
|
||||
|
||||
export let space: Ref<Space>
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const pinnedQuery = createQuery()
|
||||
let pinnedIds: Ref<ChunterMessage>[] = []
|
||||
pinnedQuery.query(
|
||||
@ -34,27 +36,28 @@
|
||||
|
||||
function getEmployee (
|
||||
message: ChunterMessage,
|
||||
employeeAccounts: IdMap<EmployeeAccount>,
|
||||
employees: IdMap<Employee>
|
||||
): Employee | undefined {
|
||||
const acc = employeeAccounts.get(message.createBy as Ref<EmployeeAccount>)
|
||||
employeeAccounts: IdMap<PersonAccount>,
|
||||
employees: IdMap<Person>
|
||||
): Person | undefined {
|
||||
const acc = employeeAccounts.get(message.createBy as Ref<PersonAccount>)
|
||||
if (acc) {
|
||||
return employees.get(acc.employee)
|
||||
return employees.get(acc.person)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="antiPopup vScroll popup">
|
||||
{#each pinnedMessages as message}
|
||||
{@const employee = getEmployee(message, $employeeAccountByIdStore, $employeeByIdStore)}
|
||||
{@const employee = getEmployee(message, $personAccountByIdStore, $personByIdStore)}
|
||||
<div class="message">
|
||||
<div class="header">
|
||||
<div class="avatar">
|
||||
<Avatar size={'medium'} avatar={employee?.avatar} />
|
||||
</div>
|
||||
<span class="name">
|
||||
{employee ? getName(employee) : ''}
|
||||
{employee ? getName(client.getHierarchy(), employee) : ''}
|
||||
</span>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="cross"
|
||||
on:click={async () => {
|
||||
|
@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import { employeeAccountByIdStore, employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Account, IdMap, Ref } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let reactionAccounts: Ref<Account>[]
|
||||
|
||||
function getAccName (acc: Ref<Account>, accounts: IdMap<EmployeeAccount>, employees: IdMap<Employee>): string {
|
||||
const account = accounts.get(acc as Ref<EmployeeAccount>)
|
||||
const client = getClient()
|
||||
function getAccName (acc: Ref<Account>, accounts: IdMap<PersonAccount>, employees: IdMap<Person>): string {
|
||||
const account = accounts.get(acc as Ref<PersonAccount>)
|
||||
if (account !== undefined) {
|
||||
const emp = employees.get(account.employee)
|
||||
return emp ? getName(emp) : ''
|
||||
const emp = employees.get(account.person)
|
||||
return emp ? getName(client.getHierarchy(), emp) : ''
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@ -17,6 +19,6 @@
|
||||
|
||||
{#each reactionAccounts as acc}
|
||||
<div>
|
||||
{getAccName(acc, $employeeAccountByIdStore, $employeeByIdStore)}
|
||||
{getAccName(acc, $personAccountByIdStore, $personByIdStore)}
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -14,8 +14,8 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Message } from '@hcengineering/chunter'
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import { personByIdStore } from '@hcengineering/contact-resources'
|
||||
import { IdMap, Ref } from '@hcengineering/core'
|
||||
import { Avatar } from '@hcengineering/contact-resources'
|
||||
import { Label, TimeSince } from '@hcengineering/ui'
|
||||
@ -26,11 +26,11 @@
|
||||
$: employees = new Set(message.replies)
|
||||
|
||||
const shown: number = 4
|
||||
let showReplies: Employee[] = []
|
||||
let showReplies: Person[] = []
|
||||
|
||||
$: updateQuery(employees, $employeeByIdStore)
|
||||
$: updateQuery(employees, $personByIdStore)
|
||||
|
||||
function updateQuery (employees: Set<Ref<Employee>>, map: IdMap<Employee>) {
|
||||
function updateQuery (employees: Set<Ref<Person>>, map: IdMap<Person>) {
|
||||
showReplies = []
|
||||
for (const employee of employees) {
|
||||
const emp = map.get(employee)
|
||||
|
@ -2,8 +2,8 @@
|
||||
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||
import { AttachmentPreview } from '@hcengineering/attachment-resources'
|
||||
import { ChunterMessage } from '@hcengineering/chunter'
|
||||
import { EmployeeAccount, getName as getContactName } from '@hcengineering/contact'
|
||||
import { employeeAccountByIdStore, employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Person, PersonAccount, getName as getContactName } from '@hcengineering/contact'
|
||||
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
|
||||
import core, { IdMap, Ref, WithLookup } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Label, Scroller } from '@hcengineering/ui'
|
||||
@ -74,12 +74,16 @@
|
||||
})
|
||||
}
|
||||
|
||||
function getName (a: Attachment, employeeAccountByIdStore: IdMap<EmployeeAccount>): string | undefined {
|
||||
const acc = employeeAccountByIdStore.get(a.modifiedBy as Ref<EmployeeAccount>)
|
||||
function getName (
|
||||
a: Attachment,
|
||||
personAccountByIdStore: IdMap<PersonAccount>,
|
||||
personByIdStore: IdMap<Person>
|
||||
): string | undefined {
|
||||
const acc = personAccountByIdStore.get(a.modifiedBy as Ref<PersonAccount>)
|
||||
if (acc !== undefined) {
|
||||
const emp = $employeeByIdStore.get(acc?.employee)
|
||||
const emp = personByIdStore.get(acc?.person)
|
||||
if (emp !== undefined) {
|
||||
return getContactName(emp)
|
||||
return getContactName(client.getHierarchy(), emp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,7 +116,7 @@
|
||||
<div class="label">
|
||||
<Label
|
||||
label={chunter.string.SharedBy}
|
||||
params={{ name: getName(att, $employeeAccountByIdStore), time: getTime(att.modifiedOn) }}
|
||||
params={{ name: getName(att, $personAccountByIdStore, $personByIdStore), time: getTime(att.modifiedOn) }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,8 +16,8 @@
|
||||
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||
import { AttachmentRefInput } from '@hcengineering/attachment-resources'
|
||||
import type { ChunterSpace, Message, ThreadMessage } from '@hcengineering/chunter'
|
||||
import contact, { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import { employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import contact, { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import { personByIdStore } from '@hcengineering/contact-resources'
|
||||
import core, { FindOptions, IdMap, Ref, SortingOrder, generateId, getCurrentAccount } from '@hcengineering/core'
|
||||
import { NotificationClientImpl } from '@hcengineering/notification-resources'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
@ -98,21 +98,21 @@
|
||||
async function getParticipants (
|
||||
comments: ThreadMessage[],
|
||||
parent: Message | undefined,
|
||||
employees: IdMap<Employee>
|
||||
employees: IdMap<Person>
|
||||
): Promise<string[]> {
|
||||
const refs = new Set(comments.map((p) => p.createBy))
|
||||
if (parent !== undefined) {
|
||||
refs.add(parent.createBy)
|
||||
}
|
||||
refs.delete(getCurrentAccount()._id)
|
||||
const accounts = await client.findAll(contact.class.EmployeeAccount, {
|
||||
_id: { $in: Array.from(refs) as Ref<EmployeeAccount>[] }
|
||||
const accounts = await client.findAll(contact.class.PersonAccount, {
|
||||
_id: { $in: Array.from(refs) as Ref<PersonAccount>[] }
|
||||
})
|
||||
const res: string[] = []
|
||||
for (const account of accounts) {
|
||||
const employee = employees.get(account.employee)
|
||||
const employee = employees.get(account.person)
|
||||
if (employee !== undefined) {
|
||||
res.push(getName(employee))
|
||||
res.push(getName(client.getHierarchy(), employee))
|
||||
}
|
||||
}
|
||||
return res
|
||||
@ -159,7 +159,7 @@
|
||||
<DmPresenter value={channel} />
|
||||
{/if}
|
||||
{/await}
|
||||
{#await getParticipants(comments, parent, $employeeByIdStore) then participants}
|
||||
{#await getParticipants(comments, parent, $personByIdStore) then participants}
|
||||
{participants.join(', ')}
|
||||
<Label label={chunter.string.AndYou} params={{ participants: participants.length }} />
|
||||
{/await}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { chunterId, ChunterMessage, Comment, ThreadMessage } from '@hcengineering/chunter'
|
||||
import contact, { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import contact, { Employee, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import { employeeByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Class, Client, Doc, getCurrentAccount, IdMap, Obj, Ref, Space, Timestamp } from '@hcengineering/core'
|
||||
import { Asset } from '@hcengineering/platform'
|
||||
@ -48,8 +48,8 @@ export function classIcon (client: Client, _class: Ref<Class<Obj>>): Asset | und
|
||||
export async function getDmName (client: Client, dm: Space): Promise<string> {
|
||||
const myAccId = getCurrentAccount()._id
|
||||
|
||||
let employeeAccounts: EmployeeAccount[] = await client.findAll(contact.class.EmployeeAccount, {
|
||||
_id: { $in: dm.members as Array<Ref<EmployeeAccount>> }
|
||||
let employeeAccounts: PersonAccount[] = await client.findAll(contact.class.PersonAccount, {
|
||||
_id: { $in: dm.members as Array<Ref<PersonAccount>> }
|
||||
})
|
||||
|
||||
if (dm.members.length > 1) {
|
||||
@ -72,9 +72,9 @@ export async function getDmName (client: Client, dm: Space): Promise<string> {
|
||||
const names: string[] = []
|
||||
|
||||
for (const acc of employeeAccounts) {
|
||||
const employee = map.get(acc.employee)
|
||||
const employee = map.get(acc.person as unknown as Ref<Employee>)
|
||||
if (employee !== undefined) {
|
||||
names.push(getName(employee))
|
||||
names.push(getName(client.getHierarchy(), employee))
|
||||
}
|
||||
}
|
||||
const name = names.join(', ')
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Employee } from '@hcengineering/contact'
|
||||
import type { Person } from '@hcengineering/contact'
|
||||
import type { Account, AttachedDoc, Class, Doc, Ref, RelatedDocument, Space, Timestamp } from '@hcengineering/core'
|
||||
import { NotificationType } from '@hcengineering/notification'
|
||||
import type { Asset, Plugin, Resource } from '@hcengineering/platform'
|
||||
@ -66,7 +66,7 @@ export interface ThreadMessage extends ChunterMessage {
|
||||
export interface Message extends ChunterMessage {
|
||||
attachedTo: Ref<Space>
|
||||
attachedToClass: Ref<Class<Space>>
|
||||
replies?: Ref<Employee>[]
|
||||
replies?: Ref<Person>[]
|
||||
repliesCount?: number
|
||||
lastReply?: Timestamp
|
||||
}
|
||||
|
@ -67,6 +67,7 @@
|
||||
"Email": "Email",
|
||||
"CreateEmployee": "Employee",
|
||||
"Inactive": "Inactive",
|
||||
"Active": "Active",
|
||||
"Birthday": "Birthday",
|
||||
"UseImage": "Attached photo",
|
||||
"UseGravatar": "Gravatar",
|
||||
@ -79,9 +80,9 @@
|
||||
"Profile": "Profile",
|
||||
"ProfilePlaceholder": "Profile...",
|
||||
"CurrentEmployee": "Current employee",
|
||||
"MergeEmployee": "Merge employee",
|
||||
"MergeEmployeeFrom": "From(inactive)",
|
||||
"MergeEmployeeTo": "To employee",
|
||||
"MergePersons": "Merge contacts",
|
||||
"MergePersonsFrom": "Source contact",
|
||||
"MergePersonsTo": "Final contact",
|
||||
"DisplayName": "Display name",
|
||||
"SelectAvatar": "Select avatar",
|
||||
"AvatarProvider": "Avatar provider",
|
||||
|
@ -67,6 +67,7 @@
|
||||
"Email": "Email",
|
||||
"CreateEmployee": "Сотрудник",
|
||||
"Inactive": "Не активный",
|
||||
"Active": "Активный",
|
||||
"Birthday": "День рождения",
|
||||
"UseImage": "Загруженное Фото",
|
||||
"UseGravatar": "Граватар",
|
||||
@ -80,9 +81,9 @@
|
||||
"Profile": "Профиль",
|
||||
"ProfilePlaceholder": "Профиль...",
|
||||
"CurrentEmployee": "Текущий сотрудник",
|
||||
"MergeEmployee": "Объединить сотрудника",
|
||||
"MergeEmployeeFrom": "Из (неактивный)",
|
||||
"MergeEmployeeTo": "В сотрудника",
|
||||
"MergePersons": "Объеденить контакта",
|
||||
"MergePersonsFrom": "Исходный контакт",
|
||||
"MergePersonsTo": "Финальный контакт",
|
||||
"DisplayName": "Отображаемое имя",
|
||||
"SelectAvatar": "Выбрать аватар",
|
||||
"GravatarsManaged": "Граватары управляются",
|
||||
|
@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import core, { Account, Ref } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
import { employeeAccountByIdStore } from '../utils'
|
||||
import { personAccountByIdStore } from '../utils'
|
||||
import UserBoxList from './UserBoxList.svelte'
|
||||
|
||||
export let label: IntlString
|
||||
@ -36,7 +36,7 @@
|
||||
function onUpdate (evt: CustomEvent<Ref<Employee>[]>): void {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(async () => {
|
||||
const accounts = await client.findAll(contact.class.EmployeeAccount, { employee: { $in: evt.detail } })
|
||||
const accounts = await client.findAll(contact.class.PersonAccount, { person: { $in: evt.detail } })
|
||||
onChange(accounts.map((it) => it._id))
|
||||
}, 500)
|
||||
}
|
||||
@ -55,14 +55,14 @@
|
||||
}
|
||||
|
||||
$: employees = Array.from(
|
||||
(value ?? []).map((it) => $employeeAccountByIdStore.get(it as Ref<EmployeeAccount>)?.employee)
|
||||
(value ?? []).map((it) => $personAccountByIdStore.get(it as Ref<PersonAccount>)?.person)
|
||||
).filter((it) => it !== undefined) as Ref<Employee>[]
|
||||
|
||||
$: docQuery =
|
||||
excluded.length > 0
|
||||
? {
|
||||
active: true,
|
||||
_id: { $nin: excluded.map((p) => (p as EmployeeAccount).employee) }
|
||||
_id: { $nin: excluded.map((p) => (p as PersonAccount).person as Ref<Employee>) }
|
||||
}
|
||||
: {
|
||||
active: true
|
||||
|
@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Person, PersonAccount } from '@hcengineering/contact'
|
||||
import core, { Account, DocumentQuery, Ref, matchQuery } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import contact from '../plugin'
|
||||
import { employeeAccountByIdStore } from '../utils'
|
||||
import { personAccountByIdStore } from '../utils'
|
||||
import UserBox from './UserBox.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
@ -33,21 +33,21 @@
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
$: accounts = matchQuery<Account>(
|
||||
Array.from($employeeAccountByIdStore.values()),
|
||||
Array.from($personAccountByIdStore.values()),
|
||||
docQuery,
|
||||
core.class.Account,
|
||||
hierarchy
|
||||
) as EmployeeAccount[]
|
||||
) as PersonAccount[]
|
||||
|
||||
let map: Map<Ref<Employee>, Ref<Account>> = new Map()
|
||||
$: map = new Map(accounts.map((p) => [p.employee, p._id]))
|
||||
let map: Map<Ref<Person>, Ref<Account>> = new Map()
|
||||
$: map = new Map(accounts.map((p) => [p.person, p._id]))
|
||||
|
||||
$: employees = accounts.map((p) => p.employee)
|
||||
$: selectedEmp = value && accounts.find((p) => p._id === value)?.employee
|
||||
$: employees = accounts.map((p) => p.person)
|
||||
$: selectedEmp = value && accounts.find((p) => p._id === value)?.person
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function change (e: CustomEvent<Ref<Employee> | null>) {
|
||||
function change (e: CustomEvent<Ref<Person> | null>) {
|
||||
if (e.detail === null) {
|
||||
dispatch('change', null)
|
||||
} else {
|
||||
@ -58,7 +58,7 @@
|
||||
</script>
|
||||
|
||||
<UserBox
|
||||
_class={contact.class.Employee}
|
||||
_class={contact.mixin.Employee}
|
||||
docQuery={{ _id: { $in: employees } }}
|
||||
showNavigate={false}
|
||||
{kind}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
|
||||
import { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import core, { IdMap, Ref, Space } from '@hcengineering/core'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { ActionIcon, Button, IconClose, Label } from '@hcengineering/ui'
|
||||
@ -11,19 +11,17 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
const employees: IdMap<Employee> = new Map()
|
||||
const employees: IdMap<Person> = new Map()
|
||||
|
||||
let membersToAdd: EmployeeAccount[] = []
|
||||
let channelMembers: Ref<Employee>[] = []
|
||||
let membersToAdd: PersonAccount[] = []
|
||||
let channelMembers: Ref<Person>[] = []
|
||||
client.findAll(core.class.Account, { _id: { $in: value.members } }).then((res) => {
|
||||
channelMembers = res
|
||||
.filter((e) => e._class === contact.class.EmployeeAccount)
|
||||
.map((e) => (e as EmployeeAccount).employee)
|
||||
channelMembers = res.filter((e) => e._class === contact.class.PersonAccount).map((e) => (e as PersonAccount).person)
|
||||
})
|
||||
|
||||
async function changeMembersToAdd (employees: Ref<Employee>[]) {
|
||||
async function changeMembersToAdd (employees: Ref<Person>[]) {
|
||||
if (employees) {
|
||||
await client.findAll(contact.class.EmployeeAccount, { employee: { $in: employees } }).then((res) => {
|
||||
await client.findAll(contact.class.PersonAccount, { person: { $in: employees } }).then((res) => {
|
||||
if (res) {
|
||||
membersToAdd = res
|
||||
}
|
||||
@ -31,9 +29,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: selectedEmployees = membersToAdd.map((e) => e.employee)
|
||||
$: selectedEmployees = membersToAdd.map((e) => e.person)
|
||||
|
||||
function removeMember (_id: Ref<EmployeeAccount>) {
|
||||
function removeMember (_id: Ref<PersonAccount>) {
|
||||
membersToAdd = membersToAdd.filter((m) => m._id !== _id)
|
||||
}
|
||||
</script>
|
||||
@ -56,9 +54,9 @@
|
||||
{#if membersToAdd.length}
|
||||
<div class="flex-row-top flex-wrap ml-6 mr-6 mt-4">
|
||||
{#each membersToAdd as m}
|
||||
{@const employee = employees.get(m.employee)}
|
||||
{@const employee = employees.get(m.person)}
|
||||
<div class="mr-2 p-1 item">
|
||||
{employee ? getName(employee) : ''}
|
||||
{employee ? getName(client.getHierarchy(), employee) : ''}
|
||||
<div class="tool">
|
||||
<ActionIcon
|
||||
icon={IconClose}
|
||||
@ -75,7 +73,7 @@
|
||||
<div class="ml-8 mr-8 mb-6 mt-4">
|
||||
<UsersPopup
|
||||
selected={undefined}
|
||||
_class={contact.class.Employee}
|
||||
_class={contact.mixin.Employee}
|
||||
docQuery={{
|
||||
active: true
|
||||
}}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Contact, Employee, getName } from '@hcengineering/contact'
|
||||
import contact, { Contact, Employee, Person, getName } from '@hcengineering/contact'
|
||||
import { Class, DocumentQuery, FindOptions, Hierarchy, Ref } from '@hcengineering/core'
|
||||
import { getEmbeddedLabel, IntlString } from '@hcengineering/platform'
|
||||
import {
|
||||
@ -34,13 +34,13 @@
|
||||
import view from '@hcengineering/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { PersonLabelTooltip, employeeByIdStore } from '..'
|
||||
import { PersonLabelTooltip, personByIdStore } from '..'
|
||||
import AssigneePopup from './AssigneePopup.svelte'
|
||||
import IconPerson from './icons/Person.svelte'
|
||||
import UserInfo from './UserInfo.svelte'
|
||||
import EmployeePresenter from './EmployeePresenter.svelte'
|
||||
|
||||
export let _class: Ref<Class<Employee>> = contact.class.Employee
|
||||
export let _class: Ref<Class<Employee>> = contact.mixin.Employee
|
||||
export let excluded: Ref<Contact>[] | undefined = undefined
|
||||
export let options: FindOptions<Employee> | undefined = undefined
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {
|
||||
@ -48,8 +48,8 @@
|
||||
}
|
||||
export let label: IntlString
|
||||
export let placeholder: IntlString = presentation.string.Search
|
||||
export let value: Ref<Employee> | null | undefined
|
||||
export let prevAssigned: Ref<Employee>[] | undefined = []
|
||||
export let value: Ref<Person> | null | undefined
|
||||
export let prevAssigned: Ref<Person>[] | undefined = []
|
||||
export let componentLead: Ref<Employee> | undefined = undefined
|
||||
export let members: Ref<Employee>[] | undefined = []
|
||||
export let allowDeselect = true
|
||||
@ -71,13 +71,15 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let selected: Employee | undefined
|
||||
let selected: Person | undefined
|
||||
let container: HTMLElement
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function updateSelected (value: Ref<Employee> | null | undefined) {
|
||||
selected = value ? $employeeByIdStore.get(value) ?? (await client.findOne(_class, { _id: value })) : undefined
|
||||
async function updateSelected (value: Ref<Person> | null | undefined) {
|
||||
selected = value
|
||||
? $personByIdStore.get(value) ?? (await client.findOne(contact.class.Person, { _id: value }))
|
||||
: undefined
|
||||
}
|
||||
|
||||
$: updateSelected(value)
|
||||
@ -132,7 +134,9 @@
|
||||
<div
|
||||
class="w-full h-full flex-streatch"
|
||||
on:click={_click}
|
||||
use:tooltip={selected !== undefined ? { label: getEmbeddedLabel(getName(selected)) } : undefined}
|
||||
use:tooltip={selected !== undefined
|
||||
? { label: getEmbeddedLabel(getName(client.getHierarchy(), selected)) }
|
||||
: undefined}
|
||||
>
|
||||
<slot name="content" />
|
||||
</div>
|
||||
@ -158,13 +162,15 @@
|
||||
style:width={showNavigate && selected
|
||||
? `calc(${width ?? 'min-content'} - 1.5rem)`
|
||||
: `${width ?? 'min-content'}`}
|
||||
use:tooltip={selected !== undefined ? { label: getEmbeddedLabel(getName(selected)) } : undefined}
|
||||
use:tooltip={selected !== undefined
|
||||
? { label: getEmbeddedLabel(getName(client.getHierarchy(), selected)) }
|
||||
: undefined}
|
||||
>
|
||||
{#if selected}
|
||||
{#if hideIcon || selected}
|
||||
<UserInfo value={selected} size={avatarSize} {icon} {short} on:accent-color />
|
||||
{:else}
|
||||
{getName(selected)}
|
||||
{getName(client.getHierarchy(), selected)}
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex-presenter not-selected">
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Contact, Employee, EmployeeAccount, Person } from '@hcengineering/contact'
|
||||
import contact, { Contact, PersonAccount, Person, Employee } from '@hcengineering/contact'
|
||||
import { DocumentQuery, FindOptions, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import type { Asset, IntlString } from '@hcengineering/platform'
|
||||
import {
|
||||
@ -52,9 +52,7 @@
|
||||
export let showCategories: boolean = true
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
|
||||
// const client = getClient()
|
||||
// const hierarchy = client.getHierarchy()
|
||||
const currentEmployee = (getCurrentAccount() as EmployeeAccount).employee
|
||||
const currentEmployee = (getCurrentAccount() as PersonAccount).person
|
||||
|
||||
let search: string = ''
|
||||
let objects: Contact[] = []
|
||||
@ -66,7 +64,7 @@
|
||||
const query = createQuery()
|
||||
|
||||
$: query.query<Contact>(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{
|
||||
...(docQuery ?? {}),
|
||||
[searchField]: { $like: '%' + search + '%' },
|
||||
|
@ -28,9 +28,7 @@
|
||||
export let items: Ref<Contact>[] = []
|
||||
export let _class: Ref<Class<Contact>> = contact.class.Contact
|
||||
export let label: IntlString
|
||||
export let docQuery: DocumentQuery<Contact> | undefined = {
|
||||
active: true
|
||||
}
|
||||
export let docQuery: DocumentQuery<Contact> | undefined = {}
|
||||
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
export let size: ButtonSize = 'small'
|
||||
|
@ -38,7 +38,7 @@
|
||||
function isEmployee (value: Contact): boolean {
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
return hierarchy.isDerived(value._class, contact.class.Employee)
|
||||
return hierarchy.isDerived(value._class, contact.mixin.Employee)
|
||||
}
|
||||
const toOrg = (contact: Contact) => contact as Organization
|
||||
const toEmployee = (contact: Contact) => contact as Employee
|
||||
|
@ -48,20 +48,22 @@
|
||||
async function createPerson () {
|
||||
changeEmail()
|
||||
const name = combineName(firstName, lastName)
|
||||
const person: Data<Employee> = {
|
||||
const person: Data<Person> = {
|
||||
name,
|
||||
city: object.city,
|
||||
active: true
|
||||
city: object.city
|
||||
}
|
||||
|
||||
person.avatar = await avatarEditor.createAvatar()
|
||||
|
||||
await client.createDoc(contact.class.Employee, contact.space.Contacts, person, id)
|
||||
await client.createDoc(contact.class.Person, contact.space.Contacts, person, id)
|
||||
await client.createMixin(id, contact.class.Person, contact.space.Contacts, contact.mixin.Employee, {
|
||||
active: true
|
||||
})
|
||||
|
||||
await client.createDoc(contact.class.EmployeeAccount, core.space.Model, {
|
||||
await client.createDoc(contact.class.PersonAccount, core.space.Model, {
|
||||
email: email.trim(),
|
||||
name,
|
||||
employee: id,
|
||||
person: id,
|
||||
role: AccountRole.User
|
||||
})
|
||||
|
||||
|
@ -17,22 +17,22 @@
|
||||
import { AccountRole, Doc, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { employeeAccountByIdStore } from '../utils'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { personAccountByIdStore } from '../utils'
|
||||
import ui, { Button, Label } from '@hcengineering/ui'
|
||||
import EmployeeAccountRefPresenter from './EmployeeAccountRefPresenter.svelte'
|
||||
import EmployeeAccountPresenter from './EmployeeAccountPresenter.svelte'
|
||||
import PersonAccountRefPresenter from './PersonAccountRefPresenter.svelte'
|
||||
import PersonAccountPresenter from './PersonAccountPresenter.svelte'
|
||||
|
||||
export let object: Doc | Doc[]
|
||||
export let deleteAction: () => void
|
||||
const objectArray = Array.isArray(object) ? object : [object]
|
||||
const owners: EmployeeAccount[] = Array.from($employeeAccountByIdStore.values()).filter(
|
||||
const owners: PersonAccount[] = Array.from($personAccountByIdStore.values()).filter(
|
||||
(acc) => acc.role === AccountRole.Owner
|
||||
)
|
||||
const dispatch = createEventDispatcher()
|
||||
$: creators = [...new Set(objectArray.map((obj) => obj.createdBy as Ref<EmployeeAccount>))]
|
||||
$: creators = [...new Set(objectArray.map((obj) => obj.createdBy as Ref<PersonAccount>))]
|
||||
$: canDelete =
|
||||
(creators.length === 1 && creators.includes(getCurrentAccount()._id as Ref<EmployeeAccount>)) ||
|
||||
(creators.length === 1 && creators.includes(getCurrentAccount()._id as Ref<PersonAccount>)) ||
|
||||
getCurrentAccount().role === AccountRole.Owner
|
||||
$: label = canDelete ? view.string.DeleteObject : view.string.DeletePopupNoPermissionTitle
|
||||
</script>
|
||||
@ -62,7 +62,7 @@
|
||||
<Label label={view.string.DeletePopupCreatorLabel} />
|
||||
{#each creators as account}
|
||||
<div class="my-2">
|
||||
<EmployeeAccountRefPresenter value={account} />
|
||||
<PersonAccountRefPresenter value={account} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@ -70,7 +70,7 @@
|
||||
<Label label={view.string.DeletePopupOwnerLabel} />
|
||||
{#each owners as owner}
|
||||
<div class="my-2">
|
||||
<EmployeeAccountPresenter value={owner} />
|
||||
<PersonAccountPresenter value={owner} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Channel, Employee, EmployeeAccount, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import { Channel, Employee, PersonAccount, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import { AccountRole, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import login from '@hcengineering/login'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
@ -28,28 +28,27 @@
|
||||
import ChannelsEditor from './ChannelsEditor.svelte'
|
||||
import EditableAvatar from './EditableAvatar.svelte'
|
||||
|
||||
export let object: Employee
|
||||
export let object: Person
|
||||
export let readonly = false
|
||||
|
||||
export let channels: Channel[] | undefined = undefined
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const account = getCurrentAccount() as EmployeeAccount
|
||||
const account = getCurrentAccount() as PersonAccount
|
||||
|
||||
let avatarEditor: EditableAvatar
|
||||
|
||||
$: owner = account.employee === object._id
|
||||
$: owner = account.person === object._id
|
||||
$: editable = !readonly && (account.role >= AccountRole.Maintainer || owner)
|
||||
let firstName = getFirstName(object.name)
|
||||
let lastName = getLastName(object.name)
|
||||
let displayName = object.displayName ?? ''
|
||||
|
||||
$: setName(object)
|
||||
|
||||
let email: string | undefined
|
||||
$: if (editable) {
|
||||
client.findOne(contact.class.EmployeeAccount, { employee: (object as Employee)._id }).then((acc) => {
|
||||
client.findOne(contact.class.PersonAccount, { person: (object as Employee)._id }).then((acc) => {
|
||||
email = acc?.email
|
||||
})
|
||||
}
|
||||
@ -71,12 +70,6 @@
|
||||
await changeName(getFirstName(object.name), lastName)
|
||||
}
|
||||
|
||||
function changeDisplayName () {
|
||||
client.update(object, {
|
||||
displayName: displayName.trim() === '' ? null : displayName
|
||||
})
|
||||
}
|
||||
|
||||
let integrations: Set<Ref<IntegrationType>> = new Set<Ref<IntegrationType>>()
|
||||
const settingsQuery = createQuery()
|
||||
$: settingsQuery.query(setting.class.Integration, { createdBy: account._id, disabled: false }, (res) => {
|
||||
@ -146,19 +139,6 @@
|
||||
{lastName}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="name">
|
||||
{#if editable}
|
||||
<EditBox
|
||||
placeholder={contact.string.DisplayName}
|
||||
bind:value={displayName}
|
||||
on:change={changeDisplayName}
|
||||
disabled={!editable}
|
||||
focusIndex={1}
|
||||
/>
|
||||
{:else}
|
||||
{displayName}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="location">
|
||||
<AttributeEditor maxWidth="20rem" _class={contact.class.Person} {editable} {object} key="city" focusIndex={3} />
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { combineName, EmployeeAccount, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import { combineName, PersonAccount, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import { getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import { AttributeEditor, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import setting, { IntegrationType } from '@hcengineering/setting'
|
||||
@ -27,7 +27,7 @@
|
||||
export let object: Person
|
||||
const client = getClient()
|
||||
|
||||
const account = getCurrentAccount() as EmployeeAccount
|
||||
const account = getCurrentAccount() as PersonAccount
|
||||
|
||||
let avatarEditor: EditableAvatar
|
||||
|
||||
|
@ -14,22 +14,22 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee } from '@hcengineering/contact'
|
||||
import contact, { Employee, Person } from '@hcengineering/contact'
|
||||
import type { Class, DocumentQuery, FindOptions, Ref } from '@hcengineering/core'
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import { ButtonKind, ButtonSize, IconSize, LabelAndProps } from '@hcengineering/ui'
|
||||
import presentation from '@hcengineering/presentation'
|
||||
import IconPerson from './icons/Person.svelte'
|
||||
import { ButtonKind, ButtonSize, IconSize, LabelAndProps } from '@hcengineering/ui'
|
||||
import UserBox from './UserBox.svelte'
|
||||
import IconPerson from './icons/Person.svelte'
|
||||
|
||||
export let _class: Ref<Class<Employee>> = contact.class.Employee
|
||||
export let _class: Ref<Class<Employee>> = contact.mixin.Employee
|
||||
export let options: FindOptions<Employee> | undefined = undefined
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {
|
||||
active: true
|
||||
}
|
||||
export let label: IntlString
|
||||
export let placeholder: IntlString = presentation.string.Search
|
||||
export let value: Ref<Employee> | null | undefined
|
||||
export let value: Ref<Person> | null | undefined
|
||||
export let allowDeselect = false
|
||||
export let titleDeselect: IntlString | undefined = undefined
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
async function updateEmployees (resultQuery: DocumentQuery<Employee>) {
|
||||
employees = await client.findAll(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{
|
||||
...resultQuery
|
||||
},
|
||||
|
@ -31,7 +31,7 @@
|
||||
export let readonly = false
|
||||
export let showNavigate = true
|
||||
|
||||
$: _class = type?.to ?? contact.class.Employee
|
||||
$: _class = type?.to ?? contact.mixin.Employee
|
||||
|
||||
const query: DocumentQuery<Employee> = {
|
||||
active: true
|
||||
|
@ -78,7 +78,7 @@
|
||||
: {
|
||||
_id: { $in: Array.from(targets.keys()) }
|
||||
}
|
||||
objectsPromise = client.findAll(contact.class.Employee, resultQuery, { sort: { name: SortingOrder.Ascending } })
|
||||
objectsPromise = client.findAll(contact.mixin.Employee, resultQuery, { sort: { name: SortingOrder.Ascending } })
|
||||
values = await objectsPromise
|
||||
if (targets.has(undefined)) {
|
||||
values.unshift(undefined)
|
||||
|
@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import CombineAvatars from './CombineAvatars.svelte'
|
||||
import contact from '../plugin'
|
||||
|
||||
export let value: Ref<Employee>[]
|
||||
export let value: Ref<Person>[]
|
||||
</script>
|
||||
|
||||
<CombineAvatars _class={contact.class.Employee} items={value} limit={5} size={'x-small'} />
|
||||
<CombineAvatars _class={contact.mixin.Employee} items={value} limit={5} size={'x-small'} />
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Employee, Person } from '@hcengineering/contact'
|
||||
import { Ref, WithLookup } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import ui, { IconSize } from '@hcengineering/ui'
|
||||
import { PersonLabelTooltip, employeeByIdStore } from '..'
|
||||
import { PersonLabelTooltip, employeeByIdStore, personByIdStore } from '..'
|
||||
import PersonPresenter from '../components/PersonPresenter.svelte'
|
||||
import contact from '../plugin'
|
||||
|
||||
export let value: Ref<Employee> | WithLookup<Employee> | null | undefined
|
||||
export let value: Ref<Person> | WithLookup<Person> | null | undefined
|
||||
export let tooltipLabels: PersonLabelTooltip | undefined = undefined
|
||||
export let shouldShowAvatar: boolean = true
|
||||
export let shouldShowName: boolean = true
|
||||
@ -21,7 +21,10 @@
|
||||
export let defaultName: IntlString | undefined = ui.string.NotSelected
|
||||
export let element: HTMLElement | undefined = undefined
|
||||
|
||||
$: employeeValue = typeof value === 'string' ? $employeeByIdStore.get(value) : value
|
||||
$: employeeValue = typeof value === 'string' ? $personByIdStore.get(value) : value
|
||||
|
||||
$: active =
|
||||
employeeValue !== undefined ? $employeeByIdStore.get(employeeValue?._id as Ref<Employee>)?.active ?? false : false
|
||||
</script>
|
||||
|
||||
<PersonPresenter
|
||||
@ -38,6 +41,6 @@
|
||||
{colorInherit}
|
||||
{accent}
|
||||
{defaultName}
|
||||
statusLabel={employeeValue?.active === false && shouldShowName ? contact.string.Inactive : undefined}
|
||||
statusLabel={active === false && shouldShowName ? contact.string.Inactive : undefined}
|
||||
on:accent-color
|
||||
/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Employee, EmployeeAccount, getName, Status } from '@hcengineering/contact'
|
||||
import { Employee, PersonAccount, getName, Status } from '@hcengineering/contact'
|
||||
import { getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import Avatar from './Avatar.svelte'
|
||||
@ -15,12 +15,12 @@
|
||||
export let employeeId: Ref<Employee>
|
||||
|
||||
const client = getClient()
|
||||
const me = (getCurrentAccount() as EmployeeAccount).employee
|
||||
const me = (getCurrentAccount() as PersonAccount).person
|
||||
$: editable = employeeId === me
|
||||
|
||||
const statusesQuery = createQuery()
|
||||
let status: Status | undefined = undefined
|
||||
$: employee = $employeeByIdStore.get(employeeId)
|
||||
$: employee = $employeeByIdStore.get(employeeId) as Employee
|
||||
statusesQuery.query(contact.class.Status, { attachedTo: employeeId }, (res) => (status = res[0]))
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -39,7 +39,7 @@
|
||||
} else if (status && !newStatus) {
|
||||
client.removeDoc(contact.class.Status, status.space, status._id)
|
||||
} else {
|
||||
client.addCollection(contact.class.Status, employee!.space, employeeId, contact.class.Employee, 'statuses', {
|
||||
client.addCollection(contact.class.Status, employee!.space, employeeId, contact.mixin.Employee, 'statuses', {
|
||||
name: newStatus.name,
|
||||
dueDate: newStatus.dueDate
|
||||
})
|
||||
@ -60,7 +60,7 @@
|
||||
<div class="flex-col-center pb-2">
|
||||
<Avatar size="x-large" avatar={employee.avatar} />
|
||||
</div>
|
||||
<div class="pb-2">{getName(employee)}</div>
|
||||
<div class="pb-2">{getName(client.getHierarchy(), employee)}</div>
|
||||
<DocNavLink object={employee}>
|
||||
<Label label={contact.string.ViewFullProfile} />
|
||||
</DocNavLink>
|
||||
|
@ -61,7 +61,7 @@
|
||||
showPopup(
|
||||
UsersPopup,
|
||||
{
|
||||
_class: contact.class.Employee,
|
||||
_class: contact.mixin.Employee,
|
||||
selectedUsers: members,
|
||||
allowDeselect: true,
|
||||
multiSelect: true,
|
||||
|
@ -13,14 +13,14 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||
import { getAttribute, getAttributeEditor, getClient } from '@hcengineering/presentation'
|
||||
import MergeComparer from './MergeComparer.svelte'
|
||||
|
||||
export let value: Employee
|
||||
export let value: Person
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let targetEmp: Employee
|
||||
export let targetEmp: Person
|
||||
export let key: string
|
||||
export let onChange: (key: string, value: boolean) => void
|
||||
export let selected = false
|
||||
|
@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import { Doc, Mixin, Ref } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { CheckBox, Label } from '@hcengineering/ui'
|
||||
|
||||
export let value: Employee
|
||||
export let targetEmp: Employee
|
||||
export let value: Person
|
||||
export let targetEmp: Person
|
||||
export let cast: Ref<Mixin<Doc>> | undefined = undefined
|
||||
export let key: string
|
||||
export let selected = false
|
||||
@ -28,7 +28,7 @@
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
function isEqual (value: Employee, targetEmp: Employee, key: string) {
|
||||
function isEqual (value: Person, targetEmp: Person, key: string) {
|
||||
if (cast !== undefined) {
|
||||
value = hierarchy.as(value, cast)
|
||||
targetEmp = hierarchy.as(targetEmp, cast)
|
||||
|
@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Channel, Employee, getName } from '@hcengineering/contact'
|
||||
import core, { Doc, DocumentUpdate, Mixin, Ref, TxProcessor } from '@hcengineering/core'
|
||||
import { Card, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Channel, Person, getName } from '@hcengineering/contact'
|
||||
import core, { Doc, DocumentUpdate, Mixin, Ref, RefTo, Tx, TxOperations, TxProcessor } from '@hcengineering/core'
|
||||
import { Card, createQuery, getClient, updateAttribute } from '@hcengineering/presentation'
|
||||
import { Toggle } from '@hcengineering/ui'
|
||||
import { isCollectionAttr } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@ -24,40 +24,40 @@
|
||||
import ChannelPresenter from './ChannelPresenter.svelte'
|
||||
import ChannelsDropdown from './ChannelsDropdown.svelte'
|
||||
import EditEmployee from './EditEmployee.svelte'
|
||||
import EmployeeBox from './EmployeeBox.svelte'
|
||||
import MergeAttributeComparer from './MergeAttributeComparer.svelte'
|
||||
import MergeComparer from './MergeComparer.svelte'
|
||||
import UserBox from './UserBox.svelte'
|
||||
|
||||
export let value: Employee
|
||||
export let value: Person
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const parent = hierarchy.getParentClass(contact.class.Employee)
|
||||
const parent = hierarchy.getParentClass(contact.class.Person)
|
||||
const mixins = hierarchy.getDescendants(parent).filter((p) => hierarchy.isMixin(p))
|
||||
|
||||
let sourceEmployee = value._id
|
||||
let sourceEmp: Employee | undefined = undefined
|
||||
let sourcePersonRef = value._id
|
||||
let sourcePerson: Person | undefined = undefined
|
||||
|
||||
let targetEmployee: Ref<Employee> | undefined = undefined
|
||||
let targetEmp: Employee | undefined = undefined
|
||||
let targetPersonRf: Ref<Person> | undefined = undefined
|
||||
let targetPerson: Person | undefined = undefined
|
||||
|
||||
const targetQuery = createQuery()
|
||||
$: targetEmployee &&
|
||||
sourceEmployee &&
|
||||
targetQuery.query(contact.class.Employee, { _id: { $in: [sourceEmployee, targetEmployee] } }, (res) => {
|
||||
$: targetPersonRf &&
|
||||
sourcePersonRef &&
|
||||
targetQuery.query(contact.class.Person, { _id: { $in: [sourcePersonRef, targetPersonRf] } }, (res) => {
|
||||
// ;[targetEmp] = res
|
||||
sourceEmp = res.find((it) => it._id === sourceEmployee)
|
||||
targetEmp = res.find((it) => it._id === targetEmployee)
|
||||
if (sourceEmp && targetEmp) {
|
||||
update = fillUpdate(sourceEmp, targetEmp)
|
||||
mixinUpdate = fillMixinUpdate(sourceEmp, targetEmp)
|
||||
sourcePerson = res.find((it) => it._id === sourcePersonRef)
|
||||
targetPerson = res.find((it) => it._id === targetPersonRf)
|
||||
if (sourcePerson && targetPerson) {
|
||||
update = fillUpdate(sourcePerson, targetPerson)
|
||||
mixinUpdate = fillMixinUpdate(sourcePerson, targetPerson)
|
||||
applyUpdate(update)
|
||||
}
|
||||
})
|
||||
|
||||
function fillUpdate (source: Employee, target: Employee): DocumentUpdate<Employee> {
|
||||
const res: DocumentUpdate<Employee> = {}
|
||||
const attributes = hierarchy.getOwnAttributes(contact.class.Employee)
|
||||
function fillUpdate (source: Person, target: Person): DocumentUpdate<Person> {
|
||||
const res: DocumentUpdate<Person> = {}
|
||||
const attributes = hierarchy.getOwnAttributes(contact.class.Person)
|
||||
for (const attribute of attributes) {
|
||||
const key = attribute[0]
|
||||
if (attribute[1].hidden) continue
|
||||
@ -69,7 +69,7 @@
|
||||
return res
|
||||
}
|
||||
|
||||
function fillMixinUpdate (source: Employee, target: Employee): Record<Ref<Mixin<Doc>>, DocumentUpdate<Doc>> {
|
||||
function fillMixinUpdate (source: Person, target: Person): Record<Ref<Mixin<Doc>>, DocumentUpdate<Doc>> {
|
||||
const res: Record<Ref<Mixin<Doc>>, DocumentUpdate<Doc>> = {}
|
||||
for (const mixin of mixins) {
|
||||
if (!hierarchy.hasMixin(source, mixin)) continue
|
||||
@ -88,30 +88,31 @@
|
||||
return res
|
||||
}
|
||||
|
||||
let update: DocumentUpdate<Employee> = {}
|
||||
let update: DocumentUpdate<Person> = {}
|
||||
let mixinUpdate: Record<Ref<Mixin<Doc>>, DocumentUpdate<Doc>> = {}
|
||||
|
||||
let result: Employee = { ...value }
|
||||
let result: Person = { ...value }
|
||||
|
||||
function applyUpdate (update: DocumentUpdate<Employee>): void {
|
||||
const r = hierarchy.clone(targetEmp)
|
||||
function applyUpdate (update: DocumentUpdate<Person>): void {
|
||||
const r = hierarchy.clone(targetPerson)
|
||||
TxProcessor.applyUpdate(r, update)
|
||||
result = r
|
||||
}
|
||||
|
||||
async function merge (): Promise<void> {
|
||||
if (sourceEmp === undefined || targetEmp === undefined) return
|
||||
if (sourcePerson === undefined || targetPerson === undefined) return
|
||||
if (Object.keys(update).length > 0) {
|
||||
if (update.avatar !== undefined || sourceEmp.avatar === targetEmp.avatar) {
|
||||
if (update.avatar !== undefined || sourcePerson.avatar === targetPerson.avatar) {
|
||||
// We replace avatar, we need to update source with target
|
||||
await client.update(sourceEmp, { avatar: sourceEmp.avatar === targetEmp.avatar ? '' : targetEmp.avatar })
|
||||
await client.update(sourcePerson, {
|
||||
avatar: sourcePerson.avatar === targetPerson.avatar ? '' : targetPerson.avatar
|
||||
})
|
||||
}
|
||||
await client.update(targetEmp, update)
|
||||
await client.update(targetPerson, update)
|
||||
}
|
||||
await client.update(sourceEmp, { mergedTo: targetEmp._id, active: false })
|
||||
for (const channel of resultChannels.values()) {
|
||||
if (channel.attachedTo !== targetEmp._id) continue
|
||||
await client.update(channel, { attachedTo: targetEmp._id })
|
||||
if (channel.attachedTo !== targetPerson._id) continue
|
||||
await client.update(channel, { attachedTo: targetPerson._id })
|
||||
}
|
||||
for (const old of oldChannels) {
|
||||
if ((enabledChannels.get(old._id) ?? true) === false) {
|
||||
@ -121,18 +122,31 @@
|
||||
for (const mixin in mixinUpdate) {
|
||||
const attrs = (mixinUpdate as any)[mixin]
|
||||
if (Object.keys(attrs).length > 0) {
|
||||
await client.updateMixin(targetEmp._id, targetEmp._class, targetEmp.space, mixin as Ref<Mixin<Doc>>, attrs)
|
||||
} else if (!hierarchy.hasMixin(targetEmp, mixin as Ref<Mixin<Doc>>)) {
|
||||
await client.createMixin(targetEmp._id, targetEmp._class, targetEmp.space, mixin as Ref<Mixin<Doc>>, {})
|
||||
await client.updateMixin(
|
||||
targetPerson._id,
|
||||
targetPerson._class,
|
||||
targetPerson.space,
|
||||
mixin as Ref<Mixin<Doc>>,
|
||||
attrs
|
||||
)
|
||||
} else if (!hierarchy.hasMixin(targetPerson, mixin as Ref<Mixin<Doc>>)) {
|
||||
await client.createMixin(
|
||||
targetPerson._id,
|
||||
targetPerson._class,
|
||||
targetPerson.space,
|
||||
mixin as Ref<Mixin<Doc>>,
|
||||
{}
|
||||
)
|
||||
}
|
||||
}
|
||||
await updateAllRefs(client, sourcePerson, targetPerson)
|
||||
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
function select (field: string, targetValue: boolean) {
|
||||
if (!targetValue) {
|
||||
;(update as any)[field] = (sourceEmp as any)[field]
|
||||
;(update as any)[field] = (sourcePerson as any)[field]
|
||||
} else {
|
||||
delete (update as any)[field]
|
||||
}
|
||||
@ -166,20 +180,20 @@
|
||||
let oldChannels: Channel[] = []
|
||||
const valueChannelsQuery = createQuery()
|
||||
|
||||
$: valueChannelsQuery.query(contact.class.Channel, { attachedTo: sourceEmployee }, (res) => {
|
||||
$: valueChannelsQuery.query(contact.class.Channel, { attachedTo: sourcePersonRef }, (res) => {
|
||||
oldChannels = res
|
||||
})
|
||||
|
||||
let targetChannels: Channel[] = []
|
||||
const targetChannelsQuery = createQuery()
|
||||
$: targetEmployee &&
|
||||
targetChannelsQuery.query(contact.class.Channel, { attachedTo: targetEmployee }, (res) => {
|
||||
$: targetPersonRf &&
|
||||
targetChannelsQuery.query(contact.class.Channel, { attachedTo: targetPersonRf }, (res) => {
|
||||
targetChannels = res
|
||||
})
|
||||
|
||||
$: resultChannels = mergeChannels(oldChannels, targetChannels, enabledChannels)
|
||||
|
||||
const attributes = hierarchy.getAllAttributes(contact.class.Employee, core.class.Doc)
|
||||
const attributes = hierarchy.getAllAttributes(contact.mixin.Employee, core.class.Doc)
|
||||
const ignoreKeys = ['name', 'avatar', 'createdOn']
|
||||
const objectAttributes = Array.from(attributes.entries()).filter(
|
||||
(p) => !p[1].hidden && !ignoreKeys.includes(p[0]) && !isCollectionAttr(hierarchy, { key: p[0], attr: p[1] })
|
||||
@ -200,25 +214,111 @@
|
||||
}
|
||||
mixinUpdate[mixin] = upd
|
||||
}
|
||||
|
||||
async function updateAllRefs (client: TxOperations, sourceAccount: Person, targetAccount: Person): Promise<Tx[]> {
|
||||
const accounts = await client.findAll(contact.class.PersonAccount, { person: sourceAccount._id })
|
||||
|
||||
const h = client.getHierarchy()
|
||||
console.log('merge employee:', sourceAccount.name, 'to', targetAccount.name)
|
||||
// Move all possible references to Account and Employee and replace to target one.
|
||||
const reftos = (await client.findAll(core.class.Attribute, { 'type._class': core.class.RefTo })).filter((it) => {
|
||||
const to = it.type as RefTo<Doc>
|
||||
return (
|
||||
to.to === contact.class.Person ||
|
||||
to.to === contact.mixin.Employee ||
|
||||
to.to === core.class.Account ||
|
||||
to.to === contact.class.PersonAccount
|
||||
)
|
||||
})
|
||||
|
||||
for (const attr of reftos) {
|
||||
if (attr.name === '_id') {
|
||||
continue
|
||||
}
|
||||
const to = attr.type as RefTo<Doc>
|
||||
if (to.to === contact.mixin.Employee || to.to === contact.class.Person) {
|
||||
const descendants = h.getDescendants(attr.attributeOf)
|
||||
for (const d of descendants) {
|
||||
if (h.isDerived(d, core.class.Tx)) {
|
||||
continue
|
||||
}
|
||||
if (h.findDomain(d) !== undefined) {
|
||||
while (true) {
|
||||
const values = await client.findAll(d, { [attr.name]: sourceAccount._id }, { limit: 100 })
|
||||
if (values.length === 0) {
|
||||
break
|
||||
}
|
||||
|
||||
const builder = client.apply(sourceAccount._id)
|
||||
for (const v of values) {
|
||||
await updateAttribute(builder, v, d, { key: attr.name, attr }, targetAccount._id)
|
||||
}
|
||||
if (builder.txes.length > 0) {
|
||||
console.log('merge employee:', sourceAccount.name, 'to', targetAccount.name, d, builder.txes.length)
|
||||
await builder.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const arrs = await client.findAll(core.class.Attribute, { 'type._class': core.class.ArrOf })
|
||||
for (const attr of arrs) {
|
||||
if (attr.name === '_id') {
|
||||
continue
|
||||
}
|
||||
const to = attr.type as RefTo<Doc>
|
||||
if (to.to === contact.mixin.Employee || to.to === contact.class.Person) {
|
||||
const descendants = h.getDescendants(attr.attributeOf)
|
||||
for (const d of descendants) {
|
||||
if (h.isDerived(d, core.class.Tx)) {
|
||||
continue
|
||||
}
|
||||
if (h.findDomain(d) !== undefined) {
|
||||
while (true) {
|
||||
const values = await client.findAll(attr.attributeOf, { [attr.name]: sourceAccount._id }, { limit: 100 })
|
||||
if (values.length === 0) {
|
||||
break
|
||||
}
|
||||
const builder = client.apply(sourceAccount._id)
|
||||
for (const v of values) {
|
||||
await updateAttribute(builder, v, d, { key: attr.name, attr }, targetAccount._id)
|
||||
}
|
||||
console.log('merge employee:', sourceAccount.name, 'to', targetAccount.name, d, builder.txes.length)
|
||||
await builder.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await client.remove(sourceAccount)
|
||||
for (const account of accounts) {
|
||||
await client.update(account, { person: targetAccount._id })
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const toAny = (a: any) => a
|
||||
</script>
|
||||
|
||||
<Card
|
||||
label={contact.string.MergeEmployee}
|
||||
okLabel={contact.string.MergeEmployee}
|
||||
label={contact.string.MergePersons}
|
||||
okLabel={contact.string.MergePersons}
|
||||
fullSize
|
||||
okAction={merge}
|
||||
canSave={targetEmp !== undefined}
|
||||
canSave={targetPerson !== undefined}
|
||||
onCancel={() => dispatch('close')}
|
||||
on:changeContent
|
||||
>
|
||||
<div class="flex-row flex-between">
|
||||
<div class="flex-row-center">
|
||||
<EmployeeBox
|
||||
<UserBox
|
||||
_class={contact.class.Person}
|
||||
showNavigate={false}
|
||||
label={contact.string.MergeEmployeeFrom}
|
||||
docQuery={{ active: { $in: [true, false] } }}
|
||||
bind:value={sourceEmployee}
|
||||
label={contact.string.MergePersonsFrom}
|
||||
docQuery={{}}
|
||||
bind:value={sourcePersonRef}
|
||||
/>
|
||||
<ChannelsDropdown
|
||||
value={oldChannels}
|
||||
@ -231,11 +331,12 @@
|
||||
</div>
|
||||
>>
|
||||
<div class="flex-row-center">
|
||||
<EmployeeBox
|
||||
<UserBox
|
||||
_class={contact.class.Person}
|
||||
showNavigate={false}
|
||||
label={contact.string.MergeEmployeeTo}
|
||||
docQuery={{ active: { $in: [true, false] } }}
|
||||
bind:value={targetEmployee}
|
||||
label={contact.string.MergePersonsTo}
|
||||
docQuery={{ _id: { $ne: sourcePersonRef } }}
|
||||
bind:value={targetPersonRf}
|
||||
/>
|
||||
<ChannelsDropdown
|
||||
value={targetChannels}
|
||||
@ -247,13 +348,13 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#key [targetEmployee, sourceEmployee]}
|
||||
{#if targetEmp && sourceEmp}
|
||||
{#key [targetPersonRf, sourcePersonRef]}
|
||||
{#if targetPerson && sourcePerson}
|
||||
<div class="flex-col flex-grow">
|
||||
<MergeComparer
|
||||
key="avatar"
|
||||
value={sourceEmp}
|
||||
{targetEmp}
|
||||
value={sourcePerson}
|
||||
targetEmp={targetPerson}
|
||||
onChange={select}
|
||||
selected={update.avatar !== undefined}
|
||||
>
|
||||
@ -261,18 +362,24 @@
|
||||
<Avatar avatar={item.avatar} size={'x-large'} icon={contact.icon.Person} />
|
||||
</svelte:fragment>
|
||||
</MergeComparer>
|
||||
<MergeComparer key="name" value={sourceEmp} {targetEmp} onChange={select} selected={update.name !== undefined}>
|
||||
<MergeComparer
|
||||
key="name"
|
||||
value={sourcePerson}
|
||||
targetEmp={targetPerson}
|
||||
onChange={select}
|
||||
selected={update.name !== undefined}
|
||||
>
|
||||
<svelte:fragment slot="item" let:item>
|
||||
{getName(item)}
|
||||
{getName(client.getHierarchy(), item)}
|
||||
</svelte:fragment>
|
||||
</MergeComparer>
|
||||
{#each objectAttributes as attribute}
|
||||
<MergeAttributeComparer
|
||||
key={attribute[0]}
|
||||
value={sourceEmp}
|
||||
{targetEmp}
|
||||
value={sourcePerson}
|
||||
targetEmp={targetPerson}
|
||||
onChange={select}
|
||||
_class={contact.class.Employee}
|
||||
_class={contact.mixin.Employee}
|
||||
selected={toAny(update)[attribute[0]] !== undefined}
|
||||
/>
|
||||
{/each}
|
||||
@ -281,8 +388,8 @@
|
||||
{#each attributes as attribute}
|
||||
<MergeAttributeComparer
|
||||
key={attribute}
|
||||
value={sourceEmp}
|
||||
{targetEmp}
|
||||
value={sourcePerson}
|
||||
targetEmp={targetPerson}
|
||||
onChange={(key, value) => selectMixin(mixin, key, value)}
|
||||
_class={mixin}
|
||||
selected={toAny(mixinUpdate)?.[mixin]?.[attribute] !== undefined}
|
@ -13,17 +13,17 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import contact from '../plugin'
|
||||
import { employeeAccountByIdStore } from '../utils'
|
||||
import { personAccountByIdStore } from '../utils'
|
||||
import CombineAvatars from './CombineAvatars.svelte'
|
||||
|
||||
export let value: Ref<EmployeeAccount>[]
|
||||
export let value: Ref<PersonAccount>[]
|
||||
|
||||
$: employees = value
|
||||
.map((p) => $employeeAccountByIdStore.get(p)?.employee)
|
||||
.map((p) => $personAccountByIdStore.get(p)?.person)
|
||||
.filter((p) => p !== undefined) as Ref<Employee>[]
|
||||
</script>
|
||||
|
||||
<CombineAvatars _class={contact.class.Employee} items={employees} limit={5} size={'x-small'} />
|
||||
<CombineAvatars _class={contact.mixin.Employee} items={employees} limit={5} size={'x-small'} />
|
@ -14,13 +14,14 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import core, { Account, systemAccountEmail } from '@hcengineering/core'
|
||||
import { Employee, PersonAccount } from '@hcengineering/contact'
|
||||
import core, { Account, Ref, systemAccountEmail } from '@hcengineering/core'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { Label, tooltip, IconSize } from '@hcengineering/ui'
|
||||
import { employeeByIdStore } from '../utils'
|
||||
import { IconSize, Label, tooltip } from '@hcengineering/ui'
|
||||
import { employeeByIdStore, personAccountPersonByIdStore } from '../utils'
|
||||
import Avatar from './Avatar.svelte'
|
||||
import EmployeePresenter from './EmployeePresenter.svelte'
|
||||
import PersonPresenter from './PersonPresenter.svelte'
|
||||
|
||||
export let value: Account
|
||||
export let avatarSize: IconSize = 'x-small'
|
||||
@ -28,8 +29,9 @@
|
||||
export let inline: boolean = false
|
||||
export let accent: boolean = false
|
||||
|
||||
$: employee = $employeeByIdStore.get((value as EmployeeAccount)?.employee)
|
||||
$: employee = $employeeByIdStore.get((value as PersonAccount)?.person as Ref<Employee>)
|
||||
|
||||
$: person = $personAccountPersonByIdStore.get((value as PersonAccount)?.person)
|
||||
const valueLabel = value?.email === systemAccountEmail ? core.string.System : getEmbeddedLabel(value?.email)
|
||||
</script>
|
||||
|
||||
@ -37,6 +39,8 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
{#if employee}
|
||||
<EmployeePresenter value={employee} {disabled} {inline} {accent} {avatarSize} on:accent-color />
|
||||
{:else if person}
|
||||
<PersonPresenter value={person} {disabled} {inline} {accent} {avatarSize} on:accent-color />
|
||||
{:else}
|
||||
<div class="flex-row-center">
|
||||
<Avatar size={avatarSize} />
|
@ -14,21 +14,21 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { IconSize } from '@hcengineering/ui'
|
||||
import { employeeAccountByIdStore } from '../utils'
|
||||
import EmployeeAccountPresenter from './EmployeeAccountPresenter.svelte'
|
||||
import { personAccountByIdStore } from '../utils'
|
||||
import PersonAccountPresenter from './PersonAccountPresenter.svelte'
|
||||
|
||||
export let value: Ref<EmployeeAccount>
|
||||
export let value: Ref<PersonAccount>
|
||||
export let avatarSize: IconSize = 'x-small'
|
||||
export let disabled: boolean = false
|
||||
export let inline: boolean = false
|
||||
export let accent: boolean = false
|
||||
|
||||
$: account = $employeeAccountByIdStore.get(value)
|
||||
$: account = $personAccountByIdStore.get(value)
|
||||
</script>
|
||||
|
||||
{#if account}
|
||||
<EmployeeAccountPresenter value={account} {disabled} {inline} {avatarSize} on:accent-color />
|
||||
<PersonAccountPresenter value={account} {disabled} {inline} {avatarSize} on:accent-color />
|
||||
{/if}
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import attachment from '@hcengineering/attachment'
|
||||
import contact, { Channel, Contact, getName } from '@hcengineering/contact'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import Avatar from './Avatar.svelte'
|
||||
import { Component, Label } from '@hcengineering/ui'
|
||||
import { DocNavLink } from '@hcengineering/view-resources'
|
||||
@ -24,6 +24,8 @@
|
||||
export let object: Contact
|
||||
export let disabled: boolean = false
|
||||
|
||||
const client = getClient()
|
||||
|
||||
let channels: Channel[] = []
|
||||
const channelsQuery = createQuery()
|
||||
channelsQuery.query(
|
||||
@ -46,7 +48,7 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<DocNavLink {object} {disabled}>
|
||||
<div class="name lines-limit-2">
|
||||
{getName(object)}
|
||||
{getName(client.getHierarchy(), object)}
|
||||
</div>
|
||||
</DocNavLink>
|
||||
<div class="description overflow-label">{object.city ?? ''}</div>
|
||||
|
@ -27,6 +27,7 @@
|
||||
import { DocNavLink } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import Avatar from './Avatar.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let value: Person | Employee | undefined | null
|
||||
export let inline: boolean = false
|
||||
@ -45,6 +46,8 @@
|
||||
export let accent: boolean = false
|
||||
export let maxWidth = ''
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const onEditClick = (evt: MouseEvent) => {
|
||||
if (!disabled) {
|
||||
onEdit?.(evt)
|
||||
@ -83,7 +86,9 @@
|
||||
</span>
|
||||
{/if}
|
||||
{#if shouldShowName}
|
||||
<span class="eContentPresenterLabel" class:colorInherit class:fs-bold={accent}>{getName(value)}</span>
|
||||
<span class="eContentPresenterLabel" class:colorInherit class:fs-bold={accent}
|
||||
>{getName(client.getHierarchy(), value)}</span
|
||||
>
|
||||
{/if}
|
||||
</span>
|
||||
</DocNavLink>
|
||||
|
@ -18,6 +18,7 @@
|
||||
import type { LabelAndProps, IconSize } from '@hcengineering/ui'
|
||||
import { PersonLabelTooltip } from '..'
|
||||
import PersonContent from './PersonContent.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let value: Person | null | undefined
|
||||
export let inline = false
|
||||
@ -36,6 +37,8 @@
|
||||
export let accent: boolean = false
|
||||
export let maxWidth = ''
|
||||
|
||||
const client = getClient()
|
||||
|
||||
function getTooltip (
|
||||
tooltipLabels: PersonLabelTooltip | undefined,
|
||||
value: Person | null | undefined
|
||||
@ -44,7 +47,7 @@
|
||||
return !value
|
||||
? undefined
|
||||
: {
|
||||
label: getEmbeddedLabel(getName(value))
|
||||
label: getEmbeddedLabel(getName(client.getHierarchy(), value))
|
||||
}
|
||||
}
|
||||
const direction = tooltipLabels?.direction
|
||||
@ -52,11 +55,15 @@
|
||||
const label = value
|
||||
? tooltipLabels.personLabel
|
||||
? tooltipLabels.personLabel
|
||||
: getEmbeddedLabel(getName(value))
|
||||
: getEmbeddedLabel(getName(client.getHierarchy(), value))
|
||||
: tooltipLabels.placeholderLabel
|
||||
? tooltipLabels.placeholderLabel
|
||||
: undefined
|
||||
const props = tooltipLabels.props ? tooltipLabels.props : value ? { value: getName(value) } : undefined
|
||||
const props = tooltipLabels.props
|
||||
? tooltipLabels.props
|
||||
: value
|
||||
? { value: getName(client.getHierarchy(), value) }
|
||||
: undefined
|
||||
return {
|
||||
component,
|
||||
label,
|
||||
|
@ -25,7 +25,7 @@
|
||||
import UsersPopup from './UsersPopup.svelte'
|
||||
|
||||
export let items: Ref<Employee>[] = []
|
||||
export let _class: Ref<Class<Employee>> = contact.class.Employee
|
||||
export let _class: Ref<Class<Employee>> = contact.mixin.Employee
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {
|
||||
active: true
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import contact, { Person, PersonAccount, Employee } from '@hcengineering/contact'
|
||||
import { Account, AccountRole, DocumentQuery, getCurrentAccount, Ref, SortingOrder, Space } from '@hcengineering/core'
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
@ -33,29 +33,24 @@
|
||||
}
|
||||
let search: string = ''
|
||||
$: isSearch = search.trim().length
|
||||
let members: Set<Ref<Employee>> = new Set<Ref<Employee>>()
|
||||
let members: Set<Ref<Person>> = new Set<Ref<Person>>()
|
||||
|
||||
async function getUsers (accounts: Ref<Account>[], search: string): Promise<Employee[]> {
|
||||
const query: DocumentQuery<EmployeeAccount> =
|
||||
isSearch > 0 ? { name: { $like: '%' + search + '%' } } : { _id: { $in: accounts as Ref<EmployeeAccount>[] } }
|
||||
const employess = await client.findAll(contact.class.EmployeeAccount, query)
|
||||
members = new Set(
|
||||
employess
|
||||
.filter((it) => it.mergedTo == null)
|
||||
.filter((p) => accounts.includes(p._id))
|
||||
.map((p) => p.employee)
|
||||
)
|
||||
async function getUsers (accounts: Ref<Account>[], search: string): Promise<Person[]> {
|
||||
const query: DocumentQuery<PersonAccount> =
|
||||
isSearch > 0 ? { name: { $like: '%' + search + '%' } } : { _id: { $in: accounts as Ref<PersonAccount>[] } }
|
||||
const employess = await client.findAll(contact.class.PersonAccount, query)
|
||||
members = new Set(employess.filter((p) => accounts.includes(p._id)).map((p) => p.person))
|
||||
return await client.findAll(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{
|
||||
_id: { $in: employess.map((e) => e.employee) }
|
||||
_id: { $in: employess.map((e) => e.person as Ref<Employee>) }
|
||||
},
|
||||
{ sort: { name: SortingOrder.Descending } }
|
||||
)
|
||||
}
|
||||
|
||||
async function add (employee: Ref<Employee>): Promise<void> {
|
||||
const account = await client.findOne(contact.class.EmployeeAccount, { employee })
|
||||
async function add (employee: Ref<Person>): Promise<void> {
|
||||
const account = await client.findOne(contact.class.PersonAccount, { employee })
|
||||
if (account === undefined) return
|
||||
await client.update(space, {
|
||||
$push: {
|
||||
@ -64,14 +59,14 @@
|
||||
})
|
||||
}
|
||||
|
||||
async function removeMember (employee: Ref<Employee>): Promise<void> {
|
||||
const account = await client.findOne(contact.class.EmployeeAccount, { employee })
|
||||
async function removeMember (employee: Ref<Person>): Promise<void> {
|
||||
const account = await client.findOne(contact.class.PersonAccount, { employee })
|
||||
if (account === undefined) return
|
||||
await client.update(space, { $pull: { members: account._id } })
|
||||
}
|
||||
|
||||
function openAddMembersPopup () {
|
||||
showPopup(AddMembersPopup, { value: space }, undefined, async (membersIds: Ref<EmployeeAccount>[]) => {
|
||||
showPopup(AddMembersPopup, { value: space }, undefined, async (membersIds: Ref<PersonAccount>[]) => {
|
||||
if (membersIds) {
|
||||
for (const member of membersIds) {
|
||||
if (space.members.includes(member)) continue
|
||||
|
@ -14,8 +14,8 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Contact, getName } from '@hcengineering/contact'
|
||||
import { Class, DocumentQuery, FindOptions, Hierarchy, Ref } from '@hcengineering/core'
|
||||
import contact, { Contact, getName } from '@hcengineering/contact'
|
||||
import { Class, DocumentQuery, FindOptions, Hierarchy, Ref, Doc } from '@hcengineering/core'
|
||||
import { Asset, getEmbeddedLabel, IntlString } from '@hcengineering/platform'
|
||||
import { getClient, ObjectCreate } from '@hcengineering/presentation'
|
||||
import {
|
||||
@ -42,6 +42,7 @@
|
||||
import UsersPopup from './UsersPopup.svelte'
|
||||
|
||||
export let _class: Ref<Class<Contact>>
|
||||
export let _previewClass: Ref<Class<Contact>> = contact.class.Contact
|
||||
export let excluded: Ref<Contact>[] | undefined = undefined
|
||||
export let options: FindOptions<Contact> | undefined = undefined
|
||||
export let docQuery: DocumentQuery<Contact> | undefined = undefined
|
||||
@ -61,6 +62,9 @@
|
||||
export let showTooltip: LabelAndProps | undefined = undefined
|
||||
export let showNavigate = true
|
||||
export let id: string | undefined = undefined
|
||||
export let filter: (it: Doc) => boolean = () => {
|
||||
return true
|
||||
}
|
||||
|
||||
export let create: ObjectCreate | undefined = undefined
|
||||
|
||||
@ -72,7 +76,7 @@
|
||||
const client = getClient()
|
||||
|
||||
async function updateSelected (value: Ref<Contact> | null | undefined) {
|
||||
selected = value ? await client.findOne(_class, { _id: value }) : undefined
|
||||
selected = value ? await client.findOne(_previewClass, { _id: value }) : undefined
|
||||
}
|
||||
|
||||
$: updateSelected(value)
|
||||
@ -93,7 +97,8 @@
|
||||
selected: value,
|
||||
titleDeselect,
|
||||
placeholder,
|
||||
create
|
||||
create,
|
||||
filter
|
||||
},
|
||||
!$$slots.content ? container : getEventPositionElement(ev),
|
||||
(result) => {
|
||||
@ -121,7 +126,9 @@
|
||||
class="w-full h-full flex-streatch"
|
||||
on:click={_click}
|
||||
class:content-color={selected === undefined}
|
||||
use:tooltip={selected !== undefined ? { label: getEmbeddedLabel(getName(selected)) } : undefined}
|
||||
use:tooltip={selected !== undefined
|
||||
? { label: getEmbeddedLabel(getName(client.getHierarchy(), selected)) }
|
||||
: undefined}
|
||||
>
|
||||
<slot name="content" />
|
||||
</div>
|
||||
@ -148,13 +155,15 @@
|
||||
style:width={showNavigate && selected
|
||||
? `calc(${width ?? 'min-content'} - 1.5rem)`
|
||||
: `${width ?? 'min-content'}`}
|
||||
use:tooltip={selected !== undefined ? { label: getEmbeddedLabel(getName(selected)) } : undefined}
|
||||
use:tooltip={selected !== undefined
|
||||
? { label: getEmbeddedLabel(getName(client.getHierarchy(), selected)) }
|
||||
: undefined}
|
||||
>
|
||||
{#if selected}
|
||||
{#if hideIcon || selected}
|
||||
<UserInfo value={selected} size={avatarSize} {icon} />
|
||||
{:else}
|
||||
{getName(selected)}
|
||||
{getName(client.getHierarchy(), selected)}
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex-presenter not-selected">
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee } from '@hcengineering/contact'
|
||||
import type { Class, DocumentQuery, IdMap, Ref } from '@hcengineering/core'
|
||||
import type { Class, Doc, DocumentQuery, IdMap, Ref } from '@hcengineering/core'
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import { Label, showPopup, ActionIcon, IconClose, IconAdd, Icon } from '@hcengineering/ui'
|
||||
import type { IconSize } from '@hcengineering/ui'
|
||||
@ -23,13 +23,12 @@
|
||||
import { employeeByIdStore } from '../utils'
|
||||
import UserInfo from './UserInfo.svelte'
|
||||
import UsersPopup from './UsersPopup.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let items: Ref<Employee>[] = []
|
||||
export let readonlyItems: Ref<Employee>[] = []
|
||||
export let _class: Ref<Class<Employee>> = contact.class.Employee
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {
|
||||
active: true
|
||||
}
|
||||
export let _class: Ref<Class<Employee>> = contact.mixin.Employee
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {}
|
||||
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let actionLabel: IntlString = plugin.string.AddMember
|
||||
@ -42,6 +41,8 @@
|
||||
let readonlyPersons: Employee[] = getPersons(readonlyItems, $employeeByIdStore)
|
||||
$: readonlyPersons = getPersons(readonlyItems, $employeeByIdStore)
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function addPerson (evt: Event): Promise<void> {
|
||||
@ -55,7 +56,13 @@
|
||||
allowDeselect: false,
|
||||
selectedUsers: items,
|
||||
ignoreUsers: readonlyItems,
|
||||
readonly
|
||||
readonly,
|
||||
filter: (it: Doc) => {
|
||||
if (client.getHierarchy().hasMixin(it, contact.mixin.Employee)) {
|
||||
return client.getHierarchy().as(it, contact.mixin.Employee).active
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
evt.target as HTMLElement,
|
||||
undefined,
|
||||
|
@ -14,23 +14,22 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee } from '@hcengineering/contact'
|
||||
import type { Class, DocumentQuery, Ref } from '@hcengineering/core'
|
||||
import type { Class, DocumentQuery, Ref, Doc } from '@hcengineering/core'
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import { Button, Label, showPopup } from '@hcengineering/ui'
|
||||
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@hcengineering/ui'
|
||||
import { Button, Label, showPopup } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../plugin'
|
||||
import { employeeByIdStore } from '../utils'
|
||||
import CombineAvatars from './CombineAvatars.svelte'
|
||||
import Members from './icons/Members.svelte'
|
||||
import UserInfo from './UserInfo.svelte'
|
||||
import UsersPopup from './UsersPopup.svelte'
|
||||
import Members from './icons/Members.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let items: Ref<Employee>[] = []
|
||||
export let _class: Ref<Class<Employee>> = contact.class.Employee
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {
|
||||
active: true
|
||||
}
|
||||
export let _class: Ref<Class<Employee>> = contact.mixin.Employee
|
||||
export let docQuery: DocumentQuery<Employee> | undefined = {}
|
||||
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
@ -45,6 +44,7 @@
|
||||
$: persons = items.map((p) => $employeeByIdStore.get(p)).filter((p) => p !== undefined) as Employee[]
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
async function addPerson (evt: Event): Promise<void> {
|
||||
showPopup(
|
||||
@ -56,6 +56,12 @@
|
||||
multiSelect: true,
|
||||
allowDeselect: false,
|
||||
selectedUsers: items,
|
||||
filter: (it: Doc) => {
|
||||
const h = client.getHierarchy()
|
||||
if (h.hasMixin(it, contact.mixin.Employee)) {
|
||||
return h.as(it, contact.mixin.Employee).active
|
||||
}
|
||||
},
|
||||
readonly
|
||||
},
|
||||
evt.target as HTMLElement,
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import { getName, Person } from '@hcengineering/contact'
|
||||
import { Asset } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { AnySvelteComponent, IconSize } from '@hcengineering/ui'
|
||||
|
||||
export let value: Person
|
||||
@ -24,6 +25,8 @@
|
||||
export let size: IconSize
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
export let short: boolean = false
|
||||
|
||||
const client = getClient()
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
@ -31,6 +34,6 @@
|
||||
<Avatar avatar={value.avatar} {size} {icon} on:accent-color />
|
||||
<div class="flex-col min-w-0 {size === 'tiny' || size === 'inline' ? 'ml-1' : 'ml-2'}" class:max-w-20={short}>
|
||||
{#if subtitle}<div class="content-dark-color text-sm">{subtitle}</div>{/if}
|
||||
<div class="label overflow-label text-left">{getName(value)}</div>
|
||||
<div class="label overflow-label text-left">{getName(client.getHierarchy(), value)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Contact, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import contact, { Contact, getFirstName, getLastName, Person } from '@hcengineering/contact'
|
||||
import type { Class, Doc, DocumentQuery, FindOptions, Ref } from '@hcengineering/core'
|
||||
import type { Asset, IntlString } from '@hcengineering/platform'
|
||||
import presentation, { getClient, ObjectCreate, ObjectPopup } from '@hcengineering/presentation'
|
||||
@ -26,6 +26,15 @@
|
||||
export let selected: Ref<Person> | undefined
|
||||
export let docQuery: DocumentQuery<Contact> | undefined = undefined
|
||||
|
||||
const client = getClient()
|
||||
|
||||
export let filter: (it: Doc) => boolean = (it) => {
|
||||
if (client.getHierarchy().hasMixin(it, contact.mixin.Employee)) {
|
||||
return client.getHierarchy().as(it, contact.mixin.Employee).active
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export let multiSelect: boolean = false
|
||||
export let allowDeselect: boolean = false
|
||||
export let titleDeselect: IntlString | undefined = undefined
|
||||
@ -61,6 +70,7 @@
|
||||
{titleDeselect}
|
||||
{placeholder}
|
||||
{docQuery}
|
||||
{filter}
|
||||
groupBy={'_class'}
|
||||
bind:selectedObjects={selectedUsers}
|
||||
bind:ignoreObjects={ignoreUsers}
|
||||
|
@ -16,7 +16,7 @@
|
||||
import contact, { Channel, Contact, getName } from '@hcengineering/contact'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { CircleButton, tooltip } from '@hcengineering/ui'
|
||||
import { DocNavLink } from '@hcengineering/view-resources'
|
||||
import { channelProviders } from '../../utils'
|
||||
@ -27,6 +27,8 @@
|
||||
let target: Contact | undefined
|
||||
const query = createQuery()
|
||||
$: query.query(contact.class.Contact, { _id: value.attachedTo as Ref<Contact> }, (res) => ([target] = res))
|
||||
|
||||
const client = getClient()
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center" use:tooltip={{ label: getEmbeddedLabel(value.value) }}>
|
||||
@ -36,7 +38,7 @@
|
||||
{#if target}
|
||||
<div class="ml-1">
|
||||
<DocNavLink object={target}>
|
||||
{getName(target)}
|
||||
{getName(client.getHierarchy(), target)}
|
||||
</DocNavLink>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Channel, Contact, Employee, getGravatarUrl, getName } from '@hcengineering/contact'
|
||||
import { Channel, Contact, getGravatarUrl, getName, Person } from '@hcengineering/contact'
|
||||
import { Class, Client, DocumentQuery, Ref, RelatedDocument, WithLookup } from '@hcengineering/core'
|
||||
import login from '@hcengineering/login'
|
||||
import { IntlString, Resources, getResource } from '@hcengineering/platform'
|
||||
@ -55,9 +55,9 @@ import EditMember from './components/EditMember.svelte'
|
||||
import EditOrganization from './components/EditOrganization.svelte'
|
||||
import EditPerson from './components/EditPerson.svelte'
|
||||
import EditableAvatar from './components/EditableAvatar.svelte'
|
||||
import EmployeeAccountFilterValuePresenter from './components/EmployeeAccountFilterValuePresenter.svelte'
|
||||
import EmployeeAccountPresenter from './components/EmployeeAccountPresenter.svelte'
|
||||
import EmployeeAccountRefPresenter from './components/EmployeeAccountRefPresenter.svelte'
|
||||
import PersonAccountFilterValuePresenter from './components/PersonAccountFilterValuePresenter.svelte'
|
||||
import PersonAccountPresenter from './components/PersonAccountPresenter.svelte'
|
||||
import PersonAccountRefPresenter from './components/PersonAccountRefPresenter.svelte'
|
||||
import EmployeeArrayEditor from './components/EmployeeArrayEditor.svelte'
|
||||
import EmployeeBox from './components/EmployeeBox.svelte'
|
||||
import EmployeeBrowser from './components/EmployeeBrowser.svelte'
|
||||
@ -70,7 +70,7 @@ import MemberPresenter from './components/MemberPresenter.svelte'
|
||||
import Members from './components/Members.svelte'
|
||||
import MembersBox from './components/MembersBox.svelte'
|
||||
import MembersPresenter from './components/MembersPresenter.svelte'
|
||||
import MergeEmployee from './components/MergeEmployee.svelte'
|
||||
import MergePersons from './components/MergePersons.svelte'
|
||||
import OrganizationEditor from './components/OrganizationEditor.svelte'
|
||||
import OrganizationPresenter from './components/OrganizationPresenter.svelte'
|
||||
import PersonEditor from './components/PersonEditor.svelte'
|
||||
@ -121,7 +121,7 @@ export {
|
||||
EmployeeBrowser,
|
||||
MemberPresenter,
|
||||
EmployeeEditor,
|
||||
EmployeeAccountRefPresenter,
|
||||
PersonAccountRefPresenter,
|
||||
MembersPresenter,
|
||||
EditPerson,
|
||||
EmployeeRefPresenter,
|
||||
@ -148,7 +148,7 @@ export {
|
||||
|
||||
const toObjectSearchResult = (e: WithLookup<Contact>): ObjectSearchResult => ({
|
||||
doc: e,
|
||||
title: getName(e),
|
||||
title: getName(getClient().getHierarchy(), e),
|
||||
icon: Avatar,
|
||||
iconProps: { size: 'x-small', avatar: e.avatar },
|
||||
component: UserInfo,
|
||||
@ -171,13 +171,13 @@ async function queryEmployee (
|
||||
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
|
||||
): Promise<ObjectSearchResult[]> {
|
||||
const q1 = await doContactQuery(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{ name: { $like: `%${search}%` }, active: true },
|
||||
filter,
|
||||
client
|
||||
)
|
||||
const q2 = await doContactQuery(
|
||||
contact.class.Employee,
|
||||
contact.mixin.Employee,
|
||||
{ displayName: { $like: `%${search}%` }, active: true },
|
||||
{
|
||||
in: filter?.in,
|
||||
@ -195,7 +195,7 @@ async function doContactQuery<T extends Contact> (
|
||||
filter: { in?: RelatedDocument[] | undefined, nin?: RelatedDocument[] | undefined } | undefined,
|
||||
client: Client
|
||||
): Promise<ObjectSearchResult[]> {
|
||||
if (_class === contact.class.Employee) {
|
||||
if (_class === contact.mixin.Employee) {
|
||||
q = { ...q, active: true }
|
||||
}
|
||||
if (filter?.in !== undefined || filter?.nin !== undefined) {
|
||||
@ -210,10 +210,12 @@ async function doContactQuery<T extends Contact> (
|
||||
return (await client.findAll(_class, q, { limit: 200 })).map(toObjectSearchResult)
|
||||
}
|
||||
|
||||
async function kickEmployee (doc: Employee): Promise<void> {
|
||||
async function kickEmployee (doc: Person): Promise<void> {
|
||||
const client = getClient()
|
||||
const email = await client.findOne(contact.class.EmployeeAccount, { employee: doc._id })
|
||||
if (!doc.active) {
|
||||
|
||||
const employee = client.getHierarchy().as(doc, contact.mixin.Employee)
|
||||
const email = await client.findOne(contact.class.PersonAccount, { person: doc._id })
|
||||
if (!employee.active) {
|
||||
showPopup(
|
||||
MessageBox,
|
||||
{
|
||||
@ -230,7 +232,7 @@ async function kickEmployee (doc: Employee): Promise<void> {
|
||||
return
|
||||
}
|
||||
if (email === undefined) {
|
||||
await client.update(doc, { active: false })
|
||||
await client.update(employee, { active: false })
|
||||
} else {
|
||||
showPopup(
|
||||
MessageBox,
|
||||
@ -288,7 +290,7 @@ export default async (): Promise<Resources> => ({
|
||||
SocialEditor,
|
||||
Contacts,
|
||||
ContactsTabs,
|
||||
EmployeeAccountPresenter,
|
||||
PersonAccountPresenter,
|
||||
EmployeePresenter,
|
||||
EmployeeRefPresenter,
|
||||
Members,
|
||||
@ -300,7 +302,7 @@ export default async (): Promise<Resources> => ({
|
||||
CreateEmployee,
|
||||
AccountArrayEditor,
|
||||
ChannelFilter,
|
||||
MergeEmployee,
|
||||
MergePersons,
|
||||
Avatar,
|
||||
UserBoxList,
|
||||
ActivityChannelMessage,
|
||||
@ -312,9 +314,9 @@ export default async (): Promise<Resources> => ({
|
||||
UserBoxItems,
|
||||
EmployeeFilter,
|
||||
EmployeeFilterValuePresenter,
|
||||
EmployeeAccountFilterValuePresenter,
|
||||
PersonAccountFilterValuePresenter,
|
||||
DeleteConfirmationPopup,
|
||||
EmployeeAccountRefPresenter
|
||||
PersonAccountRefPresenter
|
||||
},
|
||||
completion: {
|
||||
EmployeeQuery: async (
|
||||
|
@ -60,10 +60,11 @@ export default mergeIds(contactId, contact, {
|
||||
Email: '' as IntlString,
|
||||
CreateEmployee: '' as IntlString,
|
||||
Inactive: '' as IntlString,
|
||||
Active: '' as IntlString,
|
||||
NotSpecified: '' as IntlString,
|
||||
MergeEmployee: '' as IntlString,
|
||||
MergeEmployeeFrom: '' as IntlString,
|
||||
MergeEmployeeTo: '' as IntlString,
|
||||
MergePersons: '' as IntlString,
|
||||
MergePersonsFrom: '' as IntlString,
|
||||
MergePersonsTo: '' as IntlString,
|
||||
SelectAvatar: '' as IntlString,
|
||||
GravatarsManaged: '' as IntlString,
|
||||
Through: '' as IntlString,
|
||||
|
@ -18,25 +18,26 @@ import {
|
||||
AvatarProvider,
|
||||
AvatarType,
|
||||
ChannelProvider,
|
||||
Contact,
|
||||
contactId,
|
||||
Employee,
|
||||
EmployeeAccount,
|
||||
Contact,
|
||||
PersonAccount,
|
||||
contactId,
|
||||
formatName,
|
||||
getFirstName,
|
||||
getLastName,
|
||||
getName
|
||||
getName,
|
||||
Person
|
||||
} from '@hcengineering/contact'
|
||||
import { Client, Doc, getCurrentAccount, IdMap, ObjQueryType, Ref, Timestamp, toIdMap } from '@hcengineering/core'
|
||||
import { Client, Doc, IdMap, ObjQueryType, Ref, Timestamp, getCurrentAccount, toIdMap } from '@hcengineering/core'
|
||||
import notification, { DocUpdateTx, DocUpdates } from '@hcengineering/notification'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { TemplateDataProvider } from '@hcengineering/templates'
|
||||
import { TabItem, getCurrentResolvedLocation, getPanelURI, Location, ResolvedLocation } from '@hcengineering/ui'
|
||||
import { Location, ResolvedLocation, TabItem, getCurrentResolvedLocation, getPanelURI } from '@hcengineering/ui'
|
||||
import view, { Filter } from '@hcengineering/view'
|
||||
import { FilterQuery } from '@hcengineering/view-resources'
|
||||
import { get, writable } from 'svelte/store'
|
||||
import { derived, get, writable } from 'svelte/store'
|
||||
import contact from './plugin'
|
||||
import notification, { DocUpdates, DocUpdateTx } from '@hcengineering/notification'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
|
||||
export function formatDate (dueDateMs: Timestamp): string {
|
||||
return new Date(dueDateMs).toLocaleString('default', {
|
||||
@ -48,6 +49,7 @@ export function formatDate (dueDateMs: Timestamp): string {
|
||||
}
|
||||
|
||||
export async function employeeSort (value: Array<Ref<Employee>>): Promise<Array<Ref<Employee>>> {
|
||||
const h = getClient().getHierarchy()
|
||||
return value.sort((a, b) => {
|
||||
const employeeId1 = a as Ref<Employee> | null | undefined
|
||||
const employeeId2 = b as Ref<Employee> | null | undefined
|
||||
@ -63,8 +65,8 @@ export async function employeeSort (value: Array<Ref<Employee>>): Promise<Array<
|
||||
if (employeeId1 != null && employeeId2 != null) {
|
||||
const employee1 = get(employeeByIdStore).get(employeeId1)
|
||||
const employee2 = get(employeeByIdStore).get(employeeId2)
|
||||
const name1 = employee1 != null ? getName(employee1) : ''
|
||||
const name2 = employee2 != null ? getName(employee2) : ''
|
||||
const name1 = employee1 != null ? getName(h, employee1) : ''
|
||||
const name2 = employee2 != null ? getName(h, employee2) : ''
|
||||
|
||||
return name1.localeCompare(name2)
|
||||
}
|
||||
@ -137,19 +139,19 @@ export async function getRefs (
|
||||
}
|
||||
|
||||
export async function getCurrentEmployeeName (): Promise<string> {
|
||||
const me = getCurrentAccount() as EmployeeAccount
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
return formatName(me.name)
|
||||
}
|
||||
|
||||
export async function getCurrentEmployeeEmail (): Promise<string> {
|
||||
const me = getCurrentAccount() as EmployeeAccount
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
return me.email
|
||||
}
|
||||
|
||||
export async function getCurrentEmployeePosition (): Promise<string | undefined> {
|
||||
const me = getCurrentAccount() as EmployeeAccount
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
const client = getClient()
|
||||
const employee = await client.findOne(contact.class.Employee, { _id: me.employee })
|
||||
const employee = await client.findOne<Employee>(contact.mixin.Employee, { _id: me.person as Ref<Employee> })
|
||||
if (employee !== undefined) {
|
||||
return employee.position ?? ''
|
||||
}
|
||||
@ -161,7 +163,7 @@ export async function getContactName (provider: TemplateDataProvider): Promise<s
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
if (hierarchy.isDerived(value._class, contact.class.Person)) {
|
||||
return getName(value)
|
||||
return getName(client.getHierarchy(), value)
|
||||
} else {
|
||||
return value.name
|
||||
}
|
||||
@ -234,7 +236,7 @@ async function generateLocation (loc: Location, id: Ref<Contact>): Promise<Resol
|
||||
const workspace = loc.path[1] ?? ''
|
||||
const special = client.getHierarchy().isDerived(doc._class, contact.class.Organization)
|
||||
? 'companies'
|
||||
: client.getHierarchy().isDerived(doc._class, contact.class.Employee)
|
||||
: client.getHierarchy().isDerived(doc._class, contact.mixin.Employee)
|
||||
? 'employees'
|
||||
: 'persons'
|
||||
return {
|
||||
@ -252,33 +254,43 @@ async function generateLocation (loc: Location, id: Ref<Contact>): Promise<Resol
|
||||
export const employeeByIdStore = writable<IdMap<Employee>>(new Map())
|
||||
export const employeesStore = writable<Employee[]>([])
|
||||
|
||||
export const employeeAccountByIdStore = writable<IdMap<EmployeeAccount>>(new Map())
|
||||
export const personAccountByIdStore = writable<IdMap<PersonAccount>>(new Map())
|
||||
|
||||
export const channelProviders = writable<ChannelProvider[]>([])
|
||||
|
||||
export const personAccountPersonByIdStore = writable<IdMap<Person>>(new Map())
|
||||
|
||||
export const personByIdStore = derived([personAccountPersonByIdStore, employeeByIdStore], (vals) => {
|
||||
const m1 = Array.from(vals[0].entries())
|
||||
const m2 = Array.from(vals[1].entries())
|
||||
return new Map([...m1, ...m2])
|
||||
})
|
||||
|
||||
function fillStores (): void {
|
||||
const client = getClient()
|
||||
|
||||
if (client !== undefined) {
|
||||
const accountPersonQuery = createQuery(true)
|
||||
|
||||
const query = createQuery(true)
|
||||
query.query(contact.class.Employee, {}, (res) => {
|
||||
query.query(contact.mixin.Employee, {}, (res) => {
|
||||
employeesStore.set(res)
|
||||
employeeByIdStore.set(toIdMap(res))
|
||||
})
|
||||
|
||||
const accountQ = createQuery(true)
|
||||
accountQ.query(contact.class.EmployeeAccount, {}, (res) => {
|
||||
const mergedEmployees = res.filter((it) => it.mergedTo !== undefined)
|
||||
const activeEmployees = res.filter((it) => it.mergedTo === undefined)
|
||||
const ids = toIdMap(activeEmployees)
|
||||
for (const e of mergedEmployees) {
|
||||
if (e.mergedTo !== undefined) {
|
||||
const mergeTo = ids.get(e.mergedTo)
|
||||
if (mergeTo !== undefined) {
|
||||
ids.set(e._id, mergeTo)
|
||||
}
|
||||
accountQ.query(contact.class.PersonAccount, {}, (res) => {
|
||||
personAccountByIdStore.set(toIdMap(res))
|
||||
|
||||
const persons = res.map((it) => it.person)
|
||||
|
||||
accountPersonQuery.query(
|
||||
contact.class.Person,
|
||||
{ _id: { $in: persons }, [contact.mixin.Employee]: { $exists: false } },
|
||||
(res) => {
|
||||
personAccountPersonByIdStore.set(toIdMap(res))
|
||||
}
|
||||
}
|
||||
employeeAccountByIdStore.set(ids)
|
||||
)
|
||||
})
|
||||
|
||||
const providerQuery = createQuery(true)
|
||||
@ -332,5 +344,5 @@ export function getAvatarProviderId (avatar?: string | null): Ref<AvatarProvider
|
||||
export async function contactTitleProvider (client: Client, ref: Ref<Contact>): Promise<string> {
|
||||
const object = await client.findOne(contact.class.Contact, { _id: ref })
|
||||
if (object === undefined) return ''
|
||||
return getName(object)
|
||||
return getName(client.getHierarchy(), object)
|
||||
}
|
||||
|
@ -138,7 +138,6 @@ export interface Status extends AttachedDoc {
|
||||
*/
|
||||
export interface Employee extends Person {
|
||||
active: boolean
|
||||
mergedTo?: Ref<Employee>
|
||||
statuses?: number
|
||||
displayName?: string | null
|
||||
position?: string | null
|
||||
@ -147,9 +146,8 @@ export interface Employee extends Person {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface EmployeeAccount extends Account {
|
||||
employee: Ref<Employee>
|
||||
mergedTo?: Ref<EmployeeAccount>
|
||||
export interface PersonAccount extends Account {
|
||||
person: Ref<Person>
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,11 +178,13 @@ export const contactPlugin = plugin(contactId, {
|
||||
Member: '' as Ref<Class<Member>>,
|
||||
Organization: '' as Ref<Class<Organization>>,
|
||||
Organizations: '' as Ref<Class<Organizations>>,
|
||||
Employee: '' as Ref<Class<Employee>>,
|
||||
EmployeeAccount: '' as Ref<Class<EmployeeAccount>>,
|
||||
PersonAccount: '' as Ref<Class<PersonAccount>>,
|
||||
Status: '' as Ref<Class<Status>>,
|
||||
ContactsTab: '' as Ref<Class<ContactsTab>>
|
||||
},
|
||||
mixin: {
|
||||
Employee: '' as Ref<Class<Employee>>
|
||||
},
|
||||
component: {
|
||||
SocialEditor: '' as AnyComponent,
|
||||
CreateOrganization: '' as AnyComponent,
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { AttachedData, Class, Client, Doc, FindResult, Ref } from '@hcengineering/core'
|
||||
import { AttachedData, Class, Client, Doc, FindResult, Ref, Hierarchy } from '@hcengineering/core'
|
||||
import { IconSize } from '@hcengineering/ui'
|
||||
import { MD5 } from 'crypto-js'
|
||||
import { Channel, Contact, contactPlugin, Employee, Person } from '.'
|
||||
@ -211,9 +211,9 @@ export function formatName (name: string): string {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function getName (value: Contact): string {
|
||||
if (isEmployee(value)) {
|
||||
return value.displayName ?? formatName(value.name)
|
||||
export function getName (hierarchy: Hierarchy, value: Contact): string {
|
||||
if (isEmployee(hierarchy, value)) {
|
||||
return hierarchy.as(value, contactPlugin.mixin.Employee).displayName ?? formatName(value.name)
|
||||
}
|
||||
if (isPerson(value)) {
|
||||
return formatName(value.name)
|
||||
@ -221,8 +221,8 @@ export function getName (value: Contact): string {
|
||||
return value.name
|
||||
}
|
||||
|
||||
function isEmployee (value: Contact): value is Employee {
|
||||
return value._class === contactPlugin.class.Employee
|
||||
function isEmployee (hierarchy: Hierarchy, value: Contact): value is Employee {
|
||||
return hierarchy.hasMixin(value, contactPlugin.mixin.Employee)
|
||||
}
|
||||
|
||||
function isPerson (value: Contact): value is Person {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user