mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-28 23:27:38 +03:00
UBERF-5511: Fix query and include ibm plex mono (#4764)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
88b91d7ce0
commit
804f514f5f
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ temp/
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
tests/sanity/screenshots
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
*.pid
|
*.pid
|
||||||
|
@ -512,6 +512,9 @@ function getInNiN (query1: any, query2: any): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function cutObjectArray (obj: any): any {
|
export function cutObjectArray (obj: any): any {
|
||||||
|
if (obj == null) {
|
||||||
|
return obj
|
||||||
|
}
|
||||||
const r = {}
|
const r = {}
|
||||||
for (const key of Object.keys(obj)) {
|
for (const key of Object.keys(obj)) {
|
||||||
if (Array.isArray(obj[key])) {
|
if (Array.isArray(obj[key])) {
|
||||||
|
@ -132,7 +132,7 @@ async function performESBuild(filesToTranspile) {
|
|||||||
minify: false,
|
minify: false,
|
||||||
outdir: 'lib',
|
outdir: 'lib',
|
||||||
keepNames: true,
|
keepNames: true,
|
||||||
sourcemap: 'external',
|
sourcemap: 'inline',
|
||||||
allowOverwrite: true,
|
allowOverwrite: true,
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
plugins: [
|
plugins: [
|
||||||
|
@ -69,6 +69,8 @@ interface Query {
|
|||||||
options?: FindOptions<Doc>
|
options?: FindOptions<Doc>
|
||||||
total: number
|
total: number
|
||||||
callbacks: Map<string, Callback>
|
callbacks: Map<string, Callback>
|
||||||
|
|
||||||
|
requested?: Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +107,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
for (const q of [...this.queue]) {
|
for (const q of [...this.queue]) {
|
||||||
if (!this.removeFromQueue(q)) {
|
if (!this.removeFromQueue(q)) {
|
||||||
try {
|
try {
|
||||||
await this.refresh(q)
|
void this.refresh(q)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err instanceof PlatformError) {
|
if (err instanceof PlatformError) {
|
||||||
if (err.message === 'connection closed') {
|
if (err.message === 'connection closed') {
|
||||||
@ -119,7 +121,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
for (const v of this.queries.values()) {
|
for (const v of this.queries.values()) {
|
||||||
for (const q of v) {
|
for (const q of v) {
|
||||||
try {
|
try {
|
||||||
await this.refresh(q)
|
void this.refresh(q)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err instanceof PlatformError) {
|
if (err instanceof PlatformError) {
|
||||||
if (err.message === 'connection closed') {
|
if (err.message === 'connection closed') {
|
||||||
@ -728,7 +730,21 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
return this.getHierarchy().clone(results) as T[]
|
return this.getHierarchy().clone(results) as T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
private async refresh (q: Query): Promise<void> {
|
private async refresh (q: Query, reRequest: boolean = false): Promise<void> {
|
||||||
|
if (q.requested !== undefined && !reRequest) {
|
||||||
|
// we already asked for refresh, just wait.
|
||||||
|
await q.requested
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (reRequest && q.requested !== undefined) {
|
||||||
|
await q.requested
|
||||||
|
}
|
||||||
|
q.requested = this.doRefresh(q)
|
||||||
|
await q.requested
|
||||||
|
q.requested = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
private async doRefresh (q: Query): Promise<void> {
|
||||||
const res = await this.client.findAll(q._class, q.query, q.options)
|
const res = await this.client.findAll(q._class, q.query, q.options)
|
||||||
if (!deepEqual(res, q.result) || (res.total !== q.total && q.options?.total === true)) {
|
if (!deepEqual(res, q.result) || (res.total !== q.total && q.options?.total === true)) {
|
||||||
q.result = res
|
q.result = res
|
||||||
@ -737,18 +753,6 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private triggerRefresh (q: Query): void {
|
|
||||||
const r: Promise<FindResult<Doc>> | FindResult<Doc> = this.client.findAll(q._class, q.query, q.options)
|
|
||||||
q.result = r
|
|
||||||
void r.then(async (qr) => {
|
|
||||||
const oldResult = q.result
|
|
||||||
if (!deepEqual(qr, oldResult) || (qr.total !== q.total && q.options?.total === true)) {
|
|
||||||
q.total = qr.total
|
|
||||||
await this.callback(q)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if query is partially matched.
|
// Check if query is partially matched.
|
||||||
private async matchQuery (q: Query, tx: TxUpdateDoc<Doc>, docCache: Map<string, Doc>): Promise<boolean> {
|
private async matchQuery (q: Query, tx: TxUpdateDoc<Doc>, docCache: Map<string, Doc>): Promise<boolean> {
|
||||||
const clazz = this.getHierarchy().isMixin(q._class) ? this.getHierarchy().getBaseClass(q._class) : q._class
|
const clazz = this.getHierarchy().isMixin(q._class) ? this.getHierarchy().getBaseClass(q._class) : q._class
|
||||||
@ -1137,16 +1141,31 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
const docCache = new Map<string, Doc>()
|
const docCache = new Map<string, Doc>()
|
||||||
for (const tx of txes) {
|
for (const tx of txes) {
|
||||||
if (tx._class === core.class.TxWorkspaceEvent) {
|
if (tx._class === core.class.TxWorkspaceEvent) {
|
||||||
await this.checkUpdateEvents(tx)
|
await this.checkUpdateEvents(tx as TxWorkspaceEvent)
|
||||||
await this.changePrivateHandler(tx)
|
await this.changePrivateHandler(tx as TxWorkspaceEvent)
|
||||||
}
|
}
|
||||||
result.push(await this._tx(tx, docCache))
|
result.push(await this._tx(tx, docCache))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkUpdateEvents (tx: Tx): Promise<void> {
|
triggerCounter = 0
|
||||||
const evt = tx as TxWorkspaceEvent
|
searchTriggerTimer: any
|
||||||
|
|
||||||
|
private async checkUpdateEvents (evt: TxWorkspaceEvent, trigger = true): Promise<void> {
|
||||||
|
clearTimeout(this.searchTriggerTimer)
|
||||||
|
|
||||||
|
// We need to add trigger once more, since elastic could have a huge lag with document availability.
|
||||||
|
if (trigger || this.triggerCounter > 0) {
|
||||||
|
if (trigger) {
|
||||||
|
this.triggerCounter = 5 // Schedule 5 refreshes on every 5 seconds.
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.triggerCounter--
|
||||||
|
void this.checkUpdateEvents(evt, false)
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
const h = this.client.getHierarchy()
|
const h = this.client.getHierarchy()
|
||||||
function hasClass (q: Query, classes: Ref<Class<Doc>>[]): boolean {
|
function hasClass (q: Query, classes: Ref<Class<Doc>>[]): boolean {
|
||||||
return classes.includes(q._class) || classes.some((it) => h.isDerived(q._class, it) || h.isDerived(it, q._class))
|
return classes.includes(q._class) || classes.some((it) => h.isDerived(q._class, it) || h.isDerived(it, q._class))
|
||||||
@ -1157,7 +1176,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
if (hasClass(q, indexingParam._class) && q.query.$search !== undefined) {
|
if (hasClass(q, indexingParam._class) && q.query.$search !== undefined) {
|
||||||
if (!this.removeFromQueue(q)) {
|
if (!this.removeFromQueue(q)) {
|
||||||
try {
|
try {
|
||||||
this.triggerRefresh(q)
|
await this.refresh(q, true)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
@ -1167,11 +1186,14 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
for (const v of this.queries.values()) {
|
for (const v of this.queries.values()) {
|
||||||
for (const q of v) {
|
for (const q of v) {
|
||||||
if (hasClass(q, indexingParam._class) && q.query.$search !== undefined) {
|
if (hasClass(q, indexingParam._class) && q.query.$search !== undefined) {
|
||||||
|
console.log('Query update call', q)
|
||||||
try {
|
try {
|
||||||
this.triggerRefresh(q)
|
await this.refresh(q, true)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
|
} else if (q.query.$search !== undefined) {
|
||||||
|
console.log('Query update mismatch class', q._class, indexingParam._class)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1182,7 +1204,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
if (hasClass(q, params._class)) {
|
if (hasClass(q, params._class)) {
|
||||||
if (!this.removeFromQueue(q)) {
|
if (!this.removeFromQueue(q)) {
|
||||||
try {
|
try {
|
||||||
this.triggerRefresh(q)
|
await this.refresh(q, true)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
@ -1193,7 +1215,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
for (const q of v) {
|
for (const q of v) {
|
||||||
if (hasClass(q, params._class)) {
|
if (hasClass(q, params._class)) {
|
||||||
try {
|
try {
|
||||||
this.triggerRefresh(q)
|
await this.refresh(q, true)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
@ -1203,8 +1225,7 @@ export class LiveQuery implements WithTx, Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async changePrivateHandler (tx: Tx): Promise<void> {
|
private async changePrivateHandler (evt: TxWorkspaceEvent): Promise<void> {
|
||||||
const evt = tx as TxWorkspaceEvent
|
|
||||||
if (evt.event === WorkspaceEvent.SecurityChange) {
|
if (evt.event === WorkspaceEvent.SecurityChange) {
|
||||||
for (const q of [...this.queue]) {
|
for (const q of [...this.queue]) {
|
||||||
if (typeof q.query.space !== 'string') {
|
if (typeof q.query.space !== 'string') {
|
||||||
|
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Bold.woff
Normal file
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Bold.woff
Normal file
Binary file not shown.
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Medium.woff
Normal file
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Medium.woff
Normal file
Binary file not shown.
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Regular.woff
Normal file
BIN
packages/theme/fonts/complete/woff/mono/IBMPlexMono-Regular.woff
Normal file
Binary file not shown.
Binary file not shown.
BIN
packages/theme/fonts/complete/woff2/mono/IBMPlexMono-Bold.woff2
Normal file
BIN
packages/theme/fonts/complete/woff2/mono/IBMPlexMono-Bold.woff2
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -29,7 +29,7 @@
|
|||||||
@import "./tables.scss";
|
@import "./tables.scss";
|
||||||
@import "./_text-editor.scss";
|
@import "./_text-editor.scss";
|
||||||
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,500;1,400;1,500&display=swap');
|
@import "./mono.scss";
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'IBM Plex Sans';
|
font-family: 'IBM Plex Sans';
|
||||||
|
36
packages/theme/styles/mono.scss
Normal file
36
packages/theme/styles/mono.scss
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('IBM Plex Mono'),
|
||||||
|
local('IBMPlexMono'),
|
||||||
|
url('../fonts/complete/woff2/mono/IBMPlexMono-Regular.woff2') format('woff2'),
|
||||||
|
url('../fonts/complete/woff/mono/IBMPlexMono-Regular.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
src: local('IBM Plex Mono Medium'),
|
||||||
|
local('IBMPlexMono-Medium'),
|
||||||
|
url('../fonts/complete/woff2/mono/IBMPlexMono-Medium.woff2') format('woff2'),
|
||||||
|
url('../fonts/complete/woff/mono/IBMPlexMono-Medium.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
src: local('IBM Plex Mono SemiBold'),
|
||||||
|
local('IBMPlexMono-SemiBold'),
|
||||||
|
url('../fonts/complete/woff2/mono/IBMPlexMono-SemiBold.woff2') format('woff2'),
|
||||||
|
url('../fonts/complete/woff/mono/IBMPlexMono-SemiBold.woff') format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'IBM Plex Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('IBM Plex Mono Bold'),
|
||||||
|
local('IBMPlexMono-Bold'),
|
||||||
|
url('../fonts/complete/woff2/mono/IBMPlexMono-Bold.woff2') format('woff2'),
|
||||||
|
url('../fonts/complete/woff/mono/IBMPlexMono-Bold.woff') format('woff');
|
||||||
|
}
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
export let icon: Asset | AnySvelteComponent | ComponentType
|
export let icon: Asset | AnySvelteComponent | ComponentType
|
||||||
export let width: string | undefined = undefined
|
export let width: string | undefined = undefined
|
||||||
export let value: string | undefined = undefined
|
export let value: string | undefined = ''
|
||||||
export let placeholder: IntlString = plugin.string.EditBoxPlaceholder
|
export let placeholder: IntlString = plugin.string.EditBoxPlaceholder
|
||||||
export let placeholderParam: any | undefined = undefined
|
export let placeholderParam: any | undefined = undefined
|
||||||
export let autoFocus: boolean = false
|
export let autoFocus: boolean = false
|
||||||
@ -34,15 +34,15 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let textHTML: HTMLInputElement
|
let textHTML: HTMLInputElement
|
||||||
let phTraslate: string = ''
|
let phTranslate: string = ''
|
||||||
|
|
||||||
export function focus () {
|
export function focus (): void {
|
||||||
textHTML.focus()
|
textHTML.focus()
|
||||||
autoFocus = false
|
autoFocus = false
|
||||||
}
|
}
|
||||||
|
|
||||||
$: translate(placeholder, placeholderParam ?? {}).then((res) => {
|
$: void translate(placeholder, placeholderParam ?? {}).then((res) => {
|
||||||
phTraslate = res
|
phTranslate = res
|
||||||
})
|
})
|
||||||
$: if (textHTML !== undefined) {
|
$: if (textHTML !== undefined) {
|
||||||
if (autoFocus) focus()
|
if (autoFocus) focus()
|
||||||
@ -53,13 +53,13 @@
|
|||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div
|
<div
|
||||||
class="flex-between editbox {size}"
|
class="flex-between editbox {size}"
|
||||||
style={width ? 'width: ' + width : ''}
|
style={width != null ? 'width: ' + width : ''}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
textHTML.focus()
|
textHTML.focus()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="mr-2 content-dark-color"><Icon {icon} size={'small'} /></div>
|
<div class="mr-2 content-dark-color"><Icon {icon} size={'small'} /></div>
|
||||||
<input bind:this={textHTML} type="text" bind:value placeholder={phTraslate} on:change on:input on:keydown />
|
<input bind:this={textHTML} type="text" bind:value placeholder={phTranslate} on:change on:input on:keydown />
|
||||||
<slot name="extra" />
|
<slot name="extra" />
|
||||||
<div class="flex-row-center flex-no-shrink">
|
<div class="flex-row-center flex-no-shrink">
|
||||||
{#if value}
|
{#if value}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||||
import EditWithIcon from './EditWithIcon.svelte'
|
import EditWithIcon from './EditWithIcon.svelte'
|
||||||
import IconSearch from './icons/Search.svelte'
|
import IconSearch from './icons/Search.svelte'
|
||||||
import plugin from '../plugin'
|
import plugin from '../plugin'
|
||||||
@ -11,13 +11,16 @@
|
|||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let timer: any
|
let timer: any
|
||||||
|
|
||||||
function restartTimer () {
|
function restartTimer (): void {
|
||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
value = _search
|
value = _search
|
||||||
dispatch('change', _search)
|
dispatch('change', _search)
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
onDestroy(() => {
|
||||||
|
clearTimeout(timer)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<EditWithIcon
|
<EditWithIcon
|
||||||
@ -26,20 +29,14 @@
|
|||||||
placeholder={plugin.string.Search}
|
placeholder={plugin.string.Search}
|
||||||
bind:value={_search}
|
bind:value={_search}
|
||||||
on:change={() => {
|
on:change={() => {
|
||||||
if (_search === '') {
|
restartTimer()
|
||||||
value = ''
|
|
||||||
dispatch('change', '')
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
on:input={() => {
|
on:input={() => {
|
||||||
restartTimer()
|
restartTimer()
|
||||||
if (_search === '') {
|
|
||||||
value = ''
|
|
||||||
dispatch('change', '')
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
on:keydown={(evt) => {
|
on:keydown={(evt) => {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter') {
|
||||||
|
clearTimeout(timer)
|
||||||
value = _search
|
value = _search
|
||||||
dispatch('change', _search)
|
dispatch('change', _search)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import core, {
|
import core, {
|
||||||
|
DOMAIN_MODEL,
|
||||||
|
cutObjectArray,
|
||||||
type Account,
|
type Account,
|
||||||
type AccountClient,
|
type AccountClient,
|
||||||
type Class,
|
type Class,
|
||||||
@ -23,20 +25,20 @@ import core, {
|
|||||||
type FindOptions,
|
type FindOptions,
|
||||||
type FindResult,
|
type FindResult,
|
||||||
type Hierarchy,
|
type Hierarchy,
|
||||||
|
type MeasureDoneOperation,
|
||||||
type ModelDb,
|
type ModelDb,
|
||||||
type Ref,
|
type Ref,
|
||||||
|
type SearchOptions,
|
||||||
|
type SearchQuery,
|
||||||
|
type SearchResult,
|
||||||
type Tx,
|
type Tx,
|
||||||
type TxResult,
|
type TxResult,
|
||||||
type WithLookup,
|
type WithLookup
|
||||||
type SearchQuery,
|
|
||||||
type SearchOptions,
|
|
||||||
type SearchResult,
|
|
||||||
type MeasureDoneOperation,
|
|
||||||
DOMAIN_MODEL
|
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { devModelId } from '@hcengineering/devmodel'
|
import { devModelId } from '@hcengineering/devmodel'
|
||||||
import { Builder } from '@hcengineering/model'
|
import { Builder } from '@hcengineering/model'
|
||||||
import { type IntlString, type Resources, getMetadata } from '@hcengineering/platform'
|
import { getMetadata, type IntlString, type Resources } from '@hcengineering/platform'
|
||||||
|
import { testing } from '@hcengineering/ui'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
import workbench from '@hcengineering/workbench'
|
import workbench from '@hcengineering/workbench'
|
||||||
import ModelView from './components/ModelView.svelte'
|
import ModelView from './components/ModelView.svelte'
|
||||||
@ -63,7 +65,11 @@ class ModelClient implements AccountClient {
|
|||||||
client.notify = (...tx) => {
|
client.notify = (...tx) => {
|
||||||
this.notify?.(...tx)
|
this.notify?.(...tx)
|
||||||
if (this.notifyEnabled) {
|
if (this.notifyEnabled) {
|
||||||
console.debug('devmodel# notify=>', tx, this.client.getModel(), getMetadata(devmodel.metadata.DevModel))
|
console.debug(
|
||||||
|
'devmodel# notify=>',
|
||||||
|
testing ? JSON.stringify(cutObjectArray(tx)).slice(0, 160) : tx,
|
||||||
|
getMetadata(devmodel.metadata.DevModel)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,13 +103,11 @@ class ModelClient implements AccountClient {
|
|||||||
if (this.notifyEnabled && !isModel) {
|
if (this.notifyEnabled && !isModel) {
|
||||||
console.debug(
|
console.debug(
|
||||||
'devmodel# findOne=>',
|
'devmodel# findOne=>',
|
||||||
isModel,
|
|
||||||
this.getHierarchy().findDomain(_class),
|
|
||||||
_class,
|
_class,
|
||||||
query,
|
testing ? JSON.stringify(cutObjectArray(query)) : query,
|
||||||
options,
|
options,
|
||||||
'result => ',
|
'result => ',
|
||||||
result,
|
testing ? JSON.stringify(cutObjectArray(result)) : result,
|
||||||
' =>model',
|
' =>model',
|
||||||
this.client.getModel(),
|
this.client.getModel(),
|
||||||
getMetadata(devmodel.metadata.DevModel),
|
getMetadata(devmodel.metadata.DevModel),
|
||||||
@ -125,10 +129,10 @@ class ModelClient implements AccountClient {
|
|||||||
console.debug(
|
console.debug(
|
||||||
'devmodel# findAll=>',
|
'devmodel# findAll=>',
|
||||||
_class,
|
_class,
|
||||||
query,
|
testing ? JSON.stringify(cutObjectArray(query)).slice(0, 160) : query,
|
||||||
options,
|
options,
|
||||||
'result => ',
|
'result => ',
|
||||||
result,
|
testing ? JSON.stringify(cutObjectArray(result)).slice(0, 160) : result,
|
||||||
' =>model',
|
' =>model',
|
||||||
this.client.getModel(),
|
this.client.getModel(),
|
||||||
getMetadata(devmodel.metadata.DevModel),
|
getMetadata(devmodel.metadata.DevModel),
|
||||||
@ -141,7 +145,13 @@ class ModelClient implements AccountClient {
|
|||||||
async searchFulltext (query: SearchQuery, options: SearchOptions): Promise<SearchResult> {
|
async searchFulltext (query: SearchQuery, options: SearchOptions): Promise<SearchResult> {
|
||||||
const result = await this.client.searchFulltext(query, options)
|
const result = await this.client.searchFulltext(query, options)
|
||||||
if (this.notifyEnabled) {
|
if (this.notifyEnabled) {
|
||||||
console.debug('devmodel# searchFulltext=>', query, options, 'result => ', result)
|
console.debug(
|
||||||
|
'devmodel# searchFulltext=>',
|
||||||
|
testing ? JSON.stringify(cutObjectArray(query)).slice(0, 160) : query,
|
||||||
|
options,
|
||||||
|
'result => ',
|
||||||
|
result
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -150,7 +160,13 @@ class ModelClient implements AccountClient {
|
|||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
const result = await this.client.tx(tx)
|
const result = await this.client.tx(tx)
|
||||||
if (this.notifyEnabled) {
|
if (this.notifyEnabled) {
|
||||||
console.debug('devmodel# tx=>', tx, result, getMetadata(devmodel.metadata.DevModel), Date.now() - startTime)
|
console.debug(
|
||||||
|
'devmodel# tx=>',
|
||||||
|
testing ? JSON.stringify(cutObjectArray(tx)).slice(0, 160) : tx,
|
||||||
|
result,
|
||||||
|
getMetadata(devmodel.metadata.DevModel),
|
||||||
|
Date.now() - startTime
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@
|
|||||||
|
|
||||||
const limiter = new RateLimiter(10)
|
const limiter = new RateLimiter(10)
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
|
||||||
let docs: Doc[] = []
|
let docs: Doc[] = []
|
||||||
let fastDocs: Doc[] = []
|
let fastDocs: Doc[] = []
|
||||||
let slowDocs: Doc[] = []
|
let slowDocs: Doc[] = []
|
||||||
@ -146,12 +149,9 @@
|
|||||||
return resultOptions
|
return resultOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
$: dispatch('content', docs)
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
const client = getClient()
|
$: dispatch('content', docs)
|
||||||
const hierarchy = client.getHierarchy()
|
|
||||||
|
|
||||||
async function getResultQuery (
|
async function getResultQuery (
|
||||||
query: DocumentQuery<Doc>,
|
query: DocumentQuery<Doc>,
|
||||||
@ -174,7 +174,7 @@
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
function uncheckAll () {
|
function uncheckAll (): void {
|
||||||
dispatch('check', { docs, value: false })
|
dispatch('check', { docs, value: false })
|
||||||
selectedObjectIds = []
|
selectedObjectIds = []
|
||||||
}
|
}
|
||||||
@ -197,7 +197,7 @@
|
|||||||
<div class="list-container" bind:this={listDiv}>
|
<div class="list-container" bind:this={listDiv}>
|
||||||
<ListCategories
|
<ListCategories
|
||||||
bind:this={listCategories}
|
bind:this={listCategories}
|
||||||
newObjectProps={() => (space ? { space } : {})}
|
newObjectProps={() => (space != null ? { space } : {})}
|
||||||
{docs}
|
{docs}
|
||||||
{_class}
|
{_class}
|
||||||
{space}
|
{space}
|
||||||
|
@ -267,6 +267,8 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
await this.flush(flush ?? false)
|
await this.flush(flush ?? false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerCounts = 0
|
||||||
|
|
||||||
triggerIndexing = (): void => {}
|
triggerIndexing = (): void => {}
|
||||||
skippedReiterationTimeout: any
|
skippedReiterationTimeout: any
|
||||||
currentStages: Record<string, number> = {}
|
currentStages: Record<string, number> = {}
|
||||||
@ -341,6 +343,9 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
})
|
})
|
||||||
|
|
||||||
while (!this.cancelling) {
|
while (!this.cancelling) {
|
||||||
|
// Clear triggers
|
||||||
|
this.triggerCounts = 0
|
||||||
|
this.stageChanged = 0
|
||||||
await this.metrics.with('initialize-stages', { workspace: this.workspace.name }, async () => {
|
await this.metrics.with('initialize-stages', { workspace: this.workspace.name }, async () => {
|
||||||
await this.initializeStages()
|
await this.initializeStages()
|
||||||
})
|
})
|
||||||
@ -360,7 +365,11 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
|
|
||||||
_classes.forEach((it) => this.broadcastClasses.add(it))
|
_classes.forEach((it) => this.broadcastClasses.add(it))
|
||||||
|
|
||||||
if (this.toIndex.size === 0 || this.stageChanged === 0) {
|
if (this.triggerCounts > 0) {
|
||||||
|
console.log('No wait, trigger counts', this.triggerCounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.toIndex.size === 0 && this.stageChanged === 0 && this.triggerCounts === 0) {
|
||||||
if (this.toIndex.size === 0) {
|
if (this.toIndex.size === 0) {
|
||||||
console.log(this.workspace.name, 'Indexing complete', this.indexId)
|
console.log(this.workspace.name, 'Indexing complete', this.indexId)
|
||||||
}
|
}
|
||||||
@ -374,6 +383,7 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
this.triggerIndexing = () => {
|
this.triggerIndexing = () => {
|
||||||
|
this.triggerCounts++
|
||||||
resolve(null)
|
resolve(null)
|
||||||
clearTimeout(this.skippedReiterationTimeout)
|
clearTimeout(this.skippedReiterationTimeout)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { expect, type Locator, type Page } from '@playwright/test'
|
import { expect, type Locator, type Page } from '@playwright/test'
|
||||||
import { NewIssue } from './types'
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { CommonTrackerPage } from './common-tracker-page'
|
|
||||||
import { attachScreenshot, iterateLocator } from '../../utils'
|
import { attachScreenshot, iterateLocator } from '../../utils'
|
||||||
|
import { CommonTrackerPage } from './common-tracker-page'
|
||||||
|
import { NewIssue } from './types'
|
||||||
|
|
||||||
export class IssuesPage extends CommonTrackerPage {
|
export class IssuesPage extends CommonTrackerPage {
|
||||||
readonly page: Page
|
readonly page: Page
|
||||||
@ -142,8 +142,14 @@ export class IssuesPage extends CommonTrackerPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async searchIssueByName (issueName: string): Promise<void> {
|
async searchIssueByName (issueName: string): Promise<void> {
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
await this.inputSearch.fill(issueName)
|
await this.inputSearch.fill(issueName)
|
||||||
await this.page.waitForTimeout(3000)
|
const v = await this.inputSearch.inputValue()
|
||||||
|
if (v === issueName) {
|
||||||
|
await this.inputSearch.press('Enter')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async openIssueByName (issueName: string): Promise<void> {
|
async openIssueByName (issueName: string): Promise<void> {
|
||||||
|
Loading…
Reference in New Issue
Block a user