mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-24 03:59:50 +03:00
Add next test button (#7247)
This commit is contained in:
parent
3775132777
commit
abdf2572e2
@ -160,6 +160,7 @@ export function createModel (builder: Builder): void {
|
||||
defineTestSuite(builder)
|
||||
defineTestCase(builder)
|
||||
defineTestRun(builder)
|
||||
defineTestResult(builder)
|
||||
|
||||
definePresenters(builder)
|
||||
|
||||
@ -261,7 +262,7 @@ function defineTestSuite (builder: Builder): void {
|
||||
// Actions
|
||||
|
||||
builder.mixin(testManagement.class.TestSuite, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [print.action.Print, tracker.action.EditRelatedTargets]
|
||||
actions: [print.action.Print, tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
|
||||
})
|
||||
|
||||
createAction(
|
||||
@ -331,7 +332,7 @@ function defineTestCase (builder: Builder): void {
|
||||
|
||||
builder.mixin(testManagement.class.TestCase, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['priority', 'status'],
|
||||
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn']
|
||||
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn', 'name']
|
||||
})
|
||||
|
||||
builder.createDoc(
|
||||
@ -419,6 +420,12 @@ function defineTestRun (builder: Builder): void {
|
||||
component: testManagement.component.TestResultStatusPresenter
|
||||
})
|
||||
|
||||
builder.mixin(testManagement.class.TestRun, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [print.action.Print, tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
|
||||
})
|
||||
}
|
||||
|
||||
function defineTestResult (builder: Builder): void {
|
||||
builder.mixin(testManagement.class.TestResult, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: testManagement.component.TestResultPresenter
|
||||
})
|
||||
@ -448,7 +455,7 @@ function defineTestRun (builder: Builder): void {
|
||||
|
||||
builder.mixin(testManagement.class.TestResult, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['assignee', 'status', 'testSuite'],
|
||||
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn']
|
||||
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn', 'name', 'attachedTo']
|
||||
})
|
||||
|
||||
const viewOptions: ViewOptionsModel = {
|
||||
|
@ -23,7 +23,8 @@ import type { ActionCategory } from '@hcengineering/view'
|
||||
export default mergeIds(testManagementId, testManganement, {
|
||||
category: {
|
||||
TestSuite: '' as Ref<ActionCategory>,
|
||||
TestCase: '' as Ref<ActionCategory>
|
||||
TestCase: '' as Ref<ActionCategory>,
|
||||
TestResult: '' as Ref<ActionCategory>
|
||||
},
|
||||
component: {
|
||||
CreateTestCase: '' as AnyComponent,
|
||||
|
@ -250,12 +250,15 @@ export class TTestResult extends TAttachedDoc implements TestResult {
|
||||
testCase!: Ref<TestCase>
|
||||
|
||||
@Prop(TypeRef(testManagement.class.TestSuite), testManagement.string.TestSuite)
|
||||
@Index(IndexKind.Indexed)
|
||||
testSuite?: Ref<TestSuite>
|
||||
|
||||
@Prop(TypeTestRunStatus(), testManagement.string.TestRunStatus)
|
||||
@Index(IndexKind.Indexed)
|
||||
status?: TestRunStatus
|
||||
|
||||
@Prop(TypeRef(contact.mixin.Employee), testManagement.string.TestAssignee)
|
||||
@Index(IndexKind.Indexed)
|
||||
assignee?: Ref<Employee>
|
||||
|
||||
@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files })
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Termín",
|
||||
"RunTestCases": "Spustit",
|
||||
"TestCaseDescription": "Popis testovacího případu",
|
||||
"TestResultAttributes": "Výsledek"
|
||||
"TestResultAttributes": "Výsledek",
|
||||
"GoToNextTest": "Další",
|
||||
"GoToNextTestTooltip": "Přejít na další test"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Due date",
|
||||
"RunTestCases": "Run",
|
||||
"TestCaseDescription": "Test case description",
|
||||
"TestResultAttributes": "Result"
|
||||
"TestResultAttributes": "Result",
|
||||
"GoToNextTest": "Next",
|
||||
"GoToNextTestTooltip": "Go to next test"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Fecha de vencimiento",
|
||||
"RunTestCases": "Ejecutar",
|
||||
"TestCaseDescription": "Descripción del caso de prueba",
|
||||
"TestResultAttributes": "Resultado"
|
||||
"TestResultAttributes": "Resultado",
|
||||
"GoToNextTest": "Siguiente",
|
||||
"GoToNextTestTooltip": "Ir al siguiente test"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Date d'échéance",
|
||||
"RunTestCases": "Exécuter",
|
||||
"TestCaseDescription": "Description du cas de test",
|
||||
"TestResultAttributes": "Résultat"
|
||||
"TestResultAttributes": "Résultat",
|
||||
"GoToNextTest": "Suivant",
|
||||
"GoToNextTestTooltip": "Aller au test suivant"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Data di scadenza",
|
||||
"RunTestCases": "Esegui",
|
||||
"TestCaseDescription": "Descrizione del caso di test",
|
||||
"TestResultAttributes": "Risultato"
|
||||
"TestResultAttributes": "Risultato",
|
||||
"GoToNextTest": "Successivo",
|
||||
"GoToNextTestTooltip": "Vai al test successivo"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Data de vencimento",
|
||||
"RunTestCases": "Executar",
|
||||
"TestCaseDescription": "Descrição do caso de teste",
|
||||
"TestResultAttributes": "Resultado"
|
||||
"TestResultAttributes": "Resultado",
|
||||
"GoToNextTest": "Próximo",
|
||||
"GoToNextTestTooltip": "Ir para o próximo teste"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "Выполнить до",
|
||||
"RunTestCases": "Выполнить",
|
||||
"TestCaseDescription": "Описание тест-кейса",
|
||||
"TestResultAttributes": "Результат"
|
||||
"TestResultAttributes": "Результат",
|
||||
"GoToNextTest": "Следующий",
|
||||
"GoToNextTestTooltip": "Перейти к следующему тесту"
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@
|
||||
"DueDate": "到期日",
|
||||
"RunTestCases": "运行",
|
||||
"TestCaseDescription": "測試用例描述",
|
||||
"TestResultAttributes": "結果"
|
||||
"TestResultAttributes": "結果",
|
||||
"GoToNextTest": "下一個",
|
||||
"GoToNextTestTooltip": "轉到下一個測試"
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
import { DocAttributeBar, getDocMixins } from '@hcengineering/view-resources'
|
||||
|
||||
import RightHeader from './RightHeader.svelte'
|
||||
import NextButton from './NextButton.svelte'
|
||||
import TestCaseDetails from '../test-case/TestCaseDetails.svelte'
|
||||
import testManagement from '../../plugin'
|
||||
|
||||
@ -92,6 +93,10 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="extra">
|
||||
<NextButton {object} />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="aside">
|
||||
<DocAttributeBar {object} {mixins} ignoreKeys={['name']} />
|
||||
<RightHeader>
|
||||
|
@ -0,0 +1,81 @@
|
||||
<!--
|
||||
// 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 { onMount, onDestroy } from 'svelte'
|
||||
import { Button, Loading, Location, navigate } from '@hcengineering/ui'
|
||||
import { initializeIterator, testResultIteratorProvider, testIteratorStore } from './store/testIteratorStore'
|
||||
import testManagement, { TestResult } from '@hcengineering/test-management'
|
||||
import { Doc, type DocumentQuery, WithLookup } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { getObjectLinkFragment } from '@hcengineering/view-resources'
|
||||
import view from '@hcengineering/view'
|
||||
|
||||
export let object: WithLookup<TestResult> | undefined
|
||||
let isLoading = true
|
||||
let hasNext = false
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
const unsubscribe = testIteratorStore.subscribe(() => {
|
||||
hasNext = testResultIteratorProvider.getIterator()?.hasNext() ?? false
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
const query: DocumentQuery<TestResult> = { attachedTo: object?.attachedTo } as any
|
||||
await initializeIterator(query, object?._id)
|
||||
hasNext = testResultIteratorProvider.getIterator()?.hasNext() ?? false
|
||||
isLoading = false
|
||||
})
|
||||
onDestroy(() => {
|
||||
testResultIteratorProvider.reset()
|
||||
unsubscribe()
|
||||
})
|
||||
|
||||
async function goToNextItem (): Promise<void> {
|
||||
const iterator = testResultIteratorProvider.getIterator()
|
||||
if (iterator !== undefined) {
|
||||
const nextItem = iterator.next()
|
||||
if (nextItem === undefined) {
|
||||
console.error('No next item')
|
||||
return
|
||||
}
|
||||
const link = await getLink(nextItem)
|
||||
if (link !== undefined) {
|
||||
navigate(link)
|
||||
}
|
||||
|
||||
console.log('Next item:', nextItem)
|
||||
}
|
||||
}
|
||||
|
||||
async function getLink (object: Doc): Promise<Location> {
|
||||
const { component } = hierarchy.classHierarchyMixin(testManagement.class.TestResult, view.mixin.ObjectPanel) as any
|
||||
return await getObjectLinkFragment(hierarchy, object, {}, component)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if isLoading}
|
||||
<Loading />
|
||||
{:else}
|
||||
<Button
|
||||
label={testManagement.string.GoToNextTest}
|
||||
kind={'primary'}
|
||||
icon={view.icon.ArrowRight}
|
||||
disabled={!hasNext}
|
||||
on:click={goToNextItem}
|
||||
showTooltip={{ label: testManagement.string.GoToNextTestTooltip }}
|
||||
/>
|
||||
{/if}
|
@ -0,0 +1,51 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import { writable, get } from 'svelte/store'
|
||||
import {
|
||||
type IteratorState,
|
||||
type StoreAdapter,
|
||||
ObjectIteratorProvider,
|
||||
getDefaultIteratorState
|
||||
} from '@hcengineering/view-resources'
|
||||
import testManagement, { type TestResult } from '@hcengineering/test-management'
|
||||
import type { DocumentQuery, Ref } from '@hcengineering/core'
|
||||
|
||||
export const testIteratorStore = writable<IteratorState<TestResult>>(getDefaultIteratorState<TestResult>({}))
|
||||
|
||||
const adapter: StoreAdapter<TestResult> = {
|
||||
set (value: IteratorState<TestResult>) {
|
||||
testIteratorStore.set(value)
|
||||
},
|
||||
update (updater: (value: IteratorState<TestResult>) => IteratorState<TestResult>) {
|
||||
testIteratorStore.update(updater)
|
||||
},
|
||||
get () {
|
||||
return get(testIteratorStore)
|
||||
}
|
||||
}
|
||||
|
||||
export const testResultIteratorProvider = new ObjectIteratorProvider<TestResult>(adapter)
|
||||
|
||||
export async function initializeIterator (
|
||||
query: DocumentQuery<TestResult>,
|
||||
currentObject: Ref<TestResult> | undefined
|
||||
): Promise<void> {
|
||||
await testResultIteratorProvider.initialize(testManagement.class.TestResult, query, currentObject)
|
||||
}
|
||||
|
||||
export function resetTestObjectIterator (): void {
|
||||
testResultIteratorProvider.reset()
|
||||
}
|
@ -185,7 +185,9 @@ export const testManagementPlugin = plugin(testManagementId, {
|
||||
TestResults: '' as IntlString,
|
||||
RunTestCases: '' as IntlString,
|
||||
TestCaseDescription: '' as IntlString,
|
||||
TestResultAttributes: '' as IntlString
|
||||
TestResultAttributes: '' as IntlString,
|
||||
GoToNextTest: '' as IntlString,
|
||||
GoToNextTestTooltip: '' as IntlString
|
||||
},
|
||||
category: {
|
||||
TestManagement: '' as Ref<ActionCategory>
|
||||
|
142
plugins/view-resources/src/__tests__/objectIterator.test.ts
Normal file
142
plugins/view-resources/src/__tests__/objectIterator.test.ts
Normal file
@ -0,0 +1,142 @@
|
||||
// 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.
|
||||
import { ObjectIterator, type StoreAdapter, type IteratorState, ObjectIteratorProvider } from '../objectIterator'
|
||||
import { type DocumentQuery, type Doc, type Ref, type Class } from '@hcengineering/core'
|
||||
|
||||
let mockObjects: Doc[] = []
|
||||
const findAll = jest.fn(() => mockObjects)
|
||||
jest.mock('@hcengineering/presentation', () => ({
|
||||
getClient: jest.fn(() => ({
|
||||
findAll
|
||||
}))
|
||||
}))
|
||||
|
||||
describe('ObjectIterator', () => {
|
||||
let storeAdapter: StoreAdapter<Doc>
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
let state: IteratorState<Doc> = {
|
||||
query: {},
|
||||
currentObjects: [],
|
||||
iteratorIndex: 0,
|
||||
limit: 0
|
||||
}
|
||||
storeAdapter = {
|
||||
set: jest.fn((newState) => {
|
||||
state = newState
|
||||
}),
|
||||
update: jest.fn((updater) => {
|
||||
state = updater(state)
|
||||
}),
|
||||
get: jest.fn(() => state)
|
||||
}
|
||||
})
|
||||
|
||||
it('should initialize the store with the given query', async () => {
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new ObjectIterator(_class, query, storeAdapter)
|
||||
expect(storeAdapter.set).toHaveBeenCalledWith({
|
||||
query,
|
||||
currentObjects: [],
|
||||
iteratorIndex: 0,
|
||||
limit: 100
|
||||
})
|
||||
})
|
||||
|
||||
it('should load objects and update the store', async () => {
|
||||
mockObjects = [{ id: '1' }, { id: '2' }] as any
|
||||
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
|
||||
const iterator = new ObjectIterator(_class, query, storeAdapter)
|
||||
await iterator.loadObjects(undefined)
|
||||
|
||||
expect(findAll).toHaveBeenCalledWith(_class, query, {
|
||||
limit: 100,
|
||||
total: true
|
||||
})
|
||||
expect(storeAdapter.update).toHaveBeenCalledWith(expect.any(Function))
|
||||
const state = storeAdapter.get()
|
||||
expect(state?.currentObjects.length).toBe(2)
|
||||
expect(state?.iteratorIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should return the next object and update the iterator', async () => {
|
||||
mockObjects = [{ id: '1' }, { id: '2' }, { id: '3' }] as any
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
const iterator = new ObjectIterator(_class, query, storeAdapter)
|
||||
await iterator.loadObjects(undefined)
|
||||
let nextObject = iterator.next()
|
||||
|
||||
expect(nextObject).toEqual(mockObjects[0])
|
||||
expect(storeAdapter.update).toHaveBeenCalledWith(expect.any(Function))
|
||||
|
||||
nextObject = iterator.next()
|
||||
expect(nextObject).toEqual(mockObjects[1])
|
||||
|
||||
nextObject = iterator.next()
|
||||
expect(nextObject).toEqual(mockObjects[2])
|
||||
|
||||
nextObject = iterator.next()
|
||||
expect(nextObject).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined for empty array', async () => {
|
||||
mockObjects = [] as any
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
const iterator = new ObjectIterator(_class, query, storeAdapter)
|
||||
await iterator.loadObjects(undefined)
|
||||
const nextObject = iterator.next()
|
||||
|
||||
expect(nextObject).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should not create a new ObjectIterator if already defined', async () => {
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
const provider = new ObjectIteratorProvider(storeAdapter)
|
||||
|
||||
await provider.initialize(_class, query, undefined)
|
||||
const firstIterator = provider.getIterator()
|
||||
|
||||
await provider.initialize(_class, query, undefined)
|
||||
const secondIterator = provider.getIterator()
|
||||
|
||||
expect(firstIterator).toBe(secondIterator)
|
||||
expect(firstIterator).toBeDefined()
|
||||
})
|
||||
|
||||
it('should reset the state of ObjectIterator', async () => {
|
||||
const query: DocumentQuery<Doc> = { key: 'value' }
|
||||
const _class: Ref<Class<Doc>> = { id: 'class1' } as any
|
||||
const provider = new ObjectIteratorProvider(storeAdapter)
|
||||
|
||||
await provider.initialize(_class, query, undefined)
|
||||
provider.reset()
|
||||
|
||||
expect(storeAdapter.set).toHaveBeenCalledWith({
|
||||
query: {},
|
||||
currentObjects: [],
|
||||
iteratorIndex: 0,
|
||||
limit: 100
|
||||
})
|
||||
})
|
||||
})
|
@ -175,6 +175,7 @@ export * from './middleware'
|
||||
export * from './selection'
|
||||
export * from './status'
|
||||
export * from './utils'
|
||||
export * from './objectIterator'
|
||||
export {
|
||||
buildModel,
|
||||
getActiveViewletId,
|
||||
|
113
plugins/view-resources/src/objectIterator.ts
Normal file
113
plugins/view-resources/src/objectIterator.ts
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
import type { DocumentQuery, Doc, Ref, Class } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export interface IteratorState<T extends Doc> {
|
||||
query: DocumentQuery<T>
|
||||
currentObjects: T[]
|
||||
iteratorIndex: number
|
||||
limit: number
|
||||
}
|
||||
|
||||
export interface StoreAdapter<T extends Doc> {
|
||||
set: (value: IteratorState<T>) => void
|
||||
update: (updater: (value: IteratorState<T>) => IteratorState<T>) => void
|
||||
get: () => IteratorState<T>
|
||||
}
|
||||
|
||||
export function getDefaultIteratorState<T extends Doc> (query: DocumentQuery<T>): IteratorState<T> {
|
||||
return {
|
||||
query,
|
||||
currentObjects: [],
|
||||
iteratorIndex: 0,
|
||||
limit: 100
|
||||
}
|
||||
}
|
||||
|
||||
export class ObjectIterator<T extends Doc> {
|
||||
private readonly storeAdapter: StoreAdapter<T>
|
||||
private readonly class: Ref<Class<T>>
|
||||
|
||||
constructor (_class: Ref<Class<T>>, query: DocumentQuery<T>, storeAdapter: StoreAdapter<T>) {
|
||||
this.class = _class
|
||||
this.storeAdapter = storeAdapter
|
||||
this.storeAdapter.set(getDefaultIteratorState<T>(query))
|
||||
}
|
||||
|
||||
async loadObjects (currentObject: Ref<Doc> | undefined): Promise<void> {
|
||||
const client = getClient()
|
||||
const { query, limit } = this.storeAdapter.get()
|
||||
const testResults = await client.findAll(this.class, query, {
|
||||
limit,
|
||||
total: true
|
||||
})
|
||||
this.storeAdapter.update((store) => {
|
||||
store.currentObjects = [...store.currentObjects, ...testResults]
|
||||
store.limit = testResults.total
|
||||
if (currentObject !== undefined) {
|
||||
store.iteratorIndex = store.currentObjects.findIndex((obj) => obj._id === currentObject) ?? 0
|
||||
}
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
||||
next (): T | undefined {
|
||||
let nextObject
|
||||
this.storeAdapter.update((store) => {
|
||||
if (store.iteratorIndex < store.currentObjects.length) {
|
||||
store.iteratorIndex += 1
|
||||
nextObject = store.currentObjects[store.iteratorIndex]
|
||||
}
|
||||
return store
|
||||
})
|
||||
return nextObject
|
||||
}
|
||||
|
||||
hasNext (): boolean {
|
||||
const { currentObjects, iteratorIndex } = this.storeAdapter.get()
|
||||
return iteratorIndex < currentObjects.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
export class ObjectIteratorProvider<T extends Doc> {
|
||||
private objectIterator: ObjectIterator<T> | undefined = undefined
|
||||
|
||||
constructor (private readonly storeAdapter: StoreAdapter<T>) {}
|
||||
|
||||
async initialize (_class: Ref<Class<T>>, query: DocumentQuery<T>, currentObject: Ref<Doc> | undefined): Promise<void> {
|
||||
if (this.objectIterator === undefined) {
|
||||
this.objectIterator = new ObjectIterator(_class, query, this.storeAdapter)
|
||||
await this.objectIterator.loadObjects(currentObject)
|
||||
}
|
||||
}
|
||||
|
||||
reset (): void {
|
||||
this.objectIterator = undefined
|
||||
this.storeAdapter.set(getDefaultIteratorState<T>({}))
|
||||
}
|
||||
|
||||
getObject (): T | undefined {
|
||||
if (this.objectIterator === undefined) {
|
||||
console.error('ObjectIterator is not initialized')
|
||||
return undefined
|
||||
}
|
||||
return this.objectIterator?.next()
|
||||
}
|
||||
|
||||
getIterator (): ObjectIterator<T> | undefined {
|
||||
return this.objectIterator
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user