Merge branch 'staging' into develop

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2025-02-19 14:12:43 +07:00
14 changed files with 140 additions and 64 deletions
+16 -6
View File
@@ -16,7 +16,7 @@
import activity from '@hcengineering/activity'
import notification, { type NotificationType } from '@hcengineering/notification'
import { type Asset, type IntlString } from '@hcengineering/platform'
import type { BuildModelKey, Viewlet, ViewletDescriptor } from '@hcengineering/view'
import type { BuildModelKey, KeyFilterPreset, Viewlet, ViewletDescriptor } from '@hcengineering/view'
import questions from '@hcengineering/model-questions'
import contact from '@hcengineering/contact'
import tracker from '@hcengineering/model-tracker'
@@ -659,9 +659,19 @@ function defineTrainingAttempt (builder: Builder): void {
sortingKey: 'state',
displayProps: { align: 'center' }
}
const columnOwner: BuildModelKey = {
...columns.owner,
key: 'owner'
const columnTrainee: BuildModelKey = {
key: 'owner',
label: training.string.TrainingRequestTrainee,
presenter: contacts.component.EmployeePresenter,
props: { shouldShowName: true },
displayProps: { align: 'center' }
}
const columnTraineeFilter: KeyFilterPreset = {
_class: training.class.TrainingAttempt,
component: contacts.component.EmployeeFilter,
key: 'owner',
label: training.string.TrainingRequestTrainee
}
defineTableBrowserViewletDescriptor(
@@ -693,7 +703,7 @@ function defineTrainingAttempt (builder: Builder): void {
columnScore,
'createdOn',
'submittedOn',
columnOwner
columnTrainee
],
configOptions: {
strict: true,
@@ -720,7 +730,7 @@ function defineTrainingAttempt (builder: Builder): void {
})
builder.mixin(training.class.TrainingAttempt, core.class.Class, view.mixin.ClassFilters, {
filters: ['state', 'owner', 'submittedOn'] as Array<keyof TrainingAttempt>,
filters: ['state', 'submittedOn', columnTraineeFilter] as Array<keyof TrainingAttempt>,
strict: true
})
@@ -13,37 +13,43 @@
// limitations under the License.
-->
<script lang="ts">
import { generateId } from '@hcengineering/core'
import { Doc, generateId, Ref } from '@hcengineering/core'
import { ViewContext } from '@hcengineering/view'
import { onDestroy } from 'svelte'
import { ContextStore, contextStore } from '../context'
interface ViewContextWithId extends ViewContext {
id?: Ref<Doc>
}
export let context: ViewContext
const id = generateId()
$: len = $contextStore.contexts.findIndex((it) => (it as any).id === id)
onDestroy(() => {
contextStore.update((t) => {
return new ContextStore(t.contexts.slice(0, len ?? 0))
contextStore.update((cur) => {
const contexts = cur.contexts as ViewContextWithId[]
const pos = contexts.findIndex((it) => it.id === id)
if (pos === -1) {
return cur
}
return new ContextStore(contexts.slice(0, pos))
})
})
$: {
contextStore.update((cur) => {
const pos = cur.contexts.findIndex((it) => (it as any).id === id)
const newCur = {
const contexts = cur.contexts as ViewContextWithId[]
const pos = contexts.findIndex((it) => it.id === id)
const newCur: ViewContextWithId = {
id,
mode: context.mode,
application: context.application ?? cur.contexts[(pos !== -1 ? pos : cur.contexts.length) - 1]?.application
application: context.application ?? contexts[(pos !== -1 ? pos : contexts.length) - 1]?.application
}
if (pos === -1) {
len = cur.contexts.length
return new ContextStore([...cur.contexts, newCur])
return new ContextStore([...contexts, newCur])
}
len = pos
return new ContextStore([...cur.contexts.slice(0, pos), newCur])
return new ContextStore(contexts.map((it) => (it.id === id ? newCur : it)))
})
}
</script>
+1 -1
View File
@@ -56,7 +56,7 @@ export const DefaultKit = Extension.create<DefaultKitOptions>({
}),
Typography.configure({}),
Link.extend({ inclusive: false }).configure({
openOnClick: true,
openOnClick: false,
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
})
]
+3 -3
View File
@@ -68,9 +68,9 @@
--text-editor-selected-node-background: rgba(43, 81, 144, 0.1);
--text-editor-selected-node-color: #93CAF3;
--text-editor-highlighted-node-warning-active-background-color: #F2D7AE;
--text-editor-highlighted-node-warning-background-color: #F8EBD7;
--text-editor-highlighted-node-warning-border-color: #DE9B35;
--text-editor-highlighted-node-warning-active-background-color: rgba(255, 203, 0, .24);
--text-editor-highlighted-node-warning-background-color: rgba(255, 203, 0, .12);
--text-editor-highlighted-node-warning-border-color: rgba(255, 203, 0, .35);
--text-editor-highlighted-node-add-background-color: #DAEDDC;
--text-editor-highlighted-node-add-font-color: #1C4220;
+3 -1
View File
@@ -323,7 +323,9 @@
.text-editor-highlighted-node-warning {
background-color: var(--text-editor-highlighted-node-warning-background-color);
border-bottom: 0.0625rem solid var(--text-editor-highlighted-node-warning-border-color);
border-bottom: 2px solid var(--text-editor-highlighted-node-warning-border-color);
padding-bottom: 2px;
transition: background 0.2s ease, border 0.2s ease;
&.text-editor-highlighted-node-selected, &:hover {
background-color: var(--text-editor-highlighted-node-warning-active-background-color);
@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="checkmark-circle" viewBox="0 0 20 20">
<path d="M10 1.25C8.26942 1.25 6.57769 1.76318 5.13876 2.72464C3.69983 3.6861 2.57832 5.05267 1.91606 6.65152C1.25379 8.25037 1.08051 10.0097 1.41813 11.707C1.75575 13.4044 2.58911 14.9635 3.81282 16.1872C5.03653 17.4109 6.59563 18.2442 8.29296 18.5819C9.9903 18.9195 11.7496 18.7462 13.3485 18.0839C14.9473 17.4217 16.3139 16.3002 17.2754 14.8612C18.2368 13.4223 18.75 11.7306 18.75 10C18.75 7.67936 17.8281 5.45376 16.1872 3.81282C14.5462 2.17187 12.3206 1.25 10 1.25ZM10 17.5C8.51664 17.5 7.0666 17.0601 5.83323 16.236C4.59986 15.4119 3.63856 14.2406 3.07091 12.8701C2.50325 11.4997 2.35473 9.99168 2.64411 8.53682C2.9335 7.08197 3.64781 5.74559 4.6967 4.6967C5.7456 3.64781 7.08197 2.9335 8.53683 2.64411C9.99168 2.35472 11.4997 2.50325 12.8701 3.0709C14.2406 3.63856 15.4119 4.59985 16.236 5.83322C17.0601 7.06659 17.5 8.51664 17.5 10C17.5 11.9891 16.7098 13.8968 15.3033 15.3033C13.8968 16.7098 11.9891 17.5 10 17.5Z" fill="black" fill-opacity="0.8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1919 7.05821C14.436 7.30229 14.436 7.69802 14.1919 7.94209L9.19194 12.9421C8.94786 13.1862 8.55214 13.1862 8.30806 12.9421L5.80806 10.4421C5.56398 10.198 5.56398 9.80229 5.80806 9.55821C6.05214 9.31413 6.44786 9.31413 6.69194 9.55821L8.75 11.6163L13.3081 7.05821C13.5521 6.81413 13.9479 6.81413 14.1919 7.05821Z" fill="black" fill-opacity="0.8"/>
<path d="M10 1.25C8.26942 1.25 6.57769 1.76318 5.13876 2.72464C3.69983 3.6861 2.57832 5.05267 1.91606 6.65152C1.25379 8.25037 1.08051 10.0097 1.41813 11.707C1.75575 13.4044 2.58911 14.9635 3.81282 16.1872C5.03653 17.4109 6.59563 18.2442 8.29296 18.5819C9.9903 18.9195 11.7496 18.7462 13.3485 18.0839C14.9473 17.4217 16.3139 16.3002 17.2754 14.8612C18.2368 13.4223 18.75 11.7306 18.75 10C18.75 7.67936 17.8281 5.45376 16.1872 3.81282C14.5462 2.17187 12.3206 1.25 10 1.25ZM10 17.5C8.51664 17.5 7.0666 17.0601 5.83323 16.236C4.59986 15.4119 3.63856 14.2406 3.07091 12.8701C2.50325 11.4997 2.35473 9.99168 2.64411 8.53682C2.9335 7.08197 3.64781 5.74559 4.6967 4.6967C5.7456 3.64781 7.08197 2.9335 8.53683 2.64411C9.99168 2.35472 11.4997 2.50325 12.8701 3.0709C14.2406 3.63856 15.4119 4.59985 16.236 5.83322C17.0601 7.06659 17.5 8.51664 17.5 10C17.5 11.9891 16.7098 13.8968 15.3033 15.3033C13.8968 16.7098 11.9891 17.5 10 17.5Z" fill="currentColor" fill-opacity="0.8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1919 7.05821C14.436 7.30229 14.436 7.69802 14.1919 7.94209L9.19194 12.9421C8.94786 13.1862 8.55214 13.1862 8.30806 12.9421L5.80806 10.4421C5.56398 10.198 5.56398 9.80229 5.80806 9.55821C6.05214 9.31413 6.44786 9.31413 6.69194 9.55821L8.75 11.6163L13.3081 7.05821C13.5521 6.81413 13.9479 6.81413 14.1919 7.05821Z" fill="currentColor" fill-opacity="0.8"/>
</symbol>
<symbol id="documentapplication" viewBox="0 0 32 32">
<path d="M10 14C9.44772 14 9 14.4477 9 15C9 15.5523 9.44772 16 10 16H22C22.5523 16 23 15.5523 23 15C23 14.4477 22.5523 14 22 14H10Z"/>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

@@ -20,7 +20,7 @@
import { getClient } from '@hcengineering/presentation'
import view from '@hcengineering/view'
import attachment, { Attachment } from '@hcengineering/attachment'
import documents from '@hcengineering/controlled-documents'
import documents, { DocumentState } from '@hcengineering/controlled-documents'
import { Editor, Heading } from '@hcengineering/text-editor'
import {
CollaboratorEditor,
@@ -34,8 +34,9 @@
highlightUpdateCommand,
getNodeElement
} from '@hcengineering/text-editor-resources'
import { navigate, EditBox, Scroller } from '@hcengineering/ui'
import { navigate, EditBox, Scroller, Label } from '@hcengineering/ui'
import { getCollaborationUser, getObjectLinkFragment } from '@hcengineering/view-resources'
import plugin from '../../plugin'
import {
$areDocumentCommentPopupsOpened as areDocumentCommentPopupsOpened,
@@ -248,7 +249,7 @@
<TableOfContents items={headings} enumerated={true} on:select={(ev) => handleShowHeading(ev.detail)} />
</div>
<Scroller>
<div class="content">
<div class="content relative">
<DocumentTitle>
{#if $isEditable}
<EditBox
@@ -262,6 +263,13 @@
{$controlledDocument.title}
{/if}
</DocumentTitle>
{#if $controlledDocument.state === DocumentState.Obsolete}
<div class="watermark-container">
{#each { length: 24 } as _, i}
<div class="watermark"><Label label={plugin.string.Obsolete} /></div>
{/each}
</div>
{/if}
<CollaboratorEditor
bind:this={textEditor}
object={$controlledDocument}
@@ -351,6 +359,34 @@
}
.bottomSpacing {
padding-bottom: 30vh;
padding-bottom: 55vh;
}
.watermark-container {
position: absolute;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
gap: 35rem;
padding-top: 20rem;
overflow: hidden;
pointer-events: none;
}
.watermark {
z-index: 100;
margin: auto;
height: 4rem;
width: 100%;
color: var(--theme-divider-color);
font-size: 8rem;
transform: rotate(-45deg);
display: flex;
align-items: center;
justify-content: center;
}
</style>
@@ -58,33 +58,33 @@
const client = getClient()
async function changePlannedEffectiveDate (plannedEffectiveDate: Timestamp) {
if (!$controlledDocument) {
return
}
// async function changePlannedEffectiveDate (plannedEffectiveDate: Timestamp) {
// if (!$controlledDocument) {
// return
// }
await client.update($controlledDocument, { plannedEffectiveDate })
}
// await client.update($controlledDocument, { plannedEffectiveDate })
// }
let selectedDate: Timestamp =
$controlledDocument?.plannedEffectiveDate != null && $controlledDocument?.plannedEffectiveDate > 0
? $controlledDocument.plannedEffectiveDate
: Date.now()
// let selectedDate: Timestamp =
// $controlledDocument?.plannedEffectiveDate != null && $controlledDocument?.plannedEffectiveDate > 0
// ? $controlledDocument.plannedEffectiveDate
// : Date.now()
let selected: IntlString | undefined = undefined
if ($controlledDocument?.plannedEffectiveDate === 0) {
selected = documentsRes.string.EffectiveImmediately
} else if ($controlledDocument?.plannedEffectiveDate != null) {
selected = documentsRes.string.EffectiveOn
}
// let selected: IntlString | undefined = undefined
// if ($controlledDocument?.plannedEffectiveDate === 0) {
// selected = documentsRes.string.EffectiveImmediately
// } else if ($controlledDocument?.plannedEffectiveDate != null) {
// selected = documentsRes.string.EffectiveOn
// }
async function changeSelectedDate (ev: CustomEvent) {
if (ev.detail !== undefined) {
selectedDate = ev.detail
await changePlannedEffectiveDate(ev.detail)
selected = documentsRes.string.EffectiveOn
}
}
// async function changeSelectedDate (ev: CustomEvent) {
// if (ev.detail !== undefined) {
// selectedDate = ev.detail
// await changePlannedEffectiveDate(ev.detail)
// selected = documentsRes.string.EffectiveOn
// }
// }
const reviewIntervals: DropdownTextItem[] = []
for (const interval of periodicReviewIntervals) {
@@ -254,10 +254,10 @@
gap="none"
/>
</div>
<header class="fs-title text-lg my-4">
<header class="fs-title text-lg mt-4">
<Label label={documentsRes.string.EffectiveDocumentLifecycle} />
</header>
<span class="fs-title text-normal">
<!-- <span class="fs-title text-normal">
<Label label={documentsRes.string.EffectiveDate} />
</span>
<div>
@@ -298,7 +298,7 @@
</div>
</RadioButton>
</div>
</div>
</div> -->
<div class="flex-row-center flex-gap-2">
<span class="whitespace-nowrap fs-title text-normal">
<Label label={documentsRes.string.PeriodicReviewToBeCompleted} />
@@ -54,7 +54,7 @@
$controlledDocument != null &&
(isOrgSpace
? $controlledDocument.state !== DocumentState.Effective
: ![DocumentState.Effective, DocumentState.Obsolete, DocumentState.Archived].includes($controlledDocument.state))
: ![DocumentState.Effective, DocumentState.Archived].includes($controlledDocument.state))
</script>
{#if $controlledDocument !== null}
@@ -17,8 +17,7 @@
.theme-dark {
--theme-docs-contrast-color: #ffffff;
--theme-docs-description-border-color: rgba(0, 0, 0, 0.2);
--theme-docs-frozen-description-color: #e7f2f3;
--theme-docs-comment-highlighted-color: #fefbf1;
--theme-docs-comment-highlighted-color: var(--theme-comp-header-color);
--theme-docs-warning-color: rgba(222, 155, 53, 0.08);
--theme-docs-warning-icon-color: #d27540;
--theme-docs-accepted-color: #38833f;
@@ -28,8 +27,7 @@
.theme-light {
--theme-docs-contrast-color: #000000;
--theme-docs-description-border-color: rgba(0, 0, 0, 0.2);
--theme-docs-frozen-description-color: #e7f2f3;
--theme-docs-comment-highlighted-color: #fefbf1;
--theme-docs-comment-highlighted-color: var(--theme-comp-header-color);
--theme-docs-warning-color: rgba(222, 155, 53, 0.08);
--theme-docs-warning-icon-color: #d27540;
--theme-docs-accepted-color: #38833f;
@@ -15,6 +15,8 @@
import { showPopup } from '@hcengineering/ui'
import { Extension } from '@tiptap/core'
import { type MarkType } from '@tiptap/pm/model'
import { Plugin, PluginKey } from '@tiptap/pm/state'
import LinkPopup from '../LinkPopup.svelte'
export const LinkUtilsExtension = Extension.create<any>({
@@ -42,6 +44,28 @@ export const LinkUtilsExtension = Extension.create<any>({
},
addProseMirrorPlugins () {
return []
return [LinkClickHandlerPlugin({ type: this.editor.schema.marks.link })]
}
})
interface LinkClickHandlerOptions {
type: MarkType
}
export function LinkClickHandlerPlugin (options: LinkClickHandlerOptions): Plugin {
return new Plugin({
key: new PluginKey('handleClickLink'),
props: {
handleClick: (view, pos, event) => {
const $pos = view.state.doc.resolve(pos)
const link = options.type.isInSet($pos.marks())
if (typeof link?.attrs.href === 'string') {
window.open(link.attrs.href, link.attrs.target)
return true
}
return false
}
}
})
}
@@ -363,7 +363,7 @@ export async function getReferenceFromUrl (text: string): Promise<ReferenceNodeP
const _id: Ref<Doc> | undefined =
linkProvider !== undefined ? (await (await getResource(linkProvider.decode))(id)) ?? id : id
const label = await getReferenceLabel(objectclass, id)
const label = await getReferenceLabel(objectclass, _id)
if (label === '') return
return {
@@ -62,7 +62,7 @@ export const DefaultKit = Extension.create<DefaultKitOptions>({
}),
Typography.configure({}),
Link.extend({ inclusive: false }).configure({
openOnClick: true,
openOnClick: false,
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
}),
CodeBlockHighlighExtension.configure(codeBlockHighlightOptions)
@@ -581,7 +581,7 @@ test.describe('QMS. Documents tests', () => {
})
})
test('TESTS-162. Approve document with delayed release', async ({ page }) => {
test.skip('TESTS-162. Approve document with delayed release', async ({ page }) => {
await allure.description('Requirement\nUsers need to create document with delayed release')
await allure.tms('TESTS-162', 'https://front.hc.engineering/workbench/platform/tracker/TESTS-162')
const approveDelayedDocument: NewDocument = {