refactor(core): workspace mutation effect (#12488)
### TL;DR * refactor: workspace embedding mutation effect * tests: error display for workspace embedding
This commit is contained in:
@@ -11,15 +11,8 @@ import {
|
|||||||
onStart,
|
onStart,
|
||||||
smartRetry,
|
smartRetry,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
import { EMPTY, interval, of, Subject } from 'rxjs';
|
import { EMPTY, interval, Subject } from 'rxjs';
|
||||||
import {
|
import { exhaustMap, mergeMap, switchMap, takeUntil } from 'rxjs/operators';
|
||||||
concatMap,
|
|
||||||
exhaustMap,
|
|
||||||
mergeMap,
|
|
||||||
switchMap,
|
|
||||||
takeUntil,
|
|
||||||
tap,
|
|
||||||
} from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { COUNT_PER_PAGE } from '../constants';
|
import { COUNT_PER_PAGE } from '../constants';
|
||||||
import type { EmbeddingStore } from '../stores/embedding';
|
import type { EmbeddingStore } from '../stores/embedding';
|
||||||
@@ -110,31 +103,13 @@ export class Embedding extends Entity {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
setEnabled = effect(
|
setEnabled = (enabled: boolean) => {
|
||||||
exhaustMap((enabled: boolean) => {
|
return this.store
|
||||||
return fromPromise(signal =>
|
.updateEnabled(this.workspaceService.workspace.id, enabled)
|
||||||
this.store.updateEnabled(
|
.then(() => {
|
||||||
this.workspaceService.workspace.id,
|
|
||||||
enabled,
|
|
||||||
signal
|
|
||||||
)
|
|
||||||
).pipe(
|
|
||||||
smartRetry(),
|
|
||||||
concatMap(() => {
|
|
||||||
this.getEnabled();
|
this.getEnabled();
|
||||||
return EMPTY;
|
});
|
||||||
}),
|
};
|
||||||
catchErrorInto(this.error$, error => {
|
|
||||||
logger.error(
|
|
||||||
'Failed to update workspace doc embedding enabled',
|
|
||||||
error
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
onStart(() => this.isEnabledLoading$.setValue(true)),
|
|
||||||
onComplete(() => this.isEnabledLoading$.setValue(false))
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
getIgnoredDocs = effect(
|
getIgnoredDocs = effect(
|
||||||
exhaustMap(() => {
|
exhaustMap(() => {
|
||||||
@@ -158,30 +133,19 @@ export class Embedding extends Entity {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
updateIgnoredDocs = effect(
|
updateIgnoredDocs = ({
|
||||||
exhaustMap(({ add, remove }: { add: string[]; remove: string[] }) => {
|
|
||||||
return fromPromise(signal =>
|
|
||||||
this.store.updateIgnoredDocs(
|
|
||||||
this.workspaceService.workspace.id,
|
|
||||||
add,
|
add,
|
||||||
remove,
|
remove,
|
||||||
signal
|
}: {
|
||||||
)
|
add: string[];
|
||||||
).pipe(
|
remove: string[];
|
||||||
smartRetry(),
|
}) => {
|
||||||
concatMap(() => {
|
return this.store
|
||||||
|
.updateIgnoredDocs(this.workspaceService.workspace.id, add, remove)
|
||||||
|
.then(() => {
|
||||||
this.getIgnoredDocs();
|
this.getIgnoredDocs();
|
||||||
return EMPTY;
|
});
|
||||||
}),
|
};
|
||||||
catchErrorInto(this.error$, error => {
|
|
||||||
logger.error(
|
|
||||||
'Failed to update workspace doc embedding ignored docs',
|
|
||||||
error
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
getAttachments = effect(
|
getAttachments = effect(
|
||||||
exhaustMap((pagination: PaginationInput) => {
|
exhaustMap((pagination: PaginationInput) => {
|
||||||
@@ -219,9 +183,7 @@ export class Embedding extends Entity {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
addAttachments = effect(
|
addAttachments = (files: File[]) => {
|
||||||
// Support parallel upload
|
|
||||||
mergeMap((files: File[]) => {
|
|
||||||
const generateLocalId = () =>
|
const generateLocalId = () =>
|
||||||
Math.random().toString(36).slice(2) + Date.now();
|
Math.random().toString(36).slice(2) + Date.now();
|
||||||
const localAttachments: LocalAttachmentFile[] = files.map(file => ({
|
const localAttachments: LocalAttachmentFile[] = files.map(file => ({
|
||||||
@@ -233,34 +195,22 @@ export class Embedding extends Entity {
|
|||||||
status: 'uploading',
|
status: 'uploading',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return of({ files, localAttachments }).pipe(
|
|
||||||
// Refresh uploading attachments immediately
|
|
||||||
tap(({ localAttachments }) => {
|
|
||||||
this.uploadingAttachments$.next([
|
this.uploadingAttachments$.next([
|
||||||
...localAttachments,
|
...localAttachments,
|
||||||
...this.uploadingAttachments$.value,
|
...this.uploadingAttachments$.value,
|
||||||
]);
|
]);
|
||||||
}),
|
|
||||||
// Uploading embedding files
|
this.store
|
||||||
switchMap(({ files }) => {
|
.addEmbeddingFiles(this.workspaceService.workspace.id, files)
|
||||||
return fromPromise(signal =>
|
.then(() => {
|
||||||
this.store.addEmbeddingFiles(
|
|
||||||
this.workspaceService.workspace.id,
|
|
||||||
files,
|
|
||||||
signal
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
// Refresh uploading attachments
|
|
||||||
tap(() => {
|
|
||||||
this.uploadingAttachments$.next(
|
this.uploadingAttachments$.next(
|
||||||
this.uploadingAttachments$.value.filter(
|
this.uploadingAttachments$.value.filter(
|
||||||
att => !localAttachments.some(l => l.localId === att.localId)
|
att => !localAttachments.some(l => l.localId === att.localId)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.getAttachments({ first: COUNT_PER_PAGE, after: null });
|
this.getAttachments({ first: COUNT_PER_PAGE, after: null });
|
||||||
}),
|
})
|
||||||
catchErrorInto(this.error$, error => {
|
.catch(error => {
|
||||||
this.uploadingAttachments$.next(
|
this.uploadingAttachments$.next(
|
||||||
this.uploadingAttachments$.value.map(att =>
|
this.uploadingAttachments$.value.map(att =>
|
||||||
localAttachments.some(l => l.localId === att.localId)
|
localAttachments.some(l => l.localId === att.localId)
|
||||||
@@ -268,17 +218,10 @@ export class Embedding extends Entity {
|
|||||||
: att
|
: att
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
logger.error(
|
});
|
||||||
'Failed to add workspace doc embedding attachments',
|
};
|
||||||
error
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
removeAttachment = effect(
|
removeAttachment = (id: string) => {
|
||||||
exhaustMap((id: string) => {
|
|
||||||
const localIndex = this.uploadingAttachments$.value.findIndex(
|
const localIndex = this.uploadingAttachments$.value.findIndex(
|
||||||
att => att.localId === id
|
att => att.localId === id
|
||||||
);
|
);
|
||||||
@@ -286,28 +229,14 @@ export class Embedding extends Entity {
|
|||||||
this.uploadingAttachments$.next(
|
this.uploadingAttachments$.next(
|
||||||
this.uploadingAttachments$.value.filter(att => att.localId !== id)
|
this.uploadingAttachments$.value.filter(att => att.localId !== id)
|
||||||
);
|
);
|
||||||
return EMPTY;
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return fromPromise(signal =>
|
return this.store
|
||||||
this.store.removeEmbeddingFile(
|
.removeEmbeddingFile(this.workspaceService.workspace.id, id)
|
||||||
this.workspaceService.workspace.id,
|
.then(() => {
|
||||||
id,
|
|
||||||
signal
|
|
||||||
)
|
|
||||||
).pipe(
|
|
||||||
concatMap(() => {
|
|
||||||
this.getAttachments({ first: COUNT_PER_PAGE, after: null });
|
this.getAttachments({ first: COUNT_PER_PAGE, after: null });
|
||||||
return EMPTY;
|
});
|
||||||
}),
|
};
|
||||||
catchErrorInto(this.error$, error => {
|
|
||||||
logger.error(
|
|
||||||
'Failed to remove workspace doc embedding attachment',
|
|
||||||
error
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
startEmbeddingProgressPolling() {
|
startEmbeddingProgressPolling() {
|
||||||
this.stopEmbeddingProgressPolling();
|
this.stopEmbeddingProgressPolling();
|
||||||
@@ -355,10 +284,6 @@ export class Embedding extends Entity {
|
|||||||
this.getEnabled.unsubscribe();
|
this.getEnabled.unsubscribe();
|
||||||
this.getAttachments.unsubscribe();
|
this.getAttachments.unsubscribe();
|
||||||
this.getIgnoredDocs.unsubscribe();
|
this.getIgnoredDocs.unsubscribe();
|
||||||
this.updateIgnoredDocs.unsubscribe();
|
|
||||||
this.addAttachments.unsubscribe();
|
|
||||||
this.removeAttachment.unsubscribe();
|
|
||||||
this.setEnabled.unsubscribe();
|
|
||||||
this.stopEmbeddingProgress$.next();
|
this.stopEmbeddingProgress$.next();
|
||||||
this.getEmbeddingProgress.unsubscribe();
|
this.getEmbeddingProgress.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Button, Switch } from '@affine/component';
|
import { Button, notify, Switch } from '@affine/component';
|
||||||
import {
|
import {
|
||||||
SettingHeader,
|
SettingHeader,
|
||||||
SettingRow,
|
SettingRow,
|
||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from '@affine/component/setting-components';
|
} from '@affine/component/setting-components';
|
||||||
import { Upload } from '@affine/core/components/pure/file-upload';
|
import { Upload } from '@affine/core/components/pure/file-upload';
|
||||||
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
|
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
|
||||||
|
import { UserFriendlyError } from '@affine/error';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import track from '@affine/track';
|
import track from '@affine/track';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
@@ -48,9 +49,19 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
|
|||||||
control: 'Workspace embedding',
|
control: 'Workspace embedding',
|
||||||
option: checked ? 'on' : 'off',
|
option: checked ? 'on' : 'off',
|
||||||
});
|
});
|
||||||
embeddingService.embedding.setEnabled(checked);
|
|
||||||
|
embeddingService.embedding.setEnabled(checked).catch(error => {
|
||||||
|
const err = UserFriendlyError.fromAny(error);
|
||||||
|
notify.error({
|
||||||
|
title:
|
||||||
|
t[
|
||||||
|
'com.affine.settings.workspace.indexer-embedding.embedding.switch.error'
|
||||||
|
](),
|
||||||
|
message: t[`error.${err.name}`](err.data),
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[embeddingService.embedding]
|
[embeddingService.embedding, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAttachmentUpload = useCallback(
|
const handleAttachmentUpload = useCallback(
|
||||||
@@ -67,9 +78,18 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
|
|||||||
|
|
||||||
const handleAttachmentsDelete = useCallback(
|
const handleAttachmentsDelete = useCallback(
|
||||||
(fileId: string) => {
|
(fileId: string) => {
|
||||||
embeddingService.embedding.removeAttachment(fileId);
|
embeddingService.embedding.removeAttachment(fileId).catch(error => {
|
||||||
|
const err = UserFriendlyError.fromAny(error);
|
||||||
|
notify.error({
|
||||||
|
title:
|
||||||
|
t[
|
||||||
|
'com.affine.settings.workspace.indexer-embedding.embedding.remove-attachment.error'
|
||||||
|
](),
|
||||||
|
message: t[`error.${err.name}`](err.data),
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[embeddingService.embedding]
|
[embeddingService.embedding, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAttachmentsPageChange = useCallback(
|
const handleAttachmentsPageChange = useCallback(
|
||||||
@@ -102,7 +122,18 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
|
|||||||
});
|
});
|
||||||
const add = selectedIds.filter(id => !initialIds?.includes(id));
|
const add = selectedIds.filter(id => !initialIds?.includes(id));
|
||||||
const remove = initialIds?.filter(id => !selectedIds.includes(id));
|
const remove = initialIds?.filter(id => !selectedIds.includes(id));
|
||||||
embeddingService.embedding.updateIgnoredDocs({ add, remove });
|
embeddingService.embedding
|
||||||
|
.updateIgnoredDocs({ add, remove })
|
||||||
|
.catch(error => {
|
||||||
|
const err = UserFriendlyError.fromAny(error);
|
||||||
|
notify.error({
|
||||||
|
title:
|
||||||
|
t[
|
||||||
|
'com.affine.settings.workspace.indexer-embedding.embedding.update-ignored-docs.error'
|
||||||
|
](),
|
||||||
|
message: t[`error.${err.name}`](err.data),
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
@@ -110,6 +141,7 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
|
|||||||
isIgnoredDocsLoading,
|
isIgnoredDocsLoading,
|
||||||
workspaceDialogService,
|
workspaceDialogService,
|
||||||
embeddingService.embedding,
|
embeddingService.embedding,
|
||||||
|
t,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -6247,6 +6247,18 @@ export function useAFFiNEI18N(): {
|
|||||||
* `AI can call files embedded in the workspace.`
|
* `AI can call files embedded in the workspace.`
|
||||||
*/
|
*/
|
||||||
["com.affine.settings.workspace.indexer-embedding.embedding.switch.description"](): string;
|
["com.affine.settings.workspace.indexer-embedding.embedding.switch.description"](): string;
|
||||||
|
/**
|
||||||
|
* `Failed to update workspace doc embedding enabled`
|
||||||
|
*/
|
||||||
|
["com.affine.settings.workspace.indexer-embedding.embedding.switch.error"](): string;
|
||||||
|
/**
|
||||||
|
* `Failed to remove attachment from embedding`
|
||||||
|
*/
|
||||||
|
["com.affine.settings.workspace.indexer-embedding.embedding.remove-attachment.error"](): string;
|
||||||
|
/**
|
||||||
|
* `Failed to update ignored docs`
|
||||||
|
*/
|
||||||
|
["com.affine.settings.workspace.indexer-embedding.embedding.update-ignored-docs.error"](): string;
|
||||||
/**
|
/**
|
||||||
* `Embedding progress`
|
* `Embedding progress`
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1560,6 +1560,9 @@
|
|||||||
"com.affine.settings.workspace.indexer-embedding.embedding.select-doc": "Select doc",
|
"com.affine.settings.workspace.indexer-embedding.embedding.select-doc": "Select doc",
|
||||||
"com.affine.settings.workspace.indexer-embedding.embedding.switch.title": "Workspace Embedding",
|
"com.affine.settings.workspace.indexer-embedding.embedding.switch.title": "Workspace Embedding",
|
||||||
"com.affine.settings.workspace.indexer-embedding.embedding.switch.description": "AI can call files embedded in the workspace.",
|
"com.affine.settings.workspace.indexer-embedding.embedding.switch.description": "AI can call files embedded in the workspace.",
|
||||||
|
"com.affine.settings.workspace.indexer-embedding.embedding.switch.error": "Failed to update workspace doc embedding enabled",
|
||||||
|
"com.affine.settings.workspace.indexer-embedding.embedding.remove-attachment.error": "Failed to remove attachment from embedding",
|
||||||
|
"com.affine.settings.workspace.indexer-embedding.embedding.update-ignored-docs.error": "Failed to update ignored docs",
|
||||||
"com.affine.settings.workspace.indexer-embedding.embedding.progress.title": "Embedding progress",
|
"com.affine.settings.workspace.indexer-embedding.embedding.progress.title": "Embedding progress",
|
||||||
"com.affine.settings.workspace.indexer-embedding.embedding.progress.syncing": "Syncing",
|
"com.affine.settings.workspace.indexer-embedding.embedding.progress.syncing": "Syncing",
|
||||||
"com.affine.settings.workspace.indexer-embedding.embedding.progress.synced": "Synced",
|
"com.affine.settings.workspace.indexer-embedding.embedding.progress.synced": "Synced",
|
||||||
|
|||||||
@@ -43,6 +43,23 @@ test.describe('AISettings/Embedding', () => {
|
|||||||
await utils.settings.waitForWorkspaceEmbeddingSwitchToBe(page, true);
|
await utils.settings.waitForWorkspaceEmbeddingSwitchToBe(page, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should show error message if enable workspace embedding failed', async ({
|
||||||
|
loggedInPage: page,
|
||||||
|
utils,
|
||||||
|
}) => {
|
||||||
|
await utils.settings.enableWorkspaceEmbedding(page);
|
||||||
|
await utils.settings.disableWorkspaceEmbedding(page);
|
||||||
|
await utils.settings.waitForWorkspaceEmbeddingSwitchToBe(page, false);
|
||||||
|
|
||||||
|
await page.context().setOffline(true);
|
||||||
|
await utils.settings.enableWorkspaceEmbedding(page, false);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText(/Failed to update workspace doc embedding enabled/i)
|
||||||
|
).toBeVisible();
|
||||||
|
await page.context().setOffline(false);
|
||||||
|
});
|
||||||
|
|
||||||
test('should show embedding progress', async ({
|
test('should show embedding progress', async ({
|
||||||
loggedInPage: page,
|
loggedInPage: page,
|
||||||
utils,
|
utils,
|
||||||
@@ -297,6 +314,36 @@ test.describe('AISettings/Embedding', () => {
|
|||||||
await utils.settings.removeAttachment(page, 'document1.txt');
|
await utils.settings.removeAttachment(page, 'document1.txt');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should show error message if remove attachment failed', async ({
|
||||||
|
loggedInPage: page,
|
||||||
|
utils,
|
||||||
|
}) => {
|
||||||
|
await utils.settings.enableWorkspaceEmbedding(page);
|
||||||
|
const textContent = 'WorkspaceEBEEE is a cute cat';
|
||||||
|
const attachments = [
|
||||||
|
{
|
||||||
|
name: 'document1.txt',
|
||||||
|
mimeType: 'text/plain',
|
||||||
|
buffer: Buffer.from(textContent),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await utils.settings.uploadWorkspaceEmbedding(page, attachments);
|
||||||
|
|
||||||
|
const attachmentList = await page.getByTestId(
|
||||||
|
'workspace-embedding-setting-attachment-list'
|
||||||
|
);
|
||||||
|
await expect(
|
||||||
|
attachmentList.getByTestId('workspace-embedding-setting-attachment-item')
|
||||||
|
).toHaveCount(1);
|
||||||
|
|
||||||
|
await page.context().setOffline(true);
|
||||||
|
await utils.settings.clickRemoveAttachment(page, 'document1.txt');
|
||||||
|
await expect(
|
||||||
|
page.getByText(/Failed to remove attachment from embedding/i)
|
||||||
|
).toBeVisible();
|
||||||
|
await page.context().setOffline(false);
|
||||||
|
});
|
||||||
|
|
||||||
test('should support remove error attachment directly', async ({
|
test('should support remove error attachment directly', async ({
|
||||||
loggedInPage: page,
|
loggedInPage: page,
|
||||||
utils,
|
utils,
|
||||||
@@ -393,4 +440,23 @@ test.describe('AISettings/Embedding', () => {
|
|||||||
expect(content).toMatch(/I dont know/i);
|
expect(content).toMatch(/I dont know/i);
|
||||||
}).toPass({ timeout: 20000 });
|
}).toPass({ timeout: 20000 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should show error message if update ignored docs failed', async ({
|
||||||
|
loggedInPage: page,
|
||||||
|
utils,
|
||||||
|
}) => {
|
||||||
|
await utils.settings.enableWorkspaceEmbedding(page);
|
||||||
|
await utils.settings.closeSettingsPanel(page);
|
||||||
|
|
||||||
|
await utils.editor.createDoc(page, 'Test Doc', 'HelloWorld');
|
||||||
|
|
||||||
|
// Ignore docs
|
||||||
|
await utils.settings.openSettingsPanel(page);
|
||||||
|
await page.context().setOffline(true);
|
||||||
|
await utils.settings.ignoreDocForEmbedding(page, 'Test Doc', false);
|
||||||
|
await expect(
|
||||||
|
page.getByText(/Failed to update ignored docs/i)
|
||||||
|
).toBeVisible();
|
||||||
|
await page.context().setOffline(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,21 +46,31 @@ export class SettingsPanelUtils {
|
|||||||
await input.click();
|
await input.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async enableWorkspaceEmbedding(page: Page) {
|
public static async enableWorkspaceEmbedding(
|
||||||
|
page: Page,
|
||||||
|
waitForEnabled = true
|
||||||
|
) {
|
||||||
const enabled = await this.isWorkspaceEmbeddingEnabled(page);
|
const enabled = await this.isWorkspaceEmbeddingEnabled(page);
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
await this.toggleWorkspaceEmbedding(page);
|
await this.toggleWorkspaceEmbedding(page);
|
||||||
}
|
}
|
||||||
|
if (waitForEnabled) {
|
||||||
await this.waitForWorkspaceEmbeddingSwitchToBe(page, true);
|
await this.waitForWorkspaceEmbeddingSwitchToBe(page, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async disableWorkspaceEmbedding(page: Page) {
|
public static async disableWorkspaceEmbedding(
|
||||||
|
page: Page,
|
||||||
|
waitForDisabled = true
|
||||||
|
) {
|
||||||
const enabled = await this.isWorkspaceEmbeddingEnabled(page);
|
const enabled = await this.isWorkspaceEmbeddingEnabled(page);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
await this.toggleWorkspaceEmbedding(page);
|
await this.toggleWorkspaceEmbedding(page);
|
||||||
}
|
}
|
||||||
|
if (waitForDisabled) {
|
||||||
await this.waitForWorkspaceEmbeddingSwitchToBe(page, false);
|
await this.waitForWorkspaceEmbeddingSwitchToBe(page, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async uploadWorkspaceEmbedding(
|
public static async uploadWorkspaceEmbedding(
|
||||||
page: Page,
|
page: Page,
|
||||||
@@ -102,7 +112,7 @@ export class SettingsPanelUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async removeAttachment(
|
public static async clickRemoveAttachment(
|
||||||
page: Page,
|
page: Page,
|
||||||
attachment: string,
|
attachment: string,
|
||||||
shouldConfirm = true
|
shouldConfirm = true
|
||||||
@@ -116,6 +126,14 @@ export class SettingsPanelUtils {
|
|||||||
if (shouldConfirm) {
|
if (shouldConfirm) {
|
||||||
await page.getByTestId('confirm-modal-confirm').click();
|
await page.getByTestId('confirm-modal-confirm').click();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async removeAttachment(
|
||||||
|
page: Page,
|
||||||
|
attachment: string,
|
||||||
|
shouldConfirm = true
|
||||||
|
) {
|
||||||
|
await this.clickRemoveAttachment(page, attachment, shouldConfirm);
|
||||||
await page
|
await page
|
||||||
.getByTestId('workspace-embedding-setting-attachment-item')
|
.getByTestId('workspace-embedding-setting-attachment-item')
|
||||||
.filter({ hasText: attachment })
|
.filter({ hasText: attachment })
|
||||||
@@ -124,7 +142,11 @@ export class SettingsPanelUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ignoreDocForEmbedding(page: Page, doc: string) {
|
public static async ignoreDocForEmbedding(
|
||||||
|
page: Page,
|
||||||
|
doc: string,
|
||||||
|
shouldWaitForRefresh = true
|
||||||
|
) {
|
||||||
// Open Dos Searcher
|
// Open Dos Searcher
|
||||||
const ignoreDocsButton = await page.getByTestId(
|
const ignoreDocsButton = await page.getByTestId(
|
||||||
'workspace-embedding-setting-ignore-docs-button'
|
'workspace-embedding-setting-ignore-docs-button'
|
||||||
@@ -137,17 +159,15 @@ export class SettingsPanelUtils {
|
|||||||
await searchInput.focus();
|
await searchInput.focus();
|
||||||
await page.keyboard.insertText(doc);
|
await page.keyboard.insertText(doc);
|
||||||
|
|
||||||
const pageListItem = searcher.getByTestId('page-list-item');
|
const pageListItem = searcher.getByTestId('doc-list-item');
|
||||||
await expect(pageListItem).toHaveCount(1);
|
await expect(pageListItem).toHaveCount(1);
|
||||||
const pageListItemTitle = pageListItem.getByTestId(
|
const pageListItemTitle = pageListItem.getByTestId('doc-list-item-title');
|
||||||
'page-list-item-title-text'
|
|
||||||
);
|
|
||||||
await expect(pageListItemTitle).toHaveText(doc);
|
await expect(pageListItemTitle).toHaveText(doc);
|
||||||
|
await pageListItem.click();
|
||||||
await pageListItem.getByTestId('affine-checkbox').check();
|
|
||||||
|
|
||||||
await searcher.getByTestId('doc-selector-confirm-button').click();
|
await searcher.getByTestId('doc-selector-confirm-button').click();
|
||||||
|
|
||||||
|
if (shouldWaitForRefresh) {
|
||||||
const ignoredDocs = await page.getByTestId(
|
const ignoredDocs = await page.getByTestId(
|
||||||
'workspace-embedding-setting-ignore-docs-list'
|
'workspace-embedding-setting-ignore-docs-list'
|
||||||
);
|
);
|
||||||
@@ -157,6 +177,7 @@ export class SettingsPanelUtils {
|
|||||||
.filter({ hasText: doc })
|
.filter({ hasText: doc })
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async clearAllIgnoredDocs(page: Page) {
|
public static async clearAllIgnoredDocs(page: Page) {
|
||||||
const ignoredDocs = await page.getByTestId('ignore-doc-title').all();
|
const ignoredDocs = await page.getByTestId('ignore-doc-title').all();
|
||||||
|
|||||||
Reference in New Issue
Block a user