diff --git a/.github/workflows/baseimage.yaml b/.github/workflows/baseimage.yaml index 6ca480d9e7..33dade9009 100644 --- a/.github/workflows/baseimage.yaml +++ b/.github/workflows/baseimage.yaml @@ -23,7 +23,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Configure docker - uses: crazy-max/ghaction-setup-docker@v3 + uses: crazy-max/ghaction-setup-docker@v5 with: daemon-config: | { diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b9628a6030..fa1419c85a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -651,7 +651,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Configure docker - uses: docker/setup-docker-action@v4 + uses: docker/setup-docker-action@v5 with: daemon-config: | { diff --git a/changelog.md b/changelog.md index c4ce3364d2..87c6249616 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,12 @@ Changelog. +## [0.7.382] - 2026-03-02 + +* ๐Ÿš€ FEATURES: ยท Add ability to sort projects and hide archived ([#10552](https://github.com/hcengineering/platform/issues/10552)) ยท Add tag process fixes ([#10561](https://github.com/hcengineering/platform/issues/10561)) ยท Add tags to markdown table ([#10560](https://github.com/hcengineering/platform/issues/10560)) ยท Implement `FieldChangedRollback` to revert document updates in โ€ฆ ([#10572](https://github.com/hcengineering/platform/issues/10572)) ยท Implement field locking and unlocking functionality, including UI, backend logic, and i18n. ([#10573](https://github.com/hcengineering/platform/issues/10573)) +* ๐Ÿ› BUG FIXES: ยท Embed html instead of showing in iframe ([#10549](https://github.com/hcengineering/platform/issues/10549)) ยท Npm publish ([#10545](https://github.com/hcengineering/platform/issues/10545)) ยท FieldChangesCheck ([#10550](https://github.com/hcengineering/platform/issues/10550)) ยท Missing enum when export type ([#10551](https://github.com/hcengineering/platform/issues/10551)) ยท *(account)* Handle empty $in array to prevent PostgreSQL IN () syntax error ([#10554](https://github.com/hcengineering/platform/issues/10554)) ยท Last messages button ([#10558](https://github.com/hcengineering/platform/issues/10558)) ยท Allow kick last owner ([#10559](https://github.com/hcengineering/platform/issues/10559)) ยท Process middleware ([#10568](https://github.com/hcengineering/platform/issues/10568)) ยท Prrocess user input ([#10570](https://github.com/hcengineering/platform/issues/10570)) ยท Process ([#10571](https://github.com/hcengineering/platform/issues/10571)) ยท Dependency mismatch +* โš™๏ธ MISCELLANEOUS TASKS: ยท Changelog ([#10544](https://github.com/hcengineering/platform/issues/10544)) ยท 0.7.382 + ## [0.7.375] - 2026-02-23 * ๐Ÿš€ FEATURES: ยท Add activity section in controlled doc ([#10457](https://github.com/hcengineering/platform/issues/10457)) ยท Add data converter plugin ([#10460](https://github.com/hcengineering/platform/issues/10460)) ยท *(ui)* Add Turkish language to settings popup ([#10441](https://github.com/hcengineering/platform/issues/10441)) ยท Turkish language in dev setup ([#10462](https://github.com/hcengineering/platform/issues/10462)) ยท Add import notifications ([#10464](https://github.com/hcengineering/platform/issues/10464)) ยท Guest users to upload attachments and use reactions ([#10469](https://github.com/hcengineering/platform/issues/10469)) ยท Add activity input for controlled docs ([#10470](https://github.com/hcengineering/platform/issues/10470)) ยท Ability to select multiple docs and to export to pdf ([#10468](https://github.com/hcengineering/platform/issues/10468)) ยท Headers legibility ([#10473](https://github.com/hcengineering/platform/issues/10473)) ยท Brazilian Portuguese translation ([#10478](https://github.com/hcengineering/platform/issues/10478)) ยท Add drive permissions ([#10489](https://github.com/hcengineering/platform/issues/10489)) ยท Add unlock card and section functionality with UI updates ([#10492](https://github.com/hcengineering/platform/issues/10492)) ยท To define different viewlet actions ([#10502](https://github.com/hcengineering/platform/issues/10502)) ยท Add ability to copy all data from cards/docs tables ([#10505](https://github.com/hcengineering/platform/issues/10505)) ยท Redesign workspace join ([#10507](https://github.com/hcengineering/platform/issues/10507)) ยท For guests to update notification settings ([#10517](https://github.com/hcengineering/platform/issues/10517)) ยท Add project breadcrumb ([#10515](https://github.com/hcengineering/platform/issues/10515)) ยท Implement process import/export functionality, enhance process โ€ฆ ([#10528](https://github.com/hcengineering/platform/issues/10528)) ยท Implement CancelSubProcess action, fix process execution flow. ([#10530](https://github.com/hcengineering/platform/issues/10530)) ยท Add ability to group by issues by project ([#10531](https://github.com/hcengineering/platform/issues/10531)) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index b6b4d32982..75a27a72e5 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -5029,6 +5029,9 @@ importers: '@hcengineering/query': specifier: workspace:^0.7.17 version: link:../../../core/packages/query + '@hcengineering/rank': + specifier: workspace:^0.7.17 + version: link:../../../core/packages/rank '@hcengineering/server-core': specifier: workspace:^0.7.18 version: link:../core @@ -61377,7 +61380,7 @@ snapshots: node-loader@2.0.0(webpack@5.102.1): dependencies: loader-utils: 2.0.4 - webpack: 5.102.1 + webpack: 5.102.1(esbuild@0.25.12)(webpack-cli@5.1.4) node-localstorage@2.2.1: dependencies: diff --git a/foundations/core/packages/core/src/classes.ts b/foundations/core/packages/core/src/classes.ts index 4307dbf502..20640de419 100644 --- a/foundations/core/packages/core/src/classes.ts +++ b/foundations/core/packages/core/src/classes.ts @@ -394,6 +394,13 @@ export interface EnumOf extends Type { */ export interface TypeHyperlink extends Type {} +/** + * @public + */ +export interface TypeRank extends Type { + pos?: 'start' | 'end' +} + /** * @public * diff --git a/foundations/core/packages/model/src/dsl.ts b/foundations/core/packages/model/src/dsl.ts index dfe0313ae1..d8e086d15d 100644 --- a/foundations/core/packages/model/src/dsl.ts +++ b/foundations/core/packages/model/src/dsl.ts @@ -38,7 +38,7 @@ import core, { type Obj, type PersonId, type PropertyType, - type Rank, + type TypeRank as TypeRankType, type Ref, type RefTo, type Space, @@ -531,8 +531,8 @@ export function TypeCollaborativeDoc (): Type { /** * @public */ -export function TypeRank (): Type { - return { _class: core.class.TypeRank, label: core.string.Rank, icon: core.icon.TypeRank } +export function TypeRank (pos: 'start' | 'end' = 'end'): TypeRankType { + return { _class: core.class.TypeRank, label: core.string.Rank, icon: core.icon.TypeRank, pos } } export function TypePersonId (): Type { diff --git a/foundations/server/packages/middleware/package.json b/foundations/server/packages/middleware/package.json index 08f1b540ea..5ec5b8bf39 100644 --- a/foundations/server/packages/middleware/package.json +++ b/foundations/server/packages/middleware/package.json @@ -38,6 +38,7 @@ "@hcengineering/core": "workspace:^0.7.24", "@hcengineering/contact": "workspace:^0.7.0", "@hcengineering/platform": "workspace:^0.7.19", + "@hcengineering/rank": "workspace:^0.7.17", "@hcengineering/server-core": "workspace:^0.7.18", "@hcengineering/query": "workspace:^0.7.17", "@hcengineering/analytics": "workspace:^0.7.17", diff --git a/foundations/server/packages/middleware/src/index.ts b/foundations/server/packages/middleware/src/index.ts index 5e673060b0..061b25ab56 100644 --- a/foundations/server/packages/middleware/src/index.ts +++ b/foundations/server/packages/middleware/src/index.ts @@ -44,3 +44,4 @@ export * from './userStatus' export * from './findSecurity' export * from './normalizeTx' export * from './versioning' +export * from './rank' diff --git a/foundations/server/packages/middleware/src/rank.ts b/foundations/server/packages/middleware/src/rank.ts new file mode 100644 index 0000000000..7ca011118e --- /dev/null +++ b/foundations/server/packages/middleware/src/rank.ts @@ -0,0 +1,112 @@ +// +// Copyright ยฉ 2025 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import core, { + type MeasureContext, + type Tx, + type SessionData, + type TxCreateDoc, + type TxApplyIf, + type Doc, + type Rank, + type TxMixin, + type TypeRank, + SortingOrder +} from '@hcengineering/core' +import { makeRank } from '@hcengineering/rank' +import { + type Middleware, + type TxMiddlewareResult, + type PipelineContext, + BaseMiddleware +} from '@hcengineering/server-core' + +/** + * Special value to indicate that rank should be auto-generated + * @public + */ +export const RANK_AUTO = '' as Rank + +export class RankMiddleware extends BaseMiddleware implements Middleware { + private constructor (context: PipelineContext, next?: Middleware) { + super(context, next) + } + + static async create ( + ctx: MeasureContext, + context: PipelineContext, + next: Middleware | undefined + ): Promise { + return new RankMiddleware(context, next) + } + + async tx (ctx: MeasureContext, txes: Tx[]): Promise { + for (const tx of txes) { + await this.processTx(ctx, tx) + } + + return await this.provideTx(ctx, txes) + } + + private async processTx (ctx: MeasureContext, tx: Tx): Promise { + if (tx._class === core.class.TxCreateDoc) { + await this.setRank(ctx, tx as TxCreateDoc) + } else if (tx._class === core.class.TxApplyIf) { + const applyTx = tx as TxApplyIf + for (const atx of applyTx.txes) { + await this.processTx(ctx, atx) + } + } + } + + private async setRank (ctx: MeasureContext, tx: TxCreateDoc | TxMixin): Promise { + const attributes = + tx._class === core.class.TxCreateDoc + ? this.context.hierarchy.getAllAttributes(tx.objectClass) + : this.context.hierarchy.getOwnAttributes((tx as TxMixin).mixin) + + for (const attr of attributes) { + if (attr[1].type._class === core.class.TypeRank) { + const rankAttr = attr[1].name + const typeRank = attr[1].type as TypeRank + + const rank = (tx.attributes as any)[rankAttr] + if (rank !== undefined && rank !== RANK_AUTO) { + continue + } + + const pos = typeRank.pos ?? 'end' + + // Query for either the first (Beginning) or last (End) document + const sortOrder = pos === 'end' ? SortingOrder.Descending : SortingOrder.Ascending + const existingDoc = await this.provideFindAll( + ctx, + tx.objectClass, + { space: tx.objectSpace }, + { + sort: { [rankAttr]: sortOrder }, + projection: { [rankAttr]: 1 }, + limit: 1 + } + ) + + const lastRank = existingDoc.length > 0 ? (existingDoc[0] as any)[rankAttr] : undefined + const newRank = pos === 'end' ? makeRank(lastRank, undefined) : makeRank(undefined, lastRank) + + ;(tx.attributes as any)[rankAttr] = newRank + } + } + } +} diff --git a/models/card/src/index.ts b/models/card/src/index.ts index 653800d84f..f301c795a7 100644 --- a/models/card/src/index.ts +++ b/models/card/src/index.ts @@ -63,6 +63,7 @@ import { ReadOnly, TypeCollaborativeDoc, TypeNumber, + TypeRank, TypeRef, TypeString, UX @@ -127,7 +128,9 @@ export class TCard extends TDoc implements Card { @Prop(Collection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files }) attachments?: number - rank!: Rank + @Prop(TypeRank(), core.string.Rank) + @Hidden() + rank!: Rank @Prop(Collection(time.class.ToDo), getEmbeddedLabel('Action Items')) todos?: CollectionSize diff --git a/models/controlled-documents/src/types.ts b/models/controlled-documents/src/types.ts index 1974b9a6ee..c6d4c0b32c 100644 --- a/models/controlled-documents/src/types.ts +++ b/models/controlled-documents/src/types.ts @@ -75,7 +75,8 @@ import { UX, TypeCollaborativeDoc, TypeMarkup, - ReadOnly + ReadOnly, + TypeRank } from '@hcengineering/model' import attachment from '@hcengineering/model-attachment' import chunter, { TChatMessage } from '@hcengineering/model-chunter' @@ -181,6 +182,7 @@ export class TProjectMeta extends TDoc implements ProjectMeta { @Prop(Collection(documents.class.ProjectDocument), documents.string.Documents) documents!: CollectionSize + @Prop(TypeRank(), core.string.Rank) @Index(IndexKind.Indexed) @Hidden() rank!: Rank diff --git a/models/document/src/index.ts b/models/document/src/index.ts index 80ced86e90..75d046bb4f 100644 --- a/models/document/src/index.ts +++ b/models/document/src/index.ts @@ -38,6 +38,7 @@ import { TypeAccountUuid, TypeCollaborativeDoc, TypeNumber, + TypeRank, TypeRef, TypeString, UX @@ -116,6 +117,7 @@ export class TDocument extends TDoc implements Document, Todoable { @Prop(Collection(time.class.ToDo), getEmbeddedLabel('Action Items')) todos?: CollectionSize + @Prop(TypeRank(), core.string.Rank) @Index(IndexKind.Indexed) @Hidden() rank!: Rank diff --git a/models/task/src/index.ts b/models/task/src/index.ts index 288c95d57f..9259c85798 100644 --- a/models/task/src/index.ts +++ b/models/task/src/index.ts @@ -36,6 +36,7 @@ import { ReadOnly, TypeBoolean, TypeDate, + TypeRank, TypeRecord, TypeRef, TypeString, @@ -113,7 +114,7 @@ export class TTask extends TAttachedDoc implements Task { @Prop(TypeDate(), task.string.DueDate, { editor: task.component.DueDateEditor }) dueDate!: Timestamp | null - @Prop(TypeString(), task.string.Rank) + @Prop(TypeRank(), task.string.Rank) @Index(IndexKind.IndexedDsc) @Hidden() rank!: Rank diff --git a/models/time/src/index.ts b/models/time/src/index.ts index d9e5f60c49..c5e604b52e 100644 --- a/models/time/src/index.ts +++ b/models/time/src/index.ts @@ -44,7 +44,8 @@ import { TypeString, UX, type Builder, - TypeMarkup + TypeMarkup, + TypeRank } from '@hcengineering/model' import { TEvent } from '@hcengineering/model-calendar' import core, { TAttachedDoc, TClass, TDoc, TType } from '@hcengineering/model-core' @@ -131,6 +132,7 @@ export class TToDo extends TAttachedDoc implements ToDo { @Prop(Collection(tags.class.TagReference, tags.string.TagLabel), tags.string.Tags) labels?: number | undefined + @Prop(TypeRank(), core.string.Rank) @Index(IndexKind.Indexed) @Hidden() rank!: Rank diff --git a/plugins/bitrix/src/hr.ts b/plugins/bitrix/src/hr.ts index 97673adf2b..0c44213a29 100644 --- a/plugins/bitrix/src/hr.ts +++ b/plugins/bitrix/src/hr.ts @@ -1,17 +1,7 @@ import { Organization } from '@hcengineering/contact' -import core, { - PersonId, - Client, - Data, - Doc, - Ref, - SortingOrder, - Status, - TxOperations, - generateId -} from '@hcengineering/core' +import core, { PersonId, Client, Data, Doc, Ref, Status, TxOperations, generateId } from '@hcengineering/core' import recruit, { Applicant, Vacancy } from '@hcengineering/recruit' -import task, { ProjectType, makeRank } from '@hcengineering/task' +import task, { ProjectType } from '@hcengineering/task' export async function createVacancy ( rawClient: Client, @@ -71,13 +61,12 @@ export async function createApplication ( throw new Error('sequence object not found') } - const lastOne = await client.findOne(recruit.class.Applicant, {}, { sort: { rank: SortingOrder.Descending } }) const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true) await client.addCollection(recruit.class.Applicant, _space, doc._id, recruit.mixin.Candidate, 'applications', { ...data, status: selectedState._id, number: (incResult as any).object.sequence, - rank: makeRank(lastOne?.rank, undefined) + rank: '' }) } diff --git a/plugins/board-resources/src/components/CreateCard.svelte b/plugins/board-resources/src/components/CreateCard.svelte index 610e1802c3..6b3e21545a 100644 --- a/plugins/board-resources/src/components/CreateCard.svelte +++ b/plugins/board-resources/src/components/CreateCard.svelte @@ -18,7 +18,7 @@ import core, { AttachedData, Ref, SortingOrder, Space, generateId } from '@hcengineering/core' import { OK, Status } from '@hcengineering/platform' import { Card, SpaceSelector, createQuery, getClient } from '@hcengineering/presentation' - import task, { TaskType, makeRank } from '@hcengineering/task' + import { TaskType } from '@hcengineering/task' import { EditBox, Grid, Status as StatusControl } from '@hcengineering/ui' import { createEventDispatcher } from 'svelte' import board from '../plugin' @@ -62,7 +62,6 @@ throw new Error('sequence object not found') } - const lastOne = await client.findOne(board.class.Card, {}, { sort: { rank: SortingOrder.Descending } }) const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true) const number = (incResult as any).object.sequence @@ -73,7 +72,7 @@ title, kind, identifier: `CARD-${number}`, - rank: makeRank(lastOne?.rank, undefined), + rank: '', assignee: null, description: '', members: [], diff --git a/plugins/board-resources/src/components/add-card/AddCard.svelte b/plugins/board-resources/src/components/add-card/AddCard.svelte index 6e41e9011b..2a8fc2a9b4 100644 --- a/plugins/board-resources/src/components/add-card/AddCard.svelte +++ b/plugins/board-resources/src/components/add-card/AddCard.svelte @@ -15,8 +15,7 @@