tuist/projects/cloud/app/frontend/stores/OrganizationStore.ts

203 lines
4.8 KiB
TypeScript

import { ApolloClient } from '@apollo/client';
import { makeAutoObservable, runInAction } from 'mobx';
import {
ChangeUserRoleDocument,
OrganizationDocument,
Role,
RemoveUserDocument,
InviteUserDocument,
ResendInviteMutation,
ResendInviteDocument,
InviteUserMutation,
CancelInviteMutation,
CancelInviteDocument,
} from '@/graphql/types';
import { OrganizationDetail, mapOrganizationDetail } from '@/models';
import { mapPendingInvitation } from '@/models/PendingInvitation';
class OrganizationStore {
organization: OrganizationDetail | undefined;
client: ApolloClient<object>;
constructor(client: ApolloClient<object>) {
this.client = client;
makeAutoObservable(this);
}
get members() {
if (!this.organization) {
return [];
}
return [...this.users, ...this.admins].sort(
(first, second) => 0 - (first.name > second.name ? -1 : 1),
);
}
get users() {
if (!this.organization) {
return [];
}
return this.organization.users.map((user) => {
return {
id: user.id,
email: user.email,
name: user.accountName,
avatarUrl: user.avatarUrl ?? undefined,
role: Role.User,
};
});
}
get admins() {
if (!this.organization) {
return [];
}
return this.organization.admins.map((user) => {
return {
id: user.id,
email: user.email,
name: user.accountName,
avatarUrl: user.avatarUrl ?? undefined,
role: Role.Admin,
};
});
}
async removeMember(memberId: string) {
if (!this.organization) {
return;
}
await this.client.mutate({
mutation: RemoveUserDocument,
variables: {
input: {
organizationId: this.organization.id,
userId: memberId,
},
},
});
runInAction(() => {
if (!this.organization) {
return;
}
this.organization.users = this.organization.users.filter(
(user) => user.id !== memberId,
);
this.organization.admins = this.organization.admins.filter(
(user) => user.id !== memberId,
);
});
}
async changeUserRole(memberId: string, newRole: Role) {
if (!this.organization) {
return;
}
await this.client.mutate({
mutation: ChangeUserRoleDocument,
variables: {
input: {
userId: memberId,
organizationId: this.organization.id,
role: newRole,
},
},
});
runInAction(() => {
if (!this.organization) {
return;
}
switch (newRole) {
case Role.User:
const adminIndex = this.organization.admins
.map((admin) => admin.id)
.indexOf(memberId);
this.organization.users.push(
this.organization.admins[adminIndex],
);
this.organization.admins.splice(adminIndex, 1);
break;
case Role.Admin:
const userIndex = this.organization.users
.map((user) => user.id)
.indexOf(memberId);
this.organization.admins.push(
this.organization.users[userIndex],
);
this.organization.users.splice(userIndex, 1);
break;
}
});
}
async load(organizationName: string) {
const { data } = await this.client.query({
query: OrganizationDocument,
variables: { name: organizationName },
});
runInAction(() => {
this.organization = mapOrganizationDetail(data.organization);
});
}
async inviteMember(memberEmail: string) {
if (!this.organization) {
return;
}
const { data } = await this.client.mutate<InviteUserMutation>({
mutation: InviteUserDocument,
variables: {
input: {
inviteeEmail: memberEmail,
organizationId: this.organization.id,
},
},
});
if (data === null || data === undefined) {
return;
}
this.organization.pendingInvitations = [
mapPendingInvitation(data.inviteUser),
...this.organization.pendingInvitations,
];
}
async cancelInvite(invitationId: string) {
if (this.organization === undefined) {
return;
}
const { data } = await this.client.mutate<CancelInviteMutation>({
mutation: CancelInviteDocument,
variables: {
input: {
invitationId,
},
},
});
if (data === null || data === undefined) {
return;
}
this.organization.pendingInvitations =
this.organization.pendingInvitations.filter(
(pendingInvitation) => pendingInvitation.id !== invitationId,
);
}
async resendInvite(invitationId: string) {
await this.client.mutate<ResendInviteMutation>({
mutation: ResendInviteDocument,
variables: {
input: {
invitationId,
},
},
});
}
}
export default OrganizationStore;