Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions models/hr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,14 +404,29 @@ export function createModel (builder: Builder): void {
attachTo: hr.mixin.Staff,
descriptor: view.viewlet.Table,
config: [
'',
{ key: '', props: { showStatus: true } },
'department',
{
key: '$lookup.channels',
label: contact.string.ContactInfo,
sortingKey: ['$lookup.channels.lastMessage', 'channels']
},
'modifiedOn'
]
],
viewOptions: {
groupBy: [],
orderBy: [],
other: [
{
key: 'hideInactive',
type: 'toggle',
defaultValue: true,
actionTarget: 'query',
action: contact.function.HideInactive,
label: contact.string.HideInactive
}
]
}
},
hr.viewlet.TableMember
)
Expand Down
6 changes: 5 additions & 1 deletion models/hr/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async function rebuildDepartmentMembersFromStaff (client: MigrationClient): Prom
const persons = await client.find<Person>(DOMAIN_CONTACT, { _class: contact.class.Person })
for (const person of persons) {
const staff = client.hierarchy.asIf<Person, Staff>(person, hr.mixin.Staff)
if (staff?.department === undefined || !staff.active) {
if (staff?.department === undefined) {
continue
}

Expand Down Expand Up @@ -172,6 +172,10 @@ export const hrOperation: MigrateOperation = {
{
state: 'rebuildDepartmentMembersFromStaff',
func: rebuildDepartmentMembersFromStaff
},
{
state: 'rebuildDepartmentMembersFromStaffIncludingInactive',
func: rebuildDepartmentMembersFromStaff
}
])
},
Expand Down
5 changes: 3 additions & 2 deletions plugins/hr-resources/src/components/DepartmentCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
}
}

function openLeadEditor (event: MouseEvent) {

Check warning on line 48 in plugins/hr-resources/src/components/DepartmentCard.svelte

View workflow job for this annotation

GitHub Actions / formatting

Missing return type on function
event?.preventDefault()
event?.stopPropagation()
showPopup(
Expand All @@ -64,12 +64,12 @@
)
}

function createChild (e: MouseEvent) {

Check warning on line 67 in plugins/hr-resources/src/components/DepartmentCard.svelte

View workflow job for this annotation

GitHub Actions / formatting

Missing return type on function
showPopup(CreateDepartment, { space: value._id }, eventToHTMLElement(e))
}

function edit (e: MouseEvent): void {

Check warning on line 71 in plugins/hr-resources/src/components/DepartmentCard.svelte

View workflow job for this annotation

GitHub Actions / formatting

'e' is defined but never used
openDoc(client.getHierarchy(), value)

Check warning on line 72 in plugins/hr-resources/src/components/DepartmentCard.svelte

View workflow job for this annotation

GitHub Actions / formatting

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
}

export let dragPerson: WithLookup<Staff> | undefined
Expand All @@ -78,7 +78,8 @@
$: dragPersonId = dragPerson?._id

$: members = new Set<Ref<Staff>>(value.members as Ref<Staff>[])
$: values = allEmployees.filter((it) => members.has(it._id) && it._id !== dragPersonId)
$: activeMembers = allEmployees.filter((it) => it.active && members.has(it._id))
$: values = activeMembers.filter((it) => it._id !== dragPersonId)

$: dragging = value._id === dragOver?._id && dragPersonId !== undefined

Expand All @@ -97,7 +98,7 @@
>
<div
class="flex-between pt-4 pb-4 pr-4 pl-2 w-full"
on:dragover|preventDefault|stopPropagation={(evt) => {

Check warning on line 101 in plugins/hr-resources/src/components/DepartmentCard.svelte

View workflow job for this annotation

GitHub Actions / formatting

'evt' is defined but never used
dragOver = value
}}
on:dragend|preventDefault|stopPropagation={() => {
Expand All @@ -121,7 +122,7 @@
<div class="fs-title">
{value.name}
</div>
<Label label={hr.string.MemberCount} params={{ count: value.members.length }} />
<Label label={hr.string.MemberCount} params={{ count: activeMembers.length }} />
</div>
<PersonsPresenter value={values} bind:dragPerson showDragPerson={dragging} />
</div>
Expand Down
7 changes: 5 additions & 2 deletions plugins/hr-resources/src/components/DepartmentStaff.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import { Department } from '@hcengineering/hr'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, IconAdd, Label, Scroller, Section, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { Viewlet, ViewletPreference } from '@hcengineering/view'
import { Viewlet, ViewletPreference, type ViewOptions } from '@hcengineering/view'
import { Table, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources'
import hr from '../plugin'
import { addMember } from '../utils'
Expand Down Expand Up @@ -63,6 +63,7 @@
let preference: ViewletPreference | undefined
let loading = false
let viewlet: WithLookup<Viewlet> | undefined
let viewOptions: ViewOptions | undefined
</script>

<Section label={hr.string.Members}>
Expand All @@ -75,7 +76,7 @@
bind:loading
viewletQuery={{ _id: hr.viewlet.TableMember }}
/>
<ViewletSettingButton kind={'ghost'} bind:viewlet />
<ViewletSettingButton kind={'ghost'} bind:viewlet bind:viewOptions />
<Button id={hr.string.AddEmployee} icon={IconAdd} kind={'ghost'} on:click={add} />
</div>
</svelte:fragment>
Expand All @@ -87,6 +88,8 @@
_class={hr.mixin.Staff}
config={preference?.config ?? viewlet?.config ?? []}
options={viewlet?.options}
viewOptionsConfig={viewlet?.viewOptions?.other}
{viewOptions}
query={{ _id: { $in: members } }}
loadingProps={{ length: members.length }}
/>
Expand Down
9 changes: 6 additions & 3 deletions plugins/hr-resources/src/components/Members.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import { type Department } from '@hcengineering/hr'
import { getClient } from '@hcengineering/presentation'
import { Button, IconAdd, Label, Section, showPopup, Scroller } from '@hcengineering/ui'
import { Viewlet, ViewletPreference } from '@hcengineering/view'
import { Viewlet, ViewletPreference, type ViewOptions } from '@hcengineering/view'
import { Table, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources'
import hr from '../plugin'

Expand Down Expand Up @@ -60,6 +60,7 @@

let viewlet: Viewlet | undefined
let preference: ViewletPreference | undefined
let viewOptions: ViewOptions | undefined
</script>

<Section id="members" label={hr.string.Members} icon={hr.icon.Members}>
Expand All @@ -72,7 +73,7 @@
bind:loading
viewletQuery={{ _id: hr.viewlet.TableMember }}
/>
<ViewletSettingButton kind={'tertiary'} bind:viewlet />
<ViewletSettingButton kind={'tertiary'} bind:viewlet bind:viewOptions />
{#if !readonly}
<Button id={hr.string.AddMember} icon={IconAdd} kind={'ghost'} on:click={createApp} />
{/if}
Expand All @@ -83,9 +84,11 @@
{#if members.length > 0 && viewlet}
<Scroller horizontal noFade={false}>
<Table
_class={contact.mixin.Employee}
_class={hr.mixin.Staff}
config={preference?.config ?? viewlet.config}
options={viewlet.options}
viewOptionsConfig={viewlet.viewOptions?.other}
{viewOptions}
query={{ _id: { $in: members } }}
loadingProps={{ length: members.length }}
{readonly}
Expand Down
22 changes: 18 additions & 4 deletions plugins/view-resources/src/components/RelationshipTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
}

let resultOptions = options
let resultQuery: DocumentQuery<Doc> = query

const update = reduceCalls(async function (
_class: Ref<Class<Doc>>,
Expand All @@ -137,10 +138,12 @@
lookup: Lookup<Doc>,
associations: AssociationQuery[] | undefined,
limit: number,
options: FindOptions<Doc> | undefined
options: FindOptions<Doc> | undefined,
viewOptionsConfig: ViewOptionModel[] | undefined,
viewOptions: ViewOptions | undefined
) {
const p = await getResultQuery(hierarchy, query, viewOptionsConfig, viewOptions)
const resultQuery = mergeQueries(p, query)
resultQuery = mergeQueries(p, query)
loading += q.query(
_class,
resultQuery,
Expand All @@ -159,7 +162,18 @@
? 1
: 0
})
$: void update(_class, query, _sortKey, sortOrder, lookup, associations, limit, resultOptions)
$: void update(
_class,
query,
_sortKey,
sortOrder,
lookup,
associations,
limit,
resultOptions,
viewOptionsConfig,
viewOptions
)

$: void getResultOptions(options, viewOptionsConfig, viewOptions).then((p) => {
resultOptions = p
Expand All @@ -170,7 +184,7 @@
const qSlow = createQuery()
$: qSlow.query(
_class,
query,
resultQuery,
(result) => {
total = result.total
if (totalQuery === undefined) {
Expand Down
22 changes: 18 additions & 4 deletions plugins/view-resources/src/components/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
}

let resultOptions = options
let resultQuery: DocumentQuery<Doc> = query

const update = reduceCalls(async function (
_class: Ref<Class<Doc>>,
Expand All @@ -148,10 +149,12 @@
lookup: Lookup<Doc>,
associations: AssociationQuery[] | undefined,
limit: number,
options: FindOptions<Doc> | undefined
options: FindOptions<Doc> | undefined,
viewOptionsConfig: ViewOptionModel[] | undefined,
viewOptions: ViewOptions | undefined
) {
const p = await getResultQuery(hierarchy, query, viewOptionsConfig, viewOptions)
const resultQuery = mergeQueries(p, query)
resultQuery = mergeQueries(p, query)
loading += q.query(
_class,
resultQuery,
Expand All @@ -170,7 +173,18 @@
? 1
: 0
})
$: void update(_class, query, _sortKey, sortOrder, lookup, associations, limit, resultOptions)
$: void update(
_class,
query,
_sortKey,
sortOrder,
lookup,
associations,
limit,
resultOptions,
viewOptionsConfig,
viewOptions
)

$: void getResultOptions(options, viewOptionsConfig, viewOptions).then((p) => {
resultOptions = p
Expand All @@ -181,7 +195,7 @@
const qSlow = createQuery()
$: qSlow.query(
_class,
query,
resultQuery,
(result) => {
total = result.total
if (totalQuery === undefined) {
Expand Down
21 changes: 13 additions & 8 deletions plugins/view-resources/src/components/ViewOptions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@
}

const changeToggle = (model: ViewOptionModel) => {
viewOptions[model.key] = !viewOptions[model.key]
dispatch('update', { key: model.key, value: viewOptions[model.key] })
const value = !(viewOptions[model.key] ?? model.defaultValue)
viewOptions[model.key] = value
dispatch('update', { key: model.key, value })
}

// checking if selector provides multiple choice options
Expand Down Expand Up @@ -143,12 +144,16 @@
>
<span class="overflow-label"><Label label={model.label} /></span>
{#if isToggleType(model)}
<Toggle
on={viewOptions[model.key] ?? model.defaultValue}
on:change={() => {
changeToggle(model)
}}
/>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<span on:click|stopPropagation>
<Toggle
on={viewOptions[model.key] ?? model.defaultValue}
on:change={() => {
changeToggle(model)
}}
/>
</span>
{:else if isDropdownType(model)}
{@const items = model.values.filter(({ hidden }) => !hidden?.(viewOptions))}
<DropdownLabelsIntl
Expand Down
54 changes: 26 additions & 28 deletions server-plugins/hr-resources/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,8 @@ export async function OnDepartmentStaff (txes: Tx[], control: TriggerControl): P
const removedDepartments = await buildHierarchy(lastDepartment, control)
const removed = removedDepartments.map((p) => p._id)
const pushIds = push.map((p) => p._id)
const added = push.filter((p) => !removed.includes(p._id))
const removedIds = exclude(pushIds, removed)
result.push(...getTxes(control.txFactory, [employee], added, removedIds))
result.push(...getTxes(control.txFactory, [employee], push, removedIds))
}
}
}
Expand Down Expand Up @@ -228,12 +227,10 @@ export async function OnDepartmentUpdate (txes: Tx[], control: TriggerControl):
const oldHierarchy = oldParent !== undefined ? await buildHierarchy(oldParent, control) : []
const newHierarchy = newParent !== undefined ? await buildHierarchy(newParent, control) : []

const oldHierarchyIds = oldHierarchy.map((p) => p._id)
const newHierarchyIds = newHierarchy.map((p) => p._id)
const added = newHierarchy.filter((p) => !oldHierarchyIds.includes(p._id))
const removed = oldHierarchy.filter((p) => !newHierarchyIds.includes(p._id)).map((p) => p._id)

result.push(...getTxes(control.txFactory, members, added, removed))
result.push(...getTxes(control.txFactory, members, newHierarchy, removed))
}
return result
}
Expand Down Expand Up @@ -309,29 +306,30 @@ export async function OnEmployee (txes: Tx[], control: TriggerControl): Promise<
* @public
*/
export async function OnEmployeeDeactivate (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
const result: Tx[] = []
for (const tx of txes) {
if (core.class.TxMixin !== tx._class) {
continue
}
const ctx = tx as TxMixin<Person, Employee>
if (ctx.mixin !== contact.mixin.Employee || ctx.attributes.active !== false) {
continue
}
const employee = ctx.objectId as Ref<Employee>
const departments = await control.queryFind(control.ctx, hr.class.Department, {})
const removed = departments.filter((dep) => dep.members.some((p) => p === employee))
result.push(
...getTxes(
control.txFactory,
[employee],
[],
removed.map((p) => p._id)
)
)
}

return result
return []
// const result: Tx[] = []
// for (const tx of txes) {
// if (core.class.TxMixin !== tx._class) {
// continue
// }
// const ctx = tx as TxMixin<Person, Employee>
// if (ctx.mixin !== contact.mixin.Employee || ctx.attributes.active !== false) {
// continue
// }
// const employee = ctx.objectId as Ref<Employee>
// const departments = await control.queryFind(control.ctx, hr.class.Department, {})
// const removed = departments.filter((dep) => dep.members.some((p) => p === employee))
// result.push(
// ...getTxes(
// control.txFactory,
// [employee],
// [],
// removed.map((p) => p._id)
// )
// )
// }

// return result
}

// TODO: why we need specific email notifications instead of using general flow?
Expand Down
Loading