[WIP] Whole FE migrated (#2517)
* Wip * WIP * Removed concole log * Add relations to workspace init (#2511) * Add relations to workspace init * remove logs * update prefill * add missing isSystem * comment relation fields * Migrate v2 core models to graphql schema (#2509) * migrate v2 core models to graphql schema * Migrate to new workspace member schema * Continue work * migrated-main * Finished accountOwner nested field integration on companies * Introduce bug * Fix --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com> Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -19,7 +19,7 @@ const documents = {
|
|||||||
"\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.UpdateOneObjectMetadataItemDocument,
|
"\n mutation UpdateOneObjectMetadataItem(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.UpdateOneObjectMetadataItemDocument,
|
||||||
"\n mutation DeleteOneObjectMetadataItem($idToDelete: ID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneObjectMetadataItemDocument,
|
"\n mutation DeleteOneObjectMetadataItem($idToDelete: ID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneObjectMetadataItemDocument,
|
||||||
"\n mutation DeleteOneFieldMetadataItem($idToDelete: ID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneFieldMetadataItemDocument,
|
"\n mutation DeleteOneFieldMetadataItem($idToDelete: ID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneFieldMetadataItemDocument,
|
||||||
"\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n }\n toRelationMetadata {\n id\n relationType\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n": types.ObjectMetadataItemsDocument,
|
"\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n toRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n": types.ObjectMetadataItemsDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +63,7 @@ export function graphql(source: "\n mutation DeleteOneFieldMetadataItem($idToDe
|
|||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n }\n toRelationMetadata {\n id\n relationType\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n }\n toRelationMetadata {\n id\n relationType\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n"];
|
export function graphql(source: "\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n toRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems($filter: objectFilter) {\n objects(paging: { first: 1000 }, filter: $filter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n isSystem\n createdAt\n updatedAt\n fields(paging: { first: 1000 }) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n toRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n"];
|
||||||
|
|
||||||
export function graphql(source: string) {
|
export function graphql(source: string) {
|
||||||
return (documents as any)[source] ?? {};
|
return (documents as any)[source] ?? {};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -16,6 +16,7 @@ export type Scalars = {
|
|||||||
ConnectionCursor: any;
|
ConnectionCursor: any;
|
||||||
DateTime: string;
|
DateTime: string;
|
||||||
JSON: any;
|
JSON: any;
|
||||||
|
JSONObject: any;
|
||||||
Upload: any;
|
Upload: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -966,6 +967,15 @@ export type CompanyWhereUniqueInput = {
|
|||||||
id?: InputMaybe<Scalars['String']>;
|
id?: InputMaybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CreateOneRefreshTokenV2Input = {
|
||||||
|
/** The record to create */
|
||||||
|
refreshTokenV2: CreateRefreshTokenInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateRefreshTokenInput = {
|
||||||
|
expiresAt: Scalars['DateTime'];
|
||||||
|
};
|
||||||
|
|
||||||
export enum Currency {
|
export enum Currency {
|
||||||
Aed = 'AED',
|
Aed = 'AED',
|
||||||
Afn = 'AFN',
|
Afn = 'AFN',
|
||||||
@ -1398,6 +1408,8 @@ export type Mutation = {
|
|||||||
createOnePerson: Person;
|
createOnePerson: Person;
|
||||||
createOnePipelineProgress: PipelineProgress;
|
createOnePipelineProgress: PipelineProgress;
|
||||||
createOnePipelineStage: PipelineStage;
|
createOnePipelineStage: PipelineStage;
|
||||||
|
createOneRefreshTokenV2: RefreshTokenV2;
|
||||||
|
createOneRelation: Relation;
|
||||||
createOneWebHook: WebHook;
|
createOneWebHook: WebHook;
|
||||||
deleteCurrentWorkspace: Workspace;
|
deleteCurrentWorkspace: Workspace;
|
||||||
deleteFavorite: Favorite;
|
deleteFavorite: Favorite;
|
||||||
@ -1410,6 +1422,7 @@ export type Mutation = {
|
|||||||
deleteOnePipelineStage: PipelineStage;
|
deleteOnePipelineStage: PipelineStage;
|
||||||
deleteOneWebHook: WebHook;
|
deleteOneWebHook: WebHook;
|
||||||
deleteUserAccount: User;
|
deleteUserAccount: User;
|
||||||
|
deleteUserV2: UserV2;
|
||||||
deleteWorkspaceMember: WorkspaceMember;
|
deleteWorkspaceMember: WorkspaceMember;
|
||||||
impersonate: Verify;
|
impersonate: Verify;
|
||||||
renewToken: AuthTokens;
|
renewToken: AuthTokens;
|
||||||
@ -1430,6 +1443,7 @@ export type Mutation = {
|
|||||||
uploadImage: Scalars['String'];
|
uploadImage: Scalars['String'];
|
||||||
uploadPersonPicture: Scalars['String'];
|
uploadPersonPicture: Scalars['String'];
|
||||||
uploadProfilePicture: Scalars['String'];
|
uploadProfilePicture: Scalars['String'];
|
||||||
|
uploadProfilePictureV2: Scalars['String'];
|
||||||
uploadWorkspaceLogo: Scalars['String'];
|
uploadWorkspaceLogo: Scalars['String'];
|
||||||
verify: Verify;
|
verify: Verify;
|
||||||
};
|
};
|
||||||
@ -1515,6 +1529,11 @@ export type MutationCreateOnePipelineStageArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateOneRefreshTokenV2Args = {
|
||||||
|
input: CreateOneRefreshTokenV2Input;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateOneWebHookArgs = {
|
export type MutationCreateOneWebHookArgs = {
|
||||||
data: WebHookCreateInput;
|
data: WebHookCreateInput;
|
||||||
};
|
};
|
||||||
@ -1660,6 +1679,11 @@ export type MutationUploadProfilePictureArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUploadProfilePictureV2Args = {
|
||||||
|
file: Scalars['Upload'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUploadWorkspaceLogoArgs = {
|
export type MutationUploadWorkspaceLogoArgs = {
|
||||||
file: Scalars['Upload'];
|
file: Scalars['Upload'];
|
||||||
};
|
};
|
||||||
@ -2409,6 +2433,7 @@ export type Query = {
|
|||||||
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid;
|
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid;
|
||||||
clientConfig: ClientConfig;
|
clientConfig: ClientConfig;
|
||||||
currentUser: User;
|
currentUser: User;
|
||||||
|
currentUserV2: UserV2;
|
||||||
currentWorkspace: Workspace;
|
currentWorkspace: Workspace;
|
||||||
field: Field;
|
field: Field;
|
||||||
fields: FieldConnection;
|
fields: FieldConnection;
|
||||||
@ -2428,6 +2453,8 @@ export type Query = {
|
|||||||
findWorkspaceFromInviteHash: Workspace;
|
findWorkspaceFromInviteHash: Workspace;
|
||||||
object: Object;
|
object: Object;
|
||||||
objects: ObjectConnection;
|
objects: ObjectConnection;
|
||||||
|
relation: Relation;
|
||||||
|
relations: RelationConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2560,32 +2587,6 @@ export enum QueryMode {
|
|||||||
Insensitive = 'insensitive'
|
Insensitive = 'insensitive'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RefreshToken = {
|
|
||||||
__typename?: 'RefreshToken';
|
|
||||||
createdAt: Scalars['DateTime'];
|
|
||||||
expiresAt: Scalars['DateTime'];
|
|
||||||
id: Scalars['ID'];
|
|
||||||
updatedAt: Scalars['DateTime'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RefreshTokenConnection = {
|
|
||||||
__typename?: 'RefreshTokenConnection';
|
|
||||||
/** Array of edges. */
|
|
||||||
edges: Array<RefreshTokenEdge>;
|
|
||||||
/** Paging information */
|
|
||||||
pageInfo: PageInfo;
|
|
||||||
/** Fetch total count of records */
|
|
||||||
totalCount: Scalars['Int'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RefreshTokenEdge = {
|
|
||||||
__typename?: 'RefreshTokenEdge';
|
|
||||||
/** Cursor for this node. */
|
|
||||||
cursor: Scalars['ConnectionCursor'];
|
|
||||||
/** The node containing the RefreshToken */
|
|
||||||
node: RefreshToken;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RelationConnection = {
|
export type RelationConnection = {
|
||||||
__typename?: 'RelationConnection';
|
__typename?: 'RelationConnection';
|
||||||
/** Array of edges. */
|
/** Array of edges. */
|
||||||
@ -2644,15 +2645,6 @@ export type Support = {
|
|||||||
supportFrontChatId?: Maybe<Scalars['String']>;
|
supportFrontChatId?: Maybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TUser = {
|
|
||||||
__typename?: 'TUser';
|
|
||||||
email: Scalars['String'];
|
|
||||||
emailVerified: Scalars['Boolean'];
|
|
||||||
firstName?: Maybe<Scalars['String']>;
|
|
||||||
id: Scalars['ID'];
|
|
||||||
lastName?: Maybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Telemetry = {
|
export type Telemetry = {
|
||||||
__typename?: 'Telemetry';
|
__typename?: 'Telemetry';
|
||||||
anonymizationEnabled: Scalars['Boolean'];
|
anonymizationEnabled: Scalars['Boolean'];
|
||||||
@ -2669,6 +2661,7 @@ export type User = {
|
|||||||
comments?: Maybe<Array<Comment>>;
|
comments?: Maybe<Array<Comment>>;
|
||||||
companies?: Maybe<Array<Company>>;
|
companies?: Maybe<Array<Company>>;
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
|
defaultWorkspaceId?: Maybe<Scalars['String']>;
|
||||||
disabled: Scalars['Boolean'];
|
disabled: Scalars['Boolean'];
|
||||||
displayName: Scalars['String'];
|
displayName: Scalars['String'];
|
||||||
email: Scalars['String'];
|
email: Scalars['String'];
|
||||||
@ -2680,11 +2673,8 @@ export type User = {
|
|||||||
locale: Scalars['String'];
|
locale: Scalars['String'];
|
||||||
metadata?: Maybe<Scalars['JSON']>;
|
metadata?: Maybe<Scalars['JSON']>;
|
||||||
phoneNumber?: Maybe<Scalars['String']>;
|
phoneNumber?: Maybe<Scalars['String']>;
|
||||||
settings: UserSettings;
|
|
||||||
settingsId: Scalars['String'];
|
|
||||||
supportUserHash?: Maybe<Scalars['String']>;
|
supportUserHash?: Maybe<Scalars['String']>;
|
||||||
updatedAt: Scalars['DateTime'];
|
updatedAt: Scalars['DateTime'];
|
||||||
workspaceMember?: Maybe<WorkspaceMember>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserCreateNestedOneWithoutAssignedActivitiesInput = {
|
export type UserCreateNestedOneWithoutAssignedActivitiesInput = {
|
||||||
@ -2717,6 +2707,7 @@ export type UserOrderByWithRelationInput = {
|
|||||||
comments?: InputMaybe<CommentOrderByRelationAggregateInput>;
|
comments?: InputMaybe<CommentOrderByRelationAggregateInput>;
|
||||||
companies?: InputMaybe<CompanyOrderByRelationAggregateInput>;
|
companies?: InputMaybe<CompanyOrderByRelationAggregateInput>;
|
||||||
createdAt?: InputMaybe<SortOrder>;
|
createdAt?: InputMaybe<SortOrder>;
|
||||||
|
defaultWorkspaceId?: InputMaybe<SortOrder>;
|
||||||
disabled?: InputMaybe<SortOrder>;
|
disabled?: InputMaybe<SortOrder>;
|
||||||
email?: InputMaybe<SortOrder>;
|
email?: InputMaybe<SortOrder>;
|
||||||
emailVerified?: InputMaybe<SortOrder>;
|
emailVerified?: InputMaybe<SortOrder>;
|
||||||
@ -2727,8 +2718,6 @@ export type UserOrderByWithRelationInput = {
|
|||||||
locale?: InputMaybe<SortOrder>;
|
locale?: InputMaybe<SortOrder>;
|
||||||
metadata?: InputMaybe<SortOrder>;
|
metadata?: InputMaybe<SortOrder>;
|
||||||
phoneNumber?: InputMaybe<SortOrder>;
|
phoneNumber?: InputMaybe<SortOrder>;
|
||||||
settings?: InputMaybe<UserSettingsOrderByWithRelationInput>;
|
|
||||||
settingsId?: InputMaybe<SortOrder>;
|
|
||||||
updatedAt?: InputMaybe<SortOrder>;
|
updatedAt?: InputMaybe<SortOrder>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2741,6 +2730,7 @@ export enum UserScalarFieldEnum {
|
|||||||
AvatarUrl = 'avatarUrl',
|
AvatarUrl = 'avatarUrl',
|
||||||
CanImpersonate = 'canImpersonate',
|
CanImpersonate = 'canImpersonate',
|
||||||
CreatedAt = 'createdAt',
|
CreatedAt = 'createdAt',
|
||||||
|
DefaultWorkspaceId = 'defaultWorkspaceId',
|
||||||
DeletedAt = 'deletedAt',
|
DeletedAt = 'deletedAt',
|
||||||
Disabled = 'disabled',
|
Disabled = 'disabled',
|
||||||
Email = 'email',
|
Email = 'email',
|
||||||
@ -2753,7 +2743,6 @@ export enum UserScalarFieldEnum {
|
|||||||
Metadata = 'metadata',
|
Metadata = 'metadata',
|
||||||
PasswordHash = 'passwordHash',
|
PasswordHash = 'passwordHash',
|
||||||
PhoneNumber = 'phoneNumber',
|
PhoneNumber = 'phoneNumber',
|
||||||
SettingsId = 'settingsId',
|
|
||||||
UpdatedAt = 'updatedAt'
|
UpdatedAt = 'updatedAt'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2765,7 +2754,6 @@ export type UserSettings = {
|
|||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
locale: Scalars['String'];
|
locale: Scalars['String'];
|
||||||
updatedAt: Scalars['DateTime'];
|
updatedAt: Scalars['DateTime'];
|
||||||
user?: Maybe<User>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserSettingsOrderByWithRelationInput = {
|
export type UserSettingsOrderByWithRelationInput = {
|
||||||
@ -2775,7 +2763,6 @@ export type UserSettingsOrderByWithRelationInput = {
|
|||||||
id?: InputMaybe<SortOrder>;
|
id?: InputMaybe<SortOrder>;
|
||||||
locale?: InputMaybe<SortOrder>;
|
locale?: InputMaybe<SortOrder>;
|
||||||
updatedAt?: InputMaybe<SortOrder>;
|
updatedAt?: InputMaybe<SortOrder>;
|
||||||
user?: InputMaybe<UserOrderByWithRelationInput>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserSettingsRelationFilter = {
|
export type UserSettingsRelationFilter = {
|
||||||
@ -2783,24 +2770,11 @@ export type UserSettingsRelationFilter = {
|
|||||||
isNot?: InputMaybe<UserSettingsWhereInput>;
|
isNot?: InputMaybe<UserSettingsWhereInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserSettingsUpdateOneRequiredWithoutUserNestedInput = {
|
|
||||||
update?: InputMaybe<UserSettingsUpdateWithoutUserInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserSettingsUpdateOneWithoutWorkspaceMemberNestedInput = {
|
export type UserSettingsUpdateOneWithoutWorkspaceMemberNestedInput = {
|
||||||
connect?: InputMaybe<UserSettingsWhereUniqueInput>;
|
connect?: InputMaybe<UserSettingsWhereUniqueInput>;
|
||||||
disconnect?: InputMaybe<Scalars['Boolean']>;
|
disconnect?: InputMaybe<Scalars['Boolean']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserSettingsUpdateWithoutUserInput = {
|
|
||||||
WorkspaceMember?: InputMaybe<WorkspaceMemberUpdateManyWithoutSettingsNestedInput>;
|
|
||||||
colorScheme?: InputMaybe<ColorScheme>;
|
|
||||||
createdAt?: InputMaybe<Scalars['DateTime']>;
|
|
||||||
id?: InputMaybe<Scalars['String']>;
|
|
||||||
locale?: InputMaybe<Scalars['String']>;
|
|
||||||
updatedAt?: InputMaybe<Scalars['DateTime']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserSettingsWhereInput = {
|
export type UserSettingsWhereInput = {
|
||||||
AND?: InputMaybe<Array<UserSettingsWhereInput>>;
|
AND?: InputMaybe<Array<UserSettingsWhereInput>>;
|
||||||
NOT?: InputMaybe<Array<UserSettingsWhereInput>>;
|
NOT?: InputMaybe<Array<UserSettingsWhereInput>>;
|
||||||
@ -2811,7 +2785,6 @@ export type UserSettingsWhereInput = {
|
|||||||
id?: InputMaybe<StringFilter>;
|
id?: InputMaybe<StringFilter>;
|
||||||
locale?: InputMaybe<StringFilter>;
|
locale?: InputMaybe<StringFilter>;
|
||||||
updatedAt?: InputMaybe<DateTimeFilter>;
|
updatedAt?: InputMaybe<DateTimeFilter>;
|
||||||
user?: InputMaybe<UserRelationFilter>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserSettingsWhereUniqueInput = {
|
export type UserSettingsWhereUniqueInput = {
|
||||||
@ -2827,6 +2800,7 @@ export type UserUpdateInput = {
|
|||||||
comments?: InputMaybe<CommentUpdateManyWithoutAuthorNestedInput>;
|
comments?: InputMaybe<CommentUpdateManyWithoutAuthorNestedInput>;
|
||||||
companies?: InputMaybe<CompanyUpdateManyWithoutAccountOwnerNestedInput>;
|
companies?: InputMaybe<CompanyUpdateManyWithoutAccountOwnerNestedInput>;
|
||||||
createdAt?: InputMaybe<Scalars['DateTime']>;
|
createdAt?: InputMaybe<Scalars['DateTime']>;
|
||||||
|
defaultWorkspaceId?: InputMaybe<Scalars['String']>;
|
||||||
disabled?: InputMaybe<Scalars['Boolean']>;
|
disabled?: InputMaybe<Scalars['Boolean']>;
|
||||||
email?: InputMaybe<Scalars['String']>;
|
email?: InputMaybe<Scalars['String']>;
|
||||||
emailVerified?: InputMaybe<Scalars['Boolean']>;
|
emailVerified?: InputMaybe<Scalars['Boolean']>;
|
||||||
@ -2837,7 +2811,6 @@ export type UserUpdateInput = {
|
|||||||
locale?: InputMaybe<Scalars['String']>;
|
locale?: InputMaybe<Scalars['String']>;
|
||||||
metadata?: InputMaybe<Scalars['JSON']>;
|
metadata?: InputMaybe<Scalars['JSON']>;
|
||||||
phoneNumber?: InputMaybe<Scalars['String']>;
|
phoneNumber?: InputMaybe<Scalars['String']>;
|
||||||
settings?: InputMaybe<UserSettingsUpdateOneRequiredWithoutUserNestedInput>;
|
|
||||||
updatedAt?: InputMaybe<Scalars['DateTime']>;
|
updatedAt?: InputMaybe<Scalars['DateTime']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2845,10 +2818,6 @@ export type UserUpdateOneRequiredWithoutAuthoredActivitiesNestedInput = {
|
|||||||
connect?: InputMaybe<UserWhereUniqueInput>;
|
connect?: InputMaybe<UserWhereUniqueInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserUpdateOneRequiredWithoutWorkspaceMemberNestedInput = {
|
|
||||||
connect?: InputMaybe<UserWhereUniqueInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserUpdateOneWithoutAssignedActivitiesNestedInput = {
|
export type UserUpdateOneWithoutAssignedActivitiesNestedInput = {
|
||||||
connect?: InputMaybe<UserWhereUniqueInput>;
|
connect?: InputMaybe<UserWhereUniqueInput>;
|
||||||
disconnect?: InputMaybe<Scalars['Boolean']>;
|
disconnect?: InputMaybe<Scalars['Boolean']>;
|
||||||
@ -2871,6 +2840,7 @@ export type UserWhereInput = {
|
|||||||
comments?: InputMaybe<CommentListRelationFilter>;
|
comments?: InputMaybe<CommentListRelationFilter>;
|
||||||
companies?: InputMaybe<CompanyListRelationFilter>;
|
companies?: InputMaybe<CompanyListRelationFilter>;
|
||||||
createdAt?: InputMaybe<DateTimeFilter>;
|
createdAt?: InputMaybe<DateTimeFilter>;
|
||||||
|
defaultWorkspaceId?: InputMaybe<StringNullableFilter>;
|
||||||
disabled?: InputMaybe<BoolFilter>;
|
disabled?: InputMaybe<BoolFilter>;
|
||||||
email?: InputMaybe<StringFilter>;
|
email?: InputMaybe<StringFilter>;
|
||||||
emailVerified?: InputMaybe<BoolFilter>;
|
emailVerified?: InputMaybe<BoolFilter>;
|
||||||
@ -2881,15 +2851,12 @@ export type UserWhereInput = {
|
|||||||
locale?: InputMaybe<StringFilter>;
|
locale?: InputMaybe<StringFilter>;
|
||||||
metadata?: InputMaybe<JsonNullableFilter>;
|
metadata?: InputMaybe<JsonNullableFilter>;
|
||||||
phoneNumber?: InputMaybe<StringNullableFilter>;
|
phoneNumber?: InputMaybe<StringNullableFilter>;
|
||||||
settings?: InputMaybe<UserSettingsRelationFilter>;
|
|
||||||
settingsId?: InputMaybe<StringFilter>;
|
|
||||||
updatedAt?: InputMaybe<DateTimeFilter>;
|
updatedAt?: InputMaybe<DateTimeFilter>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserWhereUniqueInput = {
|
export type UserWhereUniqueInput = {
|
||||||
email?: InputMaybe<Scalars['String']>;
|
email?: InputMaybe<Scalars['String']>;
|
||||||
id?: InputMaybe<Scalars['String']>;
|
id?: InputMaybe<Scalars['String']>;
|
||||||
settingsId?: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Verify = {
|
export type Verify = {
|
||||||
@ -2996,7 +2963,6 @@ export type WorkspaceMember = {
|
|||||||
settings?: Maybe<UserSettings>;
|
settings?: Maybe<UserSettings>;
|
||||||
settingsId?: Maybe<Scalars['String']>;
|
settingsId?: Maybe<Scalars['String']>;
|
||||||
updatedAt: Scalars['DateTime'];
|
updatedAt: Scalars['DateTime'];
|
||||||
user: User;
|
|
||||||
userId: Scalars['String'];
|
userId: Scalars['String'];
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
};
|
};
|
||||||
@ -3040,7 +3006,6 @@ export type WorkspaceMemberOrderByWithRelationInput = {
|
|||||||
settings?: InputMaybe<UserSettingsOrderByWithRelationInput>;
|
settings?: InputMaybe<UserSettingsOrderByWithRelationInput>;
|
||||||
settingsId?: InputMaybe<SortOrder>;
|
settingsId?: InputMaybe<SortOrder>;
|
||||||
updatedAt?: InputMaybe<SortOrder>;
|
updatedAt?: InputMaybe<SortOrder>;
|
||||||
user?: InputMaybe<UserOrderByWithRelationInput>;
|
|
||||||
userId?: InputMaybe<SortOrder>;
|
userId?: InputMaybe<SortOrder>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3072,13 +3037,7 @@ export type WorkspaceMemberUpdateInput = {
|
|||||||
id?: InputMaybe<Scalars['String']>;
|
id?: InputMaybe<Scalars['String']>;
|
||||||
settings?: InputMaybe<UserSettingsUpdateOneWithoutWorkspaceMemberNestedInput>;
|
settings?: InputMaybe<UserSettingsUpdateOneWithoutWorkspaceMemberNestedInput>;
|
||||||
updatedAt?: InputMaybe<Scalars['DateTime']>;
|
updatedAt?: InputMaybe<Scalars['DateTime']>;
|
||||||
user?: InputMaybe<UserUpdateOneRequiredWithoutWorkspaceMemberNestedInput>;
|
userId?: InputMaybe<Scalars['String']>;
|
||||||
};
|
|
||||||
|
|
||||||
export type WorkspaceMemberUpdateManyWithoutSettingsNestedInput = {
|
|
||||||
connect?: InputMaybe<Array<WorkspaceMemberWhereUniqueInput>>;
|
|
||||||
disconnect?: InputMaybe<Array<WorkspaceMemberWhereUniqueInput>>;
|
|
||||||
set?: InputMaybe<Array<WorkspaceMemberWhereUniqueInput>>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceMemberUpdateManyWithoutWorkspaceNestedInput = {
|
export type WorkspaceMemberUpdateManyWithoutWorkspaceNestedInput = {
|
||||||
@ -3118,7 +3077,6 @@ export type WorkspaceMemberWhereInput = {
|
|||||||
settings?: InputMaybe<UserSettingsRelationFilter>;
|
settings?: InputMaybe<UserSettingsRelationFilter>;
|
||||||
settingsId?: InputMaybe<StringNullableFilter>;
|
settingsId?: InputMaybe<StringNullableFilter>;
|
||||||
updatedAt?: InputMaybe<DateTimeFilter>;
|
updatedAt?: InputMaybe<DateTimeFilter>;
|
||||||
user?: InputMaybe<UserRelationFilter>;
|
|
||||||
userId?: InputMaybe<StringFilter>;
|
userId?: InputMaybe<StringFilter>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3207,6 +3165,22 @@ export type ObjectEdge = {
|
|||||||
node: Object;
|
node: Object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RefreshTokenV2 = {
|
||||||
|
__typename?: 'refreshTokenV2';
|
||||||
|
createdAt: Scalars['DateTime'];
|
||||||
|
expiresAt: Scalars['DateTime'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
updatedAt: Scalars['DateTime'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RefreshTokenV2Edge = {
|
||||||
|
__typename?: 'refreshTokenV2Edge';
|
||||||
|
/** Cursor for this node. */
|
||||||
|
cursor: Scalars['ConnectionCursor'];
|
||||||
|
/** The node containing the refreshTokenV2 */
|
||||||
|
node: RefreshTokenV2;
|
||||||
|
};
|
||||||
|
|
||||||
export type Relation = {
|
export type Relation = {
|
||||||
__typename?: 'relation';
|
__typename?: 'relation';
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
@ -3229,6 +3203,36 @@ export type RelationEdge = {
|
|||||||
node: Relation;
|
node: Relation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UserV2 = {
|
||||||
|
__typename?: 'userV2';
|
||||||
|
avatarUrl: Scalars['String'];
|
||||||
|
canImpersonate: Scalars['Boolean'];
|
||||||
|
createdAt: Scalars['DateTime'];
|
||||||
|
deletedAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
disabled?: Maybe<Scalars['Boolean']>;
|
||||||
|
displayName: Scalars['String'];
|
||||||
|
email: Scalars['String'];
|
||||||
|
emailVerified: Scalars['Boolean'];
|
||||||
|
firstName: Scalars['String'];
|
||||||
|
id: Scalars['ID'];
|
||||||
|
lastName: Scalars['String'];
|
||||||
|
lastSeen?: Maybe<Scalars['DateTime']>;
|
||||||
|
locale: Scalars['String'];
|
||||||
|
metadata?: Maybe<Scalars['JSONObject']>;
|
||||||
|
passwordHash?: Maybe<Scalars['String']>;
|
||||||
|
phoneNumber?: Maybe<Scalars['String']>;
|
||||||
|
supportUserHash?: Maybe<Scalars['String']>;
|
||||||
|
updatedAt: Scalars['DateTime'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserV2Edge = {
|
||||||
|
__typename?: 'userV2Edge';
|
||||||
|
/** Cursor for this node. */
|
||||||
|
cursor: Scalars['ConnectionCursor'];
|
||||||
|
/** The node containing the userV2 */
|
||||||
|
node: UserV2;
|
||||||
|
};
|
||||||
|
|
||||||
export type ActivityWithTargetsFragment = { __typename?: 'Activity', id: string, createdAt: string, updatedAt: string, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, createdAt: string, updatedAt: string, companyId?: string | null, personId?: string | null }> | null };
|
export type ActivityWithTargetsFragment = { __typename?: 'Activity', id: string, createdAt: string, updatedAt: string, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, createdAt: string, updatedAt: string, companyId?: string | null, personId?: string | null }> | null };
|
||||||
|
|
||||||
export type ActivityQueryFragmentFragment = { __typename?: 'Activity', id: string, createdAt: string, title?: string | null, body?: string | null, type: ActivityType, completedAt?: string | null, dueAt?: string | null, assignee?: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null, author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, companyId?: string | null, personId?: string | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null, person?: { __typename?: 'Person', id: string, displayName: string, avatarUrl?: string | null } | null }> | null };
|
export type ActivityQueryFragmentFragment = { __typename?: 'Activity', id: string, createdAt: string, title?: string | null, body?: string | null, type: ActivityType, completedAt?: string | null, dueAt?: string | null, assignee?: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null, author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, companyId?: string | null, personId?: string | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null, person?: { __typename?: 'Person', id: string, displayName: string, avatarUrl?: string | null } | null }> | null };
|
||||||
@ -3329,7 +3333,7 @@ export type AuthTokenFragmentFragment = { __typename?: 'AuthToken', token: strin
|
|||||||
|
|
||||||
export type AuthTokensFragmentFragment = { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } };
|
export type AuthTokensFragmentFragment = { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } };
|
||||||
|
|
||||||
export type UserQueryFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null, avatarUrl?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } | null, settings: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } };
|
export type UserQueryFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null };
|
||||||
|
|
||||||
export type ChallengeMutationVariables = Exact<{
|
export type ChallengeMutationVariables = Exact<{
|
||||||
email: Scalars['String'];
|
email: Scalars['String'];
|
||||||
@ -3344,7 +3348,7 @@ export type ImpersonateMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null, avatarUrl?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } | null, settings: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
||||||
|
|
||||||
export type RenewTokenMutationVariables = Exact<{
|
export type RenewTokenMutationVariables = Exact<{
|
||||||
refreshToken: Scalars['String'];
|
refreshToken: Scalars['String'];
|
||||||
@ -3367,7 +3371,7 @@ export type VerifyMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null, avatarUrl?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } | null, settings: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
||||||
|
|
||||||
export type CheckUserExistsQueryVariables = Exact<{
|
export type CheckUserExistsQueryVariables = Exact<{
|
||||||
email: Scalars['String'];
|
email: Scalars['String'];
|
||||||
@ -3744,20 +3748,18 @@ export type UpdateUserMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } | null, settings: { __typename?: 'UserSettings', id: string, locale: string, colorScheme: ColorScheme } } };
|
export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string } };
|
||||||
|
|
||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', avatarUrl?: string | null, canImpersonate: boolean, supportUserHash?: string | null, id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } | null, settings: { __typename?: 'UserSettings', id: string, locale: string, colorScheme: ColorScheme } } };
|
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', canImpersonate: boolean, supportUserHash?: string | null, id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null } };
|
||||||
|
|
||||||
export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> };
|
export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> };
|
||||||
|
|
||||||
export type WorkspaceMemberFieldsFragmentFragment = { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null };
|
|
||||||
|
|
||||||
export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>;
|
export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
@ -3768,13 +3770,6 @@ export type RemoveWorkspaceLogoMutationVariables = Exact<{ [key: string]: never;
|
|||||||
|
|
||||||
export type RemoveWorkspaceLogoMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: string } };
|
export type RemoveWorkspaceLogoMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: string } };
|
||||||
|
|
||||||
export type RemoveWorkspaceMemberMutationVariables = Exact<{
|
|
||||||
where: WorkspaceMemberWhereUniqueInput;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
|
|
||||||
export type RemoveWorkspaceMemberMutation = { __typename?: 'Mutation', deleteWorkspaceMember: { __typename?: 'WorkspaceMember', id: string } };
|
|
||||||
|
|
||||||
export type UpdateWorkspaceMutationVariables = Exact<{
|
export type UpdateWorkspaceMutationVariables = Exact<{
|
||||||
data: WorkspaceUpdateInput;
|
data: WorkspaceUpdateInput;
|
||||||
}>;
|
}>;
|
||||||
@ -3789,13 +3784,10 @@ export type UploadWorkspaceLogoMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type UploadWorkspaceLogoMutation = { __typename?: 'Mutation', uploadWorkspaceLogo: string };
|
export type UploadWorkspaceLogoMutation = { __typename?: 'Mutation', uploadWorkspaceLogo: string };
|
||||||
|
|
||||||
export type UpdateOneWorkspaceMemberMutationVariables = Exact<{
|
export type GetCurrentWorkspaceQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
data: WorkspaceMemberUpdateInput;
|
|
||||||
where: WorkspaceMemberWhereUniqueInput;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
|
|
||||||
export type UpdateOneWorkspaceMemberMutation = { __typename?: 'Mutation', UpdateOneWorkspaceMember: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, inviteHash?: string | null }, assignedActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredActivities?: Array<{ __typename?: 'Activity', id: string, title?: string | null }> | null, authoredAttachments?: Array<{ __typename?: 'Attachment', id: string, name: string, type: AttachmentType }> | null, settings?: { __typename?: 'UserSettings', id: string, colorScheme: ColorScheme, locale: string } | null, companies?: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> | null, comments?: Array<{ __typename?: 'Comment', id: string, body: string }> | null } };
|
export type GetCurrentWorkspaceQuery = { __typename?: 'Query', currentWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null } };
|
||||||
|
|
||||||
export type GetWorkspaceFromInviteHashQueryVariables = Exact<{
|
export type GetWorkspaceFromInviteHashQueryVariables = Exact<{
|
||||||
inviteHash: Scalars['String'];
|
inviteHash: Scalars['String'];
|
||||||
@ -3809,7 +3801,7 @@ export type GetWorkspaceMembersQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type GetWorkspaceMembersQuery = { __typename?: 'Query', workspaceMembers: Array<{ __typename?: 'WorkspaceMember', id: string, user: { __typename?: 'User', avatarUrl?: string | null, id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null } }> };
|
export type GetWorkspaceMembersQuery = { __typename?: 'Query', workspaceMembers: Array<{ __typename?: 'WorkspaceMember', id: string }> };
|
||||||
|
|
||||||
export const ActivityWithTargetsFragmentDoc = gql`
|
export const ActivityWithTargetsFragmentDoc = gql`
|
||||||
fragment ActivityWithTargets on Activity {
|
fragment ActivityWithTargets on Activity {
|
||||||
@ -3918,50 +3910,6 @@ export const UserQueryFragmentFragmentDoc = gql`
|
|||||||
lastName
|
lastName
|
||||||
canImpersonate
|
canImpersonate
|
||||||
supportUserHash
|
supportUserHash
|
||||||
avatarUrl
|
|
||||||
workspaceMember {
|
|
||||||
id
|
|
||||||
allowImpersonation
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const BaseAccountOwnerFragmentFragmentDoc = gql`
|
export const BaseAccountOwnerFragmentFragmentDoc = gql`
|
||||||
@ -4034,46 +3982,6 @@ export const UserFieldsFragmentFragmentDoc = gql`
|
|||||||
lastName
|
lastName
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const WorkspaceMemberFieldsFragmentFragmentDoc = gql`
|
|
||||||
fragment workspaceMemberFieldsFragment on WorkspaceMember {
|
|
||||||
id
|
|
||||||
allowImpersonation
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export const AddActivityTargetsOnActivityDocument = gql`
|
export const AddActivityTargetsOnActivityDocument = gql`
|
||||||
mutation AddActivityTargetsOnActivity($activityId: String!, $activityTargetInputs: [ActivityTargetCreateManyActivityInput!]!) {
|
mutation AddActivityTargetsOnActivity($activityId: String!, $activityTargetInputs: [ActivityTargetCreateManyActivityInput!]!) {
|
||||||
updateOneActivity(
|
updateOneActivity(
|
||||||
@ -6519,52 +6427,6 @@ export const UpdateUserDocument = gql`
|
|||||||
updateUser(data: $data, where: $where) {
|
updateUser(data: $data, where: $where) {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
displayName
|
|
||||||
firstName
|
|
||||||
lastName
|
|
||||||
avatarUrl
|
|
||||||
workspaceMember {
|
|
||||||
id
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
locale
|
|
||||||
colorScheme
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -6599,21 +6461,11 @@ export const GetCurrentUserDocument = gql`
|
|||||||
query GetCurrentUser {
|
query GetCurrentUser {
|
||||||
currentUser {
|
currentUser {
|
||||||
...userFieldsFragment
|
...userFieldsFragment
|
||||||
avatarUrl
|
|
||||||
canImpersonate
|
canImpersonate
|
||||||
workspaceMember {
|
|
||||||
...workspaceMemberFieldsFragment
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
locale
|
|
||||||
colorScheme
|
|
||||||
}
|
|
||||||
supportUserHash
|
supportUserHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${UserFieldsFragmentFragmentDoc}
|
${UserFieldsFragmentFragmentDoc}`;
|
||||||
${WorkspaceMemberFieldsFragmentFragmentDoc}`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useGetCurrentUserQuery__
|
* __useGetCurrentUserQuery__
|
||||||
@ -6739,39 +6591,6 @@ export function useRemoveWorkspaceLogoMutation(baseOptions?: Apollo.MutationHook
|
|||||||
export type RemoveWorkspaceLogoMutationHookResult = ReturnType<typeof useRemoveWorkspaceLogoMutation>;
|
export type RemoveWorkspaceLogoMutationHookResult = ReturnType<typeof useRemoveWorkspaceLogoMutation>;
|
||||||
export type RemoveWorkspaceLogoMutationResult = Apollo.MutationResult<RemoveWorkspaceLogoMutation>;
|
export type RemoveWorkspaceLogoMutationResult = Apollo.MutationResult<RemoveWorkspaceLogoMutation>;
|
||||||
export type RemoveWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions<RemoveWorkspaceLogoMutation, RemoveWorkspaceLogoMutationVariables>;
|
export type RemoveWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions<RemoveWorkspaceLogoMutation, RemoveWorkspaceLogoMutationVariables>;
|
||||||
export const RemoveWorkspaceMemberDocument = gql`
|
|
||||||
mutation RemoveWorkspaceMember($where: WorkspaceMemberWhereUniqueInput!) {
|
|
||||||
deleteWorkspaceMember(where: $where) {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export type RemoveWorkspaceMemberMutationFn = Apollo.MutationFunction<RemoveWorkspaceMemberMutation, RemoveWorkspaceMemberMutationVariables>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __useRemoveWorkspaceMemberMutation__
|
|
||||||
*
|
|
||||||
* To run a mutation, you first call `useRemoveWorkspaceMemberMutation` within a React component and pass it any options that fit your needs.
|
|
||||||
* When your component renders, `useRemoveWorkspaceMemberMutation` returns a tuple that includes:
|
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
|
||||||
*
|
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const [removeWorkspaceMemberMutation, { data, loading, error }] = useRemoveWorkspaceMemberMutation({
|
|
||||||
* variables: {
|
|
||||||
* where: // value for 'where'
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
export function useRemoveWorkspaceMemberMutation(baseOptions?: Apollo.MutationHookOptions<RemoveWorkspaceMemberMutation, RemoveWorkspaceMemberMutationVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useMutation<RemoveWorkspaceMemberMutation, RemoveWorkspaceMemberMutationVariables>(RemoveWorkspaceMemberDocument, options);
|
|
||||||
}
|
|
||||||
export type RemoveWorkspaceMemberMutationHookResult = ReturnType<typeof useRemoveWorkspaceMemberMutation>;
|
|
||||||
export type RemoveWorkspaceMemberMutationResult = Apollo.MutationResult<RemoveWorkspaceMemberMutation>;
|
|
||||||
export type RemoveWorkspaceMemberMutationOptions = Apollo.BaseMutationOptions<RemoveWorkspaceMemberMutation, RemoveWorkspaceMemberMutationVariables>;
|
|
||||||
export const UpdateWorkspaceDocument = gql`
|
export const UpdateWorkspaceDocument = gql`
|
||||||
mutation UpdateWorkspace($data: WorkspaceUpdateInput!) {
|
mutation UpdateWorkspace($data: WorkspaceUpdateInput!) {
|
||||||
updateWorkspace(data: $data) {
|
updateWorkspace(data: $data) {
|
||||||
@ -6839,40 +6658,42 @@ export function useUploadWorkspaceLogoMutation(baseOptions?: Apollo.MutationHook
|
|||||||
export type UploadWorkspaceLogoMutationHookResult = ReturnType<typeof useUploadWorkspaceLogoMutation>;
|
export type UploadWorkspaceLogoMutationHookResult = ReturnType<typeof useUploadWorkspaceLogoMutation>;
|
||||||
export type UploadWorkspaceLogoMutationResult = Apollo.MutationResult<UploadWorkspaceLogoMutation>;
|
export type UploadWorkspaceLogoMutationResult = Apollo.MutationResult<UploadWorkspaceLogoMutation>;
|
||||||
export type UploadWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>;
|
export type UploadWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>;
|
||||||
export const UpdateOneWorkspaceMemberDocument = gql`
|
export const GetCurrentWorkspaceDocument = gql`
|
||||||
mutation UpdateOneWorkspaceMember($data: WorkspaceMemberUpdateInput!, $where: WorkspaceMemberWhereUniqueInput!) {
|
query getCurrentWorkspace {
|
||||||
UpdateOneWorkspaceMember(data: $data, where: $where) {
|
currentWorkspace {
|
||||||
...workspaceMemberFieldsFragment
|
id
|
||||||
|
displayName
|
||||||
|
logo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${WorkspaceMemberFieldsFragmentFragmentDoc}`;
|
`;
|
||||||
export type UpdateOneWorkspaceMemberMutationFn = Apollo.MutationFunction<UpdateOneWorkspaceMemberMutation, UpdateOneWorkspaceMemberMutationVariables>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useUpdateOneWorkspaceMemberMutation__
|
* __useGetCurrentWorkspaceQuery__
|
||||||
*
|
*
|
||||||
* To run a mutation, you first call `useUpdateOneWorkspaceMemberMutation` within a React component and pass it any options that fit your needs.
|
* To run a query within a React component, call `useGetCurrentWorkspaceQuery` and pass it any options that fit your needs.
|
||||||
* When your component renders, `useUpdateOneWorkspaceMemberMutation` returns a tuple that includes:
|
* When your component renders, `useGetCurrentWorkspaceQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
* you can use to render your UI.
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const [updateOneWorkspaceMemberMutation, { data, loading, error }] = useUpdateOneWorkspaceMemberMutation({
|
* const { data, loading, error } = useGetCurrentWorkspaceQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
* data: // value for 'data'
|
|
||||||
* where: // value for 'where'
|
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useUpdateOneWorkspaceMemberMutation(baseOptions?: Apollo.MutationHookOptions<UpdateOneWorkspaceMemberMutation, UpdateOneWorkspaceMemberMutationVariables>) {
|
export function useGetCurrentWorkspaceQuery(baseOptions?: Apollo.QueryHookOptions<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useMutation<UpdateOneWorkspaceMemberMutation, UpdateOneWorkspaceMemberMutationVariables>(UpdateOneWorkspaceMemberDocument, options);
|
return Apollo.useQuery<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>(GetCurrentWorkspaceDocument, options);
|
||||||
}
|
}
|
||||||
export type UpdateOneWorkspaceMemberMutationHookResult = ReturnType<typeof useUpdateOneWorkspaceMemberMutation>;
|
export function useGetCurrentWorkspaceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>) {
|
||||||
export type UpdateOneWorkspaceMemberMutationResult = Apollo.MutationResult<UpdateOneWorkspaceMemberMutation>;
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
export type UpdateOneWorkspaceMemberMutationOptions = Apollo.BaseMutationOptions<UpdateOneWorkspaceMemberMutation, UpdateOneWorkspaceMemberMutationVariables>;
|
return Apollo.useLazyQuery<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>(GetCurrentWorkspaceDocument, options);
|
||||||
|
}
|
||||||
|
export type GetCurrentWorkspaceQueryHookResult = ReturnType<typeof useGetCurrentWorkspaceQuery>;
|
||||||
|
export type GetCurrentWorkspaceLazyQueryHookResult = ReturnType<typeof useGetCurrentWorkspaceLazyQuery>;
|
||||||
|
export type GetCurrentWorkspaceQueryResult = Apollo.QueryResult<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>;
|
||||||
export const GetWorkspaceFromInviteHashDocument = gql`
|
export const GetWorkspaceFromInviteHashDocument = gql`
|
||||||
query GetWorkspaceFromInviteHash($inviteHash: String!) {
|
query GetWorkspaceFromInviteHash($inviteHash: String!) {
|
||||||
findWorkspaceFromInviteHash(inviteHash: $inviteHash) {
|
findWorkspaceFromInviteHash(inviteHash: $inviteHash) {
|
||||||
@ -6914,13 +6735,9 @@ export const GetWorkspaceMembersDocument = gql`
|
|||||||
query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) {
|
query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) {
|
||||||
workspaceMembers: findManyWorkspaceMember(where: $where) {
|
workspaceMembers: findManyWorkspaceMember(where: $where) {
|
||||||
id
|
id
|
||||||
user {
|
|
||||||
...userFieldsFragment
|
|
||||||
avatarUrl
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${UserFieldsFragmentFragmentDoc}`;
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useGetWorkspaceMembersQuery__
|
* __useGetWorkspaceMembersQuery__
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
||||||
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
||||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||||
@ -23,6 +24,7 @@ export const useOpenCreateActivityDrawer = () => {
|
|||||||
const { openRightDrawer } = useRightDrawer();
|
const { openRightDrawer } = useRightDrawer();
|
||||||
const [createActivityMutation] = useCreateActivityMutation();
|
const [createActivityMutation] = useCreateActivityMutation();
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const setHotkeyScope = useSetHotkeyScope();
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
|
||||||
const [, setActivityTargetableEntityArray] = useRecoilState(
|
const [, setActivityTargetableEntityArray] = useRecoilState(
|
||||||
@ -49,11 +51,11 @@ export const useOpenCreateActivityDrawer = () => {
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
author: { connect: { id: currentUser?.id ?? '' } },
|
author: { connect: { id: currentUser?.id ?? '' } },
|
||||||
workspaceMemberAuthor: {
|
workspaceMemberAuthor: {
|
||||||
connect: { id: currentUser?.workspaceMember?.id ?? '' },
|
connect: { id: currentWorkspaceMember?.id ?? '' },
|
||||||
},
|
},
|
||||||
assignee: { connect: { id: assigneeId ?? currentUser?.id ?? '' } },
|
assignee: { connect: { id: assigneeId ?? currentUser?.id ?? '' } },
|
||||||
workspaceMemberAssignee: {
|
workspaceMemberAssignee: {
|
||||||
connect: { id: currentUser?.workspaceMember?.id ?? '' },
|
connect: { id: currentWorkspaceMember?.id ?? '' },
|
||||||
},
|
},
|
||||||
type: type,
|
type: type,
|
||||||
activityTargets: {
|
activityTargets: {
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { turnFilterIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause';
|
import { turnFilterIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
import { ActivityType, useGetActivitiesQuery } from '~/generated/graphql';
|
import { ActivityType, useGetActivitiesQuery } from '~/generated/graphql';
|
||||||
@ -9,6 +10,7 @@ import { parseDate } from '~/utils/date-utils';
|
|||||||
|
|
||||||
export const useCurrentUserTaskCount = () => {
|
export const useCurrentUserTaskCount = () => {
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const [currentUser] = useRecoilState(currentUserState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const { data } = useGetActivitiesQuery({
|
const { data } = useGetActivitiesQuery({
|
||||||
variables: {
|
variables: {
|
||||||
@ -20,8 +22,11 @@ export const useCurrentUserTaskCount = () => {
|
|||||||
fieldMetadataId: 'assigneeId',
|
fieldMetadataId: 'assigneeId',
|
||||||
value: currentUser.id,
|
value: currentUser.id,
|
||||||
operand: ViewFilterOperand.Is,
|
operand: ViewFilterOperand.Is,
|
||||||
displayValue: currentUser.displayName,
|
displayValue:
|
||||||
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
|
currentWorkspaceMember?.firstName +
|
||||||
|
' ' +
|
||||||
|
currentWorkspaceMember?.lastName,
|
||||||
|
displayAvatarUrl: currentWorkspaceMember?.avatarUrl ?? undefined,
|
||||||
definition: {
|
definition: {
|
||||||
type: 'ENTITY',
|
type: 'ENTITY',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { useRecoilCallback } from 'recoil';
|
|||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { generateFindManyCustomObjectsQuery } from '@/object-record/utils/generateFindManyCustomObjectsQuery';
|
import { useGenerateFindManyCustomObjectsQuery } from '@/object-record/utils/useGenerateFindManyCustomObjectsQuery';
|
||||||
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
||||||
import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys';
|
import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys';
|
||||||
import {
|
import {
|
||||||
@ -54,7 +54,7 @@ export const useOptimisticEffect = () => {
|
|||||||
objectMetadataItem?: ObjectMetadataItem;
|
objectMetadataItem?: ObjectMetadataItem;
|
||||||
}) => {
|
}) => {
|
||||||
if (isUsingFlexibleBackend && objectMetadataItem) {
|
if (isUsingFlexibleBackend && objectMetadataItem) {
|
||||||
const generatedQuery = generateFindManyCustomObjectsQuery({
|
const generatedQuery = useGenerateFindManyCustomObjectsQuery({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -9,49 +9,5 @@ export const USER_QUERY_FRAGMENT = gql`
|
|||||||
lastName
|
lastName
|
||||||
canImpersonate
|
canImpersonate
|
||||||
supportUserHash
|
supportUserHash
|
||||||
avatarUrl
|
|
||||||
workspaceMember {
|
|
||||||
id
|
|
||||||
allowImpersonation
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -4,12 +4,19 @@ import {
|
|||||||
snapshot_UNSTABLE,
|
snapshot_UNSTABLE,
|
||||||
useGotoRecoilSnapshot,
|
useGotoRecoilSnapshot,
|
||||||
useRecoilState,
|
useRecoilState,
|
||||||
|
useSetRecoilState,
|
||||||
} from 'recoil';
|
} from 'recoil';
|
||||||
|
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
|
import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState';
|
||||||
|
import { CREATE_ONE_WORKSPACE_MEMBER_V2 } from '@/object-record/graphql/mutation/createOneWorkspaceMember';
|
||||||
|
import { FIND_ONE_WORKSPACE_MEMBER_V2 } from '@/object-record/graphql/queries/findOneWorkspaceMember';
|
||||||
import { REACT_APP_SERVER_AUTH_URL } from '~/config';
|
import { REACT_APP_SERVER_AUTH_URL } from '~/config';
|
||||||
import {
|
import {
|
||||||
useChallengeMutation,
|
useChallengeMutation,
|
||||||
useCheckUserExistsLazyQuery,
|
useCheckUserExistsLazyQuery,
|
||||||
|
useGetCurrentWorkspaceLazyQuery,
|
||||||
useSignUpMutation,
|
useSignUpMutation,
|
||||||
useVerifyMutation,
|
useVerifyMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
@ -19,13 +26,20 @@ import { tokenPairState } from '../states/tokenPairState';
|
|||||||
|
|
||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
const [, setTokenPair] = useRecoilState(tokenPairState);
|
const [, setTokenPair] = useRecoilState(tokenPairState);
|
||||||
const [, setCurrentUser] = useRecoilState(currentUserState);
|
const setCurrentUser = useSetRecoilState(currentUserState);
|
||||||
|
const setCurrentWorkspaceMember = useSetRecoilState(
|
||||||
|
currentWorkspaceMemberState,
|
||||||
|
);
|
||||||
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||||
|
const setIsVerifyPendingState = useSetRecoilState(isVerifyPendingState);
|
||||||
|
|
||||||
const [challenge] = useChallengeMutation();
|
const [challenge] = useChallengeMutation();
|
||||||
const [signUp] = useSignUpMutation();
|
const [signUp] = useSignUpMutation();
|
||||||
const [verify] = useVerifyMutation();
|
const [verify] = useVerifyMutation();
|
||||||
const [checkUserExistsQuery, { data: checkUserExistsData }] =
|
const [checkUserExistsQuery, { data: checkUserExistsData }] =
|
||||||
useCheckUserExistsLazyQuery();
|
useCheckUserExistsLazyQuery();
|
||||||
|
const [getCurrentWorkspaceQuery, { data: getCurrentWorkspaceData }] =
|
||||||
|
useGetCurrentWorkspaceLazyQuery();
|
||||||
|
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
|
|
||||||
@ -67,36 +81,56 @@ export const useAuth = () => {
|
|||||||
throw new Error('No verify result');
|
throw new Error('No verify result');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verifyResult.data?.verify.user.workspaceMember) {
|
setTokenPair(verifyResult.data?.verify.tokens);
|
||||||
throw new Error('No workspace member');
|
const workspaceMember = await client.query({
|
||||||
}
|
query: FIND_ONE_WORKSPACE_MEMBER_V2,
|
||||||
|
variables: {
|
||||||
if (!verifyResult.data?.verify.user.workspaceMember.settings) {
|
filter: {
|
||||||
throw new Error('No settings');
|
userId: { eq: verifyResult.data?.verify.user.id },
|
||||||
}
|
},
|
||||||
|
|
||||||
setCurrentUser({
|
|
||||||
...verifyResult.data?.verify.user,
|
|
||||||
workspaceMember: {
|
|
||||||
...verifyResult.data?.verify.user.workspaceMember,
|
|
||||||
settings: verifyResult.data?.verify.user.workspaceMember.settings,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
setTokenPair(verifyResult.data?.verify.tokens);
|
const currentWorkspace = await getCurrentWorkspaceQuery();
|
||||||
|
|
||||||
return verifyResult.data?.verify;
|
setCurrentUser(verifyResult.data?.verify.user);
|
||||||
|
setCurrentWorkspaceMember(workspaceMember.data?.findMany);
|
||||||
|
setCurrentWorkspace(currentWorkspace.data?.currentWorkspace ?? null);
|
||||||
|
return {
|
||||||
|
user: verifyResult.data?.verify.user,
|
||||||
|
workspaceMember: workspaceMember.data?.findMany,
|
||||||
|
workspace: currentWorkspace.data?.currentWorkspace,
|
||||||
|
tokens: verifyResult.data?.verify.tokens,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[setTokenPair, verify, setCurrentUser],
|
[
|
||||||
|
verify,
|
||||||
|
setTokenPair,
|
||||||
|
client,
|
||||||
|
getCurrentWorkspaceQuery,
|
||||||
|
setCurrentUser,
|
||||||
|
setCurrentWorkspaceMember,
|
||||||
|
setCurrentWorkspace,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCrendentialsSignIn = useCallback(
|
const handleCrendentialsSignIn = useCallback(
|
||||||
async (email: string, password: string) => {
|
async (email: string, password: string) => {
|
||||||
const { loginToken } = await handleChallenge(email, password);
|
const { loginToken } = await handleChallenge(email, password);
|
||||||
|
setIsVerifyPendingState(true);
|
||||||
|
|
||||||
const { user } = await handleVerify(loginToken.token);
|
const { user, workspaceMember, workspace } = await handleVerify(
|
||||||
return user;
|
loginToken.token,
|
||||||
|
);
|
||||||
|
|
||||||
|
setIsVerifyPendingState(false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
workspaceMember,
|
||||||
|
workspace,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[handleChallenge, handleVerify],
|
[handleChallenge, handleVerify, setIsVerifyPendingState],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSignOut = useCallback(() => {
|
const handleSignOut = useCallback(() => {
|
||||||
@ -110,6 +144,8 @@ export const useAuth = () => {
|
|||||||
|
|
||||||
const handleCredentialsSignUp = useCallback(
|
const handleCredentialsSignUp = useCallback(
|
||||||
async (email: string, password: string, workspaceInviteHash?: string) => {
|
async (email: string, password: string, workspaceInviteHash?: string) => {
|
||||||
|
setIsVerifyPendingState(true);
|
||||||
|
|
||||||
const signUpResult = await signUp({
|
const signUpResult = await signUp({
|
||||||
variables: {
|
variables: {
|
||||||
email,
|
email,
|
||||||
@ -126,13 +162,30 @@ export const useAuth = () => {
|
|||||||
throw new Error('No login token');
|
throw new Error('No login token');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { user } = await handleVerify(
|
const { user, workspace } = await handleVerify(
|
||||||
signUpResult.data?.signUp.loginToken.token,
|
signUpResult.data?.signUp.loginToken.token,
|
||||||
);
|
);
|
||||||
|
|
||||||
return user;
|
const workspaceMember = await client.mutate({
|
||||||
|
mutation: CREATE_ONE_WORKSPACE_MEMBER_V2,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
firstName: user.firstName ?? '',
|
||||||
|
lastName: user.lastName ?? '',
|
||||||
|
colorScheme: 'Light',
|
||||||
|
userId: user.id,
|
||||||
|
allowImpersonation: true,
|
||||||
|
locale: 'en',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setCurrentWorkspaceMember(workspaceMember.data?.createWorkspaceMemberV2);
|
||||||
|
|
||||||
|
setIsVerifyPendingState(false);
|
||||||
|
|
||||||
|
return { user, workspaceMember, workspace };
|
||||||
},
|
},
|
||||||
[signUp, handleVerify],
|
[setIsVerifyPendingState, signUp, handleVerify, client],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleGoogleLogin = useCallback((workspaceInviteHash?: string) => {
|
const handleGoogleLogin = useCallback((workspaceInviteHash?: string) => {
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState';
|
||||||
|
|
||||||
import { tokenPairState } from '../states/tokenPairState';
|
import { tokenPairState } from '../states/tokenPairState';
|
||||||
|
|
||||||
export const useIsLogged = (): boolean => {
|
export const useIsLogged = (): boolean => {
|
||||||
const [tokenPair] = useRecoilState(tokenPairState);
|
const [tokenPair] = useRecoilState(tokenPairState);
|
||||||
|
const isVerifyPending = useRecoilValue(isVerifyPendingState);
|
||||||
|
|
||||||
return !!tokenPair;
|
return !!tokenPair && !isVerifyPending;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,15 +1,26 @@
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
|
|
||||||
import { useIsLogged } from '../hooks/useIsLogged';
|
import { useIsLogged } from '../hooks/useIsLogged';
|
||||||
import { currentUserState } from '../states/currentUserState';
|
|
||||||
import {
|
import {
|
||||||
getOnboardingStatus,
|
getOnboardingStatus,
|
||||||
OnboardingStatus,
|
OnboardingStatus,
|
||||||
} from '../utils/getOnboardingStatus';
|
} from '../utils/getOnboardingStatus';
|
||||||
|
|
||||||
export const useOnboardingStatus = (): OnboardingStatus | undefined => {
|
export const useOnboardingStatus = (): OnboardingStatus | undefined => {
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
const isLoggedIn = useIsLogged();
|
const isLoggedIn = useIsLogged();
|
||||||
|
|
||||||
return getOnboardingStatus(isLoggedIn, currentUser);
|
console.log(
|
||||||
|
getOnboardingStatus(isLoggedIn, currentWorkspaceMember, currentWorkspace),
|
||||||
|
);
|
||||||
|
|
||||||
|
return getOnboardingStatus(
|
||||||
|
isLoggedIn,
|
||||||
|
currentWorkspaceMember,
|
||||||
|
currentWorkspace,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export const useSignInUp = () => {
|
|||||||
});
|
});
|
||||||
const [showErrors, setShowErrors] = useState(false);
|
const [showErrors, setShowErrors] = useState(false);
|
||||||
|
|
||||||
const { data: workspace } = useGetWorkspaceFromInviteHashQuery({
|
const { data: workspaceFromInviteHash } = useGetWorkspaceFromInviteHashQuery({
|
||||||
variables: { inviteHash: workspaceInviteHash || '' },
|
variables: { inviteHash: workspaceInviteHash || '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -119,20 +119,23 @@ export const useSignInUp = () => {
|
|||||||
if (!data.email || !data.password) {
|
if (!data.email || !data.password) {
|
||||||
throw new Error('Email and password are required');
|
throw new Error('Email and password are required');
|
||||||
}
|
}
|
||||||
let user;
|
let currentWorkspace;
|
||||||
|
|
||||||
if (signInUpMode === SignInUpMode.SignIn) {
|
if (signInUpMode === SignInUpMode.SignIn) {
|
||||||
user = await signInWithCredentials(
|
const { workspace } = await signInWithCredentials(
|
||||||
data.email.toLowerCase(),
|
data.email.toLowerCase(),
|
||||||
data.password,
|
data.password,
|
||||||
);
|
);
|
||||||
|
currentWorkspace = workspace;
|
||||||
} else {
|
} else {
|
||||||
user = await signUpWithCredentials(
|
const { workspace } = await signUpWithCredentials(
|
||||||
data.email.toLowerCase(),
|
data.email.toLowerCase(),
|
||||||
data.password,
|
data.password,
|
||||||
workspaceInviteHash,
|
workspaceInviteHash,
|
||||||
);
|
);
|
||||||
|
currentWorkspace = workspace;
|
||||||
}
|
}
|
||||||
if (user?.workspaceMember?.workspace?.displayName) {
|
if (currentWorkspace?.displayName) {
|
||||||
navigate('/');
|
navigate('/');
|
||||||
} else {
|
} else {
|
||||||
navigate('/create/workspace');
|
navigate('/create/workspace');
|
||||||
@ -144,12 +147,12 @@ export const useSignInUp = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
navigate,
|
signInUpMode,
|
||||||
signInWithCredentials,
|
signInWithCredentials,
|
||||||
signUpWithCredentials,
|
signUpWithCredentials,
|
||||||
workspaceInviteHash,
|
workspaceInviteHash,
|
||||||
|
navigate,
|
||||||
enqueueSnackBar,
|
enqueueSnackBar,
|
||||||
signInUpMode,
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -188,6 +191,6 @@ export const useSignInUp = () => {
|
|||||||
goBackToEmailStep,
|
goBackToEmailStep,
|
||||||
submitCredentials,
|
submitCredentials,
|
||||||
form,
|
form,
|
||||||
workspace: workspace?.findWorkspaceFromInviteHash,
|
workspace: workspaceFromInviteHash?.findWorkspaceFromInviteHash,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,32 +1,11 @@
|
|||||||
import { atom } from 'recoil';
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
import {
|
import { User } from '~/generated/graphql';
|
||||||
User,
|
|
||||||
UserSettings,
|
|
||||||
Workspace,
|
|
||||||
WorkspaceMember,
|
|
||||||
} from '~/generated/graphql';
|
|
||||||
|
|
||||||
export type CurrentUser = Pick<
|
export type CurrentUser = Pick<
|
||||||
User,
|
User,
|
||||||
| 'id'
|
'id' | 'email' | 'supportUserHash' | 'canImpersonate'
|
||||||
| 'email'
|
>;
|
||||||
| 'displayName'
|
|
||||||
| 'firstName'
|
|
||||||
| 'lastName'
|
|
||||||
| 'avatarUrl'
|
|
||||||
| 'canImpersonate'
|
|
||||||
| 'supportUserHash'
|
|
||||||
> & {
|
|
||||||
workspaceMember: Pick<WorkspaceMember, 'id' | 'allowImpersonation'> & {
|
|
||||||
workspace: Pick<
|
|
||||||
Workspace,
|
|
||||||
'id' | 'displayName' | 'domainName' | 'inviteHash' | 'logo'
|
|
||||||
>;
|
|
||||||
settings: Pick<UserSettings, 'id' | 'colorScheme' | 'locale'>;
|
|
||||||
};
|
|
||||||
settings: Pick<UserSettings, 'id' | 'colorScheme' | 'locale'>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const currentUserState = atom<CurrentUser | null>({
|
export const currentUserState = atom<CurrentUser | null>({
|
||||||
key: 'currentUserState',
|
key: 'currentUserState',
|
||||||
|
|||||||
18
front/src/modules/auth/states/currentWorkspaceMemberState.ts
Normal file
18
front/src/modules/auth/states/currentWorkspaceMemberState.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
|
import { ColorScheme } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
export type CurrentWorkspaceMember = {
|
||||||
|
id: string;
|
||||||
|
locale: string;
|
||||||
|
colorScheme: ColorScheme;
|
||||||
|
allowImpersonation: boolean;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const currentWorkspaceMemberState = atom<CurrentWorkspaceMember | null>({
|
||||||
|
key: 'currentWorkspaceMemberState',
|
||||||
|
default: null,
|
||||||
|
});
|
||||||
13
front/src/modules/auth/states/currentWorkspaceState.ts
Normal file
13
front/src/modules/auth/states/currentWorkspaceState.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
|
import { Workspace } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
export type CurrentWorkspace = Pick<
|
||||||
|
Workspace,
|
||||||
|
'id' | 'inviteHash' | 'logo' | 'displayName'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const currentWorkspaceState = atom<CurrentWorkspace | null>({
|
||||||
|
key: 'currentWorkspaceState',
|
||||||
|
default: null,
|
||||||
|
});
|
||||||
6
front/src/modules/auth/states/isVerifyPendingState.ts
Normal file
6
front/src/modules/auth/states/isVerifyPendingState.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
|
export const isVerifyPendingState = atom<boolean>({
|
||||||
|
key: 'isVerifyPendingState',
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { CurrentUser } from '../states/currentUserState';
|
import { CurrentWorkspaceMember } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
|
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
|
||||||
|
|
||||||
export enum OnboardingStatus {
|
export enum OnboardingStatus {
|
||||||
OngoingUserCreation = 'ongoing_user_creation',
|
OngoingUserCreation = 'ongoing_user_creation',
|
||||||
@ -9,21 +10,22 @@ export enum OnboardingStatus {
|
|||||||
|
|
||||||
export const getOnboardingStatus = (
|
export const getOnboardingStatus = (
|
||||||
isLoggedIn: boolean,
|
isLoggedIn: boolean,
|
||||||
currentUser: CurrentUser | null,
|
currentWorkspaceMember: CurrentWorkspaceMember | null,
|
||||||
|
currentWorkspace: CurrentWorkspace | null,
|
||||||
) => {
|
) => {
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
return OnboardingStatus.OngoingUserCreation;
|
return OnboardingStatus.OngoingUserCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user has not been fetched yet, we can't know the onboarding status
|
// if the user has not been fetched yet, we can't know the onboarding status
|
||||||
if (!currentUser) {
|
if (!currentWorkspaceMember) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentUser.workspaceMember?.workspace.displayName) {
|
if (!currentWorkspace?.displayName) {
|
||||||
return OnboardingStatus.OngoingWorkspaceCreation;
|
return OnboardingStatus.OngoingWorkspaceCreation;
|
||||||
}
|
}
|
||||||
if (!currentUser.firstName || !currentUser.lastName) {
|
if (!currentWorkspaceMember.firstName || !currentWorkspaceMember.lastName) {
|
||||||
return OnboardingStatus.OngoingProfileCreation;
|
return OnboardingStatus.OngoingProfileCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,6 @@ export const FIND_MANY_METADATA_OBJECTS = gql`
|
|||||||
label
|
label
|
||||||
description
|
description
|
||||||
icon
|
icon
|
||||||
placeholder
|
|
||||||
isCustom
|
isCustom
|
||||||
isActive
|
isActive
|
||||||
isNullable
|
isNullable
|
||||||
@ -36,10 +35,34 @@ export const FIND_MANY_METADATA_OBJECTS = gql`
|
|||||||
fromRelationMetadata {
|
fromRelationMetadata {
|
||||||
id
|
id
|
||||||
relationType
|
relationType
|
||||||
|
toObjectMetadata {
|
||||||
|
id
|
||||||
|
dataSourceId
|
||||||
|
nameSingular
|
||||||
|
namePlural
|
||||||
|
}
|
||||||
|
fromObjectMetadata {
|
||||||
|
id
|
||||||
|
dataSourceId
|
||||||
|
nameSingular
|
||||||
|
namePlural
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toRelationMetadata {
|
toRelationMetadata {
|
||||||
id
|
id
|
||||||
relationType
|
relationType
|
||||||
|
toObjectMetadata {
|
||||||
|
id
|
||||||
|
dataSourceId
|
||||||
|
nameSingular
|
||||||
|
namePlural
|
||||||
|
}
|
||||||
|
fromObjectMetadata {
|
||||||
|
id
|
||||||
|
dataSourceId
|
||||||
|
nameSingular
|
||||||
|
namePlural
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
import { logError } from '~/utils/logError';
|
import { logError } from '~/utils/logError';
|
||||||
|
|
||||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||||
import { formatPagedObjectMetadataItemsToObjectMetadataItems } from '../utils/formatPagedObjectMetadataItemsToObjectMetadataItems';
|
import { mapPaginatedObjectMetadataItemsToObjectMetadataItems } from '../utils/mapPaginatedObjectMetadataItemsToObjectMetadataItems';
|
||||||
|
|
||||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export const useFindManyObjectMetadataItems = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const objectMetadataItems = useMemo(() => {
|
const objectMetadataItems = useMemo(() => {
|
||||||
return formatPagedObjectMetadataItemsToObjectMetadataItems({
|
return mapPaginatedObjectMetadataItemsToObjectMetadataItems({
|
||||||
pagedObjectMetadataItems: data,
|
pagedObjectMetadataItems: data,
|
||||||
});
|
});
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
|
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
||||||
|
import {
|
||||||
|
ObjectFilter,
|
||||||
|
ObjectMetadataItemsQuery,
|
||||||
|
ObjectMetadataItemsQueryVariables,
|
||||||
|
} from '~/generated-metadata/graphql';
|
||||||
|
import { logError } from '~/utils/logError';
|
||||||
|
|
||||||
|
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||||
|
import { mapPaginatedObjectMetadataItemsToObjectMetadataItems } from '../utils/mapPaginatedObjectMetadataItemsToObjectMetadataItems';
|
||||||
|
|
||||||
|
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||||
|
|
||||||
|
// TODO: test fetchMore
|
||||||
|
export const useFindManyObjectMetadataItems = ({
|
||||||
|
skip,
|
||||||
|
filter,
|
||||||
|
}: { skip?: boolean; filter?: ObjectFilter } = {}) => {
|
||||||
|
const apolloMetadataClient = useApolloMetadataClient();
|
||||||
|
|
||||||
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
fetchMore: fetchMoreInternal,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useQuery<ObjectMetadataItemsQuery, ObjectMetadataItemsQueryVariables>(
|
||||||
|
FIND_MANY_METADATA_OBJECTS,
|
||||||
|
{
|
||||||
|
variables: {
|
||||||
|
filter,
|
||||||
|
},
|
||||||
|
client: apolloMetadataClient ?? undefined,
|
||||||
|
skip: skip || !apolloMetadataClient,
|
||||||
|
onError: (error) => {
|
||||||
|
logError('useFindManyObjectMetadataItems error : ' + error);
|
||||||
|
enqueueSnackBar(
|
||||||
|
`Error during useFindManyObjectMetadataItems, ${error.message}`,
|
||||||
|
{
|
||||||
|
variant: 'error',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onCompleted: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasMore = data?.objects?.pageInfo?.hasNextPage;
|
||||||
|
|
||||||
|
const fetchMore = () =>
|
||||||
|
fetchMoreInternal({
|
||||||
|
variables: {
|
||||||
|
afterCursor: data?.objects?.pageInfo?.endCursor,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const objectMetadataItems = useMemo(() => {
|
||||||
|
return mapPaginatedObjectMetadataItemsToObjectMetadataItems({
|
||||||
|
pagedObjectMetadataItems: data,
|
||||||
|
});
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
objectMetadataItems,
|
||||||
|
hasMore,
|
||||||
|
fetchMore,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
import { generateCreateOneObjectMutation } from '@/object-record/utils/generateCreateOneObjectMutation';
|
import { useGenerateCreateOneObjectMutation } from '@/object-record/utils/generateCreateOneObjectMutation';
|
||||||
import { generateDeleteOneObjectMutation } from '@/object-record/utils/generateDeleteOneObjectMutation';
|
import { useGenerateDeleteOneObjectMutation } from '@/object-record/utils/useGenerateDeleteOneObjectMutation';
|
||||||
import { generateFindManyCustomObjectsQuery } from '@/object-record/utils/generateFindManyCustomObjectsQuery';
|
import { useGenerateFindManyCustomObjectsQuery } from '@/object-record/utils/useGenerateFindManyCustomObjectsQuery';
|
||||||
import { generateFindOneCustomObjectQuery } from '@/object-record/utils/generateFindOneCustomObjectQuery';
|
import { useGenerateFindOneCustomObjectQuery } from '@/object-record/utils/useGenerateFindOneCustomObjectQuery';
|
||||||
import { generateUpdateOneObjectMutation } from '@/object-record/utils/generateUpdateOneObjectMutation';
|
import { useGenerateUpdateOneObjectMutation } from '@/object-record/utils/useGenerateUpdateOneObjectMutation';
|
||||||
import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
|
import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
|
||||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||||
@ -16,13 +16,13 @@ import { formatFieldMetadataItemsAsSortDefinitions } from '../utils/formatFieldM
|
|||||||
|
|
||||||
import { useFindManyObjectMetadataItems } from './useFindManyObjectMetadataItems';
|
import { useFindManyObjectMetadataItems } from './useFindManyObjectMetadataItems';
|
||||||
|
|
||||||
const EMPTY_QUERY = gql`
|
export const EMPTY_QUERY = gql`
|
||||||
query EmptyQuery {
|
query EmptyQuery {
|
||||||
empty
|
empty
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EMPTY_MUTATION = gql`
|
export const EMPTY_MUTATION = gql`
|
||||||
mutation EmptyMutation {
|
mutation EmptyMutation {
|
||||||
empty
|
empty
|
||||||
}
|
}
|
||||||
@ -74,35 +74,25 @@ export const useFindOneObjectMetadataItem = ({
|
|||||||
icons,
|
icons,
|
||||||
});
|
});
|
||||||
|
|
||||||
const findManyQuery = foundObjectMetadataItem
|
const findManyQuery = useGenerateFindManyCustomObjectsQuery({
|
||||||
? generateFindManyCustomObjectsQuery({
|
objectMetadataItem: foundObjectMetadataItem,
|
||||||
objectMetadataItem: foundObjectMetadataItem,
|
});
|
||||||
})
|
|
||||||
: EMPTY_QUERY;
|
|
||||||
|
|
||||||
const findOneQuery = foundObjectMetadataItem
|
const findOneQuery = useGenerateFindOneCustomObjectQuery({
|
||||||
? generateFindOneCustomObjectQuery({
|
objectMetadataItem: foundObjectMetadataItem,
|
||||||
objectMetadataItem: foundObjectMetadataItem,
|
});
|
||||||
})
|
|
||||||
: EMPTY_QUERY;
|
|
||||||
|
|
||||||
const createOneMutation = foundObjectMetadataItem
|
const createOneMutation = useGenerateCreateOneObjectMutation({
|
||||||
? generateCreateOneObjectMutation({
|
objectMetadataItem: foundObjectMetadataItem,
|
||||||
objectMetadataItem: foundObjectMetadataItem,
|
});
|
||||||
})
|
|
||||||
: EMPTY_MUTATION;
|
|
||||||
|
|
||||||
const updateOneMutation = foundObjectMetadataItem
|
const updateOneMutation = useGenerateUpdateOneObjectMutation({
|
||||||
? generateUpdateOneObjectMutation({
|
objectMetadataItem: foundObjectMetadataItem,
|
||||||
objectMetadataItem: foundObjectMetadataItem,
|
});
|
||||||
})
|
|
||||||
: EMPTY_MUTATION;
|
|
||||||
|
|
||||||
const deleteOneMutation = foundObjectMetadataItem
|
const deleteOneMutation = useGenerateDeleteOneObjectMutation({
|
||||||
? generateDeleteOneObjectMutation({
|
objectMetadataItem: foundObjectMetadataItem,
|
||||||
objectMetadataItem: foundObjectMetadataItem,
|
});
|
||||||
})
|
|
||||||
: EMPTY_MUTATION;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
foundObjectMetadataItem,
|
foundObjectMetadataItem,
|
||||||
|
|||||||
@ -0,0 +1,86 @@
|
|||||||
|
import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems';
|
||||||
|
import { FieldType } from '@/ui/object/field/types/FieldType';
|
||||||
|
|
||||||
|
import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||||
|
|
||||||
|
export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||||
|
const { objectMetadataItems } = useFindManyObjectMetadataItems();
|
||||||
|
|
||||||
|
const mapFieldMetadataToGraphQLQuery = (field: FieldMetadataItem): any => {
|
||||||
|
// TODO: parse
|
||||||
|
const fieldType = field.type as FieldType;
|
||||||
|
|
||||||
|
const fieldIsSimpleValue = (
|
||||||
|
[
|
||||||
|
'TEXT',
|
||||||
|
'PHONE',
|
||||||
|
'DATE',
|
||||||
|
'EMAIL',
|
||||||
|
'NUMBER',
|
||||||
|
'BOOLEAN',
|
||||||
|
'DATE',
|
||||||
|
] as FieldType[]
|
||||||
|
).includes(fieldType);
|
||||||
|
|
||||||
|
const fieldIsURL = fieldType === 'URL' || fieldType === 'URL_V2';
|
||||||
|
|
||||||
|
const fieldIsMoneyAmount =
|
||||||
|
fieldType === 'MONEY' || fieldType === 'MONEY_AMOUNT_V2';
|
||||||
|
|
||||||
|
if (fieldIsSimpleValue) {
|
||||||
|
return field.name;
|
||||||
|
} else if (
|
||||||
|
fieldType === 'RELATION' &&
|
||||||
|
field.toRelationMetadata?.relationType === 'ONE_TO_MANY'
|
||||||
|
) {
|
||||||
|
console.log({ objectMetadataItems, field });
|
||||||
|
|
||||||
|
const relationMetadataItem = objectMetadataItems.find(
|
||||||
|
(objectMetadataItem) =>
|
||||||
|
objectMetadataItem.id ===
|
||||||
|
(field.toRelationMetadata as any)?.fromObjectMetadata?.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log({ relationMetadataItem });
|
||||||
|
|
||||||
|
return `${field.name}
|
||||||
|
{
|
||||||
|
id
|
||||||
|
${relationMetadataItem?.fields
|
||||||
|
.filter((field) => field.type !== 'RELATION')
|
||||||
|
.map((field) => field.name)
|
||||||
|
.join('\n')}
|
||||||
|
}`;
|
||||||
|
} else if (
|
||||||
|
fieldType === 'RELATION' &&
|
||||||
|
field.fromRelationMetadata?.relationType === 'ONE_TO_MANY'
|
||||||
|
) {
|
||||||
|
return `${field.name}
|
||||||
|
{
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
} else if (fieldIsURL) {
|
||||||
|
return `
|
||||||
|
${field.name}
|
||||||
|
{
|
||||||
|
text
|
||||||
|
link
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
} else if (fieldIsMoneyAmount) {
|
||||||
|
return `
|
||||||
|
${field.name}
|
||||||
|
{
|
||||||
|
amount
|
||||||
|
currency
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapFieldMetadataToGraphQLQuery;
|
||||||
|
};
|
||||||
@ -1,65 +0,0 @@
|
|||||||
import { FieldType } from '@/ui/object/field/types/FieldType';
|
|
||||||
|
|
||||||
import { FieldMetadataItem } from '../types/FieldMetadataItem';
|
|
||||||
|
|
||||||
export const mapFieldMetadataToGraphQLQuery = (field: FieldMetadataItem) => {
|
|
||||||
// TODO: parse
|
|
||||||
const fieldType = field.type as FieldType;
|
|
||||||
|
|
||||||
const fieldIsSimpleValue = (
|
|
||||||
[
|
|
||||||
'TEXT',
|
|
||||||
'PHONE',
|
|
||||||
'DATE',
|
|
||||||
'EMAIL',
|
|
||||||
'NUMBER',
|
|
||||||
'BOOLEAN',
|
|
||||||
'DATE',
|
|
||||||
] as FieldType[]
|
|
||||||
).includes(fieldType);
|
|
||||||
|
|
||||||
const fieldIsURL = fieldType === 'URL' || fieldType === 'URL_V2';
|
|
||||||
|
|
||||||
const fieldIsMoneyAmount =
|
|
||||||
fieldType === 'MONEY' || fieldType === 'MONEY_AMOUNT_V2';
|
|
||||||
|
|
||||||
if (fieldIsSimpleValue) {
|
|
||||||
return field.name;
|
|
||||||
} else if (
|
|
||||||
fieldType === 'RELATION' &&
|
|
||||||
field.toRelationMetadata?.relationType === 'ONE_TO_MANY'
|
|
||||||
) {
|
|
||||||
return `${field.name}
|
|
||||||
{
|
|
||||||
id
|
|
||||||
}`;
|
|
||||||
} else if (
|
|
||||||
fieldType === 'RELATION' &&
|
|
||||||
field.fromRelationMetadata?.relationType === 'ONE_TO_MANY'
|
|
||||||
) {
|
|
||||||
return `${field.name}
|
|
||||||
{
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
} else if (fieldIsURL) {
|
|
||||||
return `
|
|
||||||
${field.name}
|
|
||||||
{
|
|
||||||
text
|
|
||||||
link
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
} else if (fieldIsMoneyAmount) {
|
|
||||||
return `
|
|
||||||
${field.name}
|
|
||||||
{
|
|
||||||
amount
|
|
||||||
currency
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -2,8 +2,8 @@ import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql';
|
|||||||
|
|
||||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||||
|
|
||||||
export const formatPagedObjectMetadataItemsToObjectMetadataItems = ({
|
export const mapPaginatedObjectMetadataItemsToObjectMetadataItems = ({
|
||||||
pagedObjectMetadataItems: pagedObjectMetadataItems,
|
pagedObjectMetadataItems,
|
||||||
}: {
|
}: {
|
||||||
pagedObjectMetadataItems: ObjectMetadataItemsQuery | undefined;
|
pagedObjectMetadataItems: ObjectMetadataItemsQuery | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const CREATE_ONE_WORKSPACE_MEMBER_V2 = gql`
|
||||||
|
mutation CreateOneWorkspaceMemberV2($input: WorkspaceMemberV2CreateInput!) {
|
||||||
|
createWorkspaceMemberV2(data: $input) {
|
||||||
|
id
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const FIND_ONE_WORKSPACE_MEMBER_V2 = gql`
|
||||||
|
query FindManyWorkspaceMembersV2($filter: WorkspaceMemberV2FilterInput) {
|
||||||
|
workspaceMembersV2(filter: $filter) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -20,12 +20,10 @@ export const useDeleteOneObjectRecord = ({
|
|||||||
const [mutate] = useMutation(deleteOneMutation);
|
const [mutate] = useMutation(deleteOneMutation);
|
||||||
|
|
||||||
const deleteOneObject = foundObjectMetadataItem
|
const deleteOneObject = foundObjectMetadataItem
|
||||||
? (input: Record<string, any>) => {
|
? (idToDelete: string) => {
|
||||||
return mutate({
|
return mutate({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
idToDelete,
|
||||||
...input,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
refetchQueries: [getOperationName(findManyQuery) ?? ''],
|
refetchQueries: [getOperationName(findManyQuery) ?? ''],
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import {
|
|||||||
PaginatedObjectTypeEdge,
|
PaginatedObjectTypeEdge,
|
||||||
PaginatedObjectTypeResults,
|
PaginatedObjectTypeResults,
|
||||||
} from '../types/PaginatedObjectTypeResults';
|
} from '../types/PaginatedObjectTypeResults';
|
||||||
import { formatPagedObjectsToObjects } from '../utils/formatPagedObjectsToObjects';
|
import { mapPaginatedObjectsToObjects } from '../utils/mapPaginatedObjectsToObjects';
|
||||||
|
|
||||||
// TODO: test with a wrong name
|
// TODO: test with a wrong name
|
||||||
// TODO: add zod to validate that we have at least id on each object
|
// TODO: add zod to validate that we have at least id on each object
|
||||||
@ -163,7 +163,7 @@ export const useFindManyObjectRecords = <
|
|||||||
const objects = useMemo(
|
const objects = useMemo(
|
||||||
() =>
|
() =>
|
||||||
objectNamePlural
|
objectNamePlural
|
||||||
? formatPagedObjectsToObjects({
|
? mapPaginatedObjectsToObjects({
|
||||||
pagedObjects: data,
|
pagedObjects: data,
|
||||||
objectNamePlural,
|
objectNamePlural,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -16,6 +16,8 @@ export const useUpdateOneObjectRecord = ({
|
|||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('update one object');
|
||||||
|
|
||||||
// TODO: type this with a minimal type at least with Record<string, any>
|
// TODO: type this with a minimal type at least with Record<string, any>
|
||||||
const [mutate] = useMutation(updateOneMutation);
|
const [mutate] = useMutation(updateOneMutation);
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,21 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
import { EMPTY_MUTATION } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
|
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { mapFieldMetadataToGraphQLQuery } from '@/object-metadata/utils/mapFieldMetadataToGraphQLQuery';
|
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const generateCreateOneObjectMutation = ({
|
export const useGenerateCreateOneObjectMutation = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem | undefined | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
|
||||||
|
|
||||||
|
if (!objectMetadataItem) {
|
||||||
|
return EMPTY_MUTATION;
|
||||||
|
}
|
||||||
|
|
||||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
||||||
|
|
||||||
return gql`
|
return gql`
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export const formatPagedObjectsToObjects = <
|
export const mapPaginatedObjectsToObjects = <
|
||||||
ObjectType extends { id: string } & Record<string, any>,
|
ObjectType extends { id: string } & Record<string, any>,
|
||||||
ObjectTypeQuery extends {
|
ObjectTypeQuery extends {
|
||||||
[objectNamePlural: string]: {
|
[objectNamePlural: string]: {
|
||||||
@ -1,14 +1,19 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
import { EMPTY_MUTATION } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const generateDeleteOneObjectMutation = ({
|
export const useGenerateDeleteOneObjectMutation = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem | undefined | null;
|
||||||
}) => {
|
}) => {
|
||||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
if (!objectMetadataItem) {
|
||||||
|
return EMPTY_MUTATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const capitalizedObjectName = capitalize(objectMetadataItem?.nameSingular);
|
||||||
|
|
||||||
return gql`
|
return gql`
|
||||||
mutation DeleteOne${capitalizedObjectName}($idToDelete: ID!) {
|
mutation DeleteOne${capitalizedObjectName}($idToDelete: ID!) {
|
||||||
@ -1,14 +1,21 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
import { EMPTY_QUERY } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
|
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { mapFieldMetadataToGraphQLQuery } from '@/object-metadata/utils/mapFieldMetadataToGraphQLQuery';
|
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const generateFindManyCustomObjectsQuery = ({
|
export const useGenerateFindManyCustomObjectsQuery = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem | undefined | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
|
||||||
|
|
||||||
|
if (!objectMetadataItem) {
|
||||||
|
return EMPTY_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
return gql`
|
return gql`
|
||||||
query FindMany${capitalize(
|
query FindMany${capitalize(
|
||||||
objectMetadataItem.namePlural,
|
objectMetadataItem.namePlural,
|
||||||
@ -1,13 +1,20 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
import { EMPTY_QUERY } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
|
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { mapFieldMetadataToGraphQLQuery } from '@/object-metadata/utils/mapFieldMetadataToGraphQLQuery';
|
|
||||||
|
|
||||||
export const generateFindOneCustomObjectQuery = ({
|
export const useGenerateFindOneCustomObjectQuery = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem | null | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
|
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
|
||||||
|
|
||||||
|
if (!objectMetadataItem) {
|
||||||
|
return EMPTY_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
return gql`
|
return gql`
|
||||||
query FindOne${objectMetadataItem.nameSingular}($objectMetadataId: UUID!) {
|
query FindOne${objectMetadataItem.nameSingular}($objectMetadataId: UUID!) {
|
||||||
${objectMetadataItem.nameSingular}(filter: {
|
${objectMetadataItem.nameSingular}(filter: {
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
import { EMPTY_MUTATION } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
|
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { mapFieldMetadataToGraphQLQuery } from '@/object-metadata/utils/mapFieldMetadataToGraphQLQuery';
|
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const getUpdateOneObjectMutationGraphQLField = ({
|
export const getUpdateOneObjectMutationGraphQLField = ({
|
||||||
@ -12,11 +13,17 @@ export const getUpdateOneObjectMutationGraphQLField = ({
|
|||||||
return `update${capitalize(objectNameSingular)}`;
|
return `update${capitalize(objectNameSingular)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateUpdateOneObjectMutation = ({
|
export const useGenerateUpdateOneObjectMutation = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem | undefined | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
|
||||||
|
|
||||||
|
if (!objectMetadataItem) {
|
||||||
|
return EMPTY_MUTATION;
|
||||||
|
}
|
||||||
|
|
||||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
||||||
|
|
||||||
const graphQLFieldForUpdateOneObjectMutation =
|
const graphQLFieldForUpdateOneObjectMutation =
|
||||||
149
front/src/modules/search/hooks/useFilteredSearchEntityQueryV2.ts
Normal file
149
front/src/modules/search/hooks/useFilteredSearchEntityQueryV2.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import { QueryHookOptions, QueryResult } from '@apollo/client';
|
||||||
|
|
||||||
|
import { mapPaginatedObjectsToObjects } from '@/object-record/utils/mapPaginatedObjectsToObjects';
|
||||||
|
import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
|
||||||
|
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||||
|
import { QueryMode, SortOrder } from '~/generated/graphql';
|
||||||
|
|
||||||
|
type SelectStringKeys<T> = NonNullable<
|
||||||
|
{
|
||||||
|
[K in keyof T]: K extends '__typename'
|
||||||
|
? never
|
||||||
|
: T[K] extends string | undefined | null
|
||||||
|
? K
|
||||||
|
: never;
|
||||||
|
}[keyof T]
|
||||||
|
>;
|
||||||
|
|
||||||
|
type ExtractEntityTypeFromQueryResponse<T> = T extends {
|
||||||
|
searchResults: Array<infer U>;
|
||||||
|
}
|
||||||
|
? U
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type SearchFilter = { fieldNames: string[]; filter: string | number };
|
||||||
|
|
||||||
|
const DEFAULT_SEARCH_REQUEST_LIMIT = 10;
|
||||||
|
|
||||||
|
// TODO: use this for all search queries, because we need selectedEntities and entitiesToSelect each time we want to search
|
||||||
|
// Filtered entities to select are
|
||||||
|
export const useFilteredSearchEntityQueryV2 = ({
|
||||||
|
queryHook,
|
||||||
|
orderByField,
|
||||||
|
filters,
|
||||||
|
sortOrder = SortOrder.Asc,
|
||||||
|
selectedIds,
|
||||||
|
mappingFunction,
|
||||||
|
limit,
|
||||||
|
excludeEntityIds = [],
|
||||||
|
objectNamePlural,
|
||||||
|
}: {
|
||||||
|
queryHook: (
|
||||||
|
queryOptions?: QueryHookOptions<any, any>,
|
||||||
|
) => QueryResult<any, any>;
|
||||||
|
orderByField: string;
|
||||||
|
filters: SearchFilter[];
|
||||||
|
sortOrder?: SortOrder;
|
||||||
|
selectedIds: string[];
|
||||||
|
mappingFunction: (entity: any) => EntityForSelect;
|
||||||
|
limit?: number;
|
||||||
|
excludeEntityIds?: string[];
|
||||||
|
objectNamePlural: string;
|
||||||
|
}): EntitiesForMultipleEntitySelect<EntityForSelect> => {
|
||||||
|
const { loading: selectedEntitiesLoading, data: selectedEntitiesData } =
|
||||||
|
queryHook({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: selectedIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
[orderByField]: sortOrder,
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchFilter = filters.map(({ fieldNames, filter }) => {
|
||||||
|
return {
|
||||||
|
OR: fieldNames.map((fieldName) => ({
|
||||||
|
[fieldName]: {
|
||||||
|
startsWith: `%${filter}%`,
|
||||||
|
mode: QueryMode.Insensitive,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
loading: filteredSelectedEntitiesLoading,
|
||||||
|
data: filteredSelectedEntitiesData,
|
||||||
|
} = queryHook({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{
|
||||||
|
AND: searchFilter,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
in: selectedIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
[orderByField]: sortOrder,
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { loading: entitiesToSelectLoading, data: entitiesToSelectData } =
|
||||||
|
queryHook({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{
|
||||||
|
AND: searchFilter,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
notIn: [...selectedIds, ...excludeEntityIds],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
|
||||||
|
orderBy: {
|
||||||
|
[orderByField]: sortOrder,
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
selectedEntitiesData,
|
||||||
|
test: mapPaginatedObjectsToObjects({
|
||||||
|
objectNamePlural: objectNamePlural,
|
||||||
|
pagedObjects: selectedEntitiesData,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectedEntities: mapPaginatedObjectsToObjects({
|
||||||
|
objectNamePlural: objectNamePlural,
|
||||||
|
pagedObjects: selectedEntitiesData,
|
||||||
|
}).map(mappingFunction),
|
||||||
|
filteredSelectedEntities: mapPaginatedObjectsToObjects({
|
||||||
|
objectNamePlural: objectNamePlural,
|
||||||
|
pagedObjects: filteredSelectedEntitiesData,
|
||||||
|
}).map(mappingFunction),
|
||||||
|
entitiesToSelect: mapPaginatedObjectsToObjects({
|
||||||
|
objectNamePlural: objectNamePlural,
|
||||||
|
pagedObjects: entitiesToSelectData,
|
||||||
|
}).map(mappingFunction),
|
||||||
|
loading:
|
||||||
|
entitiesToSelectLoading ||
|
||||||
|
filteredSelectedEntitiesLoading ||
|
||||||
|
selectedEntitiesLoading,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -5,6 +5,7 @@ import debounce from 'lodash.debounce';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
||||||
import { useUpdateUserMutation } from '~/generated/graphql';
|
import { useUpdateUserMutation } from '~/generated/graphql';
|
||||||
@ -30,9 +31,14 @@ export const NameFields = ({
|
|||||||
onLastNameUpdate,
|
onLastNameUpdate,
|
||||||
}: NameFieldsProps) => {
|
}: NameFieldsProps) => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const [firstName, setFirstName] = useState(currentUser?.firstName ?? '');
|
const [firstName, setFirstName] = useState(
|
||||||
const [lastName, setLastName] = useState(currentUser?.lastName ?? '');
|
currentWorkspaceMember?.firstName ?? '',
|
||||||
|
);
|
||||||
|
const [lastName, setLastName] = useState(
|
||||||
|
currentWorkspaceMember?.lastName ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
const [updateUser] = useUpdateUserMutation();
|
const [updateUser] = useUpdateUserMutation();
|
||||||
|
|
||||||
@ -69,13 +75,13 @@ export const NameFields = ({
|
|||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentUser) {
|
if (!currentWorkspaceMember) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
currentUser.firstName !== firstName ||
|
currentWorkspaceMember.firstName !== firstName ||
|
||||||
currentUser.lastName !== lastName
|
currentWorkspaceMember.lastName !== lastName
|
||||||
) {
|
) {
|
||||||
debouncedUpdate();
|
debouncedUpdate();
|
||||||
}
|
}
|
||||||
@ -83,7 +89,14 @@ export const NameFields = ({
|
|||||||
return () => {
|
return () => {
|
||||||
debouncedUpdate.cancel();
|
debouncedUpdate.cancel();
|
||||||
};
|
};
|
||||||
}, [firstName, lastName, currentUser, debouncedUpdate, autoSave]);
|
}, [
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
currentUser,
|
||||||
|
debouncedUpdate,
|
||||||
|
autoSave,
|
||||||
|
currentWorkspaceMember,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledComboInputContainer>
|
<StyledComboInputContainer>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { ImageInput } from '@/ui/input/components/ImageInput';
|
import { ImageInput } from '@/ui/input/components/ImageInput';
|
||||||
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
||||||
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
||||||
@ -16,6 +17,8 @@ export const ProfilePictureUploader = () => {
|
|||||||
useUploadProfilePictureMutation();
|
useUploadProfilePictureMutation();
|
||||||
const [removePicture] = useRemoveProfilePictureMutation();
|
const [removePicture] = useRemoveProfilePictureMutation();
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const [currentUser] = useRecoilState(currentUserState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const [uploadController, setUploadController] =
|
const [uploadController, setUploadController] =
|
||||||
useState<AbortController | null>(null);
|
useState<AbortController | null>(null);
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
@ -69,7 +72,7 @@ export const ProfilePictureUploader = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ImageInput
|
<ImageInput
|
||||||
picture={getImageAbsoluteURIOrBase64(currentUser?.avatarUrl)}
|
picture={getImageAbsoluteURIOrBase64(currentWorkspaceMember?.avatarUrl)}
|
||||||
onUpload={handleUpload}
|
onUpload={handleUpload}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
onAbort={handleAbort}
|
onAbort={handleAbort}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
||||||
import { Toggle } from '@/ui/input/components/Toggle';
|
import { Toggle } from '@/ui/input/components/Toggle';
|
||||||
import { useUpdateAllowImpersonationMutation } from '~/generated/graphql';
|
import { useUpdateAllowImpersonationMutation } from '~/generated/graphql';
|
||||||
@ -8,7 +8,7 @@ import { useUpdateAllowImpersonationMutation } from '~/generated/graphql';
|
|||||||
export const ToggleField = () => {
|
export const ToggleField = () => {
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const [updateAllowImpersonation] = useUpdateAllowImpersonationMutation();
|
const [updateAllowImpersonation] = useUpdateAllowImpersonationMutation();
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ export const ToggleField = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Toggle
|
<Toggle
|
||||||
value={currentUser?.workspaceMember?.allowImpersonation}
|
value={currentWorkspaceMember?.allowImpersonation}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { useCallback, useEffect, useState } from 'react';
|
|||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import debounce from 'lodash.debounce';
|
import debounce from 'lodash.debounce';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
||||||
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
||||||
@ -27,10 +27,11 @@ export const NameField = ({
|
|||||||
autoSave = true,
|
autoSave = true,
|
||||||
onNameUpdate,
|
onNameUpdate,
|
||||||
}: NameFieldProps) => {
|
}: NameFieldProps) => {
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
const workspace = currentUser?.workspaceMember?.workspace;
|
|
||||||
|
|
||||||
const [displayName, setDisplayName] = useState(workspace?.displayName ?? '');
|
const [displayName, setDisplayName] = useState(
|
||||||
|
currentWorkspace?.displayName ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
const [updateWorkspace] = useUpdateWorkspaceMutation();
|
const [updateWorkspace] = useUpdateWorkspaceMutation();
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { ImageInput } from '@/ui/input/components/ImageInput';
|
import { ImageInput } from '@/ui/input/components/ImageInput';
|
||||||
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
||||||
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
||||||
@ -13,7 +13,8 @@ import {
|
|||||||
export const WorkspaceLogoUploader = () => {
|
export const WorkspaceLogoUploader = () => {
|
||||||
const [uploadLogo] = useUploadWorkspaceLogoMutation();
|
const [uploadLogo] = useUploadWorkspaceLogoMutation();
|
||||||
const [removeLogo] = useRemoveWorkspaceLogoMutation();
|
const [removeLogo] = useRemoveWorkspaceLogoMutation();
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
|
|
||||||
const onUpload = async (file: File) => {
|
const onUpload = async (file: File) => {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return;
|
return;
|
||||||
@ -34,9 +35,7 @@ export const WorkspaceLogoUploader = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ImageInput
|
<ImageInput
|
||||||
picture={getImageAbsoluteURIOrBase64(
|
picture={getImageAbsoluteURIOrBase64(currentWorkspace?.logo)}
|
||||||
currentUser?.workspaceMember?.workspace.logo,
|
|
||||||
)}
|
|
||||||
onUpload={onUpload}
|
onUpload={onUpload}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { Avatar, AvatarType } from '@/users/components/Avatar';
|
|||||||
|
|
||||||
import { Chip, ChipVariant } from './Chip';
|
import { Chip, ChipVariant } from './Chip';
|
||||||
|
|
||||||
type EntityChipProps = {
|
export type EntityChipProps = {
|
||||||
linkToEntity?: string;
|
linkToEntity?: string;
|
||||||
entityId: string;
|
entityId: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -62,9 +62,13 @@ export const SingleEntitySelectBase = <
|
|||||||
|
|
||||||
const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter(
|
const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter(
|
||||||
(entity): entity is CustomEntityForSelect =>
|
(entity): entity is CustomEntityForSelect =>
|
||||||
assertNotNull(entity) && isNonEmptyString(entity.name.trim()),
|
assertNotNull(entity) && isNonEmptyString(entity.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
entitiesInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
const { preselectedOptionId, resetScroll } = useEntitySelectScroll({
|
const { preselectedOptionId, resetScroll } = useEntitySelectScroll({
|
||||||
selectableOptionIds: [
|
selectableOptionIds: [
|
||||||
EmptyButtonId,
|
EmptyButtonId,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export enum Entity {
|
|||||||
Company = 'Company',
|
Company = 'Company',
|
||||||
Person = 'Person',
|
Person = 'Person',
|
||||||
User = 'User',
|
User = 'User',
|
||||||
|
WorkspaceMember = 'WorkspaceMember',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EntityTypeForSelect =
|
export type EntityTypeForSelect =
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import styled from '@emotion/styled';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
|
||||||
|
|
||||||
import NavCollapseButton from './NavCollapseButton';
|
import NavCollapseButton from './NavCollapseButton';
|
||||||
@ -53,8 +54,8 @@ const NavWorkspaceButton = ({
|
|||||||
showCollapseButton,
|
showCollapseButton,
|
||||||
}: NavWorkspaceButtonProps) => {
|
}: NavWorkspaceButtonProps) => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
|
|
||||||
const currentWorkspace = currentUser?.workspaceMember?.workspace;
|
|
||||||
const DEFAULT_LOGO =
|
const DEFAULT_LOGO =
|
||||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=';
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=';
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,10 @@ import styled from '@emotion/styled';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import {
|
||||||
|
CurrentWorkspaceMember,
|
||||||
|
currentWorkspaceMemberState,
|
||||||
|
} from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||||
import { IconHelpCircle } from '@/ui/display/icon';
|
import { IconHelpCircle } from '@/ui/display/icon';
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
@ -30,13 +34,18 @@ const insertScript = ({
|
|||||||
|
|
||||||
const SupportChat = () => {
|
const SupportChat = () => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const supportChat = useRecoilValue(supportChatState);
|
const supportChat = useRecoilValue(supportChatState);
|
||||||
const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false);
|
const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false);
|
||||||
|
|
||||||
const configureFront = useCallback(
|
const configureFront = useCallback(
|
||||||
(
|
(
|
||||||
chatId: string,
|
chatId: string,
|
||||||
currentUser: Pick<User, 'email' | 'displayName' | 'supportUserHash'>,
|
currentUser: Pick<User, 'email' | 'supportUserHash'>,
|
||||||
|
currentWorkspaceMember: Pick<
|
||||||
|
CurrentWorkspaceMember,
|
||||||
|
'firstName' | 'lastName'
|
||||||
|
>,
|
||||||
) => {
|
) => {
|
||||||
const url = 'https://chat-assets.frontapp.com/v1/chat.bundle.js';
|
const url = 'https://chat-assets.frontapp.com/v1/chat.bundle.js';
|
||||||
const script = document.querySelector(`script[src="${url}"]`);
|
const script = document.querySelector(`script[src="${url}"]`);
|
||||||
@ -49,7 +58,10 @@ const SupportChat = () => {
|
|||||||
chatId,
|
chatId,
|
||||||
useDefaultLauncher: false,
|
useDefaultLauncher: false,
|
||||||
email: currentUser.email,
|
email: currentUser.email,
|
||||||
name: currentUser.displayName,
|
name:
|
||||||
|
currentWorkspaceMember.firstName +
|
||||||
|
' ' +
|
||||||
|
currentWorkspaceMember.lastName,
|
||||||
userHash: currentUser?.supportUserHash,
|
userHash: currentUser?.supportUserHash,
|
||||||
});
|
});
|
||||||
setIsFrontChatLoaded(true);
|
setIsFrontChatLoaded(true);
|
||||||
@ -65,9 +77,14 @@ const SupportChat = () => {
|
|||||||
supportChat?.supportDriver === 'front' &&
|
supportChat?.supportDriver === 'front' &&
|
||||||
supportChat.supportFrontChatId &&
|
supportChat.supportFrontChatId &&
|
||||||
currentUser?.email &&
|
currentUser?.email &&
|
||||||
|
currentWorkspaceMember &&
|
||||||
!isFrontChatLoaded
|
!isFrontChatLoaded
|
||||||
) {
|
) {
|
||||||
configureFront(supportChat.supportFrontChatId, currentUser);
|
configureFront(
|
||||||
|
supportChat.supportFrontChatId,
|
||||||
|
currentUser,
|
||||||
|
currentWorkspaceMember,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
configureFront,
|
configureFront,
|
||||||
@ -75,6 +92,7 @@ const SupportChat = () => {
|
|||||||
isFrontChatLoaded,
|
isFrontChatLoaded,
|
||||||
supportChat?.supportDriver,
|
supportChat?.supportDriver,
|
||||||
supportChat.supportFrontChatId,
|
supportChat.supportFrontChatId,
|
||||||
|
currentWorkspaceMember,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return isFrontChatLoaded ? (
|
return isFrontChatLoaded ? (
|
||||||
|
|||||||
@ -105,13 +105,16 @@ export const usePersistField = () => {
|
|||||||
valueToPersist,
|
valueToPersist,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
fieldName,
|
||||||
|
valueToPersist,
|
||||||
|
});
|
||||||
|
|
||||||
updateEntity?.({
|
updateEntity?.({
|
||||||
variables: {
|
variables: {
|
||||||
where: { id: entityId },
|
where: { id: entityId },
|
||||||
data: {
|
data: {
|
||||||
[fieldName]: valueToPersist
|
[fieldName]: valueToPersist?.id,
|
||||||
? { connect: { id: valueToPersist.id } }
|
|
||||||
: { disconnect: true },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,24 +1,27 @@
|
|||||||
import { EntityChip } from '@/ui/display/chip/components/EntityChip';
|
import { EntityChip } from '@/ui/display/chip/components/EntityChip';
|
||||||
|
import { getEntityChipFromFieldMetadata } from '@/ui/object/field/meta-types/display/utils/getEntityChipFromFieldMetadata';
|
||||||
|
|
||||||
import { useRelationField } from '../../hooks/useRelationField';
|
import { useRelationField } from '../../hooks/useRelationField';
|
||||||
|
|
||||||
export const RelationFieldDisplay = () => {
|
export const RelationFieldDisplay = () => {
|
||||||
const { fieldValue, fieldDefinition } = useRelationField();
|
const { fieldValue, fieldDefinition } = useRelationField();
|
||||||
const { entityChipDisplayMapper } = fieldDefinition;
|
|
||||||
if (!entityChipDisplayMapper) {
|
console.log({
|
||||||
throw new Error(
|
fieldDefinition,
|
||||||
"Missing entityChipDisplayMapper in FieldContext. Please provide it in the FieldContextProvider's value prop.",
|
fieldValue,
|
||||||
);
|
});
|
||||||
}
|
|
||||||
const { name, pictureUrl, avatarType } =
|
const entityChipProps = getEntityChipFromFieldMetadata(
|
||||||
entityChipDisplayMapper?.(fieldValue);
|
fieldDefinition,
|
||||||
|
fieldValue,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EntityChip
|
<EntityChip
|
||||||
entityId={fieldValue?.id}
|
entityId={entityChipProps.entityId}
|
||||||
name={name}
|
name={entityChipProps.name}
|
||||||
pictureUrl={pictureUrl}
|
pictureUrl={entityChipProps.pictureUrl}
|
||||||
avatarType={avatarType}
|
avatarType={entityChipProps.avatarType}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
import { EntityChipProps } from '@/ui/display/chip/components/EntityChip';
|
||||||
|
import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition';
|
||||||
|
import { FieldRelationMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||||
|
|
||||||
|
export const getEntityChipFromFieldMetadata = (
|
||||||
|
fieldDefinition: FieldDefinition<FieldRelationMetadata>,
|
||||||
|
fieldValue: any,
|
||||||
|
) => {
|
||||||
|
const { fieldName } = fieldDefinition.metadata;
|
||||||
|
|
||||||
|
const chipValue: Pick<
|
||||||
|
EntityChipProps,
|
||||||
|
'name' | 'pictureUrl' | 'avatarType' | 'entityId'
|
||||||
|
> = {
|
||||||
|
name: '',
|
||||||
|
pictureUrl: '',
|
||||||
|
avatarType: 'rounded',
|
||||||
|
entityId: fieldValue?.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
fieldName,
|
||||||
|
fieldValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: use every
|
||||||
|
if (fieldName === 'accountOwner' && fieldValue) {
|
||||||
|
chipValue.name = fieldValue.firstName + ' ' + fieldValue.lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chipValue;
|
||||||
|
};
|
||||||
@ -22,6 +22,11 @@ export const useRelationField = () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
fieldDefinition,
|
||||||
|
fieldValue,
|
||||||
|
});
|
||||||
|
|
||||||
const fieldInitialValue = useFieldInitialValue();
|
const fieldInitialValue = useFieldInitialValue();
|
||||||
|
|
||||||
const initialSearchValue = fieldInitialValue?.isEmpty
|
const initialSearchValue = fieldInitialValue?.isEmpty
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export const RelationFieldInput = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledRelationPickerContainer>
|
<StyledRelationPickerContainer>
|
||||||
{fieldDefinition.metadata.relationType === Entity.Person ? (
|
{fieldDefinition.metadata.fieldName === 'person' ? (
|
||||||
<PeoplePicker
|
<PeoplePicker
|
||||||
personId={initialValue?.id ?? ''}
|
personId={initialValue?.id ?? ''}
|
||||||
companyId={initialValue?.companyId ?? ''}
|
companyId={initialValue?.companyId ?? ''}
|
||||||
@ -48,7 +48,7 @@ export const RelationFieldInput = ({
|
|||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
initialSearchFilter={initialSearchValue}
|
initialSearchFilter={initialSearchValue}
|
||||||
/>
|
/>
|
||||||
) : fieldDefinition.metadata.relationType === Entity.User ? (
|
) : fieldDefinition.metadata.fieldName === 'accountOwner' ? (
|
||||||
<UserPicker
|
<UserPicker
|
||||||
userId={initialValue?.id ?? ''}
|
userId={initialValue?.id ?? ''}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
|||||||
@ -82,6 +82,8 @@ type RecordTableProps = {
|
|||||||
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
||||||
const tableBodyRef = useRef<HTMLDivElement>(null);
|
const tableBodyRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
console.log('record table');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
leaveTableFocus,
|
leaveTableFocus,
|
||||||
setRowSelectedState,
|
setRowSelectedState,
|
||||||
|
|||||||
@ -1,105 +1,32 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import {
|
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
|
||||||
ColorScheme,
|
import { ColorScheme } from '~/generated/graphql';
|
||||||
useUpdateOneWorkspaceMemberMutation,
|
|
||||||
useUpdateUserMutation,
|
|
||||||
} from '~/generated/graphql';
|
|
||||||
|
|
||||||
export const useColorScheme = () => {
|
export const useColorScheme = () => {
|
||||||
const [currentUser, setCurrentUser] = useRecoilState(currentUserState);
|
const [currentWorkspaceMember] = useRecoilState(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const [updateUser] = useUpdateUserMutation();
|
const { updateOneObject: updateOneWorkspaceMember } =
|
||||||
const [updateWorkspaceMember] = useUpdateOneWorkspaceMemberMutation();
|
useUpdateOneObjectRecord({
|
||||||
|
objectNamePlural: 'workspaceMembersV2',
|
||||||
const colorScheme =
|
});
|
||||||
!currentUser?.workspaceMember.settings?.colorScheme &&
|
const colorScheme = currentWorkspaceMember?.colorScheme ?? ColorScheme.System;
|
||||||
!currentUser?.settings?.colorScheme
|
|
||||||
? ColorScheme.System
|
|
||||||
: currentUser.workspaceMember.settings?.colorScheme ??
|
|
||||||
currentUser.settings.colorScheme;
|
|
||||||
|
|
||||||
const setColorScheme = useCallback(
|
const setColorScheme = useCallback(
|
||||||
async (value: ColorScheme) => {
|
async (value: ColorScheme) => {
|
||||||
try {
|
if (!currentWorkspaceMember) {
|
||||||
// connect settings to workspace member if not already connected
|
return;
|
||||||
await updateWorkspaceMember({
|
}
|
||||||
variables: {
|
await updateOneWorkspaceMember?.({
|
||||||
where: { id: currentUser?.workspaceMember.id },
|
idToUpdate: currentWorkspaceMember?.id,
|
||||||
data: { settings: { connect: { id: currentUser?.settings.id } } },
|
input: {
|
||||||
},
|
colorScheme: value,
|
||||||
});
|
},
|
||||||
|
});
|
||||||
const result = await updateUser({
|
|
||||||
variables: {
|
|
||||||
where: {
|
|
||||||
id: currentUser?.id,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
settings: {
|
|
||||||
update: {
|
|
||||||
colorScheme: value,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optimisticResponse: currentUser
|
|
||||||
? {
|
|
||||||
__typename: 'Mutation',
|
|
||||||
updateUser: {
|
|
||||||
__typename: 'User',
|
|
||||||
...currentUser,
|
|
||||||
workspaceMember: {
|
|
||||||
...currentUser.workspaceMember,
|
|
||||||
settings: {
|
|
||||||
__typename: 'UserSettings',
|
|
||||||
id: currentUser.settings.id,
|
|
||||||
colorScheme: value,
|
|
||||||
locale: currentUser.settings.locale,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
__typename: 'UserSettings',
|
|
||||||
id: currentUser.settings.id,
|
|
||||||
colorScheme: value,
|
|
||||||
locale: currentUser.settings.locale,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
update: (_cache, { data }) => {
|
|
||||||
if (
|
|
||||||
data?.updateUser.workspaceMember?.settings?.colorScheme &&
|
|
||||||
currentUser
|
|
||||||
) {
|
|
||||||
setCurrentUser({
|
|
||||||
...currentUser,
|
|
||||||
workspaceMember: {
|
|
||||||
...currentUser.workspaceMember,
|
|
||||||
settings: {
|
|
||||||
...currentUser.workspaceMember.settings,
|
|
||||||
colorScheme:
|
|
||||||
data.updateUser.workspaceMember.settings.colorScheme,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
...currentUser.settings,
|
|
||||||
colorScheme:
|
|
||||||
data.updateUser.workspaceMember.settings.colorScheme,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.data || result.errors) {
|
|
||||||
throw result.errors;
|
|
||||||
}
|
|
||||||
} catch (err) {}
|
|
||||||
},
|
},
|
||||||
[updateWorkspaceMember, currentUser, updateUser, setCurrentUser],
|
[currentWorkspaceMember, updateOneWorkspaceMember],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
|
import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2';
|
||||||
import { IconUserCircle } from '@/ui/display/icon';
|
import { IconUserCircle } from '@/ui/display/icon';
|
||||||
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
|
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
|
||||||
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useSearchUserQuery } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export type UserPickerProps = {
|
export type UserPickerProps = {
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -18,7 +19,7 @@ export type UserPickerProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type UserForSelect = EntityForSelect & {
|
type UserForSelect = EntityForSelect & {
|
||||||
entityType: Entity.User;
|
entityType: Entity.WorkspaceMember;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UserPicker = ({
|
export const UserPicker = ({
|
||||||
@ -35,29 +36,39 @@ export const UserPicker = ({
|
|||||||
setRelationPickerSearchFilter(initialSearchFilter ?? '');
|
setRelationPickerSearchFilter(initialSearchFilter ?? '');
|
||||||
}, [initialSearchFilter, setRelationPickerSearchFilter]);
|
}, [initialSearchFilter, setRelationPickerSearchFilter]);
|
||||||
|
|
||||||
const users = useFilteredSearchEntityQuery({
|
const { findManyQuery } = useFindOneObjectMetadataItem({
|
||||||
queryHook: useSearchUserQuery,
|
objectNamePlural: 'workspaceMembersV2',
|
||||||
|
});
|
||||||
|
|
||||||
|
const useFindManyWorkspaceMembers = () => useQuery(findManyQuery, {});
|
||||||
|
|
||||||
|
// TODO: put workspace member
|
||||||
|
const users = useFilteredSearchEntityQueryV2({
|
||||||
|
queryHook: useFindManyWorkspaceMembers,
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
fieldNames: ['firstName', 'lastName'],
|
fieldNames: ['firstName', 'lastName'],
|
||||||
filter: relationPickerSearchFilter,
|
filter: relationPickerSearchFilter,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
orderByField: 'firstName',
|
orderByField: '',
|
||||||
mappingFunction: (user) => ({
|
mappingFunction: (workspaceMember) => ({
|
||||||
entityType: Entity.User,
|
entityType: Entity.WorkspaceMember,
|
||||||
id: user.id,
|
id: workspaceMember.id,
|
||||||
name: user.displayName,
|
name: workspaceMember.firstName,
|
||||||
avatarType: 'rounded',
|
avatarType: 'rounded',
|
||||||
avatarUrl: user.avatarUrl ?? '',
|
avatarUrl: '',
|
||||||
originalEntity: user,
|
originalEntity: workspaceMember,
|
||||||
}),
|
}),
|
||||||
selectedIds: userId ? [userId] : [],
|
selectedIds: userId ? [userId] : [],
|
||||||
|
objectNamePlural: 'workspaceMembersV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleEntitySelected = async (
|
console.log({
|
||||||
selectedUser: UserForSelect | null | undefined,
|
users,
|
||||||
) => {
|
});
|
||||||
|
|
||||||
|
const handleEntitySelected = async (selectedUser: any | null | undefined) => {
|
||||||
onSubmit(selectedUser ?? null);
|
onSubmit(selectedUser ?? null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +1,71 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
import { useGetCurrentUserQuery } from '~/generated/graphql';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
|
import { FIND_ONE_WORKSPACE_MEMBER_V2 } from '@/object-record/graphql/queries/findOneWorkspaceMember';
|
||||||
|
import {
|
||||||
|
useGetCurrentUserQuery,
|
||||||
|
useGetCurrentWorkspaceQuery,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
export const UserProvider = ({ children }: React.PropsWithChildren) => {
|
export const UserProvider = ({ children }: React.PropsWithChildren) => {
|
||||||
const [, setCurrentUser] = useRecoilState(currentUserState);
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [isWorkspaceMemberLoading, setIsWorkspaceMemberLoading] =
|
||||||
|
useState(true);
|
||||||
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const { data, loading } = useGetCurrentUserQuery();
|
const setCurrentUser = useSetRecoilState(currentUserState);
|
||||||
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||||
|
const setCurrentWorkspaceMember = useSetRecoilState(
|
||||||
|
currentWorkspaceMemberState,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: userData, loading: userLoading } = useGetCurrentUserQuery({
|
||||||
if (!loading) {
|
onCompleted: async (data) => {
|
||||||
setIsLoading(false);
|
const workspaceMember = await apolloClient.query({
|
||||||
}
|
query: FIND_ONE_WORKSPACE_MEMBER_V2,
|
||||||
if (data?.currentUser?.workspaceMember?.settings) {
|
variables: {
|
||||||
setCurrentUser({
|
filter: {
|
||||||
...data.currentUser,
|
userId: { eq: data.currentUser.id },
|
||||||
workspaceMember: {
|
},
|
||||||
...data.currentUser.workspaceMember,
|
|
||||||
settings: data.currentUser.workspaceMember.settings,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
setCurrentWorkspaceMember(
|
||||||
|
workspaceMember.data.workspaceMembersV2.edges[0].node,
|
||||||
|
);
|
||||||
|
setIsWorkspaceMemberLoading(false);
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
setIsWorkspaceMemberLoading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: workspaceData, loading: workspaceLoading } =
|
||||||
|
useGetCurrentWorkspaceQuery();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!userLoading && !workspaceLoading && !isWorkspaceMemberLoading) {
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [setCurrentUser, data, isLoading, loading]);
|
if (userData?.currentUser) {
|
||||||
|
setCurrentUser(userData.currentUser);
|
||||||
|
}
|
||||||
|
if (workspaceData?.currentWorkspace) {
|
||||||
|
setCurrentWorkspace(workspaceData.currentWorkspace);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
setCurrentUser,
|
||||||
|
isLoading,
|
||||||
|
userLoading,
|
||||||
|
workspaceLoading,
|
||||||
|
userData?.currentUser,
|
||||||
|
workspaceData?.currentWorkspace,
|
||||||
|
setCurrentWorkspace,
|
||||||
|
isWorkspaceMemberLoading,
|
||||||
|
]);
|
||||||
|
|
||||||
return isLoading ? <></> : <>{children}</>;
|
return isLoading ? <></> : <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,52 +5,6 @@ export const UPDATE_USER = gql`
|
|||||||
updateUser(data: $data, where: $where) {
|
updateUser(data: $data, where: $where) {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
displayName
|
|
||||||
firstName
|
|
||||||
lastName
|
|
||||||
avatarUrl
|
|
||||||
workspaceMember {
|
|
||||||
id
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
locale
|
|
||||||
colorScheme
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -4,16 +4,7 @@ export const GET_CURRENT_USER = gql`
|
|||||||
query GetCurrentUser {
|
query GetCurrentUser {
|
||||||
currentUser {
|
currentUser {
|
||||||
...userFieldsFragment
|
...userFieldsFragment
|
||||||
avatarUrl
|
|
||||||
canImpersonate
|
canImpersonate
|
||||||
workspaceMember {
|
|
||||||
...workspaceMemberFieldsFragment
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
locale
|
|
||||||
colorScheme
|
|
||||||
}
|
|
||||||
supportUserHash
|
supportUserHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
export type WorkspaceMember = {
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
};
|
||||||
@ -2,7 +2,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { OverflowingTextWithTooltip } from '@/ui/display/tooltip/OverflowingTextWithTooltip';
|
import { OverflowingTextWithTooltip } from '@/ui/display/tooltip/OverflowingTextWithTooltip';
|
||||||
import { Avatar } from '@/users/components/Avatar';
|
import { Avatar } from '@/users/components/Avatar';
|
||||||
import { User } from '~/generated/graphql';
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
background: ${({ theme }) => theme.background.secondary};
|
background: ${({ theme }) => theme.background.secondary};
|
||||||
@ -29,12 +29,7 @@ const StyledEmailText = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
type WorkspaceMemberCardProps = {
|
type WorkspaceMemberCardProps = {
|
||||||
workspaceMember: {
|
workspaceMember: WorkspaceMember;
|
||||||
user: Pick<
|
|
||||||
User,
|
|
||||||
'id' | 'firstName' | 'lastName' | 'displayName' | 'avatarUrl' | 'email'
|
|
||||||
>;
|
|
||||||
};
|
|
||||||
accessory?: React.ReactNode;
|
accessory?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,15 +39,19 @@ export const WorkspaceMemberCard = ({
|
|||||||
}: WorkspaceMemberCardProps) => (
|
}: WorkspaceMemberCardProps) => (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarUrl={workspaceMember.user.avatarUrl}
|
avatarUrl={workspaceMember.avatarUrl}
|
||||||
colorId={workspaceMember.user.id}
|
colorId={workspaceMember.id}
|
||||||
placeholder={workspaceMember.user.firstName || ''}
|
placeholder={workspaceMember.firstName || ''}
|
||||||
type="squared"
|
type="squared"
|
||||||
size="xl"
|
size="xl"
|
||||||
/>
|
/>
|
||||||
<StyledContent>
|
<StyledContent>
|
||||||
<OverflowingTextWithTooltip text={workspaceMember.user.displayName} />
|
<OverflowingTextWithTooltip
|
||||||
<StyledEmailText>{workspaceMember.user.email}</StyledEmailText>
|
text={workspaceMember.firstName + ' ' + workspaceMember.lastName}
|
||||||
|
/>
|
||||||
|
<StyledEmailText>
|
||||||
|
{workspaceMember.firstName + ' ' + workspaceMember.lastName}
|
||||||
|
</StyledEmailText>
|
||||||
</StyledContent>
|
</StyledContent>
|
||||||
|
|
||||||
{accessory}
|
{accessory}
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
|
|
||||||
export const WORKSPACE_MEMBER_FIELDS_FRAGMENT = gql`
|
|
||||||
fragment workspaceMemberFieldsFragment on WorkspaceMember {
|
|
||||||
id
|
|
||||||
allowImpersonation
|
|
||||||
workspace {
|
|
||||||
id
|
|
||||||
domainName
|
|
||||||
displayName
|
|
||||||
logo
|
|
||||||
inviteHash
|
|
||||||
}
|
|
||||||
assignedActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredActivities {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
authoredAttachments {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
type
|
|
||||||
}
|
|
||||||
settings {
|
|
||||||
id
|
|
||||||
colorScheme
|
|
||||||
locale
|
|
||||||
}
|
|
||||||
companies {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
domainName
|
|
||||||
}
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
|
|
||||||
export const REMOVE_WORKSPACE_MEMBER = gql`
|
|
||||||
mutation RemoveWorkspaceMember($where: WorkspaceMemberWhereUniqueInput!) {
|
|
||||||
deleteWorkspaceMember(where: $where) {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
|
|
||||||
export const UPDATE_WORKSPACE_MEMBER = gql`
|
|
||||||
mutation UpdateOneWorkspaceMember(
|
|
||||||
$data: WorkspaceMemberUpdateInput!
|
|
||||||
$where: WorkspaceMemberWhereUniqueInput!
|
|
||||||
) {
|
|
||||||
UpdateOneWorkspaceMember(data: $data, where: $where) {
|
|
||||||
...workspaceMemberFieldsFragment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const GET_CURRENT_WORKSPACE = gql`
|
||||||
|
query getCurrentWorkspace {
|
||||||
|
currentWorkspace {
|
||||||
|
id
|
||||||
|
displayName
|
||||||
|
logo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -4,10 +4,6 @@ export const GET_WORKSPACE_MEMBERS = gql`
|
|||||||
query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) {
|
query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) {
|
||||||
workspaceMembers: findManyWorkspaceMember(where: $where) {
|
workspaceMembers: findManyWorkspaceMember(where: $where) {
|
||||||
id
|
id
|
||||||
user {
|
|
||||||
...userFieldsFragment
|
|
||||||
avatarUrl
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { z } from 'zod';
|
|||||||
import { SubTitle } from '@/auth/components/SubTitle';
|
import { SubTitle } from '@/auth/components/SubTitle';
|
||||||
import { Title } from '@/auth/components/Title';
|
import { Title } from '@/auth/components/Title';
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
|
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
|
||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
@ -57,6 +58,7 @@ export const CreateProfile = () => {
|
|||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const [currentUser] = useRecoilState(currentUserState);
|
||||||
|
const [currentWorkspaceMember] = useRecoilState(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const [updateUser] = useUpdateUserMutation();
|
const [updateUser] = useUpdateUserMutation();
|
||||||
|
|
||||||
@ -69,8 +71,8 @@ export const CreateProfile = () => {
|
|||||||
} = useForm<Form>({
|
} = useForm<Form>({
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
firstName: currentUser?.firstName ?? '',
|
firstName: currentWorkspaceMember?.firstName ?? '',
|
||||||
lastName: currentUser?.lastName ?? '',
|
lastName: currentWorkspaceMember?.lastName ?? '',
|
||||||
},
|
},
|
||||||
resolver: zodResolver(validationSchema),
|
resolver: zodResolver(validationSchema),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useAuth } from '@/auth/hooks/useAuth';
|
import { useAuth } from '@/auth/hooks/useAuth';
|
||||||
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
||||||
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
|
|
||||||
import { AppPath } from '../../modules/types/AppPath';
|
import { AppPath } from '../../modules/types/AppPath';
|
||||||
|
|
||||||
export const VerifyEffect = () => {
|
export const VerifyEffect = () => {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const loginToken = searchParams.get('loginToken');
|
const loginToken = searchParams.get('loginToken');
|
||||||
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
|
|
||||||
const isLogged = useIsLogged();
|
const isLogged = useIsLogged();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -21,13 +24,9 @@ export const VerifyEffect = () => {
|
|||||||
if (!loginToken) {
|
if (!loginToken) {
|
||||||
navigate(AppPath.SignIn);
|
navigate(AppPath.SignIn);
|
||||||
} else {
|
} else {
|
||||||
const verifyResponse = await verify(loginToken);
|
await verify(loginToken);
|
||||||
|
|
||||||
if (
|
if (isNonEmptyString(currentWorkspace?.displayName)) {
|
||||||
isNonEmptyString(
|
|
||||||
verifyResponse.user.workspaceMember?.workspace.displayName,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
navigate(AppPath.Index);
|
navigate(AppPath.Index);
|
||||||
} else {
|
} else {
|
||||||
navigate(AppPath.CreateWorkspace);
|
navigate(AppPath.CreateWorkspace);
|
||||||
|
|||||||
@ -38,21 +38,9 @@ export const ImpersonateEffect = () => {
|
|||||||
throw new Error('No impersonate result');
|
throw new Error('No impersonate result');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!impersonateResult.data?.impersonate.user.workspaceMember) {
|
|
||||||
throw new Error('No workspace member');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!impersonateResult.data?.impersonate.user.workspaceMember.settings) {
|
|
||||||
throw new Error('No workspace member settings');
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentUser({
|
setCurrentUser({
|
||||||
...impersonateResult.data.impersonate.user,
|
...impersonateResult.data.impersonate.user,
|
||||||
workspaceMember: {
|
// Todo also set WorkspaceMember
|
||||||
...impersonateResult.data.impersonate.user.workspaceMember,
|
|
||||||
settings:
|
|
||||||
impersonateResult.data.impersonate.user.workspaceMember.settings,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
setTokenPair(impersonateResult.data?.impersonate.tokens);
|
setTokenPair(impersonateResult.data?.impersonate.tokens);
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
|
import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord';
|
||||||
|
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { IconSettings, IconTrash } from '@/ui/display/icon';
|
import { IconSettings, IconTrash } from '@/ui/display/icon';
|
||||||
import { H1Title } from '@/ui/display/typography/components/H1Title';
|
import { H1Title } from '@/ui/display/typography/components/H1Title';
|
||||||
@ -13,10 +15,7 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
|
|||||||
import { Section } from '@/ui/layout/section/components/Section';
|
import { Section } from '@/ui/layout/section/components/Section';
|
||||||
import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink';
|
import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink';
|
||||||
import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard';
|
import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard';
|
||||||
import {
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
useGetWorkspaceMembersQuery,
|
|
||||||
useRemoveWorkspaceMemberMutation,
|
|
||||||
} from '~/generated/graphql';
|
|
||||||
|
|
||||||
const StyledH1Title = styled(H1Title)`
|
const StyledH1Title = styled(H1Title)`
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -31,51 +30,22 @@ const StyledButtonContainer = styled.div`
|
|||||||
|
|
||||||
export const SettingsWorkspaceMembers = () => {
|
export const SettingsWorkspaceMembers = () => {
|
||||||
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
|
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
|
||||||
const [userToDelete, setUserToDelete] = useState<string | undefined>();
|
const [workspaceMemberToDelete, setWorkspaceMemberToDelete] = useState<
|
||||||
|
string | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const { objects: workspaceMembers } =
|
||||||
const workspace = currentUser?.workspaceMember?.workspace;
|
useFindManyObjectRecords<WorkspaceMember>({
|
||||||
|
objectNamePlural: 'workspaceMembersV2',
|
||||||
const { data } = useGetWorkspaceMembersQuery();
|
|
||||||
|
|
||||||
const [removeWorkspaceMember] = useRemoveWorkspaceMemberMutation();
|
|
||||||
|
|
||||||
const handleRemoveWorkspaceMember = async (userId: string) => {
|
|
||||||
await removeWorkspaceMember({
|
|
||||||
variables: {
|
|
||||||
where: {
|
|
||||||
userId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optimisticResponse: {
|
|
||||||
__typename: 'Mutation',
|
|
||||||
deleteWorkspaceMember: {
|
|
||||||
__typename: 'WorkspaceMember',
|
|
||||||
id: userId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: (cache, { data: responseData }) => {
|
|
||||||
if (!responseData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.evict({
|
|
||||||
id: cache.identify({
|
|
||||||
id: responseData.deleteWorkspaceMember.id,
|
|
||||||
__typename: 'WorkspaceMember',
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
cache.evict({
|
|
||||||
id: cache.identify({
|
|
||||||
id: userId,
|
|
||||||
__typename: 'User',
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
cache.gc();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
const { deleteOneObject: deleteOneWorkspaceMember } =
|
||||||
|
useDeleteOneObjectRecord({
|
||||||
|
objectNamePlural: 'workspaceMembersV2',
|
||||||
|
});
|
||||||
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
|
|
||||||
|
const handleRemoveWorkspaceMember = async (workspaceMemberId: string) => {
|
||||||
|
await deleteOneWorkspaceMember?.(workspaceMemberId);
|
||||||
setIsConfirmationModalOpen(false);
|
setIsConfirmationModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,14 +53,14 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
||||||
<SettingsPageContainer width={350}>
|
<SettingsPageContainer width={350}>
|
||||||
<StyledH1Title title="Members" />
|
<StyledH1Title title="Members" />
|
||||||
{workspace?.inviteHash && (
|
{currentWorkspace?.inviteHash && (
|
||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
title="Invite"
|
title="Invite"
|
||||||
description="Send an invitation to use Twenty"
|
description="Send an invitation to use Twenty"
|
||||||
/>
|
/>
|
||||||
<WorkspaceInviteLink
|
<WorkspaceInviteLink
|
||||||
inviteLink={`${window.location.origin}/invite/${workspace?.inviteHash}`}
|
inviteLink={`${window.location.origin}/invite/${currentWorkspace?.inviteHash}`}
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
)}
|
)}
|
||||||
@ -99,17 +69,17 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
title="Members"
|
title="Members"
|
||||||
description="Manage the members of your space here"
|
description="Manage the members of your space here"
|
||||||
/>
|
/>
|
||||||
{data?.workspaceMembers?.map((member) => (
|
{workspaceMembers?.map((member) => (
|
||||||
<WorkspaceMemberCard
|
<WorkspaceMemberCard
|
||||||
key={member.user.id}
|
key={member.id}
|
||||||
workspaceMember={{ user: member.user }}
|
workspaceMember={member as WorkspaceMember}
|
||||||
accessory={
|
accessory={
|
||||||
currentUser?.id !== member.user.id && (
|
currentWorkspace?.id !== member.id && (
|
||||||
<StyledButtonContainer>
|
<StyledButtonContainer>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsConfirmationModalOpen(true);
|
setIsConfirmationModalOpen(true);
|
||||||
setUserToDelete(member.user.id);
|
setWorkspaceMemberToDelete(member.id);
|
||||||
}}
|
}}
|
||||||
variant="tertiary"
|
variant="tertiary"
|
||||||
size="medium"
|
size="medium"
|
||||||
@ -133,7 +103,8 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
onConfirmClick={() =>
|
onConfirmClick={() =>
|
||||||
userToDelete && handleRemoveWorkspaceMember(userToDelete)
|
workspaceMemberToDelete &&
|
||||||
|
handleRemoveWorkspaceMember(workspaceMemberToDelete)
|
||||||
}
|
}
|
||||||
deleteButtonText="Delete account"
|
deleteButtonText="Delete account"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter';
|
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
import { tasksFilterDefinitions } from './tasks-filter-definitions';
|
import { tasksFilterDefinitions } from './tasks-filter-definitions';
|
||||||
|
|
||||||
export const TasksEffect = () => {
|
export const TasksEffect = () => {
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const { setSelectedFilter, setAvailableFilterDefinitions } = useFilter();
|
const { setSelectedFilter, setAvailableFilterDefinitions } = useFilter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -16,16 +16,19 @@ export const TasksEffect = () => {
|
|||||||
}, [setAvailableFilterDefinitions]);
|
}, [setAvailableFilterDefinitions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentUser) {
|
if (currentWorkspaceMember) {
|
||||||
setSelectedFilter({
|
setSelectedFilter({
|
||||||
fieldMetadataId: 'assigneeId',
|
fieldMetadataId: 'assigneeId',
|
||||||
value: currentUser.id,
|
value: currentWorkspaceMember.id,
|
||||||
operand: ViewFilterOperand.Is,
|
operand: ViewFilterOperand.Is,
|
||||||
displayValue: currentUser.displayName,
|
displayValue:
|
||||||
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
|
currentWorkspaceMember.firstName +
|
||||||
|
' ' +
|
||||||
|
currentWorkspaceMember.lastName,
|
||||||
|
displayAvatarUrl: currentWorkspaceMember.avatarUrl ?? undefined,
|
||||||
definition: tasksFilterDefinitions[0],
|
definition: tasksFilterDefinitions[0],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [currentUser, setSelectedFilter]);
|
}, [currentWorkspaceMember, setSelectedFilter]);
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -58,12 +58,9 @@ export class AbilityFactory {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// User
|
// User
|
||||||
can(AbilityAction.Read, 'User', {
|
|
||||||
workspaceMember: {
|
|
||||||
workspaceId: workspace.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (user) {
|
if (user) {
|
||||||
|
can(AbilityAction.Read, 'User', { id: user.id });
|
||||||
can(AbilityAction.Update, 'User', { id: user.id });
|
can(AbilityAction.Update, 'User', { id: user.id });
|
||||||
can(AbilityAction.Delete, 'User', { id: user.id });
|
can(AbilityAction.Delete, 'User', { id: user.id });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import { TokenExpiredError, JsonWebTokenError, verify } from 'jsonwebtoken';
|
|||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
|
|
||||||
import { CoreModule } from './core/core.module';
|
import { CoreModule } from './core/core.module';
|
||||||
import { CoreV2Module } from './coreV2/core.module';
|
|
||||||
import { IntegrationsModule } from './integrations/integrations.module';
|
import { IntegrationsModule } from './integrations/integrations.module';
|
||||||
import { PrismaModule } from './database/prisma.module';
|
import { PrismaModule } from './database/prisma.module';
|
||||||
import { HealthModule } from './health/health.module';
|
import { HealthModule } from './health/health.module';
|
||||||
@ -103,7 +102,6 @@ import { ExceptionFilter } from './filters/exception.filter';
|
|||||||
AbilityModule,
|
AbilityModule,
|
||||||
IntegrationsModule,
|
IntegrationsModule,
|
||||||
CoreModule,
|
CoreModule,
|
||||||
CoreV2Module,
|
|
||||||
TenantModule,
|
TenantModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@ -130,7 +130,6 @@ export class AuthResolver {
|
|||||||
defaultFields: {
|
defaultFields: {
|
||||||
User: {
|
User: {
|
||||||
id: true,
|
id: true,
|
||||||
workspaceMember: { select: { allowImpersonation: true } },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -140,7 +139,6 @@ export class AuthResolver {
|
|||||||
assert(user.canImpersonate, 'User cannot impersonate', ForbiddenException);
|
assert(user.canImpersonate, 'User cannot impersonate', ForbiddenException);
|
||||||
const select = prismaSelect.valueOf('user') as Prisma.UserSelect & {
|
const select = prismaSelect.valueOf('user') as Prisma.UserSelect & {
|
||||||
id: true;
|
id: true;
|
||||||
workspaceMember: { select: { allowImpersonation: true } };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.authService.impersonate(impersonateInput.userId, select);
|
return this.authService.impersonate(impersonateInput.userId, select);
|
||||||
|
|||||||
@ -63,11 +63,6 @@ export class GoogleAuthController {
|
|||||||
firstName: firstName ?? '',
|
firstName: firstName ?? '',
|
||||||
lastName: lastName ?? '',
|
lastName: lastName ?? '',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
settings: {
|
|
||||||
create: {
|
|
||||||
locale: 'en',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
|||||||
@ -88,7 +88,6 @@ export class AuthService {
|
|||||||
data: {
|
data: {
|
||||||
email: signUpInput.email,
|
email: signUpInput.email,
|
||||||
passwordHash,
|
passwordHash,
|
||||||
locale: 'en',
|
|
||||||
},
|
},
|
||||||
} as Prisma.UserCreateArgs,
|
} as Prisma.UserCreateArgs,
|
||||||
workspace.id,
|
workspace.id,
|
||||||
@ -160,11 +159,6 @@ export class AuthService {
|
|||||||
userId: string,
|
userId: string,
|
||||||
select: Prisma.UserSelect & {
|
select: Prisma.UserSelect & {
|
||||||
id: true;
|
id: true;
|
||||||
workspaceMember: {
|
|
||||||
select: {
|
|
||||||
allowImpersonation: true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const user = await this.userService.findUnique({
|
const user = await this.userService.findUnique({
|
||||||
@ -175,11 +169,8 @@ export class AuthService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert(user, "This user doesn't exist", NotFoundException);
|
assert(user, "This user doesn't exist", NotFoundException);
|
||||||
assert(
|
|
||||||
user.workspaceMember?.allowImpersonation,
|
// Todo: check if workspace member can be impersonated
|
||||||
'Impersonation not allowed',
|
|
||||||
ForbiddenException,
|
|
||||||
);
|
|
||||||
|
|
||||||
const accessToken = await this.tokenService.generateAccessToken(user.id);
|
const accessToken = await this.tokenService.generateAccessToken(user.id);
|
||||||
const refreshToken = await this.tokenService.generateRefreshToken(user.id);
|
const refreshToken = await this.tokenService.generateRefreshToken(user.id);
|
||||||
|
|||||||
@ -33,22 +33,19 @@ export class TokenService {
|
|||||||
|
|
||||||
const user = await this.prismaService.client.user.findUnique({
|
const user = await this.prismaService.client.user.findUnique({
|
||||||
where: { id: userId },
|
where: { id: userId },
|
||||||
include: {
|
|
||||||
workspaceMember: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException('User is not found');
|
throw new NotFoundException('User is not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.workspaceMember) {
|
if (!user.defaultWorkspaceId) {
|
||||||
throw new ForbiddenException('User is not associated to a workspace');
|
throw new NotFoundException('User does not have a default workspace');
|
||||||
}
|
}
|
||||||
|
|
||||||
const jwtPayload: JwtPayload = {
|
const jwtPayload: JwtPayload = {
|
||||||
sub: user.id,
|
sub: user.id,
|
||||||
workspaceId: user.workspaceMember.workspaceId,
|
workspaceId: user.defaultWorkspaceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WebHookModule } from 'src/core/web-hook/web-hook.module';
|
import { WebHookModule } from 'src/core/web-hook/web-hook.module';
|
||||||
|
import { UserModule as UserV2Module } from 'src/coreV2/user/user.module';
|
||||||
|
import { RefreshTokenModule as RefreshTokenV2Module } from 'src/coreV2/refresh-token/refresh-token.module';
|
||||||
|
|
||||||
import { UserModule } from './user/user.module';
|
import { UserModule } from './user/user.module';
|
||||||
import { CommentModule } from './comment/comment.module';
|
import { CommentModule } from './comment/comment.module';
|
||||||
@ -34,6 +36,8 @@ import { ApiKeyModule } from './api-key/api-key.module';
|
|||||||
FavoriteModule,
|
FavoriteModule,
|
||||||
ApiKeyModule,
|
ApiKeyModule,
|
||||||
WebHookModule,
|
WebHookModule,
|
||||||
|
UserV2Module,
|
||||||
|
RefreshTokenV2Module,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
AuthModule,
|
AuthModule,
|
||||||
@ -48,6 +52,8 @@ import { ApiKeyModule } from './api-key/api-key.module';
|
|||||||
FavoriteModule,
|
FavoriteModule,
|
||||||
ApiKeyModule,
|
ApiKeyModule,
|
||||||
WebHookModule,
|
WebHookModule,
|
||||||
|
UserV2Module,
|
||||||
|
RefreshTokenV2Module,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreModule {}
|
export class CoreModule {}
|
||||||
|
|||||||
@ -66,13 +66,6 @@ export class UserService {
|
|||||||
: await this.workspaceService.createDefaultWorkspace();
|
: await this.workspaceService.createDefaultWorkspace();
|
||||||
|
|
||||||
assert(workspace, 'workspace is missing', BadRequestException);
|
assert(workspace, 'workspace is missing', BadRequestException);
|
||||||
|
|
||||||
const userSettings = await this.prismaService.client.userSettings.create({
|
|
||||||
data: { locale: 'en' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const settings = { connect: { id: userSettings.id } };
|
|
||||||
|
|
||||||
// Create user
|
// Create user
|
||||||
const user = await this.prismaService.client.user.upsert({
|
const user = await this.prismaService.client.user.upsert({
|
||||||
where: {
|
where: {
|
||||||
@ -80,17 +73,7 @@ export class UserService {
|
|||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
...(args.data as Prisma.UserCreateInput),
|
...(args.data as Prisma.UserCreateInput),
|
||||||
settings,
|
defaultWorkspaceId: workspace.id,
|
||||||
|
|
||||||
workspaceMember: {
|
|
||||||
create: {
|
|
||||||
workspace: {
|
|
||||||
connect: { id: workspace.id },
|
|
||||||
},
|
|
||||||
settings,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
locale: 'en',
|
|
||||||
},
|
},
|
||||||
update: {},
|
update: {},
|
||||||
...(args.select ? { select: args.select } : {}),
|
...(args.select ? { select: args.select } : {}),
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
import { GraphQLModule } from '@nestjs/graphql';
|
|
||||||
|
|
||||||
import { YogaDriverConfig, YogaDriver } from '@graphql-yoga/nestjs';
|
|
||||||
import GraphQLJSON from 'graphql-type-json';
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-imports
|
|
||||||
import config from '../../ormconfig';
|
|
||||||
|
|
||||||
import { UserModule } from './user/user.module';
|
|
||||||
import { RefreshTokenModule } from './refresh-token/refresh-token.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [
|
|
||||||
TypeOrmModule.forRoot(config),
|
|
||||||
GraphQLModule.forRoot<YogaDriverConfig>({
|
|
||||||
context: ({ req }) => ({ req }),
|
|
||||||
driver: YogaDriver,
|
|
||||||
autoSchemaFile: true,
|
|
||||||
include: [CoreV2Module],
|
|
||||||
resolvers: { JSON: GraphQLJSON },
|
|
||||||
plugins: [],
|
|
||||||
path: '/graphqlv2',
|
|
||||||
}),
|
|
||||||
UserModule,
|
|
||||||
RefreshTokenModule,
|
|
||||||
],
|
|
||||||
exports: [UserModule],
|
|
||||||
})
|
|
||||||
export class CoreV2Module {}
|
|
||||||
@ -3,7 +3,6 @@ import {
|
|||||||
PagingStrategies,
|
PagingStrategies,
|
||||||
ReadResolverOpts,
|
ReadResolverOpts,
|
||||||
} from '@ptc-org/nestjs-query-graphql';
|
} from '@ptc-org/nestjs-query-graphql';
|
||||||
import { SortDirection } from '@ptc-org/nestjs-query-core';
|
|
||||||
|
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
|
|
||||||
@ -26,7 +25,8 @@ export const refreshTokenAutoResolverOpts: AutoResolverOpts<
|
|||||||
enableTotalCount: true,
|
enableTotalCount: true,
|
||||||
pagingStrategy: PagingStrategies.CURSOR,
|
pagingStrategy: PagingStrategies.CURSOR,
|
||||||
read: {
|
read: {
|
||||||
defaultSort: [{ field: 'id', direction: SortDirection.DESC }],
|
many: { disabled: true },
|
||||||
|
one: { disabled: true },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
many: { disabled: true },
|
many: { disabled: true },
|
||||||
|
|||||||
@ -15,12 +15,12 @@ import {
|
|||||||
IDField,
|
IDField,
|
||||||
} from '@ptc-org/nestjs-query-graphql';
|
} from '@ptc-org/nestjs-query-graphql';
|
||||||
|
|
||||||
import { User } from 'src/coreV2/user/user.entity';
|
import { UserV2 } from 'src/coreV2/user/user.entity';
|
||||||
|
|
||||||
import { BeforeCreateOneRefreshToken } from './hooks/before-create-one-refresh-token.hook';
|
import { BeforeCreateOneRefreshToken } from './hooks/before-create-one-refresh-token.hook';
|
||||||
|
|
||||||
@Entity('refresh_tokens')
|
@Entity('refresh_tokens')
|
||||||
@ObjectType('RefreshToken')
|
@ObjectType('refreshTokenV2')
|
||||||
@BeforeCreateOne(BeforeCreateOneRefreshToken)
|
@BeforeCreateOne(BeforeCreateOneRefreshToken)
|
||||||
@Authorize({
|
@Authorize({
|
||||||
authorize: (context: any) => ({
|
authorize: (context: any) => ({
|
||||||
@ -32,9 +32,9 @@ export class RefreshToken {
|
|||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.refreshTokens)
|
@ManyToOne(() => UserV2, (user) => user.refreshTokens)
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
user: User;
|
user: UserV2;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
|
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
|
||||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-imports
|
||||||
|
import config from '../../../ormconfig';
|
||||||
|
|
||||||
import { RefreshToken } from './refresh-token.entity';
|
import { RefreshToken } from './refresh-token.entity';
|
||||||
import { refreshTokenAutoResolverOpts } from './refresh-token.auto-resolver-opts';
|
import { refreshTokenAutoResolverOpts } from './refresh-token.auto-resolver-opts';
|
||||||
|
|
||||||
@ -10,6 +14,7 @@ import { RefreshTokenService } from './services/refresh-token.service';
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
TypeOrmModule.forRoot(config),
|
||||||
NestjsQueryGraphQLModule.forFeature({
|
NestjsQueryGraphQLModule.forFeature({
|
||||||
imports: [NestjsQueryTypeOrmModule.forFeature([RefreshToken])],
|
imports: [NestjsQueryTypeOrmModule.forFeature([RefreshToken])],
|
||||||
services: [RefreshTokenService],
|
services: [RefreshTokenService],
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
|||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { assert } from 'src/utils/assert';
|
import { assert } from 'src/utils/assert';
|
||||||
import { User } from 'src/coreV2/user/user.entity';
|
import { UserV2 } from 'src/coreV2/user/user.entity';
|
||||||
|
|
||||||
export class UserService extends TypeOrmQueryService<User> {
|
export class UserService extends TypeOrmQueryService<UserV2> {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(User)
|
@InjectRepository(UserV2)
|
||||||
private readonly userRepository: Repository<User>,
|
private readonly userRepository: Repository<UserV2>,
|
||||||
) {
|
) {
|
||||||
super(userRepository);
|
super(userRepository);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
import { SortDirection } from '@ptc-org/nestjs-query-core';
|
|
||||||
import {
|
import {
|
||||||
AutoResolverOpts,
|
AutoResolverOpts,
|
||||||
ReadResolverOpts,
|
ReadResolverOpts,
|
||||||
PagingStrategies,
|
PagingStrategies,
|
||||||
} from '@ptc-org/nestjs-query-graphql';
|
} from '@ptc-org/nestjs-query-graphql';
|
||||||
|
|
||||||
|
import { UserV2 } from 'src/coreV2/user/user.entity';
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
|
|
||||||
import { User } from './user.entity';
|
|
||||||
|
|
||||||
export const userAutoResolverOpts: AutoResolverOpts<
|
export const userAutoResolverOpts: AutoResolverOpts<
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
@ -18,12 +16,13 @@ export const userAutoResolverOpts: AutoResolverOpts<
|
|||||||
PagingStrategies
|
PagingStrategies
|
||||||
>[] = [
|
>[] = [
|
||||||
{
|
{
|
||||||
EntityClass: User,
|
EntityClass: UserV2,
|
||||||
DTOClass: User,
|
DTOClass: UserV2,
|
||||||
enableTotalCount: true,
|
enableTotalCount: true,
|
||||||
pagingStrategy: PagingStrategies.CURSOR,
|
pagingStrategy: PagingStrategies.CURSOR,
|
||||||
read: {
|
read: {
|
||||||
defaultSort: [{ field: 'id', direction: SortDirection.DESC }],
|
many: { disabled: true },
|
||||||
|
one: { disabled: true },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
many: { disabled: true },
|
many: { disabled: true },
|
||||||
|
|||||||
@ -13,8 +13,8 @@ import { GraphQLJSONObject } from 'graphql-type-json';
|
|||||||
|
|
||||||
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
|
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
|
||||||
|
|
||||||
@Entity('users')
|
@Entity('userV2')
|
||||||
@ObjectType('user')
|
@ObjectType('userV2')
|
||||||
// @Authorize({
|
// @Authorize({
|
||||||
// authorize: (context: any) => ({
|
// authorize: (context: any) => ({
|
||||||
// // FIXME: We do not have this relation in the database
|
// // FIXME: We do not have this relation in the database
|
||||||
@ -23,7 +23,7 @@ import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
|
|||||||
// },
|
// },
|
||||||
// }),
|
// }),
|
||||||
// })
|
// })
|
||||||
export class User {
|
export class UserV2 {
|
||||||
@IDField(() => ID)
|
@IDField(() => ID)
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
|||||||
|
|
||||||
import { AbilityModule } from 'src/ability/ability.module';
|
import { AbilityModule } from 'src/ability/ability.module';
|
||||||
import { FileModule } from 'src/core/file/file.module';
|
import { FileModule } from 'src/core/file/file.module';
|
||||||
|
import { UserV2 } from 'src/coreV2/user/user.entity';
|
||||||
|
|
||||||
import { User } from './user.entity';
|
|
||||||
import { UserResolver } from './user.resolver';
|
import { UserResolver } from './user.resolver';
|
||||||
import { userAutoResolverOpts } from './user.auto-resolver-opts';
|
import { userAutoResolverOpts } from './user.auto-resolver-opts';
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ import { UserService } from './services/user.service';
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
NestjsQueryGraphQLModule.forFeature({
|
NestjsQueryGraphQLModule.forFeature({
|
||||||
imports: [NestjsQueryTypeOrmModule.forFeature([User])],
|
imports: [NestjsQueryTypeOrmModule.forFeature([UserV2])],
|
||||||
services: [UserService],
|
services: [UserService],
|
||||||
resolvers: userAutoResolverOpts,
|
resolvers: userAutoResolverOpts,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -26,8 +26,7 @@ import { FileUploadService } from 'src/core/file/services/file-upload.service';
|
|||||||
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
||||||
import { assert } from 'src/utils/assert';
|
import { assert } from 'src/utils/assert';
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
|
import { UserV2 } from 'src/coreV2/user/user.entity';
|
||||||
import { User } from './user.entity';
|
|
||||||
|
|
||||||
import { UserService } from './services/user.service';
|
import { UserService } from './services/user.service';
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ const getHMACKey = (email?: string, key?: string | null) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Resolver(() => User)
|
@Resolver(() => UserV2)
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
@ -47,8 +46,8 @@ export class UserResolver {
|
|||||||
private readonly fileUploadService: FileUploadService,
|
private readonly fileUploadService: FileUploadService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Query(() => User)
|
@Query(() => UserV2)
|
||||||
async currentUser(@AuthUser() { id }: User) {
|
async currentUserV2(@AuthUser() { id }: UserV2) {
|
||||||
const user = await this.userService.findById(id);
|
const user = await this.userService.findById(id);
|
||||||
assert(user, 'User not found');
|
assert(user, 'User not found');
|
||||||
return user;
|
return user;
|
||||||
@ -57,14 +56,14 @@ export class UserResolver {
|
|||||||
@ResolveField(() => String, {
|
@ResolveField(() => String, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
displayName(@Parent() parent: User): string {
|
displayName(@Parent() parent: UserV2): string {
|
||||||
return `${parent.firstName ?? ''} ${parent.lastName ?? ''}`;
|
return `${parent.firstName ?? ''} ${parent.lastName ?? ''}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => String, {
|
@ResolveField(() => String, {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
supportUserHash(@Parent() parent: User): string | null {
|
supportUserHash(@Parent() parent: UserV2): string | null {
|
||||||
if (this.environmentService.getSupportDriver() !== SupportDriver.Front) {
|
if (this.environmentService.getSupportDriver() !== SupportDriver.Front) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -73,8 +72,8 @@ export class UserResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => String)
|
@Mutation(() => String)
|
||||||
async uploadProfilePicture(
|
async uploadProfilePictureV2(
|
||||||
@AuthUser() { id }: User,
|
@AuthUser() { id }: UserV2,
|
||||||
@Args({ name: 'file', type: () => GraphQLUpload })
|
@Args({ name: 'file', type: () => GraphQLUpload })
|
||||||
{ createReadStream, filename, mimetype }: FileUpload,
|
{ createReadStream, filename, mimetype }: FileUpload,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
@ -96,11 +95,11 @@ export class UserResolver {
|
|||||||
return paths[0];
|
return paths[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => User)
|
@Mutation(() => UserV2)
|
||||||
@UseGuards(AbilityGuard)
|
@UseGuards(AbilityGuard)
|
||||||
@CheckAbilities(DeleteUserAbilityHandler)
|
@CheckAbilities(DeleteUserAbilityHandler)
|
||||||
async deleteUserAccount(
|
async deleteUserV2(
|
||||||
@AuthUser() { id: userId }: User,
|
@AuthUser() { id: userId }: UserV2,
|
||||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||||
) {
|
) {
|
||||||
return this.userService.deleteUser({ userId, workspaceId });
|
return this.userService.deleteUser({ userId, workspaceId });
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "workspace_members" DROP CONSTRAINT "workspace_members_userId_fkey";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "users" ADD COLUMN "defaultWorkspaceId" TEXT;
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `settingsId` on the `users` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "users" DROP CONSTRAINT "users_settingsId_fkey";
|
||||||
|
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "users_settingsId_key";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "user_settings" ADD COLUMN "userId" TEXT;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "users" DROP COLUMN "settingsId";
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "user_settings" ADD CONSTRAINT "user_settings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `userId` on the `user_settings` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "user_settings" DROP CONSTRAINT "user_settings_userId_fkey";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "user_settings" DROP COLUMN "userId";
|
||||||
@ -102,18 +102,15 @@ model User {
|
|||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
canImpersonate Boolean @default(false)
|
canImpersonate Boolean @default(false)
|
||||||
|
|
||||||
/// @TypeGraphQL.omit(input: true)
|
companies Company[]
|
||||||
workspaceMember WorkspaceMember?
|
|
||||||
companies Company[]
|
|
||||||
/// @TypeGraphQL.omit(input: true, output: true)
|
/// @TypeGraphQL.omit(input: true, output: true)
|
||||||
refreshTokens RefreshToken[]
|
refreshTokens RefreshToken[]
|
||||||
comments Comment[]
|
comments Comment[]
|
||||||
|
defaultWorkspaceId String?
|
||||||
|
|
||||||
authoredActivities Activity[] @relation(name: "authoredActivities")
|
authoredActivities Activity[] @relation(name: "authoredActivities")
|
||||||
assignedActivities Activity[] @relation(name: "assignedActivities")
|
assignedActivities Activity[] @relation(name: "assignedActivities")
|
||||||
authoredAttachments Attachment[] @relation(name: "authoredAttachments")
|
authoredAttachments Attachment[] @relation(name: "authoredAttachments")
|
||||||
settings UserSettings @relation(fields: [settingsId], references: [id])
|
|
||||||
settingsId String @unique
|
|
||||||
|
|
||||||
/// @TypeGraphQL.omit(input: true, output: true)
|
/// @TypeGraphQL.omit(input: true, output: true)
|
||||||
deletedAt DateTime?
|
deletedAt DateTime?
|
||||||
@ -138,7 +135,6 @@ model UserSettings {
|
|||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
locale String
|
locale String
|
||||||
|
|
||||||
user User?
|
|
||||||
WorkspaceMember WorkspaceMember[]
|
WorkspaceMember WorkspaceMember[]
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@ -195,7 +191,6 @@ model WorkspaceMember {
|
|||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
allowImpersonation Boolean @default(true)
|
allowImpersonation Boolean @default(true)
|
||||||
|
|
||||||
user User @relation(fields: [userId], references: [id])
|
|
||||||
userId String @unique
|
userId String @unique
|
||||||
/// @TypeGraphQL.omit(input: true, output: false)
|
/// @TypeGraphQL.omit(input: true, output: false)
|
||||||
workspace Workspace @relation(fields: [workspaceId], references: [id])
|
workspace Workspace @relation(fields: [workspaceId], references: [id])
|
||||||
|
|||||||
@ -19,19 +19,8 @@ export const seedUsers = async (prisma: PrismaClient) => {
|
|||||||
locale: 'en',
|
locale: 'en',
|
||||||
passwordHash:
|
passwordHash:
|
||||||
'$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025
|
'$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-9dcb1084c109',
|
|
||||||
avatarUrl: null,
|
avatarUrl: null,
|
||||||
workspaceMember: {
|
defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
||||||
connectOrCreate: {
|
|
||||||
where: {
|
|
||||||
id: '20202020-0687-4c41-b707-ed1bfca972a7',
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-9dcb1084c109',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -52,15 +41,8 @@ export const seedUsers = async (prisma: PrismaClient) => {
|
|||||||
lastName: 'Ive',
|
lastName: 'Ive',
|
||||||
email: 'jony.ive@apple.dev',
|
email: 'jony.ive@apple.dev',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-2c4a2035a215',
|
|
||||||
avatarUrl: null,
|
avatarUrl: null,
|
||||||
workspaceMember: {
|
defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
||||||
create: {
|
|
||||||
id: '20202020-77d5-4cb6-b60a-f4a835a85d61',
|
|
||||||
workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-2c4a2035a215',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,15 +63,8 @@ export const seedUsers = async (prisma: PrismaClient) => {
|
|||||||
lastName: 'Schiler',
|
lastName: 'Schiler',
|
||||||
email: 'phil.schiler@apple.dev',
|
email: 'phil.schiler@apple.dev',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-8e1f2097b328',
|
|
||||||
avatarUrl: null,
|
avatarUrl: null,
|
||||||
workspaceMember: {
|
defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
||||||
create: {
|
|
||||||
id: '20202020-1553-45c6-a028-5a9064cce07f',
|
|
||||||
workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-8e1f2097b328',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -110,14 +85,6 @@ export const seedUsers = async (prisma: PrismaClient) => {
|
|||||||
lastName: 'Bochet',
|
lastName: 'Bochet',
|
||||||
email: 'charles@twenty.dev',
|
email: 'charles@twenty.dev',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-5e2d1049c430',
|
|
||||||
workspaceMember: {
|
|
||||||
create: {
|
|
||||||
id: 'twenty-dev-7ed9d213-1c25-4d02-bf35-6aeccf7oa419',
|
|
||||||
workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420',
|
|
||||||
settingsId: 'twenty-ge256b39-3ec3-4fe3-8997-5e2d1049c430',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const fieldMetadataTableName = 'fieldMetadata';
|
|||||||
export enum SeedWorkspaceMemberFieldMetadataIds {
|
export enum SeedWorkspaceMemberFieldMetadataIds {
|
||||||
FirstName = '20202020-1fa8-4d38-9fa4-0cf696909298',
|
FirstName = '20202020-1fa8-4d38-9fa4-0cf696909298',
|
||||||
LastName = '20202020-8c37-4163-ba06-1dada334ce3e',
|
LastName = '20202020-8c37-4163-ba06-1dada334ce3e',
|
||||||
|
AvatarUrl = '20202020-7ba6-40d5-934b-17146183a212',
|
||||||
Locale = '20202020-10f6-4df9-8d6f-a760b65bd800',
|
Locale = '20202020-10f6-4df9-8d6f-a760b65bd800',
|
||||||
ColorScheme = '20202020-83f2-4c5f-96b0-0c51ecc160e3',
|
ColorScheme = '20202020-83f2-4c5f-96b0-0c51ecc160e3',
|
||||||
AllowImpersonation = '20202020-bb19-44a1-8156-8866f87a5f42',
|
AllowImpersonation = '20202020-bb19-44a1-8156-8866f87a5f42',
|
||||||
@ -77,6 +78,22 @@ export const seedWorkspaceMemberFieldMetadata = async (
|
|||||||
icon: 'IconCircleUser',
|
icon: 'IconCircleUser',
|
||||||
isNullable: false,
|
isNullable: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: SeedWorkspaceMemberFieldMetadataIds.AvatarUrl,
|
||||||
|
objectMetadataId: SeedObjectMetadataIds.WorkspaceMember,
|
||||||
|
isCustom: false,
|
||||||
|
workspaceId: SeedWorkspaceId,
|
||||||
|
isActive: true,
|
||||||
|
type: 'TEXT',
|
||||||
|
name: 'avatarUrl',
|
||||||
|
label: 'Avatar Url',
|
||||||
|
targetColumnMap: {
|
||||||
|
value: 'avatarUrl',
|
||||||
|
},
|
||||||
|
description: 'Workspace member avatar',
|
||||||
|
icon: 'IconFileUpload',
|
||||||
|
isNullable: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: SeedWorkspaceMemberFieldMetadataIds.UserId,
|
id: SeedWorkspaceMemberFieldMetadataIds.UserId,
|
||||||
objectMetadataId: SeedObjectMetadataIds.WorkspaceMember,
|
objectMetadataId: SeedObjectMetadataIds.WorkspaceMember,
|
||||||
@ -123,7 +140,7 @@ export const seedWorkspaceMemberFieldMetadata = async (
|
|||||||
},
|
},
|
||||||
description: 'Preferred color scheme',
|
description: 'Preferred color scheme',
|
||||||
icon: 'IconColorSwatch',
|
icon: 'IconColorSwatch',
|
||||||
isNullable: false,
|
isNullable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: SeedWorkspaceMemberFieldMetadataIds.Locale,
|
id: SeedWorkspaceMemberFieldMetadataIds.Locale,
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export const seedWorkspaceMember = async (
|
|||||||
firstName: 'Tim',
|
firstName: 'Tim',
|
||||||
lastName: 'Apple',
|
lastName: 'Apple',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
colorScheme: 'light',
|
colorScheme: 'Light',
|
||||||
allowImpersonation: true,
|
allowImpersonation: true,
|
||||||
userId: WorkspaceMemberUserIds.Tim,
|
userId: WorkspaceMemberUserIds.Tim,
|
||||||
},
|
},
|
||||||
@ -46,7 +46,7 @@ export const seedWorkspaceMember = async (
|
|||||||
firstName: 'Jony',
|
firstName: 'Jony',
|
||||||
lastName: 'Ive',
|
lastName: 'Ive',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
colorScheme: 'light',
|
colorScheme: 'Light',
|
||||||
allowImpersonation: true,
|
allowImpersonation: true,
|
||||||
userId: WorkspaceMemberUserIds.Jony,
|
userId: WorkspaceMemberUserIds.Jony,
|
||||||
},
|
},
|
||||||
@ -55,9 +55,9 @@ export const seedWorkspaceMember = async (
|
|||||||
firstName: 'Phil',
|
firstName: 'Phil',
|
||||||
lastName: 'Shiler',
|
lastName: 'Shiler',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
colorScheme: 'light',
|
colorScheme: 'Light',
|
||||||
allowImpersonation: true,
|
allowImpersonation: true,
|
||||||
userId: WorkspaceMemberUserIds.Phil,
|
userId: WorkspaceMemberUserIds.Tim,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
.execute();
|
.execute();
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { ObjectType, ID, Field, HideField } from '@nestjs/graphql';
|
import {
|
||||||
|
ObjectType,
|
||||||
|
ID,
|
||||||
|
Field,
|
||||||
|
HideField,
|
||||||
|
registerEnumType,
|
||||||
|
} from '@nestjs/graphql';
|
||||||
|
|
||||||
import { CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
import { CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
||||||
import {
|
import {
|
||||||
@ -11,6 +17,11 @@ import {
|
|||||||
import { ObjectMetadataDTO } from 'src/metadata/object-metadata/dtos/object-metadata.dto';
|
import { ObjectMetadataDTO } from 'src/metadata/object-metadata/dtos/object-metadata.dto';
|
||||||
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||||
|
|
||||||
|
registerEnumType(RelationMetadataType, {
|
||||||
|
name: 'RelationMetadataType',
|
||||||
|
description: 'Type of the relation',
|
||||||
|
});
|
||||||
|
|
||||||
@ObjectType('relation')
|
@ObjectType('relation')
|
||||||
@Authorize({
|
@Authorize({
|
||||||
authorize: (context: any) => ({
|
authorize: (context: any) => ({
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { registerEnumType } from '@nestjs/graphql';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
@ -22,11 +20,6 @@ export enum RelationMetadataType {
|
|||||||
MANY_TO_MANY = 'MANY_TO_MANY',
|
MANY_TO_MANY = 'MANY_TO_MANY',
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEnumType(RelationMetadataType, {
|
|
||||||
name: 'RelationMetadataType',
|
|
||||||
description: 'Type of the relation',
|
|
||||||
});
|
|
||||||
|
|
||||||
@Entity('relationMetadata')
|
@Entity('relationMetadata')
|
||||||
export class RelationMetadataEntity implements RelationMetadataInterface {
|
export class RelationMetadataEntity implements RelationMetadataInterface {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
|||||||
@ -22,6 +22,11 @@ export const addWorkspaceMemberTable: TenantMigrationTableAction[] = [
|
|||||||
columnType: 'varchar',
|
columnType: 'varchar',
|
||||||
action: TenantMigrationColumnActionType.CREATE,
|
action: TenantMigrationColumnActionType.CREATE,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
columnName: 'avatarUrl',
|
||||||
|
columnType: 'varchar',
|
||||||
|
action: TenantMigrationColumnActionType.CREATE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
columnName: 'colorScheme',
|
columnName: 'colorScheme',
|
||||||
columnType: 'varchar',
|
columnType: 'varchar',
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
export const companyPrefillData = async (
|
||||||
|
entityManager: EntityManager,
|
||||||
|
schemaName: string,
|
||||||
|
) => {
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.company`, [
|
||||||
|
'name',
|
||||||
|
'domainName',
|
||||||
|
'address',
|
||||||
|
'employees',
|
||||||
|
])
|
||||||
|
.orIgnore()
|
||||||
|
.values([
|
||||||
|
{
|
||||||
|
name: 'Airbnb',
|
||||||
|
domainName: 'airbnb.com',
|
||||||
|
address: 'San Francisco',
|
||||||
|
employees: 5000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Qonto',
|
||||||
|
domainName: 'qonto.com',
|
||||||
|
address: 'San Francisco',
|
||||||
|
employees: 800,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Stripe',
|
||||||
|
domainName: 'stripe.com',
|
||||||
|
address: 'San Francisco',
|
||||||
|
employees: 8000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Figma',
|
||||||
|
domainName: 'figma.com',
|
||||||
|
address: 'San Francisco',
|
||||||
|
employees: 800,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Notion',
|
||||||
|
domainName: 'notion.com',
|
||||||
|
address: 'San Francisco',
|
||||||
|
employees: 400,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.returning('*')
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,41 @@
|
|||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
export const pipelineStepPrefillData = async (
|
||||||
|
entityManager: EntityManager,
|
||||||
|
schemaName: string,
|
||||||
|
) => {
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.pipelineStep`, ['name', 'color', 'position'])
|
||||||
|
.orIgnore()
|
||||||
|
.values([
|
||||||
|
{
|
||||||
|
name: 'New',
|
||||||
|
color: 'red',
|
||||||
|
position: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Screening',
|
||||||
|
color: 'purple',
|
||||||
|
position: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Meeting',
|
||||||
|
color: 'sky',
|
||||||
|
position: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Proposal',
|
||||||
|
color: 'turquoise',
|
||||||
|
position: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Customer',
|
||||||
|
color: 'yellow',
|
||||||
|
position: 4,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.returning('*')
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
@ -1,269 +1,31 @@
|
|||||||
import { DataSource, EntityManager } from 'typeorm';
|
import { DataSource, EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
|
||||||
|
import { viewPrefillData } from 'src/tenant-manager/standard-objects-prefill-data/view';
|
||||||
|
import { companyPrefillData } from 'src/tenant-manager/standard-objects-prefill-data/company';
|
||||||
|
import { personPrefillData } from 'src/tenant-manager/standard-objects-prefill-data/person';
|
||||||
|
import { pipelineStepPrefillData } from 'src/tenant-manager/standard-objects-prefill-data/pipeline-step';
|
||||||
|
|
||||||
export const standardObjectsPrefillData = async (
|
export const standardObjectsPrefillData = async (
|
||||||
workspaceDataSource: DataSource,
|
workspaceDataSource: DataSource,
|
||||||
schemaName: string,
|
schemaName: string,
|
||||||
|
objectMetadata: ObjectMetadataEntity[],
|
||||||
) => {
|
) => {
|
||||||
|
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
|
||||||
|
acc[object.nameSingular] = {
|
||||||
|
id: object.id,
|
||||||
|
fields: object.fields.reduce((acc, field) => {
|
||||||
|
acc[field.name] = field.id;
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
workspaceDataSource.transaction(async (entityManager: EntityManager) => {
|
workspaceDataSource.transaction(async (entityManager: EntityManager) => {
|
||||||
const createdCompanies = await entityManager
|
await companyPrefillData(entityManager, schemaName);
|
||||||
.createQueryBuilder()
|
await personPrefillData(entityManager, schemaName);
|
||||||
.insert()
|
await viewPrefillData(entityManager, schemaName, objectMetadataMap);
|
||||||
.into(`${schemaName}.company`, [
|
await pipelineStepPrefillData(entityManager, schemaName);
|
||||||
'name',
|
|
||||||
'domainName',
|
|
||||||
'address',
|
|
||||||
'employees',
|
|
||||||
])
|
|
||||||
.orIgnore()
|
|
||||||
.values([
|
|
||||||
{
|
|
||||||
name: 'Airbnb',
|
|
||||||
domainName: 'airbnb.com',
|
|
||||||
address: 'San Francisco',
|
|
||||||
employees: 5000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Qonto',
|
|
||||||
domainName: 'qonto.com',
|
|
||||||
address: 'San Francisco',
|
|
||||||
employees: 800,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Stripe',
|
|
||||||
domainName: 'stripe.com',
|
|
||||||
address: 'San Francisco',
|
|
||||||
employees: 8000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Figma',
|
|
||||||
domainName: 'figma.com',
|
|
||||||
address: 'San Francisco',
|
|
||||||
employees: 800,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Notion',
|
|
||||||
domainName: 'notion.com',
|
|
||||||
address: 'San Francisco',
|
|
||||||
employees: 400,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.returning('*')
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
const companyIdMap = createdCompanies.raw.reduce((acc, view) => {
|
|
||||||
acc[view.name] = view.id;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const createdViews = await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type'])
|
|
||||||
.orIgnore()
|
|
||||||
.values([
|
|
||||||
{
|
|
||||||
name: 'All companies',
|
|
||||||
objectMetadataId: 'company',
|
|
||||||
type: 'table',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'All people',
|
|
||||||
objectMetadataId: 'person',
|
|
||||||
type: 'table',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'All opportunities',
|
|
||||||
objectMetadataId: 'company',
|
|
||||||
type: 'kanban',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'All Companies (V2)',
|
|
||||||
objectMetadataId: companyIdMap['Airbnb'],
|
|
||||||
type: 'table',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.returning('*')
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
const viewIdMap = createdViews.raw.reduce((acc, view) => {
|
|
||||||
acc[view.name] = view.id;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.viewField`, [
|
|
||||||
'fieldMetadataId',
|
|
||||||
'viewId',
|
|
||||||
'position',
|
|
||||||
'isVisible',
|
|
||||||
'size',
|
|
||||||
])
|
|
||||||
.orIgnore()
|
|
||||||
.values([
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'name',
|
|
||||||
viewId: viewIdMap['All Companies (V2)'],
|
|
||||||
position: 0,
|
|
||||||
isVisible: true,
|
|
||||||
size: 180,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'name',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 0,
|
|
||||||
isVisible: true,
|
|
||||||
size: 180,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'domainName',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 1,
|
|
||||||
isVisible: true,
|
|
||||||
size: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'accountOwner',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 2,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'createdAt',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 3,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'employees',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 4,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'linkedin',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 5,
|
|
||||||
isVisible: true,
|
|
||||||
size: 170,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'address',
|
|
||||||
viewId: viewIdMap['All companies'],
|
|
||||||
position: 6,
|
|
||||||
isVisible: true,
|
|
||||||
size: 170,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'displayName',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 0,
|
|
||||||
isVisible: true,
|
|
||||||
size: 210,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'email',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 1,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'company',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 2,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'phone',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 3,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'createdAt',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 4,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'city',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 5,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'jobTitle',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 6,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'linkedin',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 7,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'x',
|
|
||||||
viewId: viewIdMap['All people'],
|
|
||||||
position: 8,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'amount',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 0,
|
|
||||||
isVisible: true,
|
|
||||||
size: 180,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'probability',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 1,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'closeDate',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 2,
|
|
||||||
isVisible: true,
|
|
||||||
size: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'company',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 3,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'createdAt',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 4,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldMetadataId: 'pointOfContact',
|
|
||||||
viewId: viewIdMap['All opportunities'],
|
|
||||||
position: 5,
|
|
||||||
isVisible: true,
|
|
||||||
size: 150,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.execute();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
278
server/src/tenant-manager/standard-objects-prefill-data/view.ts
Normal file
278
server/src/tenant-manager/standard-objects-prefill-data/view.ts
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
|
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
|
||||||
|
|
||||||
|
export const viewPrefillData = async (
|
||||||
|
entityManager: EntityManager,
|
||||||
|
schemaName: string,
|
||||||
|
objectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||||
|
) => {
|
||||||
|
// Creating views
|
||||||
|
const createdViews = await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type'])
|
||||||
|
.orIgnore()
|
||||||
|
.values([
|
||||||
|
{
|
||||||
|
name: 'All companies',
|
||||||
|
objectMetadataId: 'company',
|
||||||
|
type: 'table',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'All people',
|
||||||
|
objectMetadataId: 'person',
|
||||||
|
type: 'table',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'All opportunities',
|
||||||
|
objectMetadataId: 'company',
|
||||||
|
type: 'kanban',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'All Companies (V2)',
|
||||||
|
objectMetadataId: objectMetadataMap['companyV2'].id,
|
||||||
|
type: 'table',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'All People (V2)',
|
||||||
|
objectMetadataId: objectMetadataMap['personV2'].id,
|
||||||
|
type: 'table',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'All Opportunities (V2)',
|
||||||
|
objectMetadataId: objectMetadataMap['companyV2'].id,
|
||||||
|
type: 'kanban',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.returning('*')
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
const viewIdMap = createdViews.raw.reduce((acc, view) => {
|
||||||
|
acc[view.name] = view.id;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Creating viewFields
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.viewField`, [
|
||||||
|
'fieldMetadataId',
|
||||||
|
'viewId',
|
||||||
|
'position',
|
||||||
|
'isVisible',
|
||||||
|
'size',
|
||||||
|
])
|
||||||
|
.orIgnore()
|
||||||
|
.values([
|
||||||
|
// CompanyV2
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['companyV2'].fields['name'],
|
||||||
|
viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
size: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['companyV2'].fields['domainName'],
|
||||||
|
viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
position: 1,
|
||||||
|
isVisible: true,
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// fieldMetadataId: objectMetadataMap['companyV2'].fields['accountOwner'],
|
||||||
|
// viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
// position: 2,
|
||||||
|
// isVisible: true,
|
||||||
|
// size: 150,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// fieldMetadataId: 'createdAt',
|
||||||
|
// viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
// position: 3,
|
||||||
|
// isVisible: true,
|
||||||
|
// size: 150,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['companyV2'].fields['employees'],
|
||||||
|
viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
position: 4,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['companyV2'].fields['linkedinUrl'],
|
||||||
|
viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
position: 5,
|
||||||
|
isVisible: true,
|
||||||
|
size: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['companyV2'].fields['address'],
|
||||||
|
viewId: viewIdMap['All Companies (V2)'],
|
||||||
|
position: 6,
|
||||||
|
isVisible: true,
|
||||||
|
size: 170,
|
||||||
|
},
|
||||||
|
// PeopleV2
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['firstName'], // TODO: change to displayName once we have name field type
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
size: 210,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['email'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 1,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// fieldMetadataId: objectMetadataMap['personV2'].fields['company'],
|
||||||
|
// viewId: viewIdMap['All People (V2)'],
|
||||||
|
// position: 2,
|
||||||
|
// isVisible: true,
|
||||||
|
// size: 150,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['phone'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 3,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// fieldMetadataId: 'createdAt',
|
||||||
|
// viewId: viewIdMap['All People (V2)'],
|
||||||
|
// position: 4,
|
||||||
|
// isVisible: true,
|
||||||
|
// size: 150,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['city'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 5,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['jobTitle'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 6,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['linkedinUrl'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 7,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: objectMetadataMap['personV2'].fields['xUrl'],
|
||||||
|
viewId: viewIdMap['All People (V2)'],
|
||||||
|
position: 8,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
// Companies
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'name',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
size: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'domainName',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 1,
|
||||||
|
isVisible: true,
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'accountOwner',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 2,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'createdAt',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 3,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'employees',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 4,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'linkedin',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 5,
|
||||||
|
isVisible: true,
|
||||||
|
size: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'address',
|
||||||
|
viewId: viewIdMap['All companies'],
|
||||||
|
position: 6,
|
||||||
|
isVisible: true,
|
||||||
|
size: 170,
|
||||||
|
},
|
||||||
|
// Opportunities
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'amount',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
size: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'probability',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 1,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'closeDate',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 2,
|
||||||
|
isVisible: true,
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'company',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 3,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'createdAt',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 4,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'pointOfContact',
|
||||||
|
viewId: viewIdMap['All opportunities'],
|
||||||
|
position: 5,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user