feat(core): add default filter rules for all docs (#12197)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a filter to exclude empty journals from document collections. - Added a live-updating list of non-trashed document IDs for improved document management. - **Improvements** - Default filters in the document explorer have been updated to show all items, including trashed ones, unless filters are applied. - Enhanced filtering in workspace views to automatically exclude empty journals and trashed documents. - Increased the responsiveness of grouped document updates for a smoother user experience. - **Bug Fixes** - Removed unnecessary debug output from the document synchronization, member search, session management, and member selector components. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -27,14 +27,7 @@ export const createDocExplorerContext = () =>
|
|||||||
selectMode$: new LiveData<boolean>(false),
|
selectMode$: new LiveData<boolean>(false),
|
||||||
selectedDocIds$: new LiveData<string[]>([]),
|
selectedDocIds$: new LiveData<string[]>([]),
|
||||||
prevCheckAnchorId$: new LiveData<string | null>(null),
|
prevCheckAnchorId$: new LiveData<string | null>(null),
|
||||||
filters$: new LiveData<ExplorerPreference['filters']>([
|
filters$: new LiveData<ExplorerPreference['filters']>([]),
|
||||||
{
|
|
||||||
type: 'system',
|
|
||||||
key: 'trash',
|
|
||||||
value: 'false',
|
|
||||||
method: 'is',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
groupBy$: new LiveData<ExplorerPreference['groupBy']>(undefined),
|
groupBy$: new LiveData<ExplorerPreference['groupBy']>(undefined),
|
||||||
orderBy$: new LiveData<ExplorerPreference['orderBy']>(undefined),
|
orderBy$: new LiveData<ExplorerPreference['orderBy']>(undefined),
|
||||||
displayProperties$: new LiveData<ExplorerPreference['displayProperties']>(
|
displayProperties$: new LiveData<ExplorerPreference['displayProperties']>(
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export const MemberSelector = ({
|
|||||||
if (value.length > 0) {
|
if (value.length > 0) {
|
||||||
setFocusedInlineIndex(selected.length);
|
setFocusedInlineIndex(selected.length);
|
||||||
}
|
}
|
||||||
console.log('onInputChange', value);
|
|
||||||
debouncedSearch(value.trim());
|
debouncedSearch(value.trim());
|
||||||
},
|
},
|
||||||
[debouncedSearch, selected.length]
|
[debouncedSearch, selected.length]
|
||||||
|
|||||||
@@ -143,7 +143,25 @@ export const AllPage = () => {
|
|||||||
const collectionRulesService = useService(CollectionRulesService);
|
const collectionRulesService = useService(CollectionRulesService);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscription = collectionRulesService
|
const subscription = collectionRulesService
|
||||||
.watch(filters ?? [], groupBy, orderBy)
|
.watch(
|
||||||
|
[
|
||||||
|
...(filters ?? []),
|
||||||
|
{
|
||||||
|
type: 'system',
|
||||||
|
key: 'empty-journal',
|
||||||
|
method: 'is',
|
||||||
|
value: 'false',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'system',
|
||||||
|
key: 'trash',
|
||||||
|
method: 'is',
|
||||||
|
value: 'false',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
groupBy,
|
||||||
|
orderBy
|
||||||
|
)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: result => {
|
next: result => {
|
||||||
explorerContextValue.groups$.next(result.groups);
|
explorerContextValue.groups$.next(result.groups);
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ export class AuthSession extends Entity {
|
|||||||
|
|
||||||
async updateLabel(label: string) {
|
async updateLabel(label: string) {
|
||||||
await this.store.updateLabel(label);
|
await this.store.updateLabel(label);
|
||||||
console.log('updateLabel');
|
|
||||||
await this.waitForRevalidation();
|
await this.waitForRevalidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ export class DocCreatedByUpdatedBySyncService extends Service {
|
|||||||
.pipe(
|
.pipe(
|
||||||
map(allDocsCreatedBy => {
|
map(allDocsCreatedBy => {
|
||||||
let missingCreatedBy = false;
|
let missingCreatedBy = false;
|
||||||
console.log(allDocsCreatedBy);
|
|
||||||
for (const createdBy of allDocsCreatedBy.values()) {
|
for (const createdBy of allDocsCreatedBy.values()) {
|
||||||
if (!createdBy) {
|
if (!createdBy) {
|
||||||
missingCreatedBy = true;
|
missingCreatedBy = true;
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import type { DocsService } from '@affine/core/modules/doc';
|
||||||
|
import { Service } from '@toeverything/infra';
|
||||||
|
import { combineLatest, map, type Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import type { FilterProvider } from '../../provider';
|
||||||
|
import type { FilterParams } from '../../types';
|
||||||
|
|
||||||
|
export class EmptyJournalFilterProvider
|
||||||
|
extends Service
|
||||||
|
implements FilterProvider
|
||||||
|
{
|
||||||
|
constructor(private readonly docsService: DocsService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
filter$(params: FilterParams): Observable<Set<string>> {
|
||||||
|
return combineLatest([
|
||||||
|
this.docsService.allDocsUpdatedDate$(),
|
||||||
|
this.docsService.propertyValues$('journal'),
|
||||||
|
]).pipe(
|
||||||
|
map(([updatedAts, journalValues]) => {
|
||||||
|
const match = new Set<string>();
|
||||||
|
|
||||||
|
for (const { id, updatedDate } of updatedAts) {
|
||||||
|
const isJournal = journalValues.get(id);
|
||||||
|
const isEmptyJournal = updatedDate === undefined && isJournal;
|
||||||
|
if (
|
||||||
|
(params.value === 'false' && !isEmptyJournal) ||
|
||||||
|
(params.value === 'true' && isEmptyJournal)
|
||||||
|
) {
|
||||||
|
match.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import { CreatedAtFilterProvider } from './impls/filters/created-at';
|
|||||||
import { CreatedByFilterProvider } from './impls/filters/created-by';
|
import { CreatedByFilterProvider } from './impls/filters/created-by';
|
||||||
import { DatePropertyFilterProvider } from './impls/filters/date';
|
import { DatePropertyFilterProvider } from './impls/filters/date';
|
||||||
import { DocPrimaryModeFilterProvider } from './impls/filters/doc-primary-mode';
|
import { DocPrimaryModeFilterProvider } from './impls/filters/doc-primary-mode';
|
||||||
|
import { EmptyJournalFilterProvider } from './impls/filters/empty-journal';
|
||||||
import { JournalFilterProvider } from './impls/filters/journal';
|
import { JournalFilterProvider } from './impls/filters/journal';
|
||||||
import { PropertyFilterProvider } from './impls/filters/property';
|
import { PropertyFilterProvider } from './impls/filters/property';
|
||||||
import { SystemFilterProvider } from './impls/filters/system';
|
import { SystemFilterProvider } from './impls/filters/system';
|
||||||
@@ -114,6 +115,9 @@ export function configureCollectionRulesModule(framework: Framework) {
|
|||||||
.impl(FilterProvider('system:updatedBy'), UpdatedByFilterProvider, [
|
.impl(FilterProvider('system:updatedBy'), UpdatedByFilterProvider, [
|
||||||
DocsService,
|
DocsService,
|
||||||
])
|
])
|
||||||
|
.impl(FilterProvider('system:empty-journal'), EmptyJournalFilterProvider, [
|
||||||
|
DocsService,
|
||||||
|
])
|
||||||
// --------------- Group By ---------------
|
// --------------- Group By ---------------
|
||||||
.impl(GroupByProvider('system'), SystemGroupByProvider)
|
.impl(GroupByProvider('system'), SystemGroupByProvider)
|
||||||
.impl(GroupByProvider('property'), PropertyGroupByProvider, [
|
.impl(GroupByProvider('property'), PropertyGroupByProvider, [
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export class CollectionRulesService extends Service {
|
|||||||
}[];
|
}[];
|
||||||
filterErrors: any[];
|
filterErrors: any[];
|
||||||
}> = grouped$.pipe(
|
}> = grouped$.pipe(
|
||||||
throttleTime(500), // throttle the results to avoid too many re-renders
|
throttleTime(300, undefined, { leading: false, trailing: true }), // throttle the results to avoid too many re-renders
|
||||||
map(({ grouped, ordered, filtered, filterErrors }) => {
|
map(({ grouped, ordered, filtered, filterErrors }) => {
|
||||||
const result: { key: string; items: string[] }[] = [];
|
const result: { key: string; items: string[] }[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ export class DocRecordList extends Entity {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public readonly nonTrashDocsIds$ = LiveData.from<string[]>(
|
||||||
|
this.store.watchNonTrashDocIds(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
public readonly isReady$ = LiveData.from(
|
public readonly isReady$ = LiveData.from(
|
||||||
this.store.watchDocListReady(),
|
this.store.watchDocListReady(),
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export class DocsStore extends Store {
|
|||||||
this.workspaceService.workspace.rootYDoc.getMap('meta'),
|
this.workspaceService.workspace.rootYDoc.getMap('meta'),
|
||||||
'pages'
|
'pages'
|
||||||
).pipe(
|
).pipe(
|
||||||
switchMap(yjsObserveDeep),
|
switchMap(pages => yjsObservePath(pages, '*.trash')),
|
||||||
map(meta => {
|
map(meta => {
|
||||||
if (meta instanceof YArray) {
|
if (meta instanceof YArray) {
|
||||||
return meta
|
return meta
|
||||||
@@ -165,7 +165,7 @@ export class DocsStore extends Store {
|
|||||||
this.workspaceService.workspace.rootYDoc.getMap('meta'),
|
this.workspaceService.workspace.rootYDoc.getMap('meta'),
|
||||||
'pages'
|
'pages'
|
||||||
).pipe(
|
).pipe(
|
||||||
switchMap(yjsObserveDeep),
|
switchMap(pages => yjsObservePath(pages, '*.trash')),
|
||||||
map(meta => {
|
map(meta => {
|
||||||
if (meta instanceof YArray) {
|
if (meta instanceof YArray) {
|
||||||
return meta
|
return meta
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ export class MemberSearchService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
search(searchText?: string) {
|
search(searchText?: string) {
|
||||||
console.log('search', searchText);
|
|
||||||
this.reset();
|
this.reset();
|
||||||
this.searchText$.setValue(searchText ?? '');
|
this.searchText$.setValue(searchText ?? '');
|
||||||
this.loadMore();
|
this.loadMore();
|
||||||
|
|||||||
Reference in New Issue
Block a user