feat(core): make permission and invoice offline available (#8123)

This commit is contained in:
EYHN
2024-09-05 15:11:27 +00:00
parent 8be67dce82
commit f4db4058f8
17 changed files with 236 additions and 186 deletions
@@ -3,7 +3,6 @@ import {
type GraphQLQuery,
type QueryOptions,
type QueryResponse,
UserFriendlyError,
} from '@affine/graphql';
import { fromPromise, Service } from '@toeverything/infra';
import type { Observable } from 'rxjs';
@@ -39,13 +38,11 @@ export class GraphQLService extends Service {
try {
return await this.rawGql(options);
} catch (err) {
const standardError = UserFriendlyError.fromAnyError(err);
if (standardError.status === 403) {
if (err instanceof BackendError && err.status === 403) {
this.framework.get(AuthService).session.revalidate();
}
throw new BackendError(standardError);
throw err;
}
};
}
@@ -0,0 +1,79 @@
import type { GetMembersByWorkspaceIdQuery } from '@affine/graphql';
import type { WorkspaceService } from '@toeverything/infra';
import {
backoffRetry,
catchErrorInto,
effect,
Entity,
fromPromise,
LiveData,
onComplete,
onStart,
} from '@toeverything/infra';
import { distinctUntilChanged, EMPTY, map, mergeMap, switchMap } from 'rxjs';
import { isBackendError, isNetworkError } from '../../cloud';
import type { WorkspaceMembersStore } from '../stores/members';
export type Member =
GetMembersByWorkspaceIdQuery['workspace']['members'][number];
export class WorkspaceMembers extends Entity {
constructor(
private readonly store: WorkspaceMembersStore,
private readonly workspaceService: WorkspaceService
) {
super();
}
pageNum$ = new LiveData(0);
memberCount$ = new LiveData<number | undefined>(undefined);
pageMembers$ = new LiveData<Member[] | undefined>(undefined);
isLoading$ = new LiveData(false);
error$ = new LiveData<any>(null);
readonly PAGE_SIZE = 8;
readonly revalidate = effect(
map(() => this.pageNum$.value),
distinctUntilChanged<number>(),
switchMap(pageNum => {
return fromPromise(async signal => {
return this.store.fetchMembers(
this.workspaceService.workspace.id,
pageNum * this.PAGE_SIZE,
this.PAGE_SIZE,
signal
);
}).pipe(
mergeMap(data => {
this.memberCount$.setValue(data.memberCount);
this.pageMembers$.setValue(data.members);
return EMPTY;
}),
backoffRetry({
when: isNetworkError,
count: Infinity,
}),
backoffRetry({
when: isBackendError,
}),
catchErrorInto(this.error$),
onStart(() => {
this.pageMembers$.setValue(undefined);
this.isLoading$.setValue(true);
}),
onComplete(() => this.isLoading$.setValue(false))
);
})
);
setPageNum(pageNum: number) {
this.pageNum$.setValue(pageNum);
}
override dispose(): void {
this.revalidate.unsubscribe();
}
}
@@ -1,3 +1,5 @@
export type { Member } from './entities/members';
export { WorkspaceMembersService } from './services/members';
export { WorkspacePermissionService } from './services/permission';
import { GraphQLService } from '@affine/core/modules/cloud';
@@ -8,8 +10,11 @@ import {
WorkspacesService,
} from '@toeverything/infra';
import { WorkspaceMembers } from './entities/members';
import { WorkspacePermission } from './entities/permission';
import { WorkspaceMembersService } from './services/members';
import { WorkspacePermissionService } from './services/permission';
import { WorkspaceMembersStore } from './stores/members';
import { WorkspacePermissionStore } from './stores/permission';
export function configurePermissionsModule(framework: Framework) {
@@ -21,5 +26,8 @@ export function configurePermissionsModule(framework: Framework) {
WorkspacePermissionStore,
])
.store(WorkspacePermissionStore, [GraphQLService])
.entity(WorkspacePermission, [WorkspaceService, WorkspacePermissionStore]);
.entity(WorkspacePermission, [WorkspaceService, WorkspacePermissionStore])
.service(WorkspaceMembersService)
.store(WorkspaceMembersStore, [GraphQLService])
.entity(WorkspaceMembers, [WorkspaceMembersStore, WorkspaceService]);
}
@@ -0,0 +1,7 @@
import { Service } from '@toeverything/infra';
import { WorkspaceMembers } from '../entities/members';
export class WorkspaceMembersService extends Service {
members = this.framework.createEntity(WorkspaceMembers);
}
@@ -0,0 +1,31 @@
import { getMembersByWorkspaceIdQuery } from '@affine/graphql';
import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../../cloud';
export class WorkspaceMembersStore extends Store {
constructor(private readonly graphqlService: GraphQLService) {
super();
}
async fetchMembers(
workspaceId: string,
skip: number,
take: number,
signal?: AbortSignal
) {
const data = await this.graphqlService.gql({
query: getMembersByWorkspaceIdQuery,
variables: {
workspaceId,
skip,
take,
},
context: {
signal,
},
});
return data.workspace;
}
}