Merge branch 'develop' into staging

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov
2024-11-08 16:08:04 +07:00
28 changed files with 218 additions and 84 deletions
+35 -35
View File
@@ -57,8 +57,8 @@ dependencies:
specifier: ^7.3.1
version: 7.5.1
'@playwright/test':
specifier: ^1.47.2
version: 1.47.2
specifier: ^1.48.2
version: 1.48.2
'@rush-temp/account':
specifier: file:./projects/account.tgz
version: file:projects/account.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2)
@@ -1395,11 +1395,11 @@ dependencies:
specifier: ^1.7.3
version: 1.7.4
allure-js-commons:
specifier: ^3.0.4
version: 3.0.4(allure-playwright@3.0.4)
specifier: ^3.0.6
version: 3.0.6(allure-playwright@3.0.6)
allure-playwright:
specifier: ^3.0.4
version: 3.0.4(@playwright/test@1.47.2)
specifier: ^3.0.6
version: 3.0.6(@playwright/test@1.48.2)
autolinker:
specifier: 4.0.0
version: 4.0.0
@@ -6384,12 +6384,12 @@ packages:
dev: false
optional: true
/@playwright/test@1.47.2:
resolution: {integrity: sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==}
/@playwright/test@1.48.2:
resolution: {integrity: sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==}
engines: {node: '>=18'}
hasBin: true
dependencies:
playwright: 1.47.2
playwright: 1.48.2
dev: false
/@polka/url@1.0.0-next.24:
@@ -10894,25 +10894,25 @@ packages:
require-from-string: 2.0.2
dev: false
/allure-js-commons@3.0.4(allure-playwright@3.0.4):
resolution: {integrity: sha512-/UgTzpd7a16t8WpkA/25acmkk8xwwYUK3YDeVcZb1+3+7HHZRE943ZlKxUF/LCeLrZEFgYmOtma9xmaHagSddw==}
/allure-js-commons@3.0.6(allure-playwright@3.0.6):
resolution: {integrity: sha512-q3r3Cj3sG6hR7jH8SGkfNleLJK+yFAGwzyFDGzIfu+WLZ4yeFcBZHkWuq7QreRpxvsZWNby/38jhrj5yYFwQ2g==}
peerDependencies:
allure-playwright: 3.0.4
allure-playwright: 3.0.6
peerDependenciesMeta:
allure-playwright:
optional: true
dependencies:
allure-playwright: 3.0.4(@playwright/test@1.47.2)
allure-playwright: 3.0.6(@playwright/test@1.48.2)
md5: 2.3.0
dev: false
/allure-playwright@3.0.4(@playwright/test@1.47.2):
resolution: {integrity: sha512-P2QBUZfEtqof3PLonVXcO2BdaYmWKGRDy4Ehl4dcAGsXdfS5QdrNat+DmR5BMxBNQgvf1805fGBeZh2Zn0gagQ==}
/allure-playwright@3.0.6(@playwright/test@1.48.2):
resolution: {integrity: sha512-CYhIopRjtb1LoTHD0WhH1njd6cEz0J9B+YSSAzLmI/6FP1RPZJFqAyPg/RY8c2BObxM+98T9yZzwSdZ4l3YxjQ==}
peerDependencies:
'@playwright/test': '>=1.36.0'
dependencies:
'@playwright/test': 1.47.2
allure-js-commons: 3.0.4(allure-playwright@3.0.4)
'@playwright/test': 1.48.2
allure-js-commons: 3.0.6(allure-playwright@3.0.6)
dev: false
/ansi-colors@4.1.3:
@@ -20575,18 +20575,18 @@ packages:
find-up: 3.0.0
dev: false
/playwright-core@1.47.2:
resolution: {integrity: sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==}
/playwright-core@1.48.2:
resolution: {integrity: sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==}
engines: {node: '>=18'}
hasBin: true
dev: false
/playwright@1.47.2:
resolution: {integrity: sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==}
/playwright@1.48.2:
resolution: {integrity: sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==}
engines: {node: '>=18'}
hasBin: true
dependencies:
playwright-core: 1.47.2
playwright-core: 1.48.2
optionalDependencies:
fsevents: 2.3.2
dev: false
@@ -25715,7 +25715,7 @@ packages:
dev: false
file:projects/ai-bot-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
resolution: {integrity: sha512-VUzWp9Le++agPkh/Sq5V8y1LHVSofd+WOJNwkYFDWlJH0+TKM1F88CFBANOYUlg2ZvhOQGyLCCFTcjbPohfnSQ==, tarball: file:projects/ai-bot-resources.tgz}
resolution: {integrity: sha512-viehvi2XBP+NH8RThNUkArEOG4w3RBebbYPMB082Z1FZWw3BA2eYJYuywMQrg996RB4VKd23z2MRKsH+S9/Ryw==, tarball: file:projects/ai-bot-resources.tgz}
id: file:projects/ai-bot-resources.tgz
name: '@rush-temp/ai-bot-resources'
version: 0.0.0
@@ -25760,7 +25760,7 @@ packages:
dev: false
file:projects/ai-bot.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2):
resolution: {integrity: sha512-TH/kDh1LKw+pJRxLZZIjR7da6BQslR9S9Uy9HHXDtvtu5es55OmjRZEWPUnkBjKRmY6hTPBmaO4veq7RiaNz7g==, tarball: file:projects/ai-bot.tgz}
resolution: {integrity: sha512-9Den4fvsKoZPm3qqDIuseVnFyfc/Fho5/B0jme5SBPe8h3hWt3Z5KnuLn536JoEEnESef3XGzcNgGLrwoI/aew==, tarball: file:projects/ai-bot.tgz}
id: file:projects/ai-bot.tgz
name: '@rush-temp/ai-bot'
version: 0.0.0
@@ -28875,7 +28875,7 @@ packages:
dev: false
file:projects/love-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
resolution: {integrity: sha512-6dbzkDxFSSCZr7b3Cm7AFvESRax8JpNYiIvI/ScUNPN+M7L2a3PKWKlfdcD/ZvWOAKmQW1l0j5GPH/ucHHu8sQ==, tarball: file:projects/love-resources.tgz}
resolution: {integrity: sha512-j08lws3Rs5hRf/4J7g6XgTv81Ngee8Z6OZX5z8zJrYYyi+pF9nB+SqhYBo5XjhaTnGIB7qGmIEa3NPnOboTFXQ==, tarball: file:projects/love-resources.tgz}
id: file:projects/love-resources.tgz
name: '@rush-temp/love-resources'
version: 0.0.0
@@ -29420,7 +29420,7 @@ packages:
dev: false
file:projects/model-love.tgz:
resolution: {integrity: sha512-UiC6UZqvrfHuUWOu6yZA1F++CSp4lgs3TWAlYXv6yLUAl6tn8m+X5OWbELYe3uPJxKYE/1GGEXL/A8VdnbyRiw==, tarball: file:projects/model-love.tgz}
resolution: {integrity: sha512-bj/JjSJTq+gRJxThem8TQC39bFDXXU22xDeB1w0qEo2eQ64Se3SZKRPg/jfsovn8/TgRJZkiwAhm2BfPF04C0Q==, tarball: file:projects/model-love.tgz}
name: '@rush-temp/model-love'
version: 0.0.0
dependencies:
@@ -30902,7 +30902,7 @@ packages:
dev: false
file:projects/pod-ai-bot.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4)(zod@3.23.8):
resolution: {integrity: sha512-jpa/Fp63/KSlRLWWvQ3sAv2vui5c0rCHmcJQCTITuqGtGm+1pNUfjD4wuKCuNp0314WXT7g8+Gge1u3SrQDLJg==, tarball: file:projects/pod-ai-bot.tgz}
resolution: {integrity: sha512-DdvaIQHJvpeb14DqaJxvXMN6gIP1T1HkGubDeZRUO2S2dWW3fR6hcJi7qyKzoQSPcywWkqlvFnoZI8TjBxaf3Q==, tarball: file:projects/pod-ai-bot.tgz}
id: file:projects/pod-ai-bot.tgz
name: '@rush-temp/pod-ai-bot'
version: 0.0.0
@@ -32230,18 +32230,18 @@ packages:
dev: false
file:projects/qms-tests-sanity.tgz:
resolution: {integrity: sha512-WH2sJcYUwJBzqHng4F/ceE1IkB4XD5HhfdsuSBgCSVD5jsqm+V39F0+AFmLhgQsJuvwd6D2rM/RaCE1hHmGxPw==, tarball: file:projects/qms-tests-sanity.tgz}
resolution: {integrity: sha512-pwcr0TJv07HkRMREnDqvaEmQfzc6fDwD4GF57dZQ/LXDbukRlQicgvWZ+kTNFx/RUyXUiPzvLNvBELMGs3+k/Q==, tarball: file:projects/qms-tests-sanity.tgz}
name: '@rush-temp/qms-tests-sanity'
version: 0.0.0
dependencies:
'@faker-js/faker': 8.4.1
'@playwright/test': 1.47.2
'@playwright/test': 1.48.2
'@types/jest': 29.5.12
'@types/node': 20.11.19
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
allure-js-commons: 3.0.4(allure-playwright@3.0.4)
allure-playwright: 3.0.4(@playwright/test@1.47.2)
allure-js-commons: 3.0.6(allure-playwright@3.0.6)
allure-playwright: 3.0.6(@playwright/test@1.48.2)
cross-env: 7.0.3
dotenv: 16.0.3
eslint: 8.56.0
@@ -35767,18 +35767,18 @@ packages:
dev: false
file:projects/tests-sanity.tgz:
resolution: {integrity: sha512-Ii9d6GDonR1QAp1S1uBqI6QdL7y/Xm3PC7W/HkwUtv8QTH1/gEslKOo6dXE7jxE1rHJigMWiy3ZP1+PHLFnuhg==, tarball: file:projects/tests-sanity.tgz}
resolution: {integrity: sha512-noV3nlBP0OvM6i4C5YUevkhltHxG/2bct4pusP3O3AEQ7Za+A4qwzpsE08pHfA9f9pedEG677GE4EmG9x61rVQ==, tarball: file:projects/tests-sanity.tgz}
name: '@rush-temp/tests-sanity'
version: 0.0.0
dependencies:
'@faker-js/faker': 8.4.1
'@playwright/test': 1.47.2
'@playwright/test': 1.48.2
'@types/jest': 29.5.12
'@types/node': 20.11.19
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
allure-js-commons: 3.0.4(allure-playwright@3.0.4)
allure-playwright: 3.0.4(@playwright/test@1.47.2)
allure-js-commons: 3.0.6(allure-playwright@3.0.6)
allure-playwright: 3.0.6(@playwright/test@1.48.2)
cross-env: 7.0.3
dotenv: 16.0.3
eslint: 8.56.0
+9 -1
View File
@@ -24,6 +24,7 @@ import {
export interface FileUploader {
uploadFile: (id: Ref<Doc>, name: string, file: File, contentType?: string) => Promise<Response>
uploadCollaborativeDoc: (id: Ref<Doc>, collabId: CollaborativeDoc, data: Buffer) => Promise<Response>
getFileUrl: (id: string) => string
}
export interface UploadResult {
@@ -34,8 +35,11 @@ export interface UploadResult {
export class FrontFileUploader implements FileUploader {
constructor (
private readonly frontUrl: string,
private readonly workspaceId: string,
private readonly token: string
) {}
) {
this.getFileUrl = this.getFileUrl.bind(this)
}
public async uploadFile (id: Ref<Doc>, name: string, file: File, contentType?: string): Promise<Response> {
const form = new FormData()
@@ -55,6 +59,10 @@ export class FrontFileUploader implements FileUploader {
})
}
public getFileUrl (id: string): string {
return concatLink(this.frontUrl, `/files/${this.workspaceId}/${id}?file=${id}&workspace=${this.workspaceId}`)
}
public async uploadCollaborativeDoc (id: Ref<Doc>, collabId: CollaborativeDoc, data: Buffer): Promise<Response> {
const file = new File([data], collabId)
const { documentId } = collaborativeDocParse(collabId)
+1 -1
View File
@@ -78,7 +78,7 @@ export function importTool (): void {
return
}
const client = new TxOperations(connection, acc._id)
const fileUploader = new FrontFileUploader(getFrontUrl(), selectedWs.token)
const fileUploader = new FrontFileUploader(getFrontUrl(), selectedWs.workspaceId, selectedWs.token)
try {
await f(client, fileUploader)
} catch (err: any) {
+34 -13
View File
@@ -409,7 +409,7 @@ async function importAttachment (
}
const file = new File([data], docMeta.name)
await fileUploader.uploadFile(docMeta.id as Ref<Doc>, docMeta.name, file)
await fileUploader.uploadFile(docMeta.id as Ref<Doc>, docMeta.id, file)
const attachedData: AttachedData<Attachment> = {
file: docMeta.id as Ref<Blob>,
@@ -442,7 +442,7 @@ async function importPageDocument (
const md = data.toString() ?? ''
const json = parseMessageMarkdown(md ?? '', 'image://')
if (documentMetaMap !== undefined) {
preProcessMarkdown(json, documentMetaMap)
preProcessMarkdown(json, documentMetaMap, fileUploader)
}
const yDoc = jsonToYDocNoSchema(json, 'content')
const buffer = yDocToBuffer(yDoc)
@@ -472,7 +472,11 @@ async function importPageDocument (
await client.createDoc(document.class.Document, space, attachedData, id)
}
function preProcessMarkdown (json: MarkupNode, documentMetaMap: Map<string, DocumentMetadata>): void {
function preProcessMarkdown (
json: MarkupNode,
documentMetaMap: Map<string, DocumentMetadata>,
fileUploader: FileUploader
): void {
traverseNode(json, (node) => {
if (node.type === MarkupNodeType.image) {
const src = node.attrs?.src
@@ -480,7 +484,7 @@ function preProcessMarkdown (json: MarkupNode, documentMetaMap: Map<string, Docu
const notionId = getFileId('', src as string)
const meta = documentMetaMap.get(notionId)
if (meta !== undefined) {
alterImageNode(node, meta)
alterImageNode(node, meta, fileUploader.getFileUrl(meta.id))
}
}
} else {
@@ -561,12 +565,21 @@ function alterInternalLinkNode (node: MarkupNode, targetMeta: DocumentMetadata):
}
}
function alterImageNode (node: MarkupNode, meta: DocumentMetadata): void {
function alterImageNode (node: MarkupNode, meta: DocumentMetadata, fileUrl: string): void {
node.type = MarkupNodeType.image
if (node.attrs !== undefined) {
node.attrs['file-id'] = meta.id
if (meta.mimeType !== undefined) {
node.attrs['data-file-type'] = meta.mimeType
node.attrs = {
'file-id': meta.id,
src: fileUrl,
width: node.attrs.width ?? null,
height: node.attrs.height ?? null,
align: node.attrs.align ?? null,
alt: meta.name,
title: meta.name
}
const mimeType = getContentType(meta.name)
if (mimeType !== undefined) {
node.attrs['data-file-type'] = mimeType
}
}
}
@@ -580,19 +593,27 @@ function isExternalLink (href: any): boolean {
return URL.canParse(href)
}
function safeDecodeURI (uri: string): string {
try {
return decodeURI(uri)
} catch (e) {
return uri
}
}
function extractNotionId (fileName: string): string | undefined {
const decoded = decodeURI(fileName).trimEnd()
const decoded = safeDecodeURI(fileName).trimEnd()
const matched = decoded.match(/ ([\w\d]{32}(_all)?)(\.|$)/)
return matched !== null && matched.length >= 2 ? matched[1] : undefined
}
function extractExtension (fileName: string): string {
const decoded = decodeURI(fileName)
const decoded = safeDecodeURI(fileName)
return parse(decoded).ext.toLowerCase()
}
function extractNameWoExtension (fileName: string): string {
const decoded = decodeURI(fileName)
const decoded = safeDecodeURI(fileName)
return parse(decoded).name
}
@@ -608,8 +629,8 @@ function getFileId (filePath: string, fileName: string): string {
if (notionId !== '' && notionId !== undefined) {
return notionId
}
const decodedPath = decodeURI(filePath)
const decodedName = decodeURI(fileName)
const decodedPath = safeDecodeURI(filePath)
const decodedName = safeDecodeURI(fileName)
return join(basename(decodedPath), decodedName)
}
+13 -1
View File
@@ -38,7 +38,7 @@ import {
import templates from '@hcengineering/templates'
import setting from './plugin'
import workbench from '@hcengineering/model-workbench'
import workbench, { WidgetType } from '@hcengineering/model-workbench'
import { type AnyComponent } from '@hcengineering/ui/src/types'
export { settingId } from '@hcengineering/setting'
@@ -133,6 +133,18 @@ export function createModel (builder: Builder): void {
TSpaceTypeCreator
)
builder.createDoc(
workbench.class.Widget,
core.space.Model,
{
label: setting.string.Settings,
type: WidgetType.Flexible,
icon: setting.icon.Setting,
component: setting.component.SettingsWidget
},
setting.ids.SettingsWidget
)
builder.mixin(setting.class.Integration, core.class.Class, notification.mixin.ClassCollaborators, {
fields: ['modifiedBy']
})
+2 -1
View File
@@ -46,7 +46,8 @@ export default mergeIds(settingId, setting, {
InviteSetting: '' as AnyComponent,
ArrayEditor: '' as AnyComponent,
IntegrationPanel: '' as AnyComponent,
Configure: '' as AnyComponent
Configure: '' as AnyComponent,
SettingsWidget: '' as AnyComponent
},
category: {
Settings: '' as Ref<ActionCategory>
+2 -1
View File
@@ -41,7 +41,8 @@ import workbench from './plugin'
export { workbenchId } from '@hcengineering/workbench'
export { workbenchOperation } from './migration'
export type { Application }
export type { Application, Widget }
export { WidgetType } from '@hcengineering/workbench'
@Model(workbench.class.Application, core.class.Doc, DOMAIN_MODEL)
@UX(workbench.string.Application)
+6 -1
View File
@@ -4,8 +4,13 @@
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
"files": [
"lib/**/*",
"types/**/*",
"tsconfig.json"
],
"author": "Anticrm Platform Contributors",
"template": "@hcengineering/default-package",
"template": "@hcengineering/api-package",
"license": "EPL-2.0",
"scripts": {
"build": "compile",
+1
View File
@@ -62,6 +62,7 @@
gap: var(--spacing-4);
}
&__container {
justify-content: stretch;
height: 100%;
}
&__container:not(.columns),
+6
View File
@@ -282,4 +282,10 @@
}
}
}
&.short .hulyTableAttr-content.withTitle {
flex-direction: column;
align-items: stretch;
.hulyTableAttr-content__wrapper:empty { display: none; }
}
}
+2 -1
View File
@@ -32,6 +32,7 @@
export let padding: string | undefined = undefined
export let hidden: boolean = false
export let allowFullsize: boolean = false
export let noTopIndent: boolean = false
export let hideFooter: boolean = false
export let adaptive: 'default' | 'freezeActions' | 'doubleRow' | 'disabled' = 'disabled'
export let showCancelButton: boolean = true
@@ -56,7 +57,7 @@
<svelte:window on:keydown={onKeyDown} />
<div class="hulyModal-container {type}" class:hidden>
<div class="hulyModal-container {type}" class:hidden class:noTopIndent>
<Header
{type}
{allowFullsize}
+5
View File
@@ -164,6 +164,11 @@ export const settingsSeparators: DefSeparators = [
{ minSize: 19, size: 30, maxSize: 32, float: 'aside' }
]
export const twoPanelsSeparators: DefSeparators = [
{ minSize: 12.5, size: 17.5, maxSize: 22.5, float: 'navigator' },
null
]
export const mainSeparators: DefSeparators = [
{ minSize: 30, size: 'auto', maxSize: 'auto' },
{ minSize: 25, size: 30, maxSize: 80, float: 'sidebar' }
@@ -35,7 +35,7 @@
resolvedLocationStore,
Scroller,
Separator,
settingsSeparators
twoPanelsSeparators
} from '@hcengineering/ui'
import notification from '../../plugin'
@@ -93,7 +93,7 @@
unsubscribeTypeSetting()
unsubscribeProviderSetting()
})
defineSeparators('notificationSettings', settingsSeparators)
defineSeparators('notificationSettings', twoPanelsSeparators)
</script>
<div class="hulyComponent">
@@ -26,7 +26,9 @@
getEventPositionElement,
showPopup,
IconSettings,
ModernButton
ModernButton,
resizeObserver,
deviceWidths
} from '@hcengineering/ui'
import { ObjectPresenter } from '@hcengineering/view-resources'
import settings from '../plugin'
@@ -144,7 +146,13 @@
</div>
{/if}
{/if}
<div class="hulyTableAttr-container">
<div
class="hulyTableAttr-container"
use:resizeObserver={(el) => {
if (el.clientWidth < deviceWidths[0] && !el.classList.contains('short')) el.classList.add('short')
else if (el.clientWidth >= deviceWidths[0] && el.classList.contains('short')) el.classList.remove('short')
}}
>
<div class="hulyTableAttr-header font-medium-12" class:withButton={showHierarchy}>
{#if showHierarchy}
<ModernButton icon={IconSettings} kind={'secondary'} size={'small'} {disabled} hasMenu>
@@ -27,7 +27,7 @@
Header,
Breadcrumb,
defineSeparators,
settingsSeparators,
twoPanelsSeparators,
Separator,
NavGroup
} from '@hcengineering/ui'
@@ -97,7 +97,7 @@
$: if (ofClass !== undefined && _class !== undefined && !client.getHierarchy().isDerived(_class, ofClass)) {
_class = ofClass
}
defineSeparators('workspaceSettings', settingsSeparators)
defineSeparators('workspaceSettings', twoPanelsSeparators)
</script>
<div class="hulyComponent">
@@ -35,6 +35,7 @@
export let attribute: AnyAttribute
export let exist: boolean
export let disabled: boolean = true
export let noTopIndent: boolean = false
let name: string
let type: Type<PropertyType> | undefined = attribute.type
@@ -133,9 +134,8 @@
okLabel={presentation.string.Save}
okAction={save}
canSave={!(name === undefined || name.trim().length === 0) && !disabled}
onCancel={() => {
clearSettingsStore()
}}
onCancel={clearSettingsStore}
{noTopIndent}
>
<svelte:fragment slot="actions">
{#if !disabled}
@@ -27,7 +27,7 @@
Scroller,
Separator,
defineSeparators,
settingsSeparators,
twoPanelsSeparators,
showPopup
} from '@hcengineering/ui'
import { showMenu } from '@hcengineering/view-resources'
@@ -51,7 +51,7 @@
showPopup(setting.component.EditEnum, { title: setting.string.CreateEnum }, 'top')
}
defineSeparators('workspaceSettings', settingsSeparators)
defineSeparators('workspaceSettings', twoPanelsSeparators)
</script>
<div class="hulyComponent">
@@ -17,7 +17,8 @@
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
import login, { loginId } from '@hcengineering/login'
import { setMetadata } from '@hcengineering/platform'
import presentation, { closeClient, createQuery } from '@hcengineering/presentation'
import presentation, { closeClient, getClient, createQuery } from '@hcengineering/presentation'
import settingPlg from '../plugin'
import setting, { SettingsCategory, SettingsEvents } from '@hcengineering/setting'
import {
Component,
@@ -35,13 +36,18 @@
settingsSeparators,
showPopup,
type AnyComponent,
deviceOptionsStore as deviceInfo
deviceOptionsStore as deviceInfo,
resizeObserver,
deviceWidths
} from '@hcengineering/ui'
import { NavFooter } from '@hcengineering/workbench-resources'
import { closeWidget, NavFooter, openWidget, minimizeSidebar } from '@hcengineering/workbench-resources'
import workbench from '@hcengineering/workbench'
import { ComponentType, onDestroy, onMount } from 'svelte'
import { clearSettingsStore, settingsStore, type SettingsStore } from '../store'
import { Analytics } from '@hcengineering/analytics'
const client = getClient()
let category: SettingsCategory | undefined
let categoryId: string = ''
@@ -122,11 +128,26 @@
return ss.component === undefined ? null : ss.component
}
$: asideComponent = updatedStore($settingsStore)
let moveASide: boolean = false
const widget = client.getModel().findAllSync(workbench.class.Widget, { _id: settingPlg.ids.SettingsWidget })[0]
$: if (moveASide && asideComponent != null) {
openWidget(widget, { component: asideComponent, ...asideProps }, { active: true, openedByUser: true })
$deviceInfo.aside.visible = true
} else if ((moveASide && asideComponent == null) || (!moveASide && asideComponent != null)) {
closeWidget(widget._id)
minimizeSidebar()
}
defineSeparators('setting', settingsSeparators)
</script>
<div class="hulyPanels-container">
<div
class="hulyPanels-container"
use:resizeObserver={(el) => {
if (el.clientWidth < deviceWidths[2] && !moveASide) moveASide = true
else if (el.clientWidth >= deviceWidths[2] && moveASide) moveASide = false
}}
>
{#if $deviceInfo.navigator.visible}
<div
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
@@ -208,7 +229,7 @@
<Component is={category.component} props={{ kind: 'content' }} />
{/if}
</div>
{#if asideComponent != null}
{#if asideComponent != null && !moveASide}
<Separator name={'setting'} index={1} color={'transparent'} separatorSize={0} short />
<div class="hulySidePanel-container">
{#key asideProps}
@@ -0,0 +1,32 @@
<!--
// Copyright © 2024 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.
-->
<script lang="ts">
import { WidgetState } from '@hcengineering/workbench-resources'
import { type AnyComponent, Component } from '@hcengineering/ui'
import { ComponentType } from 'svelte'
export let widgetState: WidgetState | undefined
$: asideProps = widgetState?.data
$: asideComponent = asideProps?.component as AnyComponent | ComponentType
</script>
{#key asideProps}
{#if typeof asideComponent === 'string'}
<Component is={asideComponent} props={{ ...asideProps, noTopIndent: true }} />
{:else}
<svelte:component this={asideComponent} {...asideProps} noTopIndent />
{/if}
{/key}
+3 -1
View File
@@ -58,6 +58,7 @@ import RefEditor from './components/typeEditors/RefEditor.svelte'
import RoleAssignmentEditor from './components/typeEditors/RoleAssignmentEditor.svelte'
import StringTypeEditor from './components/typeEditors/StringTypeEditor.svelte'
import WorkspaceSettings from './components/WorkspaceSettings.svelte'
import SettingsWidget from './components/SettingsWidget.svelte'
import setting from './plugin'
import { filterDescendants, getOwnerFirstName, getOwnerLastName, getOwnerPosition, getValue } from './utils'
@@ -121,7 +122,8 @@ export default async (): Promise<Resources> => ({
SpaceTypePropertiesSectionEditor,
SpaceTypeRolesSectionEditor,
RoleEditor,
RoleAssignmentEditor
RoleAssignmentEditor,
SettingsWidget
},
actionImpl: {
DeleteMixin
+5
View File
@@ -13,12 +13,17 @@
// limitations under the License.
//
import { type Ref } from '@hcengineering/core'
import type { IntlString } from '@hcengineering/platform'
import { mergeIds } from '@hcengineering/platform'
import setting, { settingId } from '@hcengineering/setting'
import { type AnyComponent } from '@hcengineering/ui'
import { type Widget } from '@hcengineering/workbench'
export default mergeIds(settingId, setting, {
ids: {
SettingsWidget: '' as Ref<Widget>
},
component: {
EditEnum: '' as AnyComponent,
ManageSpaceTypes: '' as AnyComponent,
@@ -17,7 +17,7 @@
Breadcrumb,
Separator,
defineSeparators,
settingsSeparators,
twoPanelsSeparators,
Scroller
} from '@hcengineering/ui'
import { getActions as getContributedActions, TreeItem, TreeNode } from '@hcengineering/view-resources'
@@ -147,7 +147,7 @@
}
let space: Ref<TemplateCategory> | undefined = undefined
defineSeparators('workspaceSettings', settingsSeparators)
defineSeparators('workspaceSettings', twoPanelsSeparators)
</script>
<div class="hulyComponent">
@@ -79,7 +79,7 @@
overflow: hidden;
flex-direction: row;
min-width: 25rem;
border-radius: var(--medium-BorderRadius);
border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
&.mini:not(.float) {
width: 3.5rem !important;
@@ -89,6 +89,9 @@
&.mini.float {
justify-content: flex-end;
}
&.float > :global(.sidebar-content) {
border-top: none;
}
}
@media (max-width: 1024px) {
.sidebar-container {
@@ -96,7 +96,7 @@
}
</script>
<div class="content">
<div class="sidebar-content">
{#if widget?.component}
<div class="component" use:resizeObserver={resize}>
{#if widget.headerLabel}
@@ -145,7 +145,7 @@
<WidgetsBar {widgets} {preferences} selected={widgetId} />
<style lang="scss">
.content {
.sidebar-content {
display: flex;
flex-direction: column;
@@ -334,6 +334,8 @@ export function minimizeSidebar (closedByUser = false): void {
}
sidebarStore.set({ ...state, ...widgetsState, widget: undefined, variant: SidebarVariant.MINI })
const devInfo = get(deviceInfo)
if (devInfo.navigator.float && devInfo.aside.visible) deviceInfo.set({ ...devInfo, aside: { visible: false } })
}
export function updateTabData (widget: Ref<Widget>, tabId: string, data: Record<string, any>): void {
+3 -3
View File
@@ -42,9 +42,9 @@
"eslint-config-standard-with-typescript": "^40.0.0",
"prettier": "^3.1.0",
"typescript": "^5.3.3",
"@playwright/test": "^1.47.2",
"allure-playwright": "^3.0.4",
"allure-js-commons": "^3.0.4",
"@playwright/test": "^1.48.2",
"allure-playwright": "^3.0.6",
"allure-js-commons": "^3.0.6",
"@faker-js/faker": "^8.4.1"
},
"dependencies": {
+3 -3
View File
@@ -41,9 +41,9 @@
"eslint-config-standard-with-typescript": "^40.0.0",
"prettier": "^3.1.0",
"typescript": "^5.3.3",
"@playwright/test": "^1.47.2",
"allure-playwright": "^3.0.4",
"allure-js-commons": "^3.0.4",
"@playwright/test": "^1.48.2",
"allure-playwright": "^3.0.6",
"allure-js-commons": "^3.0.6",
"@faker-js/faker": "^8.4.1"
},
"dependencies": {
+1 -1
View File
@@ -12,7 +12,7 @@ export class SidebarPage extends CommonPage {
}
sidebar = (): Locator => this.page.locator('#sidebar')
content = (): Locator => this.sidebar().locator('.content')
content = (): Locator => this.sidebar().locator('.sidebar-content')
contentHeaderByTitle = (title: string): Locator =>
this.content().locator(`.hulyHeader-titleGroup:has-text("${title}")`)