mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-08 02:37:44 +02:00
UBER-174: Introduce createOn every there (#3222)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -35,8 +35,7 @@ const object: AttachedData<Issue> = {
|
||||
reportedTime: 0,
|
||||
estimation: 0,
|
||||
reports: 0,
|
||||
childInfo: [],
|
||||
createOn: Date.now()
|
||||
childInfo: []
|
||||
}
|
||||
|
||||
export interface IssueOptions {
|
||||
@@ -98,8 +97,7 @@ async function genIssue (client: TxOperations, statuses: Ref<IssueStatus>[]): Pr
|
||||
estimation: object.estimation,
|
||||
reports: 0,
|
||||
relations: [],
|
||||
childInfo: [],
|
||||
createOn: Date.now()
|
||||
childInfo: []
|
||||
}
|
||||
await client.addCollection(
|
||||
tracker.class.Issue,
|
||||
|
||||
@@ -2,23 +2,23 @@ import contact, { Channel, Employee, EmployeeAccount, Person } from '@hcengineer
|
||||
import core, {
|
||||
AttachedData,
|
||||
Data,
|
||||
generateId,
|
||||
MeasureContext,
|
||||
MeasureMetricsContext,
|
||||
metricsToString,
|
||||
MixinUpdate,
|
||||
Ref,
|
||||
TxOperations,
|
||||
WorkspaceId
|
||||
WorkspaceId,
|
||||
generateId,
|
||||
metricsToString
|
||||
} from '@hcengineering/core'
|
||||
import { MinioService } from '@hcengineering/minio'
|
||||
import recruit from '@hcengineering/model-recruit'
|
||||
import { Applicant, Candidate, Vacancy } from '@hcengineering/recruit'
|
||||
import { genRanks, State } from '@hcengineering/task'
|
||||
import { State, genRanks } from '@hcengineering/task'
|
||||
import faker from 'faker'
|
||||
import jpeg, { BufferRet } from 'jpeg-js'
|
||||
import { addAttachments, AttachmentOptions } from './attachments'
|
||||
import { addComments, CommentOptions } from './comments'
|
||||
import { AttachmentOptions, addAttachments } from './attachments'
|
||||
import { CommentOptions, addComments } from './comments'
|
||||
import { connect } from './connect'
|
||||
import { createUpdateSpaceKanban } from './kanban'
|
||||
import { findOrUpdate, findOrUpdateAttached } from './utils'
|
||||
@@ -162,8 +162,7 @@ async function genApplicant (
|
||||
doneState: null,
|
||||
rank: rank as string,
|
||||
startDate: null,
|
||||
dueDate: null,
|
||||
createOn: Date.now()
|
||||
dueDate: null
|
||||
}
|
||||
|
||||
// Update or create candidate
|
||||
@@ -234,8 +233,7 @@ async function genCandidate (
|
||||
const candidate: Data<Person> = {
|
||||
name: fName + ',' + lName,
|
||||
city: faker.address.city(),
|
||||
avatar: imgId,
|
||||
createOn: Date.now()
|
||||
avatar: imgId
|
||||
}
|
||||
|
||||
const candidateMixin: MixinUpdate<Person, Candidate> = {
|
||||
|
||||
@@ -91,10 +91,6 @@ export class TChunterMessage extends TAttachedDoc implements ChunterMessage {
|
||||
@ReadOnly()
|
||||
createBy!: Ref<Account>
|
||||
|
||||
@Prop(TypeTimestamp(), chunter.string.Create)
|
||||
@ReadOnly()
|
||||
createOn!: Timestamp
|
||||
|
||||
@Prop(TypeTimestamp(), chunter.string.Edit)
|
||||
editedOn?: Timestamp
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import { Comment, Message, ThreadMessage } from '@hcengineering/chunter'
|
||||
import core, { Doc, DOMAIN_TX, Ref, TxCreateDoc, TxOperations } from '@hcengineering/core'
|
||||
import core, { DOMAIN_TX, Doc, Ref, TxCreateDoc, TxOperations } from '@hcengineering/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import { DOMAIN_CHUNTER, DOMAIN_COMMENT } from './index'
|
||||
import chunter from './plugin'
|
||||
@@ -81,21 +81,6 @@ async function createBacklink (tx: TxOperations): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function setCreate (client: TxOperations): Promise<void> {
|
||||
const messages = (await client.findAll(chunter.class.Message, {}))
|
||||
.filter((m) => m.createBy === undefined)
|
||||
.map((m) => m._id)
|
||||
if (messages.length === 0) return
|
||||
const txes = await client.findAll(core.class.TxCreateDoc, { objectId: { $in: messages } })
|
||||
const promises = txes.map(async (tx) => {
|
||||
await client.updateDoc<Message>(chunter.class.Message, tx.objectSpace, tx.objectId as Ref<Message>, {
|
||||
createBy: tx.modifiedBy,
|
||||
createOn: tx.modifiedOn
|
||||
})
|
||||
})
|
||||
await Promise.all(promises)
|
||||
}
|
||||
|
||||
export async function migrateMessages (client: MigrationClient): Promise<void> {
|
||||
const messages = await client.find(DOMAIN_CHUNTER, {
|
||||
_class: chunter.class.Message,
|
||||
@@ -188,6 +173,5 @@ export const chunterOperation: MigrateOperation = {
|
||||
await createGeneral(tx)
|
||||
await createRandom(tx)
|
||||
await createBacklink(tx)
|
||||
await setCreate(tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import {
|
||||
Index,
|
||||
Model,
|
||||
Prop,
|
||||
ReadOnly,
|
||||
TypeDate,
|
||||
TypeRef,
|
||||
TypeString,
|
||||
@@ -103,10 +102,6 @@ export class TContact extends TDoc implements Contact {
|
||||
@Prop(TypeString(), contact.string.Location)
|
||||
@Index(IndexKind.FullText)
|
||||
city!: string
|
||||
|
||||
@Prop(TypeTimestamp(), contact.string.CreatedDate)
|
||||
@ReadOnly()
|
||||
createOn!: Timestamp
|
||||
}
|
||||
|
||||
@Model(contact.class.Channel, core.class.AttachedDoc, DOMAIN_CHANNEL)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
//
|
||||
|
||||
import { Contact } from '@hcengineering/contact'
|
||||
import { DOMAIN_TX, TxCreateDoc, TxOperations } from '@hcengineering/core'
|
||||
import { TxOperations } from '@hcengineering/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import core from '@hcengineering/model-core'
|
||||
import contact, { DOMAIN_CONTACT } from './index'
|
||||
import contact from './index'
|
||||
|
||||
async function createSpace (tx: TxOperations): Promise<void> {
|
||||
const current = await tx.findOne(core.class.Space, {
|
||||
@@ -43,64 +42,6 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
let totalCreateOn = 0
|
||||
async function setCreate (client: MigrationClient): Promise<void> {
|
||||
while (true) {
|
||||
const docs = await client.find<Contact>(
|
||||
DOMAIN_CONTACT,
|
||||
{
|
||||
_class: {
|
||||
$in: [contact.class.Contact, contact.class.Organization, contact.class.Person, contact.class.Employee]
|
||||
},
|
||||
createOn: { $exists: false }
|
||||
},
|
||||
{ limit: 500 }
|
||||
)
|
||||
if (docs.length === 0) {
|
||||
break
|
||||
}
|
||||
totalCreateOn += docs.length
|
||||
console.log('processing createOn migration', totalCreateOn)
|
||||
const creates = await client.find<TxCreateDoc<Contact>>(DOMAIN_TX, {
|
||||
objectId: { $in: docs.map((it) => it._id) },
|
||||
_class: core.class.TxCreateDoc
|
||||
})
|
||||
for (const doc of docs) {
|
||||
const tx = creates.find((it) => it.objectId === doc._id)
|
||||
if (tx !== undefined) {
|
||||
await client.update(
|
||||
DOMAIN_CONTACT,
|
||||
{
|
||||
_id: doc._id
|
||||
},
|
||||
{
|
||||
createOn: tx.modifiedOn
|
||||
}
|
||||
)
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
_id: tx._id
|
||||
},
|
||||
{
|
||||
'attributes.createOn': tx.modifiedOn
|
||||
}
|
||||
)
|
||||
} else {
|
||||
await client.update(
|
||||
DOMAIN_CONTACT,
|
||||
{
|
||||
_id: doc._id
|
||||
},
|
||||
{
|
||||
createOn: doc.modifiedOn
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
const employees = await client.findAll(contact.class.Employee, {})
|
||||
const channels = await client.findAll(contact.class.Channel, {
|
||||
@@ -133,9 +74,7 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
}
|
||||
|
||||
export const contactOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient): Promise<void> {
|
||||
await setCreate(client)
|
||||
},
|
||||
async migrate (client: MigrationClient): Promise<void> {},
|
||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
||||
const tx = new TxOperations(client, core.account.System)
|
||||
await createSpace(tx)
|
||||
|
||||
@@ -57,6 +57,7 @@ import {
|
||||
Mixin as MMixin,
|
||||
Model,
|
||||
Prop,
|
||||
ReadOnly,
|
||||
TypeBoolean,
|
||||
TypeIntlString,
|
||||
TypeRecord,
|
||||
@@ -101,6 +102,10 @@ export class TDoc extends TObj implements Doc {
|
||||
@Prop(TypeRef(core.class.Account), core.string.CreatedBy)
|
||||
@Index(IndexKind.Indexed)
|
||||
createdBy!: Ref<Account>
|
||||
|
||||
@Prop(TypeTimestamp(), core.string.CreatedDate)
|
||||
@ReadOnly()
|
||||
createOn!: Timestamp
|
||||
}
|
||||
|
||||
@Model(core.class.AttachedDoc, core.class.Doc)
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import core, {
|
||||
Doc,
|
||||
AttachedDoc,
|
||||
DOMAIN_BLOB,
|
||||
DOMAIN_DOC_INDEX_STATE,
|
||||
DOMAIN_MODEL,
|
||||
DOMAIN_TX,
|
||||
TxCreateDoc,
|
||||
Doc,
|
||||
TxCollectionCUD,
|
||||
AttachedDoc
|
||||
TxCreateDoc
|
||||
} from '@hcengineering/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
|
||||
async function fillCreatedBy (client: MigrationClient): Promise<void> {
|
||||
const h = client.hierarchy
|
||||
@@ -87,9 +87,72 @@ async function fillCreatedBy (client: MigrationClient): Promise<void> {
|
||||
}
|
||||
}
|
||||
}
|
||||
async function fillCreatedOn (client: MigrationClient): Promise<void> {
|
||||
const h = client.hierarchy
|
||||
const domains = h.domains()
|
||||
for (const domain of domains) {
|
||||
if (
|
||||
domain === DOMAIN_TX ||
|
||||
domain === DOMAIN_MODEL ||
|
||||
domain === DOMAIN_BLOB ||
|
||||
domain === DOMAIN_DOC_INDEX_STATE
|
||||
) {
|
||||
continue
|
||||
}
|
||||
while (true) {
|
||||
try {
|
||||
const objects = await client.find<Doc>(
|
||||
domain,
|
||||
{ createdOn: { $exists: false } },
|
||||
{ projection: { _id: 1, modifiedOn: 1 }, limit: 10000 }
|
||||
)
|
||||
if (objects.length === 0) {
|
||||
break
|
||||
}
|
||||
const txes = await client.find<TxCreateDoc<Doc>>(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
_class: core.class.TxCreateDoc,
|
||||
objectId: { $in: Array.from(objects.map((it) => it._id)) }
|
||||
},
|
||||
{ projection: { _id: 1, modifiedOn: 1, createOn: 1, objectId: 1 } }
|
||||
)
|
||||
|
||||
const txes2 = (
|
||||
await client.find<TxCollectionCUD<Doc, AttachedDoc>>(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
_class: core.class.TxCollectionCUD,
|
||||
'tx._class': core.class.TxCreateDoc,
|
||||
'tx.objectId': { $in: Array.from(objects.map((it) => it._id)) }
|
||||
},
|
||||
{ projection: { _id: 1, modifiedOn: 1, createOn: 1, tx: 1 } }
|
||||
)
|
||||
).map((it) => it.tx as unknown as TxCreateDoc<Doc>)
|
||||
|
||||
const txMap = new Map(txes.concat(txes2).map((p) => [p.objectId, p]))
|
||||
|
||||
console.log('migrateCreateOn', domain, objects.length)
|
||||
await client.bulk(
|
||||
domain,
|
||||
objects.map((it) => {
|
||||
const createTx = txMap.get(it._id)
|
||||
return {
|
||||
filter: { _id: it._id },
|
||||
update: {
|
||||
createdOn: createTx?.createOn ?? it.modifiedOn
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
} catch (err) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
export const coreOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient): Promise<void> {
|
||||
await fillCreatedBy(client)
|
||||
await fillCreatedOn(client)
|
||||
},
|
||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import contact, { EmployeeAccount } from '@hcengineering/contact'
|
||||
import core, { AccountRole, DOMAIN_TX, TxCreateDoc, TxOperations } from '@hcengineering/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import contact, { EmployeeAccount } from '@hcengineering/contact'
|
||||
import recruit from '@hcengineering/model-recruit'
|
||||
import { DOMAIN_CONTACT } from '@hcengineering/model-contact'
|
||||
import recruit from '@hcengineering/model-recruit'
|
||||
|
||||
async function createCandidate (
|
||||
tx: TxOperations,
|
||||
@@ -33,8 +33,7 @@ async function createCandidate (
|
||||
if (current !== undefined) return
|
||||
const u1 = await tx.createDoc(contact.class.Person, recruit.space.CandidatesPublic, {
|
||||
name,
|
||||
city,
|
||||
createOn: Date.now()
|
||||
city
|
||||
})
|
||||
await tx.addCollection(contact.class.Channel, recruit.space.CandidatesPublic, u1, contact.class.Person, 'channels', {
|
||||
provider: contact.channelProvider.Email,
|
||||
@@ -74,8 +73,7 @@ export const demoOperation: MigrateOperation = {
|
||||
const employee = await ops.createDoc(contact.class.Employee, contact.space.Employee, {
|
||||
name: 'Chen,Rosamund',
|
||||
city: 'Mountain View',
|
||||
active: true,
|
||||
createOn: Date.now()
|
||||
active: true
|
||||
})
|
||||
|
||||
await ops.createDoc<EmployeeAccount>(contact.class.EmployeeAccount, core.space.Model, {
|
||||
|
||||
@@ -270,6 +270,7 @@ export function createModel (builder: Builder): void {
|
||||
orderBy: [
|
||||
['state', SortingOrder.Ascending],
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['createOn', SortingOrder.Descending],
|
||||
['dueDate', SortingOrder.Ascending],
|
||||
['rank', SortingOrder.Ascending]
|
||||
],
|
||||
|
||||
@@ -29,7 +29,6 @@ import {
|
||||
TypeMarkup,
|
||||
TypeRef,
|
||||
TypeString,
|
||||
TypeTimestamp,
|
||||
UX
|
||||
} from '@hcengineering/model'
|
||||
import attachment from '@hcengineering/model-attachment'
|
||||
@@ -37,6 +36,7 @@ import calendar from '@hcengineering/model-calendar'
|
||||
import chunter from '@hcengineering/model-chunter'
|
||||
import contact, { TOrganization, TPerson } from '@hcengineering/model-contact'
|
||||
import core, { TAttachedDoc, TSpace } from '@hcengineering/model-core'
|
||||
import { generateClassNotificationTypes } from '@hcengineering/model-notification'
|
||||
import presentation from '@hcengineering/model-presentation'
|
||||
import tags from '@hcengineering/model-tags'
|
||||
import task, { DOMAIN_TASK, TSpaceWithStates, TTask, actionTemplates } from '@hcengineering/model-task'
|
||||
@@ -59,7 +59,6 @@ import { KeyBinding, ViewOptionsModel } from '@hcengineering/view'
|
||||
import recruit from './plugin'
|
||||
import { createReviewModel, reviewTableConfig, reviewTableOptions } from './review'
|
||||
import { TOpinion, TReview } from './review-model'
|
||||
import { generateClassNotificationTypes } from '@hcengineering/model-notification'
|
||||
|
||||
export { recruitId } from '@hcengineering/recruit'
|
||||
export { recruitOperation } from './migration'
|
||||
@@ -167,10 +166,6 @@ export class TApplicant extends TTask implements Applicant {
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), recruit.string.AssignedRecruiter)
|
||||
declare assignee: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeTimestamp(), contact.string.CreatedDate)
|
||||
@ReadOnly()
|
||||
createOn!: Timestamp
|
||||
}
|
||||
|
||||
@Model(recruit.class.ApplicantMatch, core.class.AttachedDoc, DOMAIN_TASK)
|
||||
@@ -629,6 +624,7 @@ export function createModel (builder: Builder): void {
|
||||
orderBy: [
|
||||
['state', SortingOrder.Ascending],
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['createOn', SortingOrder.Descending],
|
||||
['dueDate', SortingOrder.Ascending],
|
||||
['rank', SortingOrder.Ascending]
|
||||
],
|
||||
|
||||
@@ -20,7 +20,6 @@ import core, {
|
||||
DOMAIN_TX,
|
||||
Ref,
|
||||
Space,
|
||||
TxCollectionCUD,
|
||||
TxCreateDoc,
|
||||
TxFactory,
|
||||
TxOperations,
|
||||
@@ -31,8 +30,8 @@ import { DOMAIN_CALENDAR } from '@hcengineering/model-calendar'
|
||||
import contact, { DOMAIN_CONTACT } from '@hcengineering/model-contact'
|
||||
import { DOMAIN_SPACE } from '@hcengineering/model-core'
|
||||
import tags, { TagCategory } from '@hcengineering/model-tags'
|
||||
import { createKanbanTemplate, createSequence, DOMAIN_KANBAN, DOMAIN_TASK } from '@hcengineering/model-task'
|
||||
import { Applicant, Candidate, Vacancy } from '@hcengineering/recruit'
|
||||
import { createKanbanTemplate, createSequence, DOMAIN_KANBAN } from '@hcengineering/model-task'
|
||||
import { Vacancy } from '@hcengineering/recruit'
|
||||
import task, { KanbanTemplate, Sequence } from '@hcengineering/task'
|
||||
import recruit from './plugin'
|
||||
|
||||
@@ -48,47 +47,6 @@ async function fixImportedTitle (client: MigrationClient): Promise<void> {
|
||||
)
|
||||
}
|
||||
|
||||
async function setCreate (client: MigrationClient): Promise<void> {
|
||||
while (true) {
|
||||
const docs = await client.find<Applicant>(
|
||||
DOMAIN_TASK,
|
||||
{
|
||||
_class: recruit.class.Applicant,
|
||||
createOn: { $exists: false }
|
||||
},
|
||||
{ limit: 500 }
|
||||
)
|
||||
if (docs.length === 0) break
|
||||
const txex = await client.find<TxCollectionCUD<Candidate, Applicant>>(DOMAIN_TX, {
|
||||
'tx.objectId': { $in: docs.map((it) => it._id) },
|
||||
'tx._class': core.class.TxCreateDoc
|
||||
})
|
||||
for (const doc of docs) {
|
||||
const tx = txex.find((it) => it.tx.objectId === doc._id)
|
||||
if (tx !== undefined) {
|
||||
await client.update(
|
||||
DOMAIN_TASK,
|
||||
{
|
||||
_id: doc._id
|
||||
},
|
||||
{
|
||||
createOn: tx.modifiedOn
|
||||
}
|
||||
)
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
_id: tx._id
|
||||
},
|
||||
{
|
||||
'tx.attributes.createOn': tx.modifiedOn
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fillVacancyNumbers (client: MigrationClient): Promise<void> {
|
||||
const docs = await client.find<Vacancy>(DOMAIN_SPACE, {
|
||||
_class: recruit.class.Vacancy,
|
||||
@@ -142,7 +100,6 @@ async function fillVacancyNumbers (client: MigrationClient): Promise<void> {
|
||||
|
||||
export const recruitOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient): Promise<void> {
|
||||
await setCreate(client)
|
||||
await fixImportedTitle(client)
|
||||
await fillVacancyNumbers(client)
|
||||
await client.update(
|
||||
|
||||
@@ -257,10 +257,6 @@ export class TIssue extends TAttachedDoc implements Issue {
|
||||
@Prop(Collection(tracker.class.TimeSpendReport), tracker.string.TimeSpendReports)
|
||||
reports!: number
|
||||
|
||||
@Prop(TypeTimestamp(), tracker.string.CreatedDate)
|
||||
@ReadOnly()
|
||||
createOn!: Timestamp
|
||||
|
||||
declare childInfo: IssueChildInfo[]
|
||||
}
|
||||
|
||||
@@ -1780,7 +1776,8 @@ export function createModel (builder: Builder): void {
|
||||
groupBy: ['status'],
|
||||
orderBy: [
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['targetDate', SortingOrder.Descending]
|
||||
['targetDate', SortingOrder.Descending],
|
||||
['createOn', SortingOrder.Descending]
|
||||
],
|
||||
other: []
|
||||
}
|
||||
@@ -1852,7 +1849,8 @@ export function createModel (builder: Builder): void {
|
||||
groupBy: ['lead'],
|
||||
orderBy: [
|
||||
['startDate', SortingOrder.Descending],
|
||||
['modifiedOn', SortingOrder.Descending]
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['createOn', SortingOrder.Descending]
|
||||
],
|
||||
other: []
|
||||
}
|
||||
@@ -1919,7 +1917,8 @@ export function createModel (builder: Builder): void {
|
||||
groupBy: [],
|
||||
orderBy: [
|
||||
['startDate', SortingOrder.Descending],
|
||||
['modifiedOn', SortingOrder.Descending]
|
||||
['modifiedOn', SortingOrder.Descending],
|
||||
['createOn', SortingOrder.Descending]
|
||||
],
|
||||
other: [],
|
||||
groupDepth: 1
|
||||
|
||||
@@ -15,34 +15,33 @@
|
||||
|
||||
import core, {
|
||||
Class,
|
||||
DOMAIN_STATUS,
|
||||
DOMAIN_TX,
|
||||
Doc,
|
||||
DocumentUpdate,
|
||||
DOMAIN_TX,
|
||||
generateId,
|
||||
Ref,
|
||||
SortingOrder,
|
||||
StatusCategory,
|
||||
TxCollectionCUD,
|
||||
TxCreateDoc,
|
||||
TxOperations,
|
||||
TxResult,
|
||||
TxUpdateDoc,
|
||||
DOMAIN_STATUS
|
||||
generateId
|
||||
} from '@hcengineering/core'
|
||||
import { createOrUpdate, MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient, createOrUpdate } from '@hcengineering/model'
|
||||
import { DOMAIN_SPACE } from '@hcengineering/model-core'
|
||||
import tags from '@hcengineering/tags'
|
||||
import {
|
||||
calcRank,
|
||||
genRanks,
|
||||
Issue,
|
||||
IssueStatus,
|
||||
IssueTemplate,
|
||||
IssueTemplateChild,
|
||||
Project,
|
||||
Milestone,
|
||||
MilestoneStatus,
|
||||
TimeReportDayType
|
||||
Project,
|
||||
TimeReportDayType,
|
||||
calcRank,
|
||||
genRanks
|
||||
} from '@hcengineering/tracker'
|
||||
import { DOMAIN_TRACKER } from '.'
|
||||
import tracker from './plugin'
|
||||
@@ -851,59 +850,6 @@ async function renameProject (client: MigrationClient): Promise<void> {
|
||||
)
|
||||
}
|
||||
|
||||
async function setCreate (client: MigrationClient): Promise<void> {
|
||||
while (true) {
|
||||
const docs = await client.find<Issue>(
|
||||
DOMAIN_TRACKER,
|
||||
{
|
||||
_class: tracker.class.Issue,
|
||||
createOn: { $exists: false }
|
||||
},
|
||||
{ limit: 500 }
|
||||
)
|
||||
if (docs.length === 0) {
|
||||
break
|
||||
}
|
||||
const creates = await client.find<TxCollectionCUD<Issue, Issue>>(DOMAIN_TX, {
|
||||
'tx.objectId': { $in: docs.map((it) => it._id) },
|
||||
'tx._class': core.class.TxCreateDoc
|
||||
})
|
||||
for (const doc of docs) {
|
||||
const tx = creates.find((it) => it.tx.objectId === doc._id)
|
||||
if (tx !== undefined) {
|
||||
await client.update(
|
||||
DOMAIN_TRACKER,
|
||||
{
|
||||
_id: doc._id
|
||||
},
|
||||
{
|
||||
createOn: tx.modifiedOn
|
||||
}
|
||||
)
|
||||
await client.update(
|
||||
DOMAIN_TX,
|
||||
{
|
||||
_id: tx._id
|
||||
},
|
||||
{
|
||||
'tx.attributes.createOn': tx.modifiedOn
|
||||
}
|
||||
)
|
||||
} else {
|
||||
await client.update(
|
||||
DOMAIN_TRACKER,
|
||||
{
|
||||
_id: doc._id
|
||||
},
|
||||
{
|
||||
createOn: doc.modifiedOn
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fixMilestoneEmptyStatuses (client: MigrationClient): Promise<void> {
|
||||
await client.update<Milestone>(
|
||||
DOMAIN_TRACKER,
|
||||
@@ -928,7 +874,6 @@ export const trackerOperation: MigrateOperation = {
|
||||
await fillRank(client)
|
||||
await renameSprintToMilestone(client)
|
||||
await renameProject(client)
|
||||
await setCreate(client)
|
||||
|
||||
// Move all status objects into status domain
|
||||
await client.move(
|
||||
|
||||
@@ -56,7 +56,8 @@ export interface Doc extends Obj {
|
||||
space: Ref<Space>
|
||||
modifiedOn: Timestamp
|
||||
modifiedBy: Ref<Account>
|
||||
createdBy?: Ref<Account>
|
||||
createdBy?: Ref<Account> // Marked as optional since it will be filled by platform.
|
||||
createOn?: Timestamp // Marked as optional since it will be filled by platform.
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -259,7 +259,16 @@ async function loadModel (
|
||||
): Promise<Timestamp> {
|
||||
const t = Date.now()
|
||||
|
||||
const atxes = await conn.loadModel(lastTxTime)
|
||||
let atxes = []
|
||||
try {
|
||||
atxes = await conn.loadModel(lastTxTime)
|
||||
} catch (err: any) {
|
||||
atxes = await conn.findAll(
|
||||
core.class.Tx,
|
||||
{ objectSpace: core.space.Model },
|
||||
{ sort: { _id: SortingOrder.Ascending, modifiedOn: SortingOrder.Ascending } }
|
||||
)
|
||||
}
|
||||
|
||||
if (reload && atxes.length > modelTransactionThreshold) {
|
||||
return -1
|
||||
|
||||
@@ -172,6 +172,7 @@ export default plugin(coreId, {
|
||||
Object: '' as IntlString,
|
||||
System: '' as IntlString,
|
||||
CreatedBy: '' as IntlString,
|
||||
CreatedDate: '' as IntlString,
|
||||
Status: '' as IntlString,
|
||||
Account: '' as IntlString,
|
||||
StatusCategory: '' as IntlString
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"Object": "Object",
|
||||
"System": "System",
|
||||
"CreatedBy": "Created by",
|
||||
"CreatedDate": "Created date",
|
||||
"Status": "Status",
|
||||
"StatusCategory": "Status category",
|
||||
"Account": "Account"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"Object": "Объект",
|
||||
"System": "Система",
|
||||
"CreatedBy": "Создан",
|
||||
"CreatedDate": "Дата создания",
|
||||
"Status": "Статус",
|
||||
"StatusCategory": "Категория статуса",
|
||||
"Account": "Аккаунт"
|
||||
|
||||
@@ -353,7 +353,8 @@ export abstract class TxProcessor implements WithTx {
|
||||
space: tx.objectSpace,
|
||||
modifiedBy: tx.modifiedBy,
|
||||
modifiedOn: tx.modifiedOn,
|
||||
createdBy: tx.createdBy ?? tx.modifiedBy
|
||||
createdBy: tx.createdBy ?? tx.modifiedBy,
|
||||
createOn: tx.createOn ?? tx.modifiedBy
|
||||
} as T
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ export async function createApplication (
|
||||
...data,
|
||||
state: state._id,
|
||||
number: (incResult as any).object.sequence,
|
||||
rank: calcRank(lastOne, undefined),
|
||||
createOn: Date.now()
|
||||
rank: calcRank(lastOne, undefined)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -940,8 +940,7 @@ async function synchronizeUsers (
|
||||
name: combineName(u.NAME, u.LAST_NAME),
|
||||
avatar: u.PERSONAL_PHOTO,
|
||||
active: u.ACTIVE,
|
||||
city: u.PERSONAL_CITY,
|
||||
createOn: Date.now()
|
||||
city: u.PERSONAL_CITY
|
||||
})
|
||||
accountId = await ops.client.createDoc(contact.class.EmployeeAccount, core.space.Model, {
|
||||
email: u.EMAIL,
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
if (docUpdate === undefined || lastView === undefined) return -1
|
||||
for (let index = 0; index < messages.length; index++) {
|
||||
const message = messages[index]
|
||||
if (message.createOn >= lastView) return index
|
||||
if ((message.createOn ?? 0) >= lastView) return index
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@@ -209,7 +209,7 @@
|
||||
{#if newMessagesPos === i}
|
||||
<ChannelSeparator title={chunter.string.New} line reverse isNew />
|
||||
{/if}
|
||||
{#if i === 0 || isOtherDay(message.createOn, messages[i - 1].createOn)}
|
||||
{#if i === 0 || isOtherDay(message.createOn ?? 0, messages[i - 1].createOn ?? 0)}
|
||||
<JumpToDateSelector selectedDate={message.createOn} on:jumpToDate={handleJumpToDate} />
|
||||
{/if}
|
||||
<MessageComponent
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||
import { AttachmentRefInput } from '@hcengineering/attachment-resources'
|
||||
import { ChunterMessage, ChunterSpace, Message } from '@hcengineering/chunter'
|
||||
import { generateId, getCurrentAccount, Ref, Space } from '@hcengineering/core'
|
||||
import { Ref, Space, generateId, getCurrentAccount } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { location, navigate } from '@hcengineering/ui'
|
||||
import { get } from 'svelte/store'
|
||||
@@ -44,7 +44,6 @@
|
||||
'messages',
|
||||
{
|
||||
content: message,
|
||||
createOn: Date.now(),
|
||||
createBy: me,
|
||||
attachments
|
||||
},
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
{#if employee}
|
||||
<EmployeePresenter value={employee} shouldShowAvatar={false} inline />
|
||||
{/if}
|
||||
<span>{getTime(message.createOn)}</span>
|
||||
<span>{getTime(message.createOn ?? 0)}</span>
|
||||
{#if message.editedOn}
|
||||
<span use:tooltip={{ label: ui.string.TimeTooltip, props: { value: getTime(message.editedOn) } }}>
|
||||
<Label label={chunter.string.Edited} />
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<MessageViewer message={message.content} />
|
||||
<span class="time">{getTime(message.createOn)}</span>
|
||||
<span class="time">{getTime(message.createOn ?? 0)}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -131,7 +131,6 @@
|
||||
collection: 'repliesCount',
|
||||
content: message,
|
||||
createBy: me,
|
||||
createOn: 0,
|
||||
attachments
|
||||
},
|
||||
commentId
|
||||
|
||||
@@ -144,7 +144,6 @@
|
||||
{
|
||||
content: message,
|
||||
createBy: me,
|
||||
createOn: Date.now(),
|
||||
attachments
|
||||
},
|
||||
commentId
|
||||
@@ -165,7 +164,7 @@
|
||||
if (docUpdate === undefined || lastView === undefined) return -1
|
||||
for (let index = 0; index < comments.length; index++) {
|
||||
const comment = comments[index]
|
||||
if (comment.createOn >= lastView) return index
|
||||
if ((comment.createOn ?? 0) >= lastView) return index
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ export interface ChunterMessage extends AttachedDoc {
|
||||
content: string
|
||||
attachments?: number
|
||||
createBy: Ref<Account>
|
||||
createOn: Timestamp
|
||||
editedOn?: Timestamp
|
||||
reactions?: number
|
||||
}
|
||||
|
||||
@@ -70,8 +70,7 @@
|
||||
"UseImage": "Attached photo",
|
||||
"UseGravatar": "Gravatar",
|
||||
"UseColor": "Color",
|
||||
"NotSpecified": "Not specified",
|
||||
"CreatedDate": "Created date",
|
||||
"NotSpecified": "Not specified",
|
||||
"Whatsapp": "Whatsapp",
|
||||
"WhatsappPlaceholder": "Whatsapp",
|
||||
"Skype": "Skype",
|
||||
|
||||
@@ -71,8 +71,7 @@
|
||||
"UseGravatar": "Граватар",
|
||||
"UseColor": "Цвет",
|
||||
"AvatarProvider": "Тип аватара",
|
||||
"NotSpecified": "Не указан",
|
||||
"CreatedDate": "Дата создания",
|
||||
"NotSpecified": "Не указан",
|
||||
"Whatsapp": "Whatsapp",
|
||||
"WhatsappPlaceholder": "Whatsapp",
|
||||
"Skype": "Skype",
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
changeEmail()
|
||||
const name = combineName(firstName, lastName)
|
||||
const person: Data<Employee> = {
|
||||
createOn: Date.now(),
|
||||
name,
|
||||
city: object.city,
|
||||
active: true
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import { Channel, combineName, findPerson, Person } from '@hcengineering/contact'
|
||||
import { AttachedData, Data, generateId } from '@hcengineering/core'
|
||||
import { Card, getClient } from '@hcengineering/presentation'
|
||||
import { EditBox, IconInfo, Label, createFocusManager, FocusHandler } from '@hcengineering/ui'
|
||||
import { createFocusManager, EditBox, FocusHandler, IconInfo, Label } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { ChannelsDropdown } from '..'
|
||||
import contact from '../plugin'
|
||||
@@ -41,7 +41,6 @@
|
||||
|
||||
async function createPerson () {
|
||||
const person: Data<Person> = {
|
||||
createOn: Date.now(),
|
||||
name: combineName(firstName, lastName),
|
||||
city: object.city
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
'tx.attributes.incoming': false
|
||||
},
|
||||
(res) => {
|
||||
const filtered = res.filter((p) => (p.tx as TxCreateDoc<ChannelItem>).attributes.sendOn >= object.createOn)
|
||||
const filtered = res.filter((p) => (p.tx as TxCreateDoc<ChannelItem>).attributes.sendOn >= (object.createOn ?? 0))
|
||||
newTxes = createDisplayTxes(filtered)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -101,7 +101,6 @@ export interface Contact extends Doc {
|
||||
comments?: number
|
||||
channels?: number
|
||||
city: string
|
||||
createOn: Timestamp
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,8 +61,7 @@
|
||||
async function createCustomer () {
|
||||
const candidate: Data<Contact> = {
|
||||
name: formatName(targetClass._id, firstName, lastName, object.name),
|
||||
city: object.city,
|
||||
createOn: Date.now()
|
||||
city: object.city
|
||||
}
|
||||
if (avatar !== undefined) {
|
||||
candidate.avatar = await avatarEditor.createAvatar()
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
modifiedOn: Date.now(),
|
||||
modifiedBy: '' as Ref<Account>,
|
||||
startDate: null,
|
||||
dueDate: null,
|
||||
createOn: Date.now()
|
||||
dueDate: null
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@@ -149,8 +148,7 @@
|
||||
assignee: doc.assignee,
|
||||
rank: calcRank(lastOne, undefined),
|
||||
startDate: null,
|
||||
dueDate: null,
|
||||
createOn: Date.now()
|
||||
dueDate: null
|
||||
},
|
||||
doc._id
|
||||
)
|
||||
@@ -182,8 +180,7 @@
|
||||
modifiedOn: Date.now(),
|
||||
modifiedBy: '' as Ref<Account>,
|
||||
startDate: null,
|
||||
dueDate: null,
|
||||
createOn: Date.now()
|
||||
dueDate: null
|
||||
}
|
||||
fillDefaults(hierarchy, doc, recruit.class.Applicant)
|
||||
}
|
||||
|
||||
@@ -174,8 +174,7 @@
|
||||
const candidate: Data<Person> = {
|
||||
name: combineName(object.firstName ?? '', object.lastName ?? ''),
|
||||
city: object.city,
|
||||
channels: 0,
|
||||
createOn: Date.now()
|
||||
channels: 0
|
||||
}
|
||||
if (avatar !== undefined) {
|
||||
candidate.avatar = await avatarEditor.createAvatar()
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
estimation: template.estimation,
|
||||
reports: 0,
|
||||
relations: [{ _id: id, _class: recruit.class.Vacancy }],
|
||||
childInfo: [],
|
||||
createOn: Date.now()
|
||||
childInfo: []
|
||||
})
|
||||
if ((template.labels?.length ?? 0) > 0) {
|
||||
const tagElements = await client.findAll(tags.class.TagElement, { _id: { $in: template.labels } })
|
||||
|
||||
@@ -89,7 +89,6 @@ export interface Applicant extends Task {
|
||||
attachedTo: Ref<Candidate>
|
||||
attachments?: number
|
||||
comments?: number
|
||||
createOn: Timestamp
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -270,7 +270,6 @@
|
||||
|
||||
"SevenHoursLength": "Seven Hours",
|
||||
"EightHoursLength": "Eight Hours",
|
||||
"CreatedDate": "Created date",
|
||||
"HourLabel": "h",
|
||||
"Saved": "Saved...",
|
||||
"CreatedIssue": "Created issue",
|
||||
|
||||
@@ -270,7 +270,6 @@
|
||||
|
||||
"SevenHoursLength": "Семь Часов",
|
||||
"EightHoursLength": "Восемь Часов",
|
||||
"CreatedDate": "Дата создания",
|
||||
"HourLabel": "ч",
|
||||
"Saved": "Сохранено...",
|
||||
"CreatedIssue": "Создал(а) задачу",
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
IssuePriority,
|
||||
IssueStatus,
|
||||
IssueTemplate,
|
||||
Project,
|
||||
Milestone
|
||||
Milestone,
|
||||
Project
|
||||
} from '@hcengineering/tracker'
|
||||
import {
|
||||
ActionIcon,
|
||||
@@ -67,9 +67,9 @@
|
||||
import PriorityEditor from './issues/PriorityEditor.svelte'
|
||||
import StatusEditor from './issues/StatusEditor.svelte'
|
||||
import EstimationEditor from './issues/timereport/EstimationEditor.svelte'
|
||||
import MilestoneSelector from './milestones/MilestoneSelector.svelte'
|
||||
import SetDueDateActionPopup from './SetDueDateActionPopup.svelte'
|
||||
import SetParentIssueActionPopup from './SetParentIssueActionPopup.svelte'
|
||||
import MilestoneSelector from './milestones/MilestoneSelector.svelte'
|
||||
import SubIssues from './SubIssues.svelte'
|
||||
|
||||
export let space: Ref<Project>
|
||||
@@ -354,8 +354,7 @@
|
||||
estimation: object.estimation,
|
||||
reports: 0,
|
||||
relations: relatedTo !== undefined ? [{ _id: relatedTo._id, _class: relatedTo._class }] : [],
|
||||
childInfo: [],
|
||||
createOn: Date.now()
|
||||
childInfo: []
|
||||
}
|
||||
|
||||
await client.addCollection(
|
||||
|
||||
@@ -94,8 +94,7 @@
|
||||
estimation: subIssue.estimation,
|
||||
reports: 0,
|
||||
relations: [],
|
||||
childInfo: [],
|
||||
createOn: Date.now()
|
||||
childInfo: []
|
||||
}
|
||||
|
||||
await client.addCollection(
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
const config: [string, IntlString, object][] = [
|
||||
['assigned', tracker.string.Assigned, {}],
|
||||
['created', tracker.string.Created, {}],
|
||||
['created', tracker.string.Created, { value: 2 }],
|
||||
['subscribed', tracker.string.Subscribed, {}]
|
||||
]
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
|
||||
@@ -173,8 +173,6 @@ export interface Issue extends AttachedDoc {
|
||||
|
||||
childInfo: IssueChildInfo[]
|
||||
|
||||
createOn: Timestamp
|
||||
|
||||
template?: {
|
||||
// A template issue is based on
|
||||
template: Ref<IssueTemplate>
|
||||
|
||||
@@ -184,7 +184,7 @@ async function ThreadMessageDelete (tx: Tx, control: TriggerControl): Promise<Tx
|
||||
comment.attachedTo,
|
||||
{
|
||||
replies: comments.map((comm) => (control.modelDb.getObject(comm.createBy) as EmployeeAccount).employee),
|
||||
lastReply: comments.length > 0 ? Math.max(...comments.map((comm) => comm.createOn)) : undefined
|
||||
lastReply: comments.length > 0 ? Math.max(...comments.map((comm) => comm.createOn ?? comm.modifiedOn)) : undefined
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -623,8 +623,7 @@ async function createEmployee (ops: TxOperations, name: string, email: string):
|
||||
name,
|
||||
city: '',
|
||||
...(hasGravatar ? { avatar: `${AvatarType.GRAVATAR}://${gravatarId}` } : {}),
|
||||
active: true,
|
||||
createOn: Date.now()
|
||||
active: true
|
||||
})
|
||||
if (!hasGravatar) {
|
||||
await ops.updateDoc(contact.class.Employee, contact.space.Employee, id, {
|
||||
|
||||
@@ -198,11 +198,13 @@ export async function backup (transactorUrl: string, workspaceId: WorkspaceId, s
|
||||
const connection = (await connect(transactorUrl, workspaceId, undefined, {
|
||||
mode: 'backup'
|
||||
})) as unknown as CoreClient & BackupClient
|
||||
console.log('starting backup')
|
||||
try {
|
||||
const domains = connection
|
||||
.getHierarchy()
|
||||
.domains()
|
||||
.filter((it) => it !== DOMAIN_TRANSIENT && it !== DOMAIN_MODEL)
|
||||
console.log('domains for dump', domains.length)
|
||||
|
||||
let backupInfo: BackupInfo = {
|
||||
workspace: workspaceId.name,
|
||||
@@ -431,7 +433,10 @@ export async function backup (transactorUrl: string, workspaceId: WorkspaceId, s
|
||||
}
|
||||
|
||||
await storage.writeFile(infoFile, gzipSync(JSON.stringify(backupInfo, undefined, 2)))
|
||||
} catch (err: any) {
|
||||
console.error(err)
|
||||
} finally {
|
||||
console.log('end backup')
|
||||
await connection.close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import core, {
|
||||
AttachedDoc,
|
||||
Doc,
|
||||
MeasureContext,
|
||||
ServerStorage,
|
||||
Timestamp,
|
||||
Tx,
|
||||
TxCollectionCUD,
|
||||
TxCreateDoc
|
||||
} from '@hcengineering/core'
|
||||
import core, { MeasureContext, ServerStorage, Tx } from '@hcengineering/core'
|
||||
import { BroadcastFunc, Middleware, SessionContext, TxMiddlewareResult } from '@hcengineering/server-core'
|
||||
import { BaseMiddleware } from './base'
|
||||
|
||||
@@ -46,24 +37,7 @@ export class ModifiedMiddleware extends BaseMiddleware implements Middleware {
|
||||
async tx (ctx: SessionContext, tx: Tx): Promise<TxMiddlewareResult> {
|
||||
if (tx.modifiedBy !== core.account.System) {
|
||||
tx.modifiedOn = Date.now()
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = tx as TxCreateDoc<Doc & { createOn: Timestamp }>
|
||||
const hasCreateOn = this.storage.hierarchy.findAttribute(createTx.objectClass, 'createOn')
|
||||
if (hasCreateOn !== undefined) {
|
||||
createTx.attributes.createOn = tx.modifiedOn
|
||||
}
|
||||
}
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCollectionCUD)) {
|
||||
const coltx = tx as TxCollectionCUD<Doc, AttachedDoc>
|
||||
coltx.tx.modifiedOn = tx.modifiedOn
|
||||
if (this.storage.hierarchy.isDerived(coltx.tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = coltx.tx as TxCreateDoc<AttachedDoc & { createOn: Timestamp }>
|
||||
const hasCreateOn = this.storage.hierarchy.findAttribute(createTx.objectClass, 'createOn')
|
||||
if (hasCreateOn !== undefined) {
|
||||
createTx.attributes.createOn = tx.modifiedOn
|
||||
}
|
||||
}
|
||||
}
|
||||
tx.createOn = tx.createOn ?? tx.modifiedOn
|
||||
}
|
||||
return await this.provideTx(ctx, tx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user