mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 18:16:15 +08:00
feat(core): make permission and invoice offline available (#8123)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user