diff --git a/.vscode/extensions.json b/.vscode/extensions.json index cedc2cd1b..fde89b835 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -7,7 +7,6 @@ "ms-vscode.makefile-tools", "esbenp.prettier-vscode", "GraphQL.vscode-graphql", - "prisma.prisma", "yoavbls.pretty-ts-errors", "graphql.vscode-graphql-syntax", "graphql.vscode-graphql", diff --git a/.vscode/settings.json b/.vscode/settings.json index 366fb922e..3f4b28eeb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,10 +25,6 @@ "[json]": { "editor.formatOnSave": true }, - "[prisma]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "Prisma.prisma" - }, "javascript.format.enable": false, "typescript.format.enable": false, "cSpell.enableFiletypes": [ diff --git a/docs/docs/contributor/local-setup/docker-setup.mdx b/docs/docs/contributor/local-setup/docker-setup.mdx index 68bc67a92..371439636 100644 --- a/docs/docs/contributor/local-setup/docker-setup.mdx +++ b/docs/docs/contributor/local-setup/docker-setup.mdx @@ -94,7 +94,7 @@ Start the containers: make up ``` -Setup database, generate prisma client, run migrations, and seed: +Setup database, run migrations, and seed: ```bash make server-database-init ``` diff --git a/front/src/App.tsx b/front/src/App.tsx index c0b20d31c..d0c6f2e6d 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -12,13 +12,9 @@ import { CreateProfile } from '~/pages/auth/CreateProfile'; import { CreateWorkspace } from '~/pages/auth/CreateWorkspace'; import { SignInUp } from '~/pages/auth/SignInUp'; import { VerifyEffect } from '~/pages/auth/VerifyEffect'; -import { Companies } from '~/pages/companies/Companies'; -import { CompanyShow } from '~/pages/companies/CompanyShow'; import { ImpersonateEffect } from '~/pages/impersonate/ImpersonateEffect'; import { NotFound } from '~/pages/not-found/NotFound'; import { Opportunities } from '~/pages/opportunities/Opportunities'; -import { People } from '~/pages/people/People'; -import { PersonShow } from '~/pages/people/PersonShow'; import { SettingsNewObject } from '~/pages/settings/data-model/SettingsNewObject'; import { SettingsObjectDetail } from '~/pages/settings/data-model/SettingsObjectDetail'; import { SettingsObjectEdit } from '~/pages/settings/data-model/SettingsObjectEdit'; @@ -40,7 +36,6 @@ import { SettingsObjectNewFieldStep2 } from './pages/settings/data-model/Setting export const App = () => { const { pathname } = useLocation(); const pageTitle = getPageTitleFromPath(pathname); - return ( <> @@ -54,11 +49,7 @@ export const App = () => { } /> } /> } /> - } /> - } /> - } /> - } /> - } /> + } /> } /> } /> diff --git a/front/src/AppNavbar.tsx b/front/src/AppNavbar.tsx index fe95edf66..21c981377 100644 --- a/front/src/AppNavbar.tsx +++ b/front/src/AppNavbar.tsx @@ -59,8 +59,8 @@ export const AppNavbar = () => { diff --git a/front/src/effect-components/GotoHotkeysEffect.tsx b/front/src/effect-components/GotoHotkeysEffect.tsx index 4b79fc6ba..b6cecf7bd 100644 --- a/front/src/effect-components/GotoHotkeysEffect.tsx +++ b/front/src/effect-components/GotoHotkeysEffect.tsx @@ -1,9 +1,9 @@ import { useGoToHotkeys } from '@/ui/utilities/hotkey/hooks/useGoToHotkeys'; export const GotoHotkeysEffect = () => { - useGoToHotkeys('p', '/people'); - useGoToHotkeys('c', '/companies'); - useGoToHotkeys('o', '/opportunities'); + useGoToHotkeys('p', '/objects/people'); + useGoToHotkeys('c', '/objects/companies'); + useGoToHotkeys('o', '/objects/opportunities'); useGoToHotkeys('s', '/settings/profile'); useGoToHotkeys('t', '/tasks'); diff --git a/front/src/effect-components/PageChangeEffect.tsx b/front/src/effect-components/PageChangeEffect.tsx index d3e6daa53..244109a4e 100644 --- a/front/src/effect-components/PageChangeEffect.tsx +++ b/front/src/effect-components/PageChangeEffect.tsx @@ -2,7 +2,6 @@ import { useEffect, useState } from 'react'; import { matchPath, useLocation, useNavigate } from 'react-router-dom'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; -import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargetableEntity'; import { useEventTracker } from '@/analytics/hooks/useEventTracker'; import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; @@ -12,14 +11,11 @@ import { AppBasePath } from '@/types/AppBasePath'; import { AppPath } from '@/types/AppPath'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { SettingsPath } from '@/types/SettingsPath'; -import { IconCheckbox, IconNotes } from '@/ui/display/icon'; +import { IconCheckbox } from '@/ui/display/icon'; import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar'; import { TableHotkeyScope } from '@/ui/object/record-table/types/TableHotkeyScope'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; -import { - ActivityType, - useGetWorkspaceFromInviteHashLazyQuery, -} from '~/generated/graphql'; +import { useGetWorkspaceFromInviteHashLazyQuery } from '~/generated/graphql'; import { useIsMatchingLocation } from '../hooks/useIsMatchingLocation'; @@ -114,22 +110,14 @@ export const PageChangeEffect = () => { } switch (true) { - case isMatchingLocation(AppPath.CompaniesPage): { + case isMatchingLocation(AppPath.RecordTablePage): { setHotkeyScope(TableHotkeyScope.Table, { goto: true }); break; } - case isMatchingLocation(AppPath.PeoplePage): { - setHotkeyScope(TableHotkeyScope.Table, { goto: true }); - break; - } - case isMatchingLocation(AppPath.CompanyShowPage): { + case isMatchingLocation(AppPath.RecordShowPage): { setHotkeyScope(PageHotkeyScope.CompanyShowPage, { goto: true }); break; } - case isMatchingLocation(AppPath.PersonShowPage): { - setHotkeyScope(PageHotkeyScope.PersonShowPage, { goto: true }); - break; - } case isMatchingLocation(AppPath.OpportunitiesPage): { setHotkeyScope(PageHotkeyScope.OpportunitiesPage, { goto: true }); break; @@ -173,93 +161,16 @@ export const PageChangeEffect = () => { } setToIntitialCommandMenu(); - switch (true) { - case isMatchingLocation(AppPath.CompanyShowPage): { - const companyId = matchPath( - { path: '/companies/:id' }, - location.pathname, - )?.params.id; - const entity = !!companyId - ? { - id: companyId, - type: 'Company' as ActivityTargetableEntityType, - } - : undefined; - - addToCommandMenu([ - { - to: '', - label: 'Create Task', - type: CommandType.Create, - Icon: IconCheckbox, - onCommandClick: () => - openCreateActivity({ - type: 'Task', - targetableEntities: entity ? [entity] : undefined, - }), - }, - { - to: '', - label: 'Create Note', - type: CommandType.Create, - Icon: IconNotes, - onCommandClick: () => - openCreateActivity({ - type: ActivityType.Note, - targetableEntities: entity ? [entity] : undefined, - }), - }, - ]); - break; - } - case isMatchingLocation(AppPath.PersonShowPage): { - const personId = matchPath({ path: '/person/:id' }, location.pathname) - ?.params.id; - - const entity = !!personId - ? { id: personId, type: 'Person' as ActivityTargetableEntityType } - : undefined; - - addToCommandMenu([ - { - to: '', - label: 'Create Task', - type: CommandType.Create, - Icon: IconCheckbox, - onCommandClick: () => - openCreateActivity({ - type: ActivityType.Task, - targetableEntities: entity ? [entity] : undefined, - }), - }, - { - to: '', - label: 'Create Note', - type: CommandType.Create, - Icon: IconNotes, - onCommandClick: () => - openCreateActivity({ - type: ActivityType.Note, - targetableEntities: entity ? [entity] : undefined, - }), - }, - ]); - break; - } - default: - addToCommandMenu([ - { - to: '', - label: 'Create Task', - type: CommandType.Create, - Icon: IconCheckbox, - onCommandClick: () => - openCreateActivity({ type: ActivityType.Task }), - }, - ]); - break; - } + addToCommandMenu([ + { + to: '', + label: 'Create Task', + type: CommandType.Create, + Icon: IconCheckbox, + onCommandClick: () => openCreateActivity({ type: 'Task' }), + }, + ]); setTimeout(() => { eventTracker('pageview', { diff --git a/front/src/generated-metadata/graphql.ts b/front/src/generated-metadata/graphql.ts index 08c7365db..48d3fd79c 100644 --- a/front/src/generated-metadata/graphql.ts +++ b/front/src/generated-metadata/graphql.ts @@ -20,92 +20,8 @@ export type Scalars = { DateTime: { input: any; output: any; } /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSON: { input: any; output: any; } - /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ - JSONObject: { input: any; output: any; } }; -export type Activity = { - __typename?: 'Activity'; - activityTargets?: Maybe>; - assignee?: Maybe; - assigneeId?: Maybe; - attachments?: Maybe>; - author: User; - authorId: Scalars['String']['output']; - body?: Maybe; - comments?: Maybe>; - completedAt?: Maybe; - createdAt: Scalars['DateTime']['output']; - dueAt?: Maybe; - id: Scalars['ID']['output']; - reminderAt?: Maybe; - title?: Maybe; - type: ActivityType; - updatedAt: Scalars['DateTime']['output']; - workspaceMemberAssignee?: Maybe; - workspaceMemberAssigneeId?: Maybe; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export type ActivityTarget = { - __typename?: 'ActivityTarget'; - activity: Activity; - activityId: Scalars['String']['output']; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - person?: Maybe; - personId?: Maybe; - updatedAt: Scalars['DateTime']['output']; -}; - -export enum ActivityType { - Note = 'Note', - Task = 'Task' -} - -export type ApiKey = { - __typename?: 'ApiKey'; - createdAt: Scalars['DateTime']['output']; - expiresAt?: Maybe; - id: Scalars['ID']['output']; - name: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; -}; - -export type Attachment = { - __typename?: 'Attachment'; - activity?: Maybe; - activityId?: Maybe; - author: User; - authorId: Scalars['String']['output']; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']['output']; - fullPath: Scalars['String']['output']; - id: Scalars['ID']['output']; - name: Scalars['String']['output']; - person?: Maybe; - personId?: Maybe; - type: AttachmentType; - updatedAt: Scalars['DateTime']['output']; - workspace: Workspace; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export enum AttachmentType { - Archive = 'Archive', - Audio = 'Audio', - Image = 'Image', - Other = 'Other', - Spreadsheet = 'Spreadsheet', - TextDocument = 'TextDocument', - Video = 'Video' -} - export type AuthProviders = { __typename?: 'AuthProviders'; google: Scalars['Boolean']['output']; @@ -130,53 +46,8 @@ export type BooleanFieldComparison = { isNot?: InputMaybe; }; -export enum ColorScheme { - Dark = 'Dark', - Light = 'Light', - System = 'System' -} - -export type Comment = { - __typename?: 'Comment'; - activity?: Maybe; - activityId?: Maybe; - author: User; - authorId: Scalars['String']['output']; - body: Scalars['String']['output']; - commentThreadId?: Maybe; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - updatedAt: Scalars['DateTime']['output']; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export type Company = { - __typename?: 'Company'; - ActivityTarget?: Maybe>; - Attachment?: Maybe>; - Favorite?: Maybe>; - PipelineProgress?: Maybe>; - accountOwner?: Maybe; - accountOwnerId?: Maybe; - address: Scalars['String']['output']; - annualRecurringRevenue?: Maybe; - createdAt: Scalars['DateTime']['output']; - domainName: Scalars['String']['output']; - employees?: Maybe; - id: Scalars['ID']['output']; - idealCustomerProfile: Scalars['Boolean']['output']; - linkedinUrl?: Maybe; - name: Scalars['String']['output']; - people?: Maybe>; - updatedAt: Scalars['DateTime']['output']; - workspaceMemberAccountOwner?: Maybe; - workspaceMemberAccountOwnerId?: Maybe; - xUrl?: Maybe; -}; - export type CreateFieldInput = { - defaultValue?: InputMaybe; + defaultValue?: InputMaybe; description?: InputMaybe; icon?: InputMaybe; isNullable?: InputMaybe; @@ -223,177 +94,6 @@ export type CreateRelationInput = { toObjectMetadataId: Scalars['String']['input']; }; -export enum CurrencyCode { - Aed = 'AED', - Afn = 'AFN', - All = 'ALL', - Amd = 'AMD', - Ang = 'ANG', - Aoa = 'AOA', - Ars = 'ARS', - Aud = 'AUD', - Awg = 'AWG', - Azn = 'AZN', - Bam = 'BAM', - Bbd = 'BBD', - Bdt = 'BDT', - Bgn = 'BGN', - Bhd = 'BHD', - Bif = 'BIF', - Bmd = 'BMD', - Bnd = 'BND', - Bob = 'BOB', - Bov = 'BOV', - Brl = 'BRL', - Bsd = 'BSD', - Btn = 'BTN', - Bwp = 'BWP', - Byn = 'BYN', - Bzd = 'BZD', - Cad = 'CAD', - Cdf = 'CDF', - Chf = 'CHF', - Clf = 'CLF', - Clp = 'CLP', - Cny = 'CNY', - Cop = 'COP', - Cou = 'COU', - Crc = 'CRC', - Cuc = 'CUC', - Cup = 'CUP', - Cve = 'CVE', - Czk = 'CZK', - Djf = 'DJF', - Dkk = 'DKK', - Dop = 'DOP', - Dzd = 'DZD', - Egp = 'EGP', - Ern = 'ERN', - Etb = 'ETB', - Eur = 'EUR', - Fjd = 'FJD', - Fkp = 'FKP', - Gbp = 'GBP', - Gel = 'GEL', - Ghs = 'GHS', - Gip = 'GIP', - Gmd = 'GMD', - Gnf = 'GNF', - Gtq = 'GTQ', - Gyd = 'GYD', - Hkd = 'HKD', - Hnl = 'HNL', - Hrk = 'HRK', - Htg = 'HTG', - Huf = 'HUF', - Idr = 'IDR', - Ils = 'ILS', - Inr = 'INR', - Iqd = 'IQD', - Irr = 'IRR', - Isk = 'ISK', - Jmd = 'JMD', - Jod = 'JOD', - Jpy = 'JPY', - Kes = 'KES', - Kgs = 'KGS', - Khr = 'KHR', - Kmf = 'KMF', - Kpw = 'KPW', - Krw = 'KRW', - Kwd = 'KWD', - Kyd = 'KYD', - Kzt = 'KZT', - Lak = 'LAK', - Lbp = 'LBP', - Lkr = 'LKR', - Lrd = 'LRD', - Lsl = 'LSL', - Lyd = 'LYD', - Mad = 'MAD', - Mdl = 'MDL', - Mga = 'MGA', - Mkd = 'MKD', - Mmk = 'MMK', - Mnt = 'MNT', - Mop = 'MOP', - Mro = 'MRO', - Mru = 'MRU', - Mur = 'MUR', - Mvr = 'MVR', - Mwk = 'MWK', - Mxn = 'MXN', - Mxv = 'MXV', - Myr = 'MYR', - Mzn = 'MZN', - Nad = 'NAD', - Ngn = 'NGN', - Nio = 'NIO', - Nok = 'NOK', - Npr = 'NPR', - Nzd = 'NZD', - Omr = 'OMR', - Pab = 'PAB', - Pen = 'PEN', - Pgk = 'PGK', - Php = 'PHP', - Pkr = 'PKR', - Pln = 'PLN', - Pyg = 'PYG', - Qar = 'QAR', - Ron = 'RON', - Rsd = 'RSD', - Rub = 'RUB', - Rwf = 'RWF', - Sar = 'SAR', - Sbd = 'SBD', - Scr = 'SCR', - Sdd = 'SDD', - Sdg = 'SDG', - Sek = 'SEK', - Sgd = 'SGD', - Shp = 'SHP', - Sll = 'SLL', - Sos = 'SOS', - Srd = 'SRD', - Ssp = 'SSP', - Std = 'STD', - Stn = 'STN', - Svc = 'SVC', - Syp = 'SYP', - Szl = 'SZL', - Thb = 'THB', - Tjs = 'TJS', - Tmm = 'TMM', - Tmt = 'TMT', - Tnd = 'TND', - Top = 'TOP', - Try = 'TRY', - Ttd = 'TTD', - Twd = 'TWD', - Tzs = 'TZS', - Uah = 'UAH', - Ugx = 'UGX', - Usd = 'USD', - Uyu = 'UYU', - Uzs = 'UZS', - Vef = 'VEF', - Ves = 'VES', - Vnd = 'VND', - Vuv = 'VUV', - Wst = 'WST', - Xaf = 'XAF', - Xcd = 'XCD', - Xof = 'XOF', - Xpf = 'XPF', - Xsu = 'XSU', - Xua = 'XUA', - Yer = 'YER', - Zar = 'ZAR', - Zmw = 'ZMW', - Zwl = 'ZWL' -} - export type CursorPaging = { /** Paginate after opaque cursor */ after?: InputMaybe; @@ -420,19 +120,6 @@ export type DeleteOneRelationInput = { id: Scalars['ID']['input']; }; -export type Favorite = { - __typename?: 'Favorite'; - company?: Maybe; - companyId?: Maybe; - id: Scalars['ID']['output']; - person?: Maybe; - personId?: Maybe; - position: Scalars['Float']['output']; - workspaceId?: Maybe; - workspaceMember?: Maybe; - workspaceMemberId?: Maybe; -}; - export type FieldConnection = { __typename?: 'FieldConnection'; /** Array of edges. */ @@ -596,81 +283,6 @@ export type PageInfo = { startCursor?: Maybe; }; -export type Person = { - __typename?: 'Person'; - ActivityTarget?: Maybe>; - Attachment?: Maybe>; - Favorite?: Maybe>; - PipelineProgress?: Maybe>; - avatarUrl?: Maybe; - city?: Maybe; - company?: Maybe; - companyId?: Maybe; - contactPipelineProgresses?: Maybe>; - createdAt: Scalars['DateTime']['output']; - email?: Maybe; - firstName?: Maybe; - id: Scalars['ID']['output']; - jobTitle?: Maybe; - lastName?: Maybe; - linkedinUrl?: Maybe; - phone?: Maybe; - updatedAt: Scalars['DateTime']['output']; - xUrl?: Maybe; -}; - -export type Pipeline = { - __typename?: 'Pipeline'; - createdAt: Scalars['DateTime']['output']; - currency: CurrencyCode; - icon: Scalars['String']['output']; - id: Scalars['ID']['output']; - name: Scalars['String']['output']; - pipelineProgressableType: PipelineProgressableType; - pipelineProgresses?: Maybe>; - pipelineStages?: Maybe>; - updatedAt: Scalars['DateTime']['output']; -}; - -export type PipelineProgress = { - __typename?: 'PipelineProgress'; - amount?: Maybe; - closeDate?: Maybe; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - person?: Maybe; - personId?: Maybe; - pipeline: Pipeline; - pipelineId: Scalars['String']['output']; - pipelineStage: PipelineStage; - pipelineStageId: Scalars['String']['output']; - pointOfContact?: Maybe; - pointOfContactId?: Maybe; - probability?: Maybe; - updatedAt: Scalars['DateTime']['output']; -}; - -export enum PipelineProgressableType { - Company = 'Company', - Person = 'Person' -} - -export type PipelineStage = { - __typename?: 'PipelineStage'; - color: Scalars['String']['output']; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - name: Scalars['String']['output']; - pipeline: Pipeline; - pipelineId: Scalars['String']['output']; - pipelineProgresses?: Maybe>; - position?: Maybe; - type: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; -}; - export type Query = { __typename?: 'Query'; field: Field; @@ -713,6 +325,22 @@ export type QueryRelationsArgs = { paging?: CursorPaging; }; +export type RefreshToken = { + __typename?: 'RefreshToken'; + createdAt: Scalars['DateTime']['output']; + expiresAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + updatedAt: Scalars['DateTime']['output']; +}; + +export type RefreshTokenEdge = { + __typename?: 'RefreshTokenEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the RefreshToken */ + node: RefreshToken; +}; + export type RelationConnection = { __typename?: 'RelationConnection'; /** Array of edges. */ @@ -788,86 +416,49 @@ export type UpdateOneObjectInput = { export type User = { __typename?: 'User'; - assignedActivities?: Maybe>; - authoredActivities?: Maybe>; - authoredAttachments?: Maybe>; - avatarUrl?: Maybe; + avatarUrl: Scalars['String']['output']; canImpersonate: Scalars['Boolean']['output']; - comments?: Maybe>; - companies?: Maybe>; createdAt: Scalars['DateTime']['output']; - defaultWorkspaceId?: Maybe; - disabled: Scalars['Boolean']['output']; + deletedAt?: Maybe; + disabled?: Maybe; email: Scalars['String']['output']; emailVerified: Scalars['Boolean']['output']; - firstName?: Maybe; + firstName: Scalars['String']['output']; id: Scalars['ID']['output']; - lastName?: Maybe; + lastName: Scalars['String']['output']; lastSeen?: Maybe; locale: Scalars['String']['output']; - metadata?: Maybe; + passwordHash?: Maybe; phoneNumber?: Maybe; updatedAt: Scalars['DateTime']['output']; }; -export type UserSettings = { - __typename?: 'UserSettings'; - WorkspaceMember?: Maybe>; - colorScheme: ColorScheme; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - locale: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; -}; - -export type WebHook = { - __typename?: 'WebHook'; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - operation: Scalars['String']['output']; - targetUrl: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; +export type UserEdge = { + __typename?: 'UserEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the User */ + node: User; }; export type Workspace = { __typename?: 'Workspace'; - Attachment?: Maybe>; - activities?: Maybe>; - activityTargets?: Maybe>; - apiKeys?: Maybe>; - comments?: Maybe>; - companies?: Maybe>; createdAt: Scalars['DateTime']['output']; + deletedAt?: Maybe; displayName?: Maybe; domainName?: Maybe; id: Scalars['ID']['output']; inviteHash?: Maybe; logo?: Maybe; - people?: Maybe>; - pipelineProgresses?: Maybe>; - pipelineStages?: Maybe>; - pipelines?: Maybe>; updatedAt: Scalars['DateTime']['output']; - webHooks?: Maybe>; - workspaceMember?: Maybe>; }; -export type WorkspaceMember = { - __typename?: 'WorkspaceMember'; - Favorite?: Maybe>; - allowImpersonation: Scalars['Boolean']['output']; - assignedActivities?: Maybe>; - authoredActivities?: Maybe>; - authoredAttachments?: Maybe>; - comments?: Maybe>; - companies?: Maybe>; - createdAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - settings?: Maybe; - settingsId?: Maybe; - updatedAt: Scalars['DateTime']['output']; - userId: Scalars['String']['output']; - workspace: Workspace; +export type WorkspaceEdge = { + __typename?: 'WorkspaceEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the Workspace */ + node: Workspace; }; export type Field = { @@ -948,22 +539,6 @@ export type ObjectFilter = { or?: InputMaybe>; }; -export type RefreshTokenV2 = { - __typename?: 'refreshTokenV2'; - createdAt: Scalars['DateTime']['output']; - expiresAt: Scalars['DateTime']['output']; - id: Scalars['ID']['output']; - updatedAt: Scalars['DateTime']['output']; -}; - -export type RefreshTokenV2Edge = { - __typename?: 'refreshTokenV2Edge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the refreshTokenV2 */ - node: RefreshTokenV2; -}; - export type Relation = { __typename?: 'relation'; createdAt: Scalars['DateTime']['output']; @@ -986,54 +561,6 @@ export type RelationEdge = { node: Relation; }; -export type UserV2 = { - __typename?: 'userV2'; - avatarUrl: Scalars['String']['output']; - canImpersonate: Scalars['Boolean']['output']; - createdAt: Scalars['DateTime']['output']; - deletedAt?: Maybe; - disabled?: Maybe; - email: Scalars['String']['output']; - emailVerified: Scalars['Boolean']['output']; - firstName: Scalars['String']['output']; - id: Scalars['ID']['output']; - lastName: Scalars['String']['output']; - lastSeen?: Maybe; - locale: Scalars['String']['output']; - metadata?: Maybe; - passwordHash?: Maybe; - phoneNumber?: Maybe; - updatedAt: Scalars['DateTime']['output']; -}; - -export type UserV2Edge = { - __typename?: 'userV2Edge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the userV2 */ - node: UserV2; -}; - -export type WorkspaceV2 = { - __typename?: 'workspaceV2'; - createdAt: Scalars['DateTime']['output']; - deletedAt?: Maybe; - displayName?: Maybe; - domainName?: Maybe; - id: Scalars['ID']['output']; - inviteHash?: Maybe; - logo?: Maybe; - updatedAt: Scalars['DateTime']['output']; -}; - -export type WorkspaceV2Edge = { - __typename?: 'workspaceV2Edge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the workspaceV2 */ - node: WorkspaceV2; -}; - export type CreateOneObjectMetadataItemMutationVariables = Exact<{ input: CreateOneObjectInput; }>; diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index cd6980802..2139c4a91 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -16,615 +16,18 @@ export type Scalars = { ConnectionCursor: any; DateTime: string; JSON: any; - JSONObject: any; Upload: any; }; -export type Activity = { - __typename?: 'Activity'; - activityTargets?: Maybe>; - assignee?: Maybe; - assigneeId?: Maybe; - attachments?: Maybe>; - author: User; - authorId: Scalars['String']; - body?: Maybe; - comments?: Maybe>; - completedAt?: Maybe; - createdAt: Scalars['DateTime']; - dueAt?: Maybe; - id: Scalars['ID']; - reminderAt?: Maybe; - title?: Maybe; - type: ActivityType; - updatedAt: Scalars['DateTime']; - workspaceMemberAssignee?: Maybe; - workspaceMemberAssigneeId?: Maybe; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export type ActivityCreateInput = { - activityTargets?: InputMaybe; - assignee?: InputMaybe; - attachments?: InputMaybe; - author: UserCreateNestedOneWithoutAuthoredActivitiesInput; - body?: InputMaybe; - comments?: InputMaybe; - completedAt?: InputMaybe; - createdAt?: InputMaybe; - dueAt?: InputMaybe; - id?: InputMaybe; - reminderAt?: InputMaybe; - title?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAssignee?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; -}; - -export type ActivityCreateNestedOneWithoutActivityTargetsInput = { - connect?: InputMaybe; -}; - -export type ActivityCreateNestedOneWithoutCommentsInput = { - connect?: InputMaybe; -}; - -export type ActivityListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type ActivityOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type ActivityOrderByWithRelationInput = { - activityTargets?: InputMaybe; - assignee?: InputMaybe; - assigneeId?: InputMaybe; - attachments?: InputMaybe; - author?: InputMaybe; - authorId?: InputMaybe; - body?: InputMaybe; - comments?: InputMaybe; - completedAt?: InputMaybe; - createdAt?: InputMaybe; - dueAt?: InputMaybe; - id?: InputMaybe; - reminderAt?: InputMaybe; - title?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAssignee?: InputMaybe; - workspaceMemberAssigneeId?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; - workspaceMemberAuthorId?: InputMaybe; -}; - -export type ActivityRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum ActivityScalarFieldEnum { - AssigneeId = 'assigneeId', - AuthorId = 'authorId', - Body = 'body', - CompletedAt = 'completedAt', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - DueAt = 'dueAt', - Id = 'id', - ReminderAt = 'reminderAt', - Title = 'title', - Type = 'type', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId', - WorkspaceMemberAssigneeId = 'workspaceMemberAssigneeId', - WorkspaceMemberAuthorId = 'workspaceMemberAuthorId' -} - -export type ActivityTarget = { - __typename?: 'ActivityTarget'; - activity: Activity; - activityId: Scalars['String']; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - person?: Maybe; - personId?: Maybe; - updatedAt: Scalars['DateTime']; -}; - -export type ActivityTargetCreateManyActivityInput = { - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - personId?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateManyActivityInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - -export type ActivityTargetCreateManyCompanyInput = { - activityId: Scalars['String']; - createdAt?: InputMaybe; - id?: InputMaybe; - personId?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateManyCompanyInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - -export type ActivityTargetCreateManyPersonInput = { - activityId: Scalars['String']; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateManyPersonInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - -export type ActivityTargetCreateManyWorkspaceInput = { - activityId: Scalars['String']; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - personId?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateManyWorkspaceInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - -export type ActivityTargetCreateNestedManyWithoutActivityInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; -}; - -export type ActivityTargetCreateNestedManyWithoutCompanyInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; -}; - -export type ActivityTargetCreateNestedManyWithoutPersonInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; -}; - -export type ActivityTargetCreateOrConnectWithoutActivityInput = { - create: ActivityTargetCreateWithoutActivityInput; - where: ActivityTargetWhereUniqueInput; -}; - -export type ActivityTargetCreateOrConnectWithoutCompanyInput = { - create: ActivityTargetCreateWithoutCompanyInput; - where: ActivityTargetWhereUniqueInput; -}; - -export type ActivityTargetCreateOrConnectWithoutPersonInput = { - create: ActivityTargetCreateWithoutPersonInput; - where: ActivityTargetWhereUniqueInput; -}; - -export type ActivityTargetCreateOrConnectWithoutWorkspaceInput = { - create: ActivityTargetCreateWithoutWorkspaceInput; - where: ActivityTargetWhereUniqueInput; -}; - -export type ActivityTargetCreateWithoutActivityInput = { - company?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateWithoutCompanyInput = { - activity: ActivityCreateNestedOneWithoutActivityTargetsInput; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateWithoutPersonInput = { - activity: ActivityCreateNestedOneWithoutActivityTargetsInput; - company?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetCreateWithoutWorkspaceInput = { - activity: ActivityCreateNestedOneWithoutActivityTargetsInput; - company?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type ActivityTargetOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type ActivityTargetScalarWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - activityId?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - personId?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetUpdateManyWithoutActivityNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityTargetUpdateManyWithoutCompanyNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityTargetUpdateManyWithoutPersonNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityTargetUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityTargetWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - activity?: InputMaybe; - activityId?: InputMaybe; - company?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - personId?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ActivityTargetWhereUniqueInput = { - id?: InputMaybe; -}; - -export enum ActivityType { - Note = 'Note', - Task = 'Task' -} - -export type ActivityUpdateInput = { - activityTargets?: InputMaybe; - assignee?: InputMaybe; - attachments?: InputMaybe; - author?: InputMaybe; - body?: InputMaybe; - comments?: InputMaybe; - completedAt?: InputMaybe; - createdAt?: InputMaybe; - dueAt?: InputMaybe; - id?: InputMaybe; - reminderAt?: InputMaybe; - title?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAssignee?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; -}; - -export type ActivityUpdateManyWithoutAssigneeNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityUpdateManyWithoutAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityUpdateManyWithoutWorkspaceMemberAssigneeNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityUpdateManyWithoutWorkspaceMemberAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ActivityWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - activityTargets?: InputMaybe; - assignee?: InputMaybe; - assigneeId?: InputMaybe; - attachments?: InputMaybe; - author?: InputMaybe; - authorId?: InputMaybe; - body?: InputMaybe; - comments?: InputMaybe; - completedAt?: InputMaybe; - createdAt?: InputMaybe; - dueAt?: InputMaybe; - id?: InputMaybe; - reminderAt?: InputMaybe; - title?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAssignee?: InputMaybe; - workspaceMemberAssigneeId?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; - workspaceMemberAuthorId?: InputMaybe; -}; - -export type ActivityWhereUniqueInput = { - id?: InputMaybe; -}; - -export type AffectedRows = { - __typename?: 'AffectedRows'; - count: Scalars['Int']; -}; - export type Analytics = { __typename?: 'Analytics'; /** Boolean that confirms query was dispatched */ success: Scalars['Boolean']; }; -export type ApiKey = { - __typename?: 'ApiKey'; - createdAt: Scalars['DateTime']; - expiresAt?: Maybe; - id: Scalars['ID']; - name: Scalars['String']; - updatedAt: Scalars['DateTime']; -}; - -export type ApiKeyCreateInput = { - createdAt?: InputMaybe; - expiresAt?: InputMaybe; - id?: InputMaybe; - name: Scalars['String']; - updatedAt?: InputMaybe; -}; - -export type ApiKeyOrderByWithRelationInput = { - createdAt?: InputMaybe; - expiresAt?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export enum ApiKeyScalarFieldEnum { - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - ExpiresAt = 'expiresAt', - Id = 'id', - Name = 'name', - RevokedAt = 'revokedAt', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' -} - export type ApiKeyToken = { __typename?: 'ApiKeyToken'; - createdAt: Scalars['DateTime']; - expiresAt?: Maybe; - id: Scalars['ID']; - name: Scalars['String']; token: Scalars['String']; - updatedAt: Scalars['DateTime']; -}; - -export type ApiKeyUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type ApiKeyWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - createdAt?: InputMaybe; - expiresAt?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ApiKeyWhereUniqueInput = { - id?: InputMaybe; -}; - -export type Attachment = { - __typename?: 'Attachment'; - activity?: Maybe; - activityId?: Maybe; - author: User; - authorId: Scalars['String']; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']; - fullPath: Scalars['String']; - id: Scalars['ID']; - name: Scalars['String']; - person?: Maybe; - personId?: Maybe; - type: AttachmentType; - updatedAt: Scalars['DateTime']; - workspace: Workspace; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export type AttachmentCreateNestedManyWithoutActivityInput = { - connect?: InputMaybe>; -}; - -export type AttachmentCreateNestedManyWithoutCompanyInput = { - connect?: InputMaybe>; -}; - -export type AttachmentCreateNestedManyWithoutPersonInput = { - connect?: InputMaybe>; -}; - -export type AttachmentListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type AttachmentOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export enum AttachmentType { - Archive = 'Archive', - Audio = 'Audio', - Image = 'Image', - Other = 'Other', - Spreadsheet = 'Spreadsheet', - TextDocument = 'TextDocument', - Video = 'Video' -} - -export type AttachmentUpdateManyWithoutActivityNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentUpdateManyWithoutAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentUpdateManyWithoutCompanyNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentUpdateManyWithoutPersonNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentUpdateManyWithoutWorkspaceMemberAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type AttachmentWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - activity?: InputMaybe; - activityId?: InputMaybe; - author?: InputMaybe; - authorId?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - fullPath?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - personId?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; - workspaceMemberAuthorId?: InputMaybe; -}; - -export type AttachmentWhereUniqueInput = { - id?: InputMaybe; }; export type AuthProviders = { @@ -651,11 +54,6 @@ export type AuthTokens = { tokens: AuthTokenPair; }; -export type BoolFilter = { - equals?: InputMaybe; - not?: InputMaybe; -}; - export type BooleanFieldComparison = { is?: InputMaybe; isNot?: InputMaybe; @@ -670,488 +68,15 @@ export type ClientConfig = { telemetry: Telemetry; }; -export enum ColorScheme { - Dark = 'Dark', - Light = 'Light', - System = 'System' -} - -export type Comment = { - __typename?: 'Comment'; - activity?: Maybe; - activityId?: Maybe; - author: User; - authorId: Scalars['String']; - body: Scalars['String']; - commentThreadId?: Maybe; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - updatedAt: Scalars['DateTime']; - workspaceMemberAuthor?: Maybe; - workspaceMemberAuthorId?: Maybe; -}; - -export type CommentCreateInput = { - activity?: InputMaybe; - author: UserCreateNestedOneWithoutCommentsInput; - body: Scalars['String']; - commentThreadId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; -}; - -export type CommentCreateNestedManyWithoutActivityInput = { - connect?: InputMaybe>; -}; - -export type CommentListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type CommentOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type CommentUpdateManyWithoutActivityNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CommentUpdateManyWithoutAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CommentUpdateManyWithoutWorkspaceMemberAuthorNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CommentUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CommentWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - activity?: InputMaybe; - activityId?: InputMaybe; - author?: InputMaybe; - authorId?: InputMaybe; - body?: InputMaybe; - commentThreadId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAuthor?: InputMaybe; - workspaceMemberAuthorId?: InputMaybe; -}; - -export type CommentWhereUniqueInput = { - id?: InputMaybe; -}; - -export type Company = { - __typename?: 'Company'; - ActivityTarget?: Maybe>; - Attachment?: Maybe>; - Favorite?: Maybe>; - PipelineProgress?: Maybe>; - _activityCount: Scalars['Int']; - accountOwner?: Maybe; - accountOwnerId?: Maybe; - activities: Array; - address: Scalars['String']; - annualRecurringRevenue?: Maybe; - comments: Array; - createdAt: Scalars['DateTime']; - domainName: Scalars['String']; - employees?: Maybe; - id: Scalars['ID']; - idealCustomerProfile: Scalars['Boolean']; - linkedinUrl?: Maybe; - name: Scalars['String']; - people?: Maybe>; - updatedAt: Scalars['DateTime']; - workspaceMemberAccountOwner?: Maybe; - workspaceMemberAccountOwnerId?: Maybe; - xUrl?: Maybe; -}; - -export type CompanyCreateInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - accountOwner?: InputMaybe; - address: Scalars['String']; - annualRecurringRevenue?: InputMaybe; - createdAt?: InputMaybe; - domainName: Scalars['String']; - employees?: InputMaybe; - id?: InputMaybe; - idealCustomerProfile?: InputMaybe; - linkedinUrl?: InputMaybe; - name: Scalars['String']; - people?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAccountOwner?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type CompanyCreateManyInput = { - accountOwnerId?: InputMaybe; - address: Scalars['String']; - annualRecurringRevenue?: InputMaybe; - createdAt?: InputMaybe; - domainName: Scalars['String']; - employees?: InputMaybe; - id?: InputMaybe; - idealCustomerProfile?: InputMaybe; - linkedinUrl?: InputMaybe; - name: Scalars['String']; - updatedAt?: InputMaybe; - workspaceMemberAccountOwnerId?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type CompanyCreateNestedOneWithoutActivityTargetInput = { - connect?: InputMaybe; -}; - -export type CompanyCreateNestedOneWithoutPeopleInput = { - connect?: InputMaybe; -}; - -export type CompanyCreateNestedOneWithoutPipelineProgressInput = { - connect?: InputMaybe; -}; - -export type CompanyListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type CompanyOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type CompanyOrderByWithRelationInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - accountOwner?: InputMaybe; - accountOwnerId?: InputMaybe; - address?: InputMaybe; - annualRecurringRevenue?: InputMaybe; - createdAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - idealCustomerProfile?: InputMaybe; - linkedinUrl?: InputMaybe; - name?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAccountOwner?: InputMaybe; - workspaceMemberAccountOwnerId?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type CompanyRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum CompanyScalarFieldEnum { - AccountOwnerId = 'accountOwnerId', - Address = 'address', - AnnualRecurringRevenue = 'annualRecurringRevenue', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - DomainName = 'domainName', - Employees = 'employees', - Id = 'id', - IdealCustomerProfile = 'idealCustomerProfile', - LinkedinUrl = 'linkedinUrl', - Name = 'name', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId', - WorkspaceMemberAccountOwnerId = 'workspaceMemberAccountOwnerId', - XUrl = 'xUrl' -} - -export type CompanyUpdateInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - accountOwner?: InputMaybe; - address?: InputMaybe; - annualRecurringRevenue?: InputMaybe; - createdAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - idealCustomerProfile?: InputMaybe; - linkedinUrl?: InputMaybe; - name?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAccountOwner?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type CompanyUpdateManyWithoutAccountOwnerNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CompanyUpdateManyWithoutWorkspaceMemberAccountOwnerNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CompanyUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type CompanyUpdateOneWithoutPeopleNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type CompanyUpdateOneWithoutPipelineProgressNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type CompanyWhereInput = { - AND?: InputMaybe>; - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - NOT?: InputMaybe>; - OR?: InputMaybe>; - PipelineProgress?: InputMaybe; - accountOwner?: InputMaybe; - accountOwnerId?: InputMaybe; - address?: InputMaybe; - annualRecurringRevenue?: InputMaybe; - createdAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - idealCustomerProfile?: InputMaybe; - linkedinUrl?: InputMaybe; - name?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; - workspaceMemberAccountOwner?: InputMaybe; - workspaceMemberAccountOwnerId?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type CompanyWhereUniqueInput = { - id?: InputMaybe; -}; - -export type CreateOneRefreshTokenV2Input = { +export type CreateOneRefreshTokenInput = { /** The record to create */ - refreshTokenV2: CreateRefreshTokenInput; + refreshToken: CreateRefreshTokenInput; }; export type CreateRefreshTokenInput = { expiresAt: Scalars['DateTime']; }; -export enum CurrencyCode { - Aed = 'AED', - Afn = 'AFN', - All = 'ALL', - Amd = 'AMD', - Ang = 'ANG', - Aoa = 'AOA', - Ars = 'ARS', - Aud = 'AUD', - Awg = 'AWG', - Azn = 'AZN', - Bam = 'BAM', - Bbd = 'BBD', - Bdt = 'BDT', - Bgn = 'BGN', - Bhd = 'BHD', - Bif = 'BIF', - Bmd = 'BMD', - Bnd = 'BND', - Bob = 'BOB', - Bov = 'BOV', - Brl = 'BRL', - Bsd = 'BSD', - Btn = 'BTN', - Bwp = 'BWP', - Byn = 'BYN', - Bzd = 'BZD', - Cad = 'CAD', - Cdf = 'CDF', - Chf = 'CHF', - Clf = 'CLF', - Clp = 'CLP', - Cny = 'CNY', - Cop = 'COP', - Cou = 'COU', - Crc = 'CRC', - Cuc = 'CUC', - Cup = 'CUP', - Cve = 'CVE', - Czk = 'CZK', - Djf = 'DJF', - Dkk = 'DKK', - Dop = 'DOP', - Dzd = 'DZD', - Egp = 'EGP', - Ern = 'ERN', - Etb = 'ETB', - Eur = 'EUR', - Fjd = 'FJD', - Fkp = 'FKP', - Gbp = 'GBP', - Gel = 'GEL', - Ghs = 'GHS', - Gip = 'GIP', - Gmd = 'GMD', - Gnf = 'GNF', - Gtq = 'GTQ', - Gyd = 'GYD', - Hkd = 'HKD', - Hnl = 'HNL', - Hrk = 'HRK', - Htg = 'HTG', - Huf = 'HUF', - Idr = 'IDR', - Ils = 'ILS', - Inr = 'INR', - Iqd = 'IQD', - Irr = 'IRR', - Isk = 'ISK', - Jmd = 'JMD', - Jod = 'JOD', - Jpy = 'JPY', - Kes = 'KES', - Kgs = 'KGS', - Khr = 'KHR', - Kmf = 'KMF', - Kpw = 'KPW', - Krw = 'KRW', - Kwd = 'KWD', - Kyd = 'KYD', - Kzt = 'KZT', - Lak = 'LAK', - Lbp = 'LBP', - Lkr = 'LKR', - Lrd = 'LRD', - Lsl = 'LSL', - Lyd = 'LYD', - Mad = 'MAD', - Mdl = 'MDL', - Mga = 'MGA', - Mkd = 'MKD', - Mmk = 'MMK', - Mnt = 'MNT', - Mop = 'MOP', - Mro = 'MRO', - Mru = 'MRU', - Mur = 'MUR', - Mvr = 'MVR', - Mwk = 'MWK', - Mxn = 'MXN', - Mxv = 'MXV', - Myr = 'MYR', - Mzn = 'MZN', - Nad = 'NAD', - Ngn = 'NGN', - Nio = 'NIO', - Nok = 'NOK', - Npr = 'NPR', - Nzd = 'NZD', - Omr = 'OMR', - Pab = 'PAB', - Pen = 'PEN', - Pgk = 'PGK', - Php = 'PHP', - Pkr = 'PKR', - Pln = 'PLN', - Pyg = 'PYG', - Qar = 'QAR', - Ron = 'RON', - Rsd = 'RSD', - Rub = 'RUB', - Rwf = 'RWF', - Sar = 'SAR', - Sbd = 'SBD', - Scr = 'SCR', - Sdd = 'SDD', - Sdg = 'SDG', - Sek = 'SEK', - Sgd = 'SGD', - Shp = 'SHP', - Sll = 'SLL', - Sos = 'SOS', - Srd = 'SRD', - Ssp = 'SSP', - Std = 'STD', - Stn = 'STN', - Svc = 'SVC', - Syp = 'SYP', - Szl = 'SZL', - Thb = 'THB', - Tjs = 'TJS', - Tmm = 'TMM', - Tmt = 'TMT', - Tnd = 'TND', - Top = 'TOP', - Try = 'TRY', - Ttd = 'TTD', - Twd = 'TWD', - Tzs = 'TZS', - Uah = 'UAH', - Ugx = 'UGX', - Usd = 'USD', - Uyu = 'UYU', - Uzs = 'UZS', - Vef = 'VEF', - Ves = 'VES', - Vnd = 'VND', - Vuv = 'VUV', - Wst = 'WST', - Xaf = 'XAF', - Xcd = 'XCD', - Xof = 'XOF', - Xpf = 'XPF', - Xsu = 'XSU', - Xua = 'XUA', - Yer = 'YER', - Zar = 'ZAR', - Zmw = 'ZMW', - Zwl = 'ZWL' -} - export type CursorPaging = { /** Paginate after opaque cursor */ after?: InputMaybe; @@ -1163,144 +88,6 @@ export type CursorPaging = { last?: InputMaybe; }; -export type DateTimeFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type DateTimeNullableFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type EnumActivityTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type EnumAttachmentTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type EnumColorSchemeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type EnumCurrencyCodeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type EnumPipelineProgressableTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type Favorite = { - __typename?: 'Favorite'; - company?: Maybe; - companyId?: Maybe; - id: Scalars['ID']; - person?: Maybe; - personId?: Maybe; - position: Scalars['Float']; - workspaceId?: Maybe; - workspaceMember?: Maybe; - workspaceMemberId?: Maybe; -}; - -export type FavoriteCreateNestedManyWithoutCompanyInput = { - connect?: InputMaybe>; -}; - -export type FavoriteCreateNestedManyWithoutPersonInput = { - connect?: InputMaybe>; -}; - -export type FavoriteListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type FavoriteMutationForCompanyArgs = { - companyId: Scalars['String']; - position: Scalars['Float']; -}; - -export type FavoriteMutationForPersonArgs = { - personId: Scalars['String']; - position: Scalars['Float']; -}; - -export type FavoriteOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type FavoriteUpdateInput = { - id?: InputMaybe; - position?: InputMaybe; - workspaceId?: InputMaybe; -}; - -export type FavoriteUpdateManyWithoutCompanyNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type FavoriteUpdateManyWithoutPersonNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type FavoriteUpdateManyWithoutWorkspaceMemberNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type FavoriteWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - companyId?: InputMaybe; - id?: InputMaybe; - personId?: InputMaybe; - position?: InputMaybe; - workspaceId?: InputMaybe; - workspaceMemberId?: InputMaybe; -}; - -export type FavoriteWhereUniqueInput = { - id?: InputMaybe; -}; - export type FieldConnection = { __typename?: 'FieldConnection'; /** Array of edges. */ @@ -1353,17 +140,6 @@ export enum FileFolder { WorkspaceLogo = 'WorkspaceLogo' } -export type FloatFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - export type IdFilterComparison = { eq?: InputMaybe; gt?: InputMaybe; @@ -1381,33 +157,6 @@ export type IdFilterComparison = { notLike?: InputMaybe; }; -export type IntNullableFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type JsonNullableFilter = { - array_contains?: InputMaybe; - array_ends_with?: InputMaybe; - array_starts_with?: InputMaybe; - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - path?: InputMaybe>; - string_contains?: InputMaybe; - string_ends_with?: InputMaybe; - string_starts_with?: InputMaybe; -}; - export type LoginToken = { __typename?: 'LoginToken'; loginToken: AuthToken; @@ -1415,78 +164,32 @@ export type LoginToken = { export type Mutation = { __typename?: 'Mutation'; - UpdateOneWorkspaceMember: WorkspaceMember; - allowImpersonation: WorkspaceMember; challenge: LoginToken; createEvent: Analytics; - createFavoriteForCompany: Favorite; - createFavoriteForPerson: Favorite; - createManyCompany: AffectedRows; - createManyPerson: AffectedRows; - createOneActivity: Activity; - createOneApiKey: ApiKeyToken; - createOneComment: Comment; - createOneCompany: Company; createOneField: Field; createOneObject: Object; - createOnePerson: Person; - createOnePipelineProgress: PipelineProgress; - createOnePipelineStage: PipelineStage; - createOneRefreshTokenV2: RefreshTokenV2; + createOneRefreshToken: RefreshToken; createOneRelation: Relation; - createOneWebHook: WebHook; deleteCurrentWorkspace: Workspace; - deleteFavorite: Favorite; - deleteManyActivities: AffectedRows; - deleteManyCompany: AffectedRows; - deleteManyPerson: AffectedRows; - deleteManyPipelineProgress: AffectedRows; deleteOneField: FieldDeleteResponse; deleteOneObject: ObjectDeleteResponse; - deleteOnePipelineStage: PipelineStage; deleteOneRelation: RelationDeleteResponse; - deleteOneWebHook: WebHook; - deleteUserAccount: User; - deleteUserV2: UserV2; - deleteWorkspaceMember: WorkspaceMember; - generateApiKeyV2Token: ApiKeyToken; + deleteUser: User; + generateApiKeyToken: ApiKeyToken; impersonate: Verify; renewToken: AuthTokens; - revokeOneApiKey: ApiKey; signUp: LoginToken; - updateOneActivity: Activity; - updateOneCompany?: Maybe; - updateOneFavorites: Favorite; updateOneField: Field; updateOneObject: Object; - updateOnePerson?: Maybe; - updateOnePipelineProgress?: Maybe; - updateOnePipelineStage?: Maybe; - updateOneWorkspaceV2: WorkspaceV2; - updateUser: User; updateWorkspace: Workspace; - uploadAttachment: Scalars['String']; uploadFile: Scalars['String']; uploadImage: Scalars['String']; - uploadPersonPicture: Scalars['String']; uploadProfilePicture: Scalars['String']; - uploadProfilePictureV2: Scalars['String']; uploadWorkspaceLogo: Scalars['String']; verify: Verify; }; -export type MutationUpdateOneWorkspaceMemberArgs = { - data: WorkspaceMemberUpdateInput; - where: WorkspaceMemberWhereUniqueInput; -}; - - -export type MutationAllowImpersonationArgs = { - allowImpersonation: Scalars['Boolean']; -}; - - export type MutationChallengeArgs = { email: Scalars['String']; password: Scalars['String']; @@ -1499,115 +202,14 @@ export type MutationCreateEventArgs = { }; -export type MutationCreateFavoriteForCompanyArgs = { - data: FavoriteMutationForCompanyArgs; +export type MutationCreateOneRefreshTokenArgs = { + input: CreateOneRefreshTokenInput; }; -export type MutationCreateFavoriteForPersonArgs = { - data: FavoriteMutationForPersonArgs; -}; - - -export type MutationCreateManyCompanyArgs = { - data: Array; - skipDuplicates?: InputMaybe; -}; - - -export type MutationCreateManyPersonArgs = { - data: Array; - skipDuplicates?: InputMaybe; -}; - - -export type MutationCreateOneActivityArgs = { - data: ActivityCreateInput; -}; - - -export type MutationCreateOneApiKeyArgs = { - data: ApiKeyCreateInput; -}; - - -export type MutationCreateOneCommentArgs = { - data: CommentCreateInput; -}; - - -export type MutationCreateOneCompanyArgs = { - data: CompanyCreateInput; -}; - - -export type MutationCreateOnePersonArgs = { - data: PersonCreateInput; -}; - - -export type MutationCreateOnePipelineProgressArgs = { - data: PipelineProgressCreateInput; -}; - - -export type MutationCreateOnePipelineStageArgs = { - data: PipelineStageCreateInput; -}; - - -export type MutationCreateOneRefreshTokenV2Args = { - input: CreateOneRefreshTokenV2Input; -}; - - -export type MutationCreateOneWebHookArgs = { - data: WebHookCreateInput; -}; - - -export type MutationDeleteFavoriteArgs = { - where: FavoriteWhereInput; -}; - - -export type MutationDeleteManyActivitiesArgs = { - where?: InputMaybe; -}; - - -export type MutationDeleteManyCompanyArgs = { - where?: InputMaybe; -}; - - -export type MutationDeleteManyPersonArgs = { - where?: InputMaybe; -}; - - -export type MutationDeleteManyPipelineProgressArgs = { - where?: InputMaybe; -}; - - -export type MutationDeleteOnePipelineStageArgs = { - where: PipelineStageWhereUniqueInput; -}; - - -export type MutationDeleteOneWebHookArgs = { - where: WebHookWhereUniqueInput; -}; - - -export type MutationDeleteWorkspaceMemberArgs = { - where: WorkspaceMemberWhereUniqueInput; -}; - - -export type MutationGenerateApiKeyV2TokenArgs = { - data: ApiKeyCreateInput; +export type MutationGenerateApiKeyTokenArgs = { + apiKeyId: Scalars['String']; + expiresAt: Scalars['String']; }; @@ -1621,11 +223,6 @@ export type MutationRenewTokenArgs = { }; -export type MutationRevokeOneApiKeyArgs = { - where: ApiKeyWhereUniqueInput; -}; - - export type MutationSignUpArgs = { email: Scalars['String']; password: Scalars['String']; @@ -1633,63 +230,8 @@ export type MutationSignUpArgs = { }; -export type MutationUpdateOneActivityArgs = { - data: ActivityUpdateInput; - where: ActivityWhereUniqueInput; -}; - - -export type MutationUpdateOneCompanyArgs = { - data: CompanyUpdateInput; - where: CompanyWhereUniqueInput; -}; - - -export type MutationUpdateOneFavoritesArgs = { - data: FavoriteUpdateInput; - where: FavoriteWhereUniqueInput; -}; - - -export type MutationUpdateOnePersonArgs = { - data: PersonUpdateInput; - where: PersonWhereUniqueInput; -}; - - -export type MutationUpdateOnePipelineProgressArgs = { - data: PipelineProgressUpdateInput; - where: PipelineProgressWhereUniqueInput; -}; - - -export type MutationUpdateOnePipelineStageArgs = { - data: PipelineStageUpdateInput; - where: PipelineStageWhereUniqueInput; -}; - - -export type MutationUpdateOneWorkspaceV2Args = { - input: UpdateOneWorkspaceV2Input; -}; - - -export type MutationUpdateUserArgs = { - data: UserUpdateInput; - where: UserWhereUniqueInput; -}; - - export type MutationUpdateWorkspaceArgs = { - data: WorkspaceUpdateInput; -}; - - -export type MutationUploadAttachmentArgs = { - activityId: Scalars['String']; - companyId: Scalars['String']; - file: Scalars['Upload']; - personId: Scalars['String']; + data: UpdateWorkspaceInput; }; @@ -1705,22 +247,11 @@ export type MutationUploadImageArgs = { }; -export type MutationUploadPersonPictureArgs = { - file: Scalars['Upload']; - id: Scalars['String']; -}; - - export type MutationUploadProfilePictureArgs = { file: Scalars['Upload']; }; -export type MutationUploadProfilePictureV2Args = { - file: Scalars['Upload']; -}; - - export type MutationUploadWorkspaceLogoArgs = { file: Scalars['Upload']; }; @@ -1730,118 +261,6 @@ export type MutationVerifyArgs = { loginToken: Scalars['String']; }; -export type NestedBoolFilter = { - equals?: InputMaybe; - not?: InputMaybe; -}; - -export type NestedDateTimeFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedDateTimeNullableFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedEnumActivityTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedEnumAttachmentTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedEnumColorSchemeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedEnumCurrencyCodeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedEnumPipelineProgressableTypeFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedFloatFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedIntNullableFilter = { - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; -}; - -export type NestedStringFilter = { - contains?: InputMaybe; - endsWith?: InputMaybe; - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; - startsWith?: InputMaybe; -}; - -export type NestedStringNullableFilter = { - contains?: InputMaybe; - endsWith?: InputMaybe; - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; - startsWith?: InputMaybe; -}; - export type ObjectConnection = { __typename?: 'ObjectConnection'; /** Array of edges. */ @@ -1891,609 +310,20 @@ export type PageInfo = { startCursor?: Maybe; }; -export type Person = { - __typename?: 'Person'; - ActivityTarget?: Maybe>; - Attachment?: Maybe>; - Favorite?: Maybe>; - PipelineProgress?: Maybe>; - _activityCount: Scalars['Int']; - activities: Array; - avatarUrl?: Maybe; - city?: Maybe; - comments: Array; - company?: Maybe; - companyId?: Maybe; - contactPipelineProgresses?: Maybe>; - createdAt: Scalars['DateTime']; - displayName: Scalars['String']; - email?: Maybe; - firstName?: Maybe; - id: Scalars['ID']; - jobTitle?: Maybe; - lastName?: Maybe; - linkedinUrl?: Maybe; - phone?: Maybe; - updatedAt: Scalars['DateTime']; - xUrl?: Maybe; -}; - -export type PersonCreateInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - avatarUrl?: InputMaybe; - city?: InputMaybe; - company?: InputMaybe; - contactPipelineProgresses?: InputMaybe; - createdAt?: InputMaybe; - email?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - jobTitle?: InputMaybe; - lastName?: InputMaybe; - linkedinUrl?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type PersonCreateManyInput = { - avatarUrl?: InputMaybe; - city?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - email?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - jobTitle?: InputMaybe; - lastName?: InputMaybe; - linkedinUrl?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type PersonCreateNestedManyWithoutCompanyInput = { - connect?: InputMaybe>; -}; - -export type PersonCreateNestedOneWithoutActivityTargetInput = { - connect?: InputMaybe; -}; - -export type PersonCreateNestedOneWithoutContactPipelineProgressesInput = { - connect?: InputMaybe; -}; - -export type PersonCreateNestedOneWithoutPipelineProgressInput = { - connect?: InputMaybe; -}; - -export type PersonListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type PersonOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type PersonOrderByWithRelationInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - avatarUrl?: InputMaybe; - city?: InputMaybe; - company?: InputMaybe; - companyId?: InputMaybe; - contactPipelineProgresses?: InputMaybe; - createdAt?: InputMaybe; - email?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - jobTitle?: InputMaybe; - lastName?: InputMaybe; - linkedinUrl?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type PersonRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum PersonScalarFieldEnum { - AvatarUrl = 'avatarUrl', - City = 'city', - CompanyId = 'companyId', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - Email = 'email', - FirstName = 'firstName', - Id = 'id', - JobTitle = 'jobTitle', - LastName = 'lastName', - LinkedinUrl = 'linkedinUrl', - Phone = 'phone', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId', - XUrl = 'xUrl' -} - -export type PersonUpdateInput = { - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - PipelineProgress?: InputMaybe; - avatarUrl?: InputMaybe; - city?: InputMaybe; - company?: InputMaybe; - contactPipelineProgresses?: InputMaybe; - createdAt?: InputMaybe; - email?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - jobTitle?: InputMaybe; - lastName?: InputMaybe; - linkedinUrl?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type PersonUpdateManyWithoutCompanyNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PersonUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PersonUpdateOneWithoutContactPipelineProgressesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type PersonUpdateOneWithoutPipelineProgressNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type PersonWhereInput = { - AND?: InputMaybe>; - ActivityTarget?: InputMaybe; - Attachment?: InputMaybe; - Favorite?: InputMaybe; - NOT?: InputMaybe>; - OR?: InputMaybe>; - PipelineProgress?: InputMaybe; - avatarUrl?: InputMaybe; - city?: InputMaybe; - company?: InputMaybe; - companyId?: InputMaybe; - contactPipelineProgresses?: InputMaybe; - createdAt?: InputMaybe; - email?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - jobTitle?: InputMaybe; - lastName?: InputMaybe; - linkedinUrl?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; - xUrl?: InputMaybe; -}; - -export type PersonWhereUniqueInput = { - id?: InputMaybe; -}; - -export type Pipeline = { - __typename?: 'Pipeline'; - createdAt: Scalars['DateTime']; - currency: CurrencyCode; - icon: Scalars['String']; - id: Scalars['ID']; - name: Scalars['String']; - pipelineProgressableType: PipelineProgressableType; - pipelineProgresses?: Maybe>; - pipelineStages?: Maybe>; - updatedAt: Scalars['DateTime']; -}; - -export type PipelineCreateNestedOneWithoutPipelineProgressesInput = { - connect?: InputMaybe; -}; - -export type PipelineCreateNestedOneWithoutPipelineStagesInput = { - connect?: InputMaybe; -}; - -export type PipelineOrderByWithRelationInput = { - createdAt?: InputMaybe; - currency?: InputMaybe; - icon?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - pipelineProgressableType?: InputMaybe; - pipelineProgresses?: InputMaybe; - pipelineStages?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineProgress = { - __typename?: 'PipelineProgress'; - amount?: Maybe; - closeDate?: Maybe; - company?: Maybe; - companyId?: Maybe; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - person?: Maybe; - personId?: Maybe; - pipeline: Pipeline; - pipelineId: Scalars['String']; - pipelineStage: PipelineStage; - pipelineStageId: Scalars['String']; - pointOfContact?: Maybe; - pointOfContactId?: Maybe; - probability?: Maybe; - updatedAt: Scalars['DateTime']; -}; - -export type PipelineProgressCreateInput = { - amount?: InputMaybe; - closeDate?: InputMaybe; - company?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - pipeline: PipelineCreateNestedOneWithoutPipelineProgressesInput; - pipelineStage: PipelineStageCreateNestedOneWithoutPipelineProgressesInput; - pointOfContact?: InputMaybe; - probability?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineProgressCreateNestedManyWithoutCompanyInput = { - connect?: InputMaybe>; -}; - -export type PipelineProgressCreateNestedManyWithoutPersonInput = { - connect?: InputMaybe>; -}; - -export type PipelineProgressCreateNestedManyWithoutPipelineStageInput = { - connect?: InputMaybe>; -}; - -export type PipelineProgressCreateNestedManyWithoutPointOfContactInput = { - connect?: InputMaybe>; -}; - -export type PipelineProgressListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type PipelineProgressOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type PipelineProgressOrderByWithRelationInput = { - amount?: InputMaybe; - closeDate?: InputMaybe; - company?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - personId?: InputMaybe; - pipeline?: InputMaybe; - pipelineId?: InputMaybe; - pipelineStage?: InputMaybe; - pipelineStageId?: InputMaybe; - pointOfContact?: InputMaybe; - pointOfContactId?: InputMaybe; - probability?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export enum PipelineProgressScalarFieldEnum { - Amount = 'amount', - CloseDate = 'closeDate', - CompanyId = 'companyId', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - Id = 'id', - PersonId = 'personId', - PipelineId = 'pipelineId', - PipelineStageId = 'pipelineStageId', - PointOfContactId = 'pointOfContactId', - Probability = 'probability', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' -} - -export type PipelineProgressUpdateInput = { - amount?: InputMaybe; - closeDate?: InputMaybe; - company?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - pipeline?: InputMaybe; - pipelineStage?: InputMaybe; - pointOfContact?: InputMaybe; - probability?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineProgressUpdateManyWithoutCompanyNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineProgressUpdateManyWithoutPersonNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineProgressUpdateManyWithoutPipelineStageNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineProgressUpdateManyWithoutPointOfContactNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineProgressUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineProgressWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - amount?: InputMaybe; - closeDate?: InputMaybe; - company?: InputMaybe; - companyId?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - person?: InputMaybe; - personId?: InputMaybe; - pipeline?: InputMaybe; - pipelineId?: InputMaybe; - pipelineStage?: InputMaybe; - pipelineStageId?: InputMaybe; - pointOfContact?: InputMaybe; - pointOfContactId?: InputMaybe; - probability?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineProgressWhereUniqueInput = { - id?: InputMaybe; -}; - -export enum PipelineProgressableType { - Company = 'Company', - Person = 'Person' -} - -export type PipelineRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum PipelineScalarFieldEnum { - CreatedAt = 'createdAt', - Currency = 'currency', - DeletedAt = 'deletedAt', - Icon = 'icon', - Id = 'id', - Name = 'name', - PipelineProgressableType = 'pipelineProgressableType', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' -} - -export type PipelineStage = { - __typename?: 'PipelineStage'; - color: Scalars['String']; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - name: Scalars['String']; - pipeline: Pipeline; - pipelineId: Scalars['String']; - pipelineProgresses?: Maybe>; - position?: Maybe; - type: Scalars['String']; - updatedAt: Scalars['DateTime']; -}; - -export type PipelineStageCreateInput = { - color: Scalars['String']; - createdAt?: InputMaybe; - id?: InputMaybe; - name: Scalars['String']; - pipeline: PipelineCreateNestedOneWithoutPipelineStagesInput; - pipelineProgresses?: InputMaybe; - position?: InputMaybe; - type: Scalars['String']; - updatedAt?: InputMaybe; -}; - -export type PipelineStageCreateNestedOneWithoutPipelineProgressesInput = { - connect?: InputMaybe; -}; - -export type PipelineStageListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type PipelineStageOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type PipelineStageOrderByWithRelationInput = { - color?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - pipeline?: InputMaybe; - pipelineId?: InputMaybe; - pipelineProgresses?: InputMaybe; - position?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineStageRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum PipelineStageScalarFieldEnum { - Color = 'color', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - Id = 'id', - Name = 'name', - PipelineId = 'pipelineId', - Position = 'position', - Type = 'type', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' -} - -export type PipelineStageUpdateInput = { - color?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - pipeline?: InputMaybe; - pipelineProgresses?: InputMaybe; - position?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineStageUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineStageUpdateOneRequiredWithoutPipelineProgressesNestedInput = { - connect?: InputMaybe; -}; - -export type PipelineStageWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - color?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - pipeline?: InputMaybe; - pipelineId?: InputMaybe; - pipelineProgresses?: InputMaybe; - position?: InputMaybe; - type?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineStageWhereUniqueInput = { - id?: InputMaybe; -}; - -export type PipelineUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type PipelineUpdateOneRequiredWithoutPipelineProgressesNestedInput = { - connect?: InputMaybe; -}; - -export type PipelineUpdateOneRequiredWithoutPipelineStagesNestedInput = { - connect?: InputMaybe; -}; - -export type PipelineWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - createdAt?: InputMaybe; - currency?: InputMaybe; - icon?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - pipelineProgressableType?: InputMaybe; - pipelineProgresses?: InputMaybe; - pipelineStages?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type PipelineWhereUniqueInput = { - id?: InputMaybe; -}; - export type Query = { __typename?: 'Query'; checkUserExists: UserExists; checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; clientConfig: ClientConfig; currentUser: User; - currentUserV2: UserV2; currentWorkspace: Workspace; field: Field; fields: FieldConnection; - findFavorites: Array; - findManyActivities: Array; - findManyApiKey: Array; - findManyCompany: Array; - findManyPerson: Array; - findManyPipeline: Array; - findManyPipelineProgress: Array; - findManyPipelineStage: Array; - findManyUser: Array; - findManyWebHook: Array; - findManyWorkspaceMember: Array; - findUniqueCompany: Company; - findUniquePerson: Person; findWorkspaceFromInviteHash: Workspace; object: Object; objects: ObjectConnection; relation: Relation; relations: RelationConnection; - workspaceV2: WorkspaceV2; - workspaceV2s: WorkspaceV2Connection; }; @@ -2507,137 +337,26 @@ export type QueryCheckWorkspaceInviteHashIsValidArgs = { }; -export type QueryFindManyActivitiesArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyApiKeyArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyCompanyArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyPersonArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyPipelineArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyPipelineProgressArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyPipelineStageArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyUserArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyWebHookArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindManyWorkspaceMemberArgs = { - cursor?: InputMaybe; - distinct?: InputMaybe>; - orderBy?: InputMaybe>; - skip?: InputMaybe; - take?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryFindUniqueCompanyArgs = { - where: CompanyWhereUniqueInput; -}; - - -export type QueryFindUniquePersonArgs = { - id: Scalars['String']; -}; - - export type QueryFindWorkspaceFromInviteHashArgs = { inviteHash: Scalars['String']; }; - -export type QueryWorkspaceV2Args = { +export type RefreshToken = { + __typename?: 'RefreshToken'; + createdAt: Scalars['DateTime']; + expiresAt: Scalars['DateTime']; id: Scalars['ID']; + updatedAt: Scalars['DateTime']; }; - -export type QueryWorkspaceV2sArgs = { - filter?: WorkspaceV2Filter; - paging?: CursorPaging; - sorting?: Array; +export type RefreshTokenEdge = { + __typename?: 'RefreshTokenEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the RefreshToken */ + node: RefreshToken; }; -export enum QueryMode { - Default = 'default', - Insensitive = 'insensitive' -} - export type RelationConnection = { __typename?: 'RelationConnection'; /** Array of edges. */ @@ -2667,53 +386,6 @@ export enum RelationMetadataType { OneToOne = 'ONE_TO_ONE' } -/** Sort Directions */ -export enum SortDirection { - Asc = 'ASC', - Desc = 'DESC' -} - -/** Sort Nulls Options */ -export enum SortNulls { - NullsFirst = 'NULLS_FIRST', - NullsLast = 'NULLS_LAST' -} - -export enum SortOrder { - Asc = 'asc', - Desc = 'desc' -} - -export type StringFilter = { - contains?: InputMaybe; - endsWith?: InputMaybe; - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - mode?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; - startsWith?: InputMaybe; -}; - -export type StringNullableFilter = { - contains?: InputMaybe; - endsWith?: InputMaybe; - equals?: InputMaybe; - gt?: InputMaybe; - gte?: InputMaybe; - in?: InputMaybe>; - lt?: InputMaybe; - lte?: InputMaybe; - mode?: InputMaybe; - not?: InputMaybe; - notIn?: InputMaybe>; - startsWith?: InputMaybe; -}; - export type Support = { __typename?: 'Support'; supportDriver: Scalars['String']; @@ -2726,60 +398,37 @@ export type Telemetry = { enabled: Scalars['Boolean']; }; -export type UpdateOneWorkspaceV2Input = { - /** The id of the record to update */ - id: Scalars['ID']; - /** The update to apply. */ - update: UpdateWorkspaceInput; -}; - export type UpdateWorkspaceInput = { - displayName: Scalars['String']; - domainName: Scalars['String']; - inviteHash: Scalars['String']; - logo: Scalars['String']; + displayName?: InputMaybe; + domainName?: InputMaybe; + inviteHash?: InputMaybe; + logo?: InputMaybe; }; export type User = { __typename?: 'User'; - assignedActivities?: Maybe>; - authoredActivities?: Maybe>; - authoredAttachments?: Maybe>; - avatarUrl?: Maybe; canImpersonate: Scalars['Boolean']; - comments?: Maybe>; - companies?: Maybe>; createdAt: Scalars['DateTime']; - defaultWorkspaceId?: Maybe; - disabled: Scalars['Boolean']; - displayName: Scalars['String']; + defaultWorkspace: Workspace; + deletedAt?: Maybe; + disabled?: Maybe; email: Scalars['String']; emailVerified: Scalars['Boolean']; - firstName?: Maybe; + firstName: Scalars['String']; id: Scalars['ID']; - lastName?: Maybe; - lastSeen?: Maybe; - locale: Scalars['String']; - metadata?: Maybe; - phoneNumber?: Maybe; + lastName: Scalars['String']; + passwordHash?: Maybe; supportUserHash?: Maybe; updatedAt: Scalars['DateTime']; + workspaceMember: UserWorkspaceMember; }; -export type UserCreateNestedOneWithoutAssignedActivitiesInput = { - connect?: InputMaybe; -}; - -export type UserCreateNestedOneWithoutAuthoredActivitiesInput = { - connect?: InputMaybe; -}; - -export type UserCreateNestedOneWithoutCommentsInput = { - connect?: InputMaybe; -}; - -export type UserCreateNestedOneWithoutCompaniesInput = { - connect?: InputMaybe; +export type UserEdge = { + __typename?: 'UserEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the User */ + node: User; }; export type UserExists = { @@ -2787,165 +436,20 @@ export type UserExists = { exists: Scalars['Boolean']; }; -export type UserOrderByWithRelationInput = { - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - avatarUrl?: InputMaybe; - canImpersonate?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - defaultWorkspaceId?: InputMaybe; - disabled?: InputMaybe; - email?: InputMaybe; - emailVerified?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - lastName?: InputMaybe; - lastSeen?: InputMaybe; - locale?: InputMaybe; - metadata?: InputMaybe; - phoneNumber?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type UserRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum UserScalarFieldEnum { - AvatarUrl = 'avatarUrl', - CanImpersonate = 'canImpersonate', - CreatedAt = 'createdAt', - DefaultWorkspaceId = 'defaultWorkspaceId', - DeletedAt = 'deletedAt', - Disabled = 'disabled', - Email = 'email', - EmailVerified = 'emailVerified', - FirstName = 'firstName', - Id = 'id', - LastName = 'lastName', - LastSeen = 'lastSeen', - Locale = 'locale', - Metadata = 'metadata', - PasswordHash = 'passwordHash', - PhoneNumber = 'phoneNumber', - UpdatedAt = 'updatedAt' -} - -export type UserSettings = { - __typename?: 'UserSettings'; - WorkspaceMember?: Maybe>; - colorScheme: ColorScheme; - createdAt: Scalars['DateTime']; +export type UserWorkspaceMember = { + __typename?: 'UserWorkspaceMember'; + allowImpersonation: Scalars['Boolean']; + avatarUrl?: Maybe; + colorScheme: Scalars['String']; id: Scalars['ID']; locale: Scalars['String']; - updatedAt: Scalars['DateTime']; + name: UserWorkspaceMemberName; }; -export type UserSettingsOrderByWithRelationInput = { - WorkspaceMember?: InputMaybe; - colorScheme?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - locale?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type UserSettingsRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export type UserSettingsUpdateOneWithoutWorkspaceMemberNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type UserSettingsWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - WorkspaceMember?: InputMaybe; - colorScheme?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - locale?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type UserSettingsWhereUniqueInput = { - id?: InputMaybe; -}; - -export type UserUpdateInput = { - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - avatarUrl?: InputMaybe; - canImpersonate?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - defaultWorkspaceId?: InputMaybe; - disabled?: InputMaybe; - email?: InputMaybe; - emailVerified?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - lastName?: InputMaybe; - lastSeen?: InputMaybe; - locale?: InputMaybe; - metadata?: InputMaybe; - phoneNumber?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type UserUpdateOneRequiredWithoutAuthoredActivitiesNestedInput = { - connect?: InputMaybe; -}; - -export type UserUpdateOneWithoutAssignedActivitiesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type UserUpdateOneWithoutCompaniesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type UserWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - avatarUrl?: InputMaybe; - canImpersonate?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - defaultWorkspaceId?: InputMaybe; - disabled?: InputMaybe; - email?: InputMaybe; - emailVerified?: InputMaybe; - firstName?: InputMaybe; - id?: InputMaybe; - lastName?: InputMaybe; - lastSeen?: InputMaybe; - locale?: InputMaybe; - metadata?: InputMaybe; - phoneNumber?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type UserWhereUniqueInput = { - email?: InputMaybe; - id?: InputMaybe; +export type UserWorkspaceMemberName = { + __typename?: 'UserWorkspaceMemberName'; + firstName: Scalars['String']; + lastName: Scalars['String']; }; export type Verify = { @@ -2954,83 +458,24 @@ export type Verify = { user: User; }; -export type WebHook = { - __typename?: 'WebHook'; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - operation: Scalars['String']; - targetUrl: Scalars['String']; - updatedAt: Scalars['DateTime']; -}; - -export type WebHookCreateInput = { - createdAt?: InputMaybe; - id?: InputMaybe; - operation: Scalars['String']; - targetUrl: Scalars['String']; - updatedAt?: InputMaybe; -}; - -export type WebHookOrderByWithRelationInput = { - createdAt?: InputMaybe; - id?: InputMaybe; - operation?: InputMaybe; - targetUrl?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export enum WebHookScalarFieldEnum { - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - Id = 'id', - Operation = 'operation', - TargetUrl = 'targetUrl', - UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' -} - -export type WebHookUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type WebHookWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - createdAt?: InputMaybe; - id?: InputMaybe; - operation?: InputMaybe; - targetUrl?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type WebHookWhereUniqueInput = { - id?: InputMaybe; -}; - export type Workspace = { __typename?: 'Workspace'; - Attachment?: Maybe>; - activities?: Maybe>; - activityTargets?: Maybe>; - apiKeys?: Maybe>; - comments?: Maybe>; - companies?: Maybe>; createdAt: Scalars['DateTime']; + deletedAt?: Maybe; displayName?: Maybe; domainName?: Maybe; id: Scalars['ID']; inviteHash?: Maybe; logo?: Maybe; - people?: Maybe>; - pipelineProgresses?: Maybe>; - pipelineStages?: Maybe>; - pipelines?: Maybe>; updatedAt: Scalars['DateTime']; - webHooks?: Maybe>; - workspaceMember?: Maybe>; +}; + +export type WorkspaceEdge = { + __typename?: 'WorkspaceEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the Workspace */ + node: Workspace; }; export type WorkspaceInviteHashValid = { @@ -3038,174 +483,6 @@ export type WorkspaceInviteHashValid = { isValid: Scalars['Boolean']; }; -export type WorkspaceMember = { - __typename?: 'WorkspaceMember'; - Favorite?: Maybe>; - allowImpersonation: Scalars['Boolean']; - assignedActivities?: Maybe>; - authoredActivities?: Maybe>; - authoredAttachments?: Maybe>; - comments?: Maybe>; - companies?: Maybe>; - createdAt: Scalars['DateTime']; - id: Scalars['ID']; - settings?: Maybe; - settingsId?: Maybe; - updatedAt: Scalars['DateTime']; - userId: Scalars['String']; - workspace: Workspace; -}; - -export type WorkspaceMemberCreateNestedOneWithoutAssignedActivitiesInput = { - connect?: InputMaybe; -}; - -export type WorkspaceMemberCreateNestedOneWithoutAuthoredActivitiesInput = { - connect?: InputMaybe; -}; - -export type WorkspaceMemberCreateNestedOneWithoutCommentsInput = { - connect?: InputMaybe; -}; - -export type WorkspaceMemberCreateNestedOneWithoutCompaniesInput = { - connect?: InputMaybe; -}; - -export type WorkspaceMemberListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type WorkspaceMemberOrderByRelationAggregateInput = { - _count?: InputMaybe; -}; - -export type WorkspaceMemberOrderByWithRelationInput = { - Favorite?: InputMaybe; - allowImpersonation?: InputMaybe; - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - settings?: InputMaybe; - settingsId?: InputMaybe; - updatedAt?: InputMaybe; - userId?: InputMaybe; -}; - -export type WorkspaceMemberRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export enum WorkspaceMemberScalarFieldEnum { - AllowImpersonation = 'allowImpersonation', - CreatedAt = 'createdAt', - DeletedAt = 'deletedAt', - Id = 'id', - SettingsId = 'settingsId', - UpdatedAt = 'updatedAt', - UserId = 'userId', - WorkspaceId = 'workspaceId' -} - -export type WorkspaceMemberUpdateInput = { - Favorite?: InputMaybe; - allowImpersonation?: InputMaybe; - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - settings?: InputMaybe; - updatedAt?: InputMaybe; - userId?: InputMaybe; -}; - -export type WorkspaceMemberUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; -}; - -export type WorkspaceMemberUpdateOneWithoutAssignedActivitiesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type WorkspaceMemberUpdateOneWithoutAuthoredActivitiesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type WorkspaceMemberUpdateOneWithoutCompaniesNestedInput = { - connect?: InputMaybe; - disconnect?: InputMaybe; -}; - -export type WorkspaceMemberWhereInput = { - AND?: InputMaybe>; - Favorite?: InputMaybe; - NOT?: InputMaybe>; - OR?: InputMaybe>; - allowImpersonation?: InputMaybe; - assignedActivities?: InputMaybe; - authoredActivities?: InputMaybe; - authoredAttachments?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - id?: InputMaybe; - settings?: InputMaybe; - settingsId?: InputMaybe; - updatedAt?: InputMaybe; - userId?: InputMaybe; -}; - -export type WorkspaceMemberWhereUniqueInput = { - id?: InputMaybe; - userId?: InputMaybe; -}; - -export type WorkspaceUpdateInput = { - Attachment?: InputMaybe; - activities?: InputMaybe; - activityTargets?: InputMaybe; - apiKeys?: InputMaybe; - comments?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - displayName?: InputMaybe; - domainName?: InputMaybe; - id?: InputMaybe; - inviteHash?: InputMaybe; - logo?: InputMaybe; - people?: InputMaybe; - pipelineProgresses?: InputMaybe; - pipelineStages?: InputMaybe; - pipelines?: InputMaybe; - updatedAt?: InputMaybe; - webHooks?: InputMaybe; - workspaceMember?: InputMaybe; -}; - -export type WorkspaceV2Connection = { - __typename?: 'WorkspaceV2Connection'; - /** Array of edges. */ - edges: Array; - /** Paging information */ - pageInfo: PageInfo; - /** Fetch total count of records */ - totalCount: Scalars['Int']; -}; - export type Field = { __typename?: 'field'; createdAt: Scalars['DateTime']; @@ -3275,22 +552,6 @@ export type ObjectEdge = { 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 = { __typename?: 'relation'; createdAt: Scalars['DateTime']; @@ -3313,72 +574,6 @@ export type RelationEdge = { node: Relation; }; -export type UserV2 = { - __typename?: 'userV2'; - avatarUrl: Scalars['String']; - canImpersonate: Scalars['Boolean']; - createdAt: Scalars['DateTime']; - deletedAt?: Maybe; - disabled?: Maybe; - displayName: Scalars['String']; - email: Scalars['String']; - emailVerified: Scalars['Boolean']; - firstName: Scalars['String']; - id: Scalars['ID']; - lastName: Scalars['String']; - lastSeen?: Maybe; - locale: Scalars['String']; - metadata?: Maybe; - passwordHash?: Maybe; - phoneNumber?: Maybe; - supportUserHash?: Maybe; - updatedAt: Scalars['DateTime']; -}; - -export type UserV2Edge = { - __typename?: 'userV2Edge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the userV2 */ - node: UserV2; -}; - -export type WorkspaceV2 = { - __typename?: 'workspaceV2'; - createdAt: Scalars['DateTime']; - deletedAt?: Maybe; - displayName?: Maybe; - domainName?: Maybe; - id: Scalars['ID']; - inviteHash?: Maybe; - logo?: Maybe; - updatedAt: Scalars['DateTime']; -}; - -export type WorkspaceV2Edge = { - __typename?: 'workspaceV2Edge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the workspaceV2 */ - node: WorkspaceV2; -}; - -export type WorkspaceV2Filter = { - and?: InputMaybe>; - id?: InputMaybe; - or?: InputMaybe>; -}; - -export type WorkspaceV2Sort = { - direction: SortDirection; - field: WorkspaceV2SortFields; - nulls?: InputMaybe; -}; - -export enum WorkspaceV2SortFields { - Id = 'id' -} - export type CreateEventMutationVariables = Exact<{ type: Scalars['String']; data: Scalars['JSON']; @@ -3391,8 +586,6 @@ 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 UserQueryFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, canImpersonate: boolean, supportUserHash?: string | null }; - export type ChallengeMutationVariables = Exact<{ email: Scalars['String']; password: Scalars['String']; @@ -3401,12 +594,20 @@ export type ChallengeMutationVariables = Exact<{ export type ChallengeMutation = { __typename?: 'Mutation', challenge: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; +export type GenerateApiKeyTokenMutationVariables = Exact<{ + apiKeyId: Scalars['String']; + expiresAt: Scalars['String']; +}>; + + +export type GenerateApiKeyTokenMutation = { __typename?: 'Mutation', generateApiKeyToken: { __typename?: 'ApiKeyToken', token: string } }; + export type ImpersonateMutationVariables = Exact<{ userId: Scalars['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 ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, allowImpersonation: boolean, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type RenewTokenMutationVariables = Exact<{ refreshToken: Scalars['String']; @@ -3429,7 +630,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 }, 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, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, allowImpersonation: boolean, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type CheckUserExistsQueryVariables = Exact<{ email: Scalars['String']; @@ -3443,292 +644,12 @@ export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>; export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, debugMode: boolean, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean }, telemetry: { __typename?: 'Telemetry', enabled: boolean, anonymizationEnabled: boolean }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null } } }; -export type BaseCompanyFieldsFragmentFragment = { __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number }; - -export type BaseAccountOwnerFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null }; - -export type CompanyFieldsFragmentFragment = { __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null }; - -export type DeleteManyCompaniesMutationVariables = Exact<{ - ids?: InputMaybe | Scalars['String']>; -}>; - - -export type DeleteManyCompaniesMutation = { __typename?: 'Mutation', deleteManyCompany: { __typename?: 'AffectedRows', count: number } }; - -export type InsertManyCompanyMutationVariables = Exact<{ - data: Array | CompanyCreateManyInput; -}>; - - -export type InsertManyCompanyMutation = { __typename?: 'Mutation', createManyCompany: { __typename?: 'AffectedRows', count: number } }; - -export type InsertOneCompanyMutationVariables = Exact<{ - data: CompanyCreateInput; -}>; - - -export type InsertOneCompanyMutation = { __typename?: 'Mutation', createOneCompany: { __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null } }; - -export type UpdateOneCompanyMutationVariables = Exact<{ - where: CompanyWhereUniqueInput; - data: CompanyUpdateInput; -}>; - - -export type UpdateOneCompanyMutation = { __typename?: 'Mutation', updateOneCompany?: { __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null } | null }; - -export type GetCompaniesQueryVariables = Exact<{ - orderBy?: InputMaybe | CompanyOrderByWithRelationInput>; - where?: InputMaybe; -}>; - - -export type GetCompaniesQuery = { __typename?: 'Query', companies: Array<{ __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null }> }; - -export type GetCompanyQueryVariables = Exact<{ - where: CompanyWhereUniqueInput; -}>; - - -export type GetCompanyQuery = { __typename?: 'Query', findUniqueCompany: { __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, Favorite?: Array<{ __typename?: 'Favorite', id: string, person?: { __typename?: 'Person', id: string } | null, company?: { __typename?: 'Company', id: string } | null }> | null, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null } }; - -export type DeleteFavoriteMutationVariables = Exact<{ - where: FavoriteWhereInput; -}>; - - -export type DeleteFavoriteMutation = { __typename?: 'Mutation', deleteFavorite: { __typename?: 'Favorite', id: string } }; - -export type InsertCompanyFavoriteMutationVariables = Exact<{ - data: FavoriteMutationForCompanyArgs; -}>; - - -export type InsertCompanyFavoriteMutation = { __typename?: 'Mutation', createFavoriteForCompany: { __typename?: 'Favorite', id: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; - -export type InsertPersonFavoriteMutationVariables = Exact<{ - data: FavoriteMutationForPersonArgs; -}>; - - -export type InsertPersonFavoriteMutation = { __typename?: 'Mutation', createFavoriteForPerson: { __typename?: 'Favorite', id: string, person?: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string } | null } }; - -export type UpdateOneFavoriteMutationVariables = Exact<{ - data: FavoriteUpdateInput; - where: FavoriteWhereUniqueInput; -}>; - - -export type UpdateOneFavoriteMutation = { __typename?: 'Mutation', updateOneFavorites: { __typename?: 'Favorite', id: string, person?: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string, accountOwner?: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } | null } | null } }; - -export type GetFavoritesQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetFavoritesQuery = { __typename?: 'Query', findFavorites: Array<{ __typename?: 'Favorite', id: string, position: number, person?: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string, accountOwner?: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } | null } | null }> }; - -export type BasePersonFieldsFragmentFragment = { __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string }; - -export type PersonFieldsFragmentFragment = { __typename?: 'Person', jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, _activityCount: number, id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }; - -export type DeleteManyPersonMutationVariables = Exact<{ - ids?: InputMaybe | Scalars['String']>; -}>; - - -export type DeleteManyPersonMutation = { __typename?: 'Mutation', deleteManyPerson: { __typename?: 'AffectedRows', count: number } }; - -export type InsertManyPersonMutationVariables = Exact<{ - data: Array | PersonCreateManyInput; -}>; - - -export type InsertManyPersonMutation = { __typename?: 'Mutation', createManyPerson: { __typename?: 'AffectedRows', count: number } }; - -export type InsertOnePersonMutationVariables = Exact<{ - data: PersonCreateInput; -}>; - - -export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, _activityCount: number, id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; - -export type RemovePersonPictureMutationVariables = Exact<{ - where: PersonWhereUniqueInput; -}>; - - -export type RemovePersonPictureMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', id: string, avatarUrl?: string | null } | null }; - -export type UpdateOnePersonMutationVariables = Exact<{ - where: PersonWhereUniqueInput; - data: PersonUpdateInput; -}>; - - -export type UpdateOnePersonMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, _activityCount: number, id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } | null }; - -export type UploadPersonPictureMutationVariables = Exact<{ - id: Scalars['String']; - file: Scalars['Upload']; -}>; - - -export type UploadPersonPictureMutation = { __typename?: 'Mutation', uploadPersonPicture: string }; - -export type GetPeopleQueryVariables = Exact<{ - orderBy?: InputMaybe | PersonOrderByWithRelationInput>; - where?: InputMaybe; - limit?: InputMaybe; -}>; - - -export type GetPeopleQuery = { __typename?: 'Query', people: Array<{ __typename?: 'Person', jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, _activityCount: number, id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }> }; - -export type GetPersonQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonQuery = { __typename?: 'Query', findUniquePerson: { __typename?: 'Person', jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, _activityCount: number, id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string, Favorite?: Array<{ __typename?: 'Favorite', id: string, person?: { __typename?: 'Person', id: string } | null, company?: { __typename?: 'Company', id: string } | null }> | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; - -export type GetPersonCityByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonCityByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, city?: string | null } }; - -export type GetPersonCommentCountByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonCommentCountByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, _activityCount: number } }; - -export type GetPersonCompanyByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonCompanyByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; - -export type GetPersonCreatedAtByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonCreatedAtByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, createdAt: string } }; - -export type GetPersonEmailByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonEmailByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, email?: string | null } }; - -export type GetPersonNamesAndCommentCountByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonNamesAndCommentCountByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, _activityCount: number } }; - -export type GetPersonPhoneByIdQueryVariables = Exact<{ - id: Scalars['String']; -}>; - - -export type GetPersonPhoneByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, phone?: string | null } }; - -export type SearchActivityQueryVariables = Exact<{ - where?: InputMaybe; - limit?: InputMaybe; - orderBy?: InputMaybe | ActivityOrderByWithRelationInput>; -}>; - - -export type SearchActivityQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Activity', id: string, title?: string | null, body?: string | null }> }; - -export type SearchCompanyQueryVariables = Exact<{ - where?: InputMaybe; - limit?: InputMaybe; - orderBy?: InputMaybe | CompanyOrderByWithRelationInput>; -}>; - - -export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', address: string, annualRecurringRevenue?: number | null, createdAt: string, domainName: string, employees?: number | null, id: string, idealCustomerProfile: boolean, linkedinUrl?: string | null, name: string, xUrl?: string | null, _activityCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } | null }> }; - -export type SearchPeopleQueryVariables = Exact<{ - where?: InputMaybe; - limit?: InputMaybe; - orderBy?: InputMaybe | PersonOrderByWithRelationInput>; -}>; - - -export type SearchPeopleQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null, createdAt: string }> }; - -export type SearchUserQueryVariables = Exact<{ - where?: InputMaybe; - limit?: InputMaybe; - orderBy?: InputMaybe | UserOrderByWithRelationInput>; -}>; - - -export type SearchUserQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'User', avatarUrl?: string | null, id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> }; - -export type DeleteOneApiKeyMutationVariables = Exact<{ - apiKeyId: Scalars['String']; -}>; - - -export type DeleteOneApiKeyMutation = { __typename?: 'Mutation', revokeOneApiKey: { __typename?: 'ApiKey', id: string } }; - -export type GenerateOneApiKeyTokenMutationVariables = Exact<{ - data: ApiKeyCreateInput; -}>; - - -export type GenerateOneApiKeyTokenMutation = { __typename?: 'Mutation', generateApiKeyV2Token: { __typename?: 'ApiKeyToken', token: string } }; - -export type InsertOneApiKeyMutationVariables = Exact<{ - data: ApiKeyCreateInput; -}>; - - -export type InsertOneApiKeyMutation = { __typename?: 'Mutation', createOneApiKey: { __typename?: 'ApiKeyToken', id: string, name: string, token: string, createdAt: string, expiresAt?: string | null } }; - -export type GetApiKeyQueryVariables = Exact<{ - apiKeyId: Scalars['String']; -}>; - - -export type GetApiKeyQuery = { __typename?: 'Query', findManyApiKey: Array<{ __typename?: 'ApiKey', id: string, name: string, expiresAt?: string | null, createdAt: string }> }; - -export type GetApiKeysQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetApiKeysQuery = { __typename?: 'Query', findManyApiKey: Array<{ __typename?: 'ApiKey', id: string, name: string, expiresAt?: string | null, createdAt: string }> }; - -export type UserFieldsFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }; +export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, allowImpersonation: boolean, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null } }; export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>; -export type DeleteUserAccountMutation = { __typename?: 'Mutation', deleteUserAccount: { __typename?: 'User', id: string } }; - -export type RemoveProfilePictureMutationVariables = Exact<{ - where: UserWhereUniqueInput; -}>; - - -export type RemoveProfilePictureMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, avatarUrl?: string | null } }; - -export type UpdateAllowImpersonationMutationVariables = Exact<{ - allowImpersonation: Scalars['Boolean']; -}>; - - -export type UpdateAllowImpersonationMutation = { __typename?: 'Mutation', allowImpersonation: { __typename?: 'WorkspaceMember', id: string, allowImpersonation: boolean } }; +export type DeleteUserAccountMutation = { __typename?: 'Mutation', deleteUser: { __typename?: 'User', id: string } }; export type UploadProfilePictureMutationVariables = Exact<{ file: Scalars['Upload']; @@ -3737,36 +658,18 @@ export type UploadProfilePictureMutationVariables = Exact<{ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProfilePicture: string }; -export type UpdateUserMutationVariables = Exact<{ - data: UserUpdateInput; - where: UserWhereUniqueInput; -}>; - - -export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string } }; - export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -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 GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> }; +export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, allowImpersonation: boolean, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null } } }; export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>; export type DeleteCurrentWorkspaceMutation = { __typename?: 'Mutation', deleteCurrentWorkspace: { __typename?: 'Workspace', id: string } }; -export type RemoveWorkspaceLogoMutationVariables = Exact<{ [key: string]: never; }>; - - -export type RemoveWorkspaceLogoMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: string } }; - export type UpdateWorkspaceMutationVariables = Exact<{ - data: WorkspaceUpdateInput; + input: UpdateWorkspaceInput; }>; @@ -3779,11 +682,6 @@ export type UploadWorkspaceLogoMutationVariables = Exact<{ export type UploadWorkspaceLogoMutation = { __typename?: 'Mutation', uploadWorkspaceLogo: string }; -export type GetCurrentWorkspaceQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetCurrentWorkspaceQuery = { __typename?: 'Query', currentWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null } }; - export type GetWorkspaceFromInviteHashQueryVariables = Exact<{ inviteHash: Scalars['String']; }>; @@ -3791,13 +689,6 @@ export type GetWorkspaceFromInviteHashQueryVariables = Exact<{ export type GetWorkspaceFromInviteHashQuery = { __typename?: 'Query', findWorkspaceFromInviteHash: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null } }; -export type GetWorkspaceMembersQueryVariables = Exact<{ - where?: InputMaybe; -}>; - - -export type GetWorkspaceMembersQuery = { __typename?: 'Query', workspaceMembers: Array<{ __typename?: 'WorkspaceMember', id: string }> }; - export const AuthTokenFragmentFragmentDoc = gql` fragment AuthTokenFragment on AuthToken { token @@ -3817,82 +708,29 @@ export const AuthTokensFragmentFragmentDoc = gql` export const UserQueryFragmentFragmentDoc = gql` fragment UserQueryFragment on User { id - email - displayName firstName lastName + email canImpersonate supportUserHash -} - `; -export const BaseAccountOwnerFragmentFragmentDoc = gql` - fragment baseAccountOwnerFragment on User { - id - email - displayName - avatarUrl - firstName - lastName -} - `; -export const BaseCompanyFieldsFragmentFragmentDoc = gql` - fragment baseCompanyFieldsFragment on Company { - address - annualRecurringRevenue - createdAt - domainName - employees - id - idealCustomerProfile - linkedinUrl - name - xUrl - _activityCount -} - `; -export const CompanyFieldsFragmentFragmentDoc = gql` - fragment companyFieldsFragment on Company { - accountOwner { - ...baseAccountOwnerFragment - } - ...baseCompanyFieldsFragment -} - ${BaseAccountOwnerFragmentFragmentDoc} -${BaseCompanyFieldsFragmentFragmentDoc}`; -export const BasePersonFieldsFragmentFragmentDoc = gql` - fragment basePersonFieldsFragment on Person { - id - phone - email - city - firstName - lastName - displayName - avatarUrl - createdAt -} - `; -export const PersonFieldsFragmentFragmentDoc = gql` - fragment personFieldsFragment on Person { - ...basePersonFieldsFragment - jobTitle - linkedinUrl - xUrl - _activityCount - company { + workspaceMember { id - name - domainName + name { + firstName + lastName + } + colorScheme + avatarUrl + locale + allowImpersonation + } + defaultWorkspace { + id + displayName + logo + domainName + inviteHash } -} - ${BasePersonFieldsFragmentFragmentDoc}`; -export const UserFieldsFragmentFragmentDoc = gql` - fragment userFieldsFragment on User { - id - email - displayName - firstName - lastName } `; export const CreateEventDocument = gql` @@ -3965,6 +803,40 @@ export function useChallengeMutation(baseOptions?: Apollo.MutationHookOptions; export type ChallengeMutationResult = Apollo.MutationResult; export type ChallengeMutationOptions = Apollo.BaseMutationOptions; +export const GenerateApiKeyTokenDocument = gql` + mutation GenerateApiKeyToken($apiKeyId: String!, $expiresAt: String!) { + generateApiKeyToken(apiKeyId: $apiKeyId, expiresAt: $expiresAt) { + token + } +} + `; +export type GenerateApiKeyTokenMutationFn = Apollo.MutationFunction; + +/** + * __useGenerateApiKeyTokenMutation__ + * + * To run a mutation, you first call `useGenerateApiKeyTokenMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useGenerateApiKeyTokenMutation` 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 [generateApiKeyTokenMutation, { data, loading, error }] = useGenerateApiKeyTokenMutation({ + * variables: { + * apiKeyId: // value for 'apiKeyId' + * expiresAt: // value for 'expiresAt' + * }, + * }); + */ +export function useGenerateApiKeyTokenMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(GenerateApiKeyTokenDocument, options); + } +export type GenerateApiKeyTokenMutationHookResult = ReturnType; +export type GenerateApiKeyTokenMutationResult = Apollo.MutationResult; +export type GenerateApiKeyTokenMutationOptions = Apollo.BaseMutationOptions; export const ImpersonateDocument = gql` mutation Impersonate($userId: String!) { impersonate(userId: $userId) { @@ -4201,1305 +1073,9 @@ export function useGetClientConfigLazyQuery(baseOptions?: Apollo.LazyQueryHookOp export type GetClientConfigQueryHookResult = ReturnType; export type GetClientConfigLazyQueryHookResult = ReturnType; export type GetClientConfigQueryResult = Apollo.QueryResult; -export const DeleteManyCompaniesDocument = gql` - mutation DeleteManyCompanies($ids: [String!]) { - deleteManyCompany(where: {id: {in: $ids}}) { - count - } -} - `; -export type DeleteManyCompaniesMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteManyCompaniesMutation__ - * - * To run a mutation, you first call `useDeleteManyCompaniesMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteManyCompaniesMutation` 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 [deleteManyCompaniesMutation, { data, loading, error }] = useDeleteManyCompaniesMutation({ - * variables: { - * ids: // value for 'ids' - * }, - * }); - */ -export function useDeleteManyCompaniesMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteManyCompaniesDocument, options); - } -export type DeleteManyCompaniesMutationHookResult = ReturnType; -export type DeleteManyCompaniesMutationResult = Apollo.MutationResult; -export type DeleteManyCompaniesMutationOptions = Apollo.BaseMutationOptions; -export const InsertManyCompanyDocument = gql` - mutation InsertManyCompany($data: [CompanyCreateManyInput!]!) { - createManyCompany(data: $data) { - count - } -} - `; -export type InsertManyCompanyMutationFn = Apollo.MutationFunction; - -/** - * __useInsertManyCompanyMutation__ - * - * To run a mutation, you first call `useInsertManyCompanyMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertManyCompanyMutation` 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 [insertManyCompanyMutation, { data, loading, error }] = useInsertManyCompanyMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertManyCompanyMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertManyCompanyDocument, options); - } -export type InsertManyCompanyMutationHookResult = ReturnType; -export type InsertManyCompanyMutationResult = Apollo.MutationResult; -export type InsertManyCompanyMutationOptions = Apollo.BaseMutationOptions; -export const InsertOneCompanyDocument = gql` - mutation InsertOneCompany($data: CompanyCreateInput!) { - createOneCompany(data: $data) { - ...companyFieldsFragment - } -} - ${CompanyFieldsFragmentFragmentDoc}`; -export type InsertOneCompanyMutationFn = Apollo.MutationFunction; - -/** - * __useInsertOneCompanyMutation__ - * - * To run a mutation, you first call `useInsertOneCompanyMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertOneCompanyMutation` 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 [insertOneCompanyMutation, { data, loading, error }] = useInsertOneCompanyMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertOneCompanyMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertOneCompanyDocument, options); - } -export type InsertOneCompanyMutationHookResult = ReturnType; -export type InsertOneCompanyMutationResult = Apollo.MutationResult; -export type InsertOneCompanyMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOneCompanyDocument = gql` - mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) { - updateOneCompany(data: $data, where: $where) { - ...companyFieldsFragment - } -} - ${CompanyFieldsFragmentFragmentDoc}`; -export type UpdateOneCompanyMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOneCompanyMutation__ - * - * To run a mutation, you first call `useUpdateOneCompanyMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOneCompanyMutation` 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 [updateOneCompanyMutation, { data, loading, error }] = useUpdateOneCompanyMutation({ - * variables: { - * where: // value for 'where' - * data: // value for 'data' - * }, - * }); - */ -export function useUpdateOneCompanyMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOneCompanyDocument, options); - } -export type UpdateOneCompanyMutationHookResult = ReturnType; -export type UpdateOneCompanyMutationResult = Apollo.MutationResult; -export type UpdateOneCompanyMutationOptions = Apollo.BaseMutationOptions; -export const GetCompaniesDocument = gql` - query GetCompanies($orderBy: [CompanyOrderByWithRelationInput!], $where: CompanyWhereInput) { - companies: findManyCompany(orderBy: $orderBy, where: $where) { - ...companyFieldsFragment - } -} - ${CompanyFieldsFragmentFragmentDoc}`; - -/** - * __useGetCompaniesQuery__ - * - * To run a query within a React component, call `useGetCompaniesQuery` and pass it any options that fit your needs. - * When your component renders, `useGetCompaniesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetCompaniesQuery({ - * variables: { - * orderBy: // value for 'orderBy' - * where: // value for 'where' - * }, - * }); - */ -export function useGetCompaniesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetCompaniesDocument, options); - } -export function useGetCompaniesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetCompaniesDocument, options); - } -export type GetCompaniesQueryHookResult = ReturnType; -export type GetCompaniesLazyQueryHookResult = ReturnType; -export type GetCompaniesQueryResult = Apollo.QueryResult; -export const GetCompanyDocument = gql` - query GetCompany($where: CompanyWhereUniqueInput!) { - findUniqueCompany(where: $where) { - ...companyFieldsFragment - Favorite { - id - person { - id - } - company { - id - } - } - } -} - ${CompanyFieldsFragmentFragmentDoc}`; - -/** - * __useGetCompanyQuery__ - * - * To run a query within a React component, call `useGetCompanyQuery` and pass it any options that fit your needs. - * When your component renders, `useGetCompanyQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetCompanyQuery({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useGetCompanyQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetCompanyDocument, options); - } -export function useGetCompanyLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetCompanyDocument, options); - } -export type GetCompanyQueryHookResult = ReturnType; -export type GetCompanyLazyQueryHookResult = ReturnType; -export type GetCompanyQueryResult = Apollo.QueryResult; -export const DeleteFavoriteDocument = gql` - mutation DeleteFavorite($where: FavoriteWhereInput!) { - deleteFavorite(where: $where) { - id - } -} - `; -export type DeleteFavoriteMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteFavoriteMutation__ - * - * To run a mutation, you first call `useDeleteFavoriteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteFavoriteMutation` 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 [deleteFavoriteMutation, { data, loading, error }] = useDeleteFavoriteMutation({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useDeleteFavoriteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteFavoriteDocument, options); - } -export type DeleteFavoriteMutationHookResult = ReturnType; -export type DeleteFavoriteMutationResult = Apollo.MutationResult; -export type DeleteFavoriteMutationOptions = Apollo.BaseMutationOptions; -export const InsertCompanyFavoriteDocument = gql` - mutation InsertCompanyFavorite($data: FavoriteMutationForCompanyArgs!) { - createFavoriteForCompany(data: $data) { - id - company { - id - name - domainName - } - } -} - `; -export type InsertCompanyFavoriteMutationFn = Apollo.MutationFunction; - -/** - * __useInsertCompanyFavoriteMutation__ - * - * To run a mutation, you first call `useInsertCompanyFavoriteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertCompanyFavoriteMutation` 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 [insertCompanyFavoriteMutation, { data, loading, error }] = useInsertCompanyFavoriteMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertCompanyFavoriteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertCompanyFavoriteDocument, options); - } -export type InsertCompanyFavoriteMutationHookResult = ReturnType; -export type InsertCompanyFavoriteMutationResult = Apollo.MutationResult; -export type InsertCompanyFavoriteMutationOptions = Apollo.BaseMutationOptions; -export const InsertPersonFavoriteDocument = gql` - mutation InsertPersonFavorite($data: FavoriteMutationForPersonArgs!) { - createFavoriteForPerson(data: $data) { - id - person { - id - firstName - lastName - displayName - } - } -} - `; -export type InsertPersonFavoriteMutationFn = Apollo.MutationFunction; - -/** - * __useInsertPersonFavoriteMutation__ - * - * To run a mutation, you first call `useInsertPersonFavoriteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertPersonFavoriteMutation` 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 [insertPersonFavoriteMutation, { data, loading, error }] = useInsertPersonFavoriteMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertPersonFavoriteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertPersonFavoriteDocument, options); - } -export type InsertPersonFavoriteMutationHookResult = ReturnType; -export type InsertPersonFavoriteMutationResult = Apollo.MutationResult; -export type InsertPersonFavoriteMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOneFavoriteDocument = gql` - mutation UpdateOneFavorite($data: FavoriteUpdateInput!, $where: FavoriteWhereUniqueInput!) { - updateOneFavorites(data: $data, where: $where) { - id - person { - id - firstName - lastName - avatarUrl - } - company { - id - name - domainName - accountOwner { - id - displayName - avatarUrl - } - } - } -} - `; -export type UpdateOneFavoriteMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOneFavoriteMutation__ - * - * To run a mutation, you first call `useUpdateOneFavoriteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOneFavoriteMutation` 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 [updateOneFavoriteMutation, { data, loading, error }] = useUpdateOneFavoriteMutation({ - * variables: { - * data: // value for 'data' - * where: // value for 'where' - * }, - * }); - */ -export function useUpdateOneFavoriteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOneFavoriteDocument, options); - } -export type UpdateOneFavoriteMutationHookResult = ReturnType; -export type UpdateOneFavoriteMutationResult = Apollo.MutationResult; -export type UpdateOneFavoriteMutationOptions = Apollo.BaseMutationOptions; -export const GetFavoritesDocument = gql` - query GetFavorites { - findFavorites { - id - position - person { - id - firstName - lastName - avatarUrl - } - company { - id - name - domainName - accountOwner { - id - displayName - avatarUrl - } - } - } -} - `; - -/** - * __useGetFavoritesQuery__ - * - * To run a query within a React component, call `useGetFavoritesQuery` and pass it any options that fit your needs. - * When your component renders, `useGetFavoritesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetFavoritesQuery({ - * variables: { - * }, - * }); - */ -export function useGetFavoritesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetFavoritesDocument, options); - } -export function useGetFavoritesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetFavoritesDocument, options); - } -export type GetFavoritesQueryHookResult = ReturnType; -export type GetFavoritesLazyQueryHookResult = ReturnType; -export type GetFavoritesQueryResult = Apollo.QueryResult; -export const DeleteManyPersonDocument = gql` - mutation DeleteManyPerson($ids: [String!]) { - deleteManyPerson(where: {id: {in: $ids}}) { - count - } -} - `; -export type DeleteManyPersonMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteManyPersonMutation__ - * - * To run a mutation, you first call `useDeleteManyPersonMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteManyPersonMutation` 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 [deleteManyPersonMutation, { data, loading, error }] = useDeleteManyPersonMutation({ - * variables: { - * ids: // value for 'ids' - * }, - * }); - */ -export function useDeleteManyPersonMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteManyPersonDocument, options); - } -export type DeleteManyPersonMutationHookResult = ReturnType; -export type DeleteManyPersonMutationResult = Apollo.MutationResult; -export type DeleteManyPersonMutationOptions = Apollo.BaseMutationOptions; -export const InsertManyPersonDocument = gql` - mutation InsertManyPerson($data: [PersonCreateManyInput!]!) { - createManyPerson(data: $data) { - count - } -} - `; -export type InsertManyPersonMutationFn = Apollo.MutationFunction; - -/** - * __useInsertManyPersonMutation__ - * - * To run a mutation, you first call `useInsertManyPersonMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertManyPersonMutation` 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 [insertManyPersonMutation, { data, loading, error }] = useInsertManyPersonMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertManyPersonMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertManyPersonDocument, options); - } -export type InsertManyPersonMutationHookResult = ReturnType; -export type InsertManyPersonMutationResult = Apollo.MutationResult; -export type InsertManyPersonMutationOptions = Apollo.BaseMutationOptions; -export const InsertOnePersonDocument = gql` - mutation InsertOnePerson($data: PersonCreateInput!) { - createOnePerson(data: $data) { - ...personFieldsFragment - } -} - ${PersonFieldsFragmentFragmentDoc}`; -export type InsertOnePersonMutationFn = Apollo.MutationFunction; - -/** - * __useInsertOnePersonMutation__ - * - * To run a mutation, you first call `useInsertOnePersonMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertOnePersonMutation` 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 [insertOnePersonMutation, { data, loading, error }] = useInsertOnePersonMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertOnePersonMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertOnePersonDocument, options); - } -export type InsertOnePersonMutationHookResult = ReturnType; -export type InsertOnePersonMutationResult = Apollo.MutationResult; -export type InsertOnePersonMutationOptions = Apollo.BaseMutationOptions; -export const RemovePersonPictureDocument = gql` - mutation RemovePersonPicture($where: PersonWhereUniqueInput!) { - updateOnePerson(data: {avatarUrl: null}, where: $where) { - id - avatarUrl - } -} - `; -export type RemovePersonPictureMutationFn = Apollo.MutationFunction; - -/** - * __useRemovePersonPictureMutation__ - * - * To run a mutation, you first call `useRemovePersonPictureMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useRemovePersonPictureMutation` 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 [removePersonPictureMutation, { data, loading, error }] = useRemovePersonPictureMutation({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useRemovePersonPictureMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(RemovePersonPictureDocument, options); - } -export type RemovePersonPictureMutationHookResult = ReturnType; -export type RemovePersonPictureMutationResult = Apollo.MutationResult; -export type RemovePersonPictureMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOnePersonDocument = gql` - mutation UpdateOnePerson($where: PersonWhereUniqueInput!, $data: PersonUpdateInput!) { - updateOnePerson(data: $data, where: $where) { - ...personFieldsFragment - } -} - ${PersonFieldsFragmentFragmentDoc}`; -export type UpdateOnePersonMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOnePersonMutation__ - * - * To run a mutation, you first call `useUpdateOnePersonMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOnePersonMutation` 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 [updateOnePersonMutation, { data, loading, error }] = useUpdateOnePersonMutation({ - * variables: { - * where: // value for 'where' - * data: // value for 'data' - * }, - * }); - */ -export function useUpdateOnePersonMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOnePersonDocument, options); - } -export type UpdateOnePersonMutationHookResult = ReturnType; -export type UpdateOnePersonMutationResult = Apollo.MutationResult; -export type UpdateOnePersonMutationOptions = Apollo.BaseMutationOptions; -export const UploadPersonPictureDocument = gql` - mutation UploadPersonPicture($id: String!, $file: Upload!) { - uploadPersonPicture(id: $id, file: $file) -} - `; -export type UploadPersonPictureMutationFn = Apollo.MutationFunction; - -/** - * __useUploadPersonPictureMutation__ - * - * To run a mutation, you first call `useUploadPersonPictureMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUploadPersonPictureMutation` 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 [uploadPersonPictureMutation, { data, loading, error }] = useUploadPersonPictureMutation({ - * variables: { - * id: // value for 'id' - * file: // value for 'file' - * }, - * }); - */ -export function useUploadPersonPictureMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UploadPersonPictureDocument, options); - } -export type UploadPersonPictureMutationHookResult = ReturnType; -export type UploadPersonPictureMutationResult = Apollo.MutationResult; -export type UploadPersonPictureMutationOptions = Apollo.BaseMutationOptions; -export const GetPeopleDocument = gql` - query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) { - people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) { - ...personFieldsFragment - } -} - ${PersonFieldsFragmentFragmentDoc}`; - -/** - * __useGetPeopleQuery__ - * - * To run a query within a React component, call `useGetPeopleQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPeopleQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPeopleQuery({ - * variables: { - * orderBy: // value for 'orderBy' - * where: // value for 'where' - * limit: // value for 'limit' - * }, - * }); - */ -export function useGetPeopleQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPeopleDocument, options); - } -export function useGetPeopleLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPeopleDocument, options); - } -export type GetPeopleQueryHookResult = ReturnType; -export type GetPeopleLazyQueryHookResult = ReturnType; -export type GetPeopleQueryResult = Apollo.QueryResult; -export const GetPersonDocument = gql` - query GetPerson($id: String!) { - findUniquePerson(id: $id) { - ...personFieldsFragment - Favorite { - id - person { - id - } - company { - id - } - } - } -} - ${PersonFieldsFragmentFragmentDoc}`; - -/** - * __useGetPersonQuery__ - * - * To run a query within a React component, call `useGetPersonQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonDocument, options); - } -export function useGetPersonLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonDocument, options); - } -export type GetPersonQueryHookResult = ReturnType; -export type GetPersonLazyQueryHookResult = ReturnType; -export type GetPersonQueryResult = Apollo.QueryResult; -export const GetPersonCityByIdDocument = gql` - query GetPersonCityById($id: String!) { - person: findUniquePerson(id: $id) { - id - city - } -} - `; - -/** - * __useGetPersonCityByIdQuery__ - * - * To run a query within a React component, call `useGetPersonCityByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonCityByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonCityByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonCityByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonCityByIdDocument, options); - } -export function useGetPersonCityByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonCityByIdDocument, options); - } -export type GetPersonCityByIdQueryHookResult = ReturnType; -export type GetPersonCityByIdLazyQueryHookResult = ReturnType; -export type GetPersonCityByIdQueryResult = Apollo.QueryResult; -export const GetPersonCommentCountByIdDocument = gql` - query GetPersonCommentCountById($id: String!) { - person: findUniquePerson(id: $id) { - id - _activityCount - } -} - `; - -/** - * __useGetPersonCommentCountByIdQuery__ - * - * To run a query within a React component, call `useGetPersonCommentCountByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonCommentCountByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonCommentCountByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonCommentCountByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonCommentCountByIdDocument, options); - } -export function useGetPersonCommentCountByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonCommentCountByIdDocument, options); - } -export type GetPersonCommentCountByIdQueryHookResult = ReturnType; -export type GetPersonCommentCountByIdLazyQueryHookResult = ReturnType; -export type GetPersonCommentCountByIdQueryResult = Apollo.QueryResult; -export const GetPersonCompanyByIdDocument = gql` - query GetPersonCompanyById($id: String!) { - person: findUniquePerson(id: $id) { - id - company { - id - name - domainName - } - } -} - `; - -/** - * __useGetPersonCompanyByIdQuery__ - * - * To run a query within a React component, call `useGetPersonCompanyByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonCompanyByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonCompanyByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonCompanyByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonCompanyByIdDocument, options); - } -export function useGetPersonCompanyByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonCompanyByIdDocument, options); - } -export type GetPersonCompanyByIdQueryHookResult = ReturnType; -export type GetPersonCompanyByIdLazyQueryHookResult = ReturnType; -export type GetPersonCompanyByIdQueryResult = Apollo.QueryResult; -export const GetPersonCreatedAtByIdDocument = gql` - query GetPersonCreatedAtById($id: String!) { - person: findUniquePerson(id: $id) { - id - createdAt - } -} - `; - -/** - * __useGetPersonCreatedAtByIdQuery__ - * - * To run a query within a React component, call `useGetPersonCreatedAtByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonCreatedAtByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonCreatedAtByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonCreatedAtByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonCreatedAtByIdDocument, options); - } -export function useGetPersonCreatedAtByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonCreatedAtByIdDocument, options); - } -export type GetPersonCreatedAtByIdQueryHookResult = ReturnType; -export type GetPersonCreatedAtByIdLazyQueryHookResult = ReturnType; -export type GetPersonCreatedAtByIdQueryResult = Apollo.QueryResult; -export const GetPersonEmailByIdDocument = gql` - query GetPersonEmailById($id: String!) { - person: findUniquePerson(id: $id) { - id - email - } -} - `; - -/** - * __useGetPersonEmailByIdQuery__ - * - * To run a query within a React component, call `useGetPersonEmailByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonEmailByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonEmailByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonEmailByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonEmailByIdDocument, options); - } -export function useGetPersonEmailByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonEmailByIdDocument, options); - } -export type GetPersonEmailByIdQueryHookResult = ReturnType; -export type GetPersonEmailByIdLazyQueryHookResult = ReturnType; -export type GetPersonEmailByIdQueryResult = Apollo.QueryResult; -export const GetPersonNamesAndCommentCountByIdDocument = gql` - query GetPersonNamesAndCommentCountById($id: String!) { - person: findUniquePerson(id: $id) { - id - firstName - lastName - displayName - _activityCount - } -} - `; - -/** - * __useGetPersonNamesAndCommentCountByIdQuery__ - * - * To run a query within a React component, call `useGetPersonNamesAndCommentCountByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonNamesAndCommentCountByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonNamesAndCommentCountByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonNamesAndCommentCountByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonNamesAndCommentCountByIdDocument, options); - } -export function useGetPersonNamesAndCommentCountByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonNamesAndCommentCountByIdDocument, options); - } -export type GetPersonNamesAndCommentCountByIdQueryHookResult = ReturnType; -export type GetPersonNamesAndCommentCountByIdLazyQueryHookResult = ReturnType; -export type GetPersonNamesAndCommentCountByIdQueryResult = Apollo.QueryResult; -export const GetPersonPhoneByIdDocument = gql` - query GetPersonPhoneById($id: String!) { - person: findUniquePerson(id: $id) { - id - phone - } -} - `; - -/** - * __useGetPersonPhoneByIdQuery__ - * - * To run a query within a React component, call `useGetPersonPhoneByIdQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPersonPhoneByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetPersonPhoneByIdQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useGetPersonPhoneByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPersonPhoneByIdDocument, options); - } -export function useGetPersonPhoneByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPersonPhoneByIdDocument, options); - } -export type GetPersonPhoneByIdQueryHookResult = ReturnType; -export type GetPersonPhoneByIdLazyQueryHookResult = ReturnType; -export type GetPersonPhoneByIdQueryResult = Apollo.QueryResult; -export const SearchActivityDocument = gql` - query SearchActivity($where: ActivityWhereInput, $limit: Int, $orderBy: [ActivityOrderByWithRelationInput!]) { - searchResults: findManyActivities( - where: $where - take: $limit - orderBy: $orderBy - ) { - id - title - body - } -} - `; - -/** - * __useSearchActivityQuery__ - * - * To run a query within a React component, call `useSearchActivityQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchActivityQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useSearchActivityQuery({ - * variables: { - * where: // value for 'where' - * limit: // value for 'limit' - * orderBy: // value for 'orderBy' - * }, - * }); - */ -export function useSearchActivityQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchActivityDocument, options); - } -export function useSearchActivityLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchActivityDocument, options); - } -export type SearchActivityQueryHookResult = ReturnType; -export type SearchActivityLazyQueryHookResult = ReturnType; -export type SearchActivityQueryResult = Apollo.QueryResult; -export const SearchCompanyDocument = gql` - query SearchCompany($where: CompanyWhereInput, $limit: Int, $orderBy: [CompanyOrderByWithRelationInput!]) { - searchResults: findManyCompany(where: $where, take: $limit, orderBy: $orderBy) { - ...companyFieldsFragment - } -} - ${CompanyFieldsFragmentFragmentDoc}`; - -/** - * __useSearchCompanyQuery__ - * - * To run a query within a React component, call `useSearchCompanyQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchCompanyQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useSearchCompanyQuery({ - * variables: { - * where: // value for 'where' - * limit: // value for 'limit' - * orderBy: // value for 'orderBy' - * }, - * }); - */ -export function useSearchCompanyQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchCompanyDocument, options); - } -export function useSearchCompanyLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchCompanyDocument, options); - } -export type SearchCompanyQueryHookResult = ReturnType; -export type SearchCompanyLazyQueryHookResult = ReturnType; -export type SearchCompanyQueryResult = Apollo.QueryResult; -export const SearchPeopleDocument = gql` - query SearchPeople($where: PersonWhereInput, $limit: Int, $orderBy: [PersonOrderByWithRelationInput!]) { - searchResults: findManyPerson(where: $where, take: $limit, orderBy: $orderBy) { - ...basePersonFieldsFragment - } -} - ${BasePersonFieldsFragmentFragmentDoc}`; - -/** - * __useSearchPeopleQuery__ - * - * To run a query within a React component, call `useSearchPeopleQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchPeopleQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useSearchPeopleQuery({ - * variables: { - * where: // value for 'where' - * limit: // value for 'limit' - * orderBy: // value for 'orderBy' - * }, - * }); - */ -export function useSearchPeopleQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchPeopleDocument, options); - } -export function useSearchPeopleLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchPeopleDocument, options); - } -export type SearchPeopleQueryHookResult = ReturnType; -export type SearchPeopleLazyQueryHookResult = ReturnType; -export type SearchPeopleQueryResult = Apollo.QueryResult; -export const SearchUserDocument = gql` - query SearchUser($where: UserWhereInput, $limit: Int, $orderBy: [UserOrderByWithRelationInput!]) { - searchResults: findManyUser(where: $where, take: $limit, orderBy: $orderBy) { - ...userFieldsFragment - avatarUrl - } -} - ${UserFieldsFragmentFragmentDoc}`; - -/** - * __useSearchUserQuery__ - * - * To run a query within a React component, call `useSearchUserQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchUserQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useSearchUserQuery({ - * variables: { - * where: // value for 'where' - * limit: // value for 'limit' - * orderBy: // value for 'orderBy' - * }, - * }); - */ -export function useSearchUserQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchUserDocument, options); - } -export function useSearchUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchUserDocument, options); - } -export type SearchUserQueryHookResult = ReturnType; -export type SearchUserLazyQueryHookResult = ReturnType; -export type SearchUserQueryResult = Apollo.QueryResult; -export const DeleteOneApiKeyDocument = gql` - mutation DeleteOneApiKey($apiKeyId: String!) { - revokeOneApiKey(where: {id: $apiKeyId}) { - id - } -} - `; -export type DeleteOneApiKeyMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteOneApiKeyMutation__ - * - * To run a mutation, you first call `useDeleteOneApiKeyMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteOneApiKeyMutation` 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 [deleteOneApiKeyMutation, { data, loading, error }] = useDeleteOneApiKeyMutation({ - * variables: { - * apiKeyId: // value for 'apiKeyId' - * }, - * }); - */ -export function useDeleteOneApiKeyMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteOneApiKeyDocument, options); - } -export type DeleteOneApiKeyMutationHookResult = ReturnType; -export type DeleteOneApiKeyMutationResult = Apollo.MutationResult; -export type DeleteOneApiKeyMutationOptions = Apollo.BaseMutationOptions; -export const GenerateOneApiKeyTokenDocument = gql` - mutation GenerateOneApiKeyToken($data: ApiKeyCreateInput!) { - generateApiKeyV2Token(data: $data) { - token - } -} - `; -export type GenerateOneApiKeyTokenMutationFn = Apollo.MutationFunction; - -/** - * __useGenerateOneApiKeyTokenMutation__ - * - * To run a mutation, you first call `useGenerateOneApiKeyTokenMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useGenerateOneApiKeyTokenMutation` 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 [generateOneApiKeyTokenMutation, { data, loading, error }] = useGenerateOneApiKeyTokenMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useGenerateOneApiKeyTokenMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(GenerateOneApiKeyTokenDocument, options); - } -export type GenerateOneApiKeyTokenMutationHookResult = ReturnType; -export type GenerateOneApiKeyTokenMutationResult = Apollo.MutationResult; -export type GenerateOneApiKeyTokenMutationOptions = Apollo.BaseMutationOptions; -export const InsertOneApiKeyDocument = gql` - mutation InsertOneApiKey($data: ApiKeyCreateInput!) { - createOneApiKey(data: $data) { - id - name - token - createdAt - expiresAt - } -} - `; -export type InsertOneApiKeyMutationFn = Apollo.MutationFunction; - -/** - * __useInsertOneApiKeyMutation__ - * - * To run a mutation, you first call `useInsertOneApiKeyMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useInsertOneApiKeyMutation` 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 [insertOneApiKeyMutation, { data, loading, error }] = useInsertOneApiKeyMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useInsertOneApiKeyMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(InsertOneApiKeyDocument, options); - } -export type InsertOneApiKeyMutationHookResult = ReturnType; -export type InsertOneApiKeyMutationResult = Apollo.MutationResult; -export type InsertOneApiKeyMutationOptions = Apollo.BaseMutationOptions; -export const GetApiKeyDocument = gql` - query GetApiKey($apiKeyId: String!) { - findManyApiKey(where: {id: {equals: $apiKeyId}}) { - id - name - expiresAt - createdAt - } -} - `; - -/** - * __useGetApiKeyQuery__ - * - * To run a query within a React component, call `useGetApiKeyQuery` and pass it any options that fit your needs. - * When your component renders, `useGetApiKeyQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetApiKeyQuery({ - * variables: { - * apiKeyId: // value for 'apiKeyId' - * }, - * }); - */ -export function useGetApiKeyQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetApiKeyDocument, options); - } -export function useGetApiKeyLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetApiKeyDocument, options); - } -export type GetApiKeyQueryHookResult = ReturnType; -export type GetApiKeyLazyQueryHookResult = ReturnType; -export type GetApiKeyQueryResult = Apollo.QueryResult; -export const GetApiKeysDocument = gql` - query GetApiKeys { - findManyApiKey { - id - name - expiresAt - createdAt - } -} - `; - -/** - * __useGetApiKeysQuery__ - * - * To run a query within a React component, call `useGetApiKeysQuery` and pass it any options that fit your needs. - * When your component renders, `useGetApiKeysQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetApiKeysQuery({ - * variables: { - * }, - * }); - */ -export function useGetApiKeysQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetApiKeysDocument, options); - } -export function useGetApiKeysLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetApiKeysDocument, options); - } -export type GetApiKeysQueryHookResult = ReturnType; -export type GetApiKeysLazyQueryHookResult = ReturnType; -export type GetApiKeysQueryResult = Apollo.QueryResult; export const DeleteUserAccountDocument = gql` mutation DeleteUserAccount { - deleteUserAccount { + deleteUser { id } } @@ -5529,74 +1105,6 @@ export function useDeleteUserAccountMutation(baseOptions?: Apollo.MutationHookOp export type DeleteUserAccountMutationHookResult = ReturnType; export type DeleteUserAccountMutationResult = Apollo.MutationResult; export type DeleteUserAccountMutationOptions = Apollo.BaseMutationOptions; -export const RemoveProfilePictureDocument = gql` - mutation RemoveProfilePicture($where: UserWhereUniqueInput!) { - updateUser(data: {avatarUrl: null}, where: $where) { - id - avatarUrl - } -} - `; -export type RemoveProfilePictureMutationFn = Apollo.MutationFunction; - -/** - * __useRemoveProfilePictureMutation__ - * - * To run a mutation, you first call `useRemoveProfilePictureMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useRemoveProfilePictureMutation` 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 [removeProfilePictureMutation, { data, loading, error }] = useRemoveProfilePictureMutation({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useRemoveProfilePictureMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(RemoveProfilePictureDocument, options); - } -export type RemoveProfilePictureMutationHookResult = ReturnType; -export type RemoveProfilePictureMutationResult = Apollo.MutationResult; -export type RemoveProfilePictureMutationOptions = Apollo.BaseMutationOptions; -export const UpdateAllowImpersonationDocument = gql` - mutation UpdateAllowImpersonation($allowImpersonation: Boolean!) { - allowImpersonation(allowImpersonation: $allowImpersonation) { - id - allowImpersonation - } -} - `; -export type UpdateAllowImpersonationMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateAllowImpersonationMutation__ - * - * To run a mutation, you first call `useUpdateAllowImpersonationMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateAllowImpersonationMutation` 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 [updateAllowImpersonationMutation, { data, loading, error }] = useUpdateAllowImpersonationMutation({ - * variables: { - * allowImpersonation: // value for 'allowImpersonation' - * }, - * }); - */ -export function useUpdateAllowImpersonationMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateAllowImpersonationDocument, options); - } -export type UpdateAllowImpersonationMutationHookResult = ReturnType; -export type UpdateAllowImpersonationMutationResult = Apollo.MutationResult; -export type UpdateAllowImpersonationMutationOptions = Apollo.BaseMutationOptions; export const UploadProfilePictureDocument = gql` mutation UploadProfilePicture($file: Upload!) { uploadProfilePicture(file: $file) @@ -5628,50 +1136,36 @@ export function useUploadProfilePictureMutation(baseOptions?: Apollo.MutationHoo export type UploadProfilePictureMutationHookResult = ReturnType; export type UploadProfilePictureMutationResult = Apollo.MutationResult; export type UploadProfilePictureMutationOptions = Apollo.BaseMutationOptions; -export const UpdateUserDocument = gql` - mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) { - updateUser(data: $data, where: $where) { - id - email - } -} - `; -export type UpdateUserMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateUserMutation__ - * - * To run a mutation, you first call `useUpdateUserMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateUserMutation` 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 [updateUserMutation, { data, loading, error }] = useUpdateUserMutation({ - * variables: { - * data: // value for 'data' - * where: // value for 'where' - * }, - * }); - */ -export function useUpdateUserMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateUserDocument, options); - } -export type UpdateUserMutationHookResult = ReturnType; -export type UpdateUserMutationResult = Apollo.MutationResult; -export type UpdateUserMutationOptions = Apollo.BaseMutationOptions; export const GetCurrentUserDocument = gql` query GetCurrentUser { currentUser { - ...userFieldsFragment + id + firstName + lastName + email canImpersonate supportUserHash + workspaceMember { + id + name { + firstName + lastName + } + colorScheme + avatarUrl + locale + allowImpersonation + } + defaultWorkspace { + id + displayName + logo + domainName + inviteHash + } } } - ${UserFieldsFragmentFragmentDoc}`; + `; /** * __useGetCurrentUserQuery__ @@ -5699,40 +1193,6 @@ export function useGetCurrentUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt export type GetCurrentUserQueryHookResult = ReturnType; export type GetCurrentUserLazyQueryHookResult = ReturnType; export type GetCurrentUserQueryResult = Apollo.QueryResult; -export const GetUsersDocument = gql` - query GetUsers { - findManyUser { - ...userFieldsFragment - } -} - ${UserFieldsFragmentFragmentDoc}`; - -/** - * __useGetUsersQuery__ - * - * To run a query within a React component, call `useGetUsersQuery` and pass it any options that fit your needs. - * When your component renders, `useGetUsersQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetUsersQuery({ - * variables: { - * }, - * }); - */ -export function useGetUsersQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetUsersDocument, options); - } -export function useGetUsersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetUsersDocument, options); - } -export type GetUsersQueryHookResult = ReturnType; -export type GetUsersLazyQueryHookResult = ReturnType; -export type GetUsersQueryResult = Apollo.QueryResult; export const DeleteCurrentWorkspaceDocument = gql` mutation DeleteCurrentWorkspace { deleteCurrentWorkspace { @@ -5765,41 +1225,9 @@ export function useDeleteCurrentWorkspaceMutation(baseOptions?: Apollo.MutationH export type DeleteCurrentWorkspaceMutationHookResult = ReturnType; export type DeleteCurrentWorkspaceMutationResult = Apollo.MutationResult; export type DeleteCurrentWorkspaceMutationOptions = Apollo.BaseMutationOptions; -export const RemoveWorkspaceLogoDocument = gql` - mutation RemoveWorkspaceLogo { - updateWorkspace(data: {logo: null}) { - id - } -} - `; -export type RemoveWorkspaceLogoMutationFn = Apollo.MutationFunction; - -/** - * __useRemoveWorkspaceLogoMutation__ - * - * To run a mutation, you first call `useRemoveWorkspaceLogoMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useRemoveWorkspaceLogoMutation` 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 [removeWorkspaceLogoMutation, { data, loading, error }] = useRemoveWorkspaceLogoMutation({ - * variables: { - * }, - * }); - */ -export function useRemoveWorkspaceLogoMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(RemoveWorkspaceLogoDocument, options); - } -export type RemoveWorkspaceLogoMutationHookResult = ReturnType; -export type RemoveWorkspaceLogoMutationResult = Apollo.MutationResult; -export type RemoveWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions; export const UpdateWorkspaceDocument = gql` - mutation UpdateWorkspace($data: WorkspaceUpdateInput!) { - updateWorkspace(data: $data) { + mutation UpdateWorkspace($input: UpdateWorkspaceInput!) { + updateWorkspace(data: $input) { id domainName displayName @@ -5822,7 +1250,7 @@ export type UpdateWorkspaceMutationFn = Apollo.MutationFunction; export type UploadWorkspaceLogoMutationResult = Apollo.MutationResult; export type UploadWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions; -export const GetCurrentWorkspaceDocument = gql` - query getCurrentWorkspace { - currentWorkspace { - id - displayName - logo - } -} - `; - -/** - * __useGetCurrentWorkspaceQuery__ - * - * To run a query within a React component, call `useGetCurrentWorkspaceQuery` and pass it any options that fit your needs. - * When your component renders, `useGetCurrentWorkspaceQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetCurrentWorkspaceQuery({ - * variables: { - * }, - * }); - */ -export function useGetCurrentWorkspaceQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetCurrentWorkspaceDocument, options); - } -export function useGetCurrentWorkspaceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetCurrentWorkspaceDocument, options); - } -export type GetCurrentWorkspaceQueryHookResult = ReturnType; -export type GetCurrentWorkspaceLazyQueryHookResult = ReturnType; -export type GetCurrentWorkspaceQueryResult = Apollo.QueryResult; export const GetWorkspaceFromInviteHashDocument = gql` query GetWorkspaceFromInviteHash($inviteHash: String!) { findWorkspaceFromInviteHash(inviteHash: $inviteHash) { @@ -5936,39 +1328,4 @@ export function useGetWorkspaceFromInviteHashLazyQuery(baseOptions?: Apollo.Lazy } export type GetWorkspaceFromInviteHashQueryHookResult = ReturnType; export type GetWorkspaceFromInviteHashLazyQueryHookResult = ReturnType; -export type GetWorkspaceFromInviteHashQueryResult = Apollo.QueryResult; -export const GetWorkspaceMembersDocument = gql` - query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) { - workspaceMembers: findManyWorkspaceMember(where: $where) { - id - } -} - `; - -/** - * __useGetWorkspaceMembersQuery__ - * - * To run a query within a React component, call `useGetWorkspaceMembersQuery` and pass it any options that fit your needs. - * When your component renders, `useGetWorkspaceMembersQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @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 - * const { data, loading, error } = useGetWorkspaceMembersQuery({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useGetWorkspaceMembersQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetWorkspaceMembersDocument, options); - } -export function useGetWorkspaceMembersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetWorkspaceMembersDocument, options); - } -export type GetWorkspaceMembersQueryHookResult = ReturnType; -export type GetWorkspaceMembersLazyQueryHookResult = ReturnType; -export type GetWorkspaceMembersQueryResult = Apollo.QueryResult; \ No newline at end of file +export type GetWorkspaceFromInviteHashQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/front/src/index.tsx b/front/src/index.tsx index 9e2955fc3..50c8202e4 100644 --- a/front/src/index.tsx +++ b/front/src/index.tsx @@ -8,6 +8,7 @@ import { ApolloProvider } from '@/apollo/components/ApolloProvider'; import { ClientConfigProvider } from '@/client-config/components/ClientConfigProvider'; import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver'; import { ApolloMetadataClientProvider } from '@/object-metadata/components/ApolloMetadataClientProvider'; +import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider'; import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager'; import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope'; import { SnackBarProvider } from '@/ui/feedback/snack-bar/components/SnackBarProvider'; @@ -36,18 +37,20 @@ root.render( - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/front/src/modules/activities/components/ActivityAssigneePicker.tsx b/front/src/modules/activities/components/ActivityAssigneePicker.tsx deleted file mode 100644 index 55cf3c3bd..000000000 --- a/front/src/modules/activities/components/ActivityAssigneePicker.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { Activity } from '@/activities/types/Activity'; -import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; -import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; -import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect'; -import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState'; -import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { - useGetWorkspaceMembersLazyQuery, - useSearchUserQuery, -} from '~/generated/graphql'; - -export type ActivityAssigneePickerProps = { - activity: Pick & { - accountOwner?: Pick | null; - }; - onSubmit?: () => void; - onCancel?: () => void; -}; - -type UserForSelect = EntityForSelect & { - entityType: Entity.User; -}; - -export const ActivityAssigneePicker = ({ - activity, - onSubmit, - onCancel, -}: ActivityAssigneePickerProps) => { - const [relationPickerSearchFilter] = useRecoilScopedState( - relationPickerSearchFilterScopedState, - ); - const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'ActivityV2', - }); - const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery(); - - const users = useFilteredSearchEntityQuery({ - queryHook: useSearchUserQuery, - filters: [ - { - fieldNames: ['firstName', 'lastName'], - filter: relationPickerSearchFilter, - }, - ], - orderByField: 'firstName', - mappingFunction: (user) => ({ - entityType: Entity.User, - id: user.id, - name: user.displayName, - firstName: user.firstName, - lastName: user.lastName, - avatarType: 'rounded', - avatarUrl: user.avatarUrl ?? '', - originalEntity: user, - }), - selectedIds: activity?.accountOwner?.id ? [activity?.accountOwner?.id] : [], - }); - - const handleEntitySelected = async ( - selectedUser: UserForSelect | null | undefined, - ) => { - if (selectedUser) { - const workspaceMemberAssignee = ( - await getWorkspaceMember({ - variables: { - where: { - userId: { equals: selectedUser.id }, - }, - }, - }) - ).data?.workspaceMembers?.[0]; - - updateOneObject?.({ - idToUpdate: activity.id, - input: { - assignee: { connect: { id: selectedUser.id } }, - workspaceMemberAssignee: { - connect: { id: workspaceMemberAssignee?.id }, - }, - }, - }); - } - - onSubmit?.(); - }; - - return ( - - ); -}; diff --git a/front/src/modules/activities/components/ActivityBodyEditor.tsx b/front/src/modules/activities/components/ActivityBodyEditor.tsx index 6a17ed49a..47de9f465 100644 --- a/front/src/modules/activities/components/ActivityBodyEditor.tsx +++ b/front/src/modules/activities/components/ActivityBodyEditor.tsx @@ -23,7 +23,7 @@ export const ActivityBodyEditor = ({ }: ActivityBodyEditorProps) => { const [body, setBody] = useState(null); const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'ActivityV2', + objectNameSingular: 'Activity', }); useEffect(() => { diff --git a/front/src/modules/activities/components/ActivityComments.tsx b/front/src/modules/activities/components/ActivityComments.tsx index 4728575ca..e144c13c3 100644 --- a/front/src/modules/activities/components/ActivityComments.tsx +++ b/front/src/modules/activities/components/ActivityComments.tsx @@ -63,7 +63,7 @@ export const ActivityComments = ({ }: ActivityCommentsProps) => { const currentUser = useRecoilValue(currentUserState); const { createOneObject } = useCreateOneObjectRecord({ - objectNameSingular: 'commentV2', + objectNameSingular: 'comment', }); if (!currentUser) { diff --git a/front/src/modules/activities/components/ActivityEditor.tsx b/front/src/modules/activities/components/ActivityEditor.tsx index 5deb9559c..f21c8ac00 100644 --- a/front/src/modules/activities/components/ActivityEditor.tsx +++ b/front/src/modules/activities/components/ActivityEditor.tsx @@ -9,13 +9,10 @@ import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { Comment } from '@/activities/types/Comment'; import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; import { PropertyBox } from '@/ui/object/record-inline-cell/property-box/components/PropertyBox'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { debounce } from '~/utils/debounce'; -import { ActivityAssigneeEditableField } from '../editable-fields/components/ActivityAssigneeEditableField'; -import { ActivityEditorDateField } from '../editable-fields/components/ActivityEditorDateField'; import { ActivityRelationEditableField } from '../editable-fields/components/ActivityRelationEditableField'; import { ActivityTitle } from './ActivityTitle'; @@ -84,7 +81,7 @@ export const ActivityEditor = ({ ); const containerRef = useRef(null); const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'activityV2', + objectNameSingular: 'activity', }); const updateTitle = useCallback( @@ -144,12 +141,12 @@ export const ActivityEditor = ({ {activity.type === 'Task' && ( <> - + {/* - + */} )} diff --git a/front/src/modules/activities/components/ActivityTargetChips.tsx b/front/src/modules/activities/components/ActivityTargetChips.tsx index cc649bebb..48470e31d 100644 --- a/front/src/modules/activities/components/ActivityTargetChips.tsx +++ b/front/src/modules/activities/components/ActivityTargetChips.tsx @@ -2,8 +2,9 @@ import styled from '@emotion/styled'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { CompanyChip } from '@/companies/components/CompanyChip'; +import { Company } from '@/companies/types/Company'; import { PersonChip } from '@/people/components/PersonChip'; -import { Company, Person } from '~/generated/graphql'; +import { Person } from '@/people/types/Person'; import { getLogoUrlFromDomainName } from '~/utils'; const StyledContainer = styled.div` @@ -17,10 +18,7 @@ export const ActivityTargetChips = ({ }: { targets?: Array< Pick & { - person?: Pick< - Person, - 'id' | 'firstName' | 'lastName' | 'avatarUrl' - > | null; + person?: Pick | null; company?: Pick | null; } > | null; @@ -47,7 +45,7 @@ export const ActivityTargetChips = ({ ); diff --git a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx b/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx deleted file mode 100644 index 238c38751..000000000 --- a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useMemo } from 'react'; - -import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; -import { IconUserCircle } from '@/ui/display/icon'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { FieldContext } from '@/ui/object/field/contexts/FieldContext'; -import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition'; -import { FieldRelationMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/RecordInlineCell'; -import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; -import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { Company, User } from '~/generated/graphql'; - -type ActivityAssigneeEditableFieldProps = { - activity: Pick & { - assignee?: Pick | null; - }; -}; - -export const ActivityAssigneeEditableField = ({ - activity, -}: ActivityAssigneeEditableFieldProps) => { - const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => { - const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'activityV2', - }); - - const updateEntity = ({ - variables, - }: { - variables: { - where: { id: string }; - data: { - [fieldName: string]: any; - }; - }; - }) => { - updateOneObject?.({ - idToUpdate: variables.where.id, - input: variables.data, - }); - }; - - return [updateEntity, { loading: false }]; - }; - const value = useMemo( - () => ({ - entityId: activity.id, - recoilScopeId: 'assignee', - fieldDefinition: { - fieldMetadataId: 'assignee', - label: 'Assignee', - Icon: IconUserCircle, - type: 'RELATION', - metadata: { - fieldName: 'assignee', - relationType: Entity.User, - }, - entityChipDisplayMapper: (dataObject: User) => { - return { - name: dataObject?.displayName, - pictureUrl: dataObject?.avatarUrl ?? undefined, - avatarType: 'rounded', - }; - }, - } satisfies FieldDefinition, - useUpdateEntityMutation: useUpdateOneObjectMutation, - hotkeyScope: InlineCellHotkeyScope.InlineCell, - }), - [activity.id], - ); - - return ( - - - - ); -}; diff --git a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableFieldEditMode.tsx b/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableFieldEditMode.tsx deleted file mode 100644 index 82fdef58d..000000000 --- a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableFieldEditMode.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import styled from '@emotion/styled'; - -import { ActivityAssigneePicker } from '@/activities/components/ActivityAssigneePicker'; -import { useInlineCell } from '@/ui/object/record-inline-cell/hooks/useInlineCell'; -import { Activity, User } from '~/generated/graphql'; - -const StyledContainer = styled.div` - left: 0px; - position: absolute; - top: -8px; -`; - -export type ActivityAssigneeEditableFieldEditModeProps = { - activity: Pick & { - assignee?: Pick | null; - }; - onSubmit?: () => void; - onCancel?: () => void; -}; - -export const ActivityAssigneeEditableFieldEditMode = ({ - activity, - onSubmit, - onCancel, -}: ActivityAssigneeEditableFieldEditModeProps) => { - const { closeInlineCell: closeEditableField } = useInlineCell(); - - const handleSubmit = () => { - closeEditableField(); - onSubmit?.(); - }; - - const handleCancel = () => { - closeEditableField(); - onCancel?.(); - }; - - return ( - - - - ); -}; diff --git a/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx b/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx deleted file mode 100644 index 1187217ea..000000000 --- a/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; -import { IconCalendar } from '@/ui/display/icon/index'; -import { FieldContext } from '@/ui/object/field/contexts/FieldContext'; -import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition'; -import { FieldDateMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/RecordInlineCell'; -import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; - -type ActivityEditorDateFieldProps = { - activityId: string; -}; - -export const ActivityEditorDateField = ({ - activityId, -}: ActivityEditorDateFieldProps) => { - const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => { - const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'activityV2', - }); - - const updateEntity = ({ - variables, - }: { - variables: { - where: { id: string }; - data: { - [fieldName: string]: any; - }; - }; - }) => { - updateOneObject?.({ - idToUpdate: variables.where.id, - input: variables.data, - }); - }; - - return [updateEntity, { loading: false }]; - }; - - return ( - - , - useUpdateEntityMutation: useUpdateOneObjectMutation, - hotkeyScope: InlineCellHotkeyScope.InlineCell, - }} - > - - - - ); -}; diff --git a/front/src/modules/activities/editable-fields/components/ActivityRelationEditableField.tsx b/front/src/modules/activities/editable-fields/components/ActivityRelationEditableField.tsx index ddf4efc7f..93158e9da 100644 --- a/front/src/modules/activities/editable-fields/components/ActivityRelationEditableField.tsx +++ b/front/src/modules/activities/editable-fields/components/ActivityRelationEditableField.tsx @@ -1,12 +1,13 @@ import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips'; import { Activity } from '@/activities/types/Activity'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; +import { Company } from '@/companies/types/Company'; +import { Person } from '@/people/types/Person'; import { IconArrowUpRight, IconPencil } from '@/ui/display/icon'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { RecordInlineCellContainer } from '@/ui/object/record-inline-cell/components/RecordInlineCellContainer'; import { FieldRecoilScopeContext } from '@/ui/object/record-inline-cell/states/recoil-scope-contexts/FieldRecoilScopeContext'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { Company, Person } from '~/generated/graphql'; import { ActivityRelationEditableFieldEditMode } from './ActivityRelationEditableFieldEditMode'; @@ -14,7 +15,7 @@ type ActivityRelationEditableFieldProps = { activity?: Pick & { activityTargets?: Array< Pick & { - person?: Pick | null; + person?: Pick | null; company?: Pick | null; } > | null; diff --git a/front/src/modules/activities/editable-fields/components/ActivityRelationEditableFieldEditMode.tsx b/front/src/modules/activities/editable-fields/components/ActivityRelationEditableFieldEditMode.tsx index e880382d8..48a7f6e31 100644 --- a/front/src/modules/activities/editable-fields/components/ActivityRelationEditableFieldEditMode.tsx +++ b/front/src/modules/activities/editable-fields/components/ActivityRelationEditableFieldEditMode.tsx @@ -92,14 +92,9 @@ export const ActivityRelationEditableFieldEditMode = ({ const { closeInlineCell: closeEditableField } = useInlineCell(); const handleSubmit = useCallback(() => { - handleCheckItemsChange(selectedEntityIds, entitiesToSelect); + //handleCheckItemsChange(selectedEntityIds, entitiesToSelect); closeEditableField(); - }, [ - handleCheckItemsChange, - selectedEntityIds, - entitiesToSelect, - closeEditableField, - ]); + }, [closeEditableField]); const handleCancel = () => { closeEditableField(); diff --git a/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts b/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts index 5882e3338..9a9636acd 100644 --- a/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts +++ b/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts @@ -17,10 +17,10 @@ export const useHandleCheckableActivityTargetChange = ({ }; }) => { const { createOneObject } = useCreateOneObjectRecord({ - objectNameSingular: 'activityTargetV2', + objectNameSingular: 'activityTarget', }); const { deleteOneObject } = useDeleteOneObjectRecord({ - objectNameSingular: 'activityTargetV2', + objectNameSingular: 'activityTarget', }); return async ( diff --git a/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index 8807681ad..86aa3826a 100644 --- a/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -18,11 +18,11 @@ export const useOpenCreateActivityDrawer = () => { const { openRightDrawer } = useRightDrawer(); const { createOneObject: createOneActivityTarget } = useCreateOneObjectRecord({ - objectNameSingular: 'activityTargetV2', + objectNameSingular: 'activityTarget', }); const { createOneObject: createOneActivity } = useCreateOneObjectRecord({ - objectNameSingular: 'activityV2', + objectNameSingular: 'activity', }); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const setHotkeyScope = useSetHotkeyScope(); diff --git a/front/src/modules/activities/notes/components/Notes.tsx b/front/src/modules/activities/notes/components/Notes.tsx index 61c1f5625..8bdbb2218 100644 --- a/front/src/modules/activities/notes/components/Notes.tsx +++ b/front/src/modules/activities/notes/components/Notes.tsx @@ -6,7 +6,6 @@ import { useNotes } from '@/activities/notes/hooks/useNotes'; import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; -import { ActivityType } from '~/generated/graphql'; const StyledTaskGroupEmptyContainer = styled.div` align-items: center; @@ -61,7 +60,7 @@ export const Notes = ({ entity }: { entity: ActivityTargetableEntity }) => { variant="secondary" onClick={() => openCreateActivity({ - type: ActivityType.Note, + type: 'Note', targetableEntities: [entity], }) } @@ -83,7 +82,7 @@ export const Notes = ({ entity }: { entity: ActivityTargetableEntity }) => { title="Add note" onClick={() => openCreateActivity({ - type: ActivityType.Note, + type: 'Note', targetableEntities: [entity], }) } diff --git a/front/src/modules/activities/notes/hooks/useNotes.ts b/front/src/modules/activities/notes/hooks/useNotes.ts index da979433f..b3d5aa4fb 100644 --- a/front/src/modules/activities/notes/hooks/useNotes.ts +++ b/front/src/modules/activities/notes/hooks/useNotes.ts @@ -5,7 +5,7 @@ import { ActivityTargetableEntity } from '../../types/ActivityTargetableEntity'; export const useNotes = (entity: ActivityTargetableEntity) => { const { objects: notes } = useFindManyObjectRecords({ - objectNamePlural: 'activitiesV2', + objectNamePlural: 'activities', filter: { type: { equals: 'None' }, activityTargets: { diff --git a/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx b/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx index 0285a8a5f..7f2e375c1 100644 --- a/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx +++ b/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx @@ -12,7 +12,7 @@ type ActivityActionBarProps = { export const ActivityActionBar = ({ activityId }: ActivityActionBarProps) => { const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); const { deleteOneObject } = useDeleteOneObjectRecord({ - objectNameSingular: 'activityV2', + objectNameSingular: 'activity', }); const deleteActivity = () => { diff --git a/front/src/modules/activities/tasks/components/AddTaskButton.tsx b/front/src/modules/activities/tasks/components/AddTaskButton.tsx index 0e8f931dc..a3ee09979 100644 --- a/front/src/modules/activities/tasks/components/AddTaskButton.tsx +++ b/front/src/modules/activities/tasks/components/AddTaskButton.tsx @@ -2,7 +2,6 @@ import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateAct import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; -import { ActivityType } from '~/generated/graphql'; export const AddTaskButton = ({ activityTargetEntity, @@ -23,7 +22,7 @@ export const AddTaskButton = ({ title="Add task" onClick={() => openCreateActivity({ - type: ActivityType.Task, + type: 'Task', targetableEntities: [activityTargetEntity], }) } diff --git a/front/src/modules/activities/tasks/components/PageAddTaskButton.tsx b/front/src/modules/activities/tasks/components/PageAddTaskButton.tsx index abf5fbf75..8f1558292 100644 --- a/front/src/modules/activities/tasks/components/PageAddTaskButton.tsx +++ b/front/src/modules/activities/tasks/components/PageAddTaskButton.tsx @@ -1,7 +1,6 @@ import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { PageAddButton } from '@/ui/layout/page/PageAddButton'; import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; -import { ActivityType } from '~/generated/graphql'; export const PageAddTaskButton = () => { const { selectedFilter } = useFilter(); @@ -9,7 +8,7 @@ export const PageAddTaskButton = () => { const handleClick = () => { openCreateActivity({ - type: ActivityType.Task, + type: 'Task', assigneeId: selectedFilter?.value, }); }; diff --git a/front/src/modules/activities/tasks/components/TaskGroups.tsx b/front/src/modules/activities/tasks/components/TaskGroups.tsx index 0c5db7a4a..012e45fa7 100644 --- a/front/src/modules/activities/tasks/components/TaskGroups.tsx +++ b/front/src/modules/activities/tasks/components/TaskGroups.tsx @@ -8,7 +8,6 @@ import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; import { activeTabIdScopedState } from '@/ui/layout/tab/states/activeTabIdScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -import { ActivityType } from '~/generated/graphql'; import { AddTaskButton } from './AddTaskButton'; import { TaskList } from './TaskList'; @@ -84,7 +83,7 @@ export const TaskGroups = ({ entity, showAddButton }: TaskGroupsProps) => { variant={'secondary'} onClick={() => openCreateActivity({ - type: ActivityType.Task, + type: 'Task', targetableEntities: entity ? [entity] : undefined, }) } diff --git a/front/src/modules/activities/tasks/hooks/useCompleteTask.ts b/front/src/modules/activities/tasks/hooks/useCompleteTask.ts index 8eeac4338..d6e600b8a 100644 --- a/front/src/modules/activities/tasks/hooks/useCompleteTask.ts +++ b/front/src/modules/activities/tasks/hooks/useCompleteTask.ts @@ -1,13 +1,13 @@ import { useCallback } from 'react'; +import { Activity } from '@/activities/types/Activity'; import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; -import { Activity } from '~/generated/graphql'; type Task = Pick; export const useCompleteTask = (task: Task) => { const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'activityV2', + objectNameSingular: 'activity', }); const completeTask = useCallback( diff --git a/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts b/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts index b8664be70..509c1e52f 100644 --- a/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts +++ b/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts @@ -9,7 +9,7 @@ export const useCurrentUserTaskCount = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { objects } = useFindManyObjectRecords({ - objectNamePlural: 'activitiesV2', + objectNamePlural: 'activities', filter: { type: { eq: 'Task' }, completedAt: { eq: null }, diff --git a/front/src/modules/activities/tasks/hooks/useTasks.ts b/front/src/modules/activities/tasks/hooks/useTasks.ts index 5f09c8ba9..ee605de5d 100644 --- a/front/src/modules/activities/tasks/hooks/useTasks.ts +++ b/front/src/modules/activities/tasks/hooks/useTasks.ts @@ -4,8 +4,7 @@ import { Activity } from '@/activities/types/Activity'; import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; -import { turnFilterIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause'; -import { SortOrder } from '~/generated/graphql'; +import { turnFiltersIntoWhereClauseV2 } from '@/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2'; import { parseDate } from '~/utils/date-utils'; export const useTasks = (entity?: ActivityTargetableEntity) => { @@ -22,10 +21,10 @@ export const useTasks = (entity?: ActivityTargetableEntity) => { }, }, } - : Object.assign({}, turnFilterIntoWhereClause(selectedFilter)); + : Object.assign({}, turnFiltersIntoWhereClauseV2([], [])); const { objects: completeTasksData } = useFindManyObjectRecords({ - objectNamePlural: 'activitiesV2', + objectNamePlural: 'activities', skip: !entity && !selectedFilter, filter: { type: { equals: 'Task' }, @@ -34,13 +33,13 @@ export const useTasks = (entity?: ActivityTargetableEntity) => { }, orderBy: [ { - createdAt: SortOrder.Desc, + createdAt: 'AscNullIsFirst', }, ], }); const { objects: incompleteTaskData } = useFindManyObjectRecords({ - objectNamePlural: 'activitiesV2', + objectNamePlural: 'activities', skip: !entity && !selectedFilter, filter: { type: { equals: 'Task' }, @@ -49,7 +48,7 @@ export const useTasks = (entity?: ActivityTargetableEntity) => { }, orderBy: [ { - createdAt: SortOrder.Desc, + createdAt: 'DescNullIsFirst', }, ], }); diff --git a/front/src/modules/activities/timeline/components/Timeline.tsx b/front/src/modules/activities/timeline/components/Timeline.tsx index 2158fc53a..32317eae6 100644 --- a/front/src/modules/activities/timeline/components/Timeline.tsx +++ b/front/src/modules/activities/timeline/components/Timeline.tsx @@ -49,7 +49,7 @@ const StyledEmptyTimelineSubTitle = styled.div` export const Timeline = ({ entity }: { entity: ActivityTargetableEntity }) => { const { objects: activityTargets, loading } = useFindManyObjectRecords({ - objectNamePlural: 'activityTargetsV2', + objectNamePlural: 'activityTargets', filter: { or: { companyId: { eq: entity.id }, @@ -60,7 +60,7 @@ export const Timeline = ({ entity }: { entity: ActivityTargetableEntity }) => { const { objects: activities } = useFindManyObjectRecords({ skip: !activityTargets?.length, - objectNamePlural: 'activitiesV2', + objectNamePlural: 'activities', filter: { activityTargets: { in: activityTargets?.map((at) => at.id) }, }, diff --git a/front/src/modules/activities/types/ActivityTarget.ts b/front/src/modules/activities/types/ActivityTarget.ts index fae64ebb0..63240e01b 100644 --- a/front/src/modules/activities/types/ActivityTarget.ts +++ b/front/src/modules/activities/types/ActivityTarget.ts @@ -1,5 +1,6 @@ import { Activity } from '@/activities/types/Activity'; -import { Company, Person } from '~/generated-metadata/graphql'; +import { Company } from '@/companies/types/Company'; +import { Person } from '@/people/types/Person'; export type ActivityTarget = { id: string; @@ -8,7 +9,7 @@ export type ActivityTarget = { companyId: string | null; personId: string | null; activity: Pick; - person?: Pick | null; + person?: Pick | null; company?: Pick | null; [key: string]: any; }; diff --git a/front/src/modules/apollo/hooks/useApolloFactory.ts b/front/src/modules/apollo/hooks/useApolloFactory.ts index e2d66eb0e..b434bace7 100644 --- a/front/src/modules/apollo/hooks/useApolloFactory.ts +++ b/front/src/modules/apollo/hooks/useApolloFactory.ts @@ -7,7 +7,6 @@ import { tokenPairState } from '@/auth/states/tokenPairState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { AppPath } from '@/types/AppPath'; import { REACT_APP_SERVER_BASE_URL } from '~/config'; -import { ActivityTarget } from '~/generated/graphql'; import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; import { useUpdateEffect } from '~/hooks/useUpdateEffect'; @@ -25,23 +24,7 @@ export const useApolloFactory = () => { const apolloClient = useMemo(() => { apolloRef.current = new ApolloFactory({ uri: `${REACT_APP_SERVER_BASE_URL}/graphql`, - cache: new InMemoryCache({ - typePolicies: { - Activity: { - fields: { - activityTargets: { - merge: ( - _existing: ActivityTarget[] = [], - incoming: ActivityTarget[], - ) => { - return [...incoming]; - }, - }, - }, - }, - ViewField: { keyFields: ['viewId', 'key'] }, - }, - }), + cache: new InMemoryCache(), defaultOptions: { query: { fetchPolicy: 'cache-first', diff --git a/front/src/modules/apollo/optimistic-effect/hooks/useOptimisticEffect.ts b/front/src/modules/apollo/optimistic-effect/hooks/useOptimisticEffect.ts index a01a759e8..457e4d16e 100644 --- a/front/src/modules/apollo/optimistic-effect/hooks/useOptimisticEffect.ts +++ b/front/src/modules/apollo/optimistic-effect/hooks/useOptimisticEffect.ts @@ -7,19 +7,11 @@ import { import { isNonEmptyArray } from '@sniptt/guards'; import { useRecoilCallback } from 'recoil'; -import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies'; import { EMPTY_QUERY, useFindOneObjectMetadataItem, } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { GET_PEOPLE } from '@/people/graphql/queries/getPeople'; -import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys'; -import { - GetApiKeysQuery, - GetCompaniesQuery, - GetPeopleQuery, -} from '~/generated/graphql'; import { optimisticEffectState } from '../states/optimisticEffectState'; import { OptimisticEffect } from '../types/internal/OptimisticEffect'; @@ -59,7 +51,6 @@ export const useOptimisticEffect = ({ newData, query, variables, - isUsingFlexibleBackend, objectMetadataItem, }: { cache: ApolloCache; @@ -69,7 +60,7 @@ export const useOptimisticEffect = ({ isUsingFlexibleBackend?: boolean; objectMetadataItem?: ObjectMetadataItem; }) => { - if (isUsingFlexibleBackend && objectMetadataItem) { + if (objectMetadataItem) { const existingData = cache.readQuery({ query: findManyQuery, variables, @@ -104,50 +95,6 @@ export const useOptimisticEffect = ({ if (!existingData) { return; } - - if (query === GET_PEOPLE) { - cache.writeQuery({ - query, - variables, - data: { - people: definition.resolver({ - currentData: (existingData as GetPeopleQuery).people as T[], - newData: newData as T[], - variables, - }), - }, - }); - } - - if (query === GET_COMPANIES) { - cache.writeQuery({ - query, - variables, - data: { - companies: definition.resolver({ - currentData: (existingData as GetCompaniesQuery) - .companies as T[], - newData: newData as T[], - variables, - }), - }, - }); - } - - if (query === GET_API_KEYS) { - cache.writeQuery({ - query, - variables, - data: { - findManyApiKey: definition.resolver({ - currentData: (existingData as GetApiKeysQuery) - .findManyApiKey as T[], - newData: newData as T[], - variables, - }), - }, - }); - } }; const optimisticEffect = { diff --git a/front/src/modules/attachments/types/Attachment.ts b/front/src/modules/attachments/types/Attachment.ts new file mode 100644 index 000000000..657ce6b48 --- /dev/null +++ b/front/src/modules/attachments/types/Attachment.ts @@ -0,0 +1,6 @@ +export type Attachment = { + id: string; + createdAt: Date; + updatedAt: Date; + deletedAt: Date | null; +}; diff --git a/front/src/modules/auth/graphql/fragments/userQueryFragment.ts b/front/src/modules/auth/graphql/fragments/userQueryFragment.ts deleted file mode 100644 index f89b76831..000000000 --- a/front/src/modules/auth/graphql/fragments/userQueryFragment.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { gql } from '@apollo/client'; - -export const USER_QUERY_FRAGMENT = gql` - fragment UserQueryFragment on User { - id - email - displayName - firstName - lastName - canImpersonate - supportUserHash - } -`; diff --git a/front/src/modules/auth/graphql/mutations/generateApiKeyToken.ts b/front/src/modules/auth/graphql/mutations/generateApiKeyToken.ts new file mode 100644 index 000000000..c8df1e78b --- /dev/null +++ b/front/src/modules/auth/graphql/mutations/generateApiKeyToken.ts @@ -0,0 +1,9 @@ +import { gql } from '@apollo/client'; + +export const GENERATE_ONE_API_KEY_TOKEN = gql` + mutation GenerateApiKeyToken($apiKeyId: String!, $expiresAt: String!) { + generateApiKeyToken(apiKeyId: $apiKeyId, expiresAt: $expiresAt) { + token + } + } +`; diff --git a/front/src/modules/auth/hooks/useAuth.ts b/front/src/modules/auth/hooks/useAuth.ts index 1afc69e30..2d0b24e7b 100644 --- a/front/src/modules/auth/hooks/useAuth.ts +++ b/front/src/modules/auth/hooks/useAuth.ts @@ -10,13 +10,11 @@ import { 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 { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; import { REACT_APP_SERVER_AUTH_URL } from '~/config'; import { useChallengeMutation, useCheckUserExistsLazyQuery, - useGetCurrentWorkspaceLazyQuery, useSignUpMutation, useVerifyMutation, } from '~/generated/graphql'; @@ -38,7 +36,6 @@ export const useAuth = () => { const [verify] = useVerifyMutation(); const [checkUserExistsQuery, { data: checkUserExistsData }] = useCheckUserExistsLazyQuery(); - const [getCurrentWorkspaceQuery] = useGetCurrentWorkspaceLazyQuery(); const client = useApolloClient(); @@ -81,31 +78,26 @@ export const useAuth = () => { } setTokenPair(verifyResult.data?.verify.tokens); - const workspaceMember = await client.query({ - query: FIND_ONE_WORKSPACE_MEMBER_V2, - variables: { - filter: { - userId: { eq: verifyResult.data?.verify.user.id }, - }, - }, - }); - const currentWorkspace = await getCurrentWorkspaceQuery(); - setCurrentUser(verifyResult.data?.verify.user); - setCurrentWorkspaceMember(workspaceMember.data?.findMany); - setCurrentWorkspace(currentWorkspace.data?.currentWorkspace ?? null); + const user = verifyResult.data?.verify.user; + const workspaceMember = { + ...user.workspaceMember, + colorScheme: user.workspaceMember?.colorScheme as ColorScheme, + }; + const workspace = user.defaultWorkspace ?? null; + setCurrentUser(user); + setCurrentWorkspaceMember(workspaceMember); + setCurrentWorkspace(workspace); return { - user: verifyResult.data?.verify.user, - workspaceMember: workspaceMember.data?.findMany, - workspace: currentWorkspace.data?.currentWorkspace, + user, + workspaceMember, + workspace, tokens: verifyResult.data?.verify.tokens, }; }, [ verify, setTokenPair, - client, - getCurrentWorkspaceQuery, setCurrentUser, setCurrentWorkspaceMember, setCurrentWorkspace, @@ -161,38 +153,15 @@ export const useAuth = () => { throw new Error('No login token'); } - const { user, workspace } = await handleVerify( + const { user, workspace, workspaceMember } = await handleVerify( signUpResult.data?.signUp.loginToken.token, ); - const workspaceMember = await client.mutate({ - mutation: CREATE_ONE_WORKSPACE_MEMBER_V2, - variables: { - input: { - name: { - 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 }; }, - [ - setIsVerifyPendingState, - signUp, - handleVerify, - client, - setCurrentWorkspaceMember, - ], + [setIsVerifyPendingState, signUp, handleVerify], ); const handleGoogleLogin = useCallback((workspaceInviteHash?: string) => { diff --git a/front/src/modules/client-config/components/ClientConfigProvider.tsx b/front/src/modules/client-config/components/ClientConfigProvider.tsx index e615d8194..94d104e00 100644 --- a/front/src/modules/client-config/components/ClientConfigProvider.tsx +++ b/front/src/modules/client-config/components/ClientConfigProvider.tsx @@ -1,5 +1,5 @@ -import { useEffect, useState } from 'react'; -import { useRecoilState, useSetRecoilState } from 'recoil'; +import { useEffect } from 'react'; +import { useSetRecoilState } from 'recoil'; import { authProvidersState } from '@/client-config/states/authProvidersState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; @@ -11,13 +11,12 @@ import { useGetClientConfigQuery } from '~/generated/graphql'; export const ClientConfigProvider: React.FC = ({ children, }) => { - const [, setAuthProviders] = useRecoilState(authProvidersState); - const [, setIsDebugMode] = useRecoilState(isDebugModeState); + const setAuthProviders = useSetRecoilState(authProvidersState); + const setIsDebugMode = useSetRecoilState(isDebugModeState); - const [, setIsSignInPrefilled] = useRecoilState(isSignInPrefilledState); + const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState); - const [, setTelemetry] = useRecoilState(telemetryState); - const [setIsLoading] = useState(true); + const setTelemetry = useSetRecoilState(telemetryState); const setSupportChat = useSetRecoilState(supportChatState); const { data, loading } = useGetClientConfigQuery(); @@ -41,10 +40,8 @@ export const ClientConfigProvider: React.FC = ({ setIsDebugMode, setIsSignInPrefilled, setTelemetry, - setIsLoading, - loading, setSupportChat, ]); - return <>{children}; + return loading ? <> : <>{children}; }; diff --git a/front/src/modules/command-menu/components/CommandMenu.tsx b/front/src/modules/command-menu/components/CommandMenu.tsx index 8d76fd4bc..a4590991a 100644 --- a/front/src/modules/command-menu/components/CommandMenu.tsx +++ b/front/src/modules/command-menu/components/CommandMenu.tsx @@ -2,17 +2,8 @@ import { useState } from 'react'; import { useRecoilValue } from 'recoil'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; -import { IconNotes } from '@/ui/display/icon'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; -import { Avatar } from '@/users/components/Avatar'; -import { - QueryMode, - useSearchActivityQuery, - useSearchCompanyQuery, - useSearchPeopleQuery, -} from '~/generated/graphql'; -import { getLogoUrlFromDomainName } from '~/utils'; import { useCommandMenu } from '../hooks/useCommandMenu'; import { commandMenuCommandsState } from '../states/commandMenuCommandsState'; @@ -45,47 +36,47 @@ export const CommandMenu = () => { [openCommandMenu, setSearch], ); - const { data: peopleData } = useSearchPeopleQuery({ - skip: !isCommandMenuOpened, - variables: { - where: { - OR: [ - { firstName: { contains: search, mode: QueryMode.Insensitive } }, - { lastName: { contains: search, mode: QueryMode.Insensitive } }, - ], - }, - limit: 3, - }, - }); + // const { data: peopleData } = useSearchPeopleQuery({ + // skip: !isCommandMenuOpened, + // variables: { + // where: { + // OR: [ + // { firstName: { contains: search, mode: QueryMode.Insensitive } }, + // { lastName: { contains: search, mode: QueryMode.Insensitive } }, + // ], + // }, + // limit: 3, + // }, + // }); - const people = peopleData?.searchResults ?? []; + // const people = peopleData?.searchResults ?? []; - const { data: companyData } = useSearchCompanyQuery({ - skip: !isCommandMenuOpened, - variables: { - where: { - OR: [{ name: { contains: search, mode: QueryMode.Insensitive } }], - }, - limit: 3, - }, - }); + // const { data: companyData } = useSearchCompanyQuery({ + // skip: !isCommandMenuOpened, + // variables: { + // where: { + // OR: [{ name: { contains: search, mode: QueryMode.Insensitive } }], + // }, + // limit: 3, + // }, + // }); - const companies = companyData?.searchResults ?? []; + // const companies = companyData?.searchResults ?? []; - const { data: activityData } = useSearchActivityQuery({ - skip: !isCommandMenuOpened, - variables: { - where: { - OR: [ - { title: { contains: search, mode: QueryMode.Insensitive } }, - { body: { contains: search, mode: QueryMode.Insensitive } }, - ], - }, - limit: 3, - }, - }); + // const { data: activityData } = useSearchActivityQuery({ + // skip: !isCommandMenuOpened, + // variables: { + // where: { + // OR: [ + // { title: { contains: search, mode: QueryMode.Insensitive } }, + // { body: { contains: search, mode: QueryMode.Insensitive } }, + // ], + // }, + // limit: 3, + // }, + // }); - const activities = activityData?.searchResults ?? []; + // const activities = activityData?.searchResults ?? []; const checkInShortcuts = (cmd: Command, search: string) => { return (cmd.firstHotKey + (cmd.secondHotKey ?? '')) @@ -158,7 +149,7 @@ export const CommandMenu = () => { /> ))} - + {/* {people.map((person) => ( { onClick={() => openActivityRightDrawer(activity.id)} /> ))} - + */} ); diff --git a/front/src/modules/command-menu/constants/commandMenuCommands.ts b/front/src/modules/command-menu/constants/commandMenuCommands.ts index 67089d82f..dcc76e7fb 100644 --- a/front/src/modules/command-menu/constants/commandMenuCommands.ts +++ b/front/src/modules/command-menu/constants/commandMenuCommands.ts @@ -10,7 +10,7 @@ import { Command, CommandType } from '../types/Command'; export const commandMenuCommands: Command[] = [ { - to: '/people', + to: '/objects/people', label: 'Go to People', type: CommandType.Navigate, firstHotKey: 'G', @@ -18,7 +18,7 @@ export const commandMenuCommands: Command[] = [ Icon: IconUser, }, { - to: '/companies', + to: '/objects/companies', label: 'Go to Companies', type: CommandType.Navigate, firstHotKey: 'G', @@ -26,7 +26,7 @@ export const commandMenuCommands: Command[] = [ Icon: IconBuildingSkyscraper, }, { - to: '/opportunities', + to: '/objects/opportunities', label: 'Go to Opportunities', type: CommandType.Navigate, firstHotKey: 'G', diff --git a/front/src/modules/companies/__stories__/CompanyBoardCard.stories.tsx b/front/src/modules/companies/__stories__/CompanyBoardCard.stories.tsx deleted file mode 100644 index 447e6af23..000000000 --- a/front/src/modules/companies/__stories__/CompanyBoardCard.stories.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { useEffect } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { Meta, StoryObj } from '@storybook/react'; - -import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard'; -import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions'; -import { BoardCardIdContext } from '@/ui/layout/board/contexts/BoardCardIdContext'; -import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState'; -import { BoardColumnRecoilScopeContext } from '@/ui/layout/board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; -import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress'; - -import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect'; -import { BoardContext } from '../states/contexts/BoardContext'; -import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; - -const meta: Meta = { - title: 'Modules/Companies/CompanyBoardCard', - component: CompanyBoardCard, - decorators: [ - (Story, context) => { - const [, setBoardCardFields] = useRecoilScopedState( - boardCardFieldsScopedState, - context.parameters.customRecoilScopeContext, - ); - - useEffect(() => { - setBoardCardFields(pipelineAvailableFieldDefinitions); - }, [setBoardCardFields]); - - return ( - - - - - - - - - - - - - ); - }, - ComponentWithRecoilScopeDecorator, - ComponentDecorator, - ], - args: {}, - argTypes: {}, - parameters: { - msw: graphqlMocks, - customRecoilScopeContext: CompanyBoardRecoilScopeContext, - }, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = {}; diff --git a/front/src/modules/companies/__stories__/mock-data.ts b/front/src/modules/companies/__stories__/mock-data.ts index 4ff4bd00e..6bfc08feb 100644 --- a/front/src/modules/companies/__stories__/mock-data.ts +++ b/front/src/modules/companies/__stories__/mock-data.ts @@ -1,38 +1,34 @@ -import { Pipeline } from '~/generated/graphql'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; -export const pipeline = { - id: 'pipeline-1', - name: 'pipeline-1', - pipelineStages: [ - { - id: 'pipeline-stage-1', - name: 'New', - position: 0, - color: 'red', - }, - { - id: 'pipeline-stage-2', - name: 'Screening', - position: 1, - color: 'purple', - }, - { - id: 'pipeline-stage-3', - name: 'Meeting', - position: 2, - color: 'sky', - }, - { - id: 'pipeline-stage-4', - name: 'Proposal', - position: 3, - color: 'turquoise', - }, - { - id: 'pipeline-stage-5', - name: 'Customer', - position: 4, - color: 'yellow', - }, - ], -} as Pipeline; +export const pipelineSteps = [ + { + id: 'pipeline-stage-1', + name: 'New', + position: 0, + color: 'red', + }, + { + id: 'pipeline-stage-2', + name: 'Screening', + position: 1, + color: 'purple', + }, + { + id: 'pipeline-stage-3', + name: 'Meeting', + position: 2, + color: 'sky', + }, + { + id: 'pipeline-stage-4', + name: 'Proposal', + position: 3, + color: 'turquoise', + }, + { + id: 'pipeline-stage-5', + name: 'Customer', + position: 4, + color: 'yellow', + }, +] as PipelineStep[]; diff --git a/front/src/modules/companies/components/AddPersonToCompany.tsx b/front/src/modules/companies/components/AddPersonToCompany.tsx index 3a72de199..2d830cf44 100644 --- a/front/src/modules/companies/components/AddPersonToCompany.tsx +++ b/front/src/modules/companies/components/AddPersonToCompany.tsx @@ -1,5 +1,4 @@ import { useState } from 'react'; -import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { flip, offset, useFloating } from '@floating-ui/react'; import { v4 } from 'uuid'; @@ -8,7 +7,6 @@ import { PeoplePicker, PersonForSelect, } from '@/people/components/PeoplePicker'; -import { GET_PEOPLE } from '@/people/graphql/queries/getPeople'; import { IconPlus } from '@/ui/display/icon'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; @@ -16,10 +14,6 @@ import { DoubleTextInput } from '@/ui/object/field/meta-types/input/components/i import { FieldDoubleText } from '@/ui/object/field/types/FieldDoubleText'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { - useInsertOnePersonMutation, - useUpdateOnePersonMutation, -} from '~/generated/graphql'; const StyledContainer = styled.div` position: static; @@ -56,8 +50,6 @@ export const AddPersonToCompany = ({ }) => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isCreationDropdownOpen, setIsCreationDropdownOpen] = useState(false); - const [updatePerson] = useUpdateOnePersonMutation(); - const [insertOnePerson] = useInsertOnePersonMutation(); const { refs, floatingStyles } = useFloating({ open: isDropdownOpen, placement: 'right-start', @@ -77,17 +69,17 @@ export const AddPersonToCompany = ({ const handlePersonSelected = (companyId: string) => async (newPerson: PersonForSelect | null) => { if (newPerson) { - await updatePerson({ - variables: { - where: { - id: newPerson.id, - }, - data: { - company: { connect: { id: companyId } }, - }, - }, - refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - }); + // await updatePerson({ + // variables: { + // where: { + // id: newPerson.id, + // }, + // data: { + // company: { connect: { id: companyId } }, + // }, + // }, + // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], + // }); handleClosePicker(); } }; @@ -114,17 +106,17 @@ export const AddPersonToCompany = ({ }: FieldDoubleText) => { if (!firstValue && !secondValue) return; const newPersonId = v4(); - await insertOnePerson({ - variables: { - data: { - company: { connect: { id: companyId } }, - id: newPersonId, - firstName: firstValue, - lastName: secondValue, - }, - }, - refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - }); + // await insertOnePerson({ + // variables: { + // data: { + // company: { connect: { id: companyId } }, + // id: newPersonId, + // firstName: firstValue, + // lastName: secondValue, + // }, + // }, + // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], + // }); setIsCreationDropdownOpen(false); }; diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index 85b624bb8..62d4e5959 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -152,7 +152,7 @@ export const CompanyBoardCard = () => { const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => { const { updateOneObject } = useUpdateOneObjectRecord({ - objectNameSingular: 'opportunityV2', + objectNameSingular: 'opportunity', }); const updateEntity = ({ @@ -242,7 +242,7 @@ export const CompanyBoardCard = () => { fieldDefinition: { fieldMetadataId: viewField.fieldMetadataId, label: viewField.label, - Icon: viewField.Icon, + iconName: viewField.iconName, type: viewField.type, metadata: viewField.metadata, entityChipDisplayMapper: diff --git a/front/src/modules/companies/components/CompanyChip.tsx b/front/src/modules/companies/components/CompanyChip.tsx index 7beeb9b6f..c6d4a2dfb 100644 --- a/front/src/modules/companies/components/CompanyChip.tsx +++ b/front/src/modules/companies/components/CompanyChip.tsx @@ -18,7 +18,7 @@ export const CompanyChip = ({ }: CompanyChipProps) => ( @@ -57,7 +57,7 @@ export const CompanyPicker = ({ originalEntity: company, }), selectedIds: companyId ? [companyId] : [], - objectNamePlural: 'companiesV2', + objectNamePlural: 'companies', }); const handleEntitySelected = async ( diff --git a/front/src/modules/companies/components/CompanyProgressPicker.tsx b/front/src/modules/companies/components/CompanyProgressPicker.tsx index e6bebfa56..ba0f1c769 100644 --- a/front/src/modules/companies/components/CompanyProgressPicker.tsx +++ b/front/src/modules/companies/components/CompanyProgressPicker.tsx @@ -73,7 +73,7 @@ export const CompanyProgressPicker = ({ const selectedPipelineStage = useMemo( () => currentPipelineStages.find( - (pipelineStage) => pipelineStage.id === selectedPipelineStageId, + (pipelineStage: any) => pipelineStage.id === selectedPipelineStageId, ), [currentPipelineStages, selectedPipelineStageId], ); @@ -85,7 +85,7 @@ export const CompanyProgressPicker = ({ > {isProgressSelectionUnfolded ? ( - {currentPipelineStages.map((pipelineStage, index) => ( + {currentPipelineStages.map((pipelineStage: any, index: number) => ( { - const { data } = useGetPeopleQuery({ - variables: { - orderBy: [], - where: { - companyId: { - equals: company.id, - }, - }, - }, - }); + // const { data } = useGetPeopleQuery({ + // variables: { + // orderBy: [], + // where: { + // companyId: { + // equals: company.id, + // }, + // }, + // }, + // }); + const data = { + people: [], + }; const peopleIds = data?.people?.map(({ id }) => id); @@ -65,7 +69,7 @@ export const CompanyTeam = ({ company }: CompanyTeamProps) => { - {data?.people?.map((person, id) => ( + {data?.people?.map((person: Person, id) => ( { const updateCompanyBoard = useUpdateCompanyBoard(); useFindManyObjectRecords({ - objectNamePlural: 'pipelineStepsV2', + objectNamePlural: 'pipelineSteps', filter: {}, onCompleted: useCallback( (data: PaginatedObjectTypeResults) => { @@ -80,14 +79,14 @@ export const HooksCompanyBoardEffect = () => { in: pipelineSteps.map((pipelineStep) => pipelineStep.id), }, }, - ...(currentViewFilters?.map(turnFilterIntoWhereClause) || []), + ...[], ], }; - }, [currentViewFilters, pipelineSteps]) as any; + }, [pipelineSteps]) as any; useFindManyObjectRecords({ skip: !pipelineSteps.length, - objectNamePlural: 'opportunitiesV2', + objectNamePlural: 'opportunities', filter: whereFilters, onCompleted: useCallback( (_data: PaginatedObjectTypeResults) => { @@ -104,7 +103,7 @@ export const HooksCompanyBoardEffect = () => { useFindManyObjectRecords({ skip: !opportunities.length, - objectNamePlural: 'companiesV2', + objectNamePlural: 'companies', filter: { id: { in: opportunities.map((opportuntiy) => opportuntiy.companyId || ''), diff --git a/front/src/modules/companies/components/NewCompanyProgressButton.tsx b/front/src/modules/companies/components/NewCompanyProgressButton.tsx index 3a76334fb..de66283f0 100644 --- a/front/src/modules/companies/components/NewCompanyProgressButton.tsx +++ b/front/src/modules/companies/components/NewCompanyProgressButton.tsx @@ -9,7 +9,6 @@ import { BoardColumnContext } from '@/ui/layout/board/contexts/BoardColumnContex import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -import { useCreateCompanyProgress } from '../hooks/useCreateCompanyProgress'; import { useFilteredSearchCompanyQuery } from '../hooks/useFilteredSearchCompanyQuery'; export const NewCompanyProgressButton = () => { @@ -25,8 +24,6 @@ export const NewCompanyProgressButton = () => { setHotkeyScopeAndMemorizePreviousScope, } = usePreviousHotkeyScope(); - const createCompanyProgress = useCreateCompanyProgress(); - const handleEntitySelect = (company: any) => { setIsCreatingCard(false); goBackToPreviousHotkeyScope(); @@ -39,7 +36,7 @@ export const NewCompanyProgressButton = () => { throw new Error('Pipeline stage id is not defined'); } - createCompanyProgress(company.id, pipelineStageId); + //createCompanyProgress(company.id, pipelineStageId); }; const handleNewClick = useCallback(() => { diff --git a/front/src/modules/companies/constants/companiesAvailableFieldDefinitions.tsx b/front/src/modules/companies/constants/companiesAvailableFieldDefinitions.tsx deleted file mode 100644 index 59eb2cc50..000000000 --- a/front/src/modules/companies/constants/companiesAvailableFieldDefinitions.tsx +++ /dev/null @@ -1,182 +0,0 @@ -import { - IconBrandLinkedin, - IconBrandX, - IconBuildingSkyscraper, - IconCalendarEvent, - IconLink, - IconMap, - IconMoneybag, - IconTarget, - IconUserCircle, - IconUsers, -} from '@/ui/display/icon/index'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { - FieldBooleanMetadata, - FieldChipMetadata, - FieldDateMetadata, - FieldMetadata, - FieldMoneyMetadata, - FieldNumberMetadata, - FieldRelationMetadata, - FieldTextMetadata, - FieldURLMetadata, -} from '@/ui/object/field/types/FieldMetadata'; -import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; -import { User } from '~/generated/graphql'; - -export const companiesAvailableFieldDefinitions: ColumnDefinition[] = - [ - { - fieldMetadataId: 'name', - label: 'Name', - Icon: IconBuildingSkyscraper, - size: 180, - position: 0, - type: 'CHIP', - metadata: { - urlFieldName: 'domainName', - contentFieldName: 'name', - relationType: Entity.Company, - placeHolder: 'Company Name', - }, - isVisible: true, - infoTooltipContent: 'The company name.', - basePathToShowPage: '/companies/', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'domainName', - label: 'URL', - Icon: IconLink, - size: 100, - position: 1, - type: 'URL', - metadata: { - fieldName: 'domainName', - placeHolder: 'example.com', - }, - isVisible: true, - infoTooltipContent: - 'The company website URL. We use this url to fetch the company icon.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'accountOwner', - label: 'Account Owner', - Icon: IconUserCircle, - size: 150, - position: 2, - type: 'RELATION', - metadata: { - fieldName: 'accountOwner', - relationType: Entity.User, - }, - isVisible: true, - infoTooltipContent: - 'Your team member responsible for managing the company account.', - entityChipDisplayMapper: (dataObject: User) => { - return { - name: dataObject?.displayName, - pictureUrl: dataObject?.avatarUrl ?? undefined, - avatarType: 'rounded', - }; - }, - } satisfies ColumnDefinition, - { - fieldMetadataId: 'createdAt', - label: 'Creation', - Icon: IconCalendarEvent, - size: 150, - position: 3, - type: 'DATE', - metadata: { - fieldName: 'createdAt', - }, - isVisible: true, - infoTooltipContent: "Date when the company's record was created.", - } satisfies ColumnDefinition, - { - fieldMetadataId: 'employees', - label: 'Employees', - Icon: IconUsers, - size: 150, - position: 4, - type: 'NUMBER', - metadata: { - fieldName: 'employees', - isPositive: true, - placeHolder: 'Employees', - }, - isVisible: true, - infoTooltipContent: 'Number of employees in the company.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'linkedin', - label: 'LinkedIn', - Icon: IconBrandLinkedin, - size: 170, - position: 5, - type: 'URL', - metadata: { - fieldName: 'linkedinUrl', - placeHolder: 'LinkedIn URL', - }, - isVisible: true, - infoTooltipContent: 'The company Linkedin account.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'address', - label: 'Address', - Icon: IconMap, - size: 170, - position: 6, - type: 'TEXT', - metadata: { - fieldName: 'address', - placeHolder: 'Addre​ss', // Hack: Fake character to prevent password-manager from filling the field - }, - isVisible: true, - infoTooltipContent: 'The company address.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'idealCustomerProfile', - label: 'ICP', - Icon: IconTarget, - size: 150, - position: 7, - type: 'BOOLEAN', - metadata: { - fieldName: 'idealCustomerProfile', - }, - isVisible: false, - infoTooltipContent: - 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'annualRecurringRevenue', - label: 'ARR', - Icon: IconMoneybag, - size: 150, - position: 8, - type: 'MONEY_AMOUNT', - metadata: { - fieldName: 'annualRecurringRevenue', - placeHolder: 'ARR', - }, - infoTooltipContent: - 'Annual Recurring Revenue: The actual or estimated annual revenue of the company.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'xUrl', - label: 'Twitter', - Icon: IconBrandX, - size: 150, - position: 9, - type: 'URL', - metadata: { - fieldName: 'xUrl', - placeHolder: 'X', - }, - isVisible: false, - infoTooltipContent: 'The company Twitter account.', - } satisfies ColumnDefinition, - ]; diff --git a/front/src/modules/companies/editable-field/components/CompanyNameEditableField.tsx b/front/src/modules/companies/editable-field/components/CompanyNameEditableField.tsx deleted file mode 100644 index c153d0233..000000000 --- a/front/src/modules/companies/editable-field/components/CompanyNameEditableField.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { useEffect, useState } from 'react'; -import styled from '@emotion/styled'; - -import { FieldRecoilScopeContext } from '@/ui/object/record-inline-cell/states/recoil-scope-contexts/FieldRecoilScopeContext'; -import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { Company, useUpdateOneCompanyMutation } from '~/generated/graphql'; - -import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope'; - -type CompanyNameEditableFieldProps = { - company: Pick; -}; - -const StyledEditableTitleInput = styled.input<{ - value: string; -}>` - background: transparent; - - border: none; - color: ${({ theme, value }) => - value ? theme.font.color.primary : theme.font.color.light}; - display: flex; - flex-direction: column; - - font-size: ${({ theme }) => theme.font.size.xl}; - font-weight: ${({ theme }) => theme.font.weight.semiBold}; - justify-content: center; - - line-height: ${({ theme }) => theme.text.lineHeight.md}; - outline: none; - &::placeholder { - color: ${({ theme }) => theme.font.color.light}; - } - text-align: center; - width: calc(100% - ${({ theme }) => theme.spacing(2)}); -`; - -export const CompanyNameEditableField = ({ - company, -}: CompanyNameEditableFieldProps) => { - const [internalValue, setInternalValue] = useState(company.name); - - const [updateCompany] = useUpdateOneCompanyMutation(); - - const { - goBackToPreviousHotkeyScope, - setHotkeyScopeAndMemorizePreviousScope, - } = usePreviousHotkeyScope(); - - useEffect(() => { - setInternalValue(company.name); - }, [company.name]); - - const handleChange = async (newValue: string) => { - setInternalValue(newValue); - }; - - const handleSubmit = async () => { - goBackToPreviousHotkeyScope(); - await updateCompany({ - variables: { - where: { - id: company.id, - }, - data: { - name: internalValue ?? '', - }, - }, - }); - }; - - const handleFocus = async () => { - setHotkeyScopeAndMemorizePreviousScope( - EditableFieldHotkeyScope.EditableField, - ); - }; - - return ( - - handleChange(event.target.value)} - onBlur={handleSubmit} - onFocus={handleFocus} - value={internalValue} - /> - - ); -}; diff --git a/front/src/modules/companies/graphql/fragments/companyFieldsFragment.ts b/front/src/modules/companies/graphql/fragments/companyFieldsFragment.ts deleted file mode 100644 index e0dcc3048..000000000 --- a/front/src/modules/companies/graphql/fragments/companyFieldsFragment.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { gql } from '@apollo/client'; - -export const BASE_COMPANY_FIELDS_FRAGMENT = gql` - fragment baseCompanyFieldsFragment on Company { - address - annualRecurringRevenue - createdAt - domainName - employees - id - idealCustomerProfile - linkedinUrl - name - xUrl - _activityCount - } -`; - -export const BASE_ACCOUNT_OWNER_FRAGMENT = gql` - fragment baseAccountOwnerFragment on User { - id - email - displayName - avatarUrl - firstName - lastName - } -`; - -export const COMPANY_FIELDS_FRAGMENT = gql` - ${BASE_COMPANY_FIELDS_FRAGMENT} - ${BASE_ACCOUNT_OWNER_FRAGMENT} - fragment companyFieldsFragment on Company { - accountOwner { - ...baseAccountOwnerFragment - } - ...baseCompanyFieldsFragment - } -`; diff --git a/front/src/modules/companies/graphql/mutations/deleteManyCompanies.ts b/front/src/modules/companies/graphql/mutations/deleteManyCompanies.ts deleted file mode 100644 index 975f2bd56..000000000 --- a/front/src/modules/companies/graphql/mutations/deleteManyCompanies.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_MANY_COMPANIES = gql` - mutation DeleteManyCompanies($ids: [String!]) { - deleteManyCompany(where: { id: { in: $ids } }) { - count - } - } -`; diff --git a/front/src/modules/companies/graphql/mutations/insertManyCompany.ts b/front/src/modules/companies/graphql/mutations/insertManyCompany.ts deleted file mode 100644 index 096720737..000000000 --- a/front/src/modules/companies/graphql/mutations/insertManyCompany.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_MANY_COMPANY = gql` - mutation InsertManyCompany($data: [CompanyCreateManyInput!]!) { - createManyCompany(data: $data) { - count - } - } -`; diff --git a/front/src/modules/companies/graphql/mutations/insertOneCompany.ts b/front/src/modules/companies/graphql/mutations/insertOneCompany.ts deleted file mode 100644 index 9e99d3ea3..000000000 --- a/front/src/modules/companies/graphql/mutations/insertOneCompany.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_ONE_COMPANY = gql` - mutation InsertOneCompany($data: CompanyCreateInput!) { - createOneCompany(data: $data) { - ...companyFieldsFragment - } - } -`; diff --git a/front/src/modules/companies/graphql/mutations/updateOneCompany.ts b/front/src/modules/companies/graphql/mutations/updateOneCompany.ts deleted file mode 100644 index b705988f5..000000000 --- a/front/src/modules/companies/graphql/mutations/updateOneCompany.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_ONE_COMPANY = gql` - mutation UpdateOneCompany( - $where: CompanyWhereUniqueInput! - $data: CompanyUpdateInput! - ) { - updateOneCompany(data: $data, where: $where) { - ...companyFieldsFragment - } - } -`; diff --git a/front/src/modules/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition.ts b/front/src/modules/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition.ts deleted file mode 100644 index c30f4d4e4..000000000 --- a/front/src/modules/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Company } from '~/generated/graphql'; - -import { GET_COMPANIES } from '../queries/getCompanies'; - -export const getCompaniesOptimisticEffectDefinition = { - key: 'generic-entity-table-data-companies', - typename: 'Company', - query: GET_COMPANIES, - resolver: ({ - currentData, - newData, - }: { - currentData: Company[]; - newData: Company[]; - }) => { - return [...newData, ...currentData]; - }, -}; diff --git a/front/src/modules/companies/graphql/queries/getCompanies.ts b/front/src/modules/companies/graphql/queries/getCompanies.ts deleted file mode 100644 index 50c42beb4..000000000 --- a/front/src/modules/companies/graphql/queries/getCompanies.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { gql } from '@apollo/client'; - -import { COMPANY_FIELDS_FRAGMENT } from '../fragments/companyFieldsFragment'; - -export const GET_COMPANIES = gql` - ${COMPANY_FIELDS_FRAGMENT} - query GetCompanies( - $orderBy: [CompanyOrderByWithRelationInput!] - $where: CompanyWhereInput - ) { - companies: findManyCompany(orderBy: $orderBy, where: $where) { - ...companyFieldsFragment - } - } -`; diff --git a/front/src/modules/companies/graphql/queries/getCompany.ts b/front/src/modules/companies/graphql/queries/getCompany.ts deleted file mode 100644 index b5059cd10..000000000 --- a/front/src/modules/companies/graphql/queries/getCompany.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_COMPANY = gql` - query GetCompany($where: CompanyWhereUniqueInput!) { - findUniqueCompany(where: $where) { - ...companyFieldsFragment - Favorite { - id - person { - id - } - company { - id - } - } - } - } -`; diff --git a/front/src/modules/companies/hooks/useCompanyQuery.ts b/front/src/modules/companies/hooks/useCompanyQuery.ts deleted file mode 100644 index 55fd95265..000000000 --- a/front/src/modules/companies/hooks/useCompanyQuery.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useSetRecoilState } from 'recoil'; - -import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; -import { useGetCompanyQuery } from '~/generated/graphql'; - -export const useCompanyQuery = (id: string) => { - const updateCompanyShowPage = useSetRecoilState(entityFieldsFamilyState(id)); - - return useGetCompanyQuery({ - variables: { where: { id } }, - onCompleted: (data) => { - updateCompanyShowPage(data?.findUniqueCompany); - }, - }); -}; diff --git a/front/src/modules/companies/hooks/useCompanyTableContextMenuEntries.tsx b/front/src/modules/companies/hooks/useCompanyTableContextMenuEntries.tsx deleted file mode 100644 index 18ff56966..000000000 --- a/front/src/modules/companies/hooks/useCompanyTableContextMenuEntries.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { getOperationName } from '@apollo/client/utilities'; -import { useRecoilCallback, useSetRecoilState } from 'recoil'; - -import { useFavorites } from '@/favorites/hooks/useFavorites'; -import { - IconCheckbox, - IconHeart, - IconHeartOff, - IconNotes, - IconTrash, -} from '@/ui/display/icon'; -import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; -import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector'; -import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState'; -import { - ActivityType, - useDeleteManyCompaniesMutation, - useGetFavoritesQuery, -} from '~/generated/graphql'; - -import { GET_COMPANY } from '../graphql/queries/getCompany'; - -import { useCreateActivityForCompany } from './useCreateActivityForCompany'; - -export const useCompanyTableContextMenuEntries = () => { - const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); - const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState); - const createActivityForCompany = useCreateActivityForCompany(); - - const setTableRowIds = useSetRecoilState(tableRowIdsState); - const { resetTableRowSelection } = useRecordTable({ - recordTableScopeId: 'companies', - }); - - const { data } = useGetFavoritesQuery(); - const favorites = data?.findFavorites; - const { createFavorite, deleteFavorite } = useFavorites({ - objectNamePlural: 'companies', - }); - - const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => { - const selectedRowIds = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - const selectedCompanyId = - selectedRowIds.length === 1 ? selectedRowIds[0] : ''; - - const isFavorite = - !!selectedCompanyId && - !!favorites?.find( - (favorite) => favorite.company?.id === selectedCompanyId, - ); - - resetTableRowSelection(); - if (isFavorite) deleteFavorite(selectedCompanyId); - else createFavorite('company', selectedCompanyId); - }); - - const [deleteManyCompany] = useDeleteManyCompaniesMutation({ - refetchQueries: [getOperationName(GET_COMPANY) ?? ''], - }); - - const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => { - const rowIdsToDelete = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - resetTableRowSelection(); - - await deleteManyCompany({ - variables: { - ids: rowIdsToDelete, - }, - optimisticResponse: { - __typename: 'Mutation', - deleteManyCompany: { - count: rowIdsToDelete.length, - }, - }, - update: () => { - setTableRowIds((tableRowIds) => - tableRowIds.filter((id) => !rowIdsToDelete.includes(id)), - ); - }, - }); - }); - - return { - setContextMenuEntries: useRecoilCallback(({ snapshot }) => () => { - const selectedRowIds = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - const selectedCompanyId = - selectedRowIds.length === 1 ? selectedRowIds[0] : ''; - - const isFavorite = - !!selectedCompanyId && - !!favorites?.find( - (favorite) => favorite.company?.id === selectedCompanyId, - ); - - setContextMenuEntries([ - { - label: 'New task', - Icon: IconCheckbox, - onClick: () => createActivityForCompany(ActivityType.Task), - }, - { - label: 'New note', - Icon: IconNotes, - onClick: () => createActivityForCompany(ActivityType.Note), - }, - ...(!!selectedCompanyId - ? [ - { - label: isFavorite - ? 'Remove from favorites' - : 'Add to favorites', - Icon: isFavorite ? IconHeartOff : IconHeart, - onClick: () => handleFavoriteButtonClick(), - }, - ] - : []), - { - label: 'Delete', - Icon: IconTrash, - accent: 'danger', - onClick: () => handleDeleteClick(), - }, - ]); - }), - setActionBarEntries: useRecoilCallback(() => () => { - setActionBarEntriesState([ - { - label: 'Task', - Icon: IconCheckbox, - onClick: () => createActivityForCompany(ActivityType.Task), - }, - { - label: 'Note', - Icon: IconNotes, - onClick: () => createActivityForCompany(ActivityType.Note), - }, - { - label: 'Delete', - Icon: IconTrash, - accent: 'danger', - onClick: () => handleDeleteClick(), - }, - ]); - }), - }; -}; diff --git a/front/src/modules/companies/hooks/useCreateActivityForCompany.ts b/front/src/modules/companies/hooks/useCreateActivityForCompany.ts deleted file mode 100644 index c464cefea..000000000 --- a/front/src/modules/companies/hooks/useCreateActivityForCompany.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useRecoilCallback } from 'recoil'; - -import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds'; -import { ActivityType } from '@/activities/types/Activity'; - -export const useCreateActivityForCompany = () => { - const openCreateActivityRightDrawer = - useOpenCreateActivityDrawerForSelectedRowIds(); - - return useRecoilCallback( - () => (type: ActivityType) => { - openCreateActivityRightDrawer(type, 'Company'); - }, - [openCreateActivityRightDrawer], - ); -}; diff --git a/front/src/modules/companies/hooks/useCreateCompanyProgress.ts b/front/src/modules/companies/hooks/useCreateCompanyProgress.ts deleted file mode 100644 index ff7dfc08f..000000000 --- a/front/src/modules/companies/hooks/useCreateCompanyProgress.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useRecoilCallback, useRecoilState } from 'recoil'; -import { v4 } from 'uuid'; - -import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord'; -import { currentPipelineState } from '@/pipeline/states/currentPipelineState'; -import { Opportunity } from '@/pipeline/types/Opportunity'; -import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState'; - -export const useCreateCompanyProgress = () => { - const { createOneObject: createOneOpportunity } = - useCreateOneObjectRecord({ - objectNameSingular: 'opportunityV2', - }); - - const [currentPipeline] = useRecoilState(currentPipelineState); - - return useRecoilCallback( - ({ set }) => - async (companyId: string, pipelineStageId: string) => { - if (!currentPipeline?.id) { - throw new Error('Pipeline not found'); - } - - const newUuid = v4(); - - set(boardCardIdsByColumnIdFamilyState(pipelineStageId), (oldValue) => [ - ...oldValue, - newUuid, - ]); - - await createOneOpportunity?.({ - pipelineStepId: pipelineStageId, - companyId: companyId, - }); - }, - [createOneOpportunity, currentPipeline?.id], - ); -}; diff --git a/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts b/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts index 1fd8e8ad4..313069c26 100644 --- a/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts +++ b/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts @@ -1,6 +1,8 @@ -import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; -import { useSearchCompanyQuery } from '~/generated/graphql'; -import { getLogoUrlFromDomainName } from '~/utils'; +import { useQuery } from '@apollo/client'; + +import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; +import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2'; +import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; export const useFilteredSearchCompanyQuery = ({ searchFilter, @@ -11,25 +13,32 @@ export const useFilteredSearchCompanyQuery = ({ selectedIds?: string[]; limit?: number; }) => { - return useFilteredSearchEntityQuery({ - queryHook: useSearchCompanyQuery, + const { findManyQuery } = useFindOneObjectMetadataItem({ + objectNameSingular: 'company', + }); + + const useFindManyCompanies = (options: any) => + useQuery(findManyQuery, options); + + return useFilteredSearchEntityQueryV2({ + queryHook: useFindManyCompanies, filters: [ { - fieldNames: ['name'], + fieldNames: ['name.firstName', 'name.lastName'], filter: searchFilter, }, ], - orderByField: 'name', + orderByField: 'createdAt', mappingFunction: (company) => ({ + entityType: Entity.Company, id: company.id, - entityType: 'Company', name: company.name, - avatarUrl: getLogoUrlFromDomainName(company.domainName), - domainName: company.domainName, avatarType: 'squared', + avatarUrl: '', originalEntity: company, }), selectedIds: selectedIds, + objectNamePlural: 'workspaceMembers', limit, }); }; diff --git a/front/src/modules/companies/hooks/useSpreadsheetCompanyImport.ts b/front/src/modules/companies/hooks/useSpreadsheetCompanyImport.ts deleted file mode 100644 index 95e5f71b8..000000000 --- a/front/src/modules/companies/hooks/useSpreadsheetCompanyImport.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { v4 as uuidv4 } from 'uuid'; - -import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport'; -import { SpreadsheetOptions } from '@/spreadsheet-import/types'; -import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar'; -import { useInsertManyCompanyMutation } from '~/generated/graphql'; - -import { fieldsForCompany } from '../utils/fieldsForCompany'; - -export type FieldCompanyMapping = (typeof fieldsForCompany)[number]['key']; - -export const useSpreadsheetCompanyImport = () => { - const { openSpreadsheetImport } = useSpreadsheetImport(); - const { enqueueSnackBar } = useSnackBar(); - - const [createManyCompany] = useInsertManyCompanyMutation(); - - const openCompanySpreadsheetImport = ( - options?: Omit< - SpreadsheetOptions, - 'fields' | 'isOpen' | 'onClose' - >, - ) => { - openSpreadsheetImport({ - ...options, - onSubmit: async (data) => { - // TODO: Add better type checking in spreadsheet import later - const createInputs = data.validData.map((company) => ({ - id: uuidv4(), - name: (company.name ?? '') as string, - domainName: (company.domainName ?? '') as string, - address: (company.address ?? '') as string, - employees: parseInt((company.employees ?? '') as string, 10), - linkedinUrl: (company.linkedinUrl ?? '') as string | undefined, - })); - - try { - const result = await createManyCompany({ - variables: { - data: createInputs, - }, - refetchQueries: 'active', - }); - - if (result.errors) { - throw result.errors; - } - } catch (error: any) { - enqueueSnackBar(error?.message || 'Something went wrong', { - variant: 'error', - }); - } - }, - fields: fieldsForCompany, - }); - }; - - return { openCompanySpreadsheetImport }; -}; diff --git a/front/src/modules/companies/table/components/CompanyTable.tsx b/front/src/modules/companies/table/components/CompanyTable.tsx deleted file mode 100644 index 78bfbea34..000000000 --- a/front/src/modules/companies/table/components/CompanyTable.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import styled from '@emotion/styled'; -import { useRecoilCallback } from 'recoil'; - -import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions'; -import { getCompaniesOptimisticEffectDefinition } from '@/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition'; -import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries'; -import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport'; -import { RecordTableEffect } from '@/ui/object/record-table/components/RecordTableEffect'; -import { RecordTableV1 } from '@/ui/object/record-table/components/RecordTableV1'; -import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown'; -import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; -import { ViewBar } from '@/views/components/ViewBar'; -import { useViewFields } from '@/views/hooks/internal/useViewFields'; -import { useView } from '@/views/hooks/useView'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField'; -import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; -import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; -import { - UpdateOneCompanyMutationVariables, - useGetCompaniesQuery, - useGetWorkspaceMembersLazyQuery, - useUpdateOneCompanyMutation, -} from '~/generated/graphql'; -import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions'; -import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions'; - -import CompanyTableEffect from './CompanyTableEffect'; - -const StyledContainer = styled.div` - display: flex; - flex-direction: column; - height: 100%; - overflow: auto; -`; - -export const CompanyTable = () => { - const viewScopeId = 'company-table-view'; - const tableScopeId = 'companies'; - - const { - setTableFilters, - setTableSorts, - setTableColumns, - upsertRecordTableItem, - } = useRecordTable({ - recordTableScopeId: tableScopeId, - }); - - const [updateEntityMutation] = useUpdateOneCompanyMutation(); - - const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery(); - const { persistViewFields } = useViewFields(viewScopeId); - const { setEntityCountInCurrentView } = useView({ viewScopeId }); - - const { setContextMenuEntries, setActionBarEntries } = - useCompanyTableContextMenuEntries(); - - const updateCompany = async ( - variables: UpdateOneCompanyMutationVariables, - ) => { - if (variables.data.accountOwner?.connect?.id) { - const workspaceMemberAccountOwner = ( - await getWorkspaceMember({ - variables: { - where: { - userId: { equals: variables.data.accountOwner.connect?.id }, - }, - }, - }) - ).data?.workspaceMembers?.[0]; - variables.data.workspaceMemberAccountOwner = { - connect: { id: workspaceMemberAccountOwner?.id }, - }; - } - - updateEntityMutation({ - variables: variables, - onCompleted: (data) => { - if (!data.updateOneCompany) { - return; - } - upsertRecordTableItem(data.updateOneCompany); - }, - }); - }; - - const { openCompanySpreadsheetImport: onImport } = - useSpreadsheetCompanyImport(); - - return ( - { - setTableColumns( - mapViewFieldsToColumnDefinitions( - viewFields, - companiesAvailableFieldDefinitions, - ), - ); - }} - onViewFiltersChange={(viewFilters) => { - setTableFilters(mapViewFiltersToFilters(viewFilters)); - }} - onViewSortsChange={(viewSorts) => { - setTableSorts(mapViewSortsToSorts(viewSorts)); - }} - > - - (columns) => { - persistViewFields(mapColumnDefinitionsToViewFields(columns)); - })} - onEntityCountChange={useRecoilCallback(() => (entityCount) => { - setEntityCountInCurrentView(entityCount); - })} - > - } - optionsDropdownScopeId={TableOptionsDropdownId} - /> - - - updateCompany(variables)} - /> - - - - ); -}; diff --git a/front/src/modules/companies/table/components/CompanyTableEffect.tsx b/front/src/modules/companies/table/components/CompanyTableEffect.tsx deleted file mode 100644 index b512100f2..000000000 --- a/front/src/modules/companies/table/components/CompanyTableEffect.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect } from 'react'; - -import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { useView } from '@/views/hooks/useView'; -import { ViewType } from '@/views/types/ViewType'; -import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions'; -import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions'; - -const CompanyTableEffect = () => { - const { - setAvailableSortDefinitions, - setAvailableFilterDefinitions, - setAvailableFieldDefinitions, - setViewType, - setViewObjectMetadataId, - } = useView(); - - const { setAvailableTableColumns } = useRecordTable(); - - useEffect(() => { - setAvailableSortDefinitions?.(companyTableSortDefinitions); - setAvailableFilterDefinitions?.(companyTableFilterDefinitions); - setAvailableFieldDefinitions?.(companiesAvailableFieldDefinitions); - setViewObjectMetadataId?.('company'); - setViewType?.(ViewType.Table); - - setAvailableTableColumns(companiesAvailableFieldDefinitions); - }, [ - setAvailableFieldDefinitions, - setAvailableFilterDefinitions, - setAvailableSortDefinitions, - setAvailableTableColumns, - setViewObjectMetadataId, - setViewType, - ]); - - return <>; -}; - -export default CompanyTableEffect; diff --git a/front/src/modules/companies/table/components/CompanyTableMockDataEffect.tsx b/front/src/modules/companies/table/components/CompanyTableMockDataEffect.tsx deleted file mode 100644 index b71462416..000000000 --- a/front/src/modules/companies/table/components/CompanyTableMockDataEffect.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useEffect } from 'react'; - -import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; - -import { mockedCompaniesData } from './companies-mock-data'; - -export const CompanyTableMockDataEffect = () => { - const { setRecordTableData, setTableColumns } = useRecordTable(); - - useEffect(() => { - setRecordTableData(mockedCompaniesData); - setTableColumns(companiesAvailableFieldDefinitions); - }, [setRecordTableData, setTableColumns]); - - return <>; -}; diff --git a/front/src/modules/companies/table/components/CompanyTableMockMode.tsx b/front/src/modules/companies/table/components/CompanyTableMockMode.tsx deleted file mode 100644 index 09a033e3c..000000000 --- a/front/src/modules/companies/table/components/CompanyTableMockMode.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import styled from '@emotion/styled'; - -import { RecordTable } from '@/ui/object/record-table/components/RecordTable'; -import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; -import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown'; -import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; -import { ViewBar } from '@/views/components/ViewBar'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { useUpdateOneCompanyMutation } from '~/generated/graphql'; - -import CompanyTableEffect from './CompanyTableEffect'; -import { CompanyTableMockDataEffect } from './CompanyTableMockDataEffect'; - -const StyledContainer = styled.div` - display: flex; - flex-direction: column; - height: 100%; - overflow: auto; -`; - -export const CompanyTableMockMode = () => { - return ( - - - {}} - onEntityCountChange={() => {}} - > - - - } - optionsDropdownScopeId={TableOptionsDropdownId} - /> - - - - - - ); -}; diff --git a/front/src/modules/companies/table/components/companies-mock-data.ts b/front/src/modules/companies/table/components/companies-mock-data.ts deleted file mode 100644 index 283473197..000000000 --- a/front/src/modules/companies/table/components/companies-mock-data.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { Favorite } from '@/favorites/types/Favorite'; -import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; - -import { Company } from '../../../../generated/graphql'; - -type MockedCompany = Pick< - Company, - | 'id' - | 'name' - | 'domainName' - | '__typename' - | 'createdAt' - | 'address' - | 'employees' - | 'linkedinUrl' - | 'xUrl' - | 'annualRecurringRevenue' - | 'idealCustomerProfile' - | '_activityCount' -> & { - accountOwner: Pick | null; -} & { Favorite: Pick | null }; - -export const mockedCompaniesData: Array = [ - { - id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', - domainName: 'airbnb.com', - name: 'Airbnb', - linkedinUrl: 'https://www.linkedin.com/company/airbnb/', - xUrl: 'https://twitter.com/airbnb', - annualRecurringRevenue: 500000, - idealCustomerProfile: true, - createdAt: '2023-04-26T10:08:54.724515+00:00', - address: 'San Francisco, CA', - employees: 5000, - Favorite: null, - _activityCount: 0, - accountOwner: { - name: { - firstName: 'Charles', - lastName: 'Test', - }, - avatarUrl: null, - id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', - }, - __typename: 'Company', - }, - { - id: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae', - domainName: 'qonto.com', - name: 'Qonto', - linkedinUrl: 'https://www.linkedin.com/company/qonto/', - xUrl: 'https://twitter.com/qonto', - annualRecurringRevenue: 500000, - idealCustomerProfile: false, - createdAt: '2023-04-26T10:12:42.33625+00:00', - address: 'Paris, France', - employees: 800, - Favorite: null, - _activityCount: 0, - accountOwner: null, - __typename: 'Company', - }, - { - id: 'a674fa6c-1455-4c57-afaf-dd5dc086361d', - domainName: 'stripe.com', - name: 'Stripe', - linkedinUrl: 'https://www.linkedin.com/company/stripe/', - xUrl: 'https://twitter.com/stripe', - annualRecurringRevenue: 5000000, - idealCustomerProfile: false, - createdAt: '2023-04-26T10:10:32.530184+00:00', - address: 'San Francisco, CA', - employees: 8000, - Favorite: null, - _activityCount: 0, - accountOwner: null, - __typename: 'Company', - }, - { - id: 'b1cfd51b-a831-455f-ba07-4e30671e1dc3', - domainName: 'figma.com', - linkedinUrl: 'https://www.linkedin.com/company/figma/', - xUrl: 'https://twitter.com/figma', - annualRecurringRevenue: 50000, - idealCustomerProfile: true, - name: 'Figma', - createdAt: '2023-03-21T06:30:25.39474+00:00', - address: 'San Francisco, CA', - employees: 800, - Favorite: null, - _activityCount: 0, - accountOwner: null, - __typename: 'Company', - }, - { - id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb', - domainName: 'notion.com', - linkedinUrl: 'https://www.linkedin.com/company/notion/', - xUrl: 'https://twitter.com/notion', - annualRecurringRevenue: 500000, - idealCustomerProfile: false, - name: 'Notion', - createdAt: '2023-04-26T10:13:29.712485+00:00', - address: 'San Francisco, CA', - employees: 400, - Favorite: null, - _activityCount: 0, - accountOwner: null, - __typename: 'Company', - }, -]; diff --git a/front/src/modules/companies/types/Company.ts b/front/src/modules/companies/types/Company.ts new file mode 100644 index 000000000..f5cf7cb5e --- /dev/null +++ b/front/src/modules/companies/types/Company.ts @@ -0,0 +1,15 @@ +export type Company = { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + name: string; + domainName: string; + address: string; + accountOwnerId: string | null; + linkedinUrl: { url: string; label: string }; + xUrl: { url: string; label: string }; + annualRecurringRevenue: { amountMicros: number | null; currencyCode: string }; + employees: number | null; + idealCustomerProfile: boolean; +}; diff --git a/front/src/modules/companies/types/CompanyProgress.ts b/front/src/modules/companies/types/CompanyProgress.ts index ca981fed3..6791fca10 100644 --- a/front/src/modules/companies/types/CompanyProgress.ts +++ b/front/src/modules/companies/types/CompanyProgress.ts @@ -1,5 +1,5 @@ +import { Company } from '@/companies/types/Company'; import { Opportunity } from '@/pipeline/types/Opportunity'; -import { Company } from '~/generated/graphql'; export type CompanyForBoard = Pick; export type PipelineProgressForBoard = Opportunity; diff --git a/front/src/modules/favorites/components/Favorites.tsx b/front/src/modules/favorites/components/Favorites.tsx index baa75ff47..86f8402f3 100644 --- a/front/src/modules/favorites/components/Favorites.tsx +++ b/front/src/modules/favorites/components/Favorites.tsx @@ -18,7 +18,7 @@ const StyledContainer = styled.div` export const Favorites = () => { // This is only temporary and will be refactored once we have main identifiers const { favorites, handleReorderFavorite } = useFavorites({ - objectNamePlural: 'companiesV2', + objectNamePlural: 'companies', }); if (!favorites || favorites.length === 0) return <>; diff --git a/front/src/modules/favorites/graphql/mutations/deleteFavorite.ts b/front/src/modules/favorites/graphql/mutations/deleteFavorite.ts deleted file mode 100644 index 4e8f2d0c7..000000000 --- a/front/src/modules/favorites/graphql/mutations/deleteFavorite.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_FAVORITE = gql` - mutation DeleteFavorite($where: FavoriteWhereInput!) { - deleteFavorite(where: $where) { - id - } - } -`; diff --git a/front/src/modules/favorites/graphql/mutations/insertCompanyFavorite.ts b/front/src/modules/favorites/graphql/mutations/insertCompanyFavorite.ts deleted file mode 100644 index e6cdc7a7c..000000000 --- a/front/src/modules/favorites/graphql/mutations/insertCompanyFavorite.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_COMPANY_FAVORITE = gql` - mutation InsertCompanyFavorite($data: FavoriteMutationForCompanyArgs!) { - createFavoriteForCompany(data: $data) { - id - company { - id - name - domainName - } - } - } -`; diff --git a/front/src/modules/favorites/graphql/mutations/insertPersonFavorite.ts b/front/src/modules/favorites/graphql/mutations/insertPersonFavorite.ts deleted file mode 100644 index b18cb0ecd..000000000 --- a/front/src/modules/favorites/graphql/mutations/insertPersonFavorite.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_PERSON_FAVORITE = gql` - mutation InsertPersonFavorite($data: FavoriteMutationForPersonArgs!) { - createFavoriteForPerson(data: $data) { - id - person { - id - firstName - lastName - displayName - } - } - } -`; diff --git a/front/src/modules/favorites/graphql/mutations/updateOneFavorite.ts b/front/src/modules/favorites/graphql/mutations/updateOneFavorite.ts deleted file mode 100644 index f31aa5602..000000000 --- a/front/src/modules/favorites/graphql/mutations/updateOneFavorite.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_FAVORITE = gql` - mutation UpdateOneFavorite( - $data: FavoriteUpdateInput! - $where: FavoriteWhereUniqueInput! - ) { - updateOneFavorites(data: $data, where: $where) { - id - person { - id - firstName - lastName - avatarUrl - } - company { - id - name - domainName - accountOwner { - id - displayName - avatarUrl - } - } - } - } -`; diff --git a/front/src/modules/favorites/graphql/queries/getFavorites.ts b/front/src/modules/favorites/graphql/queries/getFavorites.ts deleted file mode 100644 index 7102bed1e..000000000 --- a/front/src/modules/favorites/graphql/queries/getFavorites.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_FAVORITES = gql` - query GetFavorites { - findFavorites { - id - position - person { - id - firstName - lastName - avatarUrl - } - company { - id - name - domainName - accountOwner { - id - displayName - avatarUrl - } - } - } - } -`; diff --git a/front/src/modules/favorites/hooks/useFavorites.ts b/front/src/modules/favorites/hooks/useFavorites.ts index 696f97bea..145522b0d 100644 --- a/front/src/modules/favorites/hooks/useFavorites.ts +++ b/front/src/modules/favorites/hooks/useFavorites.ts @@ -4,12 +4,12 @@ import { OnDragEndResponder } from '@hello-pangea/dnd'; import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; +import { Company } from '@/companies/types/Company'; import { Favorite } from '@/favorites/types/Favorite'; import { mapFavorites } from '@/favorites/utils/mapFavorites'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults'; -import { Company } from '~/generated/graphql'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { favoritesState } from '../states/favoritesState'; @@ -25,7 +25,7 @@ export const useFavorites = ({ const { updateOneMutation, createOneMutation, deleteOneMutation } = useFindOneObjectMetadataItem({ - objectNamePlural: 'favoritesV2', + objectNamePlural: 'favorites', }); const { foundObjectMetadataItem: favoriteTargetObjectMetadataItem } = @@ -44,7 +44,7 @@ export const useFavorites = ({ // This is only temporary and will be refactored once we have main identifiers const { loading: companiesLoading } = useFindManyObjectRecords({ - objectNamePlural: 'companiesV2', + objectNamePlural: 'companies', onCompleted: async ( data: PaginatedObjectTypeResults>, ) => { @@ -64,7 +64,7 @@ export const useFavorites = ({ }); const { loading: peopleLoading } = useFindManyObjectRecords({ - objectNamePlural: 'peopleV2', + objectNamePlural: 'people', onCompleted: async (data) => { setAllPeople( data.edges.reduce( @@ -84,7 +84,7 @@ export const useFavorites = ({ useFindManyObjectRecords({ skip: companiesLoading || peopleLoading, - objectNamePlural: 'favoritesV2', + objectNamePlural: 'favorites', onCompleted: useRecoilCallback( ({ snapshot, set }) => async (data: PaginatedObjectTypeResults>) => { @@ -112,8 +112,7 @@ export const useFavorites = ({ const favorites = snapshot.getLoadable(favoritesState).getValue(); const targetObjectName = - favoriteTargetObjectMetadataItem?.nameSingular.replace('V2', '') ?? - ''; + favoriteTargetObjectMetadataItem?.nameSingular ?? ''; const result = await apolloClient.mutate({ mutation: createOneMutation, diff --git a/front/src/modules/favorites/utils/mapFavorites.ts b/front/src/modules/favorites/utils/mapFavorites.ts index 7810ae26d..3a26d4be6 100644 --- a/front/src/modules/favorites/utils/mapFavorites.ts +++ b/front/src/modules/favorites/utils/mapFavorites.ts @@ -1,4 +1,5 @@ -import { Company, Person } from '~/generated/graphql'; +import { Company } from '@/companies/types/Company'; +import { Person } from '@/people/types/Person'; import { getLogoUrlFromDomainName } from '~/utils'; import { assertNotNull } from '~/utils/assert'; import { isDefined } from '~/utils/isDefined'; @@ -7,8 +8,8 @@ export const mapFavorites = ( favorites: any, recordsDict: { [key: string]: { - firstName?: Person['firstName']; - lastName?: Person['lastName']; + firstName?: Person['name']['firstName']; + lastName?: Person['name']['lastName']; avatarUrl?: Person['avatarUrl']; name?: Company['name']; domainName?: Company['domainName']; diff --git a/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx new file mode 100644 index 000000000..b4d55bcb5 --- /dev/null +++ b/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -0,0 +1,9 @@ +import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems'; + +export const ObjectMetadataItemsProvider = ({ + children, +}: React.PropsWithChildren) => { + const { loading } = useFindManyObjectMetadataItems(); + + return loading ? <> : <>{children}; +}; diff --git a/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx b/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx index eed8e28e2..38f7b10d9 100644 --- a/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx +++ b/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx @@ -1,28 +1,19 @@ import { useNavigate } from 'react-router-dom'; +import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings'; import { Icon123 } from '@/ui/input/constants/icons'; import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import NavItem from '@/ui/navigation/navbar/components/NavItem'; -import { useFindManyObjectMetadataItems } from '../hooks/useFindManyObjectMetadataItems'; - export const ObjectMetadataNavItems = () => { - const { objectMetadataItems } = useFindManyObjectMetadataItems({ - objectFilter: { - isSystem: { is: false }, - }, - fieldFilter: { - isSystem: { is: false }, - }, - }); - + const { activeObjectMetadataItems } = useObjectMetadataItemForSettings(); const navigate = useNavigate(); const { icons } = useLazyLoadIcons(); return ( <> - {objectMetadataItems.map((objectMetadataItem) => { - if (objectMetadataItem.nameSingular === 'opportunityV2') return null; + {activeObjectMetadataItems.map((objectMetadataItem) => { + if (objectMetadataItem.nameSingular === 'opportunity') return null; return ( { + if (!objectMetadataItem) { + return { + columnDefinitions: [], + filterDefinitions: [], + sortDefinitions: [], + }; + } + + const activeFieldMetadataItems = objectMetadataItem.fields.filter( + ({ isActive }) => isActive, + ); + + const columnDefinitions: ColumnDefinition[] = + activeFieldMetadataItems.map((field, index) => + formatFieldMetadataItemAsColumnDefinition({ + position: index, + field, + objectMetadataItem: objectMetadataItem, + }), + ); + + const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({ + fields: activeFieldMetadataItems, + }); + + const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ + fields: activeFieldMetadataItems, + }); + + return { + columnDefinitions, + filterDefinitions, + sortDefinitions, + }; +}; diff --git a/front/src/modules/object-metadata/hooks/useFindOneObjectMetadataItem.ts b/front/src/modules/object-metadata/hooks/useFindOneObjectMetadataItem.ts index 85c3427ec..b74bf26a1 100644 --- a/front/src/modules/object-metadata/hooks/useFindOneObjectMetadataItem.ts +++ b/front/src/modules/object-metadata/hooks/useFindOneObjectMetadataItem.ts @@ -5,14 +5,8 @@ import { useGenerateDeleteOneObjectMutation } from '@/object-record/utils/useGen import { useGenerateFindManyCustomObjectsQuery } from '@/object-record/utils/useGenerateFindManyCustomObjectsQuery'; import { useGenerateFindOneCustomObjectQuery } from '@/object-record/utils/useGenerateFindOneCustomObjectQuery'; import { useGenerateUpdateOneObjectMutation } from '@/object-record/utils/useGenerateUpdateOneObjectMutation'; -import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier'; -import { formatFieldMetadataItemAsColumnDefinition } from '../utils/formatFieldMetadataItemAsColumnDefinition'; -import { formatFieldMetadataItemsAsFilterDefinitions } from '../utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { formatFieldMetadataItemsAsSortDefinitions } from '../utils/formatFieldMetadataItemsAsSortDefinitions'; import { useFindManyObjectMetadataItems } from './useFindManyObjectMetadataItems'; @@ -43,37 +37,10 @@ export const useFindOneObjectMetadataItem = ({ object.nameSingular === objectNameSingular, ); - const { icons } = useLazyLoadIcons(); - const objectNotFoundInMetadata = objectMetadataItems.length === 0 || (objectMetadataItems.length > 0 && !foundObjectMetadataItem); - const activeFields = - foundObjectMetadataItem?.fields.filter(({ isActive }) => isActive) ?? []; - - const columnDefinitions: ColumnDefinition[] = - foundObjectMetadataItem - ? activeFields.map((field, index) => - formatFieldMetadataItemAsColumnDefinition({ - position: index, - field, - objectMetadataItem: foundObjectMetadataItem, - icons, - }), - ) - : []; - - const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({ - fields: activeFields, - icons, - }); - - const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ - fields: activeFields, - icons, - }); - const findManyQuery = useGenerateFindManyCustomObjectsQuery({ objectMetadataItem: foundObjectMetadataItem, }); @@ -97,9 +64,6 @@ export const useFindOneObjectMetadataItem = ({ return { foundObjectMetadataItem, objectNotFoundInMetadata, - columnDefinitions, - filterDefinitions, - sortDefinitions, findManyQuery, findOneQuery, createOneMutation, diff --git a/front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts b/front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts index c736a142b..c397aebe1 100644 --- a/front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts +++ b/front/src/modules/object-metadata/hooks/useObjectMetadataItemForSettings.ts @@ -8,20 +8,13 @@ import { useFindManyObjectMetadataItems } from './useFindManyObjectMetadataItems import { useUpdateOneObjectMetadataItem } from './useUpdateOneObjectMetadataItem'; export const useObjectMetadataItemForSettings = () => { - const { objectMetadataItems, loading } = useFindManyObjectMetadataItems({ - objectFilter: { - isSystem: { is: false }, - }, - fieldFilter: { - isSystem: { is: false }, - }, - }); + const { objectMetadataItems, loading } = useFindManyObjectMetadataItems(); const activeObjectMetadataItems = objectMetadataItems.filter( - ({ isActive }) => isActive, + ({ isActive, isSystem }) => isActive && !isSystem, ); const disabledObjectMetadataItems = objectMetadataItems.filter( - ({ isActive }) => !isActive, + ({ isActive, isSystem }) => !isActive && !isSystem, ); const findActiveObjectMetadataItemBySlug = (slug: string) => diff --git a/front/src/modules/object-metadata/states/objectMetadataItemsState.ts b/front/src/modules/object-metadata/states/objectMetadataItemsState.ts deleted file mode 100644 index 10e8de47f..000000000 --- a/front/src/modules/object-metadata/states/objectMetadataItemsState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { atom } from 'recoil'; - -import { ObjectMetadataItem } from '../types/ObjectMetadataItem'; - -/** - * @deprecated Use `useFindManyObjectMetadataItems` instead. - */ -export const objectMetadataItemsState = atom({ - key: 'objectMetadataItemsState', - default: [], -}); diff --git a/front/src/modules/object-metadata/states/selectors/activeObjectMetadataItemsSelector.ts b/front/src/modules/object-metadata/states/selectors/activeObjectMetadataItemsSelector.ts deleted file mode 100644 index 977511bb9..000000000 --- a/front/src/modules/object-metadata/states/selectors/activeObjectMetadataItemsSelector.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { selector } from 'recoil'; - -import { ObjectMetadataItem } from '../../types/ObjectMetadataItem'; -import { objectMetadataItemsState } from '../objectMetadataItemsState'; - -export const activeObjectMetadataItemsSelector = selector( - { - key: 'activeObjectMetadataItemsSelector', - get: ({ get }) => - get(objectMetadataItemsState).filter(({ isActive }) => isActive), - }, -); diff --git a/front/src/modules/object-metadata/states/selectors/disabledObjectMetadataItemsSelector.ts b/front/src/modules/object-metadata/states/selectors/disabledObjectMetadataItemsSelector.ts deleted file mode 100644 index b9a6bc393..000000000 --- a/front/src/modules/object-metadata/states/selectors/disabledObjectMetadataItemsSelector.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { selector } from 'recoil'; - -import { ObjectMetadataItem } from '../../types/ObjectMetadataItem'; -import { objectMetadataItemsState } from '../objectMetadataItemsState'; - -export const disabledObjectMetadataItemsSelector = selector< - ObjectMetadataItem[] ->({ - key: 'disabledObjectMetadataItemsSelector', - get: ({ get }) => - get(objectMetadataItemsState).filter(({ isActive }) => !isActive), -}); diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts index 7f961ee72..3894054e4 100644 --- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts +++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts @@ -1,5 +1,4 @@ import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType'; -import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; @@ -12,12 +11,10 @@ export const formatFieldMetadataItemAsColumnDefinition = ({ position, field, objectMetadataItem, - icons, }: { position: number; field: FieldMetadataItem; objectMetadataItem: Omit; - icons: Record; }): ColumnDefinition => ({ position, fieldMetadataId: field.id, @@ -28,7 +25,7 @@ export const formatFieldMetadataItemAsColumnDefinition = ({ fieldName: field.name, placeHolder: field.label, }, - Icon: icons[field.icon ?? 'Icon123'], + iconName: field.icon ?? 'Icon123', isVisible: true, basePathToShowPage: `/object/${objectMetadataItem.nameSingular}/`, relationType: parseFieldRelationType(field), diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts index 16f146f1c..be0dccbf8 100644 --- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts +++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts @@ -5,10 +5,8 @@ import { ObjectMetadataItem } from '../types/ObjectMetadataItem'; export const formatFieldMetadataItemsAsFilterDefinitions = ({ fields, - icons, }: { fields: Array; - icons: Record; }): FilterDefinition[] => fields.reduce((acc, field) => { if ( @@ -20,22 +18,17 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({ ) { return acc; } - return [ - ...acc, - formatFieldMetadataItemAsFilterDefinition({ field, icons }), - ]; + return [...acc, formatFieldMetadataItemAsFilterDefinition({ field })]; }, [] as FilterDefinition[]); const formatFieldMetadataItemAsFilterDefinition = ({ field, - icons, }: { field: ObjectMetadataItem['fields'][0]; - icons: Record; }): FilterDefinition => ({ fieldMetadataId: field.id, label: field.label, - Icon: icons[field.icon ?? 'Icon123'], + iconName: field.icon ?? 'Icon123', type: field.type === FieldMetadataType.Date ? 'DATE' diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions.ts index 8f137b83f..3ed609e72 100644 --- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions.ts +++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions.ts @@ -5,10 +5,8 @@ import { ObjectMetadataItem } from '../types/ObjectMetadataItem'; export const formatFieldMetadataItemsAsSortDefinitions = ({ fields, - icons, }: { fields: Array; - icons: Record; }): SortDefinition[] => fields.reduce((acc, field) => { if ( @@ -27,7 +25,7 @@ export const formatFieldMetadataItemsAsSortDefinitions = ({ { fieldMetadataId: field.id, label: field.label, - Icon: icons[field.icon ?? 'Icon123'], + iconName: field.icon ?? 'Icon123', }, ]; }, [] as SortDefinition[]); diff --git a/front/src/modules/object-record/components/RecordShowPage.tsx b/front/src/modules/object-record/components/RecordShowPage.tsx index 089d082d3..020418fea 100644 --- a/front/src/modules/object-record/components/RecordShowPage.tsx +++ b/front/src/modules/object-record/components/RecordShowPage.tsx @@ -7,7 +7,6 @@ import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOne import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; import { filterAvailableFieldMetadataItem } from '@/object-record/utils/filterAvailableFieldMetadataItem'; import { IconBuildingSkyscraper } from '@/ui/display/icon'; -import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; @@ -36,8 +35,6 @@ export const RecordShowPage = () => { objectMetadataId: string; }>(); - const { icons } = useLazyLoadIcons(); - const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ objectNameSingular, }); @@ -91,7 +88,7 @@ export const RecordShowPage = () => { if (isFavorite) deleteFavorite(object?.id); else { const additionalData = - objectNameSingular === 'personV2' + objectNameSingular === 'person' ? { labelIdentifier: object.name.firstName + ' ' + object.name.lastName, @@ -100,7 +97,7 @@ export const RecordShowPage = () => { link: `/object/personV2/${object.id}`, recordId: object.id, } - : objectNameSingular === 'companyV2' + : objectNameSingular === 'company' ? { labelIdentifier: object.name, avatarUrl: getLogoUrlFromDomainName(object.domainName ?? ''), @@ -116,7 +113,7 @@ export const RecordShowPage = () => { if (!object) return <>; const pageName = - objectNameSingular === 'personV2' + objectNameSingular === 'person' ? object.name.firstName + ' ' + object.name.lastName : object.name; @@ -173,7 +170,6 @@ export const RecordShowPage = () => { field: metadataField, position: index, objectMetadataItem: foundObjectMetadataItem, - icons, }), useUpdateEntityMutation: useUpdateOneObjectMutation, hotkeyScope: InlineCellHotkeyScope.InlineCell, diff --git a/front/src/modules/object-record/components/RecordTableContainer.tsx b/front/src/modules/object-record/components/RecordTableContainer.tsx index 3fcc36d42..c0e768ddd 100644 --- a/front/src/modules/object-record/components/RecordTableContainer.tsx +++ b/front/src/modules/object-record/components/RecordTableContainer.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { useRecoilCallback } from 'recoil'; +import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { RecordTable } from '@/ui/object/record-table/components/RecordTable'; import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; @@ -9,7 +10,6 @@ import { TableOptionsDropdown } from '@/ui/object/record-table/options/component import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; import { ViewBar } from '@/views/components/ViewBar'; import { useViewFields } from '@/views/hooks/internal/useViewFields'; -import { useView } from '@/views/hooks/useView'; import { ViewScope } from '@/views/scopes/ViewScope'; import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; @@ -32,10 +32,12 @@ export const RecordTableContainer = ({ }: { objectNamePlural: string; }) => { - const { columnDefinitions, foundObjectMetadataItem } = - useFindOneObjectMetadataItem({ - objectNamePlural, - }); + const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ + objectNamePlural, + }); + const { columnDefinitions } = useComputeDefinitionsFromFieldMetadata( + foundObjectMetadataItem, + ); const { updateOneObject } = useUpdateOneObjectRecord({ objectNameSingular: foundObjectMetadataItem?.nameSingular, @@ -50,8 +52,6 @@ export const RecordTableContainer = ({ recordTableScopeId: tableScopeId, }); - const { setEntityCountInCurrentView } = useView({ viewScopeId }); - const updateEntity = ({ variables, }: { @@ -89,9 +89,6 @@ export const RecordTableContainer = ({ onColumnsChange={useRecoilCallback(() => (columns) => { persistViewFields(mapColumnDefinitionsToViewFields(columns)); })} - onEntityCountChange={(entityCount) => { - setEntityCountInCurrentView(entityCount); - }} > } diff --git a/front/src/modules/object-record/components/RecordTableEffect.tsx b/front/src/modules/object-record/components/RecordTableEffect.tsx index 2d99f1b5b..fb7ab109b 100644 --- a/front/src/modules/object-record/components/RecordTableEffect.tsx +++ b/front/src/modules/object-record/components/RecordTableEffect.tsx @@ -1,5 +1,6 @@ import { useEffect } from 'react'; +import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; @@ -8,24 +9,26 @@ import { useView } from '@/views/hooks/useView'; import { ViewType } from '@/views/types/ViewType'; export const RecordTableEffect = () => { - const { scopeId: objectNamePlural, setAvailableTableColumns } = - useRecordTable(); - const { - columnDefinitions, - filterDefinitions, - sortDefinitions, - foundObjectMetadataItem, - } = useFindOneObjectMetadataItem({ + scopeId: objectNamePlural, + setAvailableTableColumns, + setOnEntityCountChange, + } = useRecordTable(); + + const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ objectNamePlural, }); + const { columnDefinitions, filterDefinitions, sortDefinitions } = + useComputeDefinitionsFromFieldMetadata(foundObjectMetadataItem); + const { setAvailableSortDefinitions, setAvailableFilterDefinitions, setAvailableFieldDefinitions, setViewType, setViewObjectMetadataId, + setEntityCountInCurrentView, } = useView(); useEffect(() => { @@ -65,5 +68,11 @@ export const RecordTableEffect = () => { setContextMenuEntries?.(); }, [setActionBarEntries, setContextMenuEntries]); + useEffect(() => { + setOnEntityCountChange( + () => (entityCount: number) => setEntityCountInCurrentView(entityCount), + ); + }, [setEntityCountInCurrentView, setOnEntityCountChange]); + return <>; }; diff --git a/front/src/modules/object-record/components/RecordTablePage.tsx b/front/src/modules/object-record/components/RecordTablePage.tsx index 56f570b01..3af5a5d2b 100644 --- a/front/src/modules/object-record/components/RecordTablePage.tsx +++ b/front/src/modules/object-record/components/RecordTablePage.tsx @@ -19,6 +19,7 @@ import { RecordTableContainer } from './RecordTableContainer'; const StyledTableContainer = styled.div` display: flex; + height: 100%; width: 100%; `; @@ -48,7 +49,8 @@ export const RecordTablePage = () => { }); const handleAddButtonClick = async () => { - createOneObject?.({}); + const createdObject = await createOneObject?.({}); + console.log(createdObject); }; return ( diff --git a/front/src/modules/object-record/graphql/mutation/createOneWorkspaceMember.ts b/front/src/modules/object-record/graphql/mutation/createOneWorkspaceMember.ts index e105fb63b..381fa5ad9 100644 --- a/front/src/modules/object-record/graphql/mutation/createOneWorkspaceMember.ts +++ b/front/src/modules/object-record/graphql/mutation/createOneWorkspaceMember.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; export const CREATE_ONE_WORKSPACE_MEMBER_V2 = gql` - mutation CreateOneWorkspaceMemberV2($input: WorkspaceMemberV2CreateInput!) { - createWorkspaceMemberV2(data: $input) { + mutation CreateOneWorkspaceMember($input: WorkspaceMemberCreateInput!) { + createWorkspaceMember(data: $input) { id name { firstName diff --git a/front/src/modules/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition.ts b/front/src/modules/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition.ts index 6d7123361..9f015d3d8 100644 --- a/front/src/modules/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition.ts +++ b/front/src/modules/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition.ts @@ -23,6 +23,17 @@ export const getRecordOptimisticEffectDefinition = ({ const newRecordPaginatedCacheField = produce< PaginatedObjectTypeResults >(currentData as PaginatedObjectTypeResults, (draft) => { + if (!draft) { + return { + edges: [{ node: newData, cursor: '' }], + pageInfo: { + endCursor: '', + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + }, + }; + } draft.edges.unshift({ node: newData, cursor: '' }); }); diff --git a/front/src/modules/object-record/graphql/queries/findOneWorkspaceMember.ts b/front/src/modules/object-record/graphql/queries/findOneWorkspaceMember.ts deleted file mode 100644 index 57ac25a64..000000000 --- a/front/src/modules/object-record/graphql/queries/findOneWorkspaceMember.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { gql } from '@apollo/client'; - -export const FIND_ONE_WORKSPACE_MEMBER_V2 = gql` - query FindManyWorkspaceMembersV2($filter: WorkspaceMemberV2FilterInput) { - workspaceMembersV2(filter: $filter) { - edges { - node { - id - name { - firstName - lastName - } - colorScheme - avatarUrl - locale - allowImpersonation - } - } - } - } -`; diff --git a/front/src/modules/object-record/hooks/useObjectRecordTable.ts b/front/src/modules/object-record/hooks/useObjectRecordTable.ts index edf321409..4863ce6d2 100644 --- a/front/src/modules/object-record/hooks/useObjectRecordTable.ts +++ b/front/src/modules/object-record/hooks/useObjectRecordTable.ts @@ -14,14 +14,14 @@ import { useFindManyObjectRecords } from './useFindManyObjectRecords'; export const useObjectRecordTable = () => { const { scopeId: objectNamePlural } = useRecordTable(); - const { registerOptimisticEffect } = useOptimisticEffect({ - objectNameSingular: 'companyV2', - }); - const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ objectNamePlural, }); + const { registerOptimisticEffect } = useOptimisticEffect({ + objectNameSingular: foundObjectMetadataItem?.nameSingular, + }); + const { setRecordTableData } = useRecordTable(); const { tableFiltersState, tableSortsState } = useRecordTableScopedStates(); diff --git a/front/src/modules/people/components/PeopleCard.tsx b/front/src/modules/people/components/PeopleCard.tsx index a273d3226..46e20788b 100644 --- a/front/src/modules/people/components/PeopleCard.tsx +++ b/front/src/modules/people/components/PeopleCard.tsx @@ -1,9 +1,9 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { autoUpdate, flip, offset, useFloating } from '@floating-ui/react'; +import { Person } from '@/people/types/Person'; import { IconDotsVertical, IconLinkOff, IconTrash } from '@/ui/display/icon'; import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; @@ -11,16 +11,9 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { Avatar } from '@/users/components/Avatar'; -import { - Person, - useDeleteManyPersonMutation, - useUpdateOnePersonMutation, -} from '~/generated/graphql'; - -import { GET_PEOPLE } from '../graphql/queries/getPeople'; export type PeopleCardProps = { - person: Pick; + person: Pick; hasBottomBorder?: boolean; }; @@ -78,8 +71,6 @@ export const PeopleCard = ({ const navigate = useNavigate(); const [isHovered, setIsHovered] = useState(false); const [isOptionsOpen, setIsOptionsOpen] = useState(false); - const [updatePerson] = useUpdateOnePersonMutation(); - const [deletePerson] = useDeleteManyPersonMutation(); const { refs, floatingStyles } = useFloating({ strategy: 'absolute', @@ -114,28 +105,28 @@ export const PeopleCard = ({ }; const handleDetachPerson = () => { - updatePerson({ - variables: { - where: { - id: person.id, - }, - data: { - company: { - disconnect: true, - }, - }, - }, - refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - }); + // updatePerson({ + // variables: { + // where: { + // id: person.id, + // }, + // data: { + // company: { + // disconnect: true, + // }, + // }, + // }, + // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], + // }); }; const handleDeletePerson = () => { - deletePerson({ - variables: { - ids: person.id, - }, - refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - }); + // deletePerson({ + // variables: { + // ids: person.id, + // }, + // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], + // }); }; return ( @@ -149,11 +140,13 @@ export const PeopleCard = ({ - {person.displayName} + + {person.name.firstName + ' ' + person.name.lastName} + {person.jobTitle && {person.jobTitle}} {isHovered && ( diff --git a/front/src/modules/people/components/PeoplePicker.tsx b/front/src/modules/people/components/PeoplePicker.tsx index 60945e211..9c8ce3c43 100644 --- a/front/src/modules/people/components/PeoplePicker.tsx +++ b/front/src/modules/people/components/PeoplePicker.tsx @@ -1,12 +1,13 @@ 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 { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect'; import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState'; import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -import { useSearchPeopleQuery } from '~/generated/graphql'; export type PeoplePickerProps = { personId: string | null; @@ -40,7 +41,7 @@ export const PeoplePicker = ({ const queryFilters = [ { - fieldNames: ['firstName', 'lastName'], + fieldNames: ['name.firstName', 'name.lastName'], filter: relationPickerSearchFilter, }, ]; @@ -52,24 +53,32 @@ export const PeoplePicker = ({ }); } - const people = useFilteredSearchEntityQuery({ - queryHook: useSearchPeopleQuery, - selectedIds: [personId ?? ''], + const { findManyQuery } = useFindOneObjectMetadataItem({ + objectNameSingular: 'person', + }); + + const useFindManyPeople = (options: any) => useQuery(findManyQuery, options); + + const people = useFilteredSearchEntityQueryV2({ + queryHook: useFindManyPeople, filters: queryFilters, - mappingFunction: (person) => ({ - entityType: Entity.Person, - id: person.id, - name: `${person.firstName} ${person.lastName}`, + orderByField: 'createdAt', + mappingFunction: (workspaceMember) => ({ + entityType: Entity.WorkspaceMember, + id: workspaceMember.id, + name: + workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName, avatarType: 'rounded', - avatarUrl: person.avatarUrl ?? '', - originalEntity: person, + avatarUrl: '', + originalEntity: workspaceMember, }), - orderByField: 'firstName', + selectedIds: [personId ?? ''], excludeEntityIds: excludePersonIds, + objectNamePlural: 'people', }); const handleEntitySelected = async ( - selectedPerson: PersonForSelect | null | undefined, + selectedPerson: any | null | undefined, ) => { onSubmit(selectedPerson ?? null); }; diff --git a/front/src/modules/people/components/PeopleRecordTableDataEffect.tsx b/front/src/modules/people/components/PeopleRecordTableDataEffect.tsx deleted file mode 100644 index 71e48499a..000000000 --- a/front/src/modules/people/components/PeopleRecordTableDataEffect.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { - PersonOrderByWithRelationInput, - SortOrder, - useGetPeopleQuery, -} from '~/generated/graphql'; - -import { useSetPeopleRecordTable } from '../hooks/useSetPeopleRecordTable'; - -export const PeopleRecordTableDataEffect = ({ - orderBy = [ - { - createdAt: SortOrder.Desc, - }, - ], - whereFilters, -}: { - orderBy?: PersonOrderByWithRelationInput[]; - whereFilters?: any; -}) => { - const setPeopleRecordTable = useSetPeopleRecordTable(); - - useGetPeopleQuery({ - variables: { orderBy, where: whereFilters }, - onCompleted: (data) => { - const people = data.people ?? []; - - setPeopleRecordTable(people); - }, - }); - - return <>; -}; diff --git a/front/src/modules/people/components/__stories__/PeopleFullNameEditableField.stories.tsx b/front/src/modules/people/components/__stories__/PeopleFullNameEditableField.stories.tsx deleted file mode 100644 index 3c9cee6b8..000000000 --- a/front/src/modules/people/components/__stories__/PeopleFullNameEditableField.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; - -import { mockedPeopleData } from '~/testing/mock-data/people'; - -import { PeopleFullNameEditableField } from '../../editable-field/components/PeopleFullNameEditableField'; - -const meta: Meta = { - title: 'Modules/People/EditableFields/PeopleFullNameEditableField', - component: PeopleFullNameEditableField, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - render: () => , -}; diff --git a/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx b/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx deleted file mode 100644 index 9365386a0..000000000 --- a/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { - IconBrandLinkedin, - IconBrandX, - IconBriefcase, - IconBuildingSkyscraper, - IconCalendarEvent, - IconMail, - IconMap, - IconPhone, - IconUser, -} from '@/ui/display/icon/index'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { - FieldDateMetadata, - FieldDoubleTextChipMetadata, - FieldEmailMetadata, - FieldMetadata, - FieldPhoneMetadata, - FieldRelationMetadata, - FieldTextMetadata, - FieldURLMetadata, -} from '@/ui/object/field/types/FieldMetadata'; -import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; -import { Company } from '~/generated/graphql'; -import { getLogoUrlFromDomainName } from '~/utils'; - -export const peopleAvailableFieldDefinitions: ColumnDefinition[] = - [ - { - fieldMetadataId: 'displayName', - label: 'People', - Icon: IconUser, - size: 210, - position: 0, - type: 'DOUBLE_TEXT_CHIP', - metadata: { - firstValueFieldName: 'firstName', - secondValueFieldName: 'lastName', - firstValuePlaceholder: 'F​irst n​ame', // Hack: Fake character to prevent password-manager from filling the field - secondValuePlaceholder: 'L​ast n​ame', // Hack: Fake character to prevent password-manager from filling the field - avatarUrlFieldName: 'avatarUrl', - entityType: Entity.Person, - }, - infoTooltipContent: 'Contact’s first and last name.', - basePathToShowPage: '/person/', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'email', - label: 'Email', - Icon: IconMail, - size: 150, - type: 'EMAIL', - position: 1, - metadata: { - fieldName: 'email', - placeHolder: 'Ema​il', // Hack: Fake character to prevent password-manager from filling the field - }, - infoTooltipContent: 'Contact’s Email.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'company', - label: 'Company', - Icon: IconBuildingSkyscraper, - size: 150, - position: 2, - type: 'RELATION', - metadata: { - fieldName: 'company', - relationType: Entity.Company, - }, - infoTooltipContent: 'Contact’s company.', - entityChipDisplayMapper: (dataObject: Company) => { - return { - name: dataObject?.name, - pictureUrl: getLogoUrlFromDomainName(dataObject?.domainName), - avatarType: 'squared', - }; - }, - } satisfies ColumnDefinition, - { - fieldMetadataId: 'phone', - label: 'Phone', - Icon: IconPhone, - size: 150, - position: 3, - type: 'PHONE', - metadata: { - fieldName: 'phone', - placeHolder: 'Phon​e', // Hack: Fake character to prevent password-manager from filling the field - }, - infoTooltipContent: 'Contact’s phone number.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'createdAt', - label: 'Creation', - Icon: IconCalendarEvent, - size: 150, - position: 4, - type: 'DATE', - metadata: { - fieldName: 'createdAt', - }, - infoTooltipContent: 'Date when the contact was added.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'city', - label: 'City', - Icon: IconMap, - size: 150, - position: 5, - type: 'TEXT', - metadata: { - fieldName: 'city', - placeHolder: 'Cit​y', // Hack: Fake character to prevent password-manager from filling the field - }, - infoTooltipContent: 'Contact’s city.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'jobTitle', - label: 'Job title', - Icon: IconBriefcase, - size: 150, - position: 6, - type: 'TEXT', - metadata: { - fieldName: 'jobTitle', - placeHolder: 'Job title', - }, - infoTooltipContent: 'Contact’s job title.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'linkedin', - label: 'LinkedIn', - Icon: IconBrandLinkedin, - size: 150, - position: 7, - type: 'URL', - metadata: { - fieldName: 'linkedinUrl', - placeHolder: 'LinkedIn', - }, - infoTooltipContent: 'Contact’s Linkedin account.', - } satisfies ColumnDefinition, - { - fieldMetadataId: 'x', - label: 'Twitter', - Icon: IconBrandX, - size: 150, - position: 8, - type: 'URL', - metadata: { - fieldName: 'xUrl', - placeHolder: 'X', - }, - infoTooltipContent: 'Contact’s Twitter account.', - } satisfies ColumnDefinition, - ]; diff --git a/front/src/modules/people/editable-field/components/PeopleFullNameEditableField.tsx b/front/src/modules/people/editable-field/components/PeopleFullNameEditableField.tsx deleted file mode 100644 index bc935cd06..000000000 --- a/front/src/modules/people/editable-field/components/PeopleFullNameEditableField.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useState } from 'react'; - -import { EntityTitleDoubleTextInput } from '@/ui/input/components/EntityTitleDoubleTextInput'; -import { FieldRecoilScopeContext } from '@/ui/object/record-inline-cell/states/recoil-scope-contexts/FieldRecoilScopeContext'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { Person, useUpdateOnePersonMutation } from '~/generated/graphql'; - -type PeopleFullNameEditableFieldProps = { - people: Pick; -}; - -export const PeopleFullNameEditableField = ({ - people, -}: PeopleFullNameEditableFieldProps) => { - const [internalValueFirstName, setInternalValueFirstName] = useState( - people.firstName, - ); - const [internalValueLastName, setInternalValueLastName] = useState( - people.lastName, - ); - - const [updatePeople] = useUpdateOnePersonMutation(); - - const handleChange = async ( - newValueFirstName: string, - newValueLastName: string, - ) => { - setInternalValueFirstName(newValueFirstName); - setInternalValueLastName(newValueLastName); - handleSubmit(newValueFirstName, newValueLastName); - }; - - const handleSubmit = async ( - newValueFirstName: string, - newValueLastName: string, - ) => { - await updatePeople({ - variables: { - where: { - id: people.id, - }, - data: { - firstName: newValueFirstName ?? '', - lastName: newValueLastName ?? '', - }, - }, - }); - }; - - return ( - - - - ); -}; diff --git a/front/src/modules/people/graphql/fragments/personFieldsFragment.ts b/front/src/modules/people/graphql/fragments/personFieldsFragment.ts deleted file mode 100644 index 6156f42d0..000000000 --- a/front/src/modules/people/graphql/fragments/personFieldsFragment.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { gql } from '@apollo/client'; - -export const BASE_PERSON_FIELDS_FRAGMENT = gql` - fragment basePersonFieldsFragment on Person { - id - phone - email - city - firstName - lastName - displayName - avatarUrl - createdAt - } -`; - -export const PERSON_FIELDS_FRAGMENT = gql` - ${BASE_PERSON_FIELDS_FRAGMENT} - fragment personFieldsFragment on Person { - ...basePersonFieldsFragment - jobTitle - linkedinUrl - xUrl - _activityCount - company { - id - name - domainName - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/deleteManyPerson.ts b/front/src/modules/people/graphql/mutations/deleteManyPerson.ts deleted file mode 100644 index 6c2af650d..000000000 --- a/front/src/modules/people/graphql/mutations/deleteManyPerson.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_MANY_PERSON = gql` - mutation DeleteManyPerson($ids: [String!]) { - deleteManyPerson(where: { id: { in: $ids } }) { - count - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/insertManyPerson.ts b/front/src/modules/people/graphql/mutations/insertManyPerson.ts deleted file mode 100644 index a75a32363..000000000 --- a/front/src/modules/people/graphql/mutations/insertManyPerson.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_MANY_PERSON = gql` - mutation InsertManyPerson($data: [PersonCreateManyInput!]!) { - createManyPerson(data: $data) { - count - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/insertOnePerson.ts b/front/src/modules/people/graphql/mutations/insertOnePerson.ts deleted file mode 100644 index d905c66a1..000000000 --- a/front/src/modules/people/graphql/mutations/insertOnePerson.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_ONE_PERSON = gql` - mutation InsertOnePerson($data: PersonCreateInput!) { - createOnePerson(data: $data) { - ...personFieldsFragment - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/removePersonPicture.ts b/front/src/modules/people/graphql/mutations/removePersonPicture.ts deleted file mode 100644 index 01271ef32..000000000 --- a/front/src/modules/people/graphql/mutations/removePersonPicture.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const REMOVE_PERSON_PICTURE = gql` - mutation RemovePersonPicture($where: PersonWhereUniqueInput!) { - updateOnePerson(data: { avatarUrl: null }, where: $where) { - id - avatarUrl - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/updateOnePerson.ts b/front/src/modules/people/graphql/mutations/updateOnePerson.ts deleted file mode 100644 index 63617cf4f..000000000 --- a/front/src/modules/people/graphql/mutations/updateOnePerson.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_ONE_PERSON = gql` - mutation UpdateOnePerson( - $where: PersonWhereUniqueInput! - $data: PersonUpdateInput! - ) { - updateOnePerson(data: $data, where: $where) { - ...personFieldsFragment - } - } -`; diff --git a/front/src/modules/people/graphql/mutations/updatePersonPicture.ts b/front/src/modules/people/graphql/mutations/updatePersonPicture.ts deleted file mode 100644 index c609246bd..000000000 --- a/front/src/modules/people/graphql/mutations/updatePersonPicture.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_PERSON_PICTURE = gql` - mutation UploadPersonPicture($id: String!, $file: Upload!) { - uploadPersonPicture(id: $id, file: $file) - } -`; diff --git a/front/src/modules/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition.ts b/front/src/modules/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition.ts deleted file mode 100644 index 3a07458e2..000000000 --- a/front/src/modules/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Person } from '~/generated/graphql'; - -import { GET_PEOPLE } from '../queries/getPeople'; - -export const getPeopleOptimisticEffectDefinition = { - key: 'generic-entity-table-data-people', - typename: 'Person', - query: GET_PEOPLE, - resolver: ({ - currentData, - newData, - }: { - currentData: Person[]; - newData: Person[]; - }) => { - return [...newData, ...currentData]; - }, -}; diff --git a/front/src/modules/people/graphql/queries/getPeople.ts b/front/src/modules/people/graphql/queries/getPeople.ts deleted file mode 100644 index fd00ae789..000000000 --- a/front/src/modules/people/graphql/queries/getPeople.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { gql } from '@apollo/client'; - -import { PERSON_FIELDS_FRAGMENT } from '../fragments/personFieldsFragment'; - -export const GET_PEOPLE = gql` - ${PERSON_FIELDS_FRAGMENT} - query GetPeople( - $orderBy: [PersonOrderByWithRelationInput!] - $where: PersonWhereInput - $limit: Int - ) { - people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) { - ...personFieldsFragment - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPerson.ts b/front/src/modules/people/graphql/queries/getPerson.ts deleted file mode 100644 index ef908c72e..000000000 --- a/front/src/modules/people/graphql/queries/getPerson.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON = gql` - query GetPerson($id: String!) { - findUniquePerson(id: $id) { - ...personFieldsFragment - Favorite { - id - person { - id - } - company { - id - } - } - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonCity.ts b/front/src/modules/people/graphql/queries/getPersonCity.ts deleted file mode 100644 index c24af2a24..000000000 --- a/front/src/modules/people/graphql/queries/getPersonCity.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_CITY = gql` - query GetPersonCityById($id: String!) { - person: findUniquePerson(id: $id) { - id - city - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonCommentCount.ts b/front/src/modules/people/graphql/queries/getPersonCommentCount.ts deleted file mode 100644 index da0014805..000000000 --- a/front/src/modules/people/graphql/queries/getPersonCommentCount.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_COMMENT_COUNT = gql` - query GetPersonCommentCountById($id: String!) { - person: findUniquePerson(id: $id) { - id - _activityCount - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonCompany.ts b/front/src/modules/people/graphql/queries/getPersonCompany.ts deleted file mode 100644 index b613607cd..000000000 --- a/front/src/modules/people/graphql/queries/getPersonCompany.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_COMPANY = gql` - query GetPersonCompanyById($id: String!) { - person: findUniquePerson(id: $id) { - id - company { - id - name - domainName - } - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonCreatedAt.ts b/front/src/modules/people/graphql/queries/getPersonCreatedAt.ts deleted file mode 100644 index 04cd49822..000000000 --- a/front/src/modules/people/graphql/queries/getPersonCreatedAt.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_CREATED_AT = gql` - query GetPersonCreatedAtById($id: String!) { - person: findUniquePerson(id: $id) { - id - createdAt - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonEmail.ts b/front/src/modules/people/graphql/queries/getPersonEmail.ts deleted file mode 100644 index ece37e1b9..000000000 --- a/front/src/modules/people/graphql/queries/getPersonEmail.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_EMAIL = gql` - query GetPersonEmailById($id: String!) { - person: findUniquePerson(id: $id) { - id - email - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonNamesAndCommentCount.ts b/front/src/modules/people/graphql/queries/getPersonNamesAndCommentCount.ts deleted file mode 100644 index de9b9203c..000000000 --- a/front/src/modules/people/graphql/queries/getPersonNamesAndCommentCount.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_NAMES_AND_COMMENT_COUNT = gql` - query GetPersonNamesAndCommentCountById($id: String!) { - person: findUniquePerson(id: $id) { - id - firstName - lastName - displayName - _activityCount - } - } -`; diff --git a/front/src/modules/people/graphql/queries/getPersonPhone.ts b/front/src/modules/people/graphql/queries/getPersonPhone.ts deleted file mode 100644 index bea227947..000000000 --- a/front/src/modules/people/graphql/queries/getPersonPhone.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PERSON_PHONE = gql` - query GetPersonPhoneById($id: String!) { - person: findUniquePerson(id: $id) { - id - phone - } - } -`; diff --git a/front/src/modules/people/hooks/useCreateActivityForPeople.ts b/front/src/modules/people/hooks/useCreateActivityForPeople.ts deleted file mode 100644 index 5e4a76f16..000000000 --- a/front/src/modules/people/hooks/useCreateActivityForPeople.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useRecoilCallback } from 'recoil'; - -import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds'; -import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; -import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; -import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector'; -import { ActivityType, Person } from '~/generated/graphql'; - -export const useCreateActivityForPeople = () => { - const openCreateActivityRightDrawer = - useOpenCreateActivityDrawerForSelectedRowIds(); - - return useRecoilCallback( - ({ snapshot }) => - (type: ActivityType) => { - const relatedEntites: ActivityTargetableEntity[] = []; - const selectedRowIds = Object.keys( - snapshot.getLoadable(selectedRowIdsSelector).getValue(), - ); - for (const id of selectedRowIds) { - const person = snapshot - .getLoadable(entityFieldsFamilyState(id)) - .getValue() as Person; - if ( - person?.company?.id && - !relatedEntites.find((x) => x.id === person?.company?.id) - ) { - relatedEntites.push({ - id: person.company.id, - type: 'Company', - }); - } - } - - openCreateActivityRightDrawer(type, 'Person', relatedEntites); - }, - [openCreateActivityRightDrawer], - ); -}; diff --git a/front/src/modules/people/hooks/useFilteredSearchPeopleQuery.ts b/front/src/modules/people/hooks/useFilteredSearchPeopleQuery.ts index a7caa3704..92584b505 100644 --- a/front/src/modules/people/hooks/useFilteredSearchPeopleQuery.ts +++ b/front/src/modules/people/hooks/useFilteredSearchPeopleQuery.ts @@ -1,6 +1,8 @@ -import { ActivityTargetableEntityForSelect } from '@/activities/types/ActivityTargetableEntityForSelect'; -import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; -import { useSearchPeopleQuery } from '~/generated/graphql'; +import { useQuery } from '@apollo/client'; + +import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; +import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2'; +import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; export const useFilteredSearchPeopleQuery = ({ searchFilter, @@ -10,24 +12,32 @@ export const useFilteredSearchPeopleQuery = ({ searchFilter: string; selectedIds?: string[]; limit?: number; -}) => - useFilteredSearchEntityQuery({ - queryHook: useSearchPeopleQuery, +}) => { + const { findManyQuery } = useFindOneObjectMetadataItem({ + objectNameSingular: 'person', + }); + + const useFindManyPeople = (options: any) => useQuery(findManyQuery, options); + + return useFilteredSearchEntityQueryV2({ + queryHook: useFindManyPeople, filters: [ { - fieldNames: ['firstName', 'lastName'], + fieldNames: ['name.firstName', 'name.lastName'], filter: searchFilter, }, ], - orderByField: 'lastName', + orderByField: 'createdAt', + mappingFunction: (person) => ({ + entityType: Entity.Person, + id: person.id, + name: person.name.firstName + ' ' + person.name.lastName, + avatarType: 'rounded', + avatarUrl: '', + originalEntity: person, + }), selectedIds: selectedIds, - mappingFunction: (entity) => - ({ - id: entity.id, - entityType: 'Person', - name: `${entity.firstName} ${entity.lastName}`, - avatarUrl: entity.avatarUrl, - avatarType: 'rounded', - } as ActivityTargetableEntityForSelect), + objectNamePlural: 'workspaceMembers', limit, }); +}; diff --git a/front/src/modules/people/hooks/usePersonQuery.ts b/front/src/modules/people/hooks/usePersonQuery.ts deleted file mode 100644 index eadf7ff08..000000000 --- a/front/src/modules/people/hooks/usePersonQuery.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useSetRecoilState } from 'recoil'; - -import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; -import { useGetPersonQuery } from '~/generated/graphql'; - -export const usePersonQuery = (id: string) => { - const updatePersonShowPage = useSetRecoilState(entityFieldsFamilyState(id)); - - return useGetPersonQuery({ - variables: { id }, - onCompleted: (data) => { - updatePersonShowPage(data?.findUniquePerson); - }, - }); -}; diff --git a/front/src/modules/people/hooks/usePersonTableContextMenuEntries.tsx b/front/src/modules/people/hooks/usePersonTableContextMenuEntries.tsx deleted file mode 100644 index 78841d6a1..000000000 --- a/front/src/modules/people/hooks/usePersonTableContextMenuEntries.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { getOperationName } from '@apollo/client/utilities'; -import { useRecoilCallback, useSetRecoilState } from 'recoil'; - -import { useFavorites } from '@/favorites/hooks/useFavorites'; -import { - IconCheckbox, - IconHeart, - IconHeartOff, - IconNotes, - IconTrash, -} from '@/ui/display/icon'; -import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; -import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector'; -import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState'; -import { - ActivityType, - useDeleteManyPersonMutation, - useGetFavoritesQuery, -} from '~/generated/graphql'; - -import { GET_PEOPLE } from '../graphql/queries/getPeople'; - -import { useCreateActivityForPeople } from './useCreateActivityForPeople'; - -export const usePersonTableContextMenuEntries = () => { - const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); - const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState); - const createActivityForPeople = useCreateActivityForPeople(); - - const setTableRowIds = useSetRecoilState(tableRowIdsState); - const { resetTableRowSelection } = useRecordTable({ - recordTableScopeId: 'people', - }); - - const { data } = useGetFavoritesQuery(); - const favorites = data?.findFavorites; - const { createFavorite, deleteFavorite } = useFavorites({ - objectNamePlural: 'people', - }); - - const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => { - const selectedRowIds = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - const selectedPersonId = - selectedRowIds.length === 1 ? selectedRowIds[0] : ''; - - const isFavorite = - !!selectedPersonId && - !!favorites?.find((favorite) => favorite.person?.id === selectedPersonId); - - resetTableRowSelection(); - if (isFavorite) deleteFavorite(selectedPersonId); - else createFavorite('person', selectedPersonId); - }); - - const [deleteManyPerson] = useDeleteManyPersonMutation({ - refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - }); - - const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => { - const rowIdsToDelete = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - resetTableRowSelection(); - - await deleteManyPerson({ - variables: { - ids: rowIdsToDelete, - }, - optimisticResponse: { - __typename: 'Mutation', - deleteManyPerson: { - count: rowIdsToDelete.length, - }, - }, - update: () => { - setTableRowIds((tableRowIds) => - tableRowIds.filter((id) => !rowIdsToDelete.includes(id)), - ); - }, - }); - }); - - return { - setContextMenuEntries: useRecoilCallback(({ snapshot }) => () => { - const selectedRowIds = snapshot - .getLoadable(selectedRowIdsSelector) - .getValue(); - - const selectedPersonId = - selectedRowIds.length === 1 ? selectedRowIds[0] : ''; - - const isFavorite = - !!selectedPersonId && - !!favorites?.find( - (favorite) => favorite.person?.id === selectedPersonId, - ); - - setContextMenuEntries([ - { - label: 'New task', - Icon: IconCheckbox, - onClick: () => createActivityForPeople(ActivityType.Task), - }, - { - label: 'New note', - Icon: IconNotes, - onClick: () => createActivityForPeople(ActivityType.Note), - }, - ...(!!selectedPersonId - ? [ - { - label: isFavorite - ? 'Remove from favorites' - : 'Add to favorites', - Icon: isFavorite ? IconHeartOff : IconHeart, - onClick: () => handleFavoriteButtonClick(), - }, - ] - : []), - { - label: 'Delete', - Icon: IconTrash, - accent: 'danger', - onClick: () => handleDeleteClick(), - }, - ]); - }), - setActionBarEntries: useRecoilCallback(() => () => { - setActionBarEntriesState([ - { - label: 'Task', - Icon: IconCheckbox, - onClick: () => createActivityForPeople(ActivityType.Task), - }, - { - label: 'Note', - Icon: IconNotes, - onClick: () => createActivityForPeople(ActivityType.Note), - }, - { - label: 'Delete', - Icon: IconTrash, - accent: 'danger', - onClick: () => handleDeleteClick(), - }, - ]); - }), - }; -}; diff --git a/front/src/modules/people/hooks/useSetPeopleRecordTable.ts b/front/src/modules/people/hooks/useSetPeopleRecordTable.ts deleted file mode 100644 index 578e9794c..000000000 --- a/front/src/modules/people/hooks/useSetPeopleRecordTable.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { useLocation } from 'react-router-dom'; -import { useRecoilCallback } from 'recoil'; - -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { isFetchingRecordTableDataState } from '@/ui/object/record-table/states/isFetchingRecordTableDataState'; -import { numberOfTableRowsState } from '@/ui/object/record-table/states/numberOfTableRowsState'; -import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState'; -import { currentPageLocationState } from '@/ui/utilities/loading-state/states/currentPageLocationState'; -import { GetPeopleQuery } from '~/generated/graphql'; - -import { peopleCityFamilyState } from '../states/peopleCityFamilyState'; -import { peopleCompanyFamilyState } from '../states/peopleCompanyFamilyState'; -import { peopleCreatedAtFamilyState } from '../states/peopleCreatedAtFamilyState'; -import { peopleEmailFamilyState } from '../states/peopleEmailFamilyState'; -import { peopleJobTitleFamilyState } from '../states/peopleJobTitleFamilyState'; -import { peopleLinkedinUrlFamilyState } from '../states/peopleLinkedinUrlFamilyState'; -import { peopleNameCellFamilyState } from '../states/peopleNamesFamilyState'; -import { peoplePhoneFamilyState } from '../states/peoplePhoneFamilyState'; - -export const useSetPeopleRecordTable = () => { - const { resetTableRowSelection } = useRecordTable(); - - const currentLocation = useLocation().pathname; - - return useRecoilCallback( - ({ set, snapshot }) => - (newPeopleArray: GetPeopleQuery['people']) => { - for (const person of newPeopleArray) { - const currentEmail = snapshot - .getLoadable(peopleEmailFamilyState(person.id)) - .valueOrThrow(); - - if (currentEmail !== person.email) { - set(peopleEmailFamilyState(person.id), person.email ?? null); - } - - const currentCity = snapshot - .getLoadable(peopleCityFamilyState(person.id)) - .valueOrThrow(); - - if (currentCity !== person.city) { - set(peopleCityFamilyState(person.id), person.city ?? null); - } - - const currentCompany = snapshot - .getLoadable(peopleCompanyFamilyState(person.id)) - .valueOrThrow(); - - if ( - JSON.stringify(currentCompany) !== JSON.stringify(person.company) - ) { - set(peopleCompanyFamilyState(person.id), person.company); - } - - const currentPhone = snapshot - .getLoadable(peoplePhoneFamilyState(person.id)) - .valueOrThrow(); - - if (currentPhone !== person.phone) { - set(peoplePhoneFamilyState(person.id), person.phone ?? null); - } - - const currentCreatedAt = snapshot - .getLoadable(peopleCreatedAtFamilyState(person.id)) - .valueOrThrow(); - - if (currentCreatedAt !== person.createdAt) { - set(peopleCreatedAtFamilyState(person.id), person.createdAt); - } - - const currentJobTitle = snapshot - .getLoadable(peopleJobTitleFamilyState(person.id)) - .valueOrThrow(); - - if (currentJobTitle !== person.jobTitle) { - set(peopleJobTitleFamilyState(person.id), person.jobTitle ?? null); - } - - const currentLinkedinUrl = snapshot - .getLoadable(peopleLinkedinUrlFamilyState(person.id)) - .valueOrThrow(); - - if (currentLinkedinUrl !== person.linkedinUrl) { - set( - peopleLinkedinUrlFamilyState(person.id), - person.linkedinUrl ?? null, - ); - } - - const currentNameCell = snapshot - .getLoadable(peopleNameCellFamilyState(person.id)) - .valueOrThrow(); - - if ( - currentNameCell.firstName !== person.firstName || - currentNameCell.lastName !== person.lastName || - currentNameCell.commentCount !== person._activityCount - ) { - set(peopleNameCellFamilyState(person.id), { - firstName: person.firstName ?? null, - lastName: person.lastName ?? null, - commentCount: person._activityCount, - displayName: person.displayName ?? null, - avatarUrl: person.avatarUrl ?? null, - }); - } - } - - const peopleIds = newPeopleArray.map((people) => people.id); - - set(tableRowIdsState, (currentRowIds) => { - if (JSON.stringify(currentRowIds) !== JSON.stringify(peopleIds)) { - return peopleIds; - } - - return currentRowIds; - }); - - resetTableRowSelection(); - - set(numberOfTableRowsState, peopleIds.length); - - set(currentPageLocationState, currentLocation); - - set(isFetchingRecordTableDataState, false); - }, - [currentLocation, resetTableRowSelection], - ); -}; diff --git a/front/src/modules/people/hooks/useSpreadsheetPersonImport.ts b/front/src/modules/people/hooks/useSpreadsheetPersonImport.ts index f9c16d228..003cda2e5 100644 --- a/front/src/modules/people/hooks/useSpreadsheetPersonImport.ts +++ b/front/src/modules/people/hooks/useSpreadsheetPersonImport.ts @@ -3,7 +3,6 @@ import { v4 as uuidv4 } from 'uuid'; import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport'; import { SpreadsheetOptions } from '@/spreadsheet-import/types'; import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar'; -import { useInsertManyPersonMutation } from '~/generated/graphql'; import { fieldsForPerson } from '../utils/fieldsForPerson'; @@ -13,8 +12,6 @@ export const useSpreadsheetPersonImport = () => { const { openSpreadsheetImport } = useSpreadsheetImport(); const { enqueueSnackBar } = useSnackBar(); - const [createManyPerson] = useInsertManyPersonMutation(); - const openPersonSpreadsheetImport = ( options?: Omit< SpreadsheetOptions, @@ -37,22 +34,23 @@ export const useSpreadsheetPersonImport = () => { city: person.city as string | undefined, })); - try { - const result = await createManyPerson({ - variables: { - data: createInputs, - }, - refetchQueries: 'active', - }); + // TODO : abstract this part for any object + // try { + // const result = await createManyPerson({ + // variables: { + // data: createInputs, + // }, + // refetchQueries: 'active', + // }); - if (result.errors) { - throw result.errors; - } - } catch (error: any) { - enqueueSnackBar(error?.message || 'Something went wrong', { - variant: 'error', - }); - } + // if (result.errors) { + // throw result.errors; + // } + // } catch (error: any) { + // enqueueSnackBar(error?.message || 'Something went wrong', { + // variant: 'error', + // }); + // } }, fields: fieldsForPerson, }); diff --git a/front/src/modules/people/states/peopleCityFamilyState.ts b/front/src/modules/people/states/peopleCityFamilyState.ts deleted file mode 100644 index 8808ca711..000000000 --- a/front/src/modules/people/states/peopleCityFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleCityFamilyState = atomFamily({ - key: 'peopleCityFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleCompanyFamilyState.ts b/front/src/modules/people/states/peopleCompanyFamilyState.ts deleted file mode 100644 index b8882a870..000000000 --- a/front/src/modules/people/states/peopleCompanyFamilyState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { atomFamily } from 'recoil'; - -import { GetPeopleQuery } from '~/generated/graphql'; - -export const peopleCompanyFamilyState = atomFamily< - GetPeopleQuery['people'][0]['company'] | null, - string ->({ - key: 'peopleCompanyFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleCreatedAtFamilyState.ts b/front/src/modules/people/states/peopleCreatedAtFamilyState.ts deleted file mode 100644 index 1ef2d8abc..000000000 --- a/front/src/modules/people/states/peopleCreatedAtFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleCreatedAtFamilyState = atomFamily({ - key: 'peopleCreatedAtFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleEmailFamilyState.ts b/front/src/modules/people/states/peopleEmailFamilyState.ts deleted file mode 100644 index dd392b6ed..000000000 --- a/front/src/modules/people/states/peopleEmailFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleEmailFamilyState = atomFamily({ - key: 'peopleEmailFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleJobTitleFamilyState.ts b/front/src/modules/people/states/peopleJobTitleFamilyState.ts deleted file mode 100644 index 36eaaaa61..000000000 --- a/front/src/modules/people/states/peopleJobTitleFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleJobTitleFamilyState = atomFamily({ - key: 'peopleJobTitleFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleLinkedinUrlFamilyState.ts b/front/src/modules/people/states/peopleLinkedinUrlFamilyState.ts deleted file mode 100644 index c2f343024..000000000 --- a/front/src/modules/people/states/peopleLinkedinUrlFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleLinkedinUrlFamilyState = atomFamily({ - key: 'peopleLinkedinUrlFamilyState', - default: null, -}); diff --git a/front/src/modules/people/states/peopleNamesFamilyState.ts b/front/src/modules/people/states/peopleNamesFamilyState.ts deleted file mode 100644 index cf50f397d..000000000 --- a/front/src/modules/people/states/peopleNamesFamilyState.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peopleNameCellFamilyState = atomFamily< - { - firstName: string | null; - lastName: string | null; - commentCount: number | null; - displayName: string | null; - avatarUrl: string | null; - }, - string ->({ - key: 'peopleNameCellFamilyState', - default: { - firstName: null, - lastName: null, - commentCount: null, - displayName: null, - avatarUrl: null, - }, -}); diff --git a/front/src/modules/people/states/peoplePhoneFamilyState.ts b/front/src/modules/people/states/peoplePhoneFamilyState.ts deleted file mode 100644 index 763e9688c..000000000 --- a/front/src/modules/people/states/peoplePhoneFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const peoplePhoneFamilyState = atomFamily({ - key: 'peoplePhoneFamilyState', - default: null, -}); diff --git a/front/src/modules/people/table/components/PersonTable.tsx b/front/src/modules/people/table/components/PersonTable.tsx deleted file mode 100644 index 209fdc2d2..000000000 --- a/front/src/modules/people/table/components/PersonTable.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import styled from '@emotion/styled'; - -import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvailableFieldDefinitions'; -import { getPeopleOptimisticEffectDefinition } from '@/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition'; -import { usePersonTableContextMenuEntries } from '@/people/hooks/usePersonTableContextMenuEntries'; -import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport'; -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { RecordTableEffect } from '@/ui/object/record-table/components/RecordTableEffect'; -import { RecordTableV1 } from '@/ui/object/record-table/components/RecordTableV1'; -import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown'; -import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; -import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; -import { ViewBar } from '@/views/components/ViewBar'; -import { useViewFields } from '@/views/hooks/internal/useViewFields'; -import { useView } from '@/views/hooks/useView'; -import { ViewScope } from '@/views/scopes/ViewScope'; -import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField'; -import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; -import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; -import { - UpdateOnePersonMutationVariables, - useGetPeopleQuery, - useUpdateOnePersonMutation, -} from '~/generated/graphql'; -import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions'; -import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions'; - -import PersonTableEffect from './PersonTableEffect'; - -export const PersonTable = () => { - const viewScopeId = 'person-table-view'; - const tableScopeId = 'people'; - - const { - setTableFilters, - setTableSorts, - setTableColumns, - upsertRecordTableItem, - } = useRecordTable({ - recordTableScopeId: tableScopeId, - }); - - const [updateEntityMutation] = useUpdateOnePersonMutation(); - - const { persistViewFields } = useViewFields(viewScopeId); - - const { setContextMenuEntries, setActionBarEntries } = - usePersonTableContextMenuEntries(); - - const updatePerson = async (variables: UpdateOnePersonMutationVariables) => { - updateEntityMutation({ - variables: variables, - onCompleted: (data) => { - if (!data.updateOnePerson) { - return; - } - upsertRecordTableItem(data.updateOnePerson); - }, - }); - }; - - const handleColumnChange = (columns: ColumnDefinition[]) => { - persistViewFields(mapColumnDefinitionsToViewFields(columns)); - }; - - const { openPersonSpreadsheetImport: onImport } = - useSpreadsheetPersonImport(); - - const { setEntityCountInCurrentView } = useView({ viewScopeId }); - - const StyledContainer = styled.div` - display: flex; - flex-direction: column; - overflow: auto; - `; - - return ( - { - setTableColumns( - mapViewFieldsToColumnDefinitions( - viewFields, - peopleAvailableFieldDefinitions, - ), - ); - }} - onViewFiltersChange={(viewFilters) => { - setTableFilters(mapViewFiltersToFilters(viewFilters)); - }} - onViewSortsChange={(viewSorts) => { - setTableSorts(mapViewSortsToSorts(viewSorts)); - }} - > - - { - setEntityCountInCurrentView(entityCount); - }} - > - } - optionsDropdownScopeId={TableOptionsDropdownId} - /> - - - updatePerson(variables)} - /> - - - - ); -}; diff --git a/front/src/modules/people/table/components/PersonTableEffect.tsx b/front/src/modules/people/table/components/PersonTableEffect.tsx deleted file mode 100644 index c97d2adb0..000000000 --- a/front/src/modules/people/table/components/PersonTableEffect.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect } from 'react'; - -import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvailableFieldDefinitions'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { useView } from '@/views/hooks/useView'; -import { ViewType } from '@/views/types/ViewType'; -import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions'; -import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions'; - -const PeopleTableEffect = () => { - const { - setAvailableSortDefinitions, - setAvailableFilterDefinitions, - setAvailableFieldDefinitions, - setViewType, - setViewObjectMetadataId, - } = useView(); - - const { setAvailableTableColumns } = useRecordTable(); - - useEffect(() => { - setAvailableSortDefinitions?.(personTableSortDefinitions); - setAvailableFilterDefinitions?.(personTableFilterDefinitions); - setAvailableFieldDefinitions?.(peopleAvailableFieldDefinitions); - setViewObjectMetadataId?.('person'); - setViewType?.(ViewType.Table); - - setAvailableTableColumns(peopleAvailableFieldDefinitions); - }, [ - setAvailableFieldDefinitions, - setAvailableFilterDefinitions, - setAvailableSortDefinitions, - setAvailableTableColumns, - setViewObjectMetadataId, - setViewType, - ]); - - return <>; -}; - -export default PeopleTableEffect; diff --git a/front/src/modules/people/types/Person.ts b/front/src/modules/people/types/Person.ts new file mode 100644 index 000000000..3048495fa --- /dev/null +++ b/front/src/modules/people/types/Person.ts @@ -0,0 +1,24 @@ +export type Person = { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + name: { + firstName: string; + lastName: string; + }; + avatarUrl: string; + jobTitle: string; + linkedinLink: { + url: string; + label: string; + }; + xLink: { + url: string; + label: string; + }; + city: string; + email: string; + phone: string; + companyId: string; +}; diff --git a/front/src/modules/pipeline/components/PipelineAddButton.tsx b/front/src/modules/pipeline/components/PipelineAddButton.tsx index 7d695224e..e0be2cee2 100644 --- a/front/src/modules/pipeline/components/PipelineAddButton.tsx +++ b/front/src/modules/pipeline/components/PipelineAddButton.tsx @@ -1,5 +1,4 @@ import { CompanyProgressPicker } from '@/companies/components/CompanyProgressPicker'; -import { useCreateCompanyProgress } from '@/companies/hooks/useCreateCompanyProgress'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { IconPlus } from '@/ui/display/icon/index'; import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar'; @@ -18,8 +17,6 @@ export const PipelineAddButton = () => { dropdownScopeId: 'add-pipeline-progress', }); - const createCompanyProgress = useCreateCompanyProgress(); - const handleCompanySelected = ( selectedCompany: EntityForSelect | null, selectedPipelineStageId: string | null, @@ -48,7 +45,7 @@ export const PipelineAddButton = () => { return; } closeDropdown(); - createCompanyProgress(selectedCompany.id, selectedPipelineStageId); + //createCompanyProgress(selectedCompany.id, selectedPipelineStageId); }; return ( diff --git a/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx b/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx index 49834d68c..6a90a5111 100644 --- a/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx +++ b/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx @@ -1,9 +1,4 @@ -import { - IconCalendarEvent, - IconCurrencyDollar, - IconProgressCheck, - IconUser, -} from '@/ui/display/icon'; +import { Person } from '@/people/types/Person'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { FieldDateMetadata, @@ -13,14 +8,13 @@ import { FieldRelationMetadata, } from '@/ui/object/field/types/FieldMetadata'; import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; -import { Person } from '~/generated/graphql'; export const pipelineAvailableFieldDefinitions: ColumnDefinition[] = [ { fieldMetadataId: 'closeDate', label: 'Close Date', - Icon: IconCalendarEvent, + iconName: 'IconCalendarEvent', position: 0, type: 'DATE', metadata: { @@ -34,7 +28,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ { fieldMetadataId: 'amount', label: 'Amount', - Icon: IconCurrencyDollar, + iconName: 'IconCurrencyDollar', position: 1, type: 'NUMBER', metadata: { @@ -48,7 +42,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ { fieldMetadataId: 'probability', label: 'Probability', - Icon: IconProgressCheck, + iconName: 'IconProgressCheck', position: 2, type: 'PROBABILITY', metadata: { @@ -62,7 +56,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ { fieldMetadataId: 'pointOfContact', label: 'Point of Contact', - Icon: IconUser, + iconName: 'IconUser', position: 3, type: 'RELATION', metadata: { @@ -75,7 +69,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ infoTooltipContent: 'Primary contact within the company.', entityChipDisplayMapper: (dataObject: Person) => { return { - name: dataObject?.displayName, + name: dataObject?.name.firstName + ' ' + dataObject?.name.lastName, pictureUrl: dataObject?.avatarUrl ?? undefined, avatarType: 'rounded', }; diff --git a/front/src/modules/pipeline/hooks/usePipelineStages.ts b/front/src/modules/pipeline/hooks/usePipelineStages.ts index e14d2c097..032ec555c 100644 --- a/front/src/modules/pipeline/hooks/usePipelineStages.ts +++ b/front/src/modules/pipeline/hooks/usePipelineStages.ts @@ -12,12 +12,12 @@ export const usePipelineStages = () => { const { createOneObject: createOnePipelineStep } = useCreateOneObjectRecord({ - objectNameSingular: 'pipelineStepV2', + objectNameSingular: 'pipelineStep', }); const { deleteOneObject: deleteOnePipelineStep } = useDeleteOneObjectRecord({ - objectNameSingular: 'pipelineStepV2', + objectNameSingular: 'pipelineStep', }); const handlePipelineStageAdd = async (boardColumn: BoardColumnDefinition) => { diff --git a/front/src/modules/pipeline/states/currentPipelineState.ts b/front/src/modules/pipeline/states/currentPipelineState.ts index c80fb0782..2de1a5e5f 100644 --- a/front/src/modules/pipeline/states/currentPipelineState.ts +++ b/front/src/modules/pipeline/states/currentPipelineState.ts @@ -1,8 +1,7 @@ import { atom } from 'recoil'; +import { undefined } from 'zod'; -import { Pipeline } from '~/generated/graphql'; - -export const currentPipelineState = atom({ +export const currentPipelineState = atom({ key: 'currentPipelineState', default: undefined, }); diff --git a/front/src/modules/pipeline/types/Opportunity.ts b/front/src/modules/pipeline/types/Opportunity.ts index 8f215f2f4..fc841efab 100644 --- a/front/src/modules/pipeline/types/Opportunity.ts +++ b/front/src/modules/pipeline/types/Opportunity.ts @@ -1,5 +1,5 @@ +import { Person } from '@/people/types/Person'; import { PipelineStep } from '@/pipeline/types/PipelineStep'; -import { Person } from '~/generated-metadata/graphql'; export type Opportunity = { id: string; @@ -12,6 +12,6 @@ export type Opportunity = { pipelineStepId: string; pipelineStep: PipelineStep; pointOfContactId: string; - pointOfContact: Pick; + pointOfContact: Pick; [key: string]: any; }; diff --git a/front/src/modules/search/graphql/queries/searchActivityQuery.ts b/front/src/modules/search/graphql/queries/searchActivityQuery.ts deleted file mode 100644 index 48551e624..000000000 --- a/front/src/modules/search/graphql/queries/searchActivityQuery.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { gql } from '@apollo/client'; - -export const SEARCH_ACTIVITY_QUERY = gql` - query SearchActivity( - $where: ActivityWhereInput - $limit: Int - $orderBy: [ActivityOrderByWithRelationInput!] - ) { - searchResults: findManyActivities( - where: $where - take: $limit - orderBy: $orderBy - ) { - id - title - body - } - } -`; diff --git a/front/src/modules/search/graphql/queries/searchCompanyQuery.ts b/front/src/modules/search/graphql/queries/searchCompanyQuery.ts deleted file mode 100644 index ae65c87c7..000000000 --- a/front/src/modules/search/graphql/queries/searchCompanyQuery.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { gql } from '@apollo/client'; - -export const SEARCH_COMPANY_QUERY = gql` - query SearchCompany( - $where: CompanyWhereInput - $limit: Int - $orderBy: [CompanyOrderByWithRelationInput!] - ) { - searchResults: findManyCompany( - where: $where - take: $limit - orderBy: $orderBy - ) { - ...companyFieldsFragment - } - } -`; diff --git a/front/src/modules/search/graphql/queries/searchPeopleQuery.ts b/front/src/modules/search/graphql/queries/searchPeopleQuery.ts deleted file mode 100644 index 4ee3dbff4..000000000 --- a/front/src/modules/search/graphql/queries/searchPeopleQuery.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { gql } from '@apollo/client'; - -import { BASE_PERSON_FIELDS_FRAGMENT } from '@/people/graphql/fragments/personFieldsFragment'; - -export const SEARCH_PEOPLE_QUERY = gql` - ${BASE_PERSON_FIELDS_FRAGMENT} - query SearchPeople( - $where: PersonWhereInput - $limit: Int - $orderBy: [PersonOrderByWithRelationInput!] - ) { - searchResults: findManyPerson( - where: $where - take: $limit - orderBy: $orderBy - ) { - ...basePersonFieldsFragment - } - } -`; diff --git a/front/src/modules/search/graphql/queries/searchUserQuery.ts b/front/src/modules/search/graphql/queries/searchUserQuery.ts deleted file mode 100644 index d13a94ff3..000000000 --- a/front/src/modules/search/graphql/queries/searchUserQuery.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { gql } from '@apollo/client'; - -export const SEARCH_USER_QUERY = gql` - query SearchUser( - $where: UserWhereInput - $limit: Int - $orderBy: [UserOrderByWithRelationInput!] - ) { - searchResults: findManyUser( - where: $where - take: $limit - orderBy: $orderBy - ) { - ...userFieldsFragment - avatarUrl - } - } -`; diff --git a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts deleted file mode 100644 index 443a2f9df..000000000 --- a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { QueryHookOptions, QueryResult } from '@apollo/client'; - -import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect'; -import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; -import { - Exact, - InputMaybe, - QueryMode, - Scalars, - SortOrder, -} from '~/generated/graphql'; - -type SelectStringKeys = NonNullable< - { - [K in keyof T]: K extends '__typename' - ? never - : T[K] extends string | undefined | null - ? K - : never; - }[keyof T] ->; - -type ExtractEntityTypeFromQueryResponse = T extends { - searchResults: Array; -} - ? 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 useFilteredSearchEntityQuery = < - EntityType extends ExtractEntityTypeFromQueryResponse & { - id: string; - }, - EntityStringField extends SelectStringKeys, - OrderByField extends EntityStringField, - QueryResponseForExtract, - QueryResponse extends { - searchResults: EntityType[]; - }, - EntityWhereInput, - EntityOrderByWithRelationInput, - QueryVariables extends Exact<{ - where?: InputMaybe; - limit?: InputMaybe; - orderBy?: InputMaybe< - Array | EntityOrderByWithRelationInput - >; - }>, - CustomEntityForSelect extends EntityForSelect, ->({ - queryHook, - orderByField, - filters, - sortOrder = SortOrder.Asc, - selectedIds, - mappingFunction, - limit, - excludeEntityIds = [], -}: { - queryHook: ( - queryOptions?: QueryHookOptions, - ) => QueryResult; - orderByField: OrderByField; - filters: SearchFilter[]; - sortOrder?: SortOrder; - selectedIds: string[]; - mappingFunction: (entity: EntityType) => CustomEntityForSelect; - limit?: number; - excludeEntityIds?: string[]; -}): EntitiesForMultipleEntitySelect => { - const { loading: selectedEntitiesLoading, data: selectedEntitiesData } = - queryHook({ - variables: { - where: { - id: { - in: selectedIds, - }, - }, - orderBy: { - [orderByField]: sortOrder, - }, - } as QueryVariables, - }); - - const searchFilter = filters.map(({ fieldNames, filter }) => { - return { - OR: fieldNames.map((fieldName) => ({ - [fieldName]: { - contains: `%${filter}%`, - mode: QueryMode.Insensitive, - }, - })), - }; - }); - - const { - loading: filteredSelectedEntitiesLoading, - data: filteredSelectedEntitiesData, - } = queryHook({ - variables: { - where: { - AND: [ - { - AND: searchFilter, - }, - { - id: { - in: selectedIds, - }, - }, - ], - }, - orderBy: { - [orderByField]: sortOrder, - }, - } as QueryVariables, - }); - - 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 QueryVariables, - }); - - return { - selectedEntities: (selectedEntitiesData?.searchResults ?? []).map( - mappingFunction, - ), - filteredSelectedEntities: ( - filteredSelectedEntitiesData?.searchResults ?? [] - ).map(mappingFunction), - entitiesToSelect: (entitiesToSelectData?.searchResults ?? []).map( - mappingFunction, - ), - loading: - entitiesToSelectLoading || - filteredSelectedEntitiesLoading || - selectedEntitiesLoading, - }; -}; diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx index d3d667480..6e5b302d4 100644 --- a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx +++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx @@ -140,7 +140,7 @@ export const SettingsObjectFieldPreview = ({ entityId, fieldDefinition: { type: parseFieldType(fieldMetadata.type), - Icon: FieldIcon, + iconName: 'FieldIcon', fieldMetadataId: fieldMetadata.id || '', label: fieldMetadata.label, metadata: { fieldName }, diff --git a/front/src/modules/settings/data-model/constants/dataTypes.ts b/front/src/modules/settings/data-model/constants/dataTypes.ts index 445ac3b8e..5de4b90ba 100644 --- a/front/src/modules/settings/data-model/constants/dataTypes.ts +++ b/front/src/modules/settings/data-model/constants/dataTypes.ts @@ -13,7 +13,7 @@ import { IconUser, } from '@/ui/display/icon'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; -import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; const defaultDateValue = new Date(); defaultDateValue.setFullYear(defaultDateValue.getFullYear() + 2); @@ -61,7 +61,7 @@ export const dataTypes: Record< [FieldMetadataType.Currency]: { label: 'Currency', Icon: IconCoins, - defaultValue: { amountMicros: 2000000000, currencyCode: CurrencyCode.Usd }, + defaultValue: { amountMicros: 2000000000, currencyCode: 'USD' }, }, [FieldMetadataType.Relation]: { label: 'Relation', diff --git a/front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx b/front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx index 95510643f..a383fa3b7 100644 --- a/front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx +++ b/front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx @@ -55,7 +55,9 @@ export const SettingsObjectItemTableRow = ({ )} - {objectItem.fields.length} + + {objectItem.fields.filter((field) => !field.isSystem).length} + {objects.length} {action} diff --git a/front/src/modules/settings/developers/graphql/mutations/deleteOneApiKey.ts b/front/src/modules/settings/developers/graphql/mutations/deleteOneApiKey.ts deleted file mode 100644 index 68c53127a..000000000 --- a/front/src/modules/settings/developers/graphql/mutations/deleteOneApiKey.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_ONE_API_KEY = gql` - mutation DeleteOneApiKey($apiKeyId: String!) { - revokeOneApiKey(where: { id: $apiKeyId }) { - id - } - } -`; diff --git a/front/src/modules/settings/developers/graphql/mutations/generateApiKeyV2Token.ts b/front/src/modules/settings/developers/graphql/mutations/generateApiKeyV2Token.ts deleted file mode 100644 index 2a4a49ede..000000000 --- a/front/src/modules/settings/developers/graphql/mutations/generateApiKeyV2Token.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GENERATE_ONE_API_KEY_TOKEN = gql` - mutation GenerateOneApiKeyToken($data: ApiKeyCreateInput!) { - generateApiKeyV2Token(data: $data) { - token - } - } -`; diff --git a/front/src/modules/settings/developers/graphql/mutations/insertOneApiKey.ts b/front/src/modules/settings/developers/graphql/mutations/insertOneApiKey.ts deleted file mode 100644 index b15f1a693..000000000 --- a/front/src/modules/settings/developers/graphql/mutations/insertOneApiKey.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { gql } from '@apollo/client'; - -export const INSERT_ONE_API_KEY = gql` - mutation InsertOneApiKey($data: ApiKeyCreateInput!) { - createOneApiKey(data: $data) { - id - name - token - createdAt - expiresAt - } - } -`; diff --git a/front/src/modules/settings/developers/graphql/queries/getApiKey.ts b/front/src/modules/settings/developers/graphql/queries/getApiKey.ts deleted file mode 100644 index d2d0629cc..000000000 --- a/front/src/modules/settings/developers/graphql/queries/getApiKey.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_API_KEY = gql` - query GetApiKey($apiKeyId: String!) { - findManyApiKey(where: { id: { equals: $apiKeyId } }) { - id - name - expiresAt - createdAt - } - } -`; diff --git a/front/src/modules/settings/developers/graphql/queries/getApiKeys.ts b/front/src/modules/settings/developers/graphql/queries/getApiKeys.ts deleted file mode 100644 index e5dfe37ef..000000000 --- a/front/src/modules/settings/developers/graphql/queries/getApiKeys.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_API_KEYS = gql` - query GetApiKeys { - findManyApiKey { - id - name - expiresAt - createdAt - } - } -`; diff --git a/front/src/modules/settings/developers/optimistic-effect-definitions/getApiKeysOptimisticEffectDefinition.ts b/front/src/modules/settings/developers/optimistic-effect-definitions/getApiKeysOptimisticEffectDefinition.ts deleted file mode 100644 index fa03e7565..000000000 --- a/front/src/modules/settings/developers/optimistic-effect-definitions/getApiKeysOptimisticEffectDefinition.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys'; -import { ApiKey } from '~/generated/graphql'; - -export const getApiKeysOptimisticEffectDefinition = { - key: 'generic-entity-table-data-api-keys', - typename: 'ApiKey', - query: GET_API_KEYS, - resolver: ({ - currentData, - newData, - }: { - currentData: ApiKey[]; - newData: ApiKey[]; - }) => { - return [...newData, ...currentData]; - }, -}; diff --git a/front/src/modules/settings/developers/types/ApiKey.ts b/front/src/modules/settings/developers/types/ApiKey.ts new file mode 100644 index 000000000..f6f525f42 --- /dev/null +++ b/front/src/modules/settings/developers/types/ApiKey.ts @@ -0,0 +1,8 @@ +export type ApiKey = { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + name: string; + expiresAt: string; +}; diff --git a/front/src/modules/settings/developers/utils/format-expiration.ts b/front/src/modules/settings/developers/utils/format-expiration.ts index de85745dc..80ff7427a 100644 --- a/front/src/modules/settings/developers/utils/format-expiration.ts +++ b/front/src/modules/settings/developers/utils/format-expiration.ts @@ -1,5 +1,5 @@ import { ApiFieldItem } from '@/settings/developers/types/ApiFieldItem'; -import { ApiKey } from '~/generated/graphql'; +import { ApiKey } from '@/settings/developers/types/ApiKey'; import { beautifyDateDiff } from '~/utils/date-utils'; export const formatExpiration = ( diff --git a/front/src/modules/settings/profile/components/NameFields.tsx b/front/src/modules/settings/profile/components/NameFields.tsx index c0ef94005..6570bc412 100644 --- a/front/src/modules/settings/profile/components/NameFields.tsx +++ b/front/src/modules/settings/profile/components/NameFields.tsx @@ -42,7 +42,7 @@ export const NameFields = ({ const { updateOneObject, objectNotFoundInMetadata } = useUpdateOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); // TODO: Enhance this with react-web-hook-form (https://www.react-hook-form.com) diff --git a/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx b/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx index 589a5dfcd..df940993d 100644 --- a/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx +++ b/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx @@ -21,7 +21,7 @@ export const ProfilePictureUploader = () => { const { updateOneObject, objectNotFoundInMetadata } = useUpdateOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); const handleUpload = async (file: File) => { diff --git a/front/src/modules/settings/profile/components/ToggleField.tsx b/front/src/modules/settings/profile/components/ToggleField.tsx index 5141187b1..7188b615a 100644 --- a/front/src/modules/settings/profile/components/ToggleField.tsx +++ b/front/src/modules/settings/profile/components/ToggleField.tsx @@ -14,7 +14,7 @@ export const ToggleField = () => { const { updateOneObject, objectNotFoundInMetadata } = useUpdateOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); const handleChange = async (value: boolean) => { diff --git a/front/src/modules/settings/workspace/components/NameField.tsx b/front/src/modules/settings/workspace/components/NameField.tsx index 47aba0a3b..d0f33e002 100644 --- a/front/src/modules/settings/workspace/components/NameField.tsx +++ b/front/src/modules/settings/workspace/components/NameField.tsx @@ -1,12 +1,10 @@ import { useCallback, useEffect, useState } from 'react'; -import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import debounce from 'lodash.debounce'; import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { TextInput } from '@/ui/input/components/TextInput'; -import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser'; import { useUpdateWorkspaceMutation } from '~/generated/graphql'; import { logError } from '~/utils/logError'; @@ -48,12 +46,10 @@ export const NameField = ({ try { const { data, errors } = await updateWorkspace({ variables: { - data: { + input: { displayName: name, }, }, - refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], - awaitRefetchQueries: true, }); if (errors || !data?.updateWorkspace) { diff --git a/front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx b/front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx index 726b7a351..34eb5a5fa 100644 --- a/front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx +++ b/front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx @@ -4,13 +4,13 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { ImageInput } from '@/ui/input/components/ImageInput'; import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI'; import { - useRemoveWorkspaceLogoMutation, + useUpdateWorkspaceMutation, useUploadWorkspaceLogoMutation, } from '~/generated/graphql'; export const WorkspaceLogoUploader = () => { const [uploadLogo] = useUploadWorkspaceLogoMutation(); - const [removeLogo] = useRemoveWorkspaceLogoMutation(); + const [updateWorkspce] = useUpdateWorkspaceMutation(); const [currentWorkspace, setCurrentWorkspace] = useRecoilState( currentWorkspaceState, ); @@ -39,7 +39,12 @@ export const WorkspaceLogoUploader = () => { if (!currentWorkspace?.id) { throw new Error('Workspace id not found'); } - await removeLogo({ + await updateWorkspce({ + variables: { + input: { + logo: null, + }, + }, onCompleted: () => { setCurrentWorkspace({ ...currentWorkspace, diff --git a/front/src/modules/types/AppPath.ts b/front/src/modules/types/AppPath.ts index 11f501e21..6367e8297 100644 --- a/front/src/modules/types/AppPath.ts +++ b/front/src/modules/types/AppPath.ts @@ -11,12 +11,8 @@ export enum AppPath { // Onboarded Index = '/', - PeoplePage = '/people', - CompaniesPage = '/companies', - CompanyShowPage = '/companies/:companyId', - PersonShowPage = '/person/:personId', TasksPage = '/tasks', - OpportunitiesPage = '/opportunities', + OpportunitiesPage = '/objects/opportunities', RecordTablePage = '/objects/:objectNamePlural', RecordShowPage = '/object/:objectNameSingular/:objectMetadataId', diff --git a/front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx b/front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx index ed8c5825d..86aacfa81 100644 --- a/front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx +++ b/front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx @@ -10,7 +10,7 @@ import { import { Checkmark } from '@/ui/display/checkmark/components/Checkmark'; import DarkNoise from '@/ui/theme/assets/dark-noise.jpg'; import LightNoise from '@/ui/theme/assets/light-noise.png'; -import { ColorScheme } from '~/generated/graphql'; +import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; const StyledColorSchemeBackground = styled.div< Pick @@ -18,18 +18,18 @@ const StyledColorSchemeBackground = styled.div< align-items: flex-end; background: ${({ variant }) => { switch (variant) { - case 'dark': + case 'Dark': return `url(${DarkNoise.toString()});`; - case 'light': + case 'Light': default: return `url(${LightNoise.toString()});`; } }}; border: ${({ variant, theme }) => { switch (variant) { - case 'dark': + case 'Dark': return `1px solid ${theme.grayScale.gray70};`; - case 'light': + case 'Light': default: return `1px solid ${theme.grayScale.gray20};`; } @@ -51,18 +51,18 @@ const StyledColorSchemeContent = styled(motion.div)< >` background: ${({ theme, variant }) => { switch (variant) { - case 'dark': + case 'Dark': return theme.grayScale.gray75; - case 'light': + case 'Light': return theme.grayScale.gray0; } }}; border-left: ${({ variant, theme }) => { switch (variant) { - case 'dark': + case 'Dark': return `1px solid ${theme.grayScale.gray60};`; - case 'light': + case 'Light': default: return `1px solid ${theme.grayScale.gray20};`; } @@ -70,9 +70,9 @@ const StyledColorSchemeContent = styled(motion.div)< border-radius: ${({ theme }) => theme.border.radius.md} 0px 0px 0px; border-top: ${({ variant, theme }) => { switch (variant) { - case 'dark': + case 'Dark': return `1px solid ${theme.grayScale.gray60};`; - case 'light': + case 'Light': default: return `1px solid ${theme.grayScale.gray20};`; } @@ -80,9 +80,9 @@ const StyledColorSchemeContent = styled(motion.div)< box-sizing: border-box; color: ${({ variant, theme }) => { switch (variant) { - case 'dark': + case 'Dark': return theme.grayScale.gray30; - case 'light': + case 'Light': default: return theme.grayScale.gray60; } @@ -96,7 +96,7 @@ const StyledColorSchemeContent = styled(motion.div)< `; export type ColorSchemeSegmentProps = { - variant: `${Lowercase}`; + variant: ColorScheme; controls: AnimationControls; } & React.ComponentPropsWithoutRef<'div'>; @@ -139,7 +139,7 @@ const StyledCheckmarkContainer = styled(motion.div)` `; export type ColorSchemeCardProps = { - variant: `${Lowercase}`; + variant: ColorScheme; selected?: boolean; } & React.ComponentPropsWithoutRef<'div'>; @@ -172,7 +172,7 @@ export const ColorSchemeCard = ({ }); }; - if (variant === 'system') { + if (variant === 'System') { return ( diff --git a/front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx b/front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx index 4a49887ac..e1d14de01 100644 --- a/front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx +++ b/front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx @@ -38,7 +38,7 @@ export const ColorSchemePicker = ({ onChange('Light')} - variant="light" + variant="Light" selected={value === 'Light'} /> Light @@ -46,7 +46,7 @@ export const ColorSchemePicker = ({ onChange('Dark')} - variant="dark" + variant="Dark" selected={value === 'Dark'} /> Dark @@ -54,7 +54,7 @@ export const ColorSchemePicker = ({ onChange('System')} - variant="system" + variant="System" selected={value === 'System'} /> System settings diff --git a/front/src/modules/ui/input/color-scheme/components/__stories__/ColorSchemeCard.stories.tsx b/front/src/modules/ui/input/color-scheme/components/__stories__/ColorSchemeCard.stories.tsx index 711b6f13e..77d4e1469 100644 --- a/front/src/modules/ui/input/color-scheme/components/__stories__/ColorSchemeCard.stories.tsx +++ b/front/src/modules/ui/input/color-scheme/components/__stories__/ColorSchemeCard.stories.tsx @@ -36,9 +36,9 @@ type Story = StoryObj; export const Default: Story = { render: (args) => ( <> - - - + + + ), }; diff --git a/front/src/modules/ui/input/relation-picker/components/__stories__/SingleEntitySelect.stories.tsx b/front/src/modules/ui/input/relation-picker/components/__stories__/SingleEntitySelect.stories.tsx index 597bb7180..a3cdb3da9 100644 --- a/front/src/modules/ui/input/relation-picker/components/__stories__/SingleEntitySelect.stories.tsx +++ b/front/src/modules/ui/input/relation-picker/components/__stories__/SingleEntitySelect.stories.tsx @@ -17,7 +17,7 @@ import { SingleEntitySelect } from '../SingleEntitySelect'; const entities = mockedPeopleData.map((person) => ({ id: person.id, entityType: Entity.Person, - name: person.displayName, + name: person.name.firstName + ' ' + person.name.lastName, originalEntity: person, })); diff --git a/front/src/modules/ui/input/relation-picker/types/EntityTypeForSelect.ts b/front/src/modules/ui/input/relation-picker/types/EntityTypeForSelect.ts index 2f063042b..f0cefc03f 100644 --- a/front/src/modules/ui/input/relation-picker/types/EntityTypeForSelect.ts +++ b/front/src/modules/ui/input/relation-picker/types/EntityTypeForSelect.ts @@ -1,5 +1,4 @@ import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargetableEntity'; -import { PipelineProgressableType } from '~/generated/graphql'; export enum Entity { Company = 'Company', @@ -8,7 +7,4 @@ export enum Entity { WorkspaceMember = 'WorkspaceMember', } -export type EntityTypeForSelect = - | ActivityTargetableEntityType - | PipelineProgressableType - | Entity; +export type EntityTypeForSelect = ActivityTargetableEntityType | Entity; diff --git a/front/src/modules/ui/layout/board/components/BoardColumnMenu.tsx b/front/src/modules/ui/layout/board/components/BoardColumnMenu.tsx index 4738b84d7..741391b4a 100644 --- a/front/src/modules/ui/layout/board/components/BoardColumnMenu.tsx +++ b/front/src/modules/ui/layout/board/components/BoardColumnMenu.tsx @@ -2,7 +2,6 @@ import { useCallback, useContext, useRef, useState } from 'react'; import styled from '@emotion/styled'; import { Key } from 'ts-key-enum'; -import { useCreateCompanyProgress } from '@/companies/hooks/useCreateCompanyProgress'; import { useFilteredSearchCompanyQuery } from '@/companies/hooks/useFilteredSearchCompanyQuery'; import { IconArrowLeft, @@ -57,7 +56,6 @@ export const BoardColumnMenu = ({ const boardColumnMenuRef = useRef(null); const { enqueueSnackBar } = useSnackBar(); - const createCompanyProgress = useCreateCompanyProgress(); const { handleMoveBoardColumn } = useBoardColumns(); const handleCompanySelected = ( @@ -75,7 +73,7 @@ export const BoardColumnMenu = ({ return; } - createCompanyProgress(selectedCompany.id, stageId); + //createCompanyProgress(selectedCompany.id, stageId); closeMenu(); }; diff --git a/front/src/modules/ui/layout/board/components/EntityBoard.tsx b/front/src/modules/ui/layout/board/components/EntityBoard.tsx index 6f10c4f55..f786d5e86 100644 --- a/front/src/modules/ui/layout/board/components/EntityBoard.tsx +++ b/front/src/modules/ui/layout/board/components/EntityBoard.tsx @@ -14,7 +14,6 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutsideByClassName } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import { PipelineProgress, PipelineStage } from '~/generated/graphql'; import { logError } from '~/utils/logError'; import { useCurrentCardSelected } from '../hooks/useCurrentCardSelected'; @@ -58,7 +57,7 @@ export const EntityBoard = ({ const { updateOneObject: updateOneOpportunity } = useUpdateOneObjectRecord({ - objectNameSingular: 'opportunityV2', + objectNameSingular: 'opportunity', }); const apolloClient = useApolloClient(); @@ -66,10 +65,7 @@ export const EntityBoard = ({ const { unselectAllActiveCards } = useCurrentCardSelected(); const updatePipelineProgressStageInDB = useCallback( - async ( - pipelineProgressId: NonNullable, - pipelineStageId: NonNullable, - ) => { + async (pipelineProgressId: string, pipelineStageId: string) => { await updateOneOpportunity?.({ idToUpdate: pipelineProgressId, input: { diff --git a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts index dc970fd36..458a9967e 100644 --- a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts +++ b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts @@ -14,7 +14,7 @@ export const useBoardColumns = () => { const { updateOneObject: updateOnePipelineStep } = useUpdateOneObjectRecord({ - objectNameSingular: 'pipelineStepV2', + objectNameSingular: 'pipelineStep', }); const updatedPipelineStages = (stages: BoardColumnDefinition[]) => { diff --git a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts index 0aaaab23d..a0db15049 100644 --- a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts +++ b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts @@ -14,7 +14,7 @@ export const useDeleteSelectedBoardCards = () => { const { deleteOneObject: deleteOneOpportunity } = useDeleteOneObjectRecord({ - objectNameSingular: 'opportunityV2', + objectNameSingular: 'opportunity', }); const deleteSelectedBoardCards = useRecoilCallback( diff --git a/front/src/modules/ui/layout/board/types/BoardOptions.ts b/front/src/modules/ui/layout/board/types/BoardOptions.ts index 13f7c869a..fe137f70b 100644 --- a/front/src/modules/ui/layout/board/types/BoardOptions.ts +++ b/front/src/modules/ui/layout/board/types/BoardOptions.ts @@ -1,12 +1,12 @@ import { ComponentType } from 'react'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { FilterDefinitionByEntity } from '@/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity'; import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefinition'; -import { PipelineProgress } from '~/generated/graphql'; export type BoardOptions = { newCardComponent: React.ReactNode; CardComponent: ComponentType; - filterDefinitions: FilterDefinitionByEntity[]; + filterDefinitions: FilterDefinitionByEntity[]; sortDefinitions: SortDefinition[]; }; diff --git a/front/src/modules/ui/layout/page/DefaultLayout.tsx b/front/src/modules/ui/layout/page/DefaultLayout.tsx index ba512eeaf..b24268fac 100644 --- a/front/src/modules/ui/layout/page/DefaultLayout.tsx +++ b/front/src/modules/ui/layout/page/DefaultLayout.tsx @@ -55,7 +55,6 @@ type DefaultLayoutProps = { export const DefaultLayout = ({ children }: DefaultLayoutProps) => { const onboardingStatus = useOnboardingStatus(); - return ( diff --git a/front/src/modules/ui/layout/show-page/components/ShowPageAddButton.tsx b/front/src/modules/ui/layout/show-page/components/ShowPageAddButton.tsx index 280439965..47344a771 100644 --- a/front/src/modules/ui/layout/show-page/components/ShowPageAddButton.tsx +++ b/front/src/modules/ui/layout/show-page/components/ShowPageAddButton.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; +import { ActivityType } from '@/activities/types/Activity'; import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { IconCheckbox, IconNotes, IconPlus } from '@/ui/display/icon/index'; @@ -8,7 +9,6 @@ import { IconButton } from '@/ui/input/button/components/IconButton'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; -import { ActivityType } from '~/generated/graphql'; import { Dropdown } from '../../dropdown/components/Dropdown'; import { DropdownMenu } from '../../dropdown/components/DropdownMenu'; @@ -51,13 +51,13 @@ export const ShowPageAddButton = ({ handleSelect(ActivityType.Note)} + onClick={() => handleSelect('Note')} accent="default" LeftIcon={IconNotes} text="Note" /> handleSelect(ActivityType.Task)} + onClick={() => handleSelect('Task')} accent="default" LeftIcon={IconCheckbox} text="Task" diff --git a/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx b/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx index a63bbc14d..772c03395 100644 --- a/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx +++ b/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx @@ -2,8 +2,6 @@ import { MemoryRouter } from 'react-router-dom'; import { Meta, StoryObj } from '@storybook/react'; import { useSetRecoilState } from 'recoil'; -import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries'; -import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode'; import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; @@ -11,8 +9,6 @@ import { actionBarOpenState } from '../../states/actionBarIsOpenState'; import { ActionBar } from '../ActionBar'; const FilledActionBar = (props: { selectedIds: string[] }) => { - const { setActionBarEntries } = useCompanyTableContextMenuEntries(); - setActionBarEntries(); const setActionBarOpenState = useSetRecoilState(actionBarOpenState); setActionBarOpenState(true); return ; @@ -26,10 +22,8 @@ const meta: Meta = { {}} - onEntityCountChange={() => {}} > - diff --git a/front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx b/front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx index 9e64b94b7..38d6b8cb2 100644 --- a/front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx +++ b/front/src/modules/ui/navigation/context-menu/components/__stories__/ContextMenu.stories.tsx @@ -2,8 +2,6 @@ import { MemoryRouter } from 'react-router-dom'; import { Meta, StoryObj } from '@storybook/react'; import { useSetRecoilState } from 'recoil'; -import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries'; -import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode'; import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; @@ -12,8 +10,6 @@ import { contextMenuPositionState } from '../../states/contextMenuPositionState' import { ContextMenu } from '../ContextMenu'; const FilledContextMenu = (props: { selectedIds: string[] }) => { - const { setContextMenuEntries } = useCompanyTableContextMenuEntries(); - setContextMenuEntries(); const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); setContextMenuPosition({ x: 100, @@ -32,10 +28,8 @@ const meta: Meta = { {}} - onEntityCountChange={() => {}} > - diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx index cf05e8a53..7d57508d6 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx @@ -30,6 +30,7 @@ const meta: Meta = { fieldMetadataId: 'date', label: 'Date', type: 'DATE', + iconName: 'IconCalendarEvent', metadata: { fieldName: 'Date', }, diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx index 76fa24092..966c23979 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx @@ -29,6 +29,7 @@ const meta: Meta = { fieldMetadataId: 'email', label: 'Email', type: 'EMAIL', + iconName: 'IconLink', metadata: { fieldName: 'Email', placeHolder: 'Email', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EnumFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EnumFieldDisplay.stories.tsx index 79fe1496b..60f8bc45f 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EnumFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EnumFieldDisplay.stories.tsx @@ -28,6 +28,7 @@ const meta: Meta = { fieldDefinition: { fieldMetadataId: 'enum', label: 'Enum', + iconName: 'IconTag', type: 'ENUM', metadata: { fieldName: 'Enum', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx index 2028056a6..5ee1a05c6 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx @@ -28,6 +28,7 @@ const meta: Meta = { fieldMetadataId: 'money', label: 'Money', type: 'MONEY_AMOUNT', + iconName: 'Icon123', metadata: { fieldName: 'Amount', placeHolder: 'Amount', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx index 456096f63..c22ba699f 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx @@ -28,6 +28,7 @@ const meta: Meta = { fieldMetadataId: 'number', label: 'Number', type: 'NUMBER', + iconName: 'Icon123', metadata: { fieldName: 'Number', placeHolder: 'Number', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx index dfd48f2b9..0d34b9355 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx @@ -29,6 +29,7 @@ const meta: Meta = { fieldMetadataId: 'phone', label: 'Phone', type: 'PHONE', + iconName: 'IconPhone', metadata: { fieldName: 'Phone', placeHolder: 'Phone', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx index 9434539af..665937184 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx @@ -28,6 +28,7 @@ const meta: Meta = { fieldMetadataId: 'text', label: 'Text', type: 'TEXT', + iconName: 'IconLink', metadata: { fieldName: 'Text', placeHolder: 'Text', diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx index aaee99662..c00d54696 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx @@ -29,6 +29,7 @@ const meta: Meta = { fieldMetadataId: 'URL', label: 'URL', type: 'URL', + iconName: 'IconLink', metadata: { fieldName: 'URL', placeHolder: 'URL', diff --git a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx index dff16905a..6047218f3 100644 --- a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx +++ b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx @@ -4,7 +4,7 @@ import styled from '@emotion/styled'; import { CompanyPicker } from '@/companies/components/CompanyPicker'; import { PeoplePicker } from '@/people/components/PeoplePicker'; import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; -import { UserPicker } from '@/users/components/UserPicker'; +import { WorkspaceMemberPicker } from '@/workspace-member/components/WorkspaceMemberPicker'; import { usePersistField } from '../../../hooks/usePersistField'; import { useRelationField } from '../../hooks/useRelationField'; @@ -48,7 +48,7 @@ export const RelationFieldInput = ({ initialSearchFilter={initialSearchValue} /> ) : fieldDefinition.metadata.fieldName === 'accountOwner' ? ( - = { fieldMetadataId: string; label: string; - Icon?: IconComponent; + iconName: string; type: FieldType; metadata: T; basePathToShowPage?: string; diff --git a/front/src/modules/ui/object/field/types/FieldType.ts b/front/src/modules/ui/object/field/types/FieldType.ts index 4ddcece85..77341cb71 100644 --- a/front/src/modules/ui/object/field/types/FieldType.ts +++ b/front/src/modules/ui/object/field/types/FieldType.ts @@ -9,7 +9,7 @@ export type FieldType = | 'DOUBLE_TEXT' | 'EMAIL' | 'ENUM' - | 'MONEY_AMOUNT_V2' + | 'MONEY_AMOUNT_' | 'MONEY_AMOUNT' | 'MONEY' | 'NUMBER' diff --git a/front/src/modules/ui/object/field/types/guards/isFieldBoolean.ts b/front/src/modules/ui/object/field/types/guards/isFieldBoolean.ts index 55a82da56..d0c2a09d7 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldBoolean.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldBoolean.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldBooleanMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldBoolean = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'BOOLEAN'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldChip.ts b/front/src/modules/ui/object/field/types/guards/isFieldChip.ts index 1ed7d631a..e3082a793 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldChip.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldChip.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldChipMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldChip = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'CHIP'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts b/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts index dbf58bc96..1cba9a169 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldCurrency = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'CURRENCY'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldDate.ts b/front/src/modules/ui/object/field/types/guards/isFieldDate.ts index f6e077451..513d41256 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldDate.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldDate.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldDateMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldDate = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'DATE'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldDoubleText.ts b/front/src/modules/ui/object/field/types/guards/isFieldDoubleText.ts index ed999cbb1..55b41b834 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldDoubleText.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldDoubleText.ts @@ -2,6 +2,6 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldDoubleTextMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldDoubleText = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'DOUBLE_TEXT'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldDoubleTextChip.ts b/front/src/modules/ui/object/field/types/guards/isFieldDoubleTextChip.ts index 591274597..cdd9e5f7e 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldDoubleTextChip.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldDoubleTextChip.ts @@ -2,6 +2,6 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldDoubleTextChipMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldDoubleTextChip = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'DOUBLE_TEXT_CHIP'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldEmail.ts b/front/src/modules/ui/object/field/types/guards/isFieldEmail.ts index eb9d79555..bd5f5e4c1 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldEmail.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldEmail.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldEmailMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldEmail = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'EMAIL'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldEnum.ts b/front/src/modules/ui/object/field/types/guards/isFieldEnum.ts index 69f337a68..25a6f3950 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldEnum.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldEnum.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldEnumMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldEnum = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'ENUM'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldFullName.ts b/front/src/modules/ui/object/field/types/guards/isFieldFullName.ts index 6455090aa..d94e08138 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldFullName.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldFullName.ts @@ -2,6 +2,6 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldFullName = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'FULL_NAME'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldLink.ts b/front/src/modules/ui/object/field/types/guards/isFieldLink.ts index b32c898cb..0c957c004 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldLink.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldLink.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldLinkMetadata, FieldMetadata } from '../FieldMetadata'; export const isFieldLink = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'LINK'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldMoney.ts b/front/src/modules/ui/object/field/types/guards/isFieldMoney.ts index 18a0fab15..3131b9db0 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldMoney.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldMoney.ts @@ -2,6 +2,6 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldMoneyMetadata } from '../FieldMetadata'; export const isFieldMoney = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'MONEY_AMOUNT'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldNumber.ts b/front/src/modules/ui/object/field/types/guards/isFieldNumber.ts index 4555b0e06..b4b5c7b8d 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldNumber.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldNumber.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldNumberMetadata } from '../FieldMetadata'; export const isFieldNumber = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'NUMBER'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldPhone.ts b/front/src/modules/ui/object/field/types/guards/isFieldPhone.ts index b96e25c4d..a00e432cb 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldPhone.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldPhone.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldPhoneMetadata } from '../FieldMetadata'; export const isFieldPhone = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'PHONE'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldProbability.ts b/front/src/modules/ui/object/field/types/guards/isFieldProbability.ts index 404d5b791..49d1eeb19 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldProbability.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldProbability.ts @@ -2,6 +2,6 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldProbabilityMetadata } from '../FieldMetadata'; export const isFieldProbability = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'PROBABILITY'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldRelation.ts b/front/src/modules/ui/object/field/types/guards/isFieldRelation.ts index af277da43..2927569c3 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldRelation.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldRelation.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldRelationMetadata } from '../FieldMetadata'; export const isFieldRelation = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'RELATION'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldText.ts b/front/src/modules/ui/object/field/types/guards/isFieldText.ts index c8094a085..7c1b5eee1 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldText.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldText.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldTextMetadata } from '../FieldMetadata'; export const isFieldText = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'TEXT'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldURL.ts b/front/src/modules/ui/object/field/types/guards/isFieldURL.ts index 195c7f0a7..548ea2b24 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldURL.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldURL.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldURLMetadata } from '../FieldMetadata'; export const isFieldURL = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'URL'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts b/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts index b70efe0ea..84f83e2b1 100644 --- a/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts +++ b/front/src/modules/ui/object/field/types/guards/isFieldUuid.ts @@ -2,5 +2,5 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldUuidMetadata } from '../FieldMetadata'; export const isFieldUuid = ( - field: FieldDefinition, + field: Pick, 'type'>, ): field is FieldDefinition => field.type === 'UUID'; diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index 541d41c76..91ad36b8e 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -1,3 +1,4 @@ +import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; @@ -14,6 +15,8 @@ export const ObjectFilterDropdownFilterSelect = () => { availableFilterDefinitions, } = useFilter(); + const { icons } = useLazyLoadIcons(); + const setHotkeyScope = useSetHotkeyScope(); return ( @@ -35,7 +38,7 @@ export const ObjectFilterDropdownFilterSelect = () => { setObjectFilterDropdownSearchInput(''); }} - LeftIcon={availableFilterDefinition.Icon} + LeftIcon={icons[availableFilterDefinition.iconName]} text={availableFilterDefinition.label} /> ))} diff --git a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts index 6968c509e..d2dedea78 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts @@ -5,7 +5,7 @@ import { FilterType } from './FilterType'; export type FilterDefinition = { fieldMetadataId: string; label: string; - Icon: IconComponent; + iconName: string; type: FilterType; entitySelectComponent?: JSX.Element; selectAllLabel?: string; diff --git a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts deleted file mode 100644 index c0a9e6662..000000000 --- a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; -import { QueryMode } from '~/generated/graphql'; - -import { Filter } from '../types/Filter'; - -type FilterToTurnIntoWhereClause = Omit & { - definition: { - type: Filter['definition']['type']; - }; -}; - -export const turnFilterIntoWhereClause = ( - filter: FilterToTurnIntoWhereClause | undefined, -) => { - if (!filter) { - return {}; - } - switch (filter.operand) { - case ViewFilterOperand.IsNotNull: - return { - [filter.fieldMetadataId]: { - not: null, - }, - }; - default: - switch (filter.definition.type) { - case 'TEXT': - switch (filter.operand) { - case ViewFilterOperand.Contains: - return { - [filter.fieldMetadataId]: { - contains: filter.value, - mode: QueryMode.Insensitive, - }, - }; - case ViewFilterOperand.DoesNotContain: - return { - [filter.fieldMetadataId]: { - not: { - contains: filter.value, - mode: QueryMode.Insensitive, - }, - }, - }; - default: - throw new Error( - `Unknown operand ${filter.operand} for ${filter.definition.type} filter`, - ); - } - case 'NUMBER': - switch (filter.operand) { - case ViewFilterOperand.GreaterThan: - return { - [filter.fieldMetadataId]: { - gte: parseFloat(filter.value), - }, - }; - case ViewFilterOperand.LessThan: - return { - [filter.fieldMetadataId]: { - lte: parseFloat(filter.value), - }, - }; - default: - throw new Error( - `Unknown operand ${filter.operand} for ${filter.definition.type} filter`, - ); - } - case 'DATE': - switch (filter.operand) { - case ViewFilterOperand.GreaterThan: - return { - [filter.fieldMetadataId]: { - gte: filter.value, - }, - }; - case ViewFilterOperand.LessThan: - return { - [filter.fieldMetadataId]: { - lte: filter.value, - }, - }; - default: - throw new Error( - `Unknown operand ${filter.operand} for ${filter.definition.type} filter`, - ); - } - case 'ENTITY': - switch (filter.operand) { - case ViewFilterOperand.Is: - return { - [filter.fieldMetadataId]: { - equals: filter.value, - }, - }; - case ViewFilterOperand.IsNot: - return { - [filter.fieldMetadataId]: { - not: { equals: filter.value }, - }, - }; - default: - throw new Error( - `Unknown operand ${filter.operand} for ${filter.definition.type} filter`, - ); - } - default: - throw new Error('Unknown filter type'); - } - } -}; diff --git a/front/src/modules/ui/object/object-sort-dropdown/types/interface.ts b/front/src/modules/ui/object/object-sort-dropdown/types/interface.ts deleted file mode 100644 index 25345239d..000000000 --- a/front/src/modules/ui/object/object-sort-dropdown/types/interface.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { IconComponent } from '@/ui/display/icon/types/IconComponent'; -import { SortOrder as Order_By } from '~/generated/graphql'; - -export type SortType = { - label: string; - key: string; - Icon?: IconComponent; - orderByTemplate?: (order: Order_By) => OrderByTemplate[]; -}; - -export type SelectedSortType = SortType & { - order: 'asc' | 'desc'; -}; diff --git a/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts b/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts deleted file mode 100644 index e5bc4a085..000000000 --- a/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SortOrder as Order_By } from '~/generated/graphql'; - -import { Sort } from '../types/Sort'; - -export const reduceSortsToOrderBy = (sorts: Sort[]): any[] => - sorts - .map((sort) => { - const direction = sort.direction === 'asc' ? Order_By.Asc : Order_By.Desc; - - if (sort.definition.getOrderByTemplate) { - return sort.definition.getOrderByTemplate(direction); - } else { - return [{ [sort.definition.fieldMetadataId]: direction }]; - } - }) - .flat(); diff --git a/front/src/modules/ui/object/record-inline-cell/components/RecordInlineCell.tsx b/front/src/modules/ui/object/record-inline-cell/components/RecordInlineCell.tsx index 0a3c667f9..8699d595d 100644 --- a/front/src/modules/ui/object/record-inline-cell/components/RecordInlineCell.tsx +++ b/front/src/modules/ui/object/record-inline-cell/components/RecordInlineCell.tsx @@ -1,5 +1,6 @@ import { useContext } from 'react'; +import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { FieldDisplay } from '../../field/components/FieldDisplay'; @@ -58,6 +59,8 @@ export const RecordInlineCell = () => { closeInlineCell(); }; + const { icons } = useLazyLoadIcons(); + return ( { } : undefined } - IconLabel={fieldDefinition.Icon} + IconLabel={icons[fieldDefinition.iconName]} editModeContent={ { const theme = useTheme(); + const { icons, isLoadingIcons } = useLazyLoadIcons(); + const Icon = icons[column.iconName]; + return ( <> - {column.Icon && } + {!isLoadingIcons && } {column.label} diff --git a/front/src/modules/ui/object/record-table/components/RecordTableBodyV1.tsx b/front/src/modules/ui/object/record-table/components/RecordTableBodyV1.tsx deleted file mode 100644 index 95d4664cc..000000000 --- a/front/src/modules/ui/object/record-table/components/RecordTableBodyV1.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useRecoilValue } from 'recoil'; - -import { RowIdContext } from '../contexts/RowIdContext'; -import { RowIndexContext } from '../contexts/RowIndexContext'; -import { isFetchingRecordTableDataState } from '../states/isFetchingRecordTableDataState'; -import { tableRowIdsState } from '../states/tableRowIdsState'; - -import { RecordTableRow } from './RecordTableRow'; - -export const RecordTableBodyV1 = () => { - const tableRowIds = useRecoilValue(tableRowIdsState); - - const isFetchingRecordTableData = useRecoilValue( - isFetchingRecordTableDataState, - ); - - if (isFetchingRecordTableData) { - return <>; - } - - return ( - - {tableRowIds.map((rowId, rowIndex) => ( - - - - - - ))} - - ); -}; diff --git a/front/src/modules/ui/object/record-table/components/RecordTableEffect.tsx b/front/src/modules/ui/object/record-table/components/RecordTableEffect.tsx deleted file mode 100644 index d3f84c94d..000000000 --- a/front/src/modules/ui/object/record-table/components/RecordTableEffect.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { useEffect } from 'react'; -import { useSearchParams } from 'react-router-dom'; -import defaults from 'lodash/defaults'; -import { useRecoilValue } from 'recoil'; - -import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect'; -import { OptimisticEffectDefinition } from '@/apollo/optimistic-effect/types/OptimisticEffectDefinition'; -import { - SortOrder, - useGetCompaniesQuery, - useGetPeopleQuery, -} from '~/generated/graphql'; - -import { FilterDefinition } from '../../object-filter-dropdown/types/FilterDefinition'; -import { SortDefinition } from '../../object-sort-dropdown/types/SortDefinition'; -import { useRecordTableScopedStates } from '../hooks/internal/useRecordTableScopedStates'; -import { useRecordTable } from '../hooks/useRecordTable'; - -export const RecordTableEffect = ({ - useGetRequest, - getRequestResultKey, - getRequestOptimisticEffectDefinition, - - setActionBarEntries, - setContextMenuEntries, -}: { - useGetRequest: typeof useGetCompaniesQuery | typeof useGetPeopleQuery; - getRequestResultKey: string; - getRequestOptimisticEffectDefinition: OptimisticEffectDefinition; - filterDefinitionArray: FilterDefinition[]; - sortDefinitionArray: SortDefinition[]; - setActionBarEntries?: () => void; - setContextMenuEntries?: () => void; -}) => { - const { setRecordTableData } = useRecordTable(); - const { tableSortsOrderBySelector, tableFiltersWhereSelector } = - useRecordTableScopedStates(); - - const { registerOptimisticEffect } = useOptimisticEffect({ - objectNameSingular: 'companyV2', - }); - - const tableSortsOrderBy = useRecoilValue(tableSortsOrderBySelector); - const sortsOrderBy = defaults(tableSortsOrderBy, [ - { - createdAt: SortOrder.Desc, - }, - ]); - const tableFiltersWhere = useRecoilValue(tableFiltersWhereSelector); - - useGetRequest({ - variables: { orderBy: sortsOrderBy, where: tableFiltersWhere }, - onCompleted: (data: any) => { - const entities = data[getRequestResultKey] ?? []; - - setRecordTableData(entities); - - registerOptimisticEffect({ - variables: { orderBy: sortsOrderBy, where: tableFiltersWhere }, - definition: getRequestOptimisticEffectDefinition, - }); - }, - }); - - const [searchParams] = useSearchParams(); - - useEffect(() => { - setActionBarEntries?.(); - setContextMenuEntries?.(); - }, [searchParams, setActionBarEntries, setContextMenuEntries]); - - return <>; -}; diff --git a/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx b/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx index 2be385f24..d47f6fd9e 100644 --- a/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx +++ b/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx @@ -2,6 +2,7 @@ import { useCallback } from 'react'; import { useRecoilValue } from 'recoil'; import { IconPlus } from '@/ui/display/icon'; +import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; @@ -18,6 +19,8 @@ export const RecordTableHeaderPlusButtonContent = () => { const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector); + const { icons } = useLazyLoadIcons(); + const { handleColumnVisibilityChange } = useTableColumns(); const handleAddColumn = useCallback( @@ -39,7 +42,7 @@ export const RecordTableHeaderPlusButtonContent = () => { onClick: () => handleAddColumn(column), }, ]} - LeftIcon={column.Icon} + LeftIcon={icons[column.iconName]} text={column.label} /> ))} diff --git a/front/src/modules/ui/object/record-table/components/RecordTableV1.tsx b/front/src/modules/ui/object/record-table/components/RecordTableV1.tsx deleted file mode 100644 index f6c740245..000000000 --- a/front/src/modules/ui/object/record-table/components/RecordTableV1.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { useRef } from 'react'; -import styled from '@emotion/styled'; - -import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; -import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { - useListenClickOutside, - useListenClickOutsideByClassName, -} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; - -import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext'; -import { useRecordTable } from '../hooks/useRecordTable'; -import { TableHotkeyScope } from '../types/TableHotkeyScope'; - -import { RecordTableBodyV1 } from './RecordTableBodyV1'; -import { RecordTableHeader } from './RecordTableHeader'; - -const StyledTable = styled.table` - border-collapse: collapse; - - border-radius: ${({ theme }) => theme.border.radius.sm}; - border-spacing: 0; - margin-left: ${({ theme }) => theme.table.horizontalCellMargin}; - margin-right: ${({ theme }) => theme.table.horizontalCellMargin}; - table-layout: fixed; - - width: calc(100% - ${({ theme }) => theme.table.horizontalCellMargin} * 2); - - th { - border: 1px solid ${({ theme }) => theme.border.color.light}; - border-collapse: collapse; - color: ${({ theme }) => theme.font.color.tertiary}; - padding: 0; - text-align: left; - - :last-child { - border-right-color: transparent; - } - :first-of-type { - border-left-color: transparent; - border-right-color: transparent; - } - :last-of-type { - width: 100%; - } - } - - td { - border: 1px solid ${({ theme }) => theme.border.color.light}; - border-collapse: collapse; - color: ${({ theme }) => theme.font.color.primary}; - padding: 0; - - text-align: left; - - :last-child { - border-right-color: transparent; - } - :first-of-type { - border-left-color: transparent; - border-right-color: transparent; - } - } -`; - -const StyledTableWithHeader = styled.div` - display: flex; - flex: 1; - flex-direction: column; - width: 100%; -`; - -const StyledTableContainer = styled.div` - display: flex; - flex-direction: column; - height: 100%; - overflow: auto; - position: relative; -`; - -type RecordTableV1Props = { - updateEntityMutation: (params: any) => void; -}; - -export const RecordTableV1 = ({ updateEntityMutation }: RecordTableV1Props) => { - const tableBodyRef = useRef(null); - - const { - leaveTableFocus, - setRowSelectedState, - resetTableRowSelection, - useMapKeyboardToSoftFocus, - getIsSomeCellInEditMode, - } = useRecordTable(); - - useMapKeyboardToSoftFocus(); - - useListenClickOutside({ - refs: [tableBodyRef], - callback: () => { - leaveTableFocus(); - }, - }); - - useScopedHotkeys( - 'escape', - () => { - resetTableRowSelection(); - }, - TableHotkeyScope.Table, - ); - - useListenClickOutsideByClassName({ - classNames: ['entity-table-cell'], - excludeClassNames: ['action-bar', 'context-menu'], - callback: () => { - resetTableRowSelection(); - }, - }); - - const handleMouseLeave = () => { - const isSomeCellInEditMode = getIsSomeCellInEditMode(); - if (isSomeCellInEditMode) return; - leaveTableFocus(); - }; - - return ( - - - -
- - - - - -
-
-
-
- ); -}; diff --git a/front/src/modules/ui/object/record-table/hooks/internal/useRecordTableScopedStates.ts b/front/src/modules/ui/object/record-table/hooks/internal/useRecordTableScopedStates.ts index 965d4967c..a7d71e21f 100644 --- a/front/src/modules/ui/object/record-table/hooks/internal/useRecordTableScopedStates.ts +++ b/front/src/modules/ui/object/record-table/hooks/internal/useRecordTableScopedStates.ts @@ -17,8 +17,6 @@ export const useRecordTableScopedStates = (args?: { availableTableColumnsState, tableFiltersState, tableSortsState, - tableSortsOrderBySelector, - tableFiltersWhereSelector, tableColumnsState, tableColumnsByKeySelector, hiddenTableColumnsSelector, @@ -34,8 +32,6 @@ export const useRecordTableScopedStates = (args?: { availableTableColumnsState, tableFiltersState, tableSortsState, - tableSortsOrderBySelector, - tableFiltersWhereSelector, tableColumnsState, tableColumnsByKeySelector, hiddenTableColumnsSelector, diff --git a/front/src/modules/ui/object/record-table/hooks/useRecordTable.ts b/front/src/modules/ui/object/record-table/hooks/useRecordTable.ts index af44c7128..ef1921bef 100644 --- a/front/src/modules/ui/object/record-table/hooks/useRecordTable.ts +++ b/front/src/modules/ui/object/record-table/hooks/useRecordTable.ts @@ -43,6 +43,7 @@ export const useRecordTable = (props?: useRecordTableProps) => { tableFiltersState, tableSortsState, tableColumnsState, + onEntityCountChangeState, } = useRecordTableScopedStates({ customRecordTableScopeId: scopeId, }); @@ -51,6 +52,7 @@ export const useRecordTable = (props?: useRecordTableProps) => { availableTableColumnsState, ); + const setOnEntityCountChange = useSetRecoilState(onEntityCountChangeState); const setTableFilters = useSetRecoilState(tableFiltersState); const setTableSorts = useSetRecoilState(tableSortsState); @@ -299,6 +301,7 @@ export const useRecordTable = (props?: useRecordTableProps) => { setAvailableTableColumns, setTableFilters, setTableSorts, + setOnEntityCountChange, setRecordTableData, setTableColumns, leaveTableFocus, diff --git a/front/src/modules/ui/object/record-table/scopes/RecordTableScope.tsx b/front/src/modules/ui/object/record-table/scopes/RecordTableScope.tsx index e17592bea..9bb0ce825 100644 --- a/front/src/modules/ui/object/record-table/scopes/RecordTableScope.tsx +++ b/front/src/modules/ui/object/record-table/scopes/RecordTableScope.tsx @@ -10,27 +10,21 @@ type RecordTableScopeProps = { children: ReactNode; recordTableScopeId: string; onColumnsChange: (columns: ColumnDefinition[]) => void; - onEntityCountChange: (entityCount: number) => void; }; export const RecordTableScope = ({ children, recordTableScopeId, onColumnsChange, - onEntityCountChange, }: RecordTableScopeProps) => { return ( - + {children} ); diff --git a/front/src/modules/ui/object/record-table/scopes/RecordTableScopeInitEffect.tsx b/front/src/modules/ui/object/record-table/scopes/RecordTableScopeInitEffect.tsx index 310691ff5..e7da03262 100644 --- a/front/src/modules/ui/object/record-table/scopes/RecordTableScopeInitEffect.tsx +++ b/front/src/modules/ui/object/record-table/scopes/RecordTableScopeInitEffect.tsx @@ -12,23 +12,14 @@ type RecordTableScopeInitEffectProps = { export const RecordTableScopeInitEffect = ({ onColumnsChange, - onEntityCountChange, }: RecordTableScopeInitEffectProps) => { - const { onColumnsChangeState, onEntityCountChangeState } = - useRecordTableScopedStates(); + const { onColumnsChangeState } = useRecordTableScopedStates(); - const setOnEntityCountChange = useSetRecoilState(onEntityCountChangeState); const setOnColumnsChange = useSetRecoilState(onColumnsChangeState); useEffect(() => { - setOnEntityCountChange(() => onEntityCountChange); setOnColumnsChange(() => onColumnsChange); - }, [ - onColumnsChange, - onEntityCountChange, - setOnColumnsChange, - setOnEntityCountChange, - ]); + }, [onColumnsChange, setOnColumnsChange]); return <>; }; diff --git a/front/src/modules/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts b/front/src/modules/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts index 1fab91ccf..98aa2501d 100644 --- a/front/src/modules/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts +++ b/front/src/modules/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts @@ -6,7 +6,6 @@ import { ColumnDefinition } from '../../types/ColumnDefinition'; type RecordTableScopeInternalContextProps = ScopedStateKey & { onColumnsChange: (columns: ColumnDefinition[]) => void; - onEntityCountChange: (entityCount: number) => void; }; export const RecordTableScopeInternalContext = diff --git a/front/src/modules/ui/object/record-table/states/selectors/tableSortsOrderByScopedSelector.ts b/front/src/modules/ui/object/record-table/states/selectors/tableSortsOrderByScopedSelector.ts deleted file mode 100644 index 3c866934b..000000000 --- a/front/src/modules/ui/object/record-table/states/selectors/tableSortsOrderByScopedSelector.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { reduceSortsToOrderBy } from '@/ui/object/object-sort-dropdown/utils/helpers'; -import { SortOrder } from '~/generated/graphql'; - -import { tableSortsScopedState } from '../tableSortsScopedState'; - -export const tableSortsOrderByScopedSelector = selectorFamily({ - key: 'tableSortsOrderByScopedSelector', - get: - (scopeId: string) => - ({ get }) => { - const orderBy = reduceSortsToOrderBy( - get(tableSortsScopedState({ scopeId })), - ); - return orderBy.length ? orderBy : [{ createdAt: SortOrder.Desc }]; - }, -}); diff --git a/front/src/modules/ui/object/record-table/states/selectors/tablefiltersWhereScopedSelector.ts b/front/src/modules/ui/object/record-table/states/selectors/tablefiltersWhereScopedSelector.ts deleted file mode 100644 index f013cb59b..000000000 --- a/front/src/modules/ui/object/record-table/states/selectors/tablefiltersWhereScopedSelector.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { turnFilterIntoWhereClause } from '../../../object-filter-dropdown/utils/turnFilterIntoWhereClause'; -import { tableFiltersScopedState } from '../tableFiltersScopedState'; - -export const tableFiltersWhereScopedSelector = selectorFamily({ - key: 'tablefiltersWhereScopedSelector', - get: - (scopeId: string) => - ({ get }) => ({ - AND: get(tableFiltersScopedState({ scopeId })).map( - turnFilterIntoWhereClause, - ), - }), -}); diff --git a/front/src/modules/ui/object/record-table/utils/getRecordTableScopedStates.ts b/front/src/modules/ui/object/record-table/utils/getRecordTableScopedStates.ts index c9b3cba6e..fcb716692 100644 --- a/front/src/modules/ui/object/record-table/utils/getRecordTableScopedStates.ts +++ b/front/src/modules/ui/object/record-table/utils/getRecordTableScopedStates.ts @@ -4,8 +4,6 @@ import { availableTableColumnsScopedState } from '../states/availableTableColumn import { onColumnsChangeScopedState } from '../states/onColumnsChangeScopedState'; import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector'; import { tableColumnsByKeyScopedSelector } from '../states/selectors/tableColumnsByKeyScopedSelector'; -import { tableFiltersWhereScopedSelector } from '../states/selectors/tablefiltersWhereScopedSelector'; -import { tableSortsOrderByScopedSelector } from '../states/selectors/tableSortsOrderByScopedSelector'; import { visibleTableColumnsScopedSelector } from '../states/selectors/visibleTableColumnsScopedSelector'; import { tableColumnsScopedState } from '../states/tableColumnsScopedState'; import { tableFiltersScopedState } from '../states/tableFiltersScopedState'; @@ -33,12 +31,6 @@ export const getRecordTableScopedStates = ({ recordTableScopeId, ); - const tableSortsOrderBySelector = - tableSortsOrderByScopedSelector(recordTableScopeId); - - const tableFiltersWhereSelector = - tableFiltersWhereScopedSelector(recordTableScopeId); - const tableColumnsState = getScopedState( tableColumnsScopedState, recordTableScopeId, @@ -67,8 +59,6 @@ export const getRecordTableScopedStates = ({ availableTableColumnsState, tableFiltersState, tableSortsState, - tableSortsOrderBySelector, - tableFiltersWhereSelector, tableColumnsState, tableColumnsByKeySelector, hiddenTableColumnsSelector, diff --git a/front/src/modules/ui/theme/components/AppThemeProvider.tsx b/front/src/modules/ui/theme/components/AppThemeProvider.tsx index 7a55ebb08..947825f9a 100644 --- a/front/src/modules/ui/theme/components/AppThemeProvider.tsx +++ b/front/src/modules/ui/theme/components/AppThemeProvider.tsx @@ -1,7 +1,6 @@ import { ThemeProvider } from '@emotion/react'; import { darkTheme, lightTheme } from '@/ui/theme/constants/theme'; -import { ColorScheme } from '~/generated/graphql'; import { useColorScheme } from '../hooks/useColorScheme'; import { useSystemColorScheme } from '../hooks/useSystemColorScheme'; @@ -10,20 +9,14 @@ type AppThemeProviderProps = { children: JSX.Element; }; -const themes = { - [ColorScheme.Dark]: darkTheme, - [ColorScheme.Light]: lightTheme, -}; - export const AppThemeProvider = ({ children }: AppThemeProviderProps) => { const systemColorScheme = useSystemColorScheme(); const { colorScheme } = useColorScheme(); - const theme = - themes[ - colorScheme === ColorScheme.System ? systemColorScheme : colorScheme - ]; + const computedColorScheme = + colorScheme === 'System' ? systemColorScheme : colorScheme; + const theme = computedColorScheme === 'Dark' ? darkTheme : lightTheme; return {children}; }; diff --git a/front/src/modules/ui/theme/hooks/useColorScheme.ts b/front/src/modules/ui/theme/hooks/useColorScheme.ts index 943cc5d87..a0f6def44 100644 --- a/front/src/modules/ui/theme/hooks/useColorScheme.ts +++ b/front/src/modules/ui/theme/hooks/useColorScheme.ts @@ -12,8 +12,9 @@ export const useColorScheme = () => { const { updateOneObject: updateOneWorkspaceMember } = useUpdateOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); + const colorScheme = currentWorkspaceMember?.colorScheme ?? 'System'; const setColorScheme = useCallback( diff --git a/front/src/modules/ui/theme/hooks/useSystemColorScheme.ts b/front/src/modules/ui/theme/hooks/useSystemColorScheme.ts index ce17cc4ad..ea9f02648 100644 --- a/front/src/modules/ui/theme/hooks/useSystemColorScheme.ts +++ b/front/src/modules/ui/theme/hooks/useSystemColorScheme.ts @@ -1,21 +1,16 @@ import { useEffect, useMemo, useState } from 'react'; -import { ColorScheme } from '~/generated/graphql'; +import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; -type SystemColorScheme = ColorScheme.Light | ColorScheme.Dark; - -export const useSystemColorScheme = (): SystemColorScheme => { +export const useSystemColorScheme = (): ColorScheme => { const mediaQuery = useMemo( () => window.matchMedia('(prefers-color-scheme: dark)'), [], ); - const [preferredColorScheme, setPreferredColorScheme] = - useState( - !window.matchMedia || !mediaQuery.matches - ? ColorScheme.Light - : ColorScheme.Dark, - ); + const [preferredColorScheme, setPreferredColorScheme] = useState( + !window.matchMedia || !mediaQuery.matches ? 'Light' : 'Dark', + ); useEffect(() => { if (!window.matchMedia) { @@ -23,9 +18,7 @@ export const useSystemColorScheme = (): SystemColorScheme => { } const handleChange = (event: MediaQueryListEvent): void => { - setPreferredColorScheme( - event.matches ? ColorScheme.Dark : ColorScheme.Light, - ); + setPreferredColorScheme(event.matches ? 'Dark' : 'Light'); }; mediaQuery.addEventListener('change', handleChange); diff --git a/front/src/modules/users/components/FilterDropdownUserSearchSelect.tsx b/front/src/modules/users/components/FilterDropdownUserSearchSelect.tsx index b334d142d..fdd577d4f 100644 --- a/front/src/modules/users/components/FilterDropdownUserSearchSelect.tsx +++ b/front/src/modules/users/components/FilterDropdownUserSearchSelect.tsx @@ -1,8 +1,10 @@ -import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; +import { useQuery } from '@apollo/client'; + +import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; +import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { ObjectFilterDropdownEntitySearchSelect } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect'; import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; -import { useSearchUserQuery } from '~/generated/graphql'; export const FilterDropdownUserSearchSelect = () => { const { @@ -10,31 +12,40 @@ export const FilterDropdownUserSearchSelect = () => { objectFilterDropdownSelectedEntityId, } = useFilter(); - const usersForSelect = useFilteredSearchEntityQuery({ - queryHook: useSearchUserQuery, + const { findManyQuery } = useFindOneObjectMetadataItem({ + objectNameSingular: 'workspaceMember', + }); + + const useFindManyWorkspaceMembers = (options: any) => + useQuery(findManyQuery, options); + + const workspaceMembers = useFilteredSearchEntityQueryV2({ + queryHook: useFindManyWorkspaceMembers, filters: [ { - fieldNames: ['firstName', 'lastName'], + fieldNames: ['name.firstName', 'name.lastName'], filter: objectFilterDropdownSearchInput, }, ], - orderByField: 'lastName', - mappingFunction: (user) => ({ - id: user.id, - entityType: Entity.User, - name: `${user.displayName}`, + orderByField: 'createdAt', + mappingFunction: (workspaceMember) => ({ + entityType: Entity.WorkspaceMember, + id: workspaceMember.id, + name: + workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName, avatarType: 'rounded', - avatarUrl: user.avatarUrl ?? '', - originalEntity: user, + avatarUrl: '', + originalEntity: workspaceMember, }), selectedIds: objectFilterDropdownSelectedEntityId ? [objectFilterDropdownSelectedEntityId] : [], + objectNamePlural: 'workspaceMembers', }); return ( ); }; diff --git a/front/src/modules/users/components/UserProvider.tsx b/front/src/modules/users/components/UserProvider.tsx index ed38cc221..cb31acb04 100644 --- a/front/src/modules/users/components/UserProvider.tsx +++ b/front/src/modules/users/components/UserProvider.tsx @@ -1,21 +1,14 @@ import { useEffect, useState } from 'react'; -import { useApolloClient } from '@apollo/client'; import { useSetRecoilState } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; 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'; +import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; +import { useGetCurrentUserQuery } from '~/generated/graphql'; export const UserProvider = ({ children }: React.PropsWithChildren) => { const [isLoading, setIsLoading] = useState(true); - const [isWorkspaceMemberLoading, setIsWorkspaceMemberLoading] = - useState(true); - const apolloClient = useApolloClient(); const setCurrentUser = useSetRecoilState(currentUserState); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); @@ -23,48 +16,28 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => { currentWorkspaceMemberState, ); - const { data: userData, loading: userLoading } = useGetCurrentUserQuery({ - onCompleted: async (data) => { - const workspaceMember = await apolloClient.query({ - query: FIND_ONE_WORKSPACE_MEMBER_V2, - variables: { - filter: { - userId: { eq: data.currentUser.id }, - }, - }, - }); - setCurrentWorkspaceMember( - workspaceMember.data.workspaceMembersV2.edges[0].node, - ); - setIsWorkspaceMemberLoading(false); - }, - onError: () => { - setIsWorkspaceMemberLoading(false); - }, - }); - - const { data: workspaceData, loading: workspaceLoading } = - useGetCurrentWorkspaceQuery(); + const { data: userData, loading: userLoading } = useGetCurrentUserQuery({}); useEffect(() => { - if (!userLoading && !workspaceLoading && !isWorkspaceMemberLoading) { + if (!userLoading) { setIsLoading(false); } - if (userData?.currentUser) { + if (userData?.currentUser?.workspaceMember) { setCurrentUser(userData.currentUser); - } - if (workspaceData?.currentWorkspace) { - setCurrentWorkspace(workspaceData.currentWorkspace); + setCurrentWorkspace(userData.currentUser.defaultWorkspace); + const workspaceMember = userData.currentUser.workspaceMember; + setCurrentWorkspaceMember({ + ...workspaceMember, + colorScheme: (workspaceMember.colorScheme as ColorScheme) ?? 'Light', + }); } }, [ setCurrentUser, isLoading, userLoading, - workspaceLoading, - userData?.currentUser, - workspaceData?.currentWorkspace, setCurrentWorkspace, - isWorkspaceMemberLoading, + setCurrentWorkspaceMember, + userData?.currentUser, ]); return isLoading ? <> : <>{children}; diff --git a/front/src/modules/users/graphql/fragments/userFieldsFragment.ts b/front/src/modules/users/graphql/fragments/userFieldsFragment.ts deleted file mode 100644 index 4a8f7db34..000000000 --- a/front/src/modules/users/graphql/fragments/userFieldsFragment.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { gql } from '@apollo/client'; - -export const USER_FIELDS_FRAGMENT = gql` - fragment userFieldsFragment on User { - id - email - displayName - firstName - lastName - } -`; diff --git a/front/src/modules/users/graphql/fragments/userQueryFragment.ts b/front/src/modules/users/graphql/fragments/userQueryFragment.ts new file mode 100644 index 000000000..5cbcc2a0c --- /dev/null +++ b/front/src/modules/users/graphql/fragments/userQueryFragment.ts @@ -0,0 +1,30 @@ +import { gql } from '@apollo/client'; + +export const USER_QUERY_FRAGMENT = gql` + fragment UserQueryFragment on User { + id + firstName + lastName + email + canImpersonate + supportUserHash + workspaceMember { + id + name { + firstName + lastName + } + colorScheme + avatarUrl + locale + allowImpersonation + } + defaultWorkspace { + id + displayName + logo + domainName + inviteHash + } + } +`; diff --git a/front/src/modules/users/graphql/mutations/deleteUserAccount.ts b/front/src/modules/users/graphql/mutations/deleteUserAccount.ts index feb1eedb7..9ed8df865 100644 --- a/front/src/modules/users/graphql/mutations/deleteUserAccount.ts +++ b/front/src/modules/users/graphql/mutations/deleteUserAccount.ts @@ -2,7 +2,7 @@ import { gql } from '@apollo/client'; export const DELETE_USER_ACCOUNT = gql` mutation DeleteUserAccount { - deleteUserAccount { + deleteUser { id } } diff --git a/front/src/modules/users/graphql/mutations/removeProfilePicture.ts b/front/src/modules/users/graphql/mutations/removeProfilePicture.ts deleted file mode 100644 index 906fd1d47..000000000 --- a/front/src/modules/users/graphql/mutations/removeProfilePicture.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const REMOVE_PROFILE_PICTURE = gql` - mutation RemoveProfilePicture($where: UserWhereUniqueInput!) { - updateUser(data: { avatarUrl: null }, where: $where) { - id - avatarUrl - } - } -`; diff --git a/front/src/modules/users/graphql/mutations/updateAllowImpersonation.ts b/front/src/modules/users/graphql/mutations/updateAllowImpersonation.ts deleted file mode 100644 index 62e06e7c8..000000000 --- a/front/src/modules/users/graphql/mutations/updateAllowImpersonation.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_ALLOW_IMPERSONATION = gql` - mutation UpdateAllowImpersonation($allowImpersonation: Boolean!) { - allowImpersonation(allowImpersonation: $allowImpersonation) { - id - allowImpersonation - } - } -`; diff --git a/front/src/modules/users/graphql/mutations/updateUser.ts b/front/src/modules/users/graphql/mutations/updateUser.ts deleted file mode 100644 index 8dfde4aac..000000000 --- a/front/src/modules/users/graphql/mutations/updateUser.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_USER = gql` - mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) { - updateUser(data: $data, where: $where) { - id - email - } - } -`; diff --git a/front/src/modules/users/graphql/mutations/updateProfilePicture.ts b/front/src/modules/users/graphql/mutations/uploadProfilePicture.ts similarity index 75% rename from front/src/modules/users/graphql/mutations/updateProfilePicture.ts rename to front/src/modules/users/graphql/mutations/uploadProfilePicture.ts index 573fb878c..711a1efc2 100644 --- a/front/src/modules/users/graphql/mutations/updateProfilePicture.ts +++ b/front/src/modules/users/graphql/mutations/uploadProfilePicture.ts @@ -1,6 +1,6 @@ import { gql } from '@apollo/client'; -export const UPDATE_PROFILE_PICTURE = gql` +export const UPLOAD_PROFILE_PICTURE = gql` mutation UploadProfilePicture($file: Upload!) { uploadProfilePicture(file: $file) } diff --git a/front/src/modules/users/graphql/queries/getCurrentUser.ts b/front/src/modules/users/graphql/queries/getCurrentUser.ts index 4e5efb9f6..a374d762b 100644 --- a/front/src/modules/users/graphql/queries/getCurrentUser.ts +++ b/front/src/modules/users/graphql/queries/getCurrentUser.ts @@ -3,9 +3,30 @@ import { gql } from '@apollo/client'; export const GET_CURRENT_USER = gql` query GetCurrentUser { currentUser { - ...userFieldsFragment + id + firstName + lastName + email canImpersonate supportUserHash + workspaceMember { + id + name { + firstName + lastName + } + colorScheme + avatarUrl + locale + allowImpersonation + } + defaultWorkspace { + id + displayName + logo + domainName + inviteHash + } } } `; diff --git a/front/src/modules/users/graphql/queries/getUsers.ts b/front/src/modules/users/graphql/queries/getUsers.ts deleted file mode 100644 index 8fcc6c7ca..000000000 --- a/front/src/modules/users/graphql/queries/getUsers.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_USERS = gql` - query GetUsers { - findManyUser { - ...userFieldsFragment - } - } -`; diff --git a/front/src/modules/views/components/ViewBarDetails.tsx b/front/src/modules/views/components/ViewBarDetails.tsx index a362e50f7..30a1791c3 100644 --- a/front/src/modules/views/components/ViewBarDetails.tsx +++ b/front/src/modules/views/components/ViewBarDetails.tsx @@ -3,6 +3,7 @@ import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; import { IconArrowDown, IconArrowUp } from '@/ui/display/icon/index'; +import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { AddObjectFilterFromDetailsButton } from '@/ui/object/object-filter-dropdown/components/AddObjectFilterFromDetailsButton'; import { getOperandLabelShort } from '@/ui/object/object-filter-dropdown/utils/getOperandLabel'; @@ -95,6 +96,7 @@ export const ViewBarDetails = ({ canPersistSortsSelector, isViewBarExpandedState, } = useViewScopedStates(); + const { icons } = useLazyLoadIcons(); const currentViewSorts = useRecoilValue(currentViewSortsState); const currentViewFilters = useRecoilValue(currentViewFiltersState); @@ -149,7 +151,7 @@ export const ViewBarDetails = ({ labelValue={`${getOperandLabelShort(filter.operand)} ${ filter.displayValue }`} - Icon={filter.definition.Icon} + Icon={icons[filter.definition.iconName]} onRemove={() => { removeViewFilter(filter.fieldMetadataId); }} diff --git a/front/src/modules/views/components/ViewBarEffect.tsx b/front/src/modules/views/components/ViewBarEffect.tsx index c0980a72b..d97941824 100644 --- a/front/src/modules/views/components/ViewBarEffect.tsx +++ b/front/src/modules/views/components/ViewBarEffect.tsx @@ -34,7 +34,7 @@ export const ViewBarEffect = () => { const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); useFindManyObjectRecords({ - objectNamePlural: 'viewsV2', + objectNamePlural: 'views', filter: { type: { eq: viewType }, objectMetadataId: { eq: viewObjectMetadataId }, @@ -66,7 +66,7 @@ export const ViewBarEffect = () => { useFindManyObjectRecords({ skip: !currentViewId, - objectNamePlural: 'viewFieldsV2', + objectNamePlural: 'viewFields', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot, set }) => @@ -107,7 +107,7 @@ export const ViewBarEffect = () => { useFindManyObjectRecords({ skip: !currentViewId, - objectNamePlural: 'viewFiltersV2', + objectNamePlural: 'viewFilters', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot, set }) => @@ -161,7 +161,7 @@ export const ViewBarEffect = () => { useFindManyObjectRecords({ skip: !currentViewId, - objectNamePlural: 'viewSortsV2', + objectNamePlural: 'viewSorts', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( ({ snapshot, set }) => diff --git a/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx b/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx index bcfe9a537..005f4bd59 100644 --- a/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx +++ b/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx @@ -9,6 +9,7 @@ import { import { IconMinus, IconPlus } from '@/ui/display/icon'; import { AppTooltip } from '@/ui/display/tooltip/AppTooltip'; import { IconInfoCircle } from '@/ui/input/constants/icons'; +import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem'; import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; @@ -48,6 +49,8 @@ export const ViewFieldsVisibilityDropdownSection = ({ else setOpenToolTipIndex(index); }; + const { icons } = useLazyLoadIcons(); + const getIconButtons = ( index: number, field: Omit, 'size' | 'position'>, @@ -103,7 +106,7 @@ export const ViewFieldsVisibilityDropdownSection = ({ itemComponent={ ( { const { updateOneMutation, createOneMutation, findManyQuery } = useFindOneObjectMetadataItem({ - objectNameSingular: 'viewFieldV2', + objectNameSingular: 'viewField', }); const apolloClient = useApolloClient(); diff --git a/front/src/modules/views/hooks/internal/useViewFilters.ts b/front/src/modules/views/hooks/internal/useViewFilters.ts index 769a280bf..a4ad6e4df 100644 --- a/front/src/modules/views/hooks/internal/useViewFilters.ts +++ b/front/src/modules/views/hooks/internal/useViewFilters.ts @@ -17,7 +17,7 @@ export const useViewFilters = (viewScopeId: string) => { deleteOneMutation, findManyQuery, } = useFindOneObjectMetadataItem({ - objectNameSingular: 'viewFilterV2', + objectNameSingular: 'viewFilter', }); const apolloClient = useApolloClient(); diff --git a/front/src/modules/views/hooks/internal/useViewSorts.ts b/front/src/modules/views/hooks/internal/useViewSorts.ts index 1789bbf1a..43aacd174 100644 --- a/front/src/modules/views/hooks/internal/useViewSorts.ts +++ b/front/src/modules/views/hooks/internal/useViewSorts.ts @@ -17,7 +17,7 @@ export const useViewSorts = (viewScopeId: string) => { deleteOneMutation, findManyQuery, } = useFindOneObjectMetadataItem({ - objectNameSingular: 'viewSortV2', + objectNameSingular: 'viewSort', }); const apolloClient = useApolloClient(); diff --git a/front/src/modules/views/hooks/internal/useViews.ts b/front/src/modules/views/hooks/internal/useViews.ts index 99f5e91b2..f4713ecfa 100644 --- a/front/src/modules/views/hooks/internal/useViews.ts +++ b/front/src/modules/views/hooks/internal/useViews.ts @@ -12,7 +12,7 @@ export const useViews = (scopeId: string) => { deleteOneMutation, findManyQuery, } = useFindOneObjectMetadataItem({ - objectNameSingular: 'viewV2', + objectNameSingular: 'view', }); const apolloClient = useApolloClient(); diff --git a/front/src/modules/views/hooks/useView.ts b/front/src/modules/views/hooks/useView.ts index 59e2d7065..62447d0d2 100644 --- a/front/src/modules/views/hooks/useView.ts +++ b/front/src/modules/views/hooks/useView.ts @@ -55,6 +55,7 @@ export const useView = (props?: UseViewProps) => { } = useViews(scopeId); const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState); + const setAvailableFieldDefinitions = useSetRecoilState( availableFieldDefinitionsState, ); diff --git a/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts b/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts index be4f29909..5dada6459 100644 --- a/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts +++ b/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts @@ -23,7 +23,7 @@ export const mapViewFieldsToBoardFieldDefinitions = ( correspondingFieldMetadata.entityChipDisplayMapper, infoTooltipContent: correspondingFieldMetadata.infoTooltipContent, basePathToShowPage: correspondingFieldMetadata.basePathToShowPage, - Icon: correspondingFieldMetadata.Icon, + iconName: correspondingFieldMetadata.iconName, type: correspondingFieldMetadata.type, position: viewField.position, isVisible: viewField.isVisible, diff --git a/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts b/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts index d3119a6ee..52c6432ea 100644 --- a/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts +++ b/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts @@ -23,7 +23,7 @@ export const mapViewFieldsToColumnDefinitions = ( correspondingFieldMetadata.entityChipDisplayMapper, infoTooltipContent: correspondingFieldMetadata.infoTooltipContent, basePathToShowPage: correspondingFieldMetadata.basePathToShowPage, - Icon: correspondingFieldMetadata.Icon, + iconName: correspondingFieldMetadata.iconName, type: correspondingFieldMetadata.type, position: viewField.position, size: viewField.size ?? correspondingFieldMetadata.size, diff --git a/front/src/modules/users/components/UserPicker.tsx b/front/src/modules/workspace-member/components/WorkspaceMemberPicker.tsx similarity index 92% rename from front/src/modules/users/components/UserPicker.tsx rename to front/src/modules/workspace-member/components/WorkspaceMemberPicker.tsx index 0a712376b..0f67e526e 100644 --- a/front/src/modules/users/components/UserPicker.tsx +++ b/front/src/modules/workspace-member/components/WorkspaceMemberPicker.tsx @@ -10,7 +10,7 @@ import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelec import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; -export type UserPickerProps = { +export type WorkspaceMemberPickerProps = { userId: string; onSubmit: (newUser: EntityForSelect | null) => void; onCancel?: () => void; @@ -18,13 +18,13 @@ export type UserPickerProps = { initialSearchFilter?: string | null; }; -export const UserPicker = ({ +export const WorkspaceMemberPicker = ({ userId, onSubmit, onCancel, width, initialSearchFilter, -}: UserPickerProps) => { +}: WorkspaceMemberPickerProps) => { const [relationPickerSearchFilter, setRelationPickerSearchFilter] = useRecoilScopedState(relationPickerSearchFilterScopedState); @@ -33,7 +33,7 @@ export const UserPicker = ({ }, [initialSearchFilter, setRelationPickerSearchFilter]); const { findManyQuery } = useFindOneObjectMetadataItem({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); const useFindManyWorkspaceMembers = (options: any) => @@ -58,7 +58,7 @@ export const UserPicker = ({ originalEntity: workspaceMember, }), selectedIds: userId ? [userId] : [], - objectNamePlural: 'workspaceMembersV2', + objectNamePlural: 'workspaceMembers', }); const handleEntitySelected = async (selectedUser: any | null | undefined) => { diff --git a/front/src/modules/workspace-member/types/WorkspaceMember.ts b/front/src/modules/workspace-member/types/WorkspaceMember.ts index 790743cdd..20111a3eb 100644 --- a/front/src/modules/workspace-member/types/WorkspaceMember.ts +++ b/front/src/modules/workspace-member/types/WorkspaceMember.ts @@ -6,8 +6,8 @@ export type WorkspaceMember = { firstName: string; lastName: string; }; - avatarUrl: string | null; + avatarUrl?: string | null; locale: string; - colorScheme: ColorScheme; + colorScheme?: ColorScheme; allowImpersonation: boolean; }; diff --git a/front/src/modules/workspace/graphql/mutations/removeWorkspaceLogo.ts b/front/src/modules/workspace/graphql/mutations/removeWorkspaceLogo.ts deleted file mode 100644 index 7f1b09623..000000000 --- a/front/src/modules/workspace/graphql/mutations/removeWorkspaceLogo.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const REMOVE_WORKSPACE_LOGO = gql` - mutation RemoveWorkspaceLogo { - updateWorkspace(data: { logo: null }) { - id - } - } -`; diff --git a/front/src/modules/workspace/graphql/mutations/updateWorkspace.ts b/front/src/modules/workspace/graphql/mutations/updateWorkspace.ts index 8ed42c7a2..d4c4021b7 100644 --- a/front/src/modules/workspace/graphql/mutations/updateWorkspace.ts +++ b/front/src/modules/workspace/graphql/mutations/updateWorkspace.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; export const UPDATE_WORKSPACE = gql` - mutation UpdateWorkspace($data: WorkspaceUpdateInput!) { - updateWorkspace(data: $data) { + mutation UpdateWorkspace($input: UpdateWorkspaceInput!) { + updateWorkspace(data: $input) { id domainName displayName diff --git a/front/src/modules/workspace/graphql/mutations/updateWorkspaceLogo.ts b/front/src/modules/workspace/graphql/mutations/uploadWorkspaceLogo.ts similarity index 75% rename from front/src/modules/workspace/graphql/mutations/updateWorkspaceLogo.ts rename to front/src/modules/workspace/graphql/mutations/uploadWorkspaceLogo.ts index f89d18cb2..68435c50a 100644 --- a/front/src/modules/workspace/graphql/mutations/updateWorkspaceLogo.ts +++ b/front/src/modules/workspace/graphql/mutations/uploadWorkspaceLogo.ts @@ -1,6 +1,6 @@ import { gql } from '@apollo/client'; -export const UPDATE_WORKSPACE_LOGO = gql` +export const UPLOAD_WORKSPACE_LOGO = gql` mutation UploadWorkspaceLogo($file: Upload!) { uploadWorkspaceLogo(file: $file) } diff --git a/front/src/modules/workspace/graphql/queries/getCurrentWorkspace.ts b/front/src/modules/workspace/graphql/queries/getCurrentWorkspace.ts deleted file mode 100644 index 78b10c558..000000000 --- a/front/src/modules/workspace/graphql/queries/getCurrentWorkspace.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_CURRENT_WORKSPACE = gql` - query getCurrentWorkspace { - currentWorkspace { - id - displayName - logo - } - } -`; diff --git a/front/src/modules/workspace/graphql/queries/getWorkspaceMembers.ts b/front/src/modules/workspace/graphql/queries/getWorkspaceMembers.ts deleted file mode 100644 index f886e1970..000000000 --- a/front/src/modules/workspace/graphql/queries/getWorkspaceMembers.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_WORKSPACE_MEMBERS = gql` - query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) { - workspaceMembers: findManyWorkspaceMember(where: $where) { - id - } - } -`; diff --git a/front/src/pages/auth/CreateProfile.tsx b/front/src/pages/auth/CreateProfile.tsx index 35d50ed09..4515e225d 100644 --- a/front/src/pages/auth/CreateProfile.tsx +++ b/front/src/pages/auth/CreateProfile.tsx @@ -9,7 +9,9 @@ import { z } from 'zod'; import { SubTitle } from '@/auth/components/SubTitle'; import { Title } from '@/auth/components/Title'; +import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; +import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; @@ -52,6 +54,7 @@ type Form = z.infer; export const CreateProfile = () => { const navigate = useNavigate(); + const onboardingStatus = useOnboardingStatus(); const { enqueueSnackBar } = useSnackBar(); @@ -61,7 +64,7 @@ export const CreateProfile = () => { const { updateOneObject, objectNotFoundInMetadata } = useUpdateOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); // Form @@ -139,6 +142,10 @@ export const CreateProfile = () => { [onSubmit], ); + if (onboardingStatus !== OnboardingStatus.OngoingProfileCreation) { + return null; + } + return ( <> Create profile diff --git a/front/src/pages/auth/CreateWorkspace.tsx b/front/src/pages/auth/CreateWorkspace.tsx index 383169870..cd8c99ab6 100644 --- a/front/src/pages/auth/CreateWorkspace.tsx +++ b/front/src/pages/auth/CreateWorkspace.tsx @@ -8,7 +8,9 @@ import { z } from 'zod'; import { SubTitle } from '@/auth/components/SubTitle'; import { Title } from '@/auth/components/Title'; +import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; +import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { H2Title } from '@/ui/display/typography/components/H2Title'; @@ -43,6 +45,7 @@ export const CreateWorkspace = () => { const navigate = useNavigate(); const { enqueueSnackBar } = useSnackBar(); + const onboardingStatus = useOnboardingStatus(); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const [updateWorkspace] = useUpdateWorkspaceMutation(); @@ -66,7 +69,7 @@ export const CreateWorkspace = () => { try { const result = await updateWorkspace({ variables: { - data: { + input: { displayName: data.name, }, }, @@ -101,6 +104,10 @@ export const CreateWorkspace = () => { [onSubmit], ); + if (onboardingStatus !== OnboardingStatus.OngoingWorkspaceCreation) { + return null; + } + return ( <> Create your workspace diff --git a/front/src/pages/companies/Companies.tsx b/front/src/pages/companies/Companies.tsx deleted file mode 100644 index af81aca75..000000000 --- a/front/src/pages/companies/Companies.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { getOperationName } from '@apollo/client/utilities'; -import styled from '@emotion/styled'; -import { v4 } from 'uuid'; - -import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect'; -import { CompanyTable } from '@/companies/table/components/CompanyTable'; -import { SEARCH_COMPANY_QUERY } from '@/search/graphql/queries/searchCompanyQuery'; -import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; -import { IconBuildingSkyscraper } from '@/ui/display/icon'; -import { PageAddButton } from '@/ui/layout/page/PageAddButton'; -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageHeader } from '@/ui/layout/page/PageHeader'; -import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect'; -import { RecordTableActionBar } from '@/ui/object/record-table/action-bar/components/RecordTableActionBar'; -import { RecordTableContextMenu } from '@/ui/object/record-table/context-menu/components/RecordTableContextMenu'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { useUpsertTableRowId } from '@/ui/object/record-table/hooks/useUpsertTableRowId'; -import { useInsertOneCompanyMutation } from '~/generated/graphql'; - -const StyledTableContainer = styled.div` - display: flex; - width: 100%; -`; - -export const Companies = () => { - const [insertCompany] = useInsertOneCompanyMutation(); - const { upsertRecordTableItem } = useRecordTable({ - recordTableScopeId: 'companies', - }); - const upsertTableRowIds = useUpsertTableRowId(); - const { triggerOptimisticEffects } = useOptimisticEffect({ - objectNameSingular: 'company', - }); - - const handleAddButtonClick = async () => { - const newCompanyId: string = v4(); - await insertCompany({ - variables: { - data: { - id: newCompanyId, - name: '', - domainName: '', - address: '', - }, - }, - update: (_cache, { data }) => { - if (data?.createOneCompany) { - upsertTableRowIds(data?.createOneCompany.id); - upsertRecordTableItem(data?.createOneCompany); - triggerOptimisticEffects('Company', [data?.createOneCompany]); - } - }, - refetchQueries: [getOperationName(SEARCH_COMPANY_QUERY) ?? ''], - }); - }; - - return ( - - - - - - - - - - - - - - - - ); -}; diff --git a/front/src/pages/companies/CompaniesMockMode.tsx b/front/src/pages/companies/CompaniesMockMode.tsx index 9d8ad5921..f7d276c47 100644 --- a/front/src/pages/companies/CompaniesMockMode.tsx +++ b/front/src/pages/companies/CompaniesMockMode.tsx @@ -1,6 +1,5 @@ import styled from '@emotion/styled'; -import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode'; import { IconBuildingSkyscraper } from '@/ui/display/icon'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; @@ -16,9 +15,7 @@ export const CompaniesMockMode = () => { - - - + ); diff --git a/front/src/pages/companies/CompanyShow.tsx b/front/src/pages/companies/CompanyShow.tsx deleted file mode 100644 index 36eb03d9c..000000000 --- a/front/src/pages/companies/CompanyShow.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { useEffect } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; - -import { CompanyTeam } from '@/companies/components/CompanyTeam'; -import { useCompanyQuery } from '@/companies/hooks/useCompanyQuery'; -import { useFavorites } from '@/favorites/hooks/useFavorites'; -import { AppPath } from '@/types/AppPath'; -import { IconBuildingSkyscraper } from '@/ui/display/icon'; -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; -import { PageHeader } from '@/ui/layout/page/PageHeader'; -import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton'; -import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer'; -import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer'; -import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard'; -import { ShowPageRecoilScopeContext } from '@/ui/layout/states/ShowPageRecoilScopeContext'; -import { FieldContext } from '@/ui/object/field/contexts/FieldContext'; -import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/RecordInlineCell'; -import { PropertyBox } from '@/ui/object/record-inline-cell/property-box/components/PropertyBox'; -import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; -import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { useUpdateOneCompanyMutation } from '~/generated/graphql'; -import { getLogoUrlFromDomainName } from '~/utils'; - -import { CompanyNameEditableField } from '../../modules/companies/editable-field/components/CompanyNameEditableField'; -import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer'; - -import { companyShowFieldDefinitions } from './constants/companyShowFieldDefinitions'; - -export const CompanyShow = () => { - const companyId = useParams().companyId ?? ''; - const { createFavorite, deleteFavorite } = useFavorites({ - objectNamePlural: 'companies', - }); - const navigate = useNavigate(); - const { data, loading } = useCompanyQuery(companyId); - const company = data?.findUniqueCompany; - - useEffect(() => { - if (!loading && !company) { - navigate(AppPath.NotFound); - } - }, [loading, company, navigate]); - - if (!company) return <>; - - const isFavorite = - company.Favorite && company.Favorite?.length > 0 ? true : false; - - const handleFavoriteButtonClick = async () => { - if (isFavorite) deleteFavorite(companyId); - else createFavorite('company', companyId); - }; - - return ( - - - - - - - - - - - ( - - )} - avatarType="squared" - /> - - {companyShowFieldDefinitions.map((fieldDefinition) => { - return ( - - - - ); - })} - - - - - - - - - ); -}; diff --git a/front/src/pages/companies/__stories__/Companies.add.stories.tsx b/front/src/pages/companies/__stories__/Companies.add.stories.tsx deleted file mode 100644 index e0d8bd0f7..000000000 --- a/front/src/pages/companies/__stories__/Companies.add.stories.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedCompaniesData } from '~/testing/mock-data/companies'; -import { sleep } from '~/testing/sleep'; - -import { Companies } from '../Companies'; - -import { Story } from './Companies.stories'; - -const meta: Meta = { - title: 'Pages/Companies/Add', - component: Companies, - decorators: [PageDecorator], - args: { routePath: AppPath.CompaniesPage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export const AddNewCompany: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedCompaniesData[0].name, - {}, - { timeout: 3000 }, - ); - }); - - const rowsBeforeAdd = canvas.getAllByRole('row'); - - await step('Click on add button', async () => { - const addButton = canvas.getByRole('button', { name: 'Add' }); - - await userEvent.click(addButton); - }); - - await sleep(1000); - - await step('Check an empty row has been added', async () => { - const rowsAfterAdd = canvas.getAllByRole('row'); - - const firstRow = rowsAfterAdd[1]; - const cells = within(firstRow).getAllByRole('cell'); - - expect(cells[1].textContent).toBe(''); - expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); - }); - }, -}; diff --git a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx deleted file mode 100644 index b151a356f..000000000 --- a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedCompaniesData } from '~/testing/mock-data/companies'; -import { sleep } from '~/testing/sleep'; - -import { Companies } from '../Companies'; - -import { Story } from './Companies.stories'; - -const meta: Meta = { - title: 'Pages/Companies/FilterBy', - component: Companies, - decorators: [PageDecorator], - args: { routePath: AppPath.CompaniesPage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export const FilterByName: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedCompaniesData[0].name, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on filter button', async () => { - const filterButton = canvas.getByText('Filter'); - await userEvent.click(filterButton); - }); - - await step('Select name filter', async () => { - const nameFilterButton = canvas.getByTestId('select-filter-0'); - await userEvent.click(nameFilterButton); - - const nameInput = canvas.getByPlaceholderText('Name'); - await userEvent.type(nameInput, 'Air', { delay: 200 }); - - const nameFilter = canvas.getAllByText( - (_, element) => !!element?.textContent?.includes('Name: Air'), - ); - expect(nameFilter).not.toHaveLength(0); - }); - - await sleep(1000); - - await step('Check filtered rows', async () => { - expect(canvas.getByText('Airbnb')).toBeVisible(); - expect(canvas.getByText('Aircall')).toBeVisible(); - expect(canvas.queryByText('Qonto')).toBeNull(); - }); - }, -}; - -export const FilterByAccountOwner: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedCompaniesData[0].name, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on filter button', async () => { - const filterButton = canvas.getByText('Filter'); - await userEvent.click(filterButton); - }); - - await step('Select account owner filter', async () => { - const accountOwnerFilterButton = canvas.getByTestId('select-filter-5'); - await userEvent.click(accountOwnerFilterButton); - - const accountOwnerNameInput = - canvas.getByPlaceholderText('Account owner'); - await userEvent.type(accountOwnerNameInput, 'Char', { delay: 200 }); - - const charlesChip = await canvas.findByRole( - 'listitem', - { - name: (_, element) => - !!element?.textContent?.includes('Charles Test'), - }, - { timeout: 1000 }, - ); - await userEvent.click(charlesChip); - - const accountOwnerFilter = canvas.getAllByText( - (_, element) => - !!element?.textContent?.includes('Account owner: Charles Test'), - ); - expect(accountOwnerFilter).not.toHaveLength(0); - }); - - await sleep(1000); - - await step('Check filtered rows', async () => { - expect(canvas.getByText('Airbnb')).toBeVisible(); - expect(canvas.queryByText('Qonto')).toBeNull(); - }); - }, -}; diff --git a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx deleted file mode 100644 index 5b1560db2..000000000 --- a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedCompaniesData } from '~/testing/mock-data/companies'; -import { sleep } from '~/testing/sleep'; - -import { Companies } from '../Companies'; - -import { Story } from './Companies.stories'; - -const meta: Meta = { - title: 'Pages/Companies/SortBy', - component: Companies, - decorators: [PageDecorator], - args: { routePath: AppPath.CompaniesPage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -const sortedCompanyNames = [...mockedCompaniesData] - .map(({ name }) => name) - .sort((a, b) => a.localeCompare(b)); - -export const SortByName: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedCompaniesData[0].name, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on sort button', async () => { - const sortButton = canvas.getByRole('button', { name: 'Sort' }); - await userEvent.click(sortButton); - }); - - await step('Select sort by name', async () => { - const nameSortButton = canvas.getByTestId('select-sort-0'); - await userEvent.click(nameSortButton); - - await canvas.findByTestId('remove-icon-name', {}, { timeout: 3000 }); - }); - - await sleep(1000); - - await step('Check rows are sorted by name', async () => { - const nameCells = canvas.getAllByText( - (_, element) => - sortedCompanyNames.some((name) => - element?.textContent?.includes(name), - ), - { selector: '[data-testid="editable-cell-display-mode"]' }, - ); - - expect(nameCells).toHaveLength(sortedCompanyNames.length); - - sortedCompanyNames.forEach((name, index) => - expect(nameCells[index]).toHaveTextContent(name), - ); - }); - }, -}; diff --git a/front/src/pages/companies/__stories__/Companies.stories.tsx b/front/src/pages/companies/__stories__/Companies.stories.tsx deleted file mode 100644 index f78aa824d..000000000 --- a/front/src/pages/companies/__stories__/Companies.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; - -import { Companies } from '../Companies'; - -const meta: Meta = { - title: 'Pages/Companies', - component: Companies, - decorators: [PageDecorator], - args: { routePath: AppPath.CompaniesPage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export type Story = StoryObj; - -export const Default: Story = {}; diff --git a/front/src/pages/companies/__stories__/Company.stories.tsx b/front/src/pages/companies/__stories__/Company.stories.tsx deleted file mode 100644 index 9384c99e0..000000000 --- a/front/src/pages/companies/__stories__/Company.stories.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { getOperationName } from '@apollo/client/utilities'; -import { expect } from '@storybook/jest'; -import { Meta, StoryObj } from '@storybook/react'; -import { fireEvent, within } from '@storybook/testing-library'; -import { graphql } from 'msw'; - -import { UPDATE_ONE_COMPANY } from '@/companies/graphql/mutations/updateOneCompany'; -import { GET_COMPANY } from '@/companies/graphql/queries/getCompany'; -import { AppPath } from '@/types/AppPath'; -import { ObjectFilterDropdownScope } from '@/ui/object/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedCompaniesData } from '~/testing/mock-data/companies'; - -import { CompanyShow } from '../CompanyShow'; - -const meta: Meta = { - title: 'Pages/Companies/Company', - component: CompanyShow, - decorators: [PageDecorator], - args: { - routePath: AppPath.CompanyShowPage, - routeParams: { ':companyId': mockedCompaniesData[0].id }, - }, - parameters: { - msw: [ - ...graphqlMocks, - graphql.query(getOperationName(GET_COMPANY) ?? '', (req, res, ctx) => { - return res( - ctx.data({ - findUniqueCompany: mockedCompaniesData[0], - }), - ); - }), - ], - }, -}; - -export default meta; - -export type Story = StoryObj; - -export const Default: Story = {}; - -export const EditNoteByAddButton: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const firstNoteTitle = await canvas.findByText('My very first note'); - await firstNoteTitle.click(); - - expect( - await canvas.findByDisplayValue('My very first note'), - ).toBeInTheDocument(); - - const workspaceName = await canvas.findByText('Twenty'); - await fireEvent.click(workspaceName); - - expect(await canvas.queryByDisplayValue('My very first note')).toBeNull(); - - const addDropdown = await canvas.findByTestId('add-showpage-button'); - await addDropdown.click(); - - const noteButton = await canvas.findByText('Note'); - await noteButton.click(); - - expect( - await canvas.findByDisplayValue('My very first note'), - ).toBeInTheDocument(); - }, - parameters: { - msw: [ - ...meta.parameters?.msw, - graphql.mutation( - getOperationName(UPDATE_ONE_COMPANY) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - updateOneCompany: [mockedCompaniesData[0]], - }), - ); - }, - ), - ], - }, -}; - -export const NoteTab: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const noteTab = await canvas.findByTestId('tab-notes'); - await noteTab.click(); - - expect(await canvas.findByText('My very first note')).toBeInTheDocument(); - - const workspaceName = await canvas.findByText('Twenty'); - await fireEvent.click(workspaceName); - - expect(await canvas.queryByDisplayValue('My very first note')).toBeNull(); - - const addButton = await canvas.findByText('Add note'); - await addButton.click(); - - const noteButton = await canvas.findByText('Note'); - await noteButton.click(); - - expect(await canvas.findByText('My very first note')).toBeInTheDocument(); - }, - parameters: { - msw: [ - ...meta.parameters?.msw, - graphql.mutation( - getOperationName(UPDATE_ONE_COMPANY) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - updateOneCompany: [mockedCompaniesData[0]], - }), - ); - }, - ), - ], - }, -}; - -export const TaskTab: Story = { - decorators: [ - (Story) => ( - - - - ), - ], - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const taskTab = await canvas.findByTestId('tab-tasks'); - await taskTab.click(); - - expect(await canvas.findByText('My very first task')).toBeInTheDocument(); - - const workspaceName = await canvas.findByText('Twenty'); - await fireEvent.click(workspaceName); - - expect(await canvas.queryByDisplayValue('My very first task')).toBeNull(); - - const addButton = await canvas.findByText('Add task'); - await addButton.click(); - - const taskButton = await canvas.findByText('Task'); - await taskButton.click(); - - expect(await canvas.findByText('My very first task')).toBeInTheDocument(); - }, - parameters: { - msw: [ - ...meta.parameters?.msw, - graphql.mutation( - getOperationName(UPDATE_ONE_COMPANY) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - updateOneCompany: [mockedCompaniesData[0]], - }), - ); - }, - ), - ], - }, -}; diff --git a/front/src/pages/companies/constants/companyShowFieldDefinitions.tsx b/front/src/pages/companies/constants/companyShowFieldDefinitions.tsx deleted file mode 100644 index 45389acfb..000000000 --- a/front/src/pages/companies/constants/companyShowFieldDefinitions.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { - IconBrandX, - IconCalendar, - IconLink, - IconMap, - IconTarget, - IconUserCircle, - IconUsers, -} from '@/ui/display/icon'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition'; -import { - FieldBooleanMetadata, - FieldDateMetadata, - FieldMetadata, - FieldNumberMetadata, - FieldRelationMetadata, - FieldTextMetadata, - FieldURLMetadata, -} from '@/ui/object/field/types/FieldMetadata'; -import { User } from '~/generated/graphql'; - -export const companyShowFieldDefinitions: FieldDefinition[] = [ - { - fieldMetadataId: 'domainName', - label: 'Domain name', - Icon: IconLink, - type: 'URL', - metadata: { - fieldName: 'domainName', - placeHolder: 'URL', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'accountOwner', - label: 'Account owner', - Icon: IconUserCircle, - type: 'RELATION', - metadata: { - fieldName: 'accountOwner', - relationType: Entity.User, - }, - entityChipDisplayMapper: (dataObject: User) => { - return { - name: dataObject?.displayName, - pictureUrl: dataObject?.avatarUrl ?? undefined, - avatarType: 'rounded', - }; - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'employees', - label: 'Employees', - Icon: IconUsers, - type: 'NUMBER', - metadata: { - fieldName: 'employees', - placeHolder: 'Employees', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'address', - label: 'Address', - Icon: IconMap, - type: 'TEXT', - metadata: { - fieldName: 'address', - placeHolder: 'Address', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'idealCustomerProfile', - label: 'ICP', - Icon: IconTarget, - type: 'BOOLEAN', - metadata: { - fieldName: 'idealCustomerProfile', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'xUrl', - label: 'Twitter', - Icon: IconBrandX, - type: 'URL', - metadata: { - fieldName: 'xUrl', - placeHolder: 'X', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'createdAt', - label: 'Created at', - Icon: IconCalendar, - type: 'DATE', - metadata: { - fieldName: 'createdAt', - }, - } satisfies FieldDefinition, -]; diff --git a/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx b/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx deleted file mode 100644 index ace176c23..000000000 --- a/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { - IconBuildingSkyscraper, - IconCalendarEvent, - IconLink, - IconMap, - IconUser, - IconUsers, -} from '@/ui/display/icon/index'; -import { FilterDefinitionByEntity } from '@/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity'; -import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect'; -import { Company } from '~/generated/graphql'; - -export const companyTableFilterDefinitions: FilterDefinitionByEntity[] = - [ - { - fieldMetadataId: 'name', - label: 'Name', - Icon: IconBuildingSkyscraper, - type: 'TEXT', - }, - { - fieldMetadataId: 'employees', - label: 'Employees', - Icon: IconUsers, - type: 'NUMBER', - }, - { - fieldMetadataId: 'domainName', - label: 'URL', - Icon: IconLink, - type: 'TEXT', - }, - { - fieldMetadataId: 'address', - label: 'Address', - Icon: IconMap, - type: 'TEXT', - }, - { - fieldMetadataId: 'createdAt', - label: 'Created at', - Icon: IconCalendarEvent, - type: 'DATE', - }, - { - fieldMetadataId: 'accountOwnerId', - label: 'Account owner', - Icon: IconUser, - type: 'ENTITY', - entitySelectComponent: , - }, - ]; diff --git a/front/src/pages/companies/constants/companyTableSortDefinitions.tsx b/front/src/pages/companies/constants/companyTableSortDefinitions.tsx deleted file mode 100644 index 284ababfb..000000000 --- a/front/src/pages/companies/constants/companyTableSortDefinitions.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { - IconBuildingSkyscraper, - IconCalendarEvent, - IconLink, - IconMap, - IconUsers, -} from '@/ui/display/icon/index'; -import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefinition'; - -export const companyTableSortDefinitions: SortDefinition[] = [ - { - fieldMetadataId: 'name', - label: 'Name', - Icon: IconBuildingSkyscraper, - }, - { - fieldMetadataId: 'employees', - label: 'Employees', - Icon: IconUsers, - }, - { - fieldMetadataId: 'domainName', - label: 'Url', - Icon: IconLink, - }, - { - fieldMetadataId: 'address', - label: 'Address', - Icon: IconMap, - }, - { - fieldMetadataId: 'createdAt', - label: 'Creation', - Icon: IconCalendarEvent, - }, -]; diff --git a/front/src/pages/opportunities/Opportunities.tsx b/front/src/pages/opportunities/Opportunities.tsx index 98e6b430d..895e6c2e1 100644 --- a/front/src/pages/opportunities/Opportunities.tsx +++ b/front/src/pages/opportunities/Opportunities.tsx @@ -28,7 +28,7 @@ export const Opportunities = () => { const { updateOneObject: updateOnePipelineStep } = useUpdateOneObjectRecord({ - objectNameSingular: 'pipelineStepV2', + objectNameSingular: 'pipelineStep', }); const handleEditColumnTitle = ( @@ -46,7 +46,7 @@ export const Opportunities = () => { }; const opportunitiesV2MetadataId = useFindOneObjectMetadataItem({ - objectNameSingular: 'opportunityV2', + objectNameSingular: 'opportunity', }).foundObjectMetadataItem?.id; const { setViewObjectMetadataId } = useView({ diff --git a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx index 17218af0c..c52b0d8f1 100644 --- a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx +++ b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx @@ -1,40 +1,34 @@ import { FilterDropdownCompanySearchSelect } from '@/companies/components/FilterDropdownCompanySearchSelect'; -import { - IconBuildingSkyscraper, - IconCalendarEvent, - IconCurrencyDollar, - IconUser, -} from '@/ui/display/icon/index'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { FilterDefinitionByEntity } from '@/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity'; -import { PipelineProgress } from '~/generated/graphql'; import { FilterDropdownPeopleSearchSelect } from '../../../modules/people/components/FilterDropdownPeopleSearchSelect'; -export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity[] = +export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity[] = [ { fieldMetadataId: 'amount', label: 'Amount', - Icon: IconCurrencyDollar, + iconName: 'IconCurrencyDollar', type: 'NUMBER', }, { fieldMetadataId: 'closeDate', label: 'Close date', - Icon: IconCalendarEvent, + iconName: 'IconCalendarEvent', type: 'DATE', }, { fieldMetadataId: 'companyId', label: 'Company', - Icon: IconBuildingSkyscraper, + iconName: 'IconBuildingSkyscraper', type: 'ENTITY', entitySelectComponent: , }, { fieldMetadataId: 'pointOfContactId', label: 'Point of contact', - Icon: IconUser, + iconName: 'IconUser', type: 'ENTITY', entitySelectComponent: , }, diff --git a/front/src/pages/people/People.tsx b/front/src/pages/people/People.tsx deleted file mode 100644 index 5fe8606b2..000000000 --- a/front/src/pages/people/People.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import styled from '@emotion/styled'; -import { v4 } from 'uuid'; - -import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect'; -import { PersonTable } from '@/people/table/components/PersonTable'; -import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; -import { IconUser } from '@/ui/display/icon'; -import { PageAddButton } from '@/ui/layout/page/PageAddButton'; -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageHeader } from '@/ui/layout/page/PageHeader'; -import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect'; -import { RecordTableActionBar } from '@/ui/object/record-table/action-bar/components/RecordTableActionBar'; -import { RecordTableContextMenu } from '@/ui/object/record-table/context-menu/components/RecordTableContextMenu'; -import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; -import { useUpsertTableRowId } from '@/ui/object/record-table/hooks/useUpsertTableRowId'; -import { useInsertOnePersonMutation } from '~/generated/graphql'; - -const StyledTableContainer = styled.div` - display: flex; - width: 100%; -`; - -export const People = () => { - const [insertOnePerson] = useInsertOnePersonMutation(); - const { upsertRecordTableItem } = useRecordTable({ - recordTableScopeId: 'people', - }); - const upsertTableRowIds = useUpsertTableRowId(); - const { triggerOptimisticEffects } = useOptimisticEffect({ - objectNameSingular: 'Person', - }); - - const handleAddButtonClick = async () => { - const newPersonId: string = v4(); - await insertOnePerson({ - variables: { - data: { - id: newPersonId, - firstName: '', - lastName: '', - }, - }, - update: (_cache, { data }) => { - if (data?.createOnePerson) { - upsertTableRowIds(data?.createOnePerson.id); - upsertRecordTableItem(data?.createOnePerson); - triggerOptimisticEffects('Person', [data?.createOnePerson]); - } - }, - }); - }; - - return ( - - - - - - - - - - - - - - - - ); -}; diff --git a/front/src/pages/people/PersonShow.tsx b/front/src/pages/people/PersonShow.tsx deleted file mode 100644 index 777652bef..000000000 --- a/front/src/pages/people/PersonShow.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import { useEffect } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; -import { getOperationName } from '@apollo/client/utilities'; - -import { useFavorites } from '@/favorites/hooks/useFavorites'; -import { GET_PERSON } from '@/people/graphql/queries/getPerson'; -import { usePersonQuery } from '@/people/hooks/usePersonQuery'; -import { AppPath } from '@/types/AppPath'; -import { IconUser } from '@/ui/display/icon'; -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; -import { PageHeader } from '@/ui/layout/page/PageHeader'; -import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton'; -import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer'; -import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer'; -import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard'; -import { ShowPageRecoilScopeContext } from '@/ui/layout/states/ShowPageRecoilScopeContext'; -import { FieldContext } from '@/ui/object/field/contexts/FieldContext'; -import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/RecordInlineCell'; -import { PropertyBox } from '@/ui/object/record-inline-cell/property-box/components/PropertyBox'; -import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; -import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { - useUpdateOnePersonMutation, - useUploadPersonPictureMutation, -} from '~/generated/graphql'; - -import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField'; -import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer'; - -import { personShowFieldDefinition } from './constants/personShowFieldDefinitions'; - -export const PersonShow = () => { - const personId = useParams().personId ?? ''; - const { createFavorite, deleteFavorite } = useFavorites({ - objectNamePlural: 'peopleV2', - }); - const navigate = useNavigate(); - - const { data, loading } = usePersonQuery(personId); - const person = data?.findUniquePerson; - - const [uploadPicture] = useUploadPersonPictureMutation(); - - useEffect(() => { - if (!loading && !person) { - navigate(AppPath.NotFound); - } - }, [loading, person, navigate]); - - if (!person) return <>; - - const isFavorite = - person.Favorite && person.Favorite?.length > 0 ? true : false; - - const onUploadPicture = async (file: File) => { - if (!file || !person?.id) { - return; - } - await uploadPicture({ - variables: { - file, - id: person.id, - }, - refetchQueries: [getOperationName(GET_PERSON) ?? ''], - }); - }; - - const handleFavoriteButtonClick = async () => { - if (isFavorite) deleteFavorite(person.id); - else createFavorite('person', person.id); - }; - - return ( - - - - - - - - - - - - person ? ( - - ) : ( - <> - ) - } - onUploadPicture={onUploadPicture} - avatarType="rounded" - /> - - {personShowFieldDefinition.map((fieldDefinition) => { - return ( - - - - ); - })} - - - - - - - - ); -}; diff --git a/front/src/pages/people/__stories__/People.add.stories.tsx b/front/src/pages/people/__stories__/People.add.stories.tsx deleted file mode 100644 index c45e80d68..000000000 --- a/front/src/pages/people/__stories__/People.add.stories.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPeopleData } from '~/testing/mock-data/people'; -import { sleep } from '~/testing/sleep'; - -import { People } from '../People'; - -import { Story } from './People.stories'; - -const meta: Meta = { - title: 'Pages/People/Add', - component: People, - decorators: [PageDecorator], - args: { routePath: AppPath.PeoplePage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export const AddNewPerson: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 3000 }, - ); - }); - - const rowsBeforeAdd = canvas.getAllByRole('row'); - - await step('Click on add button', async () => { - const addButton = canvas.getByRole('button', { name: 'Add' }); - - await userEvent.click(addButton); - }); - - await sleep(1000); - - await step('Check an empty row has been added', async () => { - const rowsAfterAdd = canvas.getAllByRole('row'); - - const firstRow = rowsAfterAdd[1]; - const cells = within(firstRow).getAllByRole('cell'); - - expect(cells[1].textContent).toBe(''); - expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); - }); - }, -}; diff --git a/front/src/pages/people/__stories__/People.filterBy.stories.tsx b/front/src/pages/people/__stories__/People.filterBy.stories.tsx deleted file mode 100644 index f0c680fa2..000000000 --- a/front/src/pages/people/__stories__/People.filterBy.stories.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPeopleData } from '~/testing/mock-data/people'; -import { sleep } from '~/testing/sleep'; - -import { People } from '../People'; - -import { Story } from './People.stories'; - -const meta: Meta = { - title: 'Pages/People/FilterBy', - component: People, - decorators: [PageDecorator], - args: { routePath: AppPath.PeoplePage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export const Email: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on filter button', async () => { - const filterButton = canvas.getByText('Filter'); - await userEvent.click(filterButton); - }); - - await step('Select email filter', async () => { - const emailFilterButton = canvas.getByTestId('select-filter-2'); - await userEvent.click(emailFilterButton); - - const emailInput = canvas.getByPlaceholderText('Email'); - await userEvent.type(emailInput, 'al', { delay: 200 }); - - const emailFilter = canvas.getAllByText( - (_, element) => !!element?.textContent?.includes('Email: al'), - ); - expect(emailFilter).not.toHaveLength(0); - }); - - await sleep(1000); - - await step('Check filtered rows', async () => { - expect(canvas.getByText('Alexandre Prot')).toBeVisible(); - expect(canvas.queryByText('John Doe')).toBeNull(); - }); - }, -}; - -export const CompanyName: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on filter button', async () => { - const filterButton = canvas.getByText('Filter'); - await userEvent.click(filterButton); - }); - - await step('Select company filter', async () => { - const companyFilterButton = canvas.getByTestId('select-filter-3'); - await userEvent.click(companyFilterButton); - - const companyNameInput = canvas.getByPlaceholderText('Company'); - await userEvent.type(companyNameInput, 'Qon', { delay: 200 }); - - const qontoChip = await canvas.findByRole( - 'listitem', - { name: (_, element) => !!element?.textContent?.includes('Qonto') }, - { timeout: 1000 }, - ); - await userEvent.click(qontoChip); - - const companyFilter = canvas.getAllByText( - (_, element) => !!element?.textContent?.includes('Company: Qonto'), - ); - expect(companyFilter).not.toHaveLength(0); - }); - - await sleep(1000); - - await step('Check filtered rows', async () => { - expect(canvas.getByText('Alexandre Prot')).toBeVisible(); - expect(canvas.queryByText('John Doe')).toBeNull(); - }); - }, -}; diff --git a/front/src/pages/people/__stories__/People.inputs.stories.tsx b/front/src/pages/people/__stories__/People.inputs.stories.tsx deleted file mode 100644 index 3b34d2c4b..000000000 --- a/front/src/pages/people/__stories__/People.inputs.stories.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; -import assert from 'assert'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPeopleData } from '~/testing/mock-data/people'; -import { sleep } from '~/testing/sleep'; - -import { People } from '../People'; - -import { Story } from './People.stories'; - -const meta: Meta = { - title: 'Pages/People/Input', - component: People, - decorators: [PageDecorator], - args: { routePath: AppPath.PeoplePage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export const InteractWithManyRows: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - - const firstRowEmailCell = await canvas.findByText( - mockedPeopleData[0].email, - {}, - { timeout: 3000 }, - ); - assert(firstRowEmailCell.parentElement); - - const secondRowEmailCell = canvas.getByText(mockedPeopleData[1].email); - assert(secondRowEmailCell.parentElement); - - expect( - canvas.queryByTestId('editable-cell-edit-mode-container'), - ).toBeNull(); - - await userEvent.click(firstRowEmailCell.parentElement); - - expect( - canvas.getByTestId('editable-cell-edit-mode-container'), - ).toBeVisible(); - - await userEvent.click(secondRowEmailCell.parentElement); - - await sleep(25); - - expect( - canvas.queryByTestId('editable-cell-edit-mode-container'), - ).toBeNull(); - - await userEvent.click(secondRowEmailCell.parentElement); - - expect( - canvas.getByTestId('editable-cell-edit-mode-container'), - ).toBeVisible(); - }, -}; - -export const CheckCheckboxes: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 3000 }, - ); - }); - - const [, firstRowCheckbox, secondRowCheckbox] = - canvas.getAllByRole('checkbox'); - - await step('Select first row', async () => { - assert(firstRowCheckbox.parentElement); - - await userEvent.click(firstRowCheckbox.parentElement); - await sleep(25); - - expect(firstRowCheckbox).toBeChecked(); - }); - - await step('Select second row', async () => { - await userEvent.click(secondRowCheckbox); - await sleep(25); - - expect(secondRowCheckbox).toBeChecked(); - }); - - await step('Unselect second row', async () => { - assert(secondRowCheckbox.parentElement); - - await userEvent.click(secondRowCheckbox.parentElement); - await sleep(25); - - expect(secondRowCheckbox).not.toBeChecked(); - }); - }, -}; - -export const EditRelation: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Click on third row company cell', async () => { - const thirdRowCompanyCell = await canvas.findByText( - mockedPeopleData[2].company.name, - {}, - { timeout: 3000 }, - ); - - await userEvent.click(thirdRowCompanyCell); - }); - - await step('Type "Air" in relation picker', async () => { - const relationSearchInput = canvas.getByPlaceholderText('Search'); - - await userEvent.type(relationSearchInput, 'Air', { delay: 200 }); - }); - - await step('Select "Airbnb"', async () => { - const airbnbChip = await canvas.findByRole('listitem', { - name: (_, element) => !!element?.textContent?.includes('Airbnb'), - }); - - await userEvent.click(airbnbChip); - }); - - await step('Check if Airbnb is in the table', async () => { - expect( - await canvas.findByText('Airbnb', {}, { timeout: 3000 }), - ).toBeVisible(); - }); - }, -}; - -export const SelectRelationWithKeys: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Click on first row company cell', async () => { - const firstRowCompanyCell = await canvas.findByText( - mockedPeopleData[0].company.name, - {}, - { timeout: 3000 }, - ); - - await userEvent.click(firstRowCompanyCell); - }); - - const relationSearchInput = canvas.getByPlaceholderText('Search'); - - await step('Type "Air" in relation picker', async () => { - await userEvent.type(relationSearchInput, 'Air', { delay: 200 }); - }); - - await step('Select "Aircall"', async () => { - await userEvent.keyboard('{arrowdown}'); - - await sleep(50); - - await userEvent.keyboard('{arrowup}'); - - await sleep(50); - - await userEvent.keyboard('{arrowdown}'); - - await sleep(50); - - await userEvent.keyboard('{arrowdown}'); - - await sleep(50); - - await userEvent.keyboard('{arrowdown}'); - - await sleep(50); - - await userEvent.keyboard('{enter}'); - }); - - await step('Check if Aircall is in the table', async () => { - expect( - await canvas.findByText('Aircall', {}, { timeout: 3000 }), - ).toBeVisible(); - }); - }, -}; diff --git a/front/src/pages/people/__stories__/People.sortBy.stories.tsx b/front/src/pages/people/__stories__/People.sortBy.stories.tsx deleted file mode 100644 index 751fb0b86..000000000 --- a/front/src/pages/people/__stories__/People.sortBy.stories.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPeopleData } from '~/testing/mock-data/people'; -import { sleep } from '~/testing/sleep'; - -import { People } from '../People'; - -import { Story } from './People.stories'; - -const meta: Meta = { - title: 'Pages/People/SortBy', - component: People, - decorators: [PageDecorator], - args: { routePath: AppPath.PeoplePage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -const peopleEmails = mockedPeopleData.map(({ email }) => email); -const sortedPeopleEmails = [...peopleEmails].sort((a, b) => a.localeCompare(b)); - -export const Email: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 1000 }, - ); - }); - - await step('Click on sort button', async () => { - const sortButton = canvas.getByRole('button', { name: 'Sort' }); - await userEvent.click(sortButton); - }); - - await step('Select sort by email', async () => { - const emailSortButton = canvas.getByTestId('select-sort-2'); - await userEvent.click(emailSortButton); - - await canvas.findByTestId('remove-icon-email', {}, { timeout: 3000 }); - }); - - await sleep(1000); - - await step('Check rows are sorted by email', async () => { - const emailCells = canvas.getAllByText( - (_, element) => - sortedPeopleEmails.some((email) => - element?.textContent?.includes(email), - ), - { selector: '[data-testid="editable-cell-display-mode"]' }, - ); - - expect(emailCells).toHaveLength(sortedPeopleEmails.length); - - sortedPeopleEmails.forEach((email, index) => - expect(emailCells[index]).toHaveTextContent(email), - ); - }); - }, -}; - -export const Reset: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - - await step('Wait for rows to appear', async () => { - await canvas.findByText( - mockedPeopleData[0].displayName, - {}, - { timeout: 3000 }, - ); - }); - - await step('Click on sort button', async () => { - const sortButton = canvas.getByRole('button', { name: 'Sort' }); - await userEvent.click(sortButton); - }); - - await step('Select sort by email', async () => { - const emailSortButton = canvas.getByTestId('select-sort-2'); - await userEvent.click(emailSortButton); - - expect( - await canvas.findByTestId('remove-icon-email'), - ).toBeInTheDocument(); - }); - - await step('Click on reset button', async () => { - const resetButton = canvas.getByRole('button', { name: 'Reset' }); - await userEvent.click(resetButton); - - expect(canvas.queryByTestId('remove-icon-email')).toBeNull(); - }); - - await step('Check rows are in initial order', async () => { - const emailCells = canvas.getAllByText( - (_, element) => - peopleEmails.some((email) => element?.textContent?.includes(email)), - { selector: '[data-testid="editable-cell-display-mode"]' }, - ); - - expect(emailCells).toHaveLength(peopleEmails.length); - - peopleEmails.forEach((email, index) => - expect(emailCells[index]).toHaveTextContent(email), - ); - }); - }, -}; diff --git a/front/src/pages/people/__stories__/People.stories.tsx b/front/src/pages/people/__stories__/People.stories.tsx deleted file mode 100644 index 80f7b6992..000000000 --- a/front/src/pages/people/__stories__/People.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; - -import { People } from '../People'; - -const meta: Meta = { - title: 'Pages/People', - component: People, - decorators: [PageDecorator], - args: { routePath: AppPath.PeoplePage }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export type Story = StoryObj; - -export const Default: Story = {}; diff --git a/front/src/pages/people/__stories__/Person.stories.tsx b/front/src/pages/people/__stories__/Person.stories.tsx deleted file mode 100644 index ae23274eb..000000000 --- a/front/src/pages/people/__stories__/Person.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; - -import { AppPath } from '@/types/AppPath'; -import { - PageDecorator, - PageDecoratorArgs, -} from '~/testing/decorators/PageDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; -import { mockedPeopleData } from '~/testing/mock-data/people'; - -import { PersonShow } from '../PersonShow'; - -const meta: Meta = { - title: 'Pages/People/Person', - component: PersonShow, - decorators: [PageDecorator], - args: { - routePath: AppPath.PersonShowPage, - routeParams: { ':personId': mockedPeopleData[0].id }, - }, - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; - -export type Story = StoryObj; - -export const Default: Story = {}; diff --git a/front/src/pages/people/constants/personShowFieldDefinitions.tsx b/front/src/pages/people/constants/personShowFieldDefinitions.tsx deleted file mode 100644 index 08abc5ac7..000000000 --- a/front/src/pages/people/constants/personShowFieldDefinitions.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { - IconBrandLinkedin, - IconBrandX, - IconBriefcase, - IconBuildingSkyscraper, - IconCalendar, - IconMail, - IconMap, - IconPhone, -} from '@/ui/display/icon'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; -import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition'; -import { - FieldDateMetadata, - FieldMetadata, - FieldPhoneMetadata, - FieldRelationMetadata, - FieldTextMetadata, - FieldURLMetadata, -} from '@/ui/object/field/types/FieldMetadata'; -import { Company } from '~/generated/graphql'; -import { getLogoUrlFromDomainName } from '~/utils'; - -export const personShowFieldDefinition: FieldDefinition[] = [ - { - fieldMetadataId: 'email', - label: 'Email', - Icon: IconMail, - type: 'TEXT', - metadata: { - fieldName: 'email', - placeHolder: 'Email', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'company', - label: 'Company', - Icon: IconBuildingSkyscraper, - type: 'RELATION', - metadata: { - fieldName: 'company', - relationType: Entity.Company, - }, - entityChipDisplayMapper: (dataObject: Company) => { - return { - name: dataObject?.name, - pictureUrl: getLogoUrlFromDomainName(dataObject?.domainName), - avatarType: 'squared', - }; - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'phone', - label: 'Phone', - Icon: IconPhone, - type: 'PHONE', - metadata: { - fieldName: 'phone', - placeHolder: 'Phone', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'jobTitle', - label: 'Job Title', - Icon: IconBriefcase, - type: 'TEXT', - metadata: { - fieldName: 'jobTitle', - placeHolder: 'Job Title', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'city', - label: 'City', - Icon: IconMap, - type: 'TEXT', - metadata: { - fieldName: 'city', - placeHolder: 'City', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'linkedinUrl', - label: 'Linkedin URL', - Icon: IconBrandLinkedin, - type: 'URL', - metadata: { - fieldName: 'linkedinUrl', - placeHolder: 'Linkedin URL', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'xUrl', - label: 'X URL', - Icon: IconBrandX, - type: 'URL', - metadata: { - fieldName: 'xUrl', - placeHolder: 'X URL', - }, - } satisfies FieldDefinition, - { - fieldMetadataId: 'createdAt', - label: 'Created at', - Icon: IconCalendar, - type: 'DATE', - metadata: { - fieldName: 'createdAt', - }, - } satisfies FieldDefinition, -]; diff --git a/front/src/pages/people/constants/personTableFilterDefinitions.tsx b/front/src/pages/people/constants/personTableFilterDefinitions.tsx deleted file mode 100644 index be4ade7e1..000000000 --- a/front/src/pages/people/constants/personTableFilterDefinitions.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { FilterDropdownCompanySearchSelect } from '@/companies/components/FilterDropdownCompanySearchSelect'; -import { - IconBuildingSkyscraper, - IconCalendarEvent, - IconMail, - IconMap, - IconPhone, - IconUser, -} from '@/ui/display/icon/index'; -import { FilterDefinitionByEntity } from '@/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity'; -import { Person } from '~/generated/graphql'; - -export const personTableFilterDefinitions: FilterDefinitionByEntity[] = - [ - { - fieldMetadataId: 'firstName', - label: 'First name', - Icon: IconUser, - type: 'TEXT', - }, - { - fieldMetadataId: 'lastName', - label: 'Last name', - Icon: IconUser, - type: 'TEXT', - }, - { - fieldMetadataId: 'email', - label: 'Email', - Icon: IconMail, - type: 'TEXT', - }, - { - fieldMetadataId: 'companyId', - label: 'Company', - Icon: IconBuildingSkyscraper, - type: 'ENTITY', - // TODO: replace this with a component that selects the dropdown to use based on the entity type - entitySelectComponent: , - }, - { - fieldMetadataId: 'phone', - label: 'Phone', - Icon: IconPhone, - type: 'TEXT', - }, - { - fieldMetadataId: 'createdAt', - label: 'Created at', - Icon: IconCalendarEvent, - type: 'DATE', - }, - { - fieldMetadataId: 'city', - label: 'City', - Icon: IconMap, - type: 'TEXT', - }, - ]; diff --git a/front/src/pages/people/constants/personTableSortDefinitions.tsx b/front/src/pages/people/constants/personTableSortDefinitions.tsx deleted file mode 100644 index 6c9eff630..000000000 --- a/front/src/pages/people/constants/personTableSortDefinitions.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - IconBuildingSkyscraper, - IconCalendarEvent, - IconMail, - IconMap, - IconPhone, - IconUser, -} from '@/ui/display/icon/index'; -import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefinition'; -import { SortDirection } from '@/ui/object/object-sort-dropdown/types/SortDirection'; - -export const personTableSortDefinitions: SortDefinition[] = [ - { - fieldMetadataId: 'fullname', - label: 'People', - Icon: IconUser, - - getOrderByTemplate: (direction: SortDirection) => [ - { firstName: direction }, - { lastName: direction }, - ], - }, - { - fieldMetadataId: 'company_name', - label: 'Company', - Icon: IconBuildingSkyscraper, - getOrderByTemplate: (direction: SortDirection) => [ - { company: { name: direction } }, - ], - }, - { - fieldMetadataId: 'email', - label: 'Email', - Icon: IconMail, - }, - { - fieldMetadataId: 'phone', - label: 'Phone', - Icon: IconPhone, - }, - { - fieldMetadataId: 'createdAt', - label: 'Created at', - Icon: IconCalendarEvent, - }, - { - fieldMetadataId: 'city', - label: 'City', - Icon: IconMap, - }, -]; diff --git a/front/src/pages/settings/SettingsWorkspaceMembers.tsx b/front/src/pages/settings/SettingsWorkspaceMembers.tsx index 24c1bc9ca..64679d1e2 100644 --- a/front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -36,11 +36,11 @@ export const SettingsWorkspaceMembers = () => { const { objects: workspaceMembers } = useFindManyObjectRecords({ - objectNamePlural: 'workspaceMembersV2', + objectNamePlural: 'workspaceMembers', }); const { deleteOneObject: deleteOneWorkspaceMember } = useDeleteOneObjectRecord({ - objectNameSingular: 'workspaceMemberV2', + objectNameSingular: 'workspaceMember', }); const currentWorkspace = useRecoilValue(currentWorkspaceState); diff --git a/front/src/pages/settings/data-model/SettingsNewObject.tsx b/front/src/pages/settings/data-model/SettingsNewObject.tsx index 505a7e202..62e2544be 100644 --- a/front/src/pages/settings/data-model/SettingsNewObject.tsx +++ b/front/src/pages/settings/data-model/SettingsNewObject.tsx @@ -19,7 +19,6 @@ import { H2Title } from '@/ui/display/typography/components/H2Title'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; -import { ViewType } from '@/views/types/ViewType'; export const SettingsNewObject = () => { const navigate = useNavigate(); @@ -33,7 +32,7 @@ export const SettingsNewObject = () => { } = useObjectMetadataItemForSettings(); const { createOneObject: createOneView } = useCreateOneObjectRecord({ - objectNameSingular: 'viewV2', + objectNameSingular: 'view', }); const [ @@ -79,12 +78,6 @@ export const SettingsNewObject = () => { icon: customFormValues.icon, }); - await createOneView?.({ - objectMetadataId: createdObject.data?.createOneObject.id, - type: ViewType.Table, - name: `All ${customFormValues.labelPlural}`, - }); - navigate( createdObject.data?.createOneObject.isActive ? `/settings/objects/${getObjectSlug( diff --git a/front/src/pages/settings/data-model/SettingsObjectDetail.tsx b/front/src/pages/settings/data-model/SettingsObjectDetail.tsx index c00fc4e55..bdf0017c8 100644 --- a/front/src/pages/settings/data-model/SettingsObjectDetail.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectDetail.tsx @@ -54,10 +54,10 @@ export const SettingsObjectDetail = () => { if (!activeObjectMetadataItem) return null; const activeMetadataFields = activeObjectMetadataItem.fields.filter( - (metadataField) => metadataField.isActive, + (metadataField) => metadataField.isActive && !metadataField.isSystem, ); const disabledMetadataFields = activeObjectMetadataItem.fields.filter( - (metadataField) => !metadataField.isActive, + (metadataField) => !metadataField.isActive && !metadataField.isSystem, ); const handleDisable = async () => { diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx index 50aecad7f..8e9327fbb 100644 --- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx @@ -54,7 +54,7 @@ export const SettingsObjectNewFieldStep2 = () => { initForm({ relation: { field: { icon: activeObjectMetadataItem.icon }, - objectMetadataId: findObjectMetadataItemByNamePlural('peopleV2')?.id, + objectMetadataId: findObjectMetadataItemByNamePlural('people')?.id, }, }); }, [ @@ -69,11 +69,11 @@ export const SettingsObjectNewFieldStep2 = () => { const [relationObjectViews, setRelationObjectViews] = useState([]); const { createOneObject: createOneViewField } = useCreateOneObjectRecord({ - objectNameSingular: 'viewFieldV2', + objectNameSingular: 'viewField', }); useFindManyObjectRecords({ - objectNamePlural: 'viewsV2', + objectNamePlural: 'views', filter: { type: { eq: ViewType.Table }, objectMetadataId: { eq: activeObjectMetadataItem?.id }, @@ -88,7 +88,7 @@ export const SettingsObjectNewFieldStep2 = () => { }); useFindManyObjectRecords({ - objectNamePlural: 'viewsV2', + objectNamePlural: 'views', skip: !formValues.relation?.objectMetadataId, filter: { type: { eq: ViewType.Table }, diff --git a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx index 1a6c2d9cc..026b921ca 100644 --- a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx +++ b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx @@ -13,6 +13,7 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain import { ApiKeyInput } from '@/settings/developers/components/ApiKeyInput'; import { useGeneratedApiKeys } from '@/settings/developers/hooks/useGeneratedApiKeys'; import { generatedApiKeyFamilyState } from '@/settings/developers/states/generatedApiKeyFamilyState'; +import { ApiKey } from '@/settings/developers/types/ApiKey'; import { computeNewExpirationDate } from '@/settings/developers/utils/compute-new-expiration-date'; import { formatExpiration } from '@/settings/developers/utils/format-expiration'; import { IconRepeat, IconSettings, IconTrash } from '@/ui/display/icon'; @@ -22,7 +23,7 @@ import { TextInput } from '@/ui/input/components/TextInput'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; -import { ApiKey, useGenerateOneApiKeyTokenMutation } from '~/generated/graphql'; +import { useGenerateApiKeyTokenMutation } from '~/generated/graphql'; const StyledInfo = styled.span` color: ${({ theme }) => theme.font.color.light}; @@ -48,18 +49,18 @@ export const SettingsDevelopersApiKeyDetail = () => { ); const { performOptimisticEvict } = useOptimisticEvict(); - const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation(); + const [generateOneApiKeyToken] = useGenerateApiKeyTokenMutation(); const { createOneObject: createOneApiKey } = useCreateOneObjectRecord( { - objectNameSingular: 'apiKeyV2', + objectNameSingular: 'apiKey', }, ); const { updateOneObject: updateApiKey } = useUpdateOneObjectRecord({ - objectNameSingular: 'apiKeyV2', + objectNameSingular: 'apiKey', }); const { object: apiKeyData } = useFindOneObjectRecord({ - objectNameSingular: 'apiKeyV2', + objectNameSingular: 'apiKey', objectRecordId: apiKeyId, }); @@ -68,7 +69,7 @@ export const SettingsDevelopersApiKeyDetail = () => { idToUpdate: apiKeyId, input: { revokedAt: DateTime.now().toString() }, }); - performOptimisticEvict('ApiKeyV2', 'id', apiKeyId); + performOptimisticEvict('ApiKey', 'id', apiKeyId); if (redirect) { navigate('/settings/developers/api-keys'); } @@ -89,16 +90,13 @@ export const SettingsDevelopersApiKeyDetail = () => { const tokenData = await generateOneApiKeyToken({ variables: { - data: { - id: newApiKey.id, - expiresAt: newApiKey.expiresAt, - name: newApiKey.name, // TODO update typing to remove useless name param here - }, + apiKeyId: newApiKey.id, + expiresAt: newApiKey?.expiresAt, }, }); return { id: newApiKey.id, - token: tokenData.data?.generateApiKeyV2Token.token, + token: tokenData.data?.generateApiKeyToken.token, }; }; diff --git a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeys.tsx b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeys.tsx index 7d3ea89b7..c24ee7185 100644 --- a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeys.tsx +++ b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeys.tsx @@ -45,14 +45,14 @@ export const SettingsDevelopersApiKeys = () => { const [apiKeys, setApiKeys] = useState>([]); const { registerOptimisticEffect } = useOptimisticEffect({ - objectNameSingular: 'apiKeyV2', + objectNameSingular: 'apiKey', }); const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ - objectNameSingular: 'apiKeyV2', + objectNameSingular: 'apiKey', }); const filter = { revokedAt: { eq: null } }; useFindManyObjectRecords({ - objectNamePlural: 'apiKeysV2', + objectNamePlural: 'apiKeys', filter, onCompleted: (data) => { setApiKeys( @@ -66,7 +66,7 @@ export const SettingsDevelopersApiKeys = () => { ); if (foundObjectMetadataItem) { registerOptimisticEffect({ - variables: { filter }, + variables: { filter, first: 30, orderBy: {} }, definition: getRecordOptimisticEffectDefinition({ objectMetadataItem: foundObjectMetadataItem, }), diff --git a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx index b6e2031e2..e34f18fda 100644 --- a/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx +++ b/front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx @@ -8,6 +8,7 @@ import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderCon import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { ExpirationDates } from '@/settings/developers/constants/expirationDates'; import { useGeneratedApiKeys } from '@/settings/developers/hooks/useGeneratedApiKeys'; +import { ApiKey } from '@/settings/developers/types/ApiKey'; import { IconSettings } from '@/ui/display/icon'; import { H2Title } from '@/ui/display/typography/components/H2Title'; import { Select } from '@/ui/input/components/Select'; @@ -15,10 +16,10 @@ import { TextInput } from '@/ui/input/components/TextInput'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; -import { ApiKey, useGenerateOneApiKeyTokenMutation } from '~/generated/graphql'; +import { useGenerateApiKeyTokenMutation } from '~/generated/graphql'; export const SettingsDevelopersApiKeysNew = () => { - const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation(); + const [generateOneApiKeyToken] = useGenerateApiKeyTokenMutation(); const navigate = useNavigate(); const setGeneratedApi = useGeneratedApiKeys(); const [formValues, setFormValues] = useState<{ @@ -30,14 +31,12 @@ export const SettingsDevelopersApiKeysNew = () => { }); const { createOneObject: createOneApiKey } = useCreateOneObjectRecord( - { - objectNameSingular: 'apiKeyV2', - }, + { objectNameSingular: 'apiKey' }, ); const onSave = async () => { - const expiresAt = formValues.expirationDate - ? DateTime.now().plus({ days: formValues.expirationDate }).toString() - : null; + const expiresAt = DateTime.now() + .plus({ days: formValues.expirationDate ?? 30 }) + .toString(); const newApiKey = await createOneApiKey?.({ name: formValues.name, expiresAt, @@ -49,15 +48,12 @@ export const SettingsDevelopersApiKeysNew = () => { const tokenData = await generateOneApiKeyToken({ variables: { - data: { - id: newApiKey.id, - expiresAt: newApiKey.expiresAt, - name: newApiKey.name, // TODO update typing to remove useless name param here - }, + apiKeyId: newApiKey.id, + expiresAt: expiresAt, }, }); - if (tokenData.data?.generateApiKeyV2Token) { - setGeneratedApi(newApiKey.id, tokenData.data.generateApiKeyV2Token.token); + if (tokenData.data?.generateApiKeyToken) { + setGeneratedApi(newApiKey.id, tokenData.data.generateApiKeyToken.token); navigate(`/settings/developers/api-keys/${newApiKey.id}`); } }; diff --git a/front/src/pages/tasks/tasks-filter-definitions.tsx b/front/src/pages/tasks/tasks-filter-definitions.tsx index 2349693df..75d637871 100644 --- a/front/src/pages/tasks/tasks-filter-definitions.tsx +++ b/front/src/pages/tasks/tasks-filter-definitions.tsx @@ -1,13 +1,13 @@ -import { IconUser, IconUserCircle } from '@/ui/display/icon'; +import { Activity } from '@/activities/types/Activity'; +import { IconUserCircle } from '@/ui/display/icon'; import { FilterDefinitionByEntity } from '@/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity'; import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect'; -import { Activity } from '~/generated/graphql'; export const tasksFilterDefinitions: FilterDefinitionByEntity[] = [ { fieldMetadataId: 'assigneeId', label: 'Assignee', - Icon: IconUser, + iconName: 'IconUser', type: 'ENTITY', entitySelectComponent: , selectAllLabel: 'All assignees', diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index 6622e37ca..1ccbebd24 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -3,143 +3,19 @@ import { graphql } from 'msw'; import { CREATE_EVENT } from '@/analytics/graphql/queries/createEvent'; import { GET_CLIENT_CONFIG } from '@/client-config/graphql/queries/getClientConfig'; -import { INSERT_ONE_COMPANY } from '@/companies/graphql/mutations/insertOneCompany'; -import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies'; import { FIND_MANY_METADATA_OBJECTS } from '@/object-metadata/graphql/queries'; -import { INSERT_ONE_PERSON } from '@/people/graphql/mutations/insertOnePerson'; -import { UPDATE_ONE_PERSON } from '@/people/graphql/mutations/updateOnePerson'; -import { GET_PEOPLE } from '@/people/graphql/queries/getPeople'; -import { GET_PERSON } from '@/people/graphql/queries/getPerson'; -import { SEARCH_ACTIVITY_QUERY } from '@/search/graphql/queries/searchActivityQuery'; -import { SEARCH_COMPANY_QUERY } from '@/search/graphql/queries/searchCompanyQuery'; -import { SEARCH_PEOPLE_QUERY } from '@/search/graphql/queries/searchPeopleQuery'; -import { SEARCH_USER_QUERY } from '@/search/graphql/queries/searchUserQuery'; -import { GET_API_KEY } from '@/settings/developers/graphql/queries/getApiKey'; -import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys'; import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser'; -import { - GetCompaniesQuery, - GetPeopleQuery, - GetPersonQuery, - SearchActivityQuery, - SearchCompanyQuery, - SearchPeopleQuery, - SearchUserQuery, -} from '~/generated/graphql'; -import { mockedApiKeys } from '~/testing/mock-data/api-keys'; -import { mockedActivities } from './mock-data/activities'; -import { - mockedCompaniesData, - mockedEmptyCompanyData, -} from './mock-data/companies'; import { mockedObjectMetadataItems } from './mock-data/metadata'; -import { mockedEmptyPersonData, mockedPeopleData } from './mock-data/people'; import { mockedUsersData } from './mock-data/users'; import { mockedViewFieldsData } from './mock-data/view-fields'; import { mockedViewsData } from './mock-data/views'; -import { - fetchOneFromData, - filterAndSortData, - updateOneFromData, -} from './mock-data'; -import { createEvent } from '@storybook/testing-library'; const metadataGraphql = graphql.link( `${process.env.REACT_APP_SERVER_BASE_URL}/metadata`, ); export const graphqlMocks = [ - graphql.query(getOperationName(GET_COMPANIES) ?? '', (req, res, ctx) => { - const returnedMockedData = filterAndSortData< - GetCompaniesQuery['companies'][0] - >( - mockedCompaniesData, - req.variables.where, - req.variables.orderBy, - req.variables.limit, - ); - return res( - ctx.data({ - companies: returnedMockedData, - }), - ); - }), - graphql.query( - getOperationName(SEARCH_COMPANY_QUERY) ?? '', - (req, res, ctx) => { - const returnedMockedData = filterAndSortData< - SearchCompanyQuery['searchResults'][0] - >( - mockedCompaniesData, - req.variables.where, - !req.variables.orderBy || Array.isArray(req.variables.orderBy) - ? req.variables.orderBy - : [req.variables.orderBy], - req.variables.limit, - ); - return res( - ctx.data({ - searchResults: returnedMockedData, - }), - ); - }, - ), - graphql.query( - getOperationName(SEARCH_PEOPLE_QUERY) ?? '', - (req, res, ctx) => { - const returnedMockedData = filterAndSortData< - SearchPeopleQuery['searchResults'][0] - >( - mockedPeopleData, - req.variables.where, - !req.variables.orderBy || Array.isArray(req.variables.orderBy) - ? req.variables.orderBy - : [req.variables.orderBy], - req.variables.limit, - ); - return res( - ctx.data({ - searchResults: returnedMockedData, - }), - ); - }, - ), - graphql.query(getOperationName(SEARCH_USER_QUERY) ?? '', (req, res, ctx) => { - const returnedMockedData = filterAndSortData< - SearchUserQuery['searchResults'][0] - >( - mockedUsersData, - req.variables.where, - req.variables.orderBy, - req.variables.limit, - ); - return res( - ctx.data({ - searchResults: returnedMockedData, - }), - ); - }), - graphql.query( - getOperationName(SEARCH_ACTIVITY_QUERY) ?? '', - (req, res, ctx) => { - const returnedMockedData = filterAndSortData< - SearchActivityQuery['searchResults'][0] - >( - mockedActivities, - req.variables.where, - !req.variables.orderBy || Array.isArray(req.variables.orderBy) - ? req.variables.orderBy - : [req.variables.orderBy], - req.variables.limit, - ); - return res( - ctx.data({ - searchResults: returnedMockedData, - }), - ); - }, - ), graphql.query(getOperationName(GET_CURRENT_USER) ?? '', (req, res, ctx) => { return res( ctx.data({ @@ -147,62 +23,6 @@ export const graphqlMocks = [ }), ); }), - graphql.query(getOperationName(GET_PERSON) ?? '', (req, res, ctx) => { - const returnedMockedData = fetchOneFromData< - GetPersonQuery['findUniquePerson'] - >(mockedPeopleData, req.variables.id); - return res( - ctx.data({ - findUniquePerson: returnedMockedData, - }), - ); - }), - graphql.query(getOperationName(GET_PEOPLE) ?? '', (req, res, ctx) => { - const returnedMockedData = filterAndSortData( - mockedPeopleData, - req.variables.where, - req.variables.orderBy, - req.variables.limit, - ); - return res( - ctx.data({ - people: returnedMockedData, - }), - ); - }), - graphql.mutation( - getOperationName(UPDATE_ONE_PERSON) ?? '', - (req, res, ctx) => { - const updatedCompanyId = req.variables.data?.company?.connect?.id; - const updatedCompany = mockedCompaniesData.find( - ({ id }) => id === updatedCompanyId, - ); - const updatedCompanyData = updatedCompany - ? { - companyId: updatedCompany.id, - company: { - id: updatedCompany.id, - name: updatedCompany.name, - domainName: updatedCompany.domainName, - __typename: 'Company', - }, - } - : {}; - return res( - ctx.data({ - updateOnePerson: { - ...updateOneFromData( - mockedPeopleData, - req.variables.where.id, - req.variables, - ), - ...updatedCompanyData, - }, - }), - ); - }, - ), - graphql.mutation(getOperationName(CREATE_EVENT) ?? '', (req, res, ctx) => { return res( ctx.data({ @@ -228,55 +48,13 @@ export const graphqlMocks = [ }), ); }), - - graphql.query(getOperationName(GET_API_KEY) ?? '', (req, res, ctx) => { - return res( - ctx.data({ - findManyApiKey: [mockedApiKeys[0]], - }), - ); - }), - graphql.query(getOperationName(GET_API_KEYS) ?? '', (req, res, ctx) => { - return res( - ctx.data({ - findManyApiKey: mockedApiKeys, - }), - ); - }), - - graphql.mutation( - getOperationName(INSERT_ONE_COMPANY) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - createOneCompany: { - ...mockedEmptyCompanyData, - ...req.variables.data, - }, - }), - ); - }, - ), - graphql.mutation( - getOperationName(INSERT_ONE_PERSON) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - createOnePerson: { - ...mockedEmptyPersonData, - ...req.variables.data, - }, - }), - ); - }, - ), metadataGraphql.query( getOperationName(FIND_MANY_METADATA_OBJECTS) ?? '', (req, res, ctx) => { return res(ctx.data({ objects: mockedObjectMetadataItems })); }, ), - graphql.query('FindManyViewsV2', (req, res, ctx) => { + graphql.query('FindManyViews', (req, res, ctx) => { const objectMetadataId = req.variables.filter.objectMetadataId.eq; const viewType = req.variables.filter.type.eq; @@ -303,7 +81,7 @@ export const graphqlMocks = [ }), ); }), - graphql.query('FindManyViewFieldsV2', (req, res, ctx) => { + graphql.query('FindManyViewFields', (req, res, ctx) => { const viewId = req.variables.filter.view.eq; return res( diff --git a/front/src/testing/mock-data/activities.ts b/front/src/testing/mock-data/activities.ts index f8bf154ab..34f7c45c1 100644 --- a/front/src/testing/mock-data/activities.ts +++ b/front/src/testing/mock-data/activities.ts @@ -1,8 +1,9 @@ import { Activity } from '@/activities/types/Activity'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { Comment } from '@/activities/types/Comment'; +import { Company } from '@/companies/types/Company'; +import { Person } from '@/people/types/Person'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { Company, Person } from '~/generated/graphql'; type MockedActivity = Pick< Activity, @@ -32,7 +33,7 @@ type MockedActivity = Pick< | 'companyId' > & { activity: Pick; - person?: Pick | null; + person?: Pick | null; company?: Pick | null; } >; @@ -178,7 +179,10 @@ export const mockedActivities: Array = [ personId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', // Alexandre person: { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', - displayName: 'Alexandre Test', + name: { + firstName: 'Alexandre', + lastName: 'Test', + }, avatarUrl: '', }, company: null, @@ -200,7 +204,10 @@ export const mockedActivities: Array = [ company: null, person: { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', - displayName: "Jean d'Eau", + name: { + firstName: 'Jean', + lastName: "d'Eau", + }, avatarUrl: '', }, activityId: '89bb825c-171e-4bcc-9cf7-43448d6fb278a', diff --git a/front/src/testing/mock-data/api-keys.ts b/front/src/testing/mock-data/api-keys.ts index dd8b41c63..ca17413d5 100644 --- a/front/src/testing/mock-data/api-keys.ts +++ b/front/src/testing/mock-data/api-keys.ts @@ -1,8 +1,8 @@ -import { ApiKey } from '~/generated/graphql'; +import { ApiKey } from '@/settings/developers/types/ApiKey'; type MockedApiKey = Pick< ApiKey, - 'id' | 'name' | 'createdAt' | 'updatedAt' | 'expiresAt' | '__typename' + 'id' | 'name' | 'createdAt' | 'updatedAt' | 'expiresAt' >; export const mockedApiKeys: Array = [ { @@ -11,15 +11,13 @@ export const mockedApiKeys: Array = [ createdAt: '2023-04-26T10:12:42.33625+00:00', updatedAt: '2023-04-26T10:23:42.33625+00:00', expiresAt: '2100-11-06T23:59:59.825Z', - __typename: 'ApiKey', }, { id: 'f7c6d736-8fcd-4e9c-ab99-28f6a9031571', name: 'Gmail Integration', createdAt: '2023-04-26T10:12:42.33625+00:00', updatedAt: '2023-04-26T10:23:42.33625+00:00', - expiresAt: null, - __typename: 'ApiKey', + expiresAt: '2100-11-06T23:59:59.825Z', }, { id: 'f7c6d736-8fcd-4e9c-ab99-28f6a9031572', @@ -27,6 +25,5 @@ export const mockedApiKeys: Array = [ createdAt: '2023-04-26T10:12:42.33625+00:00', updatedAt: '2023-04-26T10:23:42.33625+00:00', expiresAt: '2022-11-06T23:59:59.825Z', - __typename: 'ApiKey', }, ]; diff --git a/front/src/testing/mock-data/companies.ts b/front/src/testing/mock-data/companies.ts index 7e167ae2a..880ab5223 100644 --- a/front/src/testing/mock-data/companies.ts +++ b/front/src/testing/mock-data/companies.ts @@ -1,4 +1,6 @@ -import { Company, Favorite, User } from '~/generated/graphql'; +import { Company } from '@/companies/types/Company'; +import { Favorite } from '@/favorites/types/Favorite'; +import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { mockedUsersData } from './users'; @@ -7,7 +9,6 @@ type MockedCompany = Pick< | 'id' | 'name' | 'domainName' - | '__typename' | 'createdAt' | 'address' | 'employees' @@ -15,19 +16,9 @@ type MockedCompany = Pick< | 'xUrl' | 'annualRecurringRevenue' | 'idealCustomerProfile' - | '_activityCount' | 'accountOwnerId' > & { - accountOwner: Pick< - User, - | 'id' - | 'email' - | 'displayName' - | 'avatarUrl' - | '__typename' - | 'firstName' - | 'lastName' - > | null; + accountOwner: Pick | null; Favorite: Pick | null; }; @@ -39,23 +30,26 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:08:54.724515+00:00', address: '17 rue de clignancourt', employees: 12, - linkedinUrl: 'https://www.linkedin.com/company/airbnb/', - xUrl: 'https://twitter.com/airbnb', - annualRecurringRevenue: 500000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/airbnb/', + label: 'https://www.linkedin.com/company/airbnb/', + }, + xUrl: { + url: 'https://twitter.com/airbnb', + label: 'https://twitter.com/airbnb', + }, + annualRecurringRevenue: { amountMicros: 5000000, currencyCode: 'USD' }, idealCustomerProfile: true, - _activityCount: 1, Favorite: null, accountOwnerId: mockedUsersData[0].id, accountOwner: { - email: 'charles@test.com', - displayName: 'Charles Test', - firstName: 'Charles', - lastName: 'Test', + name: { + firstName: 'Charles', + lastName: 'Test', + }, avatarUrl: null, id: mockedUsersData[0].id, - __typename: 'User', }, - __typename: 'Company', }, { id: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae', @@ -64,14 +58,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:12:42.33625+00:00', address: '', employees: 1, - linkedinUrl: 'https://www.linkedin.com/company/aircall/', - xUrl: 'https://twitter.com/aircall', - annualRecurringRevenue: 50000, + accountOwnerId: null, + linkedinUrl: { + url: 'https://www.linkedin.com/company/aircall/', + label: 'https://www.linkedin.com/company/aircall/', + }, + xUrl: { + url: 'https://twitter.com/aircall', + label: 'https://twitter.com/aircall', + }, + annualRecurringRevenue: { amountMicros: 500000, currencyCode: 'USD' }, idealCustomerProfile: false, - _activityCount: 1, accountOwner: null, Favorite: null, - __typename: 'Company', }, { id: 'a674fa6c-1455-4c57-afaf-dd5dc086361d', @@ -80,14 +79,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:10:32.530184+00:00', address: '', employees: 1, - linkedinUrl: 'https://www.linkedin.com/company/algolia/', - xUrl: 'https://twitter.com/algolia', - annualRecurringRevenue: 500000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/algolia/', + label: 'https://www.linkedin.com/company/algolia/', + }, + xUrl: { + url: 'https://twitter.com/algolia', + label: 'https://twitter.com/algolia', + }, + annualRecurringRevenue: { amountMicros: 5000000, currencyCode: 'USD' }, idealCustomerProfile: true, - _activityCount: 1, accountOwner: null, Favorite: null, - __typename: 'Company', + accountOwnerId: null, }, { id: 'b1cfd51b-a831-455f-ba07-4e30671e1dc3', @@ -96,14 +100,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-03-21T06:30:25.39474+00:00', address: '', employees: 10, - linkedinUrl: 'https://www.linkedin.com/company/apple/', - xUrl: 'https://twitter.com/apple', - annualRecurringRevenue: 5000000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/apple/', + label: 'https://www.linkedin.com/company/apple/', + }, + xUrl: { + url: 'https://twitter.com/apple', + label: 'https://twitter.com/apple', + }, + annualRecurringRevenue: { amountMicros: 1000000, currencyCode: 'USD' }, idealCustomerProfile: false, - _activityCount: 0, accountOwner: null, Favorite: null, - __typename: 'Company', + accountOwnerId: null, }, { id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb', @@ -112,14 +121,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:13:29.712485+00:00', address: '10 rue de la Paix', employees: 1, - linkedinUrl: 'https://www.linkedin.com/company/qonto/', - xUrl: 'https://twitter.com/qonto', - annualRecurringRevenue: 500000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/qonto/', + label: 'https://www.linkedin.com/company/qonto/', + }, + xUrl: { + url: 'https://twitter.com/qonto', + label: 'https://twitter.com/qonto', + }, + annualRecurringRevenue: { amountMicros: 5000000, currencyCode: 'USD' }, idealCustomerProfile: false, - _activityCount: 2, accountOwner: null, Favorite: null, - __typename: 'Company', + accountOwnerId: null, }, { id: '9d162de6-cfbf-4156-a790-e39854dcd4eb', @@ -128,14 +142,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:09:25.656555+00:00', address: '', employees: 1, - linkedinUrl: 'https://www.linkedin.com/company/facebook/', - xUrl: 'https://twitter.com/facebook', - annualRecurringRevenue: 5000000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/facebook/', + label: 'https://www.linkedin.com/company/facebook/', + }, + xUrl: { + url: 'https://twitter.com/facebook', + label: 'https://twitter.com/facebook', + }, + annualRecurringRevenue: { amountMicros: 5000000, currencyCode: 'USD' }, idealCustomerProfile: true, - _activityCount: 13, accountOwner: null, Favorite: null, - __typename: 'Company', + accountOwnerId: null, }, { id: '9d162de6-cfbf-4156-a790-e39854dcd4ef', @@ -144,14 +163,19 @@ export const mockedCompaniesData: Array = [ createdAt: '2023-04-26T10:09:25.656555+00:00', address: '', employees: 1, - linkedinUrl: 'https://www.linkedin.com/company/sequoia/', - xUrl: 'https://twitter.com/sequoia', - annualRecurringRevenue: 500000, + linkedinUrl: { + url: 'https://www.linkedin.com/company/sequoia/', + label: 'https://www.linkedin.com/company/sequoia/', + }, + xUrl: { + url: 'https://twitter.com/sequoia', + label: 'https://twitter.com/sequoia', + }, + annualRecurringRevenue: { amountMicros: 5000000, currencyCode: 'USD' }, idealCustomerProfile: true, - _activityCount: 1, accountOwner: null, Favorite: null, - __typename: 'Company', + accountOwnerId: null, }, ]; diff --git a/front/src/testing/mock-data/index.ts b/front/src/testing/mock-data/index.ts index 0ec54e945..a2099efa2 100644 --- a/front/src/testing/mock-data/index.ts +++ b/front/src/testing/mock-data/index.ts @@ -1,15 +1,15 @@ import { isObject, isString } from '@sniptt/guards'; import { GraphQLVariables } from 'msw'; -import { - CompanyOrderByWithRelationInput, - PersonOrderByWithRelationInput, - StringFilter, - UserOrderByWithRelationInput, -} from '~/generated/graphql'; - import { isDefined } from '../../utils/isDefined'; +type StringFilter = { + equals?: string; + contains?: string; + in?: Array; + notIn?: Array; +}; + const filterData = ( data: Array, where: Record, @@ -90,11 +90,7 @@ const filterData = ( export const filterAndSortData = ( data: Array, where?: Record, - orderBy?: Array< - PersonOrderByWithRelationInput & - CompanyOrderByWithRelationInput & - UserOrderByWithRelationInput - >, + orderBy?: Array, limit?: number, ): Array => { let filteredData = data; diff --git a/front/src/testing/mock-data/metadata.ts b/front/src/testing/mock-data/metadata.ts index ab06463e9..50032bc85 100644 --- a/front/src/testing/mock-data/metadata.ts +++ b/front/src/testing/mock-data/metadata.ts @@ -188,8 +188,8 @@ export const mockedObjectMetadataItems = { node: { id: 'b25eb5e6-9fdc-4df2-a039-40ccea4c8032', dataSourceId: '', - nameSingular: 'viewV2', - namePlural: 'viewsV2', + nameSingular: 'view', + namePlural: 'views', labelSingular: 'View', labelPlural: 'Views', description: '(System) Views', @@ -269,8 +269,8 @@ export const mockedObjectMetadataItems = { node: { id: 'c419540f-ff6e-47bf-9d87-3aa366afd8e4', dataSourceId: '', - nameSingular: 'viewFieldV2', - namePlural: 'viewFieldsV2', + nameSingular: 'viewField', + namePlural: 'viewFields', labelSingular: 'View Field', labelPlural: 'View Fields', description: '(System) View Fields', diff --git a/front/src/testing/mock-data/people.ts b/front/src/testing/mock-data/people.ts index 98e13d100..b459b9b25 100644 --- a/front/src/testing/mock-data/people.ts +++ b/front/src/testing/mock-data/people.ts @@ -1,4 +1,5 @@ -import { Company, Person } from '~/generated/graphql'; +import { Company } from '@/companies/types/Company'; +import { Person } from '@/people/types/Person'; type RequiredAndNotNull = { [P in keyof T]-?: Exclude; @@ -8,35 +9,37 @@ type MockedPerson = RequiredAndNotNull< Pick< Person, | 'id' - | 'firstName' - | 'lastName' - | 'displayName' - | 'linkedinUrl' - | 'xUrl' + | 'name' + | 'linkedinLink' + | 'xLink' | 'jobTitle' | 'email' - | '__typename' | 'phone' | 'city' | 'avatarUrl' - | '_activityCount' | 'createdAt' | 'companyId' > & { - company: Pick; + company: Pick; } >; export const mockedPeopleData: MockedPerson[] = [ { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', - __typename: 'Person', - firstName: 'Alexandre', - lastName: 'Prot', - displayName: 'Alexandre Prot', + name: { + firstName: 'Alexandre', + lastName: 'Prot', + }, email: 'alexandre@qonto.com', - linkedinUrl: 'https://www.linkedin.com/in/alexandreprot/', - xUrl: 'https://twitter.com/alexandreprot', + linkedinLink: { + url: 'https://www.linkedin.com/in/alexandreprot/', + label: 'https://www.linkedin.com/in/alexandreprot/', + }, + xLink: { + url: 'https://twitter.com/alexandreprot', + label: 'https://twitter.com/alexandreprot', + }, avatarUrl: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADwAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIADwAPAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAoHCBUSFRgSEhUYGBgYGBgYGBgYGBgYGBgYGBgZGRgaGBgcIS4lHB4rIRgYJjgmKy8xNTU1GiQ7QDszPy40NTH/2wBDAQwMDBAPEBwSEh40ISQkMTQ0NjQxNDQ2NDQ0NDQ0MTQ0NDQ0NDQ0NDQ0NDE0NDQ0NDQ0PzQ0NDQ0NDQ0NDQ0NDT/3QAEAAT/2gAMAwEAAhEDEQA/AOtApcUtLWpkJiub1TxlawHaC0pGM+WAQM9ixIGfal8bas8ESwwjMs5KLjqq4+ZgO55A/wCBe1cDceGLxVyYCysOqfNjnoQOQfzqJTs7GkYNq53uleLba5KoCyO2fldcDI7b/uk/jW8VrxSSJowQ6OPqhwPxxXofw81Mz27IxyYmCjPUKRlee/f8qIyuKUbHT4oxT6SrIP/Q6+ilorUyOJ147tTjzjbFArEk4A3M/wD9au20u4Rl+R1bHXawJFZ89vGbgM4GWj2898HI/rTbXSIo5lkj5fpuyWO3upPccVx1H7zO6nH3EizroBjbIB/KuL+H0eJ7soMIBGPx3Ocfkf1rUbRPPzM0jYYtv3MTjkjCDOF7flS+C7Hyo5XznzZSRxjhAEH16E1VH4ia/wAJ0dFFLXUcZ//R7HFIRWXq/iS1teJZRu6hEG9+/JC9Bx1OK43VPiM7ZW2iCejyHc34Ivyj8zWpmdtqkiq8QfoxYe3bGfryKbNb8HEzIwyUYKCQCOnbP0IPasPwtKb+3JlcvICUck8hgSVYAcLkFSMelSya3LbL5U8Bl28K67efTcD0P0rjm7zZ3UtIocsZEQhDEu5IXrnaTks+Scnqa3LWBY1EaDCqMDkn9TXCSapNBIb+ZR0ZRGSQArY+Vf8Aa4GD9a6XRvE9tdYCuFc/8s3IVvw7MPcVtRStcwrybZuilpopa2Oc/9Ly0J/kUBaVTS1sZl7SNWmtH8yB9pPBBGVYZzhl7j9R611T/ERmHzWqFvXzDt+uNuevb9a4eiolCMtyozlHYu6zrE12QZSAF+6ijCjPfHc+5/Ss3bUlFUkkrITbbuze8P8Aiqe0IDMZIsjcjEsQOh8ticqcduhx26163FKGUMpyGAII6EEZBrwQmvX/AAFIXso93O0ug/3Vdgo/KmI//9k=', jobTitle: 'CEO', @@ -45,21 +48,22 @@ export const mockedPeopleData: MockedPerson[] = [ id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb', name: 'Qonto', domainName: 'qonto.com', - __typename: 'Company', }, phone: '06 12 34 56 78', - _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', city: 'Paris', }, { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', - __typename: 'Person', - firstName: 'John', - lastName: 'Doe', - displayName: 'John Doe', - linkedinUrl: 'https://www.linkedin.com/in/johndoe/', - xUrl: 'https://twitter.com/johndoe', + name: { firstName: 'John', lastName: 'Doe' }, + linkedinLink: { + url: 'https://www.linkedin.com/in/johndoe/', + label: 'https://www.linkedin.com/in/johndoe/', + }, + xLink: { + url: 'https://twitter.com/johndoe', + label: 'https://twitter.com/johndoe', + }, avatarUrl: '', jobTitle: 'CTO', email: 'john@linkedin.com', @@ -68,21 +72,25 @@ export const mockedPeopleData: MockedPerson[] = [ id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e', name: 'LinkedIn', domainName: 'linkedin.com', - __typename: 'Company', }, phone: '06 12 34 56 78', - _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', city: 'Paris', }, { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6f', - __typename: 'Person', - firstName: 'Jane', - lastName: 'Doe', - displayName: 'Jane Doe', - linkedinUrl: 'https://www.linkedin.com/in/janedoe/', - xUrl: 'https://twitter.com/janedoe', + name: { + firstName: 'Jane', + lastName: 'Doe', + }, + linkedinLink: { + url: 'https://www.linkedin.com/in/janedoe/', + label: 'https://www.linkedin.com/in/janedoe/', + }, + xLink: { + url: 'https://twitter.com/janedoe', + label: 'https://twitter.com/janedoe', + }, avatarUrl: '', jobTitle: 'Investor', email: 'jane@sequoiacap.com', @@ -91,22 +99,26 @@ export const mockedPeopleData: MockedPerson[] = [ id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g', name: 'Sequoia', domainName: 'sequoiacap.com', - __typename: 'Company', }, phone: '06 12 34 56 78', - _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', city: 'Paris', }, { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6h', - __typename: 'Person', - firstName: 'Janice', - lastName: 'Dane', - displayName: 'Janice Dane', + name: { + firstName: 'Janice', + lastName: 'Dane', + }, email: 'janice@facebook.com', - linkedinUrl: 'https://www.linkedin.com/in/janicedane/', - xUrl: 'https://twitter.com/janicedane', + linkedinLink: { + url: 'https://www.linkedin.com/in/janicedane/', + label: 'https://www.linkedin.com/in/janicedane/', + }, + xLink: { + url: 'https://twitter.com/janicedane', + label: 'https://twitter.com/janicedane', + }, avatarUrl: '', jobTitle: 'CEO', companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i', @@ -114,10 +126,8 @@ export const mockedPeopleData: MockedPerson[] = [ id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i', name: 'Facebook', domainName: 'facebook.com', - __typename: 'Company', }, phone: '06 12 34 56 78', - _activityCount: 2, createdAt: '2023-04-20T13:20:09.158312+00:00', city: 'Paris', }, diff --git a/front/src/testing/mock-data/pipeline-progress.ts b/front/src/testing/mock-data/pipeline-progress.ts deleted file mode 100644 index 8f03f0923..000000000 --- a/front/src/testing/mock-data/pipeline-progress.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { PipelineProgress, User } from '../../generated/graphql'; - -type MockedPipelineProgress = Pick< - PipelineProgress, - | 'id' - | 'amount' - | 'closeDate' - | 'companyId' - | 'pipelineStageId' - | 'probability' - | 'pointOfContact' - | 'pointOfContactId' - | 'personId' -> & { - accountOwner: Pick< - User, - | 'id' - | 'email' - | 'displayName' - | 'avatarUrl' - | '__typename' - | 'firstName' - | 'lastName' - > | null; -}; - -const accountOwner = { - email: 'charles@test.com', - displayName: 'Charles Test', - firstName: 'Charles', - lastName: 'Test', - id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', -}; - -export const mockedPipelineProgressData: Array = [ - { - id: '0ac8761c-1ad6-11ee-be56-0242ac120002', - amount: 78, - closeDate: '2021-10-01T00:00:00.000Z', - companyId: '0', - accountOwner: accountOwner, - pipelineStageId: 'another-pipeline-stage-1', - probability: null, - pointOfContact: null, - pointOfContactId: null, - personId: null, - }, - { - id: 'fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - companyId: '89bb825c-171e-4bcc-9cf7-43448d6fb278', - pipelineStageId: 'fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - amount: 7, - closeDate: '2021-10-01T00:00:00.000Z', - accountOwner, - probability: null, - pointOfContact: null, - pointOfContactId: null, - personId: null, - }, - { - id: '4a886c90-f4f2-4984-8222-882ebbb905d6', - companyId: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae', - amount: 100, - closeDate: '2021-10-01T00:00:00.000Z', - accountOwner, - pipelineStageId: 'fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - probability: null, - pointOfContact: null, - pointOfContactId: null, - personId: null, - }, -]; diff --git a/front/src/testing/mock-data/pipelines.ts b/front/src/testing/mock-data/pipelines.ts deleted file mode 100644 index 216a36a7f..000000000 --- a/front/src/testing/mock-data/pipelines.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { - Pipeline, - PipelineProgress, - PipelineProgressableType, - PipelineStage, -} from '../../generated/graphql'; - -type MockedPipeline = Pick< - Pipeline, - 'id' | 'name' | 'pipelineProgressableType' | '__typename' -> & { - pipelineStages: Array< - Pick & { - pipelineProgresses: Array< - Pick< - PipelineProgress, - 'id' | 'companyId' | 'amount' | 'closeDate' | '__typename' - > - >; - } - >; -}; - -export const mockedPipelinesData: Array = [ - { - id: 'fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - name: 'Sales pipeline', - pipelineProgressableType: PipelineProgressableType.Company, - pipelineStages: [ - { - id: 'fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - name: 'New', - color: 'red', - position: 0, - pipelineProgresses: [ - { - id: 'fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - companyId: '89bb825c-171e-4bcc-9cf7-43448d6fb278', - amount: null, - closeDate: null, - __typename: 'PipelineProgress', - }, - { - id: '4a886c90-f4f2-4984-8222-882ebbb905d6', - companyId: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae', - amount: null, - closeDate: null, - __typename: 'PipelineProgress', - }, - ], - __typename: 'PipelineStage', - }, - { - id: 'fe256b39-3ec3-4fe4-8998-b76aa0bfb600', - name: 'Screening', - color: 'purple', - position: 1, - pipelineProgresses: [], - __typename: 'PipelineStage', - }, - { - id: 'fe256b39-3ec3-4fe5-8998-b76aa0bfb600', - name: 'Meeting', - color: 'sky', - position: 2, - pipelineProgresses: [], - __typename: 'PipelineStage', - }, - { - id: 'fe256b39-3ec3-4fe6-8998-b76aa0bfb600', - name: 'Proposal', - color: 'turquoise', - position: 3, - pipelineProgresses: [], - __typename: 'PipelineStage', - }, - { - id: 'fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - name: 'Customer', - color: 'yellow', - position: 4, - pipelineProgresses: [], - __typename: 'PipelineStage', - }, - ], - __typename: 'Pipeline', - }, -]; diff --git a/front/src/testing/mock-data/users.ts b/front/src/testing/mock-data/users.ts index fcd426b69..45216033c 100644 --- a/front/src/testing/mock-data/users.ts +++ b/front/src/testing/mock-data/users.ts @@ -1,45 +1,24 @@ -import { - Activity, - Attachment, - ColorScheme, - Company, - User, - UserSettings, - Workspace, - WorkspaceMember, -} from '~/generated/graphql'; +import { Activity } from '@/activities/types/Activity'; +import { Attachment } from '@/attachments/types/Attachment'; +import { Company } from '@/companies/types/Company'; +import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; +import { User, Workspace } from '~/generated/graphql'; type MockedUser = Pick< User, - | 'id' - | 'email' - | 'displayName' - | 'firstName' - | 'lastName' - | 'avatarUrl' - | 'canImpersonate' - | 'supportUserHash' - | '__typename' + 'id' | 'email' | 'firstName' | 'lastName' | 'canImpersonate' | '__typename' > & { - workspaceMember: Pick< - WorkspaceMember, - 'id' | 'allowImpersonation' | '__typename' - > & { + workspaceMember: Pick & { workspace: Pick< Workspace, 'id' | 'displayName' | 'domainName' | 'inviteHash' | 'logo' | '__typename' >; - settings: Pick< - UserSettings, - 'id' | 'colorScheme' | 'locale' | '__typename' - >; assignedActivities: Array; authoredActivities: Array; authoredAttachments: Array; companies: Array; comments: Array; }; - settings: Pick; }; export const avatarUrl = @@ -52,14 +31,10 @@ export const mockedUsersData: Array = [ id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', __typename: 'User', email: 'charles@test.com', - displayName: 'Charles Test', firstName: 'Charles', lastName: 'Test', - avatarUrl: null, canImpersonate: false, - supportUserHash: '', workspaceMember: { - __typename: 'WorkspaceMember', id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', allowImpersonation: true, workspace: { @@ -70,36 +45,21 @@ export const mockedUsersData: Array = [ inviteHash: 'twenty.com-invite-hash', logo: workspaceLogoUrl, }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, authoredAttachments: [], assignedActivities: [], authoredActivities: [], companies: [], comments: [], }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, }, { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6c', __typename: 'User', email: 'felix@test.com', - displayName: 'Felix Test', firstName: 'Felix', lastName: 'Test', canImpersonate: false, - supportUserHash: '', workspaceMember: { - __typename: 'WorkspaceMember', id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', allowImpersonation: true, workspace: { @@ -110,24 +70,12 @@ export const mockedUsersData: Array = [ inviteHash: 'twenty.com-invite-hash', logo: workspaceLogoUrl, }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, authoredAttachments: [], assignedActivities: [], authoredActivities: [], companies: [], comments: [], }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cdt7a', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, }, ]; @@ -136,14 +84,10 @@ export const mockedOnboardingUsersData: Array = [ id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', __typename: 'User', email: 'workspace-onboarding@test.com', - displayName: '', firstName: '', lastName: '', - avatarUrl: null, canImpersonate: false, - supportUserHash: '', workspaceMember: { - __typename: 'WorkspaceMember', id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', allowImpersonation: true, workspace: { @@ -154,37 +98,21 @@ export const mockedOnboardingUsersData: Array = [ inviteHash: 'twenty.com-invite-hash-1', logo: '', }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, authoredAttachments: [], assignedActivities: [], authoredActivities: [], companies: [], comments: [], }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, }, { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', __typename: 'User', email: 'profile-onboarding@test.com', - displayName: '', firstName: '', lastName: '', - avatarUrl: null, canImpersonate: false, - supportUserHash: '', workspaceMember: { - __typename: 'WorkspaceMember', id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', allowImpersonation: true, workspace: { @@ -195,23 +123,11 @@ export const mockedOnboardingUsersData: Array = [ inviteHash: 'twenty.com-invite-hash-2', logo: '', }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, authoredAttachments: [], assignedActivities: [], authoredActivities: [], companies: [], comments: [], }, - settings: { - id: '7dfbc3f7-6e5e-4128-957e-8d86808cde9y', - __typename: 'UserSettings', - locale: 'en', - colorScheme: ColorScheme.System, - }, }, ]; diff --git a/front/src/utils/title-utils.ts b/front/src/utils/title-utils.ts index b7e779cd1..ff18aea44 100644 --- a/front/src/utils/title-utils.ts +++ b/front/src/utils/title-utils.ts @@ -16,10 +16,6 @@ export const getPageTitleFromPath = (pathname: string): string => { return 'Create Workspace'; case AppPath.CreateProfile: return 'Create Profile'; - case AppPath.PeoplePage: - return 'People'; - case AppPath.CompaniesPage: - return 'Companies'; case AppPath.TasksPage: return 'Tasks'; case AppPath.OpportunitiesPage: diff --git a/infra/build/server/Dockerfile b/infra/build/server/Dockerfile index 354183f28..955b79d5b 100644 --- a/infra/build/server/Dockerfile +++ b/infra/build/server/Dockerfile @@ -7,8 +7,6 @@ COPY ./server/patches ./patches RUN yarn install COPY ./server . -RUN npx prisma generate - RUN yarn build LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty diff --git a/infra/dev/Makefile b/infra/dev/Makefile index 1a6aa7718..488059686 100644 --- a/infra/dev/Makefile +++ b/infra/dev/Makefile @@ -59,9 +59,6 @@ server-database-setup: server-database-migrate: @docker compose exec twenty-dev sh -c "cd /app/server && yarn database:migrate" -server-database-generate: - @docker compose exec twenty-dev sh -c "cd /app/server && yarn database:generate" - server-database-seed: @docker compose exec twenty-dev sh -c "cd /app/server && yarn database:seed" diff --git a/server/.env.example b/server/.env.example index 55a06ac2a..e8e21e75f 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,5 +1,5 @@ # Use this for local setup -PG_DATABASE_URL=postgres://twenty:twenty@localhost:5432/default?connection_limit=1 +PG_DATABASE_URL=postgres://twenty:twenty@localhost:5432/default # Use this for docker setup # PG_DATABASE_URL=postgres://twenty:twenty@postgres:5432/default?connection_limit=1 diff --git a/server/jest.config.ts b/server/jest.config.ts index 1ae2d964e..59b1f41e8 100644 --- a/server/jest.config.ts +++ b/server/jest.config.ts @@ -2,9 +2,6 @@ module.exports = { clearMocks: true, preset: 'ts-jest', testEnvironment: 'node', - setupFilesAfterEnv: [ - '/src/database/client-mock/jest-prisma-singleton.ts', - ], moduleFileExtensions: ['js', 'json', 'ts'], moduleNameMapper: { diff --git a/server/ormconfig.ts b/server/ormconfig.ts index 153603fdc..cc37a46bf 100644 --- a/server/ormconfig.ts +++ b/server/ormconfig.ts @@ -5,7 +5,7 @@ dotenv.config(); export default { url: process.env.PG_DATABASE_URL, type: 'postgres', - entities: [__dirname + '/src/coreV2/**/*.entity{.ts,.js}'], + entities: [__dirname + '/src/core/**/*.entity{.ts,.js}'], synchronize: false, migrationsRun: false, migrationsTableName: '_typeorm_migrations', diff --git a/server/package.json b/server/package.json index f36415e3d..afb3e0f3c 100644 --- a/server/package.json +++ b/server/package.json @@ -20,20 +20,13 @@ "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "./scripts/run-integration.sh", - "prisma:generate-client": "npx prisma generate --generator client && yarn prisma:generate-gql-select", - "prisma:generate-gql-select": "node scripts/generate-model-select-map.js", - "prisma:generate-nest-graphql": "npx prisma generate --generator nestgraphql", - "prisma:generate": "yarn prisma:generate-client && yarn prisma:generate-gql-select && yarn prisma:generate-nest-graphql", - "prisma:seed": "npx prisma db seed", - "prisma:migrate": "npx prisma migrate deploy", "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js", "typeorm:migrate": "yarn typeorm migration:run -d ./src/database/typeorm/metadata/metadata.datasource.ts", "database:init": "yarn database:setup && yarn database:seed", - "database:setup": "npx ts-node ./scripts/setup-db.ts && yarn database:migrate && yarn database:generate", + "database:setup": "npx ts-node ./scripts/setup-db.ts && yarn database:migrate", "database:truncate": "npx ts-node ./scripts/truncate-db.ts", - "database:migrate": "yarn typeorm:migrate && yarn prisma:migrate", - "database:generate": "yarn prisma:generate", - "database:seed": "yarn prisma:seed && yarn build && yarn command workspace:seed", + "database:migrate": "yarn build && yarn typeorm:migrate", + "database:seed": "yarn build && yarn command workspace:seed", "database:reset": "yarn database:truncate && yarn database:init", "command": "node dist/src/command" }, @@ -42,7 +35,6 @@ "@aws-sdk/client-s3": "^3.363.0", "@aws-sdk/credential-providers": "^3.363.0", "@casl/ability": "^6.5.0", - "@casl/prisma": "1.4.0", "@graphql-tools/schema": "^10.0.0", "@graphql-yoga/nestjs": "^2.1.0", "@nestjs/apollo": "^11.0.5", @@ -57,7 +49,6 @@ "@nestjs/terminus": "^9.2.2", "@nestjs/typeorm": "^10.0.0", "@paljs/plugins": "^5.3.3", - "@prisma/client": "4.13.0", "@ptc-org/nestjs-query-core": "^4.2.0", "@ptc-org/nestjs-query-graphql": "^4.2.0", "@ptc-org/nestjs-query-typeorm": "^4.2.1-alpha.2", @@ -102,7 +93,6 @@ "patch-package": "^8.0.0", "pg": "^8.11.3", "postinstall-postinstall": "^2.1.0", - "prisma-graphql-type-decimal": "^3.0.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", @@ -144,9 +134,6 @@ "eslint-plugin-unused-imports": "^3.0.0", "jest": "28.1.3", "prettier": "^2.3.2", - "prisma": "4.13.0", - "prisma-nestjs-graphql": "^18.0.2", - "prisma-query-log": "^3.2.0", "source-map-support": "^0.5.20", "supertest": "^6.1.3", "ts-jest": "28.0.8", @@ -157,9 +144,5 @@ }, "resolutions": { "graphql": "16.8.0" - }, - "prisma": { - "schema": "src/database/schema.prisma", - "seed": "ts-node src/database/seeds/index.ts" } } diff --git a/server/scripts/generate-model-select-map.js b/server/scripts/generate-model-select-map.js deleted file mode 100644 index 41f245e10..000000000 --- a/server/scripts/generate-model-select-map.js +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const fs = require('fs'); -const path = require('path'); -const { getDMMF, getSchemaPath } = require('@prisma/internals'); - -const generateTypes = async () => { - const schemaPath = await getSchemaPath(); - const dmmf = await getDMMF({ - datamodel: fs.readFileSync(schemaPath, 'utf-8'), - }); - - let content = - '// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n'; - content += "import { Prisma } from '@prisma/client';\n\n"; - content += 'export type ModelSelectMap = {\n'; - - for (const model of dmmf.datamodel.models) { - content += ` ${model.name}: Prisma.${model.name}Select;\n`; - } - - content += '};\n'; - - fs.writeFileSync( - path.join(__dirname, '../src/utils/prisma-select/model-select-map.ts'), - content, - ); -}; - -generateTypes().catch((e) => { - console.error(e); - process.exit(1); -}); diff --git a/server/scripts/render-run.sh b/server/scripts/render-run.sh index 4899ace77..97add4561 100755 --- a/server/scripts/render-run.sh +++ b/server/scripts/render-run.sh @@ -1,5 +1,4 @@ #!/bin/sh export PG_DATABASE_URL=postgres://twenty:twenty@$PG_DATABASE_HOST:$PG_DATABASE_PORT/default -yarn prisma:migrate yarn database:setup node dist/src/main \ No newline at end of file diff --git a/server/scripts/setup-db.ts b/server/scripts/setup-db.ts index d8845071f..5a36c2889 100644 --- a/server/scripts/setup-db.ts +++ b/server/scripts/setup-db.ts @@ -13,6 +13,10 @@ connectionSource 'CREATE SCHEMA IF NOT EXISTS "metadata"', 'create schema "metadata"', ); + await performQuery( + 'CREATE SCHEMA IF NOT EXISTS "core"', + 'create schema "core"', + ); await performQuery( 'CREATE EXTENSION IF NOT EXISTS pg_graphql', 'create extension pg_graphql', @@ -24,7 +28,7 @@ connectionSource ); await performQuery( - `COMMENT ON SCHEMA "public" IS '@graphql({"inflect_names": true})';`, + `COMMENT ON SCHEMA "core" IS '@graphql({"inflect_names": true})';`, 'inflect names for graphql', ); diff --git a/server/src/ability/ability.action.ts b/server/src/ability/ability.action.ts deleted file mode 100644 index da035d7bf..000000000 --- a/server/src/ability/ability.action.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum AbilityAction { - Manage = 'manage', - Create = 'create', - Read = 'read', - Update = 'update', - Delete = 'delete', -} diff --git a/server/src/ability/ability.factory.ts b/server/src/ability/ability.factory.ts deleted file mode 100644 index 57c8c9cfc..000000000 --- a/server/src/ability/ability.factory.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PureAbility, AbilityBuilder } from '@casl/ability'; -import { createPrismaAbility, PrismaQuery, Subjects } from '@casl/prisma'; -import { - Activity, - ActivityTarget, - Attachment, - ApiKey, - Comment, - Company, - Favorite, - Person, - Pipeline, - PipelineProgress, - PipelineStage, - RefreshToken, - User, - UserSettings, - WebHook, - Workspace, - WorkspaceMember, -} from '@prisma/client'; - -import { AbilityAction } from './ability.action'; - -type SubjectsAbility = Subjects<{ - Activity: Activity; - ActivityTarget: ActivityTarget; - Attachment: Attachment; - ApiKey: ApiKey; - Comment: Comment; - Company: Company; - Favorite: Favorite; - WebHook: WebHook; - Person: Person; - Pipeline: Pipeline; - PipelineProgress: PipelineProgress; - PipelineStage: PipelineStage; - RefreshToken: RefreshToken; - User: User; - UserSettings: UserSettings; - - Workspace: Workspace; - WorkspaceMember: WorkspaceMember; -}>; - -export type AppAbility = PureAbility< - [string, SubjectsAbility | 'all'], - PrismaQuery ->; - -@Injectable() -export class AbilityFactory { - defineAbility(workspace: Workspace, user?: User) { - const { can, cannot, build } = new AbilityBuilder( - createPrismaAbility, - ); - - // User - - if (user) { - can(AbilityAction.Read, 'User', { id: user.id }); - can(AbilityAction.Update, 'User', { id: user.id }); - can(AbilityAction.Delete, 'User', { id: user.id }); - } else { - cannot(AbilityAction.Update, 'User'); - cannot(AbilityAction.Delete, 'User'); - } - - // ApiKey - can(AbilityAction.Read, 'ApiKey', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'ApiKey'); - can(AbilityAction.Update, 'ApiKey', { workspaceId: workspace.id }); - - // WebHook - can(AbilityAction.Read, 'WebHook', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'WebHook'); - can(AbilityAction.Delete, 'WebHook', { workspaceId: workspace.id }); - - // Workspace - can(AbilityAction.Read, 'Workspace'); - can(AbilityAction.Update, 'Workspace'); - can(AbilityAction.Delete, 'Workspace'); - - // Workspace Member - can(AbilityAction.Read, 'WorkspaceMember', { workspaceId: workspace.id }); - if (user) { - can(AbilityAction.Delete, 'WorkspaceMember', { - workspaceId: workspace.id, - }); - cannot(AbilityAction.Delete, 'WorkspaceMember', { userId: user.id }); - can(AbilityAction.Update, 'WorkspaceMember', { - userId: user.id, - workspaceId: workspace.id, - }); - } else { - cannot(AbilityAction.Delete, 'WorkspaceMember'); - cannot(AbilityAction.Update, 'WorkspaceMember'); - } - - // Company - can(AbilityAction.Read, 'Company', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Company'); - can(AbilityAction.Update, 'Company', { workspaceId: workspace.id }); - can(AbilityAction.Delete, 'Company', { workspaceId: workspace.id }); - - // Person - can(AbilityAction.Read, 'Person', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Person'); - can(AbilityAction.Update, 'Person', { workspaceId: workspace.id }); - can(AbilityAction.Delete, 'Person', { workspaceId: workspace.id }); - - // RefreshToken - cannot(AbilityAction.Manage, 'RefreshToken'); - - // Activity - can(AbilityAction.Read, 'Activity', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Activity'); - can(AbilityAction.Update, 'Activity', { workspaceId: workspace.id }); - can(AbilityAction.Delete, 'Activity', { workspaceId: workspace.id }); - - // Comment - can(AbilityAction.Read, 'Comment', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Comment'); - if (user) { - can(AbilityAction.Update, 'Comment', { - workspaceId: workspace.id, - authorId: user.id, - }); - can(AbilityAction.Delete, 'Comment', { - workspaceId: workspace.id, - authorId: user.id, - }); - } else { - cannot(AbilityAction.Update, 'Comment'); - cannot(AbilityAction.Delete, 'Comment'); - } - - // ActivityTarget - can(AbilityAction.Read, 'ActivityTarget'); - can(AbilityAction.Create, 'ActivityTarget'); - - // Attachment - can(AbilityAction.Read, 'Attachment', { workspaceId: workspace.id }); - can(AbilityAction.Update, 'Attachment', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Attachment', { workspaceId: workspace.id }); - - // Pipeline - can(AbilityAction.Read, 'Pipeline', { workspaceId: workspace.id }); - - // PipelineStage - can(AbilityAction.Read, 'PipelineStage', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'PipelineStage', { workspaceId: workspace.id }); - can(AbilityAction.Update, 'PipelineStage', { workspaceId: workspace.id }); - can(AbilityAction.Delete, 'PipelineStage', { workspaceId: workspace.id }); - - // PipelineProgress - can(AbilityAction.Read, 'PipelineProgress', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'PipelineProgress'); - can(AbilityAction.Update, 'PipelineProgress', { - workspaceId: workspace.id, - }); - can(AbilityAction.Delete, 'PipelineProgress', { - workspaceId: workspace.id, - }); - - // Favorite - can(AbilityAction.Read, 'Favorite', { workspaceId: workspace.id }); - can(AbilityAction.Create, 'Favorite'); - can(AbilityAction.Update, 'Favorite', { workspaceId: workspace.id }); - can(AbilityAction.Delete, 'Favorite', { workspaceId: workspace.id }); - - return build(); - } -} diff --git a/server/src/ability/ability.module.ts b/server/src/ability/ability.module.ts deleted file mode 100644 index e7fa87b0c..000000000 --- a/server/src/ability/ability.module.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AbilityFactory } from 'src/ability/ability.factory'; -import { PrismaService } from 'src/database/prisma.service'; -import { - CreateWebHookAbilityHandler, - DeleteWebHookAbilityHandler, - ReadWebHookAbilityHandler, -} from 'src/ability/handlers/web-hook.ability-handler'; - -import { - CreateUserAbilityHandler, - DeleteUserAbilityHandler, - ManageUserAbilityHandler, - ReadUserAbilityHandler, - UpdateUserAbilityHandler, -} from './handlers/user.ability-handler'; -import { - CreateWorkspaceAbilityHandler, - DeleteWorkspaceAbilityHandler, - ManageWorkspaceAbilityHandler, - ReadWorkspaceAbilityHandler, - UpdateWorkspaceAbilityHandler, -} from './handlers/workspace.ability-handler'; -import { - CreateWorkspaceMemberAbilityHandler, - DeleteWorkspaceMemberAbilityHandler, - ManageWorkspaceMemberAbilityHandler, - ReadWorkspaceMemberAbilityHandler, - UpdateWorkspaceMemberAbilityHandler, -} from './handlers/workspace-member.ability-handler'; -import { - ManageCompanyAbilityHandler, - ReadOneCompanyAbilityHandler, - CreateCompanyAbilityHandler, - UpdateCompanyAbilityHandler, - DeleteCompanyAbilityHandler, -} from './handlers/company.ability-handler'; -import { - CreatePersonAbilityHandler, - DeletePersonAbilityHandler, - ManagePersonAbilityHandler, - ReadPersonAbilityHandler, - UpdatePersonAbilityHandler, -} from './handlers/person.ability-handler'; -import { - ManageRefreshTokenAbilityHandler, - ReadRefreshTokenAbilityHandler, - CreateRefreshTokenAbilityHandler, - UpdateRefreshTokenAbilityHandler, - DeleteRefreshTokenAbilityHandler, -} from './handlers/refresh-token.ability-handler'; -import { - ManageActivityAbilityHandler, - ReadActivityAbilityHandler, - CreateActivityAbilityHandler, - UpdateActivityAbilityHandler, - DeleteActivityAbilityHandler, -} from './handlers/activity.ability-handler'; -import { - ManageCommentAbilityHandler, - ReadCommentAbilityHandler, - CreateCommentAbilityHandler, - UpdateCommentAbilityHandler, - DeleteCommentAbilityHandler, -} from './handlers/comment.ability-handler'; -import { - ManageActivityTargetAbilityHandler, - ReadActivityTargetAbilityHandler, - CreateActivityTargetAbilityHandler, - UpdateActivityTargetAbilityHandler, - DeleteActivityTargetAbilityHandler, -} from './handlers/activity-target.ability-handler'; -import { - ManagePipelineAbilityHandler, - ReadPipelineAbilityHandler, - CreatePipelineAbilityHandler, - UpdatePipelineAbilityHandler, - DeletePipelineAbilityHandler, -} from './handlers/pipeline.ability-handler'; -import { - ManagePipelineStageAbilityHandler, - ReadPipelineStageAbilityHandler, - CreatePipelineStageAbilityHandler, - UpdatePipelineStageAbilityHandler, - DeletePipelineStageAbilityHandler, -} from './handlers/pipeline-stage.ability-handler'; -import { - ManagePipelineProgressAbilityHandler, - ReadPipelineProgressAbilityHandler, - CreatePipelineProgressAbilityHandler, - UpdatePipelineProgressAbilityHandler, - DeletePipelineProgressAbilityHandler, -} from './handlers/pipeline-progress.ability-handler'; -import { - CreateAttachmentAbilityHandler, - DeleteAttachmentAbilityHandler, - ManageAttachmentAbilityHandler, - ReadAttachmentAbilityHandler, - UpdateAttachmentAbilityHandler, -} from './handlers/attachment.ability-handler'; -import { - CreateFavoriteAbilityHandler, - ReadFavoriteAbilityHandler, - DeleteFavoriteAbilityHandler, - UpdateFavoriteAbilityHandler, -} from './handlers/favorite.ability-handler'; -import { - CreateApiKeyAbilityHandler, - UpdateApiKeyAbilityHandler, - ManageApiKeyAbilityHandler, - ReadApiKeyAbilityHandler, -} from './handlers/api-key.ability-handler'; - -@Module({ - providers: [ - AbilityFactory, - PrismaService, - // User - ManageUserAbilityHandler, - ReadUserAbilityHandler, - CreateUserAbilityHandler, - UpdateUserAbilityHandler, - DeleteUserAbilityHandler, - // Workspace - ManageWorkspaceAbilityHandler, - ReadWorkspaceAbilityHandler, - CreateWorkspaceAbilityHandler, - UpdateWorkspaceAbilityHandler, - DeleteWorkspaceAbilityHandler, - // Workspace Member - ManageWorkspaceMemberAbilityHandler, - ReadWorkspaceMemberAbilityHandler, - CreateWorkspaceMemberAbilityHandler, - UpdateWorkspaceMemberAbilityHandler, - DeleteWorkspaceMemberAbilityHandler, - // Company - ManageCompanyAbilityHandler, - ReadOneCompanyAbilityHandler, - CreateCompanyAbilityHandler, - UpdateCompanyAbilityHandler, - DeleteCompanyAbilityHandler, - // Person - ManagePersonAbilityHandler, - ReadPersonAbilityHandler, - CreatePersonAbilityHandler, - UpdatePersonAbilityHandler, - DeletePersonAbilityHandler, - // RefreshToken - ManageRefreshTokenAbilityHandler, - ReadRefreshTokenAbilityHandler, - CreateRefreshTokenAbilityHandler, - UpdateRefreshTokenAbilityHandler, - DeleteRefreshTokenAbilityHandler, - // Activity - ManageActivityAbilityHandler, - ReadActivityAbilityHandler, - CreateActivityAbilityHandler, - UpdateActivityAbilityHandler, - DeleteActivityAbilityHandler, - // Comment - ManageCommentAbilityHandler, - ReadCommentAbilityHandler, - CreateCommentAbilityHandler, - UpdateCommentAbilityHandler, - DeleteCommentAbilityHandler, - // ActivityTarget - ManageActivityTargetAbilityHandler, - ReadActivityTargetAbilityHandler, - CreateActivityTargetAbilityHandler, - UpdateActivityTargetAbilityHandler, - DeleteActivityTargetAbilityHandler, - //Attachment - ManageAttachmentAbilityHandler, - ReadAttachmentAbilityHandler, - CreateAttachmentAbilityHandler, - UpdateAttachmentAbilityHandler, - DeleteAttachmentAbilityHandler, - // Pipeline - ManagePipelineAbilityHandler, - ReadPipelineAbilityHandler, - CreatePipelineAbilityHandler, - UpdatePipelineAbilityHandler, - DeletePipelineAbilityHandler, - // PipelineStage - ManagePipelineStageAbilityHandler, - ReadPipelineStageAbilityHandler, - CreatePipelineStageAbilityHandler, - UpdatePipelineStageAbilityHandler, - DeletePipelineStageAbilityHandler, - // PipelineProgress - ManagePipelineProgressAbilityHandler, - ReadPipelineProgressAbilityHandler, - CreatePipelineProgressAbilityHandler, - UpdatePipelineProgressAbilityHandler, - DeletePipelineProgressAbilityHandler, - //Favorite - ReadFavoriteAbilityHandler, - CreateFavoriteAbilityHandler, - UpdateFavoriteAbilityHandler, - DeleteFavoriteAbilityHandler, - - // ApiKey - ReadApiKeyAbilityHandler, - ManageApiKeyAbilityHandler, - CreateApiKeyAbilityHandler, - UpdateApiKeyAbilityHandler, - // Hook - CreateWebHookAbilityHandler, - DeleteWebHookAbilityHandler, - ReadWebHookAbilityHandler, - ], - exports: [ - AbilityFactory, - // User - ManageUserAbilityHandler, - ReadUserAbilityHandler, - CreateUserAbilityHandler, - UpdateUserAbilityHandler, - DeleteUserAbilityHandler, - // Workspace - ManageWorkspaceAbilityHandler, - ReadWorkspaceAbilityHandler, - CreateWorkspaceAbilityHandler, - UpdateWorkspaceAbilityHandler, - DeleteWorkspaceAbilityHandler, - // Workspace Member - ManageWorkspaceMemberAbilityHandler, - ReadWorkspaceMemberAbilityHandler, - CreateWorkspaceMemberAbilityHandler, - UpdateWorkspaceMemberAbilityHandler, - DeleteWorkspaceMemberAbilityHandler, - // Company - ManageCompanyAbilityHandler, - ReadOneCompanyAbilityHandler, - CreateCompanyAbilityHandler, - UpdateCompanyAbilityHandler, - DeleteCompanyAbilityHandler, - // Person - ManagePersonAbilityHandler, - ReadPersonAbilityHandler, - CreatePersonAbilityHandler, - UpdatePersonAbilityHandler, - DeletePersonAbilityHandler, - // RefreshToken - ManageRefreshTokenAbilityHandler, - ReadRefreshTokenAbilityHandler, - CreateRefreshTokenAbilityHandler, - UpdateRefreshTokenAbilityHandler, - DeleteRefreshTokenAbilityHandler, - // Activity - ManageActivityAbilityHandler, - ReadActivityAbilityHandler, - CreateActivityAbilityHandler, - UpdateActivityAbilityHandler, - DeleteActivityAbilityHandler, - // Comment - ManageCommentAbilityHandler, - ReadCommentAbilityHandler, - CreateCommentAbilityHandler, - UpdateCommentAbilityHandler, - DeleteCommentAbilityHandler, - // ActivityTarget - ManageActivityTargetAbilityHandler, - ReadActivityTargetAbilityHandler, - CreateActivityTargetAbilityHandler, - UpdateActivityTargetAbilityHandler, - DeleteActivityTargetAbilityHandler, - //Attachment - ManageAttachmentAbilityHandler, - ReadAttachmentAbilityHandler, - CreateAttachmentAbilityHandler, - UpdateAttachmentAbilityHandler, - DeleteAttachmentAbilityHandler, - // Pipeline - ManagePipelineAbilityHandler, - ReadPipelineAbilityHandler, - CreatePipelineAbilityHandler, - UpdatePipelineAbilityHandler, - DeletePipelineAbilityHandler, - // PipelineStage - ManagePipelineStageAbilityHandler, - ReadPipelineStageAbilityHandler, - CreatePipelineStageAbilityHandler, - UpdatePipelineStageAbilityHandler, - DeletePipelineStageAbilityHandler, - // PipelineProgress - ManagePipelineProgressAbilityHandler, - ReadPipelineProgressAbilityHandler, - CreatePipelineProgressAbilityHandler, - UpdatePipelineProgressAbilityHandler, - DeletePipelineProgressAbilityHandler, - //Favorite - ReadFavoriteAbilityHandler, - CreateFavoriteAbilityHandler, - DeleteFavoriteAbilityHandler, - - // ApiKey - ReadApiKeyAbilityHandler, - ManageApiKeyAbilityHandler, - CreateApiKeyAbilityHandler, - UpdateApiKeyAbilityHandler, - // Hook - CreateWebHookAbilityHandler, - DeleteWebHookAbilityHandler, - ReadWebHookAbilityHandler, - ], -}) -export class AbilityModule {} diff --git a/server/src/ability/ability.util.ts b/server/src/ability/ability.util.ts deleted file mode 100644 index abda5a306..000000000 --- a/server/src/ability/ability.util.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { Prisma, PrismaClient } from '@prisma/client'; -import { subject } from '@casl/ability'; - -import { camelCase } from 'src/utils/camel-case'; - -import { AppAbility } from './ability.factory'; -import { AbilityAction } from './ability.action'; - -type OperationType = - | 'create' - | 'connectOrCreate' - | 'upsert' - | 'createMany' - | 'set' - | 'disconnect' - | 'delete' - | 'connect' - | 'update' - | 'updateMany' - | 'deleteMany'; - -// in most case unique identifier is the id, but it can be something else... - -type OperationAbilityChecker = ( - modelName: Prisma.ModelName, - ability: AppAbility, - prisma: PrismaClient, - data: any, -) => Promise; - -const createAbilityCheck: OperationAbilityChecker = async ( - modelName, - ability, - prisma, - data, -) => { - // Handle all operations cases - const items = data?.data - ? !Array.isArray(data.data) - ? [data.data] - : data.data - : !Array.isArray(data) - ? [data] - : data; - - // Check if user try to create an element that is not allowed to create - for (const {} of items) { - if (!ability.can(AbilityAction.Create, modelName)) { - return false; - } - } - - return true; -}; - -const simpleAbilityCheck: OperationAbilityChecker = async ( - modelName, - ability, - prisma, - data, -) => { - // TODO: Replace user by workspaceMember and remove this check - if ( - modelName === 'User' || - modelName === 'UserSettings' || - modelName === 'Workspace' - ) { - return true; - } - - if (typeof data === 'boolean') { - return true; - } - - // Extract entity name from model name - const entity = camelCase(modelName); - //TODO: Fix boolean data types so that disconnects are possible - if (typeof data === 'boolean') { - return true; - } - // Handle all operations cases - const operations = !Array.isArray(data) ? [data] : data; - // Handle where case - const normalizedOperations = operations.map((op) => - op.where ? op.where : op, - ); - // Force entity type because of Prisma typing - const items = await prisma[entity as string].findMany({ - where: { - OR: normalizedOperations, - }, - }); - - // Check if user try to connect an element that is not allowed to read - for (const item of items) { - if (!ability.can(AbilityAction.Read, subject(modelName, item))) { - return false; - } - } - - return true; -}; - -const operationAbilityCheckers: Record = - { - create: createAbilityCheck, - createMany: createAbilityCheck, - upsert: simpleAbilityCheck, - update: simpleAbilityCheck, - updateMany: simpleAbilityCheck, - delete: simpleAbilityCheck, - deleteMany: simpleAbilityCheck, - connectOrCreate: simpleAbilityCheck, - connect: simpleAbilityCheck, - disconnect: simpleAbilityCheck, - set: simpleAbilityCheck, - }; - -// Check relation nested abilities -export const relationAbilityChecker = async ( - modelName: Prisma.ModelName, - ability: AppAbility, - prisma: PrismaClient, - args: any, -) => { - // Extract models from Prisma - const models = Prisma.dmmf.datamodel.models; - // Find main model from options - const mainModel = models.find((item) => item.name === modelName); - - if (!mainModel) { - throw new Error('Main model not found'); - } - - // Loop over fields - for (const field of mainModel.fields) { - // Check if field is a relation - if (field.relationName) { - // Check if field is in args - const operation = args.data?.[field.name] ?? args?.[field.name]; - - if (operation) { - // Extract operation name and value - const operationType = Object.keys(operation)[0] as OperationType; - const operationValue = operation[operationType]; - // Get operation checker for the operation type - const operationChecker = operationAbilityCheckers[operationType]; - - if (!operationChecker) { - throw new Error('Operation not found'); - } - - // Check if operation is allowed - const allowed = await operationChecker( - field.type as Prisma.ModelName, - ability, - prisma, - operationValue, - ); - - if (!allowed) { - return false; - } - - // For the 'create', 'connectOrCreate', 'upsert', 'update', and 'updateMany' operations, - // we should also check the nested operations. - if ( - [ - 'create', - 'connectOrCreate', - 'upsert', - 'update', - 'updateMany', - ].includes(operationType) - ) { - // Handle nested operations all cases - - const operationValues = !Array.isArray(operationValue) - ? [operationValue] - : operationValue; - - // Loop over nested args - for (const nestedArgs of operationValues) { - const nestedCreateAllowed = await relationAbilityChecker( - field.type as Prisma.ModelName, - ability, - prisma, - nestedArgs.create ?? nestedArgs.data ?? nestedArgs, - ); - - if (!nestedCreateAllowed) { - return false; - } - - if (nestedArgs.update) { - const nestedUpdateAllowed = await relationAbilityChecker( - field.type as Prisma.ModelName, - ability, - prisma, - nestedArgs.update, - ); - - if (!nestedUpdateAllowed) { - return false; - } - } - } - } - } - } - } - - return true; -}; - -const isWhereInput = (input: any): boolean => { - return Object.values(input).some((value) => typeof value === 'object'); -}; - -type ExcludeUnique = T extends infer U - ? 'AND' extends keyof U - ? U - : never - : never; - -/** - * Convert a where unique input to a where input prisma - * @param args Can be a where unique input or a where input - * @returns whare input - */ -export const convertToWhereInput = ( - where: T | undefined, -): ExcludeUnique | undefined => { - const input = where as any; - - if (!input) { - return input; - } - - // If it's already a WhereInput, return it directly - if (isWhereInput(input)) { - return input; - } - - // If not convert it to a WhereInput - const whereInput = {}; - - for (const key in input) { - whereInput[key] = { equals: input[key] }; - } - - return whereInput as ExcludeUnique; -}; diff --git a/server/src/ability/handlers/activity-target.ability-handler.ts b/server/src/ability/handlers/activity-target.ability-handler.ts deleted file mode 100644 index 694fee47f..000000000 --- a/server/src/ability/handlers/activity-target.ability-handler.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { assert } from 'src/utils/assert'; -import { ActivityTargetWhereInput } from 'src/core/@generated/activity-target/activity-target-where.input'; - -class ActivityTargetArgs { - where?: ActivityTargetWhereInput; -} - -@Injectable() -export class ManageActivityTargetAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'ActivityTarget'); - } -} - -@Injectable() -export class ReadActivityTargetAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'ActivityTarget'); - } -} - -@Injectable() -export class CreateActivityTargetAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Create, 'ActivityTarget'); - } -} - -@Injectable() -export class UpdateActivityTargetAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const ActivityTarget = - await this.prismaService.client.activityTarget.findFirst({ - where: args.where, - }); - assert(ActivityTarget, '', NotFoundException); - - return ability.can( - AbilityAction.Update, - subject('ActivityTarget', ActivityTarget), - ); - } -} - -@Injectable() -export class DeleteActivityTargetAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const ActivityTarget = - await this.prismaService.client.activityTarget.findFirst({ - where: args.where, - }); - assert(ActivityTarget, '', NotFoundException); - - return ability.can( - AbilityAction.Delete, - subject('ActivityTarget', ActivityTarget), - ); - } -} diff --git a/server/src/ability/handlers/activity.ability-handler.ts b/server/src/ability/handlers/activity.ability-handler.ts deleted file mode 100644 index c161af2fa..000000000 --- a/server/src/ability/handlers/activity.ability-handler.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { assert } from 'src/utils/assert'; -import { ActivityWhereInput } from 'src/core/@generated/activity/activity-where.input'; - -class ActivityArgs { - where?: ActivityWhereInput; -} - -@Injectable() -export class ManageActivityAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Activity'); - } -} - -@Injectable() -export class ReadActivityAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Activity'); - } -} - -@Injectable() -export class CreateActivityAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Create, 'Activity'); - } -} - -@Injectable() -export class UpdateActivityAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const Activity = await this.prismaService.client.activity.findFirst({ - where: args.where, - }); - assert(Activity, '', NotFoundException); - - return ability.can(AbilityAction.Update, subject('Activity', Activity)); - } -} - -@Injectable() -export class DeleteActivityAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const Activity = await this.prismaService.client.activity.findFirst({ - where: args.where, - }); - assert(Activity, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('Activity', Activity)); - } -} diff --git a/server/src/ability/handlers/api-key.ability-handler.ts b/server/src/ability/handlers/api-key.ability-handler.ts deleted file mode 100644 index a72a6f4c6..000000000 --- a/server/src/ability/handlers/api-key.ability-handler.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { AppAbility } from 'src/ability/ability.factory'; -import { AbilityAction } from 'src/ability/ability.action'; -import { PrismaService } from 'src/database/prisma.service'; -import { ApiKeyWhereUniqueInput } from 'src/core/@generated/api-key/api-key-where-unique.input'; -import { ApiKeyWhereInput } from 'src/core/@generated/api-key/api-key-where.input'; -import { assert } from 'src/utils/assert'; -import { - convertToWhereInput, - relationAbilityChecker, -} from 'src/ability/ability.util'; - -class ApiKeyArgs { - where?: ApiKeyWhereUniqueInput | ApiKeyWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageApiKeyAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'ApiKey'); - } -} - -@Injectable() -export class ReadApiKeyAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'ApiKey'); - } -} - -@Injectable() -export class CreateApiKeyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const allowed = await relationAbilityChecker( - 'ApiKey', - ability, - this.prismaService.client, - args, - ); - if (!allowed) { - return false; - } - return ability.can(AbilityAction.Create, 'ApiKey'); - } -} - -@Injectable() -export class UpdateApiKeyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const where = convertToWhereInput(args.where); - const apiKey = await this.prismaService.client.apiKey.findFirst({ - where, - }); - assert(apiKey, '', NotFoundException); - const allowed = await relationAbilityChecker( - 'ApiKey', - ability, - this.prismaService.client, - args, - ); - if (!allowed) { - return false; - } - return ability.can(AbilityAction.Update, subject('ApiKey', apiKey)); - } -} diff --git a/server/src/ability/handlers/attachment.ability-handler.ts b/server/src/ability/handlers/attachment.ability-handler.ts deleted file mode 100644 index 6c2d33fd8..000000000 --- a/server/src/ability/handlers/attachment.ability-handler.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { - ExecutionContext, - ForbiddenException, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { assert } from 'src/utils/assert'; - -class AttachmentArgs { - activityId?: string; -} - -@Injectable() -export class ManageAttachmentAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Attachment'); - } -} - -@Injectable() -export class ReadAttachmentAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Attachment'); - } -} - -@Injectable() -export class CreateAttachmentAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - assert(args.activityId, '', ForbiddenException); - - const activity = await this.prismaService.client.activity.findUnique({ - where: { id: args.activityId }, - }); - assert(activity, '', NotFoundException); - - return ability.can(AbilityAction.Update, subject('Activity', activity)); - } -} - -@Injectable() -export class UpdateAttachmentAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Update, 'Attachment'); - } -} - -@Injectable() -export class DeleteAttachmentAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Delete, 'Attachment'); - } -} diff --git a/server/src/ability/handlers/comment.ability-handler.ts b/server/src/ability/handlers/comment.ability-handler.ts deleted file mode 100644 index 1f8b5f747..000000000 --- a/server/src/ability/handlers/comment.ability-handler.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { CommentWhereInput } from 'src/core/@generated/comment/comment-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class CommentArgs { - where?: CommentWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageCommentAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Comment'); - } -} - -@Injectable() -export class ReadCommentAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Comment'); - } -} - -@Injectable() -export class CreateCommentAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Comment', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Comment'); - } -} - -@Injectable() -export class UpdateCommentAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const comment = await this.prismaService.client.comment.findFirst({ - where: args.where, - }); - assert(comment, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Comment', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, subject('Comment', comment)); - } -} - -@Injectable() -export class DeleteCommentAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const comment = await this.prismaService.client.comment.findFirst({ - where: args.where, - }); - assert(comment, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('Comment', comment)); - } -} diff --git a/server/src/ability/handlers/company.ability-handler.ts b/server/src/ability/handlers/company.ability-handler.ts deleted file mode 100644 index 4727b4333..000000000 --- a/server/src/ability/handlers/company.ability-handler.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { CompanyWhereInput } from 'src/core/@generated/company/company-where.input'; -import { CompanyWhereUniqueInput } from 'src/core/@generated/company/company-where-unique.input'; -import { - convertToWhereInput, - relationAbilityChecker, -} from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class CompanyArgs { - where?: CompanyWhereUniqueInput | CompanyWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageCompanyAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Company'); - } -} - -@Injectable() -export class ReadOneCompanyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const company = await this.prismaService.client.company.findFirst({ - where: args.where, - }); - assert(company, '', NotFoundException); - - return ability.can(AbilityAction.Read, subject('Company', company)); - } -} - -@Injectable() -export class CreateCompanyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Company', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Company'); - } -} - -@Injectable() -export class UpdateCompanyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const where = convertToWhereInput(args.where); - const companies = await this.prismaService.client.company.findMany({ - where, - }); - assert(companies.length, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Company', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - for (const company of companies) { - const allowed = ability.can( - AbilityAction.Delete, - subject('Company', company), - ); - - if (!allowed) { - return false; - } - } - - return true; - } -} - -@Injectable() -export class DeleteCompanyAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const where = convertToWhereInput(args.where); - const companies = await this.prismaService.client.company.findMany({ - where, - }); - assert(companies.length, '', NotFoundException); - - for (const company of companies) { - const allowed = ability.can( - AbilityAction.Delete, - subject('Company', company), - ); - - if (!allowed) { - return false; - } - } - - return true; - } -} diff --git a/server/src/ability/handlers/favorite.ability-handler.ts b/server/src/ability/handlers/favorite.ability-handler.ts deleted file mode 100644 index 65fc4b3e1..000000000 --- a/server/src/ability/handlers/favorite.ability-handler.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { FavoriteWhereInput } from 'src/core/@generated/favorite/favorite-where.input'; -import { assert } from 'src/utils/assert'; - -class FavoriteArgs { - where?: FavoriteWhereInput; -} - -@Injectable() -export class ManageFavoriteAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Favorite'); - } -} - -@Injectable() -export class ReadFavoriteAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Favorite'); - } -} - -@Injectable() -export class CreateFavoriteAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Favorite', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Favorite'); - } -} - -@Injectable() -export class UpdateFavoriteAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const favorite = await this.prismaService.client.favorite.findFirst({ - where: args.where, - }); - assert(favorite, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Favorite', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, 'Favorite'); - } -} - -@Injectable() -export class DeleteFavoriteAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const favorite = await this.prismaService.client.favorite.findFirst({ - where: args.where, - }); - assert(favorite, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('Favorite', favorite)); - } -} diff --git a/server/src/ability/handlers/person.ability-handler.ts b/server/src/ability/handlers/person.ability-handler.ts deleted file mode 100644 index c9fde0c46..000000000 --- a/server/src/ability/handlers/person.ability-handler.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { PersonWhereInput } from 'src/core/@generated/person/person-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class PersonArgs { - where?: PersonWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManagePersonAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Person'); - } -} - -@Injectable() -export class ReadPersonAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Person'); - } -} - -@Injectable() -export class CreatePersonAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Person', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Person'); - } -} - -@Injectable() -export class UpdatePersonAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const person = await this.prismaService.client.person.findFirst({ - where: args.where, - }); - assert(person, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Person', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, subject('Person', person)); - } -} - -@Injectable() -export class DeletePersonAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const person = await this.prismaService.client.person.findFirst({ - where: args.where, - }); - assert(person, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('Person', person)); - } -} diff --git a/server/src/ability/handlers/pipeline-progress.ability-handler.ts b/server/src/ability/handlers/pipeline-progress.ability-handler.ts deleted file mode 100644 index 2b463061f..000000000 --- a/server/src/ability/handlers/pipeline-progress.ability-handler.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { PipelineProgressWhereInput } from 'src/core/@generated/pipeline-progress/pipeline-progress-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class PipelineProgressArgs { - where?: PipelineProgressWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManagePipelineProgressAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'PipelineProgress'); - } -} - -@Injectable() -export class ReadPipelineProgressAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'PipelineProgress'); - } -} - -@Injectable() -export class CreatePipelineProgressAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'PipelineProgress', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'PipelineProgress'); - } -} - -@Injectable() -export class UpdatePipelineProgressAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipelineProgress = - await this.prismaService.client.pipelineProgress.findFirst({ - where: args.where, - }); - assert(pipelineProgress, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'PipelineProgress', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can( - AbilityAction.Update, - subject('PipelineProgress', pipelineProgress), - ); - } -} - -@Injectable() -export class DeletePipelineProgressAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipelineProgress = - await this.prismaService.client.pipelineProgress.findFirst({ - where: args.where, - }); - assert(pipelineProgress, '', NotFoundException); - - return ability.can( - AbilityAction.Delete, - subject('PipelineProgress', pipelineProgress), - ); - } -} diff --git a/server/src/ability/handlers/pipeline-stage.ability-handler.ts b/server/src/ability/handlers/pipeline-stage.ability-handler.ts deleted file mode 100644 index 026f9b77d..000000000 --- a/server/src/ability/handlers/pipeline-stage.ability-handler.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { PipelineStageWhereInput } from 'src/core/@generated/pipeline-stage/pipeline-stage-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class PipelineStageArgs { - where?: PipelineStageWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManagePipelineStageAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'PipelineStage'); - } -} - -@Injectable() -export class ReadPipelineStageAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'PipelineStage'); - } -} - -@Injectable() -export class CreatePipelineStageAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'PipelineStage', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'PipelineStage'); - } -} - -@Injectable() -export class UpdatePipelineStageAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipelineStage = - await this.prismaService.client.pipelineStage.findFirst({ - where: args.where, - }); - assert(pipelineStage, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'PipelineStage', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can( - AbilityAction.Update, - subject('PipelineStage', pipelineStage), - ); - } -} - -@Injectable() -export class DeletePipelineStageAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipelineStage = - await this.prismaService.client.pipelineStage.findFirst({ - where: args.where, - }); - assert(pipelineStage, '', NotFoundException); - - return ability.can( - AbilityAction.Delete, - subject('PipelineStage', pipelineStage), - ); - } -} diff --git a/server/src/ability/handlers/pipeline.ability-handler.ts b/server/src/ability/handlers/pipeline.ability-handler.ts deleted file mode 100644 index e9aecfae7..000000000 --- a/server/src/ability/handlers/pipeline.ability-handler.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { PipelineWhereInput } from 'src/core/@generated/pipeline/pipeline-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class PipelineArgs { - where?: PipelineWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManagePipelineAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Pipeline'); - } -} - -@Injectable() -export class ReadPipelineAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Pipeline'); - } -} - -@Injectable() -export class CreatePipelineAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Pipeline', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Pipeline'); - } -} - -@Injectable() -export class UpdatePipelineAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipeline = await this.prismaService.client.pipeline.findFirst({ - where: args.where, - }); - assert(pipeline, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Pipeline', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, subject('Pipeline', pipeline)); - } -} - -@Injectable() -export class DeletePipelineAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const pipeline = await this.prismaService.client.pipeline.findFirst({ - where: args.where, - }); - assert(pipeline, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('Pipeline', pipeline)); - } -} diff --git a/server/src/ability/handlers/refresh-token.ability-handler.ts b/server/src/ability/handlers/refresh-token.ability-handler.ts deleted file mode 100644 index 08f68a0cf..000000000 --- a/server/src/ability/handlers/refresh-token.ability-handler.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { RefreshTokenWhereInput } from 'src/core/@generated/refresh-token/refresh-token-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class RefreshTokenArgs { - where?: RefreshTokenWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageRefreshTokenAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'RefreshToken'); - } -} - -@Injectable() -export class ReadRefreshTokenAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'RefreshToken'); - } -} - -@Injectable() -export class CreateRefreshTokenAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'RefreshToken', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'RefreshToken'); - } -} - -@Injectable() -export class UpdateRefreshTokenAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const refreshToken = await this.prismaService.client.refreshToken.findFirst( - { - where: args.where, - }, - ); - assert(refreshToken, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'RefreshToken', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can( - AbilityAction.Update, - subject('RefreshToken', refreshToken), - ); - } -} - -@Injectable() -export class DeleteRefreshTokenAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const refreshToken = await this.prismaService.client.refreshToken.findFirst( - { - where: args.where, - }, - ); - assert(refreshToken, '', NotFoundException); - - return ability.can( - AbilityAction.Delete, - subject('RefreshToken', refreshToken), - ); - } -} diff --git a/server/src/ability/handlers/user.ability-handler.ts b/server/src/ability/handlers/user.ability-handler.ts deleted file mode 100644 index 69bee102e..000000000 --- a/server/src/ability/handlers/user.ability-handler.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { UserWhereInput } from 'src/core/@generated/user/user-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class UserArgs { - where?: UserWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageUserAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'User'); - } -} - -@Injectable() -export class ReadUserAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'User'); - } -} - -@Injectable() -export class CreateUserAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'User', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'User'); - } -} - -@Injectable() -export class UpdateUserAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - // TODO: Confirm if this is correct - const user = await this.prismaService.client.user.findFirst({ - where: args.where, - }); - assert(user, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'User', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, subject('User', user)); - } -} - -@Injectable() -export class DeleteUserAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - // obtain the auth user from the context - const reqUser = gqlContext.getContext().req.user; - - // FIXME: When `args.where` is undefined(which it is in almost all the cases I've tested), - // this query will return the first user entry in the DB, which is most likely not the current user - const user = await this.prismaService.client.user.findFirst({ - where: { ...args.where, id: reqUser.user.id }, - }); - assert(user, '', NotFoundException); - - return ability.can(AbilityAction.Delete, subject('User', user)); - } -} diff --git a/server/src/ability/handlers/web-hook.ability-handler.ts b/server/src/ability/handlers/web-hook.ability-handler.ts deleted file mode 100644 index c2b73fd65..000000000 --- a/server/src/ability/handlers/web-hook.ability-handler.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { - Injectable, - ExecutionContext, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { AppAbility } from 'src/ability/ability.factory'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { assert } from 'src/utils/assert'; - -@Injectable() -export class CreateWebHookAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const allowed = await relationAbilityChecker( - 'WebHook', - ability, - this.prismaService.client, - args, - ); - if (!allowed) { - return false; - } - return ability.can(AbilityAction.Create, 'WebHook'); - } -} - -@Injectable() -export class DeleteWebHookAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const hook = await this.prismaService.client.webHook.findFirst({ - where: args.where, - }); - assert(hook, '', NotFoundException); - return ability.can(AbilityAction.Delete, subject('WebHook', hook)); - } -} - -@Injectable() -export class ReadWebHookAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'WebHook'); - } -} diff --git a/server/src/ability/handlers/workspace-member.ability-handler.ts b/server/src/ability/handlers/workspace-member.ability-handler.ts deleted file mode 100644 index 3a5d62ed9..000000000 --- a/server/src/ability/handlers/workspace-member.ability-handler.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { subject } from '@casl/ability'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { WorkspaceMemberWhereInput } from 'src/core/@generated/workspace-member/workspace-member-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class WorkspaceMemberArgs { - where?: WorkspaceMemberWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageWorkspaceMemberAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'WorkspaceMember'); - } -} - -@Injectable() -export class ReadWorkspaceMemberAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'WorkspaceMember'); - } -} - -@Injectable() -export class CreateWorkspaceMemberAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'WorkspaceMember', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'WorkspaceMember'); - } -} - -@Injectable() -export class UpdateWorkspaceMemberAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const workspaceMember = - await this.prismaService.client.workspaceMember.findFirst({ - where: args.where, - }); - assert(workspaceMember, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'WorkspaceMember', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can( - AbilityAction.Update, - subject('WorkspaceMember', workspaceMember), - ); - } -} - -@Injectable() -export class DeleteWorkspaceMemberAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const workspaceMember = - await this.prismaService.client.workspaceMember.findFirst({ - where: args.where, - }); - assert(workspaceMember, '', NotFoundException); - - return ability.can( - AbilityAction.Delete, - subject('WorkspaceMember', workspaceMember), - ); - } -} diff --git a/server/src/ability/handlers/workspace.ability-handler.ts b/server/src/ability/handlers/workspace.ability-handler.ts deleted file mode 100644 index 705d75393..000000000 --- a/server/src/ability/handlers/workspace.ability-handler.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { - ExecutionContext, - Injectable, - NotFoundException, -} from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PrismaService } from 'src/database/prisma.service'; -import { AbilityAction } from 'src/ability/ability.action'; -import { AppAbility } from 'src/ability/ability.factory'; -import { WorkspaceWhereInput } from 'src/core/@generated/workspace/workspace-where.input'; -import { relationAbilityChecker } from 'src/ability/ability.util'; -import { assert } from 'src/utils/assert'; - -class WorkspaceArgs { - where?: WorkspaceWhereInput; - [key: string]: any; -} - -@Injectable() -export class ManageWorkspaceAbilityHandler implements IAbilityHandler { - async handle(ability: AppAbility) { - return ability.can(AbilityAction.Manage, 'Workspace'); - } -} - -@Injectable() -export class ReadWorkspaceAbilityHandler implements IAbilityHandler { - handle(ability: AppAbility) { - return ability.can(AbilityAction.Read, 'Workspace'); - } -} - -@Injectable() -export class CreateWorkspaceAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - - const allowed = await relationAbilityChecker( - 'Workspace', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Create, 'Workspace'); - } -} - -@Injectable() -export class UpdateWorkspaceAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const workspace = await this.prismaService.client.workspace.findFirst({ - where: args.where, - }); - assert(workspace, '', NotFoundException); - - const allowed = await relationAbilityChecker( - 'Workspace', - ability, - this.prismaService.client, - args, - ); - - if (!allowed) { - return false; - } - - return ability.can(AbilityAction.Update, 'Workspace'); - } -} - -@Injectable() -export class DeleteWorkspaceAbilityHandler implements IAbilityHandler { - constructor(private readonly prismaService: PrismaService) {} - - async handle(ability: AppAbility, context: ExecutionContext) { - const gqlContext = GqlExecutionContext.create(context); - const args = gqlContext.getArgs(); - const workspace = await this.prismaService.client.workspace.findFirst({ - where: args.where, - }); - assert(workspace, '', NotFoundException); - - return ability.can(AbilityAction.Delete, 'Workspace'); - } -} diff --git a/server/src/ability/interfaces/ability-handler.interface.ts b/server/src/ability/interfaces/ability-handler.interface.ts deleted file mode 100644 index 28cda745d..000000000 --- a/server/src/ability/interfaces/ability-handler.interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ExecutionContext, Type } from '@nestjs/common'; - -import { AppAbility } from 'src/ability/ability.factory'; - -export interface IAbilityHandler { - handle( - ability: AppAbility, - executionContext: ExecutionContext, - ): Promise | boolean; -} - -export type AbilityHandler = Type; diff --git a/server/src/app.module.ts b/server/src/app.module.ts index b39a5ab4d..960118275 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -13,9 +13,7 @@ import { AppService } from './app.service'; import { CoreModule } from './core/core.module'; import { IntegrationsModule } from './integrations/integrations.module'; -import { PrismaModule } from './database/prisma.module'; import { HealthModule } from './health/health.module'; -import { AbilityModule } from './ability/ability.module'; import { WorkspaceModule } from './workspace/workspace.module'; import { EnvironmentService } from './integrations/environment/environment.service'; import { @@ -104,9 +102,7 @@ import { ExceptionFilter } from './filters/exception.filter'; resolvers: { JSON: GraphQLJSON }, plugins: [], }), - PrismaModule, HealthModule, - AbilityModule, IntegrationsModule, CoreModule, WorkspaceModule, diff --git a/server/src/core/activity/activity.module.ts b/server/src/core/activity/activity.module.ts deleted file mode 100644 index e058fd45f..000000000 --- a/server/src/core/activity/activity.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { ActivityResolver } from './resolvers/activity.resolver'; -import { ActivityService } from './services/activity.service'; -import { ActivityTargetService } from './services/activity-target.service'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [ActivityResolver, ActivityService, ActivityTargetService], - exports: [ActivityService, ActivityTargetService], -}) -export class ActivityModule {} diff --git a/server/src/core/activity/resolvers/activity.resolver.spec.ts b/server/src/core/activity/resolvers/activity.resolver.spec.ts deleted file mode 100644 index 63bf6ebb7..000000000 --- a/server/src/core/activity/resolvers/activity.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { ActivityService } from 'src/core/activity/services/activity.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { ActivityResolver } from './activity.resolver'; - -describe('ActivityResolver', () => { - let resolver: ActivityResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - ActivityResolver, - { - provide: ActivityService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(ActivityResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/activity/resolvers/activity.resolver.ts b/server/src/core/activity/resolvers/activity.resolver.ts deleted file mode 100644 index 231df7590..000000000 --- a/server/src/core/activity/resolvers/activity.resolver.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Resolver, Args, Mutation, Query } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; -import { Prisma } from '@prisma/client'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { - PrismaSelector, - PrismaSelect, -} from 'src/decorators/prisma-select.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreateActivityAbilityHandler, - DeleteActivityAbilityHandler, - ReadActivityAbilityHandler, - UpdateActivityAbilityHandler, -} from 'src/ability/handlers/activity.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output'; -import { Activity } from 'src/core/@generated/activity/activity.model'; -import { ActivityService } from 'src/core/activity/services/activity.service'; -import { CreateOneActivityArgs } from 'src/core/@generated/activity/create-one-activity.args'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { UpdateOneActivityArgs } from 'src/core/@generated/activity/update-one-activity.args'; -import { FindManyActivityArgs } from 'src/core/@generated/activity/find-many-activity.args'; -import { DeleteManyActivityArgs } from 'src/core/@generated/activity/delete-many-activity.args'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Activity) -export class ActivityResolver { - constructor(private readonly activityService: ActivityService) {} - - @Mutation(() => Activity, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateActivityAbilityHandler) - async createOneActivity( - @Args() args: CreateOneActivityArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Activity' }) - prismaSelect: PrismaSelect<'Activity'>, - ): Promise> { - const createdActivity = await this.activityService.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspace.id } } }, - activityTargets: args.data?.activityTargets?.createMany - ? { - createMany: { - data: args.data.activityTargets.createMany.data.map( - (target) => ({ ...target, workspaceId: workspace.id }), - ), - }, - } - : undefined, - }, - select: prismaSelect.value, - } as Prisma.ActivityCreateArgs); - - return createdActivity; - } - - @Mutation(() => Activity, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateActivityAbilityHandler) - async updateOneActivity( - @Args() args: UpdateOneActivityArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Activity' }) - prismaSelect: PrismaSelect<'Activity'>, - ): Promise> { - // TODO: Do a proper check with recursion testing on args in a more generic place - for (const key in args.data) { - if (args.data[key]) { - for (const subKey in args.data[key]) { - if (JSON.stringify(args.data[key][subKey]) === '{}') { - delete args.data[key][subKey]; - } - } - } - - if (JSON.stringify(args.data[key]) === '{}') { - delete args.data[key]; - } - } - const updatedActivity = await this.activityService.update({ - where: args.where, - data: { - ...args.data, - activityTargets: args.data?.activityTargets - ? { - createMany: args.data.activityTargets.createMany - ? { - data: args.data.activityTargets.createMany.data.map( - (target) => ({ - ...target, - workspaceId: workspace.id, - }), - ), - } - : undefined, - deleteMany: args.data.activityTargets.deleteMany ?? undefined, - } - : undefined, - }, - select: prismaSelect.value, - } as Prisma.ActivityUpdateArgs); - - return updatedActivity; - } - - @Query(() => [Activity]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadActivityAbilityHandler) - async findManyActivities( - @Args() args: FindManyActivityArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'Activity' }) - prismaSelect: PrismaSelect<'Activity'>, - ): Promise[]> { - const result = await this.activityService.findMany({ - where: { - ...args.where, - AND: [accessibleBy(ability).Activity], - }, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - - return result; - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteActivityAbilityHandler) - async deleteManyActivities( - @Args() args: DeleteManyActivityArgs, - ): Promise { - return this.activityService.deleteMany({ - where: args.where, - }); - } -} diff --git a/server/src/core/activity/services/activity-target.service.spec.ts b/server/src/core/activity/services/activity-target.service.spec.ts deleted file mode 100644 index cc18cd670..000000000 --- a/server/src/core/activity/services/activity-target.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { ActivityTargetService } from './activity-target.service'; - -describe('ActivityTargetService', () => { - let service: ActivityTargetService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - ActivityTargetService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(ActivityTargetService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/activity/services/activity-target.service.ts b/server/src/core/activity/services/activity-target.service.ts deleted file mode 100644 index 8c9398d54..000000000 --- a/server/src/core/activity/services/activity-target.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class ActivityTargetService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.activityTarget.findFirst; - findFirstOrThrow = this.prismaService.client.activityTarget.findFirstOrThrow; - - findUnique = this.prismaService.client.activityTarget.findUnique; - findUniqueOrThrow = - this.prismaService.client.activityTarget.findUniqueOrThrow; - - findMany = this.prismaService.client.activityTarget.findMany; - - // Create - create = this.prismaService.client.activityTarget.create; - createMany = this.prismaService.client.activityTarget.createMany; - - // Update - update = this.prismaService.client.activityTarget.update; - upsert = this.prismaService.client.activityTarget.upsert; - updateMany = this.prismaService.client.activityTarget.updateMany; - - // Delete - delete = this.prismaService.client.activityTarget.delete; - deleteMany = this.prismaService.client.activityTarget.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.activityTarget.aggregate; - - // Count - count = this.prismaService.client.activityTarget.count; - - // GroupBy - groupBy = this.prismaService.client.activityTarget.groupBy; -} diff --git a/server/src/core/activity/services/activity.service.spec.ts b/server/src/core/activity/services/activity.service.spec.ts deleted file mode 100644 index 5a58ece2f..000000000 --- a/server/src/core/activity/services/activity.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { ActivityService } from './activity.service'; - -describe('ActivityService', () => { - let service: ActivityService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - ActivityService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(ActivityService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/activity/services/activity.service.ts b/server/src/core/activity/services/activity.service.ts deleted file mode 100644 index ce22974b0..000000000 --- a/server/src/core/activity/services/activity.service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class ActivityService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.activity.findFirst; - findFirstOrThrow = this.prismaService.client.activity.findFirstOrThrow; - - findUnique = this.prismaService.client.activity.findUnique; - findUniqueOrThrow = this.prismaService.client.activity.findUniqueOrThrow; - - findMany = this.prismaService.client.activity.findMany; - - // Create - create = this.prismaService.client.activity.create; - createMany = this.prismaService.client.activity.createMany; - - // Update - update = this.prismaService.client.activity.update; - upsert = this.prismaService.client.activity.upsert; - updateMany = this.prismaService.client.activity.updateMany; - - // Delete - delete = this.prismaService.client.activity.delete; - deleteMany = this.prismaService.client.activity.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.activity.aggregate; - - // Count - count = this.prismaService.client.activity.count; - - // GroupBy - groupBy = this.prismaService.client.activity.groupBy; -} diff --git a/server/src/core/analytics/analytics.resolver.ts b/server/src/core/analytics/analytics.resolver.ts index dda499ff4..e4564e233 100644 --- a/server/src/core/analytics/analytics.resolver.ts +++ b/server/src/core/analytics/analytics.resolver.ts @@ -1,11 +1,11 @@ import { Resolver, Mutation, Args } from '@nestjs/graphql'; import { UseGuards } from '@nestjs/common'; -import { User, Workspace } from '@prisma/client'; - import { OptionalJwtAuthGuard } from 'src/guards/optional-jwt.auth.guard'; import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; import { AuthUser } from 'src/decorators/auth-user.decorator'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { User } from 'src/core/user/user.entity'; import { AnalyticsService } from './analytics.service'; import { Analytics } from './analytics.entity'; diff --git a/server/src/core/analytics/analytics.service.ts b/server/src/core/analytics/analytics.service.ts index 20ef2c377..76aa27c8e 100644 --- a/server/src/core/analytics/analytics.service.ts +++ b/server/src/core/analytics/analytics.service.ts @@ -1,10 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { User, Workspace } from '@prisma/client'; import axios, { AxiosInstance } from 'axios'; import { anonymize } from 'src/utils/anonymize'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; import { CreateAnalyticsInput } from './dto/create-analytics.input'; diff --git a/server/src/core/analytics/dto/create-analytics.input.ts b/server/src/core/analytics/dto/create-analytics.input.ts index dc201f345..a870673fe 100644 --- a/server/src/core/analytics/dto/create-analytics.input.ts +++ b/server/src/core/analytics/dto/create-analytics.input.ts @@ -1,6 +1,6 @@ import { ArgsType, Field } from '@nestjs/graphql'; -import GraphQLJSON from 'graphql-type-json'; +import graphqlTypeJson from 'graphql-type-json'; import { IsNotEmpty, IsString, IsObject } from 'class-validator'; @ArgsType() @@ -10,7 +10,7 @@ export class CreateAnalyticsInput { @IsString() type: string; - @Field(() => GraphQLJSON, { description: 'Event data in JSON format' }) + @Field(() => graphqlTypeJson, { description: 'Event data in JSON format' }) @IsObject() data: JSON; } diff --git a/server/src/core/api-key/api-key.module.ts b/server/src/core/api-key/api-key.module.ts deleted file mode 100644 index 4f0073d45..000000000 --- a/server/src/core/api-key/api-key.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Module } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; - -import { TokenService } from 'src/core/auth/services/token.service'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { ApiKeyResolver } from './api-key.resolver'; -import { ApiKeyService } from './api-key.service'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [ApiKeyResolver, ApiKeyService, TokenService, JwtService], -}) -export class ApiKeyModule {} diff --git a/server/src/core/api-key/api-key.resolver.spec.ts b/server/src/core/api-key/api-key.resolver.spec.ts deleted file mode 100644 index 32f24e23c..000000000 --- a/server/src/core/api-key/api-key.resolver.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { JwtService } from '@nestjs/jwt'; - -import { AbilityFactory } from 'src/ability/ability.factory'; -import { TokenService } from 'src/core/auth/services/token.service'; - -import { ApiKeyResolver } from './api-key.resolver'; -import { ApiKeyService } from './api-key.service'; - -describe('ApiKeyResolver', () => { - let resolver: ApiKeyResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - ApiKeyResolver, - { provide: ApiKeyService, useValue: {} }, - { provide: TokenService, useValue: {} }, - { provide: JwtService, useValue: {} }, - { provide: AbilityFactory, useValue: {} }, - ], - }).compile(); - resolver = module.get(ApiKeyResolver); - }); - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/api-key/api-key.resolver.ts b/server/src/core/api-key/api-key.resolver.ts deleted file mode 100644 index 4f633e144..000000000 --- a/server/src/core/api-key/api-key.resolver.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; -import { NotFoundException, UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; - -import { AbilityGuard } from 'src/guards/ability.guard'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { CreateOneApiKeyArgs } from 'src/core/@generated/api-key/create-one-api-key.args'; -import { ApiKey } from 'src/core/@generated/api-key/api-key.model'; -import { FindManyApiKeyArgs } from 'src/core/@generated/api-key/find-many-api-key.args'; -import { DeleteOneApiKeyArgs } from 'src/core/@generated/api-key/delete-one-api-key.args'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreateApiKeyAbilityHandler, - UpdateApiKeyAbilityHandler, - ReadApiKeyAbilityHandler, -} from 'src/ability/handlers/api-key.ability-handler'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { ApiKeyToken } from 'src/core/auth/dto/token.entity'; - -import { ApiKeyService } from './api-key.service'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => ApiKey) -export class ApiKeyResolver { - constructor(private readonly apiKeyService: ApiKeyService) {} - - @Mutation(() => ApiKeyToken) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateApiKeyAbilityHandler) - async createOneApiKey( - @Args() args: CreateOneApiKeyArgs, - @AuthWorkspace() { id: workspaceId }: Workspace, - ): Promise { - return await this.apiKeyService.generateApiKeyToken( - workspaceId, - args.data.name, - args.data.expiresAt, - ); - } - - @Mutation(() => ApiKeyToken) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateApiKeyAbilityHandler) - async generateApiKeyV2Token( - @Args() - args: CreateOneApiKeyArgs, - @AuthWorkspace() { id: workspaceId }: Workspace, - ): Promise | undefined> { - return await this.apiKeyService.generateApiKeyV2Token( - workspaceId, - args.data.id, - args.data.expiresAt, - ); - } - - @Mutation(() => ApiKey) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateApiKeyAbilityHandler) - async revokeOneApiKey( - @Args() args: DeleteOneApiKeyArgs, - ): Promise> { - const apiKeyToDelete = await this.apiKeyService.findFirst({ - where: { ...args.where }, - }); - if (!apiKeyToDelete) { - throw new NotFoundException(); - } - return this.apiKeyService.update({ - where: args.where, - data: { - revokedAt: new Date(), - }, - }); - } - - @Query(() => [ApiKey]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadApiKeyAbilityHandler) - async findManyApiKey( - @Args() args: FindManyApiKeyArgs, - @UserAbility() ability: AppAbility, - ) { - const filterOptions = [ - accessibleBy(ability).WorkspaceMember, - { revokedAt: null }, - ]; - if (args.where) filterOptions.push(args.where); - return this.apiKeyService.findMany({ - ...args, - where: { AND: filterOptions }, - }); - } -} diff --git a/server/src/core/api-key/api-key.service.ts b/server/src/core/api-key/api-key.service.ts deleted file mode 100644 index d3a7de114..000000000 --- a/server/src/core/api-key/api-key.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Injectable, InternalServerErrorException } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; - -import { PrismaService } from 'src/database/prisma.service'; -import { ApiKeyToken } from 'src/core/auth/dto/token.entity'; -import { assert } from 'src/utils/assert'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; - -@Injectable() -export class ApiKeyService { - constructor( - private readonly prismaService: PrismaService, - private readonly environmentService: EnvironmentService, - private readonly jwtService: JwtService, - ) {} - - findFirst = this.prismaService.client.apiKey.findFirst; - findUniqueOrThrow = this.prismaService.client.apiKey.findUniqueOrThrow; - findMany = this.prismaService.client.apiKey.findMany; - create = this.prismaService.client.apiKey.create; - update = this.prismaService.client.apiKey.update; - delete = this.prismaService.client.apiKey.delete; - - async generateApiKeyV2Token( - workspaceId: string, - apiKeyId?: string, - expiresAt?: Date | string, - ): Promise | undefined> { - if (!apiKeyId) { - return; - } - const jwtPayload = { - sub: workspaceId, - }; - const secret = this.environmentService.getAccessTokenSecret(); - let expiresIn: string | number; - if (expiresAt) { - expiresIn = Math.floor( - (new Date(expiresAt).getTime() - new Date().getTime()) / 1000, - ); - } else { - expiresIn = this.environmentService.getApiTokenExpiresIn(); - } - const token = this.jwtService.sign(jwtPayload, { - secret, - expiresIn, - jwtid: apiKeyId, - }); - return { token }; - } - - async generateApiKeyToken( - workspaceId: string, - name: string, - expiresAt?: Date | string, - ): Promise { - const secret = this.environmentService.getAccessTokenSecret(); - let expiresIn: string | number; - const now = new Date().getTime(); - if (expiresAt) { - expiresIn = Math.floor((new Date(expiresAt).getTime() - now) / 1000); - } else { - expiresIn = this.environmentService.getApiTokenExpiresIn(); - } - assert(expiresIn, '', InternalServerErrorException); - const jwtPayload = { - sub: workspaceId, - }; - const newApiKey = await this.prismaService.client.apiKey.create({ - data: { - expiresAt: expiresAt, - name: name, - workspaceId: workspaceId, - }, - }); - return { - ...newApiKey, - token: this.jwtService.sign(jwtPayload, { - secret, - expiresIn, - jwtid: newApiKey.id, - }), - }; - } -} diff --git a/server/src/core/attachment/attachment.module.ts b/server/src/core/attachment/attachment.module.ts deleted file mode 100644 index 59595bd06..000000000 --- a/server/src/core/attachment/attachment.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { AttachmentResolver } from './resolvers/attachment.resolver'; -import { AttachmentService } from './services/attachment.service'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [AttachmentService, AttachmentResolver, FileUploadService], - exports: [AttachmentService], -}) -export class AttachmentModule {} diff --git a/server/src/core/attachment/resolvers/attachment.resolver.spec.ts b/server/src/core/attachment/resolvers/attachment.resolver.spec.ts deleted file mode 100644 index 5c2f2c19e..000000000 --- a/server/src/core/attachment/resolvers/attachment.resolver.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { AttachmentService } from 'src/core/attachment/services/attachment.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { AttachmentResolver } from './attachment.resolver'; - -describe('AttachmentResolver', () => { - let resolver: AttachmentResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - AttachmentResolver, - { - provide: FileUploadService, - useValue: {}, - }, - { - provide: AttachmentService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(AttachmentResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/attachment/resolvers/attachment.resolver.ts b/server/src/core/attachment/resolvers/attachment.resolver.ts deleted file mode 100644 index add55e4a1..000000000 --- a/server/src/core/attachment/resolvers/attachment.resolver.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Resolver, Args, Mutation } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { User, Workspace } from '@prisma/client'; -import { GraphQLUpload, FileUpload } from 'graphql-upload'; -import { v4 as uuidV4 } from 'uuid'; - -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; - -import { AuthUser } from 'src/decorators/auth-user.decorator'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { streamToBuffer } from 'src/utils/stream-to-buffer'; -import { AttachmentService } from 'src/core/attachment/services/attachment.service'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Attachment } from 'src/core/@generated/attachment/attachment.model'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CreateAttachmentAbilityHandler } from 'src/ability/handlers/attachment.ability-handler'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Attachment) -@Resolver() -export class AttachmentResolver { - constructor( - private readonly fileUploadService: FileUploadService, - private readonly attachmentService: AttachmentService, - ) {} - - @UseGuards(AbilityGuard) - @CheckAbilities(CreateAttachmentAbilityHandler) - @Mutation(() => String) - async uploadAttachment( - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - @Args({ name: 'file', type: () => GraphQLUpload }) - { createReadStream, filename, mimetype }: FileUpload, - @Args('activityId') activityId?: string, - @Args('companyId') companyId?: string, - @Args('personId') personId?: string, - ): Promise { - const stream = createReadStream(); - const buffer = await streamToBuffer(stream); - - const { path } = await this.fileUploadService.uploadFile({ - file: buffer, - filename, - mimeType: mimetype, - fileFolder: FileFolder.Attachment, - }); - - await this.attachmentService.create({ - data: { - id: uuidV4(), - fullPath: path, - type: this.attachmentService.getFileTypeFromFileName(filename), - name: filename, - activityId, - companyId, - personId, - authorId: user.id, - workspaceId: workspace.id, - }, - select: { - id: true, - fullPath: true, - }, - }); - - return path; - } -} diff --git a/server/src/core/attachment/services/attachment.service.spec.ts b/server/src/core/attachment/services/attachment.service.spec.ts deleted file mode 100644 index f40eab92f..000000000 --- a/server/src/core/attachment/services/attachment.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { AttachmentService } from './attachment.service'; - -describe('AttachmentService', () => { - let service: AttachmentService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - AttachmentService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(AttachmentService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/attachment/services/attachment.service.ts b/server/src/core/attachment/services/attachment.service.ts deleted file mode 100644 index 9b70b0733..000000000 --- a/server/src/core/attachment/services/attachment.service.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { AttachmentType } from '@prisma/client'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class AttachmentService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.attachment.findFirst; - findFirstOrThrow = this.prismaService.client.attachment.findFirstOrThrow; - - findUnique = this.prismaService.client.attachment.findUnique; - findUniqueOrThrow = this.prismaService.client.attachment.findUniqueOrThrow; - - findMany = this.prismaService.client.attachment.findMany; - - // Create - create = this.prismaService.client.attachment.create; - createMany = this.prismaService.client.attachment.createMany; - - // Update - update = this.prismaService.client.attachment.update; - upsert = this.prismaService.client.attachment.upsert; - updateMany = this.prismaService.client.attachment.updateMany; - - // Delete - delete = this.prismaService.client.attachment.delete; - deleteMany = this.prismaService.client.attachment.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.attachment.aggregate; - - // Count - count = this.prismaService.client.attachment.count; - - // GroupBy - groupBy = this.prismaService.client.attachment.groupBy; - - getFileTypeFromFileName(fileName: string): AttachmentType { - const extension = fileName.split('.').pop()?.toLowerCase(); - - switch (extension) { - case 'mp4': - case 'avi': - case 'mov': - return AttachmentType.Video; - - case 'mp3': - case 'wav': - case 'ogg': - return AttachmentType.Audio; - - case 'jpg': - case 'jpeg': - case 'png': - case 'gif': - return AttachmentType.Image; - - case 'txt': - case 'doc': - case 'docx': - case 'pdf': - return AttachmentType.TextDocument; - - case 'xls': - case 'xlsx': - case 'csv': - return AttachmentType.Spreadsheet; - - case 'zip': - case 'rar': - case 'tar': - case '7z': - return AttachmentType.Archive; - - default: - return AttachmentType.Other; - } - } -} diff --git a/server/src/core/auth/auth.module.ts b/server/src/core/auth/auth.module.ts index caebb345b..e89e456c7 100644 --- a/server/src/core/auth/auth.module.ts +++ b/server/src/core/auth/auth.module.ts @@ -1,11 +1,21 @@ +/* eslint-disable no-restricted-imports */ import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; -import { PrismaService } from 'src/database/prisma.service'; -import { UserModule } from 'src/core/user/user.module'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { WorkspaceModule } from 'src/core/workspace/workspace.module'; import { FileModule } from 'src/core/file/file.module'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { User } from 'src/core/user/user.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; +import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; +import { UserModule } from 'src/core/user/user.module'; +import { WorkspaceManagerModule } from 'src/workspace/workspace-manager/workspace-manager.module'; + +import config from '../../../ormconfig'; import { AuthResolver } from './auth.resolver'; @@ -28,15 +38,22 @@ const jwtModule = JwtModule.registerAsync({ }); @Module({ - imports: [jwtModule, UserModule, WorkspaceModule, FileModule], - controllers: [GoogleAuthController, VerifyAuthController], - providers: [ - AuthService, - TokenService, - JwtAuthStrategy, - PrismaService, - AuthResolver, + imports: [ + jwtModule, + FileModule, + DataSourceModule, + UserModule, + WorkspaceManagerModule, + TypeOrmModule.forRoot(config), + NestjsQueryGraphQLModule.forFeature({ + imports: [ + TypeOrmModule.forFeature([Workspace, User, RefreshToken]), + TypeORMModule, + ], + }), ], + controllers: [GoogleAuthController, VerifyAuthController], + providers: [AuthService, TokenService, JwtAuthStrategy, AuthResolver], exports: [jwtModule], }) export class AuthModule {} diff --git a/server/src/core/auth/auth.resolver.ts b/server/src/core/auth/auth.resolver.ts index d242b0989..88b2cdb29 100644 --- a/server/src/core/auth/auth.resolver.ts +++ b/server/src/core/auth/auth.resolver.ts @@ -4,21 +4,19 @@ import { ForbiddenException, UseGuards, } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; -import { Prisma } from '@prisma/client'; +import { Repository } from 'typeorm'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; import { AuthUser } from 'src/decorators/auth-user.decorator'; import { assert } from 'src/utils/assert'; -import { User } from 'src/core/@generated/user/user.model'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; +import { User } from 'src/core/user/user.entity'; +import { ApiKeyTokenInput } from 'src/core/auth/dto/api-key-token.input'; -import { AuthTokens } from './dto/token.entity'; +import { ApiKeyToken, AuthTokens } from './dto/token.entity'; import { TokenService } from './services/token.service'; import { RefreshTokenInput } from './dto/refresh-token.input'; import { Verify } from './dto/verify.entity'; @@ -36,7 +34,8 @@ import { ImpersonateInput } from './dto/impersonate.input'; @Resolver() export class AuthResolver { constructor( - private workspaceService: WorkspaceService, + @InjectRepository(Workspace) + private readonly workspaceRepository: Repository, private authService: AuthService, private tokenService: TokenService, ) {} @@ -64,10 +63,8 @@ export class AuthResolver { async findWorkspaceFromInviteHash( @Args() workspaceInviteHashValidInput: WorkspaceInviteHashValidInput, ) { - return await this.workspaceService.findFirst({ - where: { - inviteHash: workspaceInviteHashValidInput.inviteHash, - }, + return await this.workspaceRepository.findOneBy({ + inviteHash: workspaceInviteHashValidInput.inviteHash, }); } @@ -88,21 +85,12 @@ export class AuthResolver { } @Mutation(() => Verify) - async verify( - @Args() verifyInput: VerifyInput, - @PrismaSelector({ - modelName: 'User', - defaultFields: { User: { id: true } }, - }) - prismaSelect: PrismaSelect<'User'>, - ): Promise { + async verify(@Args() verifyInput: VerifyInput): Promise { const email = await this.tokenService.verifyLoginToken( verifyInput.loginToken, ); - const select = prismaSelect.valueOf('user') as Prisma.UserSelect & { - id: true; - }; - const result = await this.authService.verify(email, select); + + const result = await this.authService.verify(email); return result; } @@ -125,22 +113,24 @@ export class AuthResolver { async impersonate( @Args() impersonateInput: ImpersonateInput, @AuthUser() user: User, - @PrismaSelector({ - modelName: 'User', - defaultFields: { - User: { - id: true, - }, - }, - }) - prismaSelect: PrismaSelect<'User'>, ): Promise { // Check if user can impersonate assert(user.canImpersonate, 'User cannot impersonate', ForbiddenException); - const select = prismaSelect.valueOf('user') as Prisma.UserSelect & { - id: true; - }; - return this.authService.impersonate(impersonateInput.userId, select); + return this.authService.impersonate(impersonateInput.userId); + } + + @UseGuards(JwtAuthGuard) + @Mutation(() => ApiKeyToken) + async generateApiKeyToken( + @Args() args: ApiKeyTokenInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ): Promise { + console.log('toto'); + return await this.tokenService.generateApiKeyToken( + workspaceId, + args.apiKeyId, + args.expiresAt, + ); } } diff --git a/server/src/core/auth/controllers/google-auth.controller.ts b/server/src/core/auth/controllers/google-auth.controller.ts index 96c83e258..96ca2957a 100644 --- a/server/src/core/auth/controllers/google-auth.controller.ts +++ b/server/src/core/auth/controllers/google-auth.controller.ts @@ -1,29 +1,29 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; import { Response } from 'express'; -import FileType from 'file-type'; -import { v4 as uuidV4 } from 'uuid'; - -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; +import { Repository } from 'typeorm'; import { GoogleRequest } from 'src/core/auth/strategies/google.auth.strategy'; -import { UserService } from 'src/core/user/user.service'; import { TokenService } from 'src/core/auth/services/token.service'; import { GoogleProviderEnabledGuard } from 'src/core/auth/guards/google-provider-enabled.guard'; import { GoogleOauthGuard } from 'src/core/auth/guards/google-oauth.guard'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { AuthService } from 'src/core/auth/services/auth.service'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { getImageBufferFromUrl } from 'src/utils/image'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; @Controller('auth/google') export class GoogleAuthController { constructor( private readonly tokenService: TokenService, - private readonly userService: UserService, - private readonly workspaceService: WorkspaceService, private readonly environmentService: EnvironmentService, - private readonly fileUploadService: FileUploadService, + private readonly typeORMService: TypeORMService, + private readonly authService: AuthService, + @InjectRepository(Workspace) + @InjectRepository(User, 'metadata') + private readonly userRepository: Repository, ) {} @Get() @@ -39,65 +39,29 @@ export class GoogleAuthController { const { firstName, lastName, email, picture, workspaceInviteHash } = req.user; - let workspaceId: string | undefined = undefined; - if (workspaceInviteHash) { - const workspace = await this.workspaceService.findFirst({ - where: { - inviteHash: workspaceInviteHash, - }, - }); + const mainDataSource = await this.typeORMService.getMainDataSource(); - if (!workspace) { - return res.redirect( - `${this.environmentService.getFrontAuthCallbackUrl()}`, - ); - } + const existingUser = await mainDataSource + .getRepository(User) + .findOneBy({ email: email }); - workspaceId = workspace.id; + if (existingUser) { + const loginToken = await this.tokenService.generateLoginToken( + existingUser.email, + ); + + return res.redirect( + this.tokenService.computeRedirectURI(loginToken.token), + ); } - let user = await this.userService.createUser( - { - data: { - email, - firstName: firstName ?? '', - lastName: lastName ?? '', - locale: 'en', - }, - }, - workspaceId, - ); - - if (!user.avatarUrl) { - let imagePath: string | undefined = undefined; - - if (picture) { - // Get image buffer from url - const buffer = await getImageBufferFromUrl(picture); - - // Extract mimetype and extension from buffer - const type = await FileType.fromBuffer(buffer); - - // Upload image - const { paths } = await this.fileUploadService.uploadImage({ - file: buffer, - filename: `${uuidV4()}.${type?.ext}`, - mimeType: type?.mime, - fileFolder: FileFolder.ProfilePicture, - }); - - imagePath = paths[0]; - } - - user = await this.userService.update({ - where: { - id: user.id, - }, - data: { - avatarUrl: imagePath, - }, - }); - } + const user = await this.authService.signUp({ + email, + firstName, + lastName, + picture, + workspaceInviteHash, + }); const loginToken = await this.tokenService.generateLoginToken(user.email); diff --git a/server/src/core/auth/controllers/verify-auth.controller.ts b/server/src/core/auth/controllers/verify-auth.controller.ts index 0323c5c8b..b427ad974 100644 --- a/server/src/core/auth/controllers/verify-auth.controller.ts +++ b/server/src/core/auth/controllers/verify-auth.controller.ts @@ -17,13 +17,7 @@ export class VerifyAuthController { const email = await this.tokenService.verifyLoginToken( verifyInput.loginToken, ); - const result = await this.authService.verify(email, { - id: true, - firstName: true, - lastName: true, - email: true, - emailVerified: true, - }); + const result = await this.authService.verify(email); return result; } diff --git a/server/src/core/auth/dto/api-key-token.input.ts b/server/src/core/auth/dto/api-key-token.input.ts new file mode 100644 index 000000000..c3dc2d6c1 --- /dev/null +++ b/server/src/core/auth/dto/api-key-token.input.ts @@ -0,0 +1,15 @@ +import { ArgsType, Field } from '@nestjs/graphql'; + +import { IsNotEmpty, IsString } from 'class-validator'; + +@ArgsType() +export class ApiKeyTokenInput { + @Field(() => String) + @IsNotEmpty() + @IsString() + apiKeyId: string; + + @Field(() => String) + @IsNotEmpty() + expiresAt: string; +} diff --git a/server/src/core/auth/dto/token.entity.ts b/server/src/core/auth/dto/token.entity.ts index 3ffdf4420..391501041 100644 --- a/server/src/core/auth/dto/token.entity.ts +++ b/server/src/core/auth/dto/token.entity.ts @@ -1,7 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { ApiKey } from 'src/core/@generated/api-key/api-key.model'; - @ObjectType() export class AuthToken { @Field(() => String) @@ -12,7 +10,7 @@ export class AuthToken { } @ObjectType() -export class ApiKeyToken extends ApiKey { +export class ApiKeyToken { @Field(() => String) token: string; } diff --git a/server/src/core/auth/dto/verify.entity.ts b/server/src/core/auth/dto/verify.entity.ts index ddf5e25b1..203599931 100644 --- a/server/src/core/auth/dto/verify.entity.ts +++ b/server/src/core/auth/dto/verify.entity.ts @@ -1,6 +1,6 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { User } from 'src/core/@generated/user/user.model'; +import { User } from 'src/core/user/user.entity'; import { AuthTokens } from './token.entity'; diff --git a/server/src/core/auth/services/auth.service.ts b/server/src/core/auth/services/auth.service.ts index e575327b0..c0a55ae80 100644 --- a/server/src/core/auth/services/auth.service.ts +++ b/server/src/core/auth/services/auth.service.ts @@ -4,11 +4,15 @@ import { Injectable, NotFoundException, } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; -import { Prisma } from '@prisma/client'; +import FileType from 'file-type'; +import { Repository } from 'typeorm'; +import { v4 } from 'uuid'; + +import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; import { ChallengeInput } from 'src/core/auth/dto/challenge.input'; -import { UserService } from 'src/core/user/user.service'; import { assert } from 'src/utils/assert'; import { PASSWORD_REGEX, @@ -17,9 +21,13 @@ import { } from 'src/core/auth/auth.util'; import { Verify } from 'src/core/auth/dto/verify.entity'; import { UserExists } from 'src/core/auth/dto/user-exists.entity'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; import { WorkspaceInviteHashValid } from 'src/core/auth/dto/workspace-invite-hash-valid.entity'; -import { SignUpInput } from 'src/core/auth/dto/sign-up.input'; +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { UserService } from 'src/core/user/services/user.service'; +import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspace-manager.service'; +import { getImageBufferFromUrl } from 'src/utils/image'; +import { FileUploadService } from 'src/core/file/services/file-upload.service'; import { TokenService } from './token.service'; @@ -34,14 +42,17 @@ export class AuthService { constructor( private readonly tokenService: TokenService, private readonly userService: UserService, - private readonly workspaceService: WorkspaceService, + private readonly workspaceManagerService: WorkspaceManagerService, + private readonly fileUploadService: FileUploadService, + @InjectRepository(Workspace) + private readonly workspaceRepository: Repository, + @InjectRepository(User) + private readonly userRepository: Repository, ) {} async challenge(challengeInput: ChallengeInput) { - const user = await this.userService.findUnique({ - where: { - email: challengeInput.email, - }, + const user = await this.userRepository.findOneBy({ + email: challengeInput.email, }); assert(user, "This user doesn't exist", NotFoundException); @@ -57,24 +68,40 @@ export class AuthService { return user; } - async signUp(signUpInput: SignUpInput) { - const existingUser = await this.userService.findUnique({ - where: { - email: signUpInput.email, - }, + async signUp({ + email, + password, + workspaceInviteHash, + firstName, + lastName, + picture, + }: { + email: string; + password?: string; + firstName?: string | null; + lastName?: string | null; + workspaceInviteHash?: string | null; + picture?: string | null; + }) { + if (!firstName) firstName = ''; + if (!lastName) lastName = ''; + + const existingUser = await this.userRepository.findOneBy({ + email: email, }); assert(!existingUser, 'This user already exists', ForbiddenException); - const isPasswordValid = PASSWORD_REGEX.test(signUpInput.password); - assert(isPasswordValid, 'Password too weak', BadRequestException); + if (password) { + const isPasswordValid = PASSWORD_REGEX.test(password); + assert(isPasswordValid, 'Password too weak', BadRequestException); + } - const passwordHash = await hashPassword(signUpInput.password); + const passwordHash = password ? await hashPassword(password) : undefined; + let workspace: Workspace | null; - if (signUpInput.workspaceInviteHash) { - const workspace = await this.workspaceService.findFirst({ - where: { - inviteHash: signUpInput.workspaceInviteHash, - }, + if (workspaceInviteHash) { + workspace = await this.workspaceRepository.findOneBy({ + inviteHash: workspaceInviteHash, }); assert( @@ -82,44 +109,59 @@ export class AuthService { 'This workspace inviteHash is invalid', ForbiddenException, ); - - return await this.userService.createUser( - { - data: { - email: signUpInput.email, - passwordHash, - }, - } as Prisma.UserCreateArgs, - workspace.id, - ); + } else { + const workspaceToCreate = this.workspaceRepository.create({ + displayName: '', + domainName: '', + inviteHash: v4(), + }); + workspace = await this.workspaceRepository.save(workspaceToCreate); + await this.workspaceManagerService.init(workspace.id); } - return await this.userService.createUser({ - data: { - email: signUpInput.email, - passwordHash, - locale: 'en', - }, - } as Prisma.UserCreateArgs); + const userToCreate = this.userRepository.create({ + email: email, + firstName: firstName, + lastName: lastName, + canImpersonate: false, + passwordHash, + defaultWorkspace: workspace, + }); + const user = await this.userRepository.save(userToCreate); + let imagePath: string | undefined = undefined; + + if (picture) { + const buffer = await getImageBufferFromUrl(picture); + + const type = await FileType.fromBuffer(buffer); + + const { paths } = await this.fileUploadService.uploadImage({ + file: buffer, + filename: `${v4()}.${type?.ext}`, + mimeType: type?.mime, + fileFolder: FileFolder.ProfilePicture, + }); + + imagePath = paths[0]; + } + await this.userService.createWorkspaceMember(user, imagePath); + + return user; } - async verify( - email: string, - select: Prisma.UserSelect & { - id: true; - }, - ): Promise { - const user = await this.userService.findUnique({ + async verify(email: string): Promise { + const user = await this.userRepository.findOne({ where: { email, }, - select, + relations: ['defaultWorkspace'], }); assert(user, "This user doesn't exist", NotFoundException); // passwordHash is hidden for security reasons user.passwordHash = ''; + user.workspaceMember = await this.userService.loadWorkspaceMember(user); const accessToken = await this.tokenService.generateAccessToken(user.id); const refreshToken = await this.tokenService.generateRefreshToken(user.id); @@ -134,10 +176,8 @@ export class AuthService { } async checkUserExists(email: string): Promise { - const user = await this.userService.findUnique({ - where: { - email, - }, + const user = await this.userRepository.findOneBy({ + email, }); return { exists: !!user }; @@ -146,26 +186,16 @@ export class AuthService { async checkWorkspaceInviteHashIsValid( inviteHash: string, ): Promise { - const workspace = await this.workspaceService.findFirst({ - where: { - inviteHash, - }, + const workspace = await this.workspaceRepository.findOneBy({ + inviteHash, }); return { isValid: !!workspace }; } - async impersonate( - userId: string, - select: Prisma.UserSelect & { - id: true; - }, - ) { - const user = await this.userService.findUnique({ - where: { - id: userId, - }, - select, + async impersonate(userId: string) { + const user = await this.userRepository.findOneBy({ + id: userId, }); assert(user, "This user doesn't exist", NotFoundException); diff --git a/server/src/core/auth/services/token.service.spec.ts b/server/src/core/auth/services/token.service.spec.ts index c28e5be87..19aecaaed 100644 --- a/server/src/core/auth/services/token.service.spec.ts +++ b/server/src/core/auth/services/token.service.spec.ts @@ -1,8 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { JwtService } from '@nestjs/jwt'; -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { TokenService } from './token.service'; @@ -22,10 +20,6 @@ describe('TokenService', () => { provide: EnvironmentService, useValue: {}, }, - { - provide: PrismaService, - useValue: prismaMock, - }, ], }).compile(); diff --git a/server/src/core/auth/services/token.service.ts b/server/src/core/auth/services/token.service.ts index 13943c4a1..6aaab72d6 100644 --- a/server/src/core/auth/services/token.service.ts +++ b/server/src/core/auth/services/token.service.ts @@ -7,23 +7,29 @@ import { UnprocessableEntityException, } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; +import { InjectRepository } from '@nestjs/typeorm'; import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { TokenExpiredError } from 'jsonwebtoken'; +import { Repository } from 'typeorm'; import { JwtPayload } from 'src/core/auth/strategies/jwt.auth.strategy'; -import { PrismaService } from 'src/database/prisma.service'; import { assert } from 'src/utils/assert'; -import { AuthToken } from 'src/core/auth/dto/token.entity'; +import { ApiKeyToken, AuthToken } from 'src/core/auth/dto/token.entity'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { User } from 'src/core/user/user.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; @Injectable() export class TokenService { constructor( private readonly jwtService: JwtService, private readonly environmentService: EnvironmentService, - private readonly prismaService: PrismaService, + @InjectRepository(User) + private readonly userRepository: Repository, + @InjectRepository(RefreshToken) + private readonly refreshTokenRepository: Repository, ) {} async generateAccessToken(userId: string): Promise { @@ -31,23 +37,26 @@ export class TokenService { assert(expiresIn, '', InternalServerErrorException); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); - const user = await this.prismaService.client.user.findUnique({ + const user = await this.userRepository.findOne({ where: { id: userId }, + relations: ['defaultWorkspace'], }); if (!user) { throw new NotFoundException('User is not found'); } - if (!user.defaultWorkspaceId) { + if (!user.defaultWorkspace) { throw new NotFoundException('User does not have a default workspace'); } const jwtPayload: JwtPayload = { sub: user.id, - workspaceId: user.defaultWorkspaceId, + workspaceId: user.defaultWorkspace.id, }; + console.log(jwtPayload); + return { token: this.jwtService.sign(jwtPayload), expiresAt, @@ -68,9 +77,13 @@ export class TokenService { sub: userId, }; - const refreshToken = await this.prismaService.client.refreshToken.create({ - data: refreshTokenPayload, - }); + const refreshToken = + this.refreshTokenRepository.create(refreshTokenPayload); + console.log(refreshToken); + + await this.refreshTokenRepository.save(refreshToken); + + console.log('toto'); return { token: this.jwtService.sign(jwtPayload, { @@ -101,6 +114,34 @@ export class TokenService { }; } + async generateApiKeyToken( + workspaceId: string, + apiKeyId?: string, + expiresAt?: Date | string, + ): Promise | undefined> { + if (!apiKeyId) { + return; + } + const jwtPayload = { + sub: workspaceId, + }; + const secret = this.environmentService.getAccessTokenSecret(); + let expiresIn: string | number; + if (expiresAt) { + expiresIn = Math.floor( + (new Date(expiresAt).getTime() - new Date().getTime()) / 1000, + ); + } else { + expiresIn = this.environmentService.getApiTokenExpiresIn(); + } + const token = this.jwtService.sign(jwtPayload, { + secret, + expiresIn, + jwtid: apiKeyId, + }); + return { token }; + } + async verifyLoginToken(loginToken: string): Promise { const loginTokenSecret = this.environmentService.getLoginTokenSecret(); @@ -120,19 +161,14 @@ export class TokenService { UnprocessableEntityException, ); - const token = await this.prismaService.client.refreshToken.findUnique({ - where: { id: jwtPayload.jti }, + const token = await this.refreshTokenRepository.findOneBy({ + id: jwtPayload.jti, }); assert(token, "This refresh token doesn't exist", NotFoundException); - const user = await this.prismaService.client.user.findUnique({ - where: { - id: jwtPayload.sub, - }, - include: { - refreshTokens: true, - }, + const user = await this.userRepository.findOneBy({ + id: jwtPayload.sub, }); assert(user, 'User not found', NotFoundException); @@ -143,16 +179,17 @@ export class TokenService { token.revokedAt.getTime() <= Date.now() - ms(coolDown) ) { // Revoke all user refresh tokens - await this.prismaService.client.refreshToken.updateMany({ - where: { - id: { - in: user.refreshTokens.map(({ id }) => id), - }, - }, - data: { - revokedAt: new Date(), - }, - }); + await Promise.all( + user.refreshTokens.map( + async ({ id }) => + await this.refreshTokenRepository.update( + { id }, + { + revokedAt: new Date(), + }, + ), + ), + ); throw new ForbiddenException( 'Suspicious activity detected, this refresh token has been revoked. All tokens has been revoked.', @@ -172,14 +209,14 @@ export class TokenService { } = await this.verifyRefreshToken(token); // Revoke old refresh token - await this.prismaService.client.refreshToken.update({ - where: { + await this.refreshTokenRepository.update( + { id, }, - data: { + { revokedAt: new Date(), }, - }); + ); const accessToken = await this.generateAccessToken(user.id); const refreshToken = await this.generateRefreshToken(user.id); diff --git a/server/src/core/auth/strategies/jwt.auth.strategy.ts b/server/src/core/auth/strategies/jwt.auth.strategy.ts index e12003fcd..a03ef51ad 100644 --- a/server/src/core/auth/strategies/jwt.auth.strategy.ts +++ b/server/src/core/auth/strategies/jwt.auth.strategy.ts @@ -1,16 +1,13 @@ import { PassportStrategy } from '@nestjs/passport'; -import { - ForbiddenException, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; import { Strategy, ExtractJwt } from 'passport-jwt'; -import { User, Workspace } from '@prisma/client'; +import { Repository } from 'typeorm'; -import { PrismaService } from 'src/database/prisma.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { assert } from 'src/utils/assert'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { User } from 'src/core/user/user.entity'; export type JwtPayload = { sub: string; workspaceId: string; jti?: string }; export type PassportUser = { user?: User; workspace: Workspace }; @@ -19,7 +16,10 @@ export type PassportUser = { user?: User; workspace: Workspace }; export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { constructor( private readonly environmentService: EnvironmentService, - private readonly prismaService: PrismaService, + @InjectRepository(Workspace) + private readonly workspaceRepository: Repository, + @InjectRepository(User) + private readonly userRepository: Repository, ) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), @@ -29,26 +29,30 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { } async validate(payload: JwtPayload): Promise { - const workspace = await this.prismaService.client.workspace.findUnique({ - where: { id: payload.workspaceId ?? payload.sub }, + const workspace = await this.workspaceRepository.findOneBy({ + id: payload.workspaceId ?? payload.sub, }); if (!workspace) { throw new UnauthorizedException(); } if (payload.jti) { // If apiKey has been deleted or revoked, we throw an error - const apiKey = await this.prismaService.client.apiKey.findUniqueOrThrow({ - where: { id: payload.jti }, - }); - assert(!apiKey.revokedAt, 'This API Key is revoked', ForbiddenException); + // const apiKey = await this.prismaService.client.apiKey.findUniqueOrThrow({ + // where: { id: payload.jti }, + // }); + // assert(!apiKey.revokedAt, 'This API Key is revoked', ForbiddenException); } const user = payload.workspaceId - ? await this.prismaService.client.user.findUniqueOrThrow({ - where: { id: payload.sub }, + ? await this.userRepository.findOneBy({ + id: payload.sub, }) : undefined; + if (!user) { + throw new UnauthorizedException(); + } + return { user, workspace }; } } diff --git a/server/src/core/comment/comment.module.ts b/server/src/core/comment/comment.module.ts deleted file mode 100644 index 8a2937584..000000000 --- a/server/src/core/comment/comment.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { CommentService } from './comment.service'; -import { CommentResolver } from './comment.resolver'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [CommentService, CommentResolver], - exports: [CommentService], -}) -export class CommentModule {} diff --git a/server/src/core/comment/comment.resolver.spec.ts b/server/src/core/comment/comment.resolver.spec.ts deleted file mode 100644 index ccc45ffab..000000000 --- a/server/src/core/comment/comment.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { CommentService } from 'src/core/comment/comment.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { CommentResolver } from './comment.resolver'; - -describe('CommentResolver', () => { - let resolver: CommentResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CommentResolver, - { - provide: CommentService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(CommentResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/comment/comment.resolver.ts b/server/src/core/comment/comment.resolver.ts deleted file mode 100644 index 053ee74e1..000000000 --- a/server/src/core/comment/comment.resolver.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Resolver, Args, Mutation } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { Prisma } from '@prisma/client'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { CreateOneCommentArgs } from 'src/core/@generated/comment/create-one-comment.args'; -import { Comment } from 'src/core/@generated/comment/comment.model'; -import { CommentService } from 'src/core/comment/comment.service'; -import { - PrismaSelector, - PrismaSelect, -} from 'src/decorators/prisma-select.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { CreateCommentAbilityHandler } from 'src/ability/handlers/comment.ability-handler'; -import { AuthUser } from 'src/decorators/auth-user.decorator'; -import { User } from 'src/core/@generated/user/user.model'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Comment) -export class CommentResolver { - constructor(private readonly commentService: CommentService) {} - - @Mutation(() => Comment, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateCommentAbilityHandler) - async createOneComment( - @Args() args: CreateOneCommentArgs, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Comment' }) - prismaSelect: PrismaSelect<'Comment'>, - ): Promise> { - return this.commentService.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspace.id } } }, - }, - select: prismaSelect.value, - } as Prisma.CommentCreateArgs); - } -} diff --git a/server/src/core/comment/comment.service.spec.ts b/server/src/core/comment/comment.service.spec.ts deleted file mode 100644 index 049d0c6c2..000000000 --- a/server/src/core/comment/comment.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { CommentService } from './comment.service'; - -describe('CommentService', () => { - let service: CommentService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CommentService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(CommentService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/comment/comment.service.ts b/server/src/core/comment/comment.service.ts deleted file mode 100644 index 846112797..000000000 --- a/server/src/core/comment/comment.service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class CommentService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.comment.findFirst; - findFirstOrThrow = this.prismaService.client.comment.findFirstOrThrow; - - findUnique = this.prismaService.client.comment.findUnique; - findUniqueOrThrow = this.prismaService.client.comment.findUniqueOrThrow; - - findMany = this.prismaService.client.comment.findMany; - - // Create - create = this.prismaService.client.comment.create; - createMany = this.prismaService.client.comment.createMany; - - // Update - update = this.prismaService.client.comment.update; - upsert = this.prismaService.client.comment.upsert; - updateMany = this.prismaService.client.comment.updateMany; - - // Delete - delete = this.prismaService.client.comment.delete; - deleteMany = this.prismaService.client.comment.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.comment.aggregate; - - // Count - count = this.prismaService.client.comment.count; - - // GroupBy - groupBy = this.prismaService.client.comment.groupBy; -} diff --git a/server/src/core/company/company-relations.resolver.spec.ts b/server/src/core/company/company-relations.resolver.spec.ts deleted file mode 100644 index 7cb12bbda..000000000 --- a/server/src/core/company/company-relations.resolver.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { CommentService } from 'src/core/comment/comment.service'; -import { ActivityService } from 'src/core/activity/services/activity.service'; - -import { CompanyRelationsResolver } from './company-relations.resolver'; -import { CompanyService } from './company.service'; - -describe('CompanyRelationsResolver', () => { - let resolver: CompanyRelationsResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CompanyRelationsResolver, - { - provide: CompanyService, - useValue: {}, - }, - { - provide: ActivityService, - useValue: {}, - }, - { - provide: CommentService, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(CompanyRelationsResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/company/company-relations.resolver.ts b/server/src/core/company/company-relations.resolver.ts deleted file mode 100644 index e432fddee..000000000 --- a/server/src/core/company/company-relations.resolver.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Resolver, ResolveField, Root, Int } from '@nestjs/graphql'; - -import { Comment } from 'src/core/@generated/comment/comment.model'; -import { Company } from 'src/core/@generated/company/company.model'; -import { CommentService } from 'src/core/comment/comment.service'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { ActivityService } from 'src/core/activity/services/activity.service'; -import { Activity } from 'src/core/@generated/activity/activity.model'; - -@Resolver(() => Company) -export class CompanyRelationsResolver { - constructor( - private readonly activityService: ActivityService, - private readonly commentService: CommentService, - ) {} - - @ResolveField(() => [Activity], { - nullable: false, - }) - async activities( - @Root() company: Company, - @PrismaSelector({ modelName: 'Activity' }) - prismaSelect: PrismaSelect<'Activity'>, - ): Promise[]> { - return this.activityService.findMany({ - where: { - activityTargets: { - some: { - companyId: company.id, - }, - }, - }, - select: prismaSelect.value, - }); - } - - @ResolveField(() => [Comment], { - nullable: false, - }) - async comments( - @Root() company: Company, - @PrismaSelector({ modelName: 'Comment' }) - prismaSelect: PrismaSelect<'Comment'>, - ): Promise[]> { - return this.commentService.findMany({ - where: { - activity: { - activityTargets: { - some: { - companyId: company.id, - }, - }, - }, - }, - select: prismaSelect.value, - }); - } - - @ResolveField(() => Int, { - nullable: false, - }) - async _activityCount(@Root() company: Company): Promise { - return this.activityService.count({ - where: { - activityTargets: { - some: { - companyId: company.id, - }, - }, - }, - }); - } -} diff --git a/server/src/core/company/company.module.ts b/server/src/core/company/company.module.ts deleted file mode 100644 index fd757a8ff..000000000 --- a/server/src/core/company/company.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { CommentModule } from 'src/core/comment/comment.module'; -import { ActivityModule } from 'src/core/activity/activity.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { CompanyService } from './company.service'; -import { CompanyResolver } from './company.resolver'; -import { CompanyRelationsResolver } from './company-relations.resolver'; - -@Module({ - imports: [CommentModule, ActivityModule, AbilityModule, PrismaModule], - providers: [CompanyService, CompanyResolver, CompanyRelationsResolver], - exports: [CompanyService], -}) -export class CompanyModule {} diff --git a/server/src/core/company/company.resolver.spec.ts b/server/src/core/company/company.resolver.spec.ts deleted file mode 100644 index c1680b544..000000000 --- a/server/src/core/company/company.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { CompanyService } from './company.service'; -import { CompanyResolver } from './company.resolver'; - -describe('CompanyResolver', () => { - let resolver: CompanyResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CompanyResolver, - { - provide: CompanyService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(CompanyResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/company/company.resolver.ts b/server/src/core/company/company.resolver.ts deleted file mode 100644 index 0ec462fdc..000000000 --- a/server/src/core/company/company.resolver.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { Resolver, Query, Args, Mutation } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { Prisma, Workspace } from '@prisma/client'; -import { accessibleBy } from '@casl/prisma'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { Company } from 'src/core/@generated/company/company.model'; -import { FindManyCompanyArgs } from 'src/core/@generated/company/find-many-company.args'; -import { UpdateOneCompanyArgs } from 'src/core/@generated/company/update-one-company.args'; -import { CreateOneCompanyArgs } from 'src/core/@generated/company/create-one-company.args'; -import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output'; -import { DeleteManyCompanyArgs } from 'src/core/@generated/company/delete-many-company.args'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreateCompanyAbilityHandler, - DeleteCompanyAbilityHandler, - ReadOneCompanyAbilityHandler, - UpdateCompanyAbilityHandler, -} from 'src/ability/handlers/company.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { FindUniqueCompanyArgs } from 'src/core/@generated/company/find-unique-company.args'; -import { CreateManyCompanyArgs } from 'src/core/@generated/company/create-many-company.args'; - -import { CompanyService } from './company.service'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Company) -export class CompanyResolver { - constructor(private readonly companyService: CompanyService) {} - - @Query(() => [Company]) - @UseGuards(AbilityGuard) - async findManyCompany( - @Args() args: FindManyCompanyArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'Company' }) - prismaSelect: PrismaSelect<'Company'>, - ): Promise[]> { - return this.companyService.findMany({ - where: args.where - ? { - AND: [args.where, accessibleBy(ability).Company], - } - : accessibleBy(ability).Company, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - } - - @Query(() => Company) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadOneCompanyAbilityHandler) - async findUniqueCompany( - @Args() args: FindUniqueCompanyArgs, - @PrismaSelector({ modelName: 'Company' }) - prismaSelect: PrismaSelect<'Company'>, - ): Promise> { - const company = this.companyService.findUniqueOrThrow({ - where: args.where, - select: prismaSelect.value, - }); - - return company; - } - - @Mutation(() => Company, { - nullable: true, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateCompanyAbilityHandler) - async updateOneCompany( - @Args() args: UpdateOneCompanyArgs, - @PrismaSelector({ modelName: 'Company' }) - prismaSelect: PrismaSelect<'Company'>, - ): Promise | null> { - return this.companyService.update({ - where: args.where, - data: args.data, - select: prismaSelect.value, - } as Prisma.CompanyUpdateArgs); - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteCompanyAbilityHandler) - async deleteManyCompany( - @Args() args: DeleteManyCompanyArgs, - ): Promise { - return this.companyService.deleteMany({ - where: args.where, - }); - } - - @Mutation(() => Company, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateCompanyAbilityHandler) - async createOneCompany( - @Args() args: CreateOneCompanyArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Company' }) - prismaSelect: PrismaSelect<'Company'>, - ): Promise> { - return this.companyService.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspace.id } } }, - }, - select: prismaSelect.value, - } as Prisma.CompanyCreateArgs); - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateCompanyAbilityHandler) - async createManyCompany( - @Args() args: CreateManyCompanyArgs, - @AuthWorkspace() workspace: Workspace, - ): Promise { - return this.companyService.createMany({ - data: args.data.map((company) => ({ - ...company, - workspaceId: workspace.id, - })), - skipDuplicates: args.skipDuplicates, - }); - } -} diff --git a/server/src/core/company/company.service.spec.ts b/server/src/core/company/company.service.spec.ts deleted file mode 100644 index b5a09b25f..000000000 --- a/server/src/core/company/company.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { CompanyService } from './company.service'; - -describe('CompanyService', () => { - let service: CompanyService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - CompanyService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(CompanyService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/company/company.service.ts b/server/src/core/company/company.service.ts deleted file mode 100644 index 769510c7e..000000000 --- a/server/src/core/company/company.service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; -import companiesSeed from 'src/core/company/seed-data/companies.json'; - -@Injectable() -export class CompanyService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.company.findFirst; - findFirstOrThrow = this.prismaService.client.company.findFirstOrThrow; - - findUnique = this.prismaService.client.company.findUnique; - findUniqueOrThrow = this.prismaService.client.company.findUniqueOrThrow; - - findMany = this.prismaService.client.company.findMany; - - // Create - create = this.prismaService.client.company.create; - createMany = this.prismaService.client.company.createMany; - - // Update - update = this.prismaService.client.company.update; - upsert = this.prismaService.client.company.upsert; - updateMany = this.prismaService.client.company.updateMany; - - // Delete - delete = this.prismaService.client.company.delete; - deleteMany = this.prismaService.client.company.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.company.aggregate; - - // Count - count = this.prismaService.client.company.count; - - // GroupBy - groupBy = this.prismaService.client.company.groupBy; - async createDefaultCompanies({ workspaceId }: { workspaceId: string }) { - const companies = companiesSeed.map((company) => ({ - ...company, - workspaceId, - })); - await this.createMany({ - data: companies, - }); - - return this.findMany({ where: { workspaceId } }); - } -} diff --git a/server/src/core/company/seed-data/companies.json b/server/src/core/company/seed-data/companies.json deleted file mode 100644 index 9d4c0aead..000000000 --- a/server/src/core/company/seed-data/companies.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "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 - } - ] - \ No newline at end of file diff --git a/server/src/core/core.module.ts b/server/src/core/core.module.ts index 3cce419bc..71ff9e6da 100644 --- a/server/src/core/core.module.ts +++ b/server/src/core/core.module.ts @@ -1,62 +1,24 @@ import { Module } from '@nestjs/common'; -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 { WorkspaceModule as WorkspaceV2Module } from 'src/coreV2/workspace/workspace.module'; +import { WorkspaceModule } from 'src/core/workspace/workspace.module'; +import { UserModule } from 'src/core/user/user.module'; +import { RefreshTokenModule } from 'src/core/refresh-token/refresh-token.module'; +import { AuthModule } from 'src/core/auth/auth.module'; -import { UserModule } from './user/user.module'; -import { CommentModule } from './comment/comment.module'; -import { CompanyModule } from './company/company.module'; -import { PersonModule } from './person/person.module'; -import { PipelineModule } from './pipeline/pipeline.module'; -import { AuthModule } from './auth/auth.module'; -import { WorkspaceModule } from './workspace/workspace.module'; import { AnalyticsModule } from './analytics/analytics.module'; import { FileModule } from './file/file.module'; import { ClientConfigModule } from './client-config/client-config.module'; -import { AttachmentModule } from './attachment/attachment.module'; -import { ActivityModule } from './activity/activity.module'; -import { FavoriteModule } from './favorite/favorite.module'; -import { ApiKeyModule } from './api-key/api-key.module'; @Module({ imports: [ AuthModule, - UserModule, - CommentModule, - CompanyModule, - PersonModule, - PipelineModule, WorkspaceModule, + UserModule, + RefreshTokenModule, AnalyticsModule, FileModule, ClientConfigModule, - AttachmentModule, - ActivityModule, - FavoriteModule, - ApiKeyModule, - WebHookModule, - UserV2Module, - RefreshTokenV2Module, - WorkspaceV2Module, - ], - exports: [ - AuthModule, - UserModule, - CommentModule, - CompanyModule, - PersonModule, - PipelineModule, - WorkspaceModule, - AnalyticsModule, - AttachmentModule, - FavoriteModule, - ApiKeyModule, - WebHookModule, - UserV2Module, - RefreshTokenV2Module, - WorkspaceV2Module, ], + exports: [AuthModule, WorkspaceModule, UserModule, AnalyticsModule], }) export class CoreModule {} diff --git a/server/src/core/favorite/favorite.module.ts b/server/src/core/favorite/favorite.module.ts deleted file mode 100644 index eb7349bf3..000000000 --- a/server/src/core/favorite/favorite.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { FavoriteResolver } from './resolvers/favorite.resolver'; -import { FavoriteService } from './services/favorite.service'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [FavoriteService, FavoriteResolver], - exports: [FavoriteService], -}) -export class FavoriteModule {} diff --git a/server/src/core/favorite/resolvers/favorite.resolver.ts b/server/src/core/favorite/resolvers/favorite.resolver.ts deleted file mode 100644 index 2c6b05ecb..000000000 --- a/server/src/core/favorite/resolvers/favorite.resolver.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { - Resolver, - Query, - Args, - Mutation, - InputType, - Field, -} from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { Prisma, Workspace } from '@prisma/client'; - -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Favorite } from 'src/core/@generated/favorite/favorite.model'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreateFavoriteAbilityHandler, - DeleteFavoriteAbilityHandler, - ReadFavoriteAbilityHandler, - UpdateFavoriteAbilityHandler, -} from 'src/ability/handlers/favorite.ability-handler'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { FavoriteService } from 'src/core/favorite/services/favorite.service'; -import { FavoriteWhereInput } from 'src/core/@generated/favorite/favorite-where.input'; -import { SortOrder } from 'src/core/@generated/prisma/sort-order.enum'; -import { UpdateOneFavoriteArgs } from 'src/core/@generated/favorite/update-one-favorite.args'; - -@InputType() -class FavoriteMutationForPersonArgs { - @Field(() => String) - personId: string; - @Field(() => Number) - position: number; -} - -@InputType() -class FavoriteMutationForCompanyArgs { - @Field(() => String) - companyId: string; - @Field(() => Number) - position: number; -} - -@UseGuards(JwtAuthGuard) -@Resolver(() => Favorite) -export class FavoriteResolver { - constructor(private readonly favoriteService: FavoriteService) {} - - @Query(() => [Favorite]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadFavoriteAbilityHandler) - async findFavorites( - @AuthWorkspace() workspace: Workspace, - ): Promise[]> { - const favorites = await this.favoriteService.findMany({ - where: { - workspaceId: workspace.id, - }, - orderBy: [{ position: SortOrder.asc }], - include: { - person: true, - company: { - include: { - accountOwner: true, - }, - }, - }, - }); - - return favorites; - } - - @Mutation(() => Favorite, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateFavoriteAbilityHandler) - async createFavoriteForPerson( - @Args('data') args: FavoriteMutationForPersonArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Favorite' }) - prismaSelect: PrismaSelect<'Favorite'>, - ): Promise> { - //To avoid duplicates we first fetch all favorites assinged by workspace - const favorite = await this.favoriteService.findFirst({ - where: { workspaceId: workspace.id, personId: args.personId }, - }); - - if (favorite) return favorite; - - return this.favoriteService.create({ - data: { - person: { - connect: { id: args.personId }, - }, - workspaceId: workspace.id, - position: args.position, - }, - select: prismaSelect.value, - }); - } - - @Mutation(() => Favorite, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateFavoriteAbilityHandler) - async createFavoriteForCompany( - @Args('data') args: FavoriteMutationForCompanyArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Favorite' }) - prismaSelect: PrismaSelect<'Favorite'>, - ): Promise> { - //To avoid duplicates we first fetch all favorites assinged by workspace - const favorite = await this.favoriteService.findFirst({ - where: { workspaceId: workspace.id, companyId: args.companyId }, - }); - - if (favorite) return favorite; - - return this.favoriteService.create({ - data: { - company: { - connect: { id: args.companyId }, - }, - workspaceId: workspace.id, - position: args.position, - }, - select: prismaSelect.value, - }); - } - - @Mutation(() => Favorite, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateFavoriteAbilityHandler) - async updateOneFavorites( - @Args() args: UpdateOneFavoriteArgs, - @PrismaSelector({ modelName: 'Favorite' }) - prismaSelect: PrismaSelect<'Favorite'>, - ): Promise> { - return this.favoriteService.update({ - data: args.data, - where: args.where, - select: prismaSelect.value, - } as Prisma.FavoriteUpdateArgs); - } - - @Mutation(() => Favorite, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteFavoriteAbilityHandler) - async deleteFavorite( - @Args('where') args: FavoriteWhereInput, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Favorite' }) - prismaSelect: PrismaSelect<'Favorite'>, - ): Promise> { - const favorite = await this.favoriteService.findFirst({ - where: { ...args, workspaceId: workspace.id }, - }); - - return this.favoriteService.delete({ - where: { id: favorite?.id }, - select: prismaSelect.value, - }); - } -} diff --git a/server/src/core/favorite/services/favorite.service.ts b/server/src/core/favorite/services/favorite.service.ts deleted file mode 100644 index e1a14d034..000000000 --- a/server/src/core/favorite/services/favorite.service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class FavoriteService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.favorite.findFirst; - findFirstOrThrow = this.prismaService.client.favorite.findFirstOrThrow; - - findUnique = this.prismaService.client.favorite.findUnique; - findUniqueOrThrow = this.prismaService.client.favorite.findUniqueOrThrow; - - findMany = this.prismaService.client.favorite.findMany; - - // Create - create = this.prismaService.client.favorite.create; - createMany = this.prismaService.client.favorite.createMany; - - // Update - update = this.prismaService.client.favorite.update; - upsert = this.prismaService.client.favorite.upsert; - updateMany = this.prismaService.client.favorite.updateMany; - - // Delete - delete = this.prismaService.client.favorite.delete; - deleteMany = this.prismaService.client.favorite.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.favorite.aggregate; - - // Count - count = this.prismaService.client.favorite.count; - - // GroupBy - groupBy = this.prismaService.client.favorite.groupBy; -} diff --git a/server/src/core/person/person-relations.resolver.spec.ts b/server/src/core/person/person-relations.resolver.spec.ts deleted file mode 100644 index 683c7d841..000000000 --- a/server/src/core/person/person-relations.resolver.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { CommentService } from 'src/core/comment/comment.service'; -import { ActivityService } from 'src/core/activity/services/activity.service'; - -import { PersonRelationsResolver } from './person-relations.resolver'; -import { PersonService } from './person.service'; - -describe('PersonRelationsResolver', () => { - let resolver: PersonRelationsResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PersonRelationsResolver, - { - provide: PersonService, - useValue: {}, - }, - { - provide: ActivityService, - useValue: {}, - }, - { - provide: CommentService, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(PersonRelationsResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/person/person-relations.resolver.ts b/server/src/core/person/person-relations.resolver.ts deleted file mode 100644 index 7eb96d466..000000000 --- a/server/src/core/person/person-relations.resolver.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Resolver, Root, ResolveField, Int } from '@nestjs/graphql'; - -import { Comment } from 'src/core/@generated/comment/comment.model'; -import { Person } from 'src/core/@generated/person/person.model'; -import { CommentService } from 'src/core/comment/comment.service'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { Activity } from 'src/core/@generated/activity/activity.model'; -import { ActivityService } from 'src/core/activity/services/activity.service'; - -@Resolver(() => Person) -export class PersonRelationsResolver { - constructor( - private readonly activityService: ActivityService, - private readonly commentService: CommentService, - ) {} - - @ResolveField(() => [Activity], { - nullable: false, - }) - async activities( - @Root() person: Person, - @PrismaSelector({ modelName: 'Activity' }) - prismaSelect: PrismaSelect<'Activity'>, - ): Promise[]> { - return await this.activityService.findMany({ - where: { - activityTargets: { - some: { - personId: person.id, - }, - }, - }, - select: prismaSelect.value, - }); - } - - @ResolveField(() => [Comment], { - nullable: false, - }) - async comments( - @Root() person: Person, - @PrismaSelector({ modelName: 'Comment' }) - prismaSelect: PrismaSelect<'Comment'>, - ): Promise[]> { - return this.commentService.findMany({ - where: { - activity: { - activityTargets: { - some: { - personId: person.id, - }, - }, - }, - }, - select: prismaSelect.value, - }); - } - - @ResolveField(() => Int, { - nullable: false, - }) - async _activityCount(@Root() person: Person): Promise { - return this.activityService.count({ - where: { - activityTargets: { - some: { - personId: person.id, - }, - }, - }, - }); - } -} diff --git a/server/src/core/person/person.module.ts b/server/src/core/person/person.module.ts deleted file mode 100644 index 45d153bea..000000000 --- a/server/src/core/person/person.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { CommentModule } from 'src/core/comment/comment.module'; -import { ActivityModule } from 'src/core/activity/activity.module'; -import { FileModule } from 'src/core/file/file.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { PersonService } from './person.service'; -import { PersonResolver } from './person.resolver'; -import { PersonRelationsResolver } from './person-relations.resolver'; - -@Module({ - imports: [ - CommentModule, - ActivityModule, - FileModule, - AbilityModule, - PrismaModule, - ], - providers: [PersonService, PersonResolver, PersonRelationsResolver], - exports: [PersonService], -}) -export class PersonModule {} diff --git a/server/src/core/person/person.resolver.spec.ts b/server/src/core/person/person.resolver.spec.ts deleted file mode 100644 index 1344450c5..000000000 --- a/server/src/core/person/person.resolver.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { AbilityFactory } from 'src/ability/ability.factory'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; - -import { PersonService } from './person.service'; -import { PersonResolver } from './person.resolver'; - -describe('PersonResolver', () => { - let resolver: PersonResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PersonResolver, - { - provide: PersonService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - { - provide: FileUploadService, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(PersonResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/person/person.resolver.ts b/server/src/core/person/person.resolver.ts deleted file mode 100644 index 0d3c23fe8..000000000 --- a/server/src/core/person/person.resolver.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { - Resolver, - Query, - Args, - Mutation, - ResolveField, - Parent, -} from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; -import { Prisma } from '@prisma/client'; -import { FileUpload, GraphQLUpload } from 'graphql-upload'; - -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Person } from 'src/core/@generated/person/person.model'; -import { FindManyPersonArgs } from 'src/core/@generated/person/find-many-person.args'; -import { UpdateOnePersonArgs } from 'src/core/@generated/person/update-one-person.args'; -import { CreateOnePersonArgs } from 'src/core/@generated/person/create-one-person.args'; -import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output'; -import { DeleteManyPersonArgs } from 'src/core/@generated/person/delete-many-person.args'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreatePersonAbilityHandler, - DeletePersonAbilityHandler, - ReadPersonAbilityHandler, - UpdatePersonAbilityHandler, -} from 'src/ability/handlers/person.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { streamToBuffer } from 'src/utils/stream-to-buffer'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { CreateManyPersonArgs } from 'src/core/@generated/person/create-many-person.args'; - -import { PersonService } from './person.service'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Person) -export class PersonResolver { - constructor( - private readonly personService: PersonService, - private readonly fileUploadService: FileUploadService, - ) {} - - @Query(() => [Person], { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadPersonAbilityHandler) - async findManyPerson( - @Args() args: FindManyPersonArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'Person' }) - prismaSelect: PrismaSelect<'Person'>, - ): Promise[]> { - return this.personService.findMany({ - where: args.where - ? { - AND: [args.where, accessibleBy(ability).Person], - } - : accessibleBy(ability).Person, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - } - - @Query(() => Person) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadPersonAbilityHandler) - async findUniquePerson( - @Args('id') id: string, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'Person' }) - prismaSelect: PrismaSelect<'Person'>, - ): Promise> { - return this.personService.findUniqueOrThrow({ - where: { - id: id, - }, - select: prismaSelect.value, - }); - } - - @ResolveField(() => String, { - nullable: false, - }) - displayName(@Parent() parent: Person): string { - return `${parent.firstName ?? ''} ${parent.lastName ?? ''}`; - } - - @Mutation(() => Person, { - nullable: true, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdatePersonAbilityHandler) - async updateOnePerson( - @Args() args: UpdateOnePersonArgs, - @PrismaSelector({ modelName: 'Person' }) - prismaSelect: PrismaSelect<'Person'>, - ): Promise | null> { - // TODO: Do a proper check with recursion testing on args in a more generic place - for (const key in args.data) { - if (args.data[key]) { - for (const subKey in args.data[key]) { - if (JSON.stringify(args.data[key][subKey]) === '{}') { - delete args.data[key][subKey]; - } - } - } - - if (JSON.stringify(args.data[key]) === '{}') { - delete args.data[key]; - } - } - - return this.personService.update({ - where: args.where, - data: args.data, - select: prismaSelect.value, - } as Prisma.PersonUpdateArgs); - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeletePersonAbilityHandler) - async deleteManyPerson( - @Args() args: DeleteManyPersonArgs, - ): Promise { - return this.personService.deleteMany({ - where: args.where, - }); - } - - @Mutation(() => Person, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreatePersonAbilityHandler) - async createOnePerson( - @Args() args: CreateOnePersonArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Person' }) - prismaSelect: PrismaSelect<'Person'>, - ): Promise> { - return this.personService.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspace.id } } }, - }, - select: prismaSelect.value, - } as Prisma.PersonCreateArgs); - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreatePersonAbilityHandler) - async createManyPerson( - @Args() args: CreateManyPersonArgs, - @AuthWorkspace() workspace: Workspace, - ): Promise { - return this.personService.createMany({ - data: args.data.map((person) => ({ - ...person, - workspaceId: workspace.id, - })), - skipDuplicates: args.skipDuplicates, - }); - } - - @Mutation(() => String) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdatePersonAbilityHandler) - async uploadPersonPicture( - @Args('id') id: string, - @Args({ name: 'file', type: () => GraphQLUpload }) - { createReadStream, filename, mimetype }: FileUpload, - ): Promise { - const stream = createReadStream(); - const buffer = await streamToBuffer(stream); - - const { paths } = await this.fileUploadService.uploadImage({ - file: buffer, - filename, - mimeType: mimetype, - fileFolder: FileFolder.PersonPicture, - }); - - await this.personService.update({ - where: { id }, - data: { - avatarUrl: paths[0], - }, - }); - - return paths[0]; - } -} diff --git a/server/src/core/person/person.service.spec.ts b/server/src/core/person/person.service.spec.ts deleted file mode 100644 index de97b9453..000000000 --- a/server/src/core/person/person.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { PersonService } from './person.service'; - -describe('PersonService', () => { - let service: PersonService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PersonService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(PersonService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/person/person.service.ts b/server/src/core/person/person.service.ts deleted file mode 100644 index dd20a7224..000000000 --- a/server/src/core/person/person.service.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { Company } from '@prisma/client'; - -import { PrismaService } from 'src/database/prisma.service'; -import peopleSeed from 'src/core/person/seed-data/people.json'; - -@Injectable() -export class PersonService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.person.findFirst; - findFirstOrThrow = this.prismaService.client.person.findFirstOrThrow; - - findUnique = this.prismaService.client.person.findUnique; - findUniqueOrThrow = this.prismaService.client.person.findUniqueOrThrow; - - findMany = this.prismaService.client.person.findMany; - - // Create - create = this.prismaService.client.person.create; - createMany = this.prismaService.client.person.createMany; - - // Update - update = this.prismaService.client.person.update; - upsert = this.prismaService.client.person.upsert; - updateMany = this.prismaService.client.person.updateMany; - - // Delete - delete = this.prismaService.client.person.delete; - deleteMany = this.prismaService.client.person.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.person.aggregate; - - // Count - count = this.prismaService.client.person.count; - - // GroupBy - groupBy = this.prismaService.client.person.groupBy; - async createDefaultPeople({ - workspaceId, - companies, - }: { - workspaceId: string; - companies: Company[]; - }) { - const people = peopleSeed.map((person, i) => ({ - ...person, - companyId: companies[i].id || null, - workspaceId, - })); - return this.createMany({ - data: people, - }); - } -} diff --git a/server/src/core/person/seed-data/people.json b/server/src/core/person/seed-data/people.json deleted file mode 100644 index 3048fe6a1..000000000 --- a/server/src/core/person/seed-data/people.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "firstName": "Brian", - "lastName": "Chesky", - "city": "San Francisco", - "email": "chesky@airbnb.com", - "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADwAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIADwAPAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAoHCBUSFRgSEhUYGBgYGBgYGBgYGBgYGBgYGBgZGRgaGBgcIS4lHB4rIRgYJjgmKy8xNTU1GiQ7QDszPy40NTH/2wBDAQwMDBAPEBwSEh40ISQkMTQ0NjQxNDQ2NDQ0NDQ0MTQ0NDQ0NDQ0NDQ0NDE0NDQ0NDQ0PzQ0NDQ0NDQ0NDQ0NDT/3QAEAAT/2gAMAwEAAhEDEQA/AOtApcUtLWpkJiub1TxlawHaC0pGM+WAQM9ixIGfal8bas8ESwwjMs5KLjqq4+ZgO55A/wCBe1cDceGLxVyYCysOqfNjnoQOQfzqJTs7GkYNq53uleLba5KoCyO2fldcDI7b/uk/jW8VrxSSJowQ6OPqhwPxxXofw81Mz27IxyYmCjPUKRlee/f8qIyuKUbHT4oxT6SrIP/Q6+ilorUyOJ147tTjzjbFArEk4A3M/wD9au20u4Rl+R1bHXawJFZ89vGbgM4GWj2898HI/rTbXSIo5lkj5fpuyWO3upPccVx1H7zO6nH3EizroBjbIB/KuL+H0eJ7soMIBGPx3Ocfkf1rUbRPPzM0jYYtv3MTjkjCDOF7flS+C7Hyo5XznzZSRxjhAEH16E1VH4ia/wAJ0dFFLXUcZ//R7HFIRWXq/iS1teJZRu6hEG9+/JC9Bx1OK43VPiM7ZW2iCejyHc34Ivyj8zWpmdtqkiq8QfoxYe3bGfryKbNb8HEzIwyUYKCQCOnbP0IPasPwtKb+3JlcvICUck8hgSVYAcLkFSMelSya3LbL5U8Bl28K67efTcD0P0rjm7zZ3UtIocsZEQhDEu5IXrnaTks+Scnqa3LWBY1EaDCqMDkn9TXCSapNBIb+ZR0ZRGSQArY+Vf8Aa4GD9a6XRvE9tdYCuFc/8s3IVvw7MPcVtRStcwrybZuilpopa2Oc/9Ly0J/kUBaVTS1sZl7SNWmtH8yB9pPBBGVYZzhl7j9R611T/ERmHzWqFvXzDt+uNuevb9a4eiolCMtyozlHYu6zrE12QZSAF+6ijCjPfHc+5/Ss3bUlFUkkrITbbuze8P8Aiqe0IDMZIsjcjEsQOh8ticqcduhx26163FKGUMpyGAII6EEZBrwQmvX/AAFIXso93O0ug/3Vdgo/KmI//9k=" - }, - { - "firstName": "Alexandre", - "lastName": "Prot", - "city": "Paris", - "email": "prot@qonto.com", - "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADwAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIADwAPAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAkGBxAQEBUQEBAVFRUVFRUVFRUVEBAVFRUQFRUWFhUVFRUYHSggGBolGxUVITEhJSkrLi4uFx8zODMtNygtLiv/2wBDAQoKCg4NDhcQEBctHR0dLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS3/3QAEAAT/2gAMAwEAAhEDEQA/APZ6KSitCRc1Sn1e3Q7XmQEdRuHH19K4n4keK3i3WluSHwu9lJBBbkID24GSfevOILa6lO4GSQ4x8qsRjuARUOVjSMLn0RDMrgMpBB7g5FPrwzRdavLaQJ+9jPZXVtjEdsEdcelex6DqQuYFlxgkYYejjqKadxSjY0aKSlpkH//Q9mooFFaEnj2vWQk1xoGUsHfzH5IBTYuB9K9HtkVU2qAABgAYGB7CsrU9Jj+2i5YfOA8ZbJyyPgqPouMD6moF8PokvnAnr1LPnPPv71zvdnbCNkT6xaxSfLKUweBuYDk9CKk+G4xbSLzlJWRg3Xenyn88A575zWVfaPG9zI7qCeDzyQhGML6DK/nXR+FQv78rjBmABB5+WNQc++c0Qeoqyurm/RSZpM1ucZ//0fZaWkqOWZV6n8O9aJXIvYzvEIjEe5iA2RtyeTjkgDucZ/KsOaR2X5QCAOu4gg+orX1aES7XIBKNuXPYEFT+hNc7dCaAkw4Zf7hOCPofT2rOrCzR1YepoZIMvmO7yM4YY5OTnoFUAACvTbWMKijAHAzgY5wMn61wGgXjSXSm5CxhWAVSR80pBK8/h+legbqVKO7JxE7tJEmaM1HmjNanOf/S9blnJ6cD171VI9afu4pjV2xVjmbuMuruOGNnlYBV6k989AAOpPTArnRc74jIFO0jcAww+09Nw7EdxW7cQq+A6hsHIyM4PqKrXVgjAkZU/wCyxGfqOholSU1bqOFZ03focTPpkszoFBGJlkPvwQB+pP4Cu8tLrDmIZ3KqliRwd2eh79OR2rLvrkxRIygE8ZJHXBxzj6VNYpnkscvyxyM8+noKcKajCxNSo5TbOhhnDdxkdcVLmsy3GJQBwNjcfRlq/msJqzNoO6P/2Q==" - }, - { - "firstName": "Patrick", - "lastName": "Collison", - "city": "San Francisco", - "email": "collison@stripe.com", - "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAACkAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIACkAPAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5Ojf/2wBDAQoKCg0MDRoPDxo3JR8lNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzf/3QAEAAT/2gAMAwEAAhEDEQA/APX0bbIUa2Voz/Grcj6j/Cq91sETuzlAgyST0q0VKfd5HpXK/ES6Nv4f8xJCmZlVznGFOc/l1qZvli2OEeaSRzGteJBcNItvhn+VYiRkKd3J+vT6VS0651CW7VYI1RWY+c/lhj/wDPAye56Yqu2p6b4bsrWGW2DzOA8jMwDbm5A59q6O0122Wwi1KS022ZO3zAnIP4Vxvmetz0YKK0sXdK/tZLhY9ZQPG5PlPv5YH+FscE+9cZ408NzaFNJNpVuBZ48wxKMiEemfTNeh3+rWWo+G7i90+Uf6PH5nIKlccmuL+IN+t94XtbuGZ2nFwFIB4f5T9724/SrhNxdjCuvd5kjz3WbiOWwj3SDzip3IOMVzUtxIz5UBR0wo4r1+18SeBn8PPpt7ZQCSSL551IM/m4+90zkHpivLIZ9sYEynf3wBW1urOWKvuf/Q9JttY8v93d8gfxj+tUfG8CX2hRsqmVPtMJITHI3DOfbHX2qje+ZCTkF09R1FXJFjk0142JMbLkgEjmueUnblZrBJSUkcz4iuNKlkCXMRdy3CISM/XFaWnajoWq6I+nHcIRkAeUVAAxyMjsSOtYk0RmkeSMmN8EM4Tc3ToAau+GLC4hsbny3ALggxzW+A/wCI/wAKlNtHZZHT6RoWm6bp7RQgMjxMhA4Dg+o6Z5rxvxP50GgaZYyLsDXDTAhwSVVNmeD2JwfevVtU1WLRNHub2RHeK1TeyKecZHAzXjXi3W01jUjPBbfZbaMFYYcgldzbmJPqzHJ+gqkuZpkStyuJjXVmvleYuRGB+dQQ38kMYjEcbAd2XmkkmcoVBO09qrFSTVJdzFQSP//Rd4l8bTWE8kdikLlM/M6lgcHnA+lcrqXjjUiJjFIMS/L94+nUehrP1r/j7l/33/lXP3H3F/3v6V1X5VZHMo8zuz0DQdSudQ0SSaKcxzwuY89cgAbc/getb/hDV9dnEkTGMxBsF3PT8K4/wH/yD77/AK6/+yCu28J/6qb/AK7j/wBBFeXVvzs9ej8COoSyt7vSryHUWLJKh8xhwfbHbr2ry99P8PXMa/aj9hdWaJ7mIhY+DgMVPygn2r1CT/kD3f8A1zNeJaj/AMg23/67P/M114WKad0cmLbTVnY1bn4dX0sPn6Le2WpwsMr5b+W5HsDkH8xXJX1jJp9y9rfIbedPvRzEKR+fUe4yK7XwR/yFx9a67xj/AMhGD/r3X/0Jq1nQja6OaOInezP/2Q==" - }, - { - "firstName": "Dylan", - "lastName": "Field", - "city": "San Francisco", - "email": "field@figma.com", - "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQABLAEsAAD/4QSQRXhpZgAATU0AKgAAAAgADAEOAAIAAADlAAAAngEPAAIAAAAGAAABhAEQAAIAAAANAAABigESAAMAAAABAAEAAAEaAAUAAAABAAABmAEbAAUAAAABAAABoAEoAAMAAAABAAIAAAExAAIAAAAhAAABqAEyAAIAAAAUAAABygE7AAIAAAAPAAAB3oKYAAIAAAASAAAB7odpAAQAAAABAAACAAAAAABTQU4gRlJBTkNJU0NPLCBDQUxJRk9STklBIC0gT0NUT0JFUiAyMDogQ28tZm91bmRlciAmIENFTyBvZsKgRmlnbWEgRHlsYW4gRmllbGQgc3BlYWtzIG9uc3RhZ2UgZHVyaW5nIFRlY2hDcnVuY2ggRGlzcnVwdCAyMDIyIG9uIE9jdG9iZXIgMjAsIDIwMjIgaW4gU2FuIEZyYW5jaXNjbywgQ2FsaWZvcm5pYS4gKFBob3RvIGJ5IEtpbWJlcmx5IFdoaXRlL0dldHR5IEltYWdlcyBmb3IgVGVjaENydW5jaCkAAENhbm9uAENhbm9uIEVPUyBSNQAAAAABLAAAAAEAAAEsAAAAAUFkb2JlIFBob3Rvc2hvcCAyMy41IChNYWNpbnRvc2gpAAAyMDIyOjEwOjIwIDEwOjU2OjU4AEtpbWJlcmx5IFdoaXRlAAAyMDIyIEdldHR5IEltYWdlcwAAI4KaAAUAAAABAAADqoKdAAUAAAABAAADsogiAAMAAAABAAEAAIgnAAMAAAABCcQAAIgwAAMAAAABAAIAAIgyAAQAAAABAAAJxJAAAAcAAAAEMDIzMZADAAIAAAAUAAADupAEAAIAAAAUAAADzpAQAAIAAAAHAAAD4pARAAIAAAAHAAAD6pASAAIAAAAHAAAD8pIBAAoAAAABAAAD+pICAAUAAAABAAAEApIEAAoAAAABAAAECpIFAAUAAAABAAAEEpIHAAMAAAABAAUAAJIJAAMAAAABAAAAAJIKAAUAAAABAAAEGpKQAAIAAAADNzgAAJKRAAIAAAADNzgAAJKSAAIAAAADNzgAAKACAAQAAAABAAAAPKADAAQAAAABAAAAUKIOAAUAAAABAAAEIqIPAAUAAAABAAAEKqIQAAMAAAABAAIAAKQBAAMAAAABAAAAAKQCAAMAAAABAAEAAKQDAAMAAAABAAEAAKQGAAMAAAABAAAAAKQxAAIAAAANAAAEMqQyAAUAAAAEAAAEQKQ0AAIAAAAcAAAEYKQ1AAIAAAALAAAEfAAAAAAAAAABAAAB9AAAAAUAAAABMjAyMjoxMDoyMCAxMjo0ODozMgAyMDIyOjEwOjIwIDEyOjQ4OjMyAC0wNTowMAAALTA1OjAwAAAtMDU6MDAAAAAAdbYAAA0hAAQwyQAA5wMAAAAAAAAAAQAAAAMAAAABAAAAbgAAAAEAFT2AAAAB2QAlDXsAAAM6MDUyMDIxMDA0MTE5AAAAAABGAAAAAQAAAMgAAAABAAAAAAAAAAEAAAAAAAAAAUVGNzAtMjAwbW0gZi8yLjhMIElTIElJIFVTTQAwMDAwNDBjNzVjAAD/4ROOaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpHZXR0eUltYWdlc0dJRlQ9Imh0dHA6Ly94bXAuZ2V0dHlpbWFnZXMuY29tL2dpZnQvMS4wLyIgeG1sbnM6SXB0YzR4bXBDb3JlPSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wQ29yZS8xLjAveG1sbnMvIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnBsdXM9Imh0dHA6Ly9ucy51c2VwbHVzLm9yZy9sZGYveG1wLzEuMC8iIHhtbG5zOnhtcFJpZ2h0cz0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3JpZ2h0cy8iIHhtbG5zOklwdGM0eG1wRXh0PSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wRXh0LzIwMDgtMDItMjkvIiBwaG90b3Nob3A6Q2l0eT0iU2FuIEZyYW5jaXNjbyIgcGhvdG9zaG9wOkRhdGVDcmVhdGVkPSIyMDIyLTEwLTIwVDEyOjQ4OjMyLjc4IiBwaG90b3Nob3A6SGVhZGxpbmU9IlRlY2hDcnVuY2ggRGlzcnVwdCAyMDIyIC0gRGF5IDMiIHBob3Rvc2hvcDpDb3VudHJ5PSJVbml0ZWQgU3RhdGVzIiBwaG90b3Nob3A6Q29weXJpZ2h0RmxhZz0idHJ1ZSIgcGhvdG9zaG9wOkNhdGVnb3J5PSJFIiBwaG90b3Nob3A6U291cmNlPSJHZXR0eSBJbWFnZXMgTm9ydGggQW1lcmljYSIgcGhvdG9zaG9wOlVyZ2VuY3k9IjMiIHBob3Rvc2hvcDpBdXRob3JzUG9zaXRpb249IlN0cmluZ2VyIiBwaG90b3Nob3A6VHJhbnNtaXNzaW9uUmVmZXJlbmNlPSI3NzU4ODQzODQiIHBob3Rvc2hvcDpVUkw9Imh0dHBzOi8vd3d3LmdldHR5aW1hZ2VzLmNvbSIgcGhvdG9zaG9wOlN0YXRlPSJDYWxpZm9ybmlhIiBwaG90b3Nob3A6Q3JlZGl0PSJHZXR0eSBJbWFnZXMgZm9yIFRlY2hDcnVuY2giIHBob3Rvc2hvcDpDYXB0aW9uV3JpdGVyPSJFRCAvIEVEIiBkYzpSaWdodHM9IjIwMjIgR2V0dHkgSW1hZ2VzIiBHZXR0eUltYWdlc0dJRlQ6SW1hZ2VSYW5rPSIzIiBHZXR0eUltYWdlc0dJRlQ6RGxyZWY9ImZjNkRiREMzK0ZHWG5PMXpiVzFKYkE9PSIgR2V0dHlJbWFnZXNHSUZUOkFzc2V0SUQ9IjE0MzUwODg1NjciIElwdGM0eG1wQ29yZTpDb3VudHJ5Q29kZT0iVVNBIiBJcHRjNHhtcENvcmU6TG9jYXRpb249Ik1vc2NvbmUgQ2VudGVyIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMi0xMC0yMFQxMjo0ODozMi43OCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjMuNSAoTWFjaW50b3NoKSIgeG1wOk1vZGlmeURhdGU9IjIwMjItMTAtMjBUMTA6NTY6NTguNzgiIHBsdXM6SW1hZ2VTdXBwbGllckltYWdlSUQ9IjE0MzUwODg1NjciIHhtcFJpZ2h0czpXZWJTdGF0ZW1lbnQ9Imh0dHBzOi8vd3d3LmdldHR5aW1hZ2VzLmNvbS9ldWxhP3V0bV9tZWRpdW09b3JnYW5pYyZhbXA7dXRtX3NvdXJjZT1nb29nbGUmYW1wO3V0bV9jYW1wYWlnbj1pcHRjdXJsIiBJcHRjNHhtcEV4dDpIZWFkbGluZT0iVGVjaENydW5jaCBEaXNydXB0IDIwMjIgLSBEYXkgMyI+IDxwaG90b3Nob3A6U3VwcGxlbWVudGFsQ2F0ZWdvcmllcz4gPHJkZjpCYWc+IDxyZGY6bGk+QUNFPC9yZGY6bGk+IDxyZGY6bGk+RU5UPC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6U3VwcGxlbWVudGFsQ2F0ZWdvcmllcz4gPGRjOnJpZ2h0cz4gPHJkZjpBbHQ+IDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+MjAyMiBHZXR0eSBJbWFnZXM8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnJpZ2h0cz4gPGRjOnN1YmplY3Q+IDxyZGY6QmFnPiA8cmRmOmxpPmFydHMgY3VsdHVyZSBhbmQgZW50ZXJ0YWlubWVudDwvcmRmOmxpPiA8L3JkZjpCYWc+IDwvZGM6c3ViamVjdD4gPGRjOmNyZWF0b3I+IDxyZGY6U2VxPiA8cmRmOmxpPktpbWJlcmx5IFdoaXRlPC9yZGY6bGk+IDwvcmRmOlNlcT4gPC9kYzpjcmVhdG9yPiA8ZGM6dGl0bGU+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPjE0MzUwODg1Njc8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8ZGM6ZGVzY3JpcHRpb24+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPlNBTiBGUkFOQ0lTQ08sIENBTElGT1JOSUEgLSBPQ1RPQkVSIDIwOiBDby1mb3VuZGVyICZhbXA7IENFTyBvZsKgRmlnbWEgRHlsYW4gRmllbGQgc3BlYWtzIG9uc3RhZ2UgZHVyaW5nIFRlY2hDcnVuY2ggRGlzcnVwdCAyMDIyIG9uIE9jdG9iZXIgMjAsIDIwMjIgaW4gU2FuIEZyYW5jaXNjbywgQ2FsaWZvcm5pYS4gKFBob3RvIGJ5IEtpbWJlcmx5IFdoaXRlL0dldHR5IEltYWdlcyBmb3IgVGVjaENydW5jaCk8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOmRlc2NyaXB0aW9uPiA8cGx1czpMaWNlbnNvcj4gPHJkZjpTZXE+IDxyZGY6bGkgcGx1czpMaWNlbnNvclVSTD0iaHR0cHM6Ly93d3cuZ2V0dHlpbWFnZXMuY29tL2RldGFpbC8xNDM1MDg4NTY3P3V0bV9tZWRpdW09b3JnYW5pYyZhbXA7dXRtX3NvdXJjZT1nb29nbGUmYW1wO3V0bV9jYW1wYWlnbj1pcHRjdXJsIi8+IDwvcmRmOlNlcT4gPC9wbHVzOkxpY2Vuc29yPiA8SXB0YzR4bXBFeHQ6UGVyc29uSW5JbWFnZT4gPHJkZjpCYWc+IDxyZGY6bGk+RHlsYW4gRmllbGQ8L3JkZjpsaT4gPC9yZGY6QmFnPiA8L0lwdGM0eG1wRXh0OlBlcnNvbkluSW1hZ2U+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/eHBhY2tldCBlbmQ9InciPz4A/+0CsFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAJ3HAFaAAMbJUccAgAAAgACHAI8AAYxMjQ4MzIcAngA5FNBTiBGUkFOQ0lTQ08sIENBTElGT1JOSUEgLSBPQ1RPQkVSIDIwOiBDby1mb3VuZGVyICYgQ0VPIG9mwqBGaWdtYSBEeWxhbiBGaWVsZCBzcGVha3Mgb25zdGFnZSBkdXJpbmcgVGVjaENydW5jaCBEaXNydXB0IDIwMjIgb24gT2N0b2JlciAyMCwgMjAyMiBpbiBTYW4gRnJhbmNpc2NvLCBDYWxpZm9ybmlhLiAoUGhvdG8gYnkgS2ltYmVybHkgV2hpdGUvR2V0dHkgSW1hZ2VzIGZvciBUZWNoQ3J1bmNoKRwCNwAIMjAyMjEwMjAcAnQAETIwMjIgR2V0dHkgSW1hZ2VzHAIKAAEzHAJpAB9UZWNoQ3J1bmNoIERpc3J1cHQgMjAyMiAtIERheSAzHAJaAA1TYW4gRnJhbmNpc2NvHAJcAA5Nb3Njb25lIENlbnRlchwCegAHRUQgLyBFRBwCFAADQUNFHAIUAANFTlQcAj4ACDIwMjIxMDIwHAJkAANVU0EcAgUACjE0MzUwODg1NjccAm4AG0dldHR5IEltYWdlcyBmb3IgVGVjaENydW5jaBwCXwAKQ2FsaWZvcm5pYRwCUAAOS2ltYmVybHkgV2hpdGUcAmUADVVuaXRlZCBTdGF0ZXMcAmcACTc3NTg4NDM4NBwCGQAeYXJ0cyBjdWx0dXJlIGFuZCBlbnRlcnRhaW5tZW50HAI/AAYxMjQ4MzIcAg8AAUUcAlUACFN0cmluZ2VyHAJzABpHZXR0eSBJbWFnZXMgTm9ydGggQW1lcmljYQA4QklNBCUAAAAAABAqVkKpihuH4+mjJhYu6lJv/+ICQElDQ19QUk9GSUxFAAEBAAACMEFEQkUCEAAAbW50clJHQiBYWVogB9AACAALABMAMwA7YWNzcEFQUEwAAAAAbm9uZQAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1BREJFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKY3BydAAAAPwAAAAyZGVzYwAAATAAAABrd3RwdAAAAZwAAAAUYmtwdAAAAbAAAAAUclRSQwAAAcQAAAAOZ1RSQwAAAdQAAAAOYlRSQwAAAeQAAAAOclhZWgAAAfQAAAAUZ1hZWgAAAggAAAAUYlhZWgAAAhwAAAAUdGV4dAAAAABDb3B5cmlnaHQgMjAwMCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZAAAAGRlc2MAAAAAAAAAEUFkb2JlIFJHQiAoMTk5OCkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABjdXJ2AAAAAAAAAAECMwAAY3VydgAAAAAAAAABAjMAAGN1cnYAAAAAAAAAAQIzAABYWVogAAAAAAAAnBgAAE+lAAAE/FhZWiAAAAAAAAA0jQAAoCwAAA+VWFlaIAAAAAAAACYxAAAQLwAAvpz/wAARCABQADwDAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwACAQECAQECAgICAgICAgMFAwMDAwMGBAQDBQcGBwcHBgcHCAkLCQgICggHBwoNCgoLDAwMDAcJDg8NDA4LDAwM/9sAQwECAgIDAwMGAwMGDAgHCAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/90ABAAI/9oADAMBAAIRAxEAPwD7H+EOseG9D8ZJceKdPfUtKWFwYUXcWc42nGR71vF2dz+acmr4KliVPHw54Wenn0Ob8RX1s2q31xADbWTSSSRI3HlR5JUH6DH5VM5KKuzhqRVWu1QWjbsvV6I5L43ft++E/Efh/S7fw5omni38N5tbi4tpw82ouAqvIqIuCgbjcz5znjAzXj4jOI7U1t1P2WPCCx1DD08RT9m1HZWu356fP82cr+zr/wAFSYvCs/iPRb3TrNLXVJTZteyQlEWMKwJXJBZhkD5VIJrGGbTgve1PYw3CLw1CdPCQs6kbNPvtpfbe76DPD37ceg/8JEGg0HxJHBZOssd29sm1trDB2bt2eM7euO1Ec+p3tJfifNvwsx0EqtGrHmVmk0+nnse4a/8AHyT9oa+TWp7iG4lFvGn7mAw7EILKCp5B5PXmvXw+MhXjzwZ8bxXQzGGMtmSXPa2isrL+ty3Y+P8AV7Hwrc+H4L+WLSbtzLLagDbI3HJOM9h3roueNTx+Ijh5YSE2qb1a7matuSMk4JqWcqXc/9D68+Fnw31H4teK00fTWtorl4ml3TyFVCrjPQH1rojG7sfzLlGV1sxxCw1Cydm9dtD46/4Kb/Htfh5PF8O43klu5Z3OrrFIyJJCoYCLcpDlWYAtjHygAnnFeRmdRv8AdR+f6H6Z4c8PyjiKmMrfYvGPXVO0pK/lonum7rY+G/ij+1zDP4Sn0zREntvsTRqRDGqR4BHyALyU4OecEHFeJSwdTmvLXQ/auenFWgjBt/2iIoNSuXu9K1mGPzGu0MgeAROUB8ouhDBG5P3cDnp1OjwrlDVpMVLmjJ2TsekH4z2NzJo+pWEfiQ2CIkc9nJMs4ieQjcVZjuKqex+bBPPAxxxwsruE+XU3lVtaULnvf/BOL9r3Qrz47ap4JuNQ1eS88S5exiurhZ4RLCjSfu24cbot/DZwYT+Pr5ZTlRqctvdl+a/z/Q/MvEzLPrWXrGx+Ki9f8Mml+ErfefpBoer+EYvhPqkFzYXEniuSY/Y7gIxjjT5cZOcDv2r6BSXLZo/H8PXy5ZfUhUg3Xb9162SOSK7mOdw59aR4p//R+l49Yn0CKa8t7ma0lgidjJHIYyFAyeRzjitpuybSP5Xwiqe1iqbabdtG1v6H4pftp/HfVPjB8efEfiPUkuVuNQujb6QDxJFaKBhAO7HbuYnpv56V50IOXvPqf07lWDpYLCU8NSXwrfu27t/N/ke7f8E0/wDglbqX7WF3J4g1y+vNL0WRUuGdYyjxSb8rEN2Vkyo3MyjA+UcnJrz8XVbl7OHQ+yyzBx5fa1D9I/F3/BKrwFB4TnTS5ZdI1XUIhDqGoQWsDzXadGHzq23cvynGDjuOK5XQslq9D3ISTb91H58/t9/8EwvF/wAI7NdT8H2Op65p1qx3XGnwZlAJDANFGNwAwV+UEYPGKmnV9m/fV0cuNwXtIXpaP7j59bwt4x/Y/wDiF4E8a69oKeFJLS9+0aTqH2jc8syxO8lvcKQQqvCZUGeRuOMVrCtzKX1eV2tfkj5vMMshVpvD4qHu1E4283t9zs15o/cv4c/Du/8AiF8DJfHkQjstNihjle1uCRcoWVW24GRkbgOvavpqavDm2P5ieQVvq1bFqScKbcXvd27GMpUDnOfeg8FJdT//0vrbwB47PgLWZ7uOxtr8z2k1p5Vx9z94u3PTtW3PbY/mXJc1eX4lYiMVLRqz8z+cj4y/8JRpHxd17T9TluH1bR7+/sUguCQ6GS6kCAKcEI3yEHoVxg4rjUlbQ/pTCTlVoU61rKSi1pa6aVrd10uuqfU/oF+EGm337Kn7Ivh+30q9txPDYRGa+v4zLHbkoCZGRMF8dAoIz6ivn+dXc5H6HQpWiqaPL9O/bk+Ifij9oCz8I6d4l0jxNC+yW6iXwtPZLaKV358/zGVvk+YAdhWuI54pK25rhnFzajK9tyD9uD9rD4g/Cv4jX2k+HNc8LeHtF0XT4tS1TXtZ06S8trSF22g7Vkj6nj73cetY0oznNpK6RWLqezgrtRv1ep8sf8FENV8Q/tafsStMbnRtY1hfFmnaZp91p1q1ol61zKLZR5TMxRt0hH3jkVOXv2eLatumfPZ3VhHD+1qy92LUrrstbn6OeGTfab4Xg04zXQiggijmiR2MW5UVTkdOo719TG9j+PJ1pyc+VvlbbtrbXv0LkcRK8kmk5mB//9P7C+EHh/w7r3jSK28U6i+maSYnZ51fYdwHyrnB606clf3tj+Zcko4KrilHMJ8tOz1216HgH7e/7Dfg/wDaP+AvxCutC0vTbrx34ehm1Lw1cKscN5qlzEhFtCZDtykmEVgSAcc4FeRWgqWI9ono3+ej/wAz+lOAM+p5rkE8sguaWEbjF/3Ltwl+cX0+8+nvhBp8ejfC/TrDVZ4pZ4bGG3lVzmMMEAauJ01ztI/RsHNzirnneo6t4C07xzqV1Z2yy3OmII7vUWZmisVb+HPO3cOwGcYzgVz3jzNRV7dT3lSahe9vI83+N/j/AOGHiP4k6G82sWl9JLALO7W1naNoUbDRF8dRkEYboSvHNZVn72jIpSUpcr7HUfFr4KaD490vwAPCdnbRaV4Y8TW+t63DI+9pEit5/Kck8s32gwH/AID7VtgEliU12Z+Y+KjlRyKurXvb5e8j13w78ZJvDvwt1bwpHp1lLHqzl3umY+ZH04Ax7evevp41Wo8p/MmHzydHAVMujBNT69UcoNxFQmeNqf/U+rfCnhLU/GutJYaTaTX15IC6xR43EDqeT2rKEW3ZH8r4LA18VVVHDR5pPojl/ij4F1LVbE2VvcRafqenX8U+24txOjGKVWeJhkYJCkBlOVbB5xg5VYKStI9LJMzq5RmMa7uuWSUkpNOyfvLR66X0d0+ol38QftLxtHLmCQ5chvlGRXkvWOp/Y+Hrp2qQejV16M4nxAfiB4C8G2x8KTeBo9Ge7ll1BdUs5ZJkRzkzB1cKzdchgOwzisqUnFcrdrH0WEp06i5nrJ920vwTPm3UPBWt+KPitcWWnzfCuLTNTDS3txpmjTR3M0j5JaQCdk355LNk8+3PHyqEnyta66K3rc68ww0I0+aVk/KTe3qke/8A7K/jNdQ+I3irRLW9W5tLGzhi2eZuYFJMbjznBIYZ9q78FR/eKa2Vz8J8WcwTyqVGUruUopfJ3Z9SeG/hdpmq/C7WfEFzrUVpqGmuUgsDs3XHAOeTnnPYdq92MY8jbep+E4XK8PUy+rjJ1bTjtHTX9TlFQY9ax5jxbs//1frnwT421P4fa4upaPcfZL1EaNZNgbAbrweK5FUcXdH8sYDMK+Dq+3w0uWWquZ2o30+q6hNdXMnmXFzI0ruersxyT+dS531OarVlUm51Hdt3fz3PG/2i9L1rwesXiXwvbR39kn7nV9NQcgr1kTH3WH8Q6dDwevmTXvtLuf1nwXiJYjIcJWlvyJP/ALdbj+hyNj/wUn8HfDbwhKdS0830cShHj8ve8Dd1kj5YfXBFVGKt7yPq6OMdN2voeW+NP+Ckvhz41Wt9pnhrQltJr6Lylu47UQFGPVY+Ac1jWgk+YjE5hzr2dPqer/sdeKvA/wABtM0/wzqF5Y6P4n8VWbax59xKscd+qSmIwoxOcxDaSG6mXIOcgb4CpzRk10dj8V8UMix0qtGvSTlFRd4pXcXffzvezZ9MJPFfQLPEyTRv92RGDKfoRxXbzH4vUi4ytNWfmPEZH8DH6UuYm/kf/9btviN/wUH+GfgLTL97TVZ/E+o2SFxp2kQ75psdSrOVjx7lsVxQoyk7bLuz+fMFwFm1aajVgqafWT2+Su/uR8t/tH/8FUvEepwRr4egi8P6TcL8rw3Ikup0bgM0m3CkHAKr05+Y11U8Kmtdz7/J+BcDg/fxH72fmvdXouvq/uD/AIJtf8FcPBXw50m98C/Fae70aGbUbq+svEUytc2mLiQO0N0eXjYSM21yCjLwWBGK58bgpc/tIeWny3P1jJsdSo0Vh56JXtpZavbTbfQ9E/bL8P8A7Nv7RXhv+2NP8SeHbnUZci11bw7rlplPaQM2CoOchhxz0rzZ06myTueu/q09XJHwrqPx48A/syXlwujXll4xv1TdE+mXYuInJzhZLnHlp7hcn0zxQsDXqfHov66GCx2Fw7bguZ/11/yPMdJ+PPiD4z/Fi88Ua7cbTdRpAY0B8qG2jJKQRr/cG49eSzsTycL6tHDxp0lTij53GYudeq6st/62PqT4I/tT+Mfhhfx3mj6xd2MpUSm184NakFjnzYnOxlIxuxhuMhgaHSR4WY5VhMdBwxUFLz+0vSW/5ryPq7wf/wAFYGfQov7b8N6Y2oDh5LTUzBDMOzKkilgD9T9axdHsfBYjw7pubdGu1Hzjd/emf//X/LjVvi5daRrFndqRLLEhYK5+XDqMjj1xW1KlzJpnFbTQ5jxl8RX8S7mitIbNc5CRZ28nJwO3PNdUKVuo7HJahEL6bzCzxv13KeQaqVNPcadjIufCsE8zNL5Mxc5ZmjDOfqSCf1rF0FcpTZdttMt4nVmVppF4VnJOB+NaRpJCcmzYtNReEYTarHGMDpjpT5EHqdj8PPFUqeIhb3Em8XMDx5JzzwR+orCrSSjdCuX9d+IEmn35jlnVJNoJAUYrONK6uK5//9D8ddTuvtDQ/NuxAoPsRkGvRhG1/U4yonyrjJrRANcZOMVQDfL4pACpg4oAmjjIAI6ZqR2HTXUlhfpNCzI8RDKw6gilurMTE1LVZdQvHlkcSu/LMR1NKMUlZDuf/9k=" - }, - { - "firstName": "Ivan", - "lastName": "Zhao", - "city": "San Francisco", - "email": "zhao@notion.com", - "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QC8RXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAeQAAAHAAAABDAyMjGRAQAHAAAABAECAwCgAAAHAAAABDAxMDCgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADykBgADAAAAAQAAAAAAAAAA/8AAEQgAPAA8AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMABgQFBgUEBgYFBgcHBggKEAoKCQkKFA4PDBAXFBgYFxQWFhodJR8aGyMcFhYgLCAjJicpKikZHy0wLSgwJSgpKP/bAEMBBwcHCggKEwoKEygaFhooKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKP/dAAQABP/aAAwDAQACEQMRAD8ANR09lRbye1dQuEeULjZyMbm6gZPpVO4givbmGOWw+129plwYm6AYxvGPu+x4ODXZS+bc2bOk32eEqHY7twYf3z9M/kM81xvi26Phbw5/as10s0rzCEi3bYS3AYYz67hnPFeNTpSTsj0pVE1dlS5JhhvNSaJY/LBMzF8xEYGdzHOT36jtWCPE+kwXMdpBqUItYUBy04I+793LZOR/MV5ZrWuXWqOiM7JaxqI4bcNlUQdB23dTyfwxUmi6HqWsBhp9pNceX18uu5YeMVebOb20pO0EeuW8KXVw96l3bzRh90JjfduIA5IHcgHB749eKsahDHqNtLc2tlFPBFbtDbxiVi56b0EmRtfd656dRXkt74e8QeH7Vr2fTb6xjUgNMPlHJ6Eqc/nXq3wh1bSNatks9TikbUw+92Jwki464HQ4GDjqe1JwtrF3Dm1tJWZNbaKJLm1SCZoJGkaWN3IIkcqNyLzwgPqOS3FULvTr9ruc3Op4l81wV8lQFwxAAyRxgemK7KZbVb2zNtEY7Nh5LRecSo38bdvUcbcHsfpWf/Z1z59wALsgSEfPukPbuD+hwfaou0X6H//Q6h3S1s8BNsAbYEGQVAC4Arxv44P52h6IyWstugkf92zbgM7ueOASeo9+9e0QW8k8SE2+CoO9VIOPfPpnn2rzX4h6JFdKbWeKQyRYcksAJHzgFQPr09s45rzr+zalI7oQda8I7nk/h/S43svPnRi8pKxqoyx47fjXtvgbQPsjJf6Cjw3iIPtENxE6JMnHykHvjOGHTvkcVznwo0KDU2e2mkeNocASJwRj/wCvXsdpH/Z2p2NmlzNcIrYbzGLsvBwM9eff0rGpVcpNvud9OioQSS6GhqenWGraNLY3ka7bmLDwyEbgGHQivk3w+s+j69exwMHe1lMS7x/rAkhVux5IH519bNo1xNqc0s1zHLbuV2ReSuUA6/N1z0/LpXhvjDw+fDetXs955U89/M13H5ZGQ7uSEx3G0YJ6dSK6KVlddzkxKcrPsVtX10yR24kikkkglE0U1rN8s8QGDnIGCpI9+OKfaa7qU1rE4jnBxgiOU7cgkcVn6Yqf2uV1OFI4cFptrn5gzD5AmMDGcg56DrVybU4jK4tv3UCnCI0hh2j02lunvVtdkcyfmf/R7mynhtbaOKdHCzTbIZNhz83IByfQd/pXO+P7F5/s92rxpDbQytKhjbe5BXBQDgjAPHXpVPxBqF6y22o+d9nhXZ5aqVO4kEe/c49q5z4geIIhp6XV3eKt4lqdoMYeOWVTlUUdwxIJx0CnPauJ++uU64t03zIPh1HFbarcCOTDJdyLuDA5U5Kk44Pauo8L3oudUkn1MCLUEky/lLcEE9AdyLtPHtXmWjvcxQRaxp6GNJMSCLsB1Feo+B/FVhMVjubSdLtmGAkZbP0I/rXCklU12PYU7Q87Hfi+W1sJ7+4LW9rboxd5GLBlAzuBPPqOcGvF9TaPxd4zYmeULtMtuHI2CNdo2AcYON555zu6jAro/jprd7iy0S3jdILmPz5GX77MrApGR6HBJxzxivNV1ECQMbaOEqpEccigiNgvTbntyeffvXbGLSueXVqcz5TQW20+Ga90y4td2LMpDPbx4kIV2Matk7cBVIB4HTvWLPNpWo+XPcwEOECAGMAgDpnPOe/41ajMMomiu5keOKA/voSqshztLEHjIyxP04Bq9BaaHh3mu52ldsuYWeJd2AD8ufatF5nO/I//0sv4ieJNGmWGOwjF08JJEkAG0L1IUnjAIB6EGvH/ABA81zZW15N/y83Epyowp2gA8epJ/Qeld3LZQNqF2pXKJYO4XPGS4Gfyrmr6BH8F6arDiPU5UX6NGWP61EIKLNJt2PSPhS1rrnhQ2m5ftEA8t0zyB2P0NeteENPWyRAFQYXDDGCDXyHomoXul3DSabdzWsocLviODg5z/KvdPDPinV0+D15qsl20+oRPNGs0oycCQgE+4Fc88KoPnR1U8U6keRlD4z6vHN4ju7yDElvp/lwSgdJAMmTHuN4wR/Etcvq/h2eC2+1pc+fFKgCXflBs5AA3hRkNgAZHB9qqRH7V4Z1ASjlGlXIJy3zHJPqT1Jrr/hhM134QtIbgK8axBcEcYxXVOnZKxyqXM2ci1u7X0LWkafZzJEUXl8NuJDKPQru5PHBB61Lc2dxHPIySrGJWMoSJyoAJJGflwSRgkj1re1jSrKKSSIW8bL9qVfmHPOBn64YjNc5qcMMVyVkjE7DjdIxzwSOgIA6Z4HUmseVp6Mp26n//2Q==" - } -] - \ No newline at end of file diff --git a/server/src/core/pipeline/pipeline.module.ts b/server/src/core/pipeline/pipeline.module.ts deleted file mode 100644 index b04c3a030..000000000 --- a/server/src/core/pipeline/pipeline.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; - -import { PipelineService } from './services/pipeline.service'; -import { PipelineResolver } from './resolvers/pipeline.resolver'; -import { PipelineStageResolver } from './resolvers/pipeline-stage.resolver'; -import { PipelineProgressResolver } from './resolvers/pipeline-progress.resolver'; -import { PipelineStageService } from './services/pipeline-stage.service'; -import { PipelineProgressService } from './services/pipeline-progress.service'; - -@Module({ - imports: [AbilityModule, PrismaModule], - providers: [ - PipelineService, - PipelineStageService, - PipelineProgressService, - PipelineResolver, - PipelineStageResolver, - PipelineProgressResolver, - ], - exports: [PipelineService, PipelineStageService, PipelineProgressService], -}) -export class PipelineModule {} diff --git a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.spec.ts b/server/src/core/pipeline/resolvers/pipeline-progress.resolver.spec.ts deleted file mode 100644 index 1a01f6709..000000000 --- a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { PipelineProgressResolver } from './pipeline-progress.resolver'; - -describe('PipelineProgressResolver', () => { - let resolver: PipelineProgressResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineProgressResolver, - { - provide: PipelineProgressService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(PipelineProgressResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts b/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts deleted file mode 100644 index d0579f817..000000000 --- a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Resolver, Args, Query, Mutation } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; -import { Prisma } from '@prisma/client'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { FindManyPipelineProgressArgs } from 'src/core/@generated/pipeline-progress/find-many-pipeline-progress.args'; -import { PipelineProgress } from 'src/core/@generated/pipeline-progress/pipeline-progress.model'; -import { UpdateOnePipelineProgressArgs } from 'src/core/@generated/pipeline-progress/update-one-pipeline-progress.args'; -import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output'; -import { DeleteManyPipelineProgressArgs } from 'src/core/@generated/pipeline-progress/delete-many-pipeline-progress.args'; -import { CreateOnePipelineProgressArgs } from 'src/core/@generated/pipeline-progress/create-one-pipeline-progress.args'; -import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreatePipelineProgressAbilityHandler, - ReadPipelineProgressAbilityHandler, - UpdatePipelineProgressAbilityHandler, - DeletePipelineProgressAbilityHandler, -} from 'src/ability/handlers/pipeline-progress.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { - PrismaSelector, - PrismaSelect, -} from 'src/decorators/prisma-select.decorator'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => PipelineProgress) -export class PipelineProgressResolver { - constructor( - private readonly pipelineProgressService: PipelineProgressService, - ) {} - - @Query(() => [PipelineProgress]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadPipelineProgressAbilityHandler) - async findManyPipelineProgress( - @Args() args: FindManyPipelineProgressArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'PipelineProgress' }) - prismaSelect: PrismaSelect<'PipelineProgress'>, - ): Promise[]> { - return this.pipelineProgressService.findMany({ - where: args.where - ? { - AND: [args.where, accessibleBy(ability).PipelineProgress], - } - : accessibleBy(ability).PipelineProgress, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - } - - @Mutation(() => PipelineProgress, { - nullable: true, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdatePipelineProgressAbilityHandler) - async updateOnePipelineProgress( - @Args() args: UpdateOnePipelineProgressArgs, - @PrismaSelector({ modelName: 'PipelineProgress' }) - prismaSelect: PrismaSelect<'PipelineProgress'>, - ): Promise | null> { - // TODO: Do a proper check with recursion testing on args in a more generic place - for (const key in args.data) { - if (args.data[key]) { - for (const subKey in args.data[key]) { - if (JSON.stringify(args.data[key][subKey]) === '{}') { - delete args.data[key][subKey]; - } - } - } - - if (JSON.stringify(args.data[key]) === '{}') { - delete args.data[key]; - } - } - return this.pipelineProgressService.update({ - where: args.where, - data: args.data, - select: prismaSelect.value, - } as Prisma.PipelineProgressUpdateArgs); - } - - @Mutation(() => AffectedRows, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeletePipelineProgressAbilityHandler) - async deleteManyPipelineProgress( - @Args() args: DeleteManyPipelineProgressArgs, - ): Promise { - return this.pipelineProgressService.deleteMany({ - where: args.where, - }); - } - - @Mutation(() => PipelineProgress, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreatePipelineProgressAbilityHandler) - async createOnePipelineProgress( - @Args() args: CreateOnePipelineProgressArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'PipelineProgress' }) - prismaSelect: PrismaSelect<'PipelineProgress'>, - ): Promise> { - return this.pipelineProgressService.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspace.id } } }, - }, - select: prismaSelect.value, - } as Prisma.PipelineProgressCreateArgs); - } -} diff --git a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.spec.ts b/server/src/core/pipeline/resolvers/pipeline-stage.resolver.spec.ts deleted file mode 100644 index 9cd093701..000000000 --- a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { PipelineStageResolver } from './pipeline-stage.resolver'; - -describe('PipelineStageResolver', () => { - let resolver: PipelineStageResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineStageResolver, - { - provide: PipelineStageService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(PipelineStageResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts b/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts deleted file mode 100644 index b0790badc..000000000 --- a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Resolver, Args, Query, Mutation } from '@nestjs/graphql'; -import { - ForbiddenException, - NotFoundException, - UseGuards, -} from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; -import { Prisma, Workspace } from '@prisma/client'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { PipelineStage } from 'src/core/@generated/pipeline-stage/pipeline-stage.model'; -import { FindManyPipelineStageArgs } from 'src/core/@generated/pipeline-stage/find-many-pipeline-stage.args'; -import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreatePipelineStageAbilityHandler, - DeletePipelineStageAbilityHandler, - ReadPipelineStageAbilityHandler, - UpdatePipelineStageAbilityHandler, -} from 'src/ability/handlers/pipeline-stage.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { - PrismaSelector, - PrismaSelect, -} from 'src/decorators/prisma-select.decorator'; -import { UpdateOnePipelineStageArgs } from 'src/core/@generated/pipeline-stage/update-one-pipeline-stage.args'; -import { CreateOnePipelineStageArgs } from 'src/core/@generated/pipeline-stage/create-one-pipeline-stage.args'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { DeleteOnePipelineStageArgs } from 'src/core/@generated/pipeline-stage/delete-one-pipeline-stage.args'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => PipelineStage) -export class PipelineStageResolver { - constructor(private readonly pipelineStageService: PipelineStageService) {} - - @Mutation(() => PipelineStage, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(CreatePipelineStageAbilityHandler) - async createOnePipelineStage( - @Args() args: CreateOnePipelineStageArgs, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'PipelineStage' }) - prismaSelect: PrismaSelect<'PipelineStage'>, - ): Promise> { - return this.pipelineStageService.create({ - data: { - ...args.data, - workspace: { connect: { id: workspace.id } }, - }, - select: prismaSelect.value, - } as Prisma.PipelineStageCreateArgs); - } - - @Query(() => [PipelineStage]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadPipelineStageAbilityHandler) - async findManyPipelineStage( - @Args() args: FindManyPipelineStageArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'PipelineStage' }) - prismaSelect: PrismaSelect<'PipelineStage'>, - ): Promise[]> { - return this.pipelineStageService.findMany({ - where: args.where - ? { - AND: [args.where, accessibleBy(ability).PipelineStage], - } - : accessibleBy(ability).PipelineStage, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - } - - @Mutation(() => PipelineStage, { - nullable: true, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdatePipelineStageAbilityHandler) - async updateOnePipelineStage( - @Args() args: UpdateOnePipelineStageArgs, - @PrismaSelector({ modelName: 'PipelineProgress' }) - prismaSelect: PrismaSelect<'PipelineProgress'>, - ): Promise | null> { - return this.pipelineStageService.update({ - where: args.where, - data: args.data, - select: prismaSelect.value, - } as Prisma.PipelineProgressUpdateArgs); - } - - @Mutation(() => PipelineStage, { - nullable: false, - }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeletePipelineStageAbilityHandler) - async deleteOnePipelineStage( - @Args() args: DeleteOnePipelineStageArgs, - ): Promise { - const pipelineStageToDelete = await this.pipelineStageService.findUnique({ - where: args.where, - }); - - if (!pipelineStageToDelete) { - throw new NotFoundException(); - } - - const { pipelineId } = pipelineStageToDelete; - - const remainingPipelineStages = await this.pipelineStageService.findMany({ - orderBy: { position: 'asc' }, - where: { - pipelineId, - NOT: { id: pipelineStageToDelete.id }, - }, - }); - - if (!remainingPipelineStages.length) { - throw new ForbiddenException( - `Deleting last pipeline stage is not allowed`, - ); - } - - const deletedPipelineStage = await this.pipelineStageService.delete({ - where: args.where, - }); - - await Promise.all( - remainingPipelineStages.map((pipelineStage, index) => { - if (pipelineStage.position === index) return; - - return this.pipelineStageService.update({ - data: { position: index }, - where: { id: pipelineStage.id }, - }); - }), - ); - - return deletedPipelineStage; - } -} diff --git a/server/src/core/pipeline/resolvers/pipeline.resolver.spec.ts b/server/src/core/pipeline/resolvers/pipeline.resolver.spec.ts deleted file mode 100644 index 0297a250e..000000000 --- a/server/src/core/pipeline/resolvers/pipeline.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { PipelineResolver } from './pipeline.resolver'; - -describe('PipelineResolver', () => { - let resolver: PipelineResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineResolver, - { - provide: PipelineService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(PipelineResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/resolvers/pipeline.resolver.ts b/server/src/core/pipeline/resolvers/pipeline.resolver.ts deleted file mode 100644 index 486b073eb..000000000 --- a/server/src/core/pipeline/resolvers/pipeline.resolver.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Resolver, Args, Query } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { Pipeline } from 'src/core/@generated/pipeline/pipeline.model'; -import { FindManyPipelineArgs } from 'src/core/@generated/pipeline/find-many-pipeline.args'; -import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { ReadPipelineAbilityHandler } from 'src/ability/handlers/pipeline.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { - PrismaSelector, - PrismaSelect, -} from 'src/decorators/prisma-select.decorator'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Pipeline) -export class PipelineResolver { - constructor(private readonly pipelineService: PipelineService) {} - - @Query(() => [Pipeline]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadPipelineAbilityHandler) - async findManyPipeline( - @Args() args: FindManyPipelineArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'Pipeline' }) - prismaSelect: PrismaSelect<'Pipeline'>, - ): Promise[]> { - return this.pipelineService.findMany({ - ...args, - where: args.where - ? { - AND: [args.where, accessibleBy(ability).Pipeline], - } - : accessibleBy(ability).Pipeline, - select: prismaSelect.value, - }); - } -} diff --git a/server/src/core/pipeline/seed-data/pipeline-stages.json b/server/src/core/pipeline/seed-data/pipeline-stages.json deleted file mode 100644 index aea167292..000000000 --- a/server/src/core/pipeline/seed-data/pipeline-stages.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "name": "New", - "color": "red", - "position": 0, - "type": "open" - }, - { - "name": "Screening", - "color": "purple", - "position": 1, - "type": "ongoing" - }, - { - "name": "Meeting", - "color": "sky", - "position": 2, - "type": "ongoing" - }, - { - "name": "Proposal", - "color": "turquoise", - "position": 3, - "type": "ongoing" - }, - { - "name": "Customer", - "color": "yellow", - "position": 4, - "type": "won" - } - ] - \ No newline at end of file diff --git a/server/src/core/pipeline/seed-data/sales-pipeline.json b/server/src/core/pipeline/seed-data/sales-pipeline.json deleted file mode 100644 index 8084910ad..000000000 --- a/server/src/core/pipeline/seed-data/sales-pipeline.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Sales pipeline", - "icon": "💰", - "pipelineProgressableType": "Company" -} - diff --git a/server/src/core/pipeline/services/pipeline-progress.service.spec.ts b/server/src/core/pipeline/services/pipeline-progress.service.spec.ts deleted file mode 100644 index b85147fcb..000000000 --- a/server/src/core/pipeline/services/pipeline-progress.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { PipelineProgressService } from './pipeline-progress.service'; - -describe('PipelineProgressService', () => { - let service: PipelineProgressService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineProgressService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(PipelineProgressService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/services/pipeline-progress.service.ts b/server/src/core/pipeline/services/pipeline-progress.service.ts deleted file mode 100644 index 1046eb6eb..000000000 --- a/server/src/core/pipeline/services/pipeline-progress.service.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class PipelineProgressService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.pipelineProgress.findFirst; - findFirstOrThrow = - this.prismaService.client.pipelineProgress.findFirstOrThrow; - - findUnique = this.prismaService.client.pipelineProgress.findUnique; - findUniqueOrThrow = - this.prismaService.client.pipelineProgress.findUniqueOrThrow; - - findMany = this.prismaService.client.pipelineProgress.findMany; - - // Create - create = this.prismaService.client.pipelineProgress.create; - createMany = this.prismaService.client.pipelineProgress.createMany; - - // Update - update = this.prismaService.client.pipelineProgress.update; - upsert = this.prismaService.client.pipelineProgress.upsert; - updateMany = this.prismaService.client.pipelineProgress.updateMany; - - // Delete - delete = this.prismaService.client.pipelineProgress.delete; - deleteMany = this.prismaService.client.pipelineProgress.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.pipelineProgress.aggregate; - - // Count - count = this.prismaService.client.pipelineProgress.count; - - // GroupBy - groupBy = this.prismaService.client.pipelineProgress.groupBy; -} diff --git a/server/src/core/pipeline/services/pipeline-stage.service.spec.ts b/server/src/core/pipeline/services/pipeline-stage.service.spec.ts deleted file mode 100644 index 9295f6df0..000000000 --- a/server/src/core/pipeline/services/pipeline-stage.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { PipelineStageService } from './pipeline-stage.service'; - -describe('PipelineStageService', () => { - let service: PipelineStageService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineStageService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(PipelineStageService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/services/pipeline-stage.service.ts b/server/src/core/pipeline/services/pipeline-stage.service.ts deleted file mode 100644 index f4052a720..000000000 --- a/server/src/core/pipeline/services/pipeline-stage.service.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; -import seedPipelineStages from 'src/core/pipeline/seed-data/pipeline-stages.json'; - -@Injectable() -export class PipelineStageService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.pipelineStage.findFirst; - findFirstOrThrow = this.prismaService.client.pipelineStage.findFirstOrThrow; - - findUnique = this.prismaService.client.pipelineStage.findUnique; - findUniqueOrThrow = this.prismaService.client.pipelineStage.findUniqueOrThrow; - - findMany = this.prismaService.client.pipelineStage.findMany; - - // Create - create = this.prismaService.client.pipelineStage.create; - createMany = this.prismaService.client.pipelineStage.createMany; - - // Update - update = this.prismaService.client.pipelineStage.update; - upsert = this.prismaService.client.pipelineStage.upsert; - updateMany = this.prismaService.client.pipelineStage.updateMany; - - // Delete - delete = this.prismaService.client.pipelineStage.delete; - deleteMany = this.prismaService.client.pipelineStage.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.pipelineStage.aggregate; - - // Count - count = this.prismaService.client.pipelineStage.count; - - // GroupBy - groupBy = this.prismaService.client.pipelineStage.groupBy; - - // Customs - async createDefaultPipelineStages({ - workspaceId, - pipelineId, - }: { - workspaceId: string; - pipelineId: string; - }) { - const pipelineStages = seedPipelineStages.map((pipelineStage) => ({ - ...pipelineStage, - workspaceId, - pipelineId, - })); - return this.createMany({ - data: pipelineStages, - }); - } -} diff --git a/server/src/core/pipeline/services/pipeline.service.spec.ts b/server/src/core/pipeline/services/pipeline.service.spec.ts deleted file mode 100644 index 17a110b10..000000000 --- a/server/src/core/pipeline/services/pipeline.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { PipelineService } from './pipeline.service'; - -describe('PipelineService', () => { - let service: PipelineService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - PipelineService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(PipelineService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/pipeline/services/pipeline.service.ts b/server/src/core/pipeline/services/pipeline.service.ts deleted file mode 100644 index 2f3d017a5..000000000 --- a/server/src/core/pipeline/services/pipeline.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PipelineProgressableType } from '@prisma/client'; - -import { PrismaService } from 'src/database/prisma.service'; -import seedSalesPipeline from 'src/core/pipeline/seed-data/sales-pipeline.json'; - -@Injectable() -export class PipelineService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.pipeline.findFirst; - findFirstOrThrow = this.prismaService.client.pipeline.findFirstOrThrow; - - findUnique = this.prismaService.client.pipeline.findUnique; - findUniqueOrThrow = this.prismaService.client.pipeline.findUniqueOrThrow; - - findMany = this.prismaService.client.pipeline.findMany; - - // Create - create = this.prismaService.client.pipeline.create; - createMany = this.prismaService.client.pipeline.createMany; - - // Update - update = this.prismaService.client.pipeline.update; - upsert = this.prismaService.client.pipeline.upsert; - updateMany = this.prismaService.client.pipeline.updateMany; - - // Delete - delete = this.prismaService.client.pipeline.delete; - deleteMany = this.prismaService.client.pipeline.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.pipeline.aggregate; - - // Count - count = this.prismaService.client.pipeline.count; - - // GroupBy - groupBy = this.prismaService.client.pipeline.groupBy; - - // Customs - async createDefaultPipeline({ workspaceId }: { workspaceId: string }) { - const pipeline = { - ...seedSalesPipeline, - pipelineProgressableType: - seedSalesPipeline.pipelineProgressableType as PipelineProgressableType, - workspaceId, - }; - - return this.create({ - data: pipeline, - }); - } -} diff --git a/server/src/coreV2/refresh-token/dtos/create-refresh-token.input.ts b/server/src/core/refresh-token/dtos/create-refresh-token.input.ts similarity index 100% rename from server/src/coreV2/refresh-token/dtos/create-refresh-token.input.ts rename to server/src/core/refresh-token/dtos/create-refresh-token.input.ts diff --git a/server/src/coreV2/refresh-token/hooks/before-create-one-refresh-token.hook.ts b/server/src/core/refresh-token/hooks/before-create-one-refresh-token.hook.ts similarity index 88% rename from server/src/coreV2/refresh-token/hooks/before-create-one-refresh-token.hook.ts rename to server/src/core/refresh-token/hooks/before-create-one-refresh-token.hook.ts index cacc807e4..ce9e3470c 100644 --- a/server/src/coreV2/refresh-token/hooks/before-create-one-refresh-token.hook.ts +++ b/server/src/core/refresh-token/hooks/before-create-one-refresh-token.hook.ts @@ -4,7 +4,7 @@ import { } from '@ptc-org/nestjs-query-graphql'; import { v4 as uuidv4 } from 'uuid'; -import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; export class BeforeCreateOneRefreshToken implements BeforeCreateOneHook diff --git a/server/src/coreV2/refresh-token/refresh-token.auto-resolver-opts.ts b/server/src/core/refresh-token/refresh-token.auto-resolver-opts.ts similarity index 100% rename from server/src/coreV2/refresh-token/refresh-token.auto-resolver-opts.ts rename to server/src/core/refresh-token/refresh-token.auto-resolver-opts.ts diff --git a/server/src/coreV2/refresh-token/refresh-token.entity.ts b/server/src/core/refresh-token/refresh-token.entity.ts similarity index 68% rename from server/src/coreV2/refresh-token/refresh-token.entity.ts rename to server/src/core/refresh-token/refresh-token.entity.ts index fc4a774ff..ff0de0e44 100644 --- a/server/src/coreV2/refresh-token/refresh-token.entity.ts +++ b/server/src/core/refresh-token/refresh-token.entity.ts @@ -9,38 +9,29 @@ import { CreateDateColumn, UpdateDateColumn, } from 'typeorm'; -import { - Authorize, - BeforeCreateOne, - IDField, -} from '@ptc-org/nestjs-query-graphql'; +import { BeforeCreateOne, IDField } from '@ptc-org/nestjs-query-graphql'; -import { UserV2 } from 'src/coreV2/user/user.entity'; +import { User } from 'src/core/user/user.entity'; import { BeforeCreateOneRefreshToken } from './hooks/before-create-one-refresh-token.hook'; -@Entity('refresh_tokens') -@ObjectType('refreshTokenV2') +@Entity({ name: 'refreshToken', schema: 'core' }) +@ObjectType('RefreshToken') @BeforeCreateOne(BeforeCreateOneRefreshToken) -@Authorize({ - authorize: (context: any) => ({ - userId: { eq: context?.req?.user?.user?.id }, - }), -}) export class RefreshToken { @IDField(() => ID) @PrimaryGeneratedColumn('uuid') id: string; - @ManyToOne(() => UserV2, (user) => user.refreshTokens) + @ManyToOne(() => User, (user) => user.refreshTokens) @JoinColumn({ name: 'userId' }) - user: UserV2; + user: User; @Column() userId: string; @Field() - @Column('time with time zone') + @Column('timestamp with time zone') expiresAt: Date; @Column('timestamp with time zone', { nullable: true }) diff --git a/server/src/coreV2/refresh-token/refresh-token.module.ts b/server/src/core/refresh-token/refresh-token.module.ts similarity index 100% rename from server/src/coreV2/refresh-token/refresh-token.module.ts rename to server/src/core/refresh-token/refresh-token.module.ts diff --git a/server/src/coreV2/refresh-token/services/refresh-token.service.spec.ts b/server/src/core/refresh-token/services/refresh-token.service.spec.ts similarity index 89% rename from server/src/coreV2/refresh-token/services/refresh-token.service.spec.ts rename to server/src/core/refresh-token/services/refresh-token.service.spec.ts index b3f948efc..b563ca550 100644 --- a/server/src/coreV2/refresh-token/services/refresh-token.service.spec.ts +++ b/server/src/core/refresh-token/services/refresh-token.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; import { RefreshTokenService } from './refresh-token.service'; diff --git a/server/src/coreV2/refresh-token/services/refresh-token.service.ts b/server/src/core/refresh-token/services/refresh-token.service.ts similarity index 65% rename from server/src/coreV2/refresh-token/services/refresh-token.service.ts rename to server/src/core/refresh-token/services/refresh-token.service.ts index acad308e3..faa99c3cb 100644 --- a/server/src/coreV2/refresh-token/services/refresh-token.service.ts +++ b/server/src/core/refresh-token/services/refresh-token.service.ts @@ -1,5 +1,5 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; -import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; export class RefreshTokenService extends TypeOrmQueryService {} diff --git a/server/src/core/user/dtos/workspace-member.dto.ts b/server/src/core/user/dtos/workspace-member.dto.ts new file mode 100644 index 000000000..0b05f7ab6 --- /dev/null +++ b/server/src/core/user/dtos/workspace-member.dto.ts @@ -0,0 +1,33 @@ +import { Field, ID, ObjectType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; + +@ObjectType('UserWorkspaceMemberName') +export class UserWorkspaceMemberName { + @Field({ nullable: false }) + firstName: string; + + @Field({ nullable: false }) + lastName: string; +} + +@ObjectType('UserWorkspaceMember') +export class UserWorkspaceMember { + @IDField(() => ID) + id: string; + + @Field(() => UserWorkspaceMemberName) + name: UserWorkspaceMemberName; + + @Field({ nullable: false }) + colorScheme: string; + + @Field({ nullable: true }) + avatarUrl: string; + + @Field({ nullable: false }) + locale: string; + + @Field({ nullable: false }) + allowImpersonation: boolean; +} diff --git a/server/src/coreV2/user/services/user.service.spec.ts b/server/src/core/user/services/user.service.spec.ts similarity index 84% rename from server/src/coreV2/user/services/user.service.spec.ts rename to server/src/core/user/services/user.service.spec.ts index b73bfe936..7bfccb0fa 100644 --- a/server/src/coreV2/user/services/user.service.spec.ts +++ b/server/src/core/user/services/user.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { UserV2 } from 'src/coreV2/user/user.entity'; +import { User } from 'src/core/user/user.entity'; import { UserService } from './user.service'; @@ -13,7 +13,7 @@ describe('UserService', () => { providers: [ UserService, { - provide: getRepositoryToken(UserV2), + provide: getRepositoryToken(User), useValue: {}, }, ], diff --git a/server/src/core/user/services/user.service.ts b/server/src/core/user/services/user.service.ts new file mode 100644 index 000000000..868de5312 --- /dev/null +++ b/server/src/core/user/services/user.service.ts @@ -0,0 +1,85 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; +import { Repository } from 'typeorm'; + +import { assert } from 'src/utils/assert'; +import { User } from 'src/core/user/user.entity'; +import { UserWorkspaceMember } from 'src/core/user/dtos/workspace-member.dto'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; + +export class UserService extends TypeOrmQueryService { + constructor( + @InjectRepository(User) + private readonly userRepository: Repository, + private readonly dataSourceService: DataSourceService, + private readonly typeORMService: TypeORMService, + ) { + super(userRepository); + } + + async loadWorkspaceMember(user: User) { + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( + user.defaultWorkspace.id, + ); + + const workspaceDataSource = await this.typeORMService.connectToDataSource( + dataSourceMetadata, + ); + + const workspaceMembers = await workspaceDataSource?.query( + `SELECT * FROM ${dataSourceMetadata.schema}."workspaceMember" WHERE "userId" = '${user.id}'`, + ); + + assert(workspaceMembers.length === 1, 'WorkspaceMember not found'); + + const userWorkspaceMember = new UserWorkspaceMember(); + + userWorkspaceMember.id = workspaceMembers[0].id; + userWorkspaceMember.colorScheme = workspaceMembers[0].colorScheme; + userWorkspaceMember.locale = workspaceMembers[0].locale; + userWorkspaceMember.allowImpersonation = + workspaceMembers[0].allowImpersonation; + userWorkspaceMember.avatarUrl = workspaceMembers[0].avatarUrl; + userWorkspaceMember.name = { + firstName: workspaceMembers[0].nameFirstName, + lastName: workspaceMembers[0].nameLastName, + }; + + return userWorkspaceMember; + } + + async createWorkspaceMember(user: User, avatarUrl?: string) { + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( + user.defaultWorkspace.id, + ); + + const workspaceDataSource = await this.typeORMService.connectToDataSource( + dataSourceMetadata, + ); + + await workspaceDataSource?.query( + `INSERT INTO ${dataSourceMetadata.schema}."workspaceMember" + ("nameFirstName", "nameLastName", "colorScheme", "userId", "allowImpersonation", "avatarUrl") + VALUES ('${user.firstName}', '${user.lastName}', 'Light', '${ + user.id + }', true, '${avatarUrl ?? ''}')`, + ); + } + + async deleteUser({ + workspaceId: _workspaceId, + userId, + }: { + workspaceId: string; + userId: string; + }) { + const user = await this.userRepository.findBy({ id: userId }); + assert(user, 'User not found'); + + return user; + } +} diff --git a/server/src/coreV2/user/user.auto-resolver-opts.ts b/server/src/core/user/user.auto-resolver-opts.ts similarity index 87% rename from server/src/coreV2/user/user.auto-resolver-opts.ts rename to server/src/core/user/user.auto-resolver-opts.ts index edc6c4887..e13034485 100644 --- a/server/src/coreV2/user/user.auto-resolver-opts.ts +++ b/server/src/core/user/user.auto-resolver-opts.ts @@ -4,7 +4,7 @@ import { PagingStrategies, } from '@ptc-org/nestjs-query-graphql'; -import { UserV2 } from 'src/coreV2/user/user.entity'; +import { User } from 'src/core/user/user.entity'; import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; export const userAutoResolverOpts: AutoResolverOpts< @@ -16,8 +16,8 @@ export const userAutoResolverOpts: AutoResolverOpts< PagingStrategies >[] = [ { - EntityClass: UserV2, - DTOClass: UserV2, + EntityClass: User, + DTOClass: User, enableTotalCount: true, pagingStrategy: PagingStrategies.CURSOR, read: { diff --git a/server/src/coreV2/user/user.entity.ts b/server/src/core/user/user.entity.ts similarity index 58% rename from server/src/coreV2/user/user.entity.ts rename to server/src/core/user/user.entity.ts index 3474992a6..0d9cdce24 100644 --- a/server/src/coreV2/user/user.entity.ts +++ b/server/src/core/user/user.entity.ts @@ -7,23 +7,17 @@ import { CreateDateColumn, UpdateDateColumn, OneToMany, + ManyToOne, } from 'typeorm'; import { IDField } from '@ptc-org/nestjs-query-graphql'; -import { GraphQLJSONObject } from 'graphql-type-json'; -import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { UserWorkspaceMember } from 'src/core/user/dtos/workspace-member.dto'; -@Entity('userV2') -@ObjectType('userV2') -// @Authorize({ -// authorize: (context: any) => ({ -// // FIXME: We do not have this relation in the database -// workspaceMember: { -// workspaceId: { eq: context?.req?.user?.workspace?.id }, -// }, -// }), -// }) -export class UserV2 { +@Entity({ name: 'user', schema: 'core' }) +@ObjectType('User') +export class User { @IDField(() => ID) @PrimaryGeneratedColumn('uuid') id: string; @@ -44,22 +38,6 @@ export class UserV2 { @Column({ default: false }) emailVerified: boolean; - @Field() - @Column({ nullable: true }) - avatarUrl: string; - - @Field() - @Column() - locale: string; - - @Field({ nullable: true }) - @Column({ nullable: true }) - phoneNumber: string; - - @Field({ nullable: true }) - @Column({ nullable: true }) - lastSeen: Date; - @Field({ nullable: true }) @Column({ default: false }) disabled: boolean; @@ -68,10 +46,6 @@ export class UserV2 { @Column({ nullable: true }) passwordHash: string; - @Field(() => GraphQLJSONObject, { nullable: true }) - @Column({ type: 'json', nullable: true }) - metadata: Record; - @Field() @Column({ default: false }) canImpersonate: boolean; @@ -88,6 +62,13 @@ export class UserV2 { @Column({ nullable: true }) deletedAt: Date; + @Field(() => Workspace, { nullable: false }) + @ManyToOne(() => Workspace, (workspace) => workspace.users) + defaultWorkspace: Workspace; + @OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user) refreshTokens: RefreshToken[]; + + @Field(() => UserWorkspaceMember, { nullable: false }) + workspaceMember: UserWorkspaceMember; } diff --git a/server/src/core/user/user.module.ts b/server/src/core/user/user.module.ts index cbefde321..567b7e1b7 100644 --- a/server/src/core/user/user.module.ts +++ b/server/src/core/user/user.module.ts @@ -1,23 +1,34 @@ +/* eslint-disable no-restricted-imports */ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { FileModule } from 'src/core/file/file.module'; -import { WorkspaceModule } from 'src/core/workspace/workspace.module'; -import { EnvironmentModule } from 'src/integrations/environment/environment.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; +import { User } from 'src/core/user/user.entity'; +import { UserResolver } from 'src/core/user/user.resolver'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; +import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; -import { UserService } from './user.service'; -import { UserResolver } from './user.resolver'; +import config from '../../../ormconfig'; + +import { userAutoResolverOpts } from './user.auto-resolver-opts'; + +import { UserService } from './services/user.service'; @Module({ imports: [ + TypeOrmModule.forRoot(config), + NestjsQueryGraphQLModule.forFeature({ + imports: [NestjsQueryTypeOrmModule.forFeature([User]), TypeORMModule], + resolvers: userAutoResolverOpts, + }), + DataSourceModule, FileModule, - WorkspaceModule, - EnvironmentModule, - AbilityModule, - PrismaModule, ], - providers: [UserService, UserResolver], exports: [UserService], + providers: [UserService, UserResolver, TypeORMService], }) export class UserModule {} diff --git a/server/src/core/user/user.resolver.spec.ts b/server/src/core/user/user.resolver.spec.ts deleted file mode 100644 index 209ea8721..000000000 --- a/server/src/core/user/user.resolver.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { AbilityFactory } from 'src/ability/ability.factory'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; - -import { UserResolver } from './user.resolver'; -import { UserService } from './user.service'; - -describe('UserResolver', () => { - let resolver: UserResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - UserResolver, - { - provide: UserService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - { - provide: FileUploadService, - useValue: {}, - }, - { - provide: EnvironmentService, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(UserResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/user/user.resolver.ts b/server/src/core/user/user.resolver.ts index 9e3a4b0ee..2a0fba704 100644 --- a/server/src/core/user/user.resolver.ts +++ b/server/src/core/user/user.resolver.ts @@ -1,48 +1,32 @@ import { - Args, Resolver, Query, - ResolveField, + Args, Parent, + ResolveField, Mutation, } from '@nestjs/graphql'; -import { UseFilters, UseGuards } from '@nestjs/common'; +import { UseGuards } from '@nestjs/common'; import crypto from 'crypto'; -import { accessibleBy } from '@casl/prisma'; -import { Prisma, Workspace } from '@prisma/client'; import { FileUpload, GraphQLUpload } from 'graphql-upload'; -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; import { SupportDriver } from 'src/integrations/environment/interfaces/support.interface'; +import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; -import { FindManyUserArgs } from 'src/core/@generated/user/find-many-user.args'; -import { User } from 'src/core/@generated/user/user.model'; -import { ExceptionFilter } from 'src/filters/exception.filter'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - DeleteUserAbilityHandler, - ReadUserAbilityHandler, - UpdateUserAbilityHandler, -} from 'src/ability/handlers/user.ability-handler'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; import { AuthUser } from 'src/decorators/auth-user.decorator'; -import { assert } from 'src/utils/assert'; -import { UpdateOneUserArgs } from 'src/core/@generated/user/update-one-user.args'; +import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { streamToBuffer } from 'src/utils/stream-to-buffer'; import { FileUploadService } from 'src/core/file/services/file-upload.service'; import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { assert } from 'src/utils/assert'; +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { UserWorkspaceMember } from 'src/core/user/dtos/workspace-member.dto'; -import { UserService } from './user.service'; +import { UserService } from './services/user.service'; const getHMACKey = (email?: string, key?: string | null) => { if (!email || !key) return null; @@ -56,85 +40,24 @@ const getHMACKey = (email?: string, key?: string | null) => { export class UserResolver { constructor( private readonly userService: UserService, + private readonly environmentService: EnvironmentService, private readonly fileUploadService: FileUploadService, - private environmentService: EnvironmentService, ) {} @Query(() => User) - async currentUser( - @AuthUser() { id }: User, - @PrismaSelector({ modelName: 'User' }) - prismaSelect: PrismaSelect<'User'>, - ) { - const select = prismaSelect.value; - - const user = await this.userService.findUnique({ - where: { - id, - }, - select, + async currentUser(@AuthUser() { id }: User) { + const user = await this.userService.findById(id, { + relations: [{ name: 'defaultWorkspace', query: {} }], }); assert(user, 'User not found'); - return user; } - @UseFilters(ExceptionFilter) - @Query(() => [User], { + @ResolveField(() => UserWorkspaceMember, { nullable: false, }) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadUserAbilityHandler) - async findManyUser( - @Args() args: FindManyUserArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'User' }) - prismaSelect: PrismaSelect<'User'>, - ): Promise[]> { - return await this.userService.findMany({ - where: args.where - ? { - AND: [args.where, accessibleBy(ability).User], - } - : accessibleBy(ability).User, - orderBy: args.orderBy, - cursor: args.cursor, - take: args.take, - skip: args.skip, - distinct: args.distinct, - select: prismaSelect.value, - }); - } - - @Mutation(() => User) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateUserAbilityHandler) - async updateUser( - @Args() args: UpdateOneUserArgs, - @AuthUser() { id }: User, - @PrismaSelector({ modelName: 'User' }) - prismaSelect: PrismaSelect<'User'>, - ) { - const user = await this.userService.findUnique({ - where: { - id, - }, - select: prismaSelect.value, - }); - assert(user, 'User not found'); - - return this.userService.update({ - where: args.where, - data: args.data, - select: prismaSelect.value, - } as Prisma.UserUpdateArgs); - } - - @ResolveField(() => String, { - nullable: false, - }) - displayName(@Parent() parent: User): string { - return `${parent.firstName ?? ''} ${parent.lastName ?? ''}`; + async workspaceMember(@Parent() user: User): Promise { + return this.userService.loadWorkspaceMember(user); } @ResolveField(() => String, { @@ -154,6 +77,10 @@ export class UserResolver { @Args({ name: 'file', type: () => GraphQLUpload }) { createReadStream, filename, mimetype }: FileUpload, ): Promise { + if (!id) { + throw new Error('User not found'); + } + const stream = createReadStream(); const buffer = await streamToBuffer(stream); const fileFolder = FileFolder.ProfilePicture; @@ -165,20 +92,11 @@ export class UserResolver { fileFolder, }); - await this.userService.update({ - where: { id }, - data: { - avatarUrl: paths[0], - }, - }); - return paths[0]; } @Mutation(() => User) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteUserAbilityHandler) - async deleteUserAccount( + async deleteUser( @AuthUser() { id: userId }: User, @AuthWorkspace() { id: workspaceId }: Workspace, ) { diff --git a/server/src/core/user/user.service.spec.ts b/server/src/core/user/user.service.spec.ts deleted file mode 100644 index 60afaa23e..000000000 --- a/server/src/core/user/user.service.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; - -import { UserService } from './user.service'; - -describe('UserService', () => { - let service: UserService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - UserService, - { - provide: PrismaService, - useValue: prismaMock, - }, - { - provide: WorkspaceService, - useValue: {}, - }, - ], - }).compile(); - - service = module.get(UserService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/user/user.service.ts b/server/src/core/user/user.service.ts deleted file mode 100644 index 6d2afe01f..000000000 --- a/server/src/core/user/user.service.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; - -import { Prisma } from '@prisma/client'; - -import { PrismaService } from 'src/database/prisma.service'; -import { assert } from 'src/utils/assert'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; - -export type UserPayload = { - displayName: string | undefined | null; - email: string; -}; - -@Injectable() -export class UserService { - constructor( - private readonly prismaService: PrismaService, - private readonly workspaceService: WorkspaceService, - ) {} - - // Find - findFirst = this.prismaService.client.user.findFirst; - findFirstOrThrow = this.prismaService.client.user.findFirstOrThrow; - - findUnique = this.prismaService.client.user.findUnique; - findUniqueOrThrow = this.prismaService.client.user.findUniqueOrThrow; - - findMany = this.prismaService.client.user.findMany; - - // Create - create = this.prismaService.client.user.create; - createMany = this.prismaService.client.user.createMany; - - // Update - update = this.prismaService.client.user.update; - upsert = this.prismaService.client.user.upsert; - updateMany = this.prismaService.client.user.updateMany; - - // Delete - delete = this.prismaService.client.user.delete; - deleteMany = this.prismaService.client.user.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.user.aggregate; - - // Count - count = this.prismaService.client.user.count; - - // GroupBy - groupBy = this.prismaService.client.user.groupBy; - - // Customs - async createUser( - args: Prisma.SelectSubset, - workspaceId?: string, - ): Promise> { - assert(args.data.email, 'email is missing', BadRequestException); - - // Create workspace if not exists - const workspace = workspaceId - ? await this.workspaceService.findUnique({ - where: { - id: workspaceId, - }, - }) - : await this.workspaceService.createDefaultWorkspace(); - - assert(workspace, 'workspace is missing', BadRequestException); - // Create user - const user = await this.prismaService.client.user.upsert({ - where: { - email: args.data.email, - }, - create: { - ...(args.data as Prisma.UserCreateInput), - defaultWorkspaceId: workspace.id, - }, - update: {}, - ...(args.select ? { select: args.select } : {}), - ...(args.include ? { include: args.include } : {}), - } as Prisma.UserUpsertArgs); - - return user as Prisma.UserGetPayload; - } - - async deleteUser({ - workspaceId, - userId, - }: { - workspaceId: string; - userId: string; - }) { - const { workspaceMember, refreshToken } = this.prismaService.client; - const user = await this.findUnique({ - where: { - id: userId, - }, - select: { - id: true, - }, - }); - assert(user, 'User not found'); - - const workspace = await this.workspaceService.findUnique({ - where: { id: workspaceId }, - select: { id: true }, - }); - assert(workspace, 'Workspace not found'); - - const workSpaceMembers = await workspaceMember.findMany({ - where: { - workspaceId, - }, - }); - - const isLastMember = - workSpaceMembers.length === 1 && workSpaceMembers[0].userId === userId; - - if (isLastMember) { - // Delete entire workspace - await this.workspaceService.deleteWorkspace({ - workspaceId, - }); - } else { - await this.prismaService.client.$transaction([ - workspaceMember.deleteMany({ - where: { userId }, - }), - - refreshToken.deleteMany({ - where: { userId }, - }), - - this.delete({ where: { id: userId } }), - ]); - } - - return user; - } -} diff --git a/server/src/core/web-hook/web-hook.module.ts b/server/src/core/web-hook/web-hook.module.ts deleted file mode 100644 index f54f86fb0..000000000 --- a/server/src/core/web-hook/web-hook.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { PrismaModule } from 'src/database/prisma.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { WebHookResolver } from 'src/core/web-hook/web-hook.resolver'; - -@Module({ - imports: [PrismaModule, AbilityModule], - providers: [WebHookResolver], -}) -export class WebHookModule {} diff --git a/server/src/core/web-hook/web-hook.resolver.ts b/server/src/core/web-hook/web-hook.resolver.ts deleted file mode 100644 index 0cf67a53a..000000000 --- a/server/src/core/web-hook/web-hook.resolver.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NotFoundException, UseGuards } from '@nestjs/common'; -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; - -import { accessibleBy } from '@casl/prisma'; - -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - CreateWebHookAbilityHandler, - DeleteWebHookAbilityHandler, - ReadWebHookAbilityHandler, -} from 'src/ability/handlers/web-hook.ability-handler'; -import { PrismaService } from 'src/database/prisma.service'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { CreateOneWebHookArgs } from 'src/core/@generated/web-hook/create-one-web-hook.args'; -import { DeleteOneWebHookArgs } from 'src/core/@generated/web-hook/delete-one-web-hook.args'; -import { FindManyWebHookArgs } from 'src/core/@generated/web-hook/find-many-web-hook.args'; -import { WebHook } from 'src/core/@generated/web-hook/web-hook.model'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => WebHook) -export class WebHookResolver { - constructor(private readonly prismaService: PrismaService) {} - @Mutation(() => WebHook) - @UseGuards(AbilityGuard) - @CheckAbilities(CreateWebHookAbilityHandler) - async createOneWebHook( - @Args() args: CreateOneWebHookArgs, - @AuthWorkspace() { id: workspaceId }: Workspace, - ): Promise { - return this.prismaService.client.webHook.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: workspaceId } } }, - }, - }); - } - - @Mutation(() => WebHook, { nullable: false }) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteWebHookAbilityHandler) - async deleteOneWebHook(@Args() args: DeleteOneWebHookArgs): Promise { - const hookToDelete = this.prismaService.client.webHook.findUnique({ - where: args.where, - }); - if (!hookToDelete) { - throw new NotFoundException(); - } - return await this.prismaService.client.webHook.delete({ - where: args.where, - }); - } - - @Query(() => [WebHook]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadWebHookAbilityHandler) - async findManyWebHook( - @Args() args: FindManyWebHookArgs, - @UserAbility() ability: AppAbility, - ) { - const filterOptions = [accessibleBy(ability).WorkspaceMember]; - if (args.where) filterOptions.push(args.where); - return this.prismaService.client.webHook.findMany({ - ...args, - where: { AND: filterOptions }, - }); - } -} diff --git a/server/src/coreV2/workspace/dtos/update-workspace-input.ts b/server/src/core/workspace/dtos/update-workspace-input.ts similarity index 60% rename from server/src/coreV2/workspace/dtos/update-workspace-input.ts rename to server/src/core/workspace/dtos/update-workspace-input.ts index e950ed2c7..4ba333e00 100644 --- a/server/src/coreV2/workspace/dtos/update-workspace-input.ts +++ b/server/src/core/workspace/dtos/update-workspace-input.ts @@ -1,31 +1,26 @@ import { Field, InputType } from '@nestjs/graphql'; -import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; +import { IsOptional, IsString } from 'class-validator'; -// FIXME: We might not need this @InputType() export class UpdateWorkspaceInput { - @Field() + @Field({ nullable: true }) @IsString() - @IsNotEmpty() @IsOptional() domainName?: string; - @Field() + @Field({ nullable: true }) @IsString() - @IsNotEmpty() @IsOptional() displayName?: string; - @Field() + @Field({ nullable: true }) @IsString() - @IsNotEmpty() @IsOptional() logo?: string; - @Field() + @Field({ nullable: true }) @IsString() - @IsNotEmpty() @IsOptional() inviteHash?: string; } diff --git a/server/src/core/workspace/resolvers/workspace-member.resolver.spec.ts b/server/src/core/workspace/resolvers/workspace-member.resolver.spec.ts deleted file mode 100644 index 4e1a74e36..000000000 --- a/server/src/core/workspace/resolvers/workspace-member.resolver.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { WorkspaceMemberService } from 'src/core/workspace/services/workspace-member.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { WorkspaceMemberResolver } from './workspace-member.resolver'; - -describe('WorkspaceMemberResolver', () => { - let resolver: WorkspaceMemberResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - WorkspaceMemberResolver, - { - provide: WorkspaceMemberService, - useValue: {}, - }, - { - provide: AbilityFactory, - useValue: {}, - }, - ], - }).compile(); - - resolver = module.get(WorkspaceMemberResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/workspace/resolvers/workspace-member.resolver.ts b/server/src/core/workspace/resolvers/workspace-member.resolver.ts deleted file mode 100644 index 30a0f2ed1..000000000 --- a/server/src/core/workspace/resolvers/workspace-member.resolver.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Args, Query, Resolver, Mutation } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { accessibleBy } from '@casl/prisma'; -import { Prisma } from '@prisma/client'; - -import { WorkspaceMember } from 'src/core/@generated/workspace-member/workspace-member.model'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - DeleteWorkspaceMemberAbilityHandler, - ReadWorkspaceMemberAbilityHandler, - UpdateWorkspaceMemberAbilityHandler, -} from 'src/ability/handlers/workspace-member.ability-handler'; -import { FindManyWorkspaceMemberArgs } from 'src/core/@generated/workspace-member/find-many-workspace-member.args'; -import { UserAbility } from 'src/decorators/user-ability.decorator'; -import { AppAbility } from 'src/ability/ability.factory'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { WorkspaceMemberService } from 'src/core/workspace/services/workspace-member.service'; -import { DeleteOneWorkspaceMemberArgs } from 'src/core/@generated/workspace-member/delete-one-workspace-member.args'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { AuthUser } from 'src/decorators/auth-user.decorator'; -import { User } from 'src/core/@generated/user/user.model'; -import { UpdateOneWorkspaceMemberArgs } from 'src/core/@generated/workspace-member/update-one-workspace-member.args'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => WorkspaceMember) -export class WorkspaceMemberResolver { - constructor( - private readonly workspaceMemberService: WorkspaceMemberService, - ) {} - - @Query(() => [WorkspaceMember]) - @UseGuards(AbilityGuard) - @CheckAbilities(ReadWorkspaceMemberAbilityHandler) - async findManyWorkspaceMember( - @Args() args: FindManyWorkspaceMemberArgs, - @UserAbility() ability: AppAbility, - @PrismaSelector({ modelName: 'WorkspaceMember' }) - prismaSelect: PrismaSelect<'WorkspaceMember'>, - ): Promise[]> { - return this.workspaceMemberService.findMany({ - ...args, - where: args.where - ? { - AND: [args.where, accessibleBy(ability).WorkspaceMember], - } - : accessibleBy(ability).WorkspaceMember, - select: prismaSelect.value, - }); - } - - @Mutation(() => WorkspaceMember) - async allowImpersonation( - @Args('allowImpersonation') allowImpersonation: boolean, - @AuthUser() user: User, - @PrismaSelector({ modelName: 'WorkspaceMember' }) - prismaSelect: PrismaSelect<'WorkspaceMember'>, - ): Promise> { - return this.workspaceMemberService.update({ - where: { - userId: user.id, - }, - data: { - allowImpersonation, - }, - select: prismaSelect.value, - }); - } - - @Mutation(() => WorkspaceMember) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteWorkspaceMemberAbilityHandler) - async deleteWorkspaceMember( - @Args() args: DeleteOneWorkspaceMemberArgs, - @PrismaSelector({ modelName: 'WorkspaceMember' }) - prismaSelect: PrismaSelect<'WorkspaceMember'>, - ): Promise> { - return this.workspaceMemberService.delete({ - where: args.where, - select: prismaSelect.value, - }); - } - - @Mutation(() => WorkspaceMember) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateWorkspaceMemberAbilityHandler) - async UpdateOneWorkspaceMember( - @Args() args: UpdateOneWorkspaceMemberArgs, - @PrismaSelector({ modelName: 'WorkspaceMember' }) - prismaSelect: PrismaSelect<'WorkspaceMember'>, - ): Promise> { - return this.workspaceMemberService.update({ - data: args.data, - where: args.where, - select: prismaSelect.value, - } as Prisma.WorkspaceMemberUpdateArgs); - } -} diff --git a/server/src/core/workspace/resolvers/workspace.resolver.spec.ts b/server/src/core/workspace/resolvers/workspace.resolver.spec.ts deleted file mode 100644 index 638899181..000000000 --- a/server/src/core/workspace/resolvers/workspace.resolver.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { AbilityFactory } from 'src/ability/ability.factory'; - -import { WorkspaceResolver } from './workspace.resolver'; - -describe('WorkspaceResolver', () => { - let resolver: WorkspaceResolver; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - WorkspaceResolver, - { provide: WorkspaceService, useValue: {} }, - { provide: AbilityFactory, useValue: {} }, - { provide: FileUploadService, useValue: {} }, - ], - }).compile(); - - resolver = module.get(WorkspaceResolver); - }); - - it('should be defined', () => { - expect(resolver).toBeDefined(); - }); -}); diff --git a/server/src/core/workspace/resolvers/workspace.resolver.ts b/server/src/core/workspace/resolvers/workspace.resolver.ts deleted file mode 100644 index f1b42c0d9..000000000 --- a/server/src/core/workspace/resolvers/workspace.resolver.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Query, Args, Mutation, Resolver } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { Prisma } from '@prisma/client'; -import { FileUpload, GraphQLUpload } from 'graphql-upload'; - -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; - -import { Workspace } from 'src/core/@generated/workspace/workspace.model'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; -import { - PrismaSelect, - PrismaSelector, -} from 'src/decorators/prisma-select.decorator'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { WorkspaceUpdateInput } from 'src/core/@generated/workspace/workspace-update.input'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { assert } from 'src/utils/assert'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { streamToBuffer } from 'src/utils/stream-to-buffer'; -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { - UpdateWorkspaceAbilityHandler, - DeleteWorkspaceAbilityHandler, -} from 'src/ability/handlers/workspace.ability-handler'; - -@UseGuards(JwtAuthGuard) -@Resolver(() => Workspace) -export class WorkspaceResolver { - constructor( - private readonly workspaceService: WorkspaceService, - private readonly fileUploadService: FileUploadService, - ) {} - - @Mutation(() => Workspace) - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateWorkspaceAbilityHandler) - async updateWorkspace( - @Args('data') data: WorkspaceUpdateInput, - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Workspace' }) - prismaSelect: PrismaSelect<'Workspace'>, - ) { - return this.workspaceService.update({ - where: { - id: workspace.id, - }, - data: { - ...data, - }, - select: prismaSelect.value, - } as Prisma.WorkspaceUpdateArgs); - } - - @Query(() => Workspace) - async currentWorkspace( - @AuthWorkspace() workspace: Workspace, - @PrismaSelector({ modelName: 'Workspace' }) - prismaSelect: PrismaSelect<'Workspace'>, - ) { - const selectedWorkspace = await this.workspaceService.findUnique({ - where: { - id: workspace.id, - }, - select: prismaSelect.value, - }); - assert(selectedWorkspace, 'User not found'); - - return selectedWorkspace; - } - - @UseGuards(AbilityGuard) - @CheckAbilities(UpdateWorkspaceAbilityHandler) - @Mutation(() => String) - async uploadWorkspaceLogo( - @AuthWorkspace() workspace: Workspace, - @Args({ name: 'file', type: () => GraphQLUpload }) - { createReadStream, filename, mimetype }: FileUpload, - ): Promise { - const stream = createReadStream(); - const buffer = await streamToBuffer(stream); - const fileFolder = FileFolder.WorkspaceLogo; - - const { paths } = await this.fileUploadService.uploadImage({ - file: buffer, - filename, - mimeType: mimetype, - fileFolder, - }); - - await this.workspaceService.update({ - where: { id: workspace.id }, - data: { - logo: paths[0], - }, - }); - - return paths[0]; - } - - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteWorkspaceAbilityHandler) - @Mutation(() => Workspace) - async deleteCurrentWorkspace( - @AuthWorkspace() { id: workspaceId }: Workspace, - @PrismaSelector({ modelName: 'Workspace' }) - { value: select }: PrismaSelect<'Workspace'>, - ) { - return this.workspaceService.deleteWorkspace({ - workspaceId, - select, - }); - } -} diff --git a/server/src/core/workspace/services/workspace-member.service.spec.ts b/server/src/core/workspace/services/workspace-member.service.spec.ts deleted file mode 100644 index 2017a0b32..000000000 --- a/server/src/core/workspace/services/workspace-member.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; - -import { WorkspaceMemberService } from './workspace-member.service'; - -describe('WorkspaceMemberService', () => { - let service: WorkspaceMemberService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - WorkspaceMemberService, - { - provide: PrismaService, - useValue: prismaMock, - }, - ], - }).compile(); - - service = module.get(WorkspaceMemberService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/core/workspace/services/workspace-member.service.ts b/server/src/core/workspace/services/workspace-member.service.ts deleted file mode 100644 index 15c043b44..000000000 --- a/server/src/core/workspace/services/workspace-member.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class WorkspaceMemberService { - constructor(private readonly prismaService: PrismaService) {} - - // Find - findFirst = this.prismaService.client.workspaceMember.findFirst; - findFirstOrThrow = this.prismaService.client.workspaceMember.findFirstOrThrow; - - findUnique = this.prismaService.client.workspaceMember.findUnique; - findUniqueOrThrow = - this.prismaService.client.workspaceMember.findUniqueOrThrow; - - findMany = this.prismaService.client.workspaceMember.findMany; - - // Create - create = this.prismaService.client.workspaceMember.create; - createMany = this.prismaService.client.workspaceMember.createMany; - - // Update - update = this.prismaService.client.workspaceMember.update; - upsert = this.prismaService.client.workspaceMember.upsert; - updateMany = this.prismaService.client.workspaceMember.updateMany; - - // Delete - delete = this.prismaService.client.workspaceMember.delete; - deleteMany = this.prismaService.client.workspaceMember.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.workspaceMember.aggregate; - - // Count - count = this.prismaService.client.workspaceMember.count; - - // GroupBy - groupBy = this.prismaService.client.workspaceMember.groupBy; -} diff --git a/server/src/core/workspace/services/workspace.service.spec.ts b/server/src/core/workspace/services/workspace.service.spec.ts index f782e8cba..51d3a7e6d 100644 --- a/server/src/core/workspace/services/workspace.service.spec.ts +++ b/server/src/core/workspace/services/workspace.service.spec.ts @@ -1,13 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; -import { PrismaService } from 'src/database/prisma.service'; -import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; -import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; -import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; -import { PersonService } from 'src/core/person/person.service'; -import { CompanyService } from 'src/core/company/company.service'; -import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service'; -import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspace-manager.service'; +import { Workspace } from 'src/core/workspace/workspace.entity'; import { WorkspaceService } from './workspace.service'; @@ -19,31 +13,7 @@ describe('WorkspaceService', () => { providers: [ WorkspaceService, { - provide: PrismaService, - useValue: prismaMock, - }, - { - provide: PipelineService, - useValue: {}, - }, - { - provide: PipelineStageService, - useValue: {}, - }, - { - provide: PersonService, - useValue: {}, - }, - { - provide: CompanyService, - useValue: {}, - }, - { - provide: PipelineProgressService, - useValue: {}, - }, - { - provide: WorkspaceManagerService, + provide: getRepositoryToken(Workspace), useValue: {}, }, ], diff --git a/server/src/core/workspace/services/workspace.service.ts b/server/src/core/workspace/services/workspace.service.ts index 0cd817b4d..0662a0799 100644 --- a/server/src/core/workspace/services/workspace.service.ts +++ b/server/src/core/workspace/services/workspace.service.ts @@ -1,167 +1,27 @@ -import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; -import { Prisma } from '@prisma/client'; -import { v4 } from 'uuid'; +import assert from 'assert'; + +import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; +import { Repository } from 'typeorm'; -import { CompanyService } from 'src/core/company/company.service'; -import { PersonService } from 'src/core/person/person.service'; -import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service'; -import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; -import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; -import { PrismaService } from 'src/database/prisma.service'; -import { assert } from 'src/utils/assert'; import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspace-manager.service'; +import { Workspace } from 'src/core/workspace/workspace.entity'; -@Injectable() -export class WorkspaceService { +export class WorkspaceService extends TypeOrmQueryService { constructor( - private readonly prismaService: PrismaService, - private readonly pipelineService: PipelineService, - private readonly companyService: CompanyService, - private readonly personService: PersonService, - private readonly pipelineStageService: PipelineStageService, - private readonly pipelineProgressService: PipelineProgressService, + @InjectRepository(Workspace) + private readonly workspaceRepository: Repository, private readonly workspaceManagerService: WorkspaceManagerService, - ) {} - - // Find - findFirst = this.prismaService.client.workspace.findFirst; - findFirstOrThrow = this.prismaService.client.workspace.findFirstOrThrow; - - findUnique = this.prismaService.client.workspace.findUnique; - findUniqueOrThrow = this.prismaService.client.workspace.findUniqueOrThrow; - - findMany = this.prismaService.client.workspace.findMany; - - // Create - create = this.prismaService.client.workspace.create; - createMany = this.prismaService.client.workspace.createMany; - - // Update - update = this.prismaService.client.workspace.update; - upsert = this.prismaService.client.workspace.upsert; - updateMany = this.prismaService.client.workspace.updateMany; - - // Delete - delete = this.prismaService.client.workspace.delete; - deleteMany = this.prismaService.client.workspace.deleteMany; - - // Aggregate - aggregate = this.prismaService.client.workspace.aggregate; - - // Count - count = this.prismaService.client.workspace.count; - - // GroupBy - groupBy = this.prismaService.client.workspace.groupBy; - - // Customs - async createDefaultWorkspace() { - const workspace = await this.create({ - data: { - inviteHash: v4(), - }, - }); - - // Create workspace schema - await this.workspaceManagerService.init(workspace.id); - - // Create default companies - const companies = await this.companyService.createDefaultCompanies({ - workspaceId: workspace.id, - }); - - // Create default people - await this.personService.createDefaultPeople({ - workspaceId: workspace.id, - companies, - }); - - // Create default pipeline - const pipeline = await this.pipelineService.createDefaultPipeline({ - workspaceId: workspace.id, - }); - - // Create default stages - await this.pipelineStageService.createDefaultPipelineStages({ - pipelineId: pipeline.id, - workspaceId: workspace.id, - }); - - return workspace; + ) { + super(workspaceRepository); } - async deleteWorkspace({ - workspaceId, - select = { id: true }, - }: { - workspaceId: string; - select?: Prisma.WorkspaceSelect; - }) { - const workspace = await this.findUnique({ - where: { id: workspaceId }, - select, - }); + async deleteWorkspace(id: string) { + const workspace = await this.workspaceRepository.findOneBy({ id }); assert(workspace, 'Workspace not found'); - const where = { workspaceId }; - - const { - workspaceMember, - attachment, - comment, - activityTarget, - activity, - apiKey, - favorite, - webHook, - } = this.prismaService.client; - - // We don't delete user or refresh tokens as they can belong to another workspace - await this.prismaService.client.$transaction([ - this.pipelineProgressService.deleteMany({ - where, - }), - this.companyService.deleteMany({ - where, - }), - this.personService.deleteMany({ - where, - }), - this.pipelineStageService.deleteMany({ - where, - }), - this.pipelineService.deleteMany({ - where, - }), - workspaceMember.deleteMany({ - where, - }), - attachment.deleteMany({ - where, - }), - comment.deleteMany({ - where, - }), - activityTarget.deleteMany({ - where, - }), - activity.deleteMany({ - where, - }), - apiKey.deleteMany({ - where, - }), - favorite.deleteMany({ - where, - }), - webHook.deleteMany({ - where, - }), - this.delete({ where: { id: workspaceId } }), - ]); - - await this.workspaceManagerService.delete(workspaceId); + await this.workspaceManagerService.delete(id); return workspace; } diff --git a/server/src/coreV2/workspace/workspace.auto-resolver-opts.ts b/server/src/core/workspace/workspace.auto-resolver-opts.ts similarity index 78% rename from server/src/coreV2/workspace/workspace.auto-resolver-opts.ts rename to server/src/core/workspace/workspace.auto-resolver-opts.ts index f94a17ff1..3ff4f0594 100644 --- a/server/src/coreV2/workspace/workspace.auto-resolver-opts.ts +++ b/server/src/core/workspace/workspace.auto-resolver-opts.ts @@ -3,10 +3,9 @@ import { PagingStrategies, ReadResolverOpts, } from '@ptc-org/nestjs-query-graphql'; -import { SortDirection } from '@ptc-org/nestjs-query-core'; import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { UpdateWorkspaceInput } from 'src/coreV2/workspace/dtos/update-workspace-input'; +import { UpdateWorkspaceInput } from 'src/core/workspace/dtos/update-workspace-input'; import { Workspace } from './workspace.entity'; @@ -25,13 +24,15 @@ export const workspaceAutoResolverOpts: AutoResolverOpts< enableTotalCount: true, pagingStrategy: PagingStrategies.CURSOR, read: { - defaultSort: [{ field: 'id', direction: SortDirection.DESC }], + many: { disabled: true }, + one: { disabled: true }, }, create: { many: { disabled: true }, one: { disabled: true }, }, update: { + one: { disabled: true }, many: { disabled: true }, }, delete: { many: { disabled: true }, one: { disabled: true } }, diff --git a/server/src/coreV2/workspace/workspace.entity.ts b/server/src/core/workspace/workspace.entity.ts similarity index 81% rename from server/src/coreV2/workspace/workspace.entity.ts rename to server/src/core/workspace/workspace.entity.ts index 860282278..76f7cd539 100644 --- a/server/src/coreV2/workspace/workspace.entity.ts +++ b/server/src/core/workspace/workspace.entity.ts @@ -5,12 +5,15 @@ import { Column, CreateDateColumn, Entity, + OneToMany, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -@Entity('workspaceV2') -@ObjectType('workspaceV2') +import { User } from 'src/core/user/user.entity'; + +@Entity({ name: 'workspace', schema: 'core' }) +@ObjectType('Workspace') export class Workspace { @IDField(() => ID) @PrimaryGeneratedColumn('uuid') @@ -43,4 +46,7 @@ export class Workspace { @Field() @UpdateDateColumn({ type: 'timestamp with time zone' }) updatedAt: Date; + + @OneToMany(() => User, (user) => user.defaultWorkspace) + users: User[]; } diff --git a/server/src/core/workspace/workspace.module.ts b/server/src/core/workspace/workspace.module.ts index 16123a1e5..3874dcc6d 100644 --- a/server/src/core/workspace/workspace.module.ts +++ b/server/src/core/workspace/workspace.module.ts @@ -1,34 +1,35 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { PipelineModule } from 'src/core/pipeline/pipeline.module'; -import { CompanyModule } from 'src/core/company/company.module'; -import { PersonModule } from 'src/core/person/person.module'; +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; + +import { FileModule } from 'src/core/file/file.module'; import { WorkspaceManagerModule } from 'src/workspace/workspace-manager/workspace-manager.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { PrismaModule } from 'src/database/prisma.module'; +import { WorkspaceResolver } from 'src/core/workspace/workspace.resolver'; + +// eslint-disable-next-line no-restricted-imports +import config from '../../../ormconfig'; + +import { Workspace } from './workspace.entity'; +import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts'; import { WorkspaceService } from './services/workspace.service'; -import { WorkspaceMemberService } from './services/workspace-member.service'; -import { WorkspaceMemberResolver } from './resolvers/workspace-member.resolver'; -import { WorkspaceResolver } from './resolvers/workspace.resolver'; @Module({ imports: [ - AbilityModule, - PipelineModule, - CompanyModule, - PersonModule, - WorkspaceManagerModule, - PrismaModule, + TypeOrmModule.forRoot(config), + NestjsQueryGraphQLModule.forFeature({ + imports: [ + NestjsQueryTypeOrmModule.forFeature([Workspace]), + WorkspaceManagerModule, + FileModule, + ], + services: [WorkspaceService], + resolvers: workspaceAutoResolverOpts, + }), ], - providers: [ - WorkspaceService, - FileUploadService, - WorkspaceMemberService, - WorkspaceMemberResolver, - WorkspaceResolver, - ], - exports: [WorkspaceService, WorkspaceMemberService], + exports: [WorkspaceService], + providers: [WorkspaceResolver, WorkspaceService], }) export class WorkspaceModule {} diff --git a/server/src/coreV2/workspace/workspace.resolver.ts b/server/src/core/workspace/workspace.resolver.ts similarity index 86% rename from server/src/coreV2/workspace/workspace.resolver.ts rename to server/src/core/workspace/workspace.resolver.ts index 35bec01f8..790179dd2 100644 --- a/server/src/coreV2/workspace/workspace.resolver.ts +++ b/server/src/core/workspace/workspace.resolver.ts @@ -10,9 +10,7 @@ import { FileUploadService } from 'src/core/file/services/file-upload.service'; import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; import { assert } from 'src/utils/assert'; import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { DeleteWorkspaceAbilityHandler } from 'src/ability/handlers/workspace.ability-handler'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { AbilityGuard } from 'src/guards/ability.guard'; +import { UpdateWorkspaceInput } from 'src/core/workspace/dtos/update-workspace-input'; import { Workspace } from './workspace.entity'; @@ -33,6 +31,14 @@ export class WorkspaceResolver { return workspace; } + @Mutation(() => Workspace) + async updateWorkspace( + @Args('data') data: UpdateWorkspaceInput, + @AuthWorkspace() workspace: Workspace, + ) { + return this.workspaceService.updateOne(workspace.id, data); + } + @Mutation(() => String) async uploadWorkspaceLogo( @AuthWorkspace() { id }: Workspace, @@ -58,8 +64,6 @@ export class WorkspaceResolver { } @Mutation(() => Workspace) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteWorkspaceAbilityHandler) async deleteCurrentWorkspace(@AuthWorkspace() { id }: Workspace) { return this.workspaceService.deleteWorkspace(id); } diff --git a/server/src/coreV2/user/services/user.service.ts b/server/src/coreV2/user/services/user.service.ts deleted file mode 100644 index 1a4b0983f..000000000 --- a/server/src/coreV2/user/services/user.service.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { InjectRepository } from '@nestjs/typeorm'; - -import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; -import { Repository } from 'typeorm'; - -import { assert } from 'src/utils/assert'; -import { UserV2 } from 'src/coreV2/user/user.entity'; - -export class UserService extends TypeOrmQueryService { - constructor( - @InjectRepository(UserV2) - private readonly userRepository: Repository, - ) { - super(userRepository); - } - - async deleteUser({ - workspaceId: _workspaceId, - userId, - }: { - workspaceId: string; - userId: string; - }) { - // const { workspaceMember, refreshToken } = this.prismaService.client; - - // const queryRunner = - // this.userRepository.manager.connection.createQueryRunner(); - // await queryRunner.connect(); - - const user = await this.userRepository.findBy({ id: userId }); - assert(user, 'User not found'); - - // FIXME: Workspace entity is not defined - // const workspace = await queryRunner.manager.findOneBy(Workspace, { - // id: userId, - // }); - // assert(workspace, 'Workspace not found'); - - // const workSpaceMembers = await queryRunner.manager.findBy(WorkspaceMember, { - // workspaceId, - // }); - - // const isLastMember = - // workSpaceMembers.length === 1 && workSpaceMembers[0].userId === userId; - - // if (isLastMember) { - // // FIXME: workspaceService is not defined - // await this.workspaceService.deleteWorkspace({ - // workspaceId, - // }); - // } else { - // await queryRunner.startTransaction(); - - // // FIXME: these other entities are not defined - // await queryRunner.manager.delete(WorkspaceMember, { - // userId, - // }); - // await queryRunner.manager.delete(RefreshToken, { - // userId, - // }); - // await queryRunner.manager.delete(User, { - // id: userId, - // }); - // await queryRunner.commitTransaction(); - - // await queryRunner.release(); - // } - - return user; - } -} diff --git a/server/src/coreV2/user/user.module.ts b/server/src/coreV2/user/user.module.ts deleted file mode 100644 index 745206c88..000000000 --- a/server/src/coreV2/user/user.module.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; -import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; - -import { AbilityModule } from 'src/ability/ability.module'; -import { FileModule } from 'src/core/file/file.module'; -import { UserV2 } from 'src/coreV2/user/user.entity'; - -import { UserResolver } from './user.resolver'; -import { userAutoResolverOpts } from './user.auto-resolver-opts'; - -import { UserService } from './services/user.service'; - -@Module({ - imports: [ - NestjsQueryGraphQLModule.forFeature({ - imports: [NestjsQueryTypeOrmModule.forFeature([UserV2])], - services: [UserService], - resolvers: userAutoResolverOpts, - }), - AbilityModule, - FileModule, - ], - providers: [UserService, UserResolver], -}) -export class UserModule {} diff --git a/server/src/coreV2/user/user.resolver.ts b/server/src/coreV2/user/user.resolver.ts deleted file mode 100644 index 469120791..000000000 --- a/server/src/coreV2/user/user.resolver.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { - Resolver, - Query, - Args, - Parent, - ResolveField, - Mutation, -} from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import crypto from 'crypto'; - -import { FileUpload, GraphQLUpload } from 'graphql-upload'; -import { Workspace } from '@prisma/client'; - -import { SupportDriver } from 'src/integrations/environment/interfaces/support.interface'; -import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; - -import { AbilityGuard } from 'src/guards/ability.guard'; -import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { DeleteUserAbilityHandler } from 'src/ability/handlers/user.ability-handler'; -import { AuthUser } from 'src/decorators/auth-user.decorator'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { streamToBuffer } from 'src/utils/stream-to-buffer'; -import { FileUploadService } from 'src/core/file/services/file-upload.service'; -import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; -import { assert } from 'src/utils/assert'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { UserV2 } from 'src/coreV2/user/user.entity'; - -import { UserService } from './services/user.service'; - -const getHMACKey = (email?: string, key?: string | null) => { - if (!email || !key) return null; - - const hmac = crypto.createHmac('sha256', key); - return hmac.update(email).digest('hex'); -}; - -@UseGuards(JwtAuthGuard) -@Resolver(() => UserV2) -export class UserResolver { - constructor( - private readonly userService: UserService, - private readonly environmentService: EnvironmentService, - private readonly fileUploadService: FileUploadService, - ) {} - - @Query(() => UserV2) - async currentUserV2(@AuthUser() { id }: UserV2) { - const user = await this.userService.findById(id); - assert(user, 'User not found'); - return user; - } - - @ResolveField(() => String, { - nullable: false, - }) - displayName(@Parent() parent: UserV2): string { - return `${parent.firstName ?? ''} ${parent.lastName ?? ''}`; - } - - @ResolveField(() => String, { - nullable: true, - }) - supportUserHash(@Parent() parent: UserV2): string | null { - if (this.environmentService.getSupportDriver() !== SupportDriver.Front) { - return null; - } - const key = this.environmentService.getSupportFrontHMACKey(); - return getHMACKey(parent.email, key); - } - - @Mutation(() => String) - async uploadProfilePictureV2( - @AuthUser() { id }: UserV2, - @Args({ name: 'file', type: () => GraphQLUpload }) - { createReadStream, filename, mimetype }: FileUpload, - ): Promise { - const stream = createReadStream(); - const buffer = await streamToBuffer(stream); - const fileFolder = FileFolder.ProfilePicture; - - const { paths } = await this.fileUploadService.uploadImage({ - file: buffer, - filename, - mimeType: mimetype, - fileFolder, - }); - - await this.userService.updateOne(id, { - avatarUrl: paths[0], - }); - - return paths[0]; - } - - @Mutation(() => UserV2) - @UseGuards(AbilityGuard) - @CheckAbilities(DeleteUserAbilityHandler) - async deleteUserV2( - @AuthUser() { id: userId }: UserV2, - @AuthWorkspace() { id: workspaceId }: Workspace, - ) { - return this.userService.deleteUser({ userId, workspaceId }); - } -} diff --git a/server/src/coreV2/workspace/services/workspace.service.spec.ts b/server/src/coreV2/workspace/services/workspace.service.spec.ts deleted file mode 100644 index a39a7ef86..000000000 --- a/server/src/coreV2/workspace/services/workspace.service.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { getRepositoryToken } from '@nestjs/typeorm'; - -import { Workspace } from 'src/coreV2/workspace/workspace.entity'; - -import { WorkspaceService } from './workspace.service'; - -describe('WorkspaceService', () => { - let service: WorkspaceService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - WorkspaceService, - { - provide: getRepositoryToken(Workspace), - useValue: {}, - }, - ], - }).compile(); - - service = module.get(WorkspaceService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/coreV2/workspace/services/workspace.service.ts b/server/src/coreV2/workspace/services/workspace.service.ts deleted file mode 100644 index de2c91ce3..000000000 --- a/server/src/coreV2/workspace/services/workspace.service.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { InjectRepository } from '@nestjs/typeorm'; - -import assert from 'assert'; - -import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; -import { Repository } from 'typeorm'; - -import { Workspace } from 'src/coreV2/workspace/workspace.entity'; -import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspace-manager.service'; - -export class WorkspaceService extends TypeOrmQueryService { - constructor( - @InjectRepository(Workspace) - private readonly workspaceRepository: Repository, - private readonly workspaceManagerService: WorkspaceManagerService, - ) { - super(workspaceRepository); - } - - async deleteWorkspace(id: string) { - const workspace = await this.workspaceRepository.findOneBy({ id }); - assert(workspace, 'Workspace not found'); - - await this.workspaceManagerService.delete(id); - - return workspace; - } -} diff --git a/server/src/coreV2/workspace/workspace.module.ts b/server/src/coreV2/workspace/workspace.module.ts deleted file mode 100644 index 3646c6eca..000000000 --- a/server/src/coreV2/workspace/workspace.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; -import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; - -import { WorkspaceResolver } from 'src/coreV2/workspace/workspace.resolver'; -import { FileModule } from 'src/core/file/file.module'; -import { AbilityModule } from 'src/ability/ability.module'; -import { WorkspaceManagerModule } from 'src/workspace/workspace-manager/workspace-manager.module'; - -import { Workspace } from './workspace.entity'; -import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts'; - -import { WorkspaceService } from './services/workspace.service'; - -@Module({ - imports: [ - NestjsQueryGraphQLModule.forFeature({ - imports: [ - NestjsQueryTypeOrmModule.forFeature([Workspace]), - WorkspaceManagerModule, - FileModule, - AbilityModule, - ], - services: [WorkspaceService], - resolvers: workspaceAutoResolverOpts, - }), - ], - providers: [WorkspaceResolver], -}) -export class WorkspaceModule {} diff --git a/server/src/database/client-mock/client.ts b/server/src/database/client-mock/client.ts deleted file mode 100644 index 736f14626..000000000 --- a/server/src/database/client-mock/client.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -const prisma = new PrismaClient(); -export default prisma; diff --git a/server/src/database/client-mock/jest-prisma-singleton.ts b/server/src/database/client-mock/jest-prisma-singleton.ts deleted file mode 100644 index 0b2100c96..000000000 --- a/server/src/database/client-mock/jest-prisma-singleton.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'; - -import prisma from './client'; - -jest.mock('./client', () => ({ - __esModule: true, - default: mockDeep(), -})); - -beforeEach(() => { - mockReset(prismaMock); -}); - -export const prismaMock = prisma as unknown as DeepMockProxy; diff --git a/server/src/database/commands/clean-inactive-workspaces.command.ts b/server/src/database/commands/clean-inactive-workspaces.command.ts deleted file mode 100644 index 4c2ed752a..000000000 --- a/server/src/database/commands/clean-inactive-workspaces.command.ts +++ /dev/null @@ -1,344 +0,0 @@ -import { - Command, - CommandRunner, - InquirerService, - Option, -} from 'nest-commander'; -import isEqual from 'lodash.isequal'; - -import { PrismaService } from 'src/database/prisma.service'; -import peopleSeed from 'src/core/person/seed-data/people.json'; -import companiesSeed from 'src/core/company/seed-data/companies.json'; -import pipelineStagesSeed from 'src/core/pipeline/seed-data/pipeline-stages.json'; -import pipelinesSeed from 'src/core/pipeline/seed-data/sales-pipeline.json'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; - -interface DataCleanInactiveOptions { - days?: number; - sameAsSeedDays?: number; - dryRun?: boolean; - confirmation?: boolean; - workspaceId?: string; -} - -interface ActivityReport { - displayName: string; - maxUpdatedAt: string; - inactiveDays: number; - sameAsSeed: boolean; -} - -interface DataCleanResults { - [key: string]: ActivityReport; -} - -const formattedPipelineStagesSeed = pipelineStagesSeed.map((pipelineStage) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { position, ...rest } = pipelineStage; - return rest; -}); - -@Command({ - name: 'workspaces:clean-inactive', - description: 'Clean inactive workspaces from the public database schema', -}) -export class DataCleanInactiveCommand extends CommandRunner { - constructor( - private readonly prismaService: PrismaService, - private readonly workspaceService: WorkspaceService, - private readonly inquiererService: InquirerService, - ) { - super(); - } - - @Option({ - flags: '-w, --workspaceId [workspace id]', - description: 'Specific workspaceId to apply cleaning', - }) - parseWorkspace(val: string): string { - return val; - } - - @Option({ - flags: '-d, --days [inactive days threshold]', - description: 'Inactive days threshold', - defaultValue: 60, - }) - parseDays(val: string): number { - return Number(val); - } - - @Option({ - flags: '-s, --same-as-seed-days [same as seed days threshold]', - description: 'Same as seed days threshold', - defaultValue: 10, - }) - parseSameAsSeedDays(val: string): number { - return Number(val); - } - - @Option({ - flags: '--dry-run [dry run]', - description: 'List inactive workspaces without removing them', - }) - parseDryRun(val: string): boolean { - return Boolean(val); - } - - // We look for public tables which contain workspaceId and updatedAt columns and exist in production database - getRelevantTables() { - return Object.keys(this.prismaService.client).filter( - (name) => - !name.startsWith('_') && - !name.startsWith('$') && - !name.includes('user') && - !name.includes('refreshToken') && - !name.includes('workspace') && - !name.includes('favorite'), - ); - } - - async getMaxUpdatedAtForAllWorkspaces(tables, workspaces) { - const result = {}; - for (const table of tables) { - result[table] = {}; - const groupByWorkspaces = await this.prismaService.client[table].groupBy({ - by: ['workspaceId'], - _max: { updatedAt: true }, - where: { - workspaceId: { in: workspaces.map((workspace) => workspace.id) }, - }, - }); - for (const groupByWorkspace of groupByWorkspaces) { - result[table][groupByWorkspace.workspaceId] = - groupByWorkspace._max.updatedAt; - } - } - return result; - } - - async addMaxUpdatedAtToWorkspaces( - result, - workspace, - table, - maxUpdatedAtForAllWorkspaces, - ) { - const newUpdatedAt = maxUpdatedAtForAllWorkspaces[table][workspace.id]; - if (!result[workspace.id]) { - result[workspace.id] = { - displayName: workspace.displayName, - maxUpdatedAt: null, - }; - } - if ( - newUpdatedAt && - new Date(result[workspace.id].maxUpdatedAt) < new Date(newUpdatedAt) - ) { - result[workspace.id].maxUpdatedAt = newUpdatedAt; - } - } - async getSeedTableData(workspaces) { - const where = { - workspaceId: { in: workspaces.map((workspace) => workspace.id) }, - }; - const companies = await this.prismaService.client.company.findMany({ - select: { - name: true, - domainName: true, - address: true, - employees: true, - workspaceId: true, - }, - where, - }); - const people = await this.prismaService.client.person.findMany({ - select: { - firstName: true, - lastName: true, - city: true, - email: true, - avatarUrl: true, - workspaceId: true, - }, - where, - }); - const pipelineStages = - await this.prismaService.client.pipelineStage.findMany({ - select: { - name: true, - color: true, - type: true, - workspaceId: true, - }, - where, - }); - const pipelines = await this.prismaService.client.pipeline.findMany({ - select: { - name: true, - icon: true, - pipelineProgressableType: true, - workspaceId: true, - }, - where, - }); - return { - companies, - people, - pipelineStages, - pipelines, - }; - } - - async detectWorkspacesWithSeedDataOnly(result, workspace, seedTableData) { - const companies = seedTableData.companies.reduce((filtered, company) => { - if (company.workspaceId === workspace.id) { - delete company.workspaceId; - filtered.push(company); - } - return filtered; - }, []); - const people = seedTableData.people.reduce((filtered, person) => { - if (person.workspaceId === workspace.id) { - delete person.workspaceId; - filtered.push(person); - } - return filtered; - }, []); - const pipelineStages = seedTableData.pipelineStages.reduce( - (filtered, pipelineStage) => { - if (pipelineStage.workspaceId === workspace.id) { - delete pipelineStage.workspaceId; - filtered.push(pipelineStage); - } - return filtered; - }, - [], - ); - const pipelines = seedTableData.pipelines.reduce((filtered, pipeline) => { - if (pipeline.workspaceId === workspace.id) { - delete pipeline.workspaceId; - filtered.push(pipeline); - } - return filtered; - }, []); - if ( - isEqual(people, peopleSeed) && - isEqual(companies, companiesSeed) && - isEqual(pipelineStages, formattedPipelineStagesSeed) && - isEqual(pipelines, [pipelinesSeed]) - ) { - result[workspace.id].sameAsSeed = true; - } else { - { - result[workspace.id].sameAsSeed = false; - } - } - } - - async getWorkspaces(options) { - const where = options.workspaceId - ? { id: { equals: options.workspaceId } } - : {}; - return await this.prismaService.client.workspace.findMany({ - where, - orderBy: [{ createdAt: 'asc' }], - }); - } - - async findInactiveWorkspaces(workspaces, result) { - const tables = this.getRelevantTables(); - const maxUpdatedAtForAllWorkspaces = - await this.getMaxUpdatedAtForAllWorkspaces(tables, workspaces); - const seedTableData = await this.getSeedTableData(workspaces); - for (const workspace of workspaces) { - for (const table of tables) { - await this.addMaxUpdatedAtToWorkspaces( - result, - workspace, - table, - maxUpdatedAtForAllWorkspaces, - ); - } - await this.detectWorkspacesWithSeedDataOnly( - result, - workspace, - seedTableData, - ); - } - } - - filterResults(result, options) { - for (const workspaceId in result) { - const timeDifferenceInSeconds = Math.abs( - new Date().getTime() - - new Date(result[workspaceId].maxUpdatedAt).getTime(), - ); - const timeDifferenceInDays = Math.ceil( - timeDifferenceInSeconds / (1000 * 3600 * 24), - ); - if ( - timeDifferenceInDays < options.days && - (!result[workspaceId].sameAsSeed || - timeDifferenceInDays < options.sameAsSeedDays) - ) { - delete result[workspaceId]; - } else { - result[workspaceId].inactiveDays = timeDifferenceInDays; - } - } - } - - async delete(result, options) { - const workspaceCount = Object.keys(result).length; - if (workspaceCount) { - console.log( - `Deleting \x1b[36m${workspaceCount}\x1b[0m inactive since \x1b[36m${options.days} days\x1b[0m or same as seed since \x1b[36m${options.sameAsSeedDays} days\x1b[0m workspaces`, - ); - } - let count = 1; - for (const workspaceId in result) { - process.stdout.write(`- deleting ${workspaceId} ...`); - await this.workspaceService.deleteWorkspace({ - workspaceId, - }); - console.log( - ` done! ....... ${Math.floor((100 * count) / workspaceCount)}%`, - ); - count += 1; - } - } - - displayResults(result, totalWorkspacesCount) { - console.log(result); - console.log( - `${ - Object.keys(result).length - } out of ${totalWorkspacesCount} workspace(s) checked (${Math.floor( - (100 * Object.keys(result).length) / totalWorkspacesCount, - )}%) will be deleted`, - ); - } - - async run( - _passedParam: string[], - options: DataCleanInactiveOptions, - ): Promise { - const result: DataCleanResults = {}; - const workspaces = await this.getWorkspaces(options); - const totalWorkspacesCount = workspaces.length; - console.log(totalWorkspacesCount, 'workspace(s) to analyse'); - await this.findInactiveWorkspaces(workspaces, result); - this.filterResults(result, options); - this.displayResults(result, totalWorkspacesCount); - if (!options.dryRun) { - options = await this.inquiererService.ask('confirm', options); - if (!options.confirmation) { - console.log('Cleaning aborted'); - return; - } - } - if (!options.dryRun) { - await this.delete(result, options); - } - } -} diff --git a/server/src/database/commands/data-seed-workspace.command.ts b/server/src/database/commands/data-seed-workspace.command.ts index e7bf83a1d..939250da6 100644 --- a/server/src/database/commands/data-seed-workspace.command.ts +++ b/server/src/database/commands/data-seed-workspace.command.ts @@ -1,4 +1,5 @@ import { Command, CommandRunner } from 'nest-commander'; +import { DataSource } from 'typeorm'; import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service'; @@ -12,6 +13,8 @@ import { seedOpportunity } from 'src/database/typeorm-seeds/workspace/opportunit import { seedPipelineStep } from 'src/database/typeorm-seeds/workspace/pipeline-step'; import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspaceMember'; import { seedPeople } from 'src/database/typeorm-seeds/workspace/people'; +import { seedCoreSchema } from 'src/database/typeorm-seeds/core'; +import { EnvironmentService } from 'src/integrations/environment/environment.service'; // TODO: implement dry-run @Command({ @@ -23,6 +26,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { workspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419'; constructor( + private readonly environmentService: EnvironmentService, private readonly dataSourceService: DataSourceService, private readonly typeORMService: TypeORMService, private readonly workspaceMigrationService: WorkspaceMigrationService, @@ -32,6 +36,22 @@ export class DataSeedWorkspaceCommand extends CommandRunner { } async run(): Promise { + try { + const dataSource = new DataSource({ + url: this.environmentService.getPGDatabaseUrl(), + type: 'postgres', + logging: true, + schema: 'public', + }); + await dataSource.initialize(); + + await seedCoreSchema(dataSource); + await seedMetadataSchema(dataSource); + } catch (error) { + console.error(error); + return; + } + const dataSourceMetadata = await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( this.workspaceId, @@ -46,8 +66,6 @@ export class DataSeedWorkspaceCommand extends CommandRunner { } try { - await seedMetadataSchema(workspaceDataSource, 'metadata'); - await this.workspaceMigrationService.insertStandardMigrations( this.workspaceId, ); diff --git a/server/src/database/commands/database-command.module.ts b/server/src/database/commands/database-command.module.ts index 7e70ddfa3..f42f2efb3 100644 --- a/server/src/database/commands/database-command.module.ts +++ b/server/src/database/commands/database-command.module.ts @@ -1,11 +1,6 @@ import { Module } from '@nestjs/common'; -import { DataCleanInactiveCommand } from 'src/database/commands/clean-inactive-workspaces.command'; import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question'; -import { PipelineModule } from 'src/core/pipeline/pipeline.module'; -import { CompanyModule } from 'src/core/company/company.module'; -import { PersonModule } from 'src/core/person/person.module'; -import { PrismaModule } from 'src/database/prisma.module'; import { WorkspaceManagerModule } from 'src/workspace/workspace-manager/workspace-manager.module'; import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; import { WorkspaceMigrationModule } from 'src/metadata/workspace-migration/workspace-migration.module'; @@ -16,21 +11,13 @@ import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-worksp @Module({ imports: [ - PipelineModule, - CompanyModule, - PersonModule, WorkspaceManagerModule, - PrismaModule, DataSourceModule, TypeORMModule, WorkspaceMigrationModule, WorkspaceMigrationRunnerModule, WorkspaceModule, ], - providers: [ - DataSeedWorkspaceCommand, - DataCleanInactiveCommand, - ConfirmationQuestion, - ], + providers: [DataSeedWorkspaceCommand, ConfirmationQuestion], }) export class DatabaseCommandModule {} diff --git a/server/src/database/migrations/20230523144316_init/migration.sql b/server/src/database/migrations/20230523144316_init/migration.sql deleted file mode 100644 index 5bc95ea1e..000000000 --- a/server/src/database/migrations/20230523144316_init/migration.sql +++ /dev/null @@ -1,103 +0,0 @@ --- CreateTable -CREATE TABLE "users" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "lastSeen" TIMESTAMP(3), - "disabled" BOOLEAN NOT NULL DEFAULT false, - "displayName" TEXT NOT NULL, - "email" TEXT NOT NULL, - "avatarUrl" TEXT, - "locale" TEXT NOT NULL, - "phoneNumber" TEXT, - "passwordHash" TEXT, - "emailVerified" BOOLEAN NOT NULL DEFAULT false, - "metadata" JSONB, - - CONSTRAINT "users_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "workspaces" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "domainName" TEXT NOT NULL, - "displayName" TEXT NOT NULL, - - CONSTRAINT "workspaces_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "workspace_members" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "userId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "workspace_members_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "companies" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "name" TEXT NOT NULL, - "domainName" TEXT NOT NULL, - "address" TEXT NOT NULL, - "employees" INTEGER NOT NULL, - "accountOwnerId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "companies_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "people" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "firstname" TEXT NOT NULL, - "lastname" TEXT NOT NULL, - "email" TEXT NOT NULL, - "phone" TEXT NOT NULL, - "city" TEXT NOT NULL, - "companyId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "people_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "workspaces_domainName_key" ON "workspaces"("domainName"); - --- CreateIndex -CREATE UNIQUE INDEX "workspace_members_userId_key" ON "workspace_members"("userId"); - --- AddForeignKey -ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "companies" ADD CONSTRAINT "companies_accountOwnerId_fkey" FOREIGN KEY ("accountOwnerId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "companies" ADD CONSTRAINT "companies_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "people" ADD CONSTRAINT "people_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "people" ADD CONSTRAINT "people_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230523151950_init/migration.sql b/server/src/database/migrations/20230523151950_init/migration.sql deleted file mode 100644 index 8f76ed253..000000000 --- a/server/src/database/migrations/20230523151950_init/migration.sql +++ /dev/null @@ -1,17 +0,0 @@ --- DropForeignKey -ALTER TABLE "companies" DROP CONSTRAINT "companies_accountOwnerId_fkey"; - --- DropForeignKey -ALTER TABLE "people" DROP CONSTRAINT "people_companyId_fkey"; - --- AlterTable -ALTER TABLE "companies" ALTER COLUMN "accountOwnerId" DROP NOT NULL; - --- AlterTable -ALTER TABLE "people" ALTER COLUMN "companyId" DROP NOT NULL; - --- AddForeignKey -ALTER TABLE "companies" ADD CONSTRAINT "companies_accountOwnerId_fkey" FOREIGN KEY ("accountOwnerId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "people" ADD CONSTRAINT "people_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230523152119_init/migration.sql b/server/src/database/migrations/20230523152119_init/migration.sql deleted file mode 100644 index 46e9233a1..000000000 --- a/server/src/database/migrations/20230523152119_init/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "companies" ALTER COLUMN "employees" DROP NOT NULL; diff --git a/server/src/database/migrations/20230524200120_add_refresh_token/migration.sql b/server/src/database/migrations/20230524200120_add_refresh_token/migration.sql deleted file mode 100644 index cba4df125..000000000 --- a/server/src/database/migrations/20230524200120_add_refresh_token/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ --- CreateTable -CREATE TABLE "RefreshToken" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "refreshToken" TEXT NOT NULL, - "userId" TEXT NOT NULL, - - CONSTRAINT "RefreshToken_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "RefreshToken" ADD CONSTRAINT "RefreshToken_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230525210157_rename_refresh_token_table/migration.sql b/server/src/database/migrations/20230525210157_rename_refresh_token_table/migration.sql deleted file mode 100644 index e5e9ec482..000000000 --- a/server/src/database/migrations/20230525210157_rename_refresh_token_table/migration.sql +++ /dev/null @@ -1,26 +0,0 @@ -/* - Warnings: - - - You are about to drop the `RefreshToken` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "RefreshToken" DROP CONSTRAINT "RefreshToken_userId_fkey"; - --- DropTable -DROP TABLE "RefreshToken"; - --- CreateTable -CREATE TABLE "refresh_tokens" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "refreshToken" TEXT NOT NULL, - "userId" TEXT NOT NULL, - - CONSTRAINT "refresh_tokens_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230526152016_add_logo_workspace/migration.sql b/server/src/database/migrations/20230526152016_add_logo_workspace/migration.sql deleted file mode 100644 index a21064dc3..000000000 --- a/server/src/database/migrations/20230526152016_add_logo_workspace/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "workspaces" ADD COLUMN "logo" TEXT; diff --git a/server/src/database/migrations/20230531093843_create_comments/migration.sql b/server/src/database/migrations/20230531093843_create_comments/migration.sql deleted file mode 100644 index 6c6fd0a3c..000000000 --- a/server/src/database/migrations/20230531093843_create_comments/migration.sql +++ /dev/null @@ -1,55 +0,0 @@ --- CreateEnum -CREATE TYPE "CommentableType" AS ENUM ('Person', 'Company'); - --- CreateTable -CREATE TABLE "comment_threads" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "comment_threads_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "comments" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "body" TEXT NOT NULL, - "authorId" TEXT NOT NULL, - "commentThreadId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "comments_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "comment_thread_targets" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "commentThreadId" TEXT NOT NULL, - "commentableType" "CommentableType" NOT NULL, - "commentableId" TEXT NOT NULL, - - CONSTRAINT "comment_thread_targets_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "comment_threads" ADD CONSTRAINT "comment_threads_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_commentThreadId_fkey" FOREIGN KEY ("commentThreadId") REFERENCES "comment_threads"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comment_thread_targets" ADD CONSTRAINT "comment_thread_targets_commentThreadId_fkey" FOREIGN KEY ("commentThreadId") REFERENCES "comment_threads"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230602102913_create_pipelines/migration.sql b/server/src/database/migrations/20230602102913_create_pipelines/migration.sql deleted file mode 100644 index 39d10c13b..000000000 --- a/server/src/database/migrations/20230602102913_create_pipelines/migration.sql +++ /dev/null @@ -1,59 +0,0 @@ --- CreateEnum -CREATE TYPE "PipelineProgressableType" AS ENUM ('Person', 'Company'); - --- CreateTable -CREATE TABLE "pipelines" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "name" TEXT NOT NULL, - "icon" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "pipelines_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "pipeline_stages" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "name" TEXT NOT NULL, - "type" TEXT NOT NULL, - "color" TEXT NOT NULL, - "pipelineId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "pipeline_stages_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "pipeline_progresses" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - "pipelineId" TEXT NOT NULL, - "pipelineStageId" TEXT NOT NULL, - "associableType" "PipelineProgressableType" NOT NULL, - "associableId" TEXT NOT NULL, - - CONSTRAINT "pipeline_progresses_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "pipelines" ADD CONSTRAINT "pipelines_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_stages" ADD CONSTRAINT "pipeline_stages_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "pipelines"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_stages" ADD CONSTRAINT "pipeline_stages_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "pipelines"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_pipelineStageId_fkey" FOREIGN KEY ("pipelineStageId") REFERENCES "pipeline_stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230613132410_rename_pipeline_progress_associable/migration.sql b/server/src/database/migrations/20230613132410_rename_pipeline_progress_associable/migration.sql deleted file mode 100644 index 84dd1cfeb..000000000 --- a/server/src/database/migrations/20230613132410_rename_pipeline_progress_associable/migration.sql +++ /dev/null @@ -1,13 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `associableId` on the `pipeline_progresses` table. All the data in the column will be lost. - - You are about to drop the column `associableType` on the `pipeline_progresses` table. All the data in the column will be lost. - - Added the required column `progressableId` to the `pipeline_progresses` table without a default value. This is not possible if the table is not empty. - - Added the required column `progressableType` to the `pipeline_progresses` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "pipeline_progresses" RENAME "associableId" TO "progressableId"; -ALTER TABLE "pipeline_progresses" RENAME "associableType" TO "progressableType"; - diff --git a/server/src/database/migrations/20230614090456_add_workspace_to_pipeline_progress/migration.sql b/server/src/database/migrations/20230614090456_add_workspace_to_pipeline_progress/migration.sql deleted file mode 100644 index f771e1876..000000000 --- a/server/src/database/migrations/20230614090456_add_workspace_to_pipeline_progress/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - Added the required column `workspaceId` to the `pipeline_progresses` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "pipeline_progresses" ADD COLUMN "workspaceId" TEXT NOT NULL; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230616135457_alter_table_refresh_token/migration.sql b/server/src/database/migrations/20230616135457_alter_table_refresh_token/migration.sql deleted file mode 100644 index d55582556..000000000 --- a/server/src/database/migrations/20230616135457_alter_table_refresh_token/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `refreshToken` on the `refresh_tokens` table. All the data in the column will be lost. - - Added the required column `expiresAt` to the `refresh_tokens` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "refresh_tokens" DROP COLUMN "refreshToken", -ADD COLUMN "expiresAt" TIMESTAMP(3) NOT NULL, -ADD COLUMN "isRevoked" BOOLEAN NOT NULL DEFAULT false; diff --git a/server/src/database/migrations/20230619143949_add_progressable_type_on_pipeline/migration.sql b/server/src/database/migrations/20230619143949_add_progressable_type_on_pipeline/migration.sql deleted file mode 100644 index 31dddc6af..000000000 --- a/server/src/database/migrations/20230619143949_add_progressable_type_on_pipeline/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "pipelines" ADD COLUMN "pipelineProgressableType" "PipelineProgressableType" NOT NULL DEFAULT 'Company'; diff --git a/server/src/database/migrations/20230627132509_cascade_delete_comment/migration.sql b/server/src/database/migrations/20230627132509_cascade_delete_comment/migration.sql deleted file mode 100644 index 116ebd672..000000000 --- a/server/src/database/migrations/20230627132509_cascade_delete_comment/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- DropForeignKey -ALTER TABLE "comments" DROP CONSTRAINT "comments_commentThreadId_fkey"; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_commentThreadId_fkey" FOREIGN KEY ("commentThreadId") REFERENCES "comment_threads"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230627132647_cascade_delete_comment_thread_target/migration.sql b/server/src/database/migrations/20230627132647_cascade_delete_comment_thread_target/migration.sql deleted file mode 100644 index 67a3839e6..000000000 --- a/server/src/database/migrations/20230627132647_cascade_delete_comment_thread_target/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- DropForeignKey -ALTER TABLE "comment_thread_targets" DROP CONSTRAINT "comment_thread_targets_commentThreadId_fkey"; - --- AddForeignKey -ALTER TABLE "comment_thread_targets" ADD CONSTRAINT "comment_thread_targets_commentThreadId_fkey" FOREIGN KEY ("commentThreadId") REFERENCES "comment_threads"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230629144237_alter_table_user_add_first_name_last_name/migration.sql b/server/src/database/migrations/20230629144237_alter_table_user_add_first_name_last_name/migration.sql deleted file mode 100644 index 8a7024a00..000000000 --- a/server/src/database/migrations/20230629144237_alter_table_user_add_first_name_last_name/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - Added the required column `firstName` to the `users` table without a default value. This is not possible if the table is not empty. - - Added the required column `lastName` to the `users` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "users" ADD COLUMN "firstName" TEXT NOT NULL DEFAULT '', -ADD COLUMN "lastName" TEXT NOT NULL DEFAULT '', -ALTER COLUMN "displayName" DROP NOT NULL; diff --git a/server/src/database/migrations/20230629145002_alter_table_person_rename_first_name_last_name/migration.sql b/server/src/database/migrations/20230629145002_alter_table_person_rename_first_name_last_name/migration.sql deleted file mode 100644 index 6113bdb9a..000000000 --- a/server/src/database/migrations/20230629145002_alter_table_person_rename_first_name_last_name/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- AlterTable -ALTER TABLE "people" -ADD COLUMN "firstName" TEXT, -ADD COLUMN "lastName" TEXT; - --- Update new columns using old columns -UPDATE "people" -SET "firstName" = "firstname", - "lastName" = "lastname"; - --- Drop old columns -ALTER TABLE "people" -DROP COLUMN "firstname", -DROP COLUMN "lastname"; - --- Make new columns NOT NULL -ALTER TABLE "people" -ALTER COLUMN "firstName" SET NOT NULL, -ALTER COLUMN "lastName" SET NOT NULL; diff --git a/server/src/database/migrations/20230704123330_alter_table_user_delete_display_name/migration.sql b/server/src/database/migrations/20230704123330_alter_table_user_delete_display_name/migration.sql deleted file mode 100644 index 0b87aa98d..000000000 --- a/server/src/database/migrations/20230704123330_alter_table_user_delete_display_name/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `displayName` on the `users` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "users" DROP COLUMN "displayName", -ALTER COLUMN "firstName" DROP DEFAULT, -ALTER COLUMN "lastName" DROP DEFAULT; diff --git a/server/src/database/migrations/20230706072223_add_body_title_author_fields_to_comment_threads/migration.sql b/server/src/database/migrations/20230706072223_add_body_title_author_fields_to_comment_threads/migration.sql deleted file mode 100644 index 2e333f05e..000000000 --- a/server/src/database/migrations/20230706072223_add_body_title_author_fields_to_comment_threads/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ --- AlterTable -ALTER TABLE "comment_threads" ADD COLUMN "body" TEXT, -ADD COLUMN "title" TEXT, -ADD COLUMN "authorId" TEXT; - - --- Update field with a random user if some rows already exist... -UPDATE "comment_threads" -SET "authorId" = (SELECT id FROM users LIMIT 1); - - -ALTER TABLE "comment_threads" -ALTER COLUMN "authorId" SET NOT NULL; - -ALTER TABLE "comment_threads" ADD CONSTRAINT "comment_threads_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql b/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql deleted file mode 100644 index 2402ca54a..000000000 --- a/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql +++ /dev/null @@ -1,6 +0,0 @@ --- DropIndex -DROP INDEX "workspaces_domainName_key"; - --- AlterTable -ALTER TABLE "workspaces" ALTER COLUMN "domainName" DROP NOT NULL, -ALTER COLUMN "displayName" DROP NOT NULL; diff --git a/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql b/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql deleted file mode 100644 index e943e4209..000000000 --- a/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "users" ALTER COLUMN "firstName" DROP NOT NULL, -ALTER COLUMN "lastName" DROP NOT NULL; diff --git a/server/src/database/migrations/20230707011226_add_opportunities_fields/migration.sql b/server/src/database/migrations/20230707011226_add_opportunities_fields/migration.sql deleted file mode 100644 index caa4532e5..000000000 --- a/server/src/database/migrations/20230707011226_add_opportunities_fields/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "pipeline_progresses" ADD COLUMN "amount" INTEGER, -ADD COLUMN "closeDate" TIMESTAMP(3); diff --git a/server/src/database/migrations/20230710235621_pipline_stage_index/migration.sql b/server/src/database/migrations/20230710235621_pipline_stage_index/migration.sql deleted file mode 100644 index 7ccb23420..000000000 --- a/server/src/database/migrations/20230710235621_pipline_stage_index/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "pipeline_stages" ADD COLUMN "index" INTEGER; diff --git a/server/src/database/migrations/20230711002359_workspace_invite_hash/migration.sql b/server/src/database/migrations/20230711002359_workspace_invite_hash/migration.sql deleted file mode 100644 index d603f3293..000000000 --- a/server/src/database/migrations/20230711002359_workspace_invite_hash/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "workspaces" ADD COLUMN "inviteHash" TEXT; diff --git a/server/src/database/migrations/20230715235515_task_type/migration.sql b/server/src/database/migrations/20230715235515_task_type/migration.sql deleted file mode 100644 index 1b5d0bf38..000000000 --- a/server/src/database/migrations/20230715235515_task_type/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ --- CreateEnum -CREATE TYPE "ActivityType" AS ENUM ('Note', 'Task'); - --- AlterTable -ALTER TABLE "comment_threads" ADD COLUMN "assigneeId" TEXT, -ADD COLUMN "completedAt" TIMESTAMP(3), -ADD COLUMN "dueAt" TIMESTAMP(3), -ADD COLUMN "reminderAt" TIMESTAMP(3), -ADD COLUMN "type" "ActivityType" NOT NULL DEFAULT 'Note'; - --- AddForeignKey -ALTER TABLE "comment_threads" ADD CONSTRAINT "comment_threads_assigneeId_fkey" FOREIGN KEY ("assigneeId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230718070849_alter_table_user_and_add_table_user_settings/migration.sql b/server/src/database/migrations/20230718070849_alter_table_user_and_add_table_user_settings/migration.sql deleted file mode 100644 index e5aa554ff..000000000 --- a/server/src/database/migrations/20230718070849_alter_table_user_and_add_table_user_settings/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- Adding 'settingsId' to 'users' table without NOT NULL constraint initially -ALTER TABLE "users" ADD COLUMN "settingsId" TEXT; - --- Creating 'user_settings' table -CREATE TYPE "ColorScheme" AS ENUM ('Light', 'Dark', 'System'); -CREATE TABLE "user_settings" ( - "id" TEXT NOT NULL, - "colorScheme" "ColorScheme" NOT NULL DEFAULT 'System', - "locale" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "user_settings_pkey" PRIMARY KEY ("id") -); - --- Applying constraints and indexes -CREATE UNIQUE INDEX "users_settingsId_key" ON "users"("settingsId"); -ALTER TABLE "users" ADD CONSTRAINT "users_settingsId_fkey" FOREIGN KEY ("settingsId") REFERENCES "user_settings"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - diff --git a/server/src/database/migrations/20230718142504_add_attachments/migration.sql b/server/src/database/migrations/20230718142504_add_attachments/migration.sql deleted file mode 100644 index 1f3c7361d..000000000 --- a/server/src/database/migrations/20230718142504_add_attachments/migration.sql +++ /dev/null @@ -1,24 +0,0 @@ --- CreateEnum -CREATE TYPE "AttachmentType" AS ENUM ('Image', 'Audio', 'Video', 'TextDocument', 'Spreadsheet', 'Archive', 'Other'); - --- CreateTable -CREATE TABLE "attachments" ( - "id" TEXT NOT NULL, - "fullPath" TEXT NOT NULL, - "type" "AttachmentType" NOT NULL, - "name" TEXT NOT NULL, - "authorId" TEXT NOT NULL, - "activityId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - "deletedAt" TIMESTAMP(3), - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "attachments_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "comment_threads"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230718224818_add_opportunity_fields/migration.sql b/server/src/database/migrations/20230718224818_add_opportunity_fields/migration.sql deleted file mode 100644 index d86a7d006..000000000 --- a/server/src/database/migrations/20230718224818_add_opportunity_fields/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ -/* - Warnings: - - - Made the column `settingsId` on table `users` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "pipeline_progresses" ADD COLUMN "pointOfContactId" TEXT, -ADD COLUMN "probability" INTEGER; - --- AlterTable -ALTER TABLE "users" ALTER COLUMN "settingsId" SET NOT NULL; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_pointOfContactId_fkey" FOREIGN KEY ("pointOfContactId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230720075726_alter_table_person_make_fields_optional/migration.sql b/server/src/database/migrations/20230720075726_alter_table_person_make_fields_optional/migration.sql deleted file mode 100644 index 3f2b71c27..000000000 --- a/server/src/database/migrations/20230720075726_alter_table_person_make_fields_optional/migration.sql +++ /dev/null @@ -1,6 +0,0 @@ --- AlterTable -ALTER TABLE "people" ALTER COLUMN "email" DROP NOT NULL, -ALTER COLUMN "phone" DROP NOT NULL, -ALTER COLUMN "city" DROP NOT NULL, -ALTER COLUMN "firstName" DROP NOT NULL, -ALTER COLUMN "lastName" DROP NOT NULL; diff --git a/server/src/database/migrations/20230721141406_alter_table_comment_thread_target_add_workspace_id/migration.sql b/server/src/database/migrations/20230721141406_alter_table_comment_thread_target_add_workspace_id/migration.sql deleted file mode 100644 index 25e2e1abe..000000000 --- a/server/src/database/migrations/20230721141406_alter_table_comment_thread_target_add_workspace_id/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - Added the required column `workspaceId` to the `comment_thread_targets` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "comment_thread_targets" ADD COLUMN "workspaceId" TEXT; - --- AddForeignKey -ALTER TABLE "comment_thread_targets" ADD CONSTRAINT "comment_thread_targets_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230721210543_add_linkedin_url_and_job_title_fields/migration.sql b/server/src/database/migrations/20230721210543_add_linkedin_url_and_job_title_fields/migration.sql deleted file mode 100644 index ec91a0a4a..000000000 --- a/server/src/database/migrations/20230721210543_add_linkedin_url_and_job_title_fields/migration.sql +++ /dev/null @@ -1,6 +0,0 @@ --- AlterTable -ALTER TABLE "companies" ADD COLUMN "linkedinUrl" TEXT; - --- AlterTable -ALTER TABLE "people" ADD COLUMN "jobTitle" TEXT, -ADD COLUMN "linkedinUrl" TEXT; diff --git a/server/src/database/migrations/20230724115133_rename_table_comment_thread_into_activity/migration.sql b/server/src/database/migrations/20230724115133_rename_table_comment_thread_into_activity/migration.sql deleted file mode 100644 index ef4086fa1..000000000 --- a/server/src/database/migrations/20230724115133_rename_table_comment_thread_into_activity/migration.sql +++ /dev/null @@ -1,32 +0,0 @@ --- Activities Table -CREATE TABLE "activities" ( - "id" TEXT NOT NULL, - "body" TEXT, - "title" TEXT, - "type" "ActivityType" NOT NULL DEFAULT 'Note', - "reminderAt" TIMESTAMP(3), - "dueAt" TIMESTAMP(3), - "completedAt" TIMESTAMP(3), - "authorId" TEXT NOT NULL, - "assigneeId" TEXT, - "workspaceId" TEXT NOT NULL, - "deletedAt" TIMESTAMP(3), - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "activities_pkey" PRIMARY KEY ("id") -); - --- Activity Targets Table -CREATE TABLE "activity_targets" ( - "id" TEXT NOT NULL, - "activityId" TEXT NOT NULL, - "personId" TEXT NOT NULL, - "companyId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - "deletedAt" TIMESTAMP(3), - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "activity_targets_pkey" PRIMARY KEY ("id") -); diff --git a/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql b/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql deleted file mode 100644 index 178c90ce8..000000000 --- a/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ --- CreateTable -CREATE TABLE "viewFields" ( - "id" TEXT NOT NULL, - "fieldName" TEXT NOT NULL, - "index" INTEGER NOT NULL, - "isVisible" BOOLEAN NOT NULL, - "objectName" TEXT NOT NULL, - "sizeInPx" INTEGER NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "viewFields_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "viewFields" ADD CONSTRAINT "viewFields_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230728061715_complete_comment_thread_migration/migration.sql b/server/src/database/migrations/20230728061715_complete_comment_thread_migration/migration.sql deleted file mode 100644 index f5a52f80e..000000000 --- a/server/src/database/migrations/20230728061715_complete_comment_thread_migration/migration.sql +++ /dev/null @@ -1,69 +0,0 @@ -/* - Warnings: - - - You are about to drop the `comment_thread_targets` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `comment_threads` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "attachments" DROP CONSTRAINT "attachments_activityId_fkey"; - --- DropForeignKey -ALTER TABLE "comment_thread_targets" DROP CONSTRAINT "comment_thread_targets_commentThreadId_fkey"; - --- DropForeignKey -ALTER TABLE "comment_thread_targets" DROP CONSTRAINT "comment_thread_targets_workspaceId_fkey"; - --- DropForeignKey -ALTER TABLE "comment_threads" DROP CONSTRAINT "comment_threads_assigneeId_fkey"; - --- DropForeignKey -ALTER TABLE "comment_threads" DROP CONSTRAINT "comment_threads_authorId_fkey"; - --- DropForeignKey -ALTER TABLE "comment_threads" DROP CONSTRAINT "comment_threads_workspaceId_fkey"; - --- DropForeignKey -ALTER TABLE "comments" DROP CONSTRAINT "comments_commentThreadId_fkey"; - --- AlterTable -ALTER TABLE "activity_targets" ADD COLUMN "commentableId" TEXT, -ADD COLUMN "commentableType" "CommentableType", -ALTER COLUMN "personId" DROP NOT NULL, -ALTER COLUMN "companyId" DROP NOT NULL; - --- AlterTable -ALTER TABLE "comments" ADD COLUMN "activityId" TEXT; - --- DropTable -DROP TABLE "comment_thread_targets"; - --- DropTable -DROP TABLE "comment_threads"; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_assigneeId_fkey" FOREIGN KEY ("assigneeId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "activities"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "activities"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "activities"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230728063528_make_comment_thread_id_optional/migration.sql b/server/src/database/migrations/20230728063528_make_comment_thread_id_optional/migration.sql deleted file mode 100644 index 8b75896dd..000000000 --- a/server/src/database/migrations/20230728063528_make_comment_thread_id_optional/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "comments" ALTER COLUMN "commentThreadId" DROP NOT NULL; diff --git a/server/src/database/migrations/20230728193900_add_avatar_url_to_people_table/migration.sql b/server/src/database/migrations/20230728193900_add_avatar_url_to_people_table/migration.sql deleted file mode 100644 index 6ee2aa23b..000000000 --- a/server/src/database/migrations/20230728193900_add_avatar_url_to_people_table/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "people" ADD COLUMN "avatarUrl" TEXT; diff --git a/server/src/database/migrations/20230731072336_add_impersonate_ability/migration.sql b/server/src/database/migrations/20230731072336_add_impersonate_ability/migration.sql deleted file mode 100644 index 2a93c6ce6..000000000 --- a/server/src/database/migrations/20230731072336_add_impersonate_ability/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "users" ADD COLUMN "canImpersonate" BOOLEAN NOT NULL DEFAULT false; - --- AlterTable -ALTER TABLE "workspace_members" ADD COLUMN "allowImpersonation" BOOLEAN NOT NULL DEFAULT true; diff --git a/server/src/database/migrations/20230803115502_add_entities_on_pipeline_progress/migration.sql b/server/src/database/migrations/20230803115502_add_entities_on_pipeline_progress/migration.sql deleted file mode 100644 index ccc3c5c87..000000000 --- a/server/src/database/migrations/20230803115502_add_entities_on_pipeline_progress/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ --- AlterTable -ALTER TABLE "pipeline_progresses" ADD COLUMN "companyId" TEXT, -ADD COLUMN "personId" TEXT; - --- AddForeignKey ---ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey ---ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230803121208_data_migration_move_progressable_ids_to_typed_fields/migration.sql b/server/src/database/migrations/20230803121208_data_migration_move_progressable_ids_to_typed_fields/migration.sql deleted file mode 100644 index 2cbb82a32..000000000 --- a/server/src/database/migrations/20230803121208_data_migration_move_progressable_ids_to_typed_fields/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- This is a manually written data migration that copies the progressable ids to the right colums in pipeline progress. -UPDATE "pipeline_progresses" SET - "companyId"="progressableId" -WHERE "progressableType"='Company'; - -UPDATE "pipeline_progresses" SET - "personId"="progressableId" -WHERE "progressableType"='Person'; \ No newline at end of file diff --git a/server/src/database/migrations/20230803141808_remove_progressable_id_from_pipeline_progress/migration.sql b/server/src/database/migrations/20230803141808_remove_progressable_id_from_pipeline_progress/migration.sql deleted file mode 100644 index a8596427d..000000000 --- a/server/src/database/migrations/20230803141808_remove_progressable_id_from_pipeline_progress/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `progressableId` on the `pipeline_progresses` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "pipeline_progresses" DROP COLUMN "progressableId"; diff --git a/server/src/database/migrations/20230803143326_remove_progressable_type_on_pipeline_progress/migration.sql b/server/src/database/migrations/20230803143326_remove_progressable_type_on_pipeline_progress/migration.sql deleted file mode 100644 index df8c52e6c..000000000 --- a/server/src/database/migrations/20230803143326_remove_progressable_type_on_pipeline_progress/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `progressableType` on the `pipeline_progresses` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "pipeline_progresses" DROP COLUMN "progressableType"; diff --git a/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql b/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql deleted file mode 100644 index a57411345..000000000 --- a/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "people" ADD COLUMN "twitterUrl" TEXT; diff --git a/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql b/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql deleted file mode 100644 index 4f3993584..000000000 --- a/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "people" RENAME COLUMN "twitterUrl" TO "xUrl"; diff --git a/server/src/database/migrations/20230809143432_add_views_table/migration.sql b/server/src/database/migrations/20230809143432_add_views_table/migration.sql deleted file mode 100644 index 08c77e595..000000000 --- a/server/src/database/migrations/20230809143432_add_views_table/migration.sql +++ /dev/null @@ -1,34 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[workspaceId,viewId,objectName,fieldName]` on the table `viewFields` will be added. If there are existing duplicate values, this will fail. - -*/ --- CreateEnum -CREATE TYPE "ViewType" AS ENUM ('Table', 'Pipeline'); - --- AlterTable -ALTER TABLE "viewFields" ADD COLUMN "viewId" TEXT; - --- CreateTable -CREATE TABLE "views" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "objectId" TEXT NOT NULL, - "type" "ViewType" NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "views_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "views_workspaceId_type_objectId_name_key" ON "views"("workspaceId", "type", "objectId", "name"); - --- CreateIndex -CREATE UNIQUE INDEX "viewFields_workspaceId_viewId_objectName_fieldName_key" ON "viewFields"("workspaceId", "viewId", "objectName", "fieldName"); - --- AddForeignKey -ALTER TABLE "views" ADD CONSTRAINT "views_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "viewFields" ADD CONSTRAINT "viewFields_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230809143836_add_view_sorts_table/migration.sql b/server/src/database/migrations/20230809143836_add_view_sorts_table/migration.sql deleted file mode 100644 index 870add1fa..000000000 --- a/server/src/database/migrations/20230809143836_add_view_sorts_table/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- CreateEnum -CREATE TYPE "ViewSortDirection" AS ENUM ('asc', 'desc'); - --- CreateTable -CREATE TABLE "viewSorts" ( - "direction" "ViewSortDirection" NOT NULL, - "key" TEXT NOT NULL, - "name" TEXT NOT NULL, - "viewId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "viewSorts_pkey" PRIMARY KEY ("viewId","key") -); - --- AddForeignKey -ALTER TABLE "viewSorts" ADD CONSTRAINT "viewSorts_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "viewSorts" ADD CONSTRAINT "viewSorts_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230810222531_add_favorites/migration.sql b/server/src/database/migrations/20230810222531_add_favorites/migration.sql deleted file mode 100644 index 874c23506..000000000 --- a/server/src/database/migrations/20230810222531_add_favorites/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- CreateTable -CREATE TABLE "favorites" ( - "id" TEXT NOT NULL, - "workspaceId" TEXT, - "personId" TEXT, - "companyId" TEXT, - "workspaceMemberId" TEXT, - - CONSTRAINT "favorites_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "favorites" ADD CONSTRAINT "favorites_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "favorites" ADD CONSTRAINT "favorites_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "favorites" ADD CONSTRAINT "favorites_workspaceMemberId_fkey" FOREIGN KEY ("workspaceMemberId") REFERENCES "workspace_members"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230811193858_add_missing_constraints/migration.sql b/server/src/database/migrations/20230811193858_add_missing_constraints/migration.sql deleted file mode 100644 index 63060a14b..000000000 --- a/server/src/database/migrations/20230811193858_add_missing_constraints/migration.sql +++ /dev/null @@ -1,17 +0,0 @@ --- DropForeignKey -ALTER TABLE "activity_targets" DROP CONSTRAINT "activity_targets_companyId_fkey"; - --- DropForeignKey -ALTER TABLE "activity_targets" DROP CONSTRAINT "activity_targets_personId_fkey"; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activity_targets" ADD CONSTRAINT "activity_targets_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230811232332_remove_activity_commentable_type_and_commentable_id/migration.sql b/server/src/database/migrations/20230811232332_remove_activity_commentable_type_and_commentable_id/migration.sql deleted file mode 100644 index df5dc619b..000000000 --- a/server/src/database/migrations/20230811232332_remove_activity_commentable_type_and_commentable_id/migration.sql +++ /dev/null @@ -1,13 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `commentableId` on the `activity_targets` table. All the data in the column will be lost. - - You are about to drop the column `commentableType` on the `activity_targets` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "activity_targets" DROP COLUMN "commentableId", -DROP COLUMN "commentableType"; - --- DropEnum -DROP TYPE "CommentableType"; diff --git a/server/src/database/migrations/20230815183117_apply_cascade_deletion/migration.sql b/server/src/database/migrations/20230815183117_apply_cascade_deletion/migration.sql deleted file mode 100644 index adbaa3f6a..000000000 --- a/server/src/database/migrations/20230815183117_apply_cascade_deletion/migration.sql +++ /dev/null @@ -1,53 +0,0 @@ --- DropForeignKey -ALTER TABLE "activities" DROP CONSTRAINT "activities_authorId_fkey"; - --- DropForeignKey -ALTER TABLE "attachments" DROP CONSTRAINT "attachments_activityId_fkey"; - --- DropForeignKey -ALTER TABLE "attachments" DROP CONSTRAINT "attachments_authorId_fkey"; - --- DropForeignKey -ALTER TABLE "favorites" DROP CONSTRAINT "favorites_companyId_fkey"; - --- DropForeignKey -ALTER TABLE "favorites" DROP CONSTRAINT "favorites_personId_fkey"; - --- DropForeignKey -ALTER TABLE "pipeline_progresses" DROP CONSTRAINT "pipeline_progresses_pipelineId_fkey"; - --- DropForeignKey -ALTER TABLE "pipeline_progresses" DROP CONSTRAINT "pipeline_progresses_pipelineStageId_fkey"; - --- DropForeignKey -ALTER TABLE "pipeline_stages" DROP CONSTRAINT "pipeline_stages_pipelineId_fkey"; - --- DropForeignKey -ALTER TABLE "comments" DROP CONSTRAINT "comments_authorId_fkey"; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_stages" ADD CONSTRAINT "pipeline_stages_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "pipelines"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "pipelines"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_pipelineStageId_fkey" FOREIGN KEY ("pipelineStageId") REFERENCES "pipeline_stages"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "activities"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "favorites" ADD CONSTRAINT "favorites_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "favorites" ADD CONSTRAINT "favorites_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230816085431_apply_views_cascade_deletion/migration.sql b/server/src/database/migrations/20230816085431_apply_views_cascade_deletion/migration.sql deleted file mode 100644 index 271070b01..000000000 --- a/server/src/database/migrations/20230816085431_apply_views_cascade_deletion/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ --- DropForeignKey -ALTER TABLE "viewFields" DROP CONSTRAINT "viewFields_viewId_fkey"; - --- DropForeignKey -ALTER TABLE "viewSorts" DROP CONSTRAINT "viewSorts_viewId_fkey"; - --- AddForeignKey -ALTER TABLE "viewSorts" ADD CONSTRAINT "viewSorts_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "viewFields" ADD CONSTRAINT "viewFields_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230817201132_add_new_company_fields/migration.sql b/server/src/database/migrations/20230817201132_add_new_company_fields/migration.sql deleted file mode 100644 index 5352bde5d..000000000 --- a/server/src/database/migrations/20230817201132_add_new_company_fields/migration.sql +++ /dev/null @@ -1,4 +0,0 @@ --- AlterTable -ALTER TABLE "companies" ADD COLUMN "annualRecurringRevenue" INTEGER, -ADD COLUMN "idealCustomerProfile" BOOLEAN DEFAULT false, -ADD COLUMN "xUrl" TEXT; diff --git a/server/src/database/migrations/20230821142706_add_view_filters_table/migration.sql b/server/src/database/migrations/20230821142706_add_view_filters_table/migration.sql deleted file mode 100644 index 161b7bda1..000000000 --- a/server/src/database/migrations/20230821142706_add_view_filters_table/migration.sql +++ /dev/null @@ -1,21 +0,0 @@ --- CreateEnum -CREATE TYPE "ViewFilterOperand" AS ENUM ('Contains', 'DoesNotContain', 'GreaterThan', 'LessThan', 'Is', 'IsNot'); - --- CreateTable -CREATE TABLE "viewFilters" ( - "displayValue" TEXT NOT NULL, - "key" TEXT NOT NULL, - "name" TEXT NOT NULL, - "operand" "ViewFilterOperand" NOT NULL, - "value" TEXT NOT NULL, - "viewId" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - - CONSTRAINT "viewFilters_pkey" PRIMARY KEY ("viewId","key") -); - --- AddForeignKey -ALTER TABLE "viewFilters" ADD CONSTRAINT "viewFilters_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "viewFilters" ADD CONSTRAINT "viewFilters_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230829120042_allow_views_with_same_name/migration.sql b/server/src/database/migrations/20230829120042_allow_views_with_same_name/migration.sql deleted file mode 100644 index 1f4e16edb..000000000 --- a/server/src/database/migrations/20230829120042_allow_views_with_same_name/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- DropIndex -DROP INDEX "views_workspaceId_type_objectId_name_key"; diff --git a/server/src/database/migrations/20230901150707_index_view_field_by_view_id_and_key/migration.sql b/server/src/database/migrations/20230901150707_index_view_field_by_view_id_and_key/migration.sql deleted file mode 100644 index a836f5f79..000000000 --- a/server/src/database/migrations/20230901150707_index_view_field_by_view_id_and_key/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ -/* - Warnings: - - - The primary key for the `viewFields` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `id` on the `viewFields` table. All the data in the column will be lost. - - Added the required column `key` to the `viewFields` table without a default value. This is not possible if the table is not empty. - - Made the column `viewId` on table `viewFields` required. This step will fail if there are existing NULL values in that column. - -*/ --- DropIndex -DROP INDEX "viewFields_workspaceId_viewId_objectName_fieldName_key"; - --- AlterTable -ALTER TABLE "viewFields" DROP CONSTRAINT "viewFields_pkey", -DROP COLUMN "id", -ADD COLUMN "key" TEXT NOT NULL, -ALTER COLUMN "viewId" SET NOT NULL, -ADD CONSTRAINT "viewFields_pkey" PRIMARY KEY ("viewId", "key"); diff --git a/server/src/database/migrations/20230901163822_rename_view_field_properties/migration.sql b/server/src/database/migrations/20230901163822_rename_view_field_properties/migration.sql deleted file mode 100644 index b7a78bbb8..000000000 --- a/server/src/database/migrations/20230901163822_rename_view_field_properties/migration.sql +++ /dev/null @@ -1,4 +0,0 @@ --- AlterTable -ALTER TABLE "viewFields" RENAME COLUMN "fieldName" TO "name"; -ALTER TABLE "viewFields" RENAME COLUMN "objectName" TO "objectId"; -ALTER TABLE "viewFields" RENAME COLUMN "sizeInPx" TO "size"; diff --git a/server/src/database/migrations/20230905121813_add_fields_to_workspace_member/migration.sql b/server/src/database/migrations/20230905121813_add_fields_to_workspace_member/migration.sql deleted file mode 100644 index b50fd78ec..000000000 --- a/server/src/database/migrations/20230905121813_add_fields_to_workspace_member/migration.sql +++ /dev/null @@ -1,40 +0,0 @@ -/* - Warnings: - - - Made the column `idealCustomerProfile` on table `companies` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "activities" ADD COLUMN "workspaceMemberAssigneeId" TEXT, -ADD COLUMN "workspaceMemberAuthorId" TEXT; - --- AlterTable -ALTER TABLE "attachments" ADD COLUMN "workspaceMemberAuthorId" TEXT; - --- AlterTable -ALTER TABLE "comments" ADD COLUMN "workspaceMemberAuthorId" TEXT; - --- AlterTable -ALTER TABLE "companies" ADD COLUMN "workspaceMemberAccountOwnerId" TEXT, -ALTER COLUMN "idealCustomerProfile" SET NOT NULL; - --- AlterTable -ALTER TABLE "workspace_members" ADD COLUMN "settingsId" TEXT; - --- AddForeignKey -ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_settingsId_fkey" FOREIGN KEY ("settingsId") REFERENCES "user_settings"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "companies" ADD CONSTRAINT "companies_workspaceMemberAccountOwnerId_fkey" FOREIGN KEY ("workspaceMemberAccountOwnerId") REFERENCES "workspace_members"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_workspaceMemberAuthorId_fkey" FOREIGN KEY ("workspaceMemberAuthorId") REFERENCES "workspace_members"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "activities" ADD CONSTRAINT "activities_workspaceMemberAssigneeId_fkey" FOREIGN KEY ("workspaceMemberAssigneeId") REFERENCES "workspace_members"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "comments" ADD CONSTRAINT "comments_workspaceMemberAuthorId_fkey" FOREIGN KEY ("workspaceMemberAuthorId") REFERENCES "workspace_members"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_workspaceMemberAuthorId_fkey" FOREIGN KEY ("workspaceMemberAuthorId") REFERENCES "workspace_members"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230905150352_make_view_field_size_optional/migration.sql b/server/src/database/migrations/20230905150352_make_view_field_size_optional/migration.sql deleted file mode 100644 index 60036a5cc..000000000 --- a/server/src/database/migrations/20230905150352_make_view_field_size_optional/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "viewFields" ALTER COLUMN "size" DROP NOT NULL; diff --git a/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql b/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql deleted file mode 100644 index 1d60790db..000000000 --- a/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "viewFields" ALTER COLUMN "index" SET DATA TYPE DOUBLE PRECISION; diff --git a/server/src/database/migrations/20230925151034_add_currency_column/migration.sql b/server/src/database/migrations/20230925151034_add_currency_column/migration.sql deleted file mode 100644 index da47f8520..000000000 --- a/server/src/database/migrations/20230925151034_add_currency_column/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- CreateEnum -CREATE TYPE "Currency" AS ENUM ('AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP', 'CNY', 'COP', 'COU', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDD', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STD', 'STN', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMM', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XOF', 'XPF', 'XSU', 'XUA', 'YER', 'ZAR', 'ZMW', 'ZWL'); - --- AlterTable -ALTER TABLE "pipelines" ADD COLUMN "currency" "Currency" NOT NULL DEFAULT 'USD'; diff --git a/server/src/database/migrations/20230925153619_add_company_and_person_to_attachment/migration.sql b/server/src/database/migrations/20230925153619_add_company_and_person_to_attachment/migration.sql deleted file mode 100644 index 12f941b0d..000000000 --- a/server/src/database/migrations/20230925153619_add_company_and_person_to_attachment/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- AlterTable -ALTER TABLE "attachments" ADD COLUMN "companyId" TEXT, -ADD COLUMN "personId" TEXT, -ALTER COLUMN "activityId" DROP NOT NULL; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "attachments" ADD CONSTRAINT "attachments_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20230926150534_alter_table_refresh_token_add_revoked_at/migration.sql b/server/src/database/migrations/20230926150534_alter_table_refresh_token_add_revoked_at/migration.sql deleted file mode 100644 index d2ea6379e..000000000 --- a/server/src/database/migrations/20230926150534_alter_table_refresh_token_add_revoked_at/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Step 1: Add the new column -ALTER TABLE "refresh_tokens" ADD COLUMN "revokedAt" TIMESTAMP(3); - --- Step 2: Update the new column based on the isRevoked column value -UPDATE "refresh_tokens" SET "revokedAt" = NOW() - INTERVAL '1 day' WHERE "isRevoked" = TRUE; - --- Step 3: Drop the isRevoked column -ALTER TABLE "refresh_tokens" DROP COLUMN "isRevoked"; diff --git a/server/src/database/migrations/20231010133527_complete_comment_thread_migration/migration.sql b/server/src/database/migrations/20231010133527_complete_comment_thread_migration/migration.sql deleted file mode 100644 index f30c55293..000000000 --- a/server/src/database/migrations/20231010133527_complete_comment_thread_migration/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ --- AlterEnum -ALTER TYPE "ViewFilterOperand" ADD VALUE 'IsNotNull'; - --- CreateTable -CREATE TABLE "api_keys" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "key" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - "expiresAt" TIMESTAMP(3), - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - - CONSTRAINT "api_keys_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "api_keys_key_key" ON "api_keys"("key"); - --- AddForeignKey -ALTER TABLE "api_keys" ADD CONSTRAINT "api_keys_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20231012121531_complete_comment_thread_migration/migration.sql b/server/src/database/migrations/20231012121531_complete_comment_thread_migration/migration.sql deleted file mode 100644 index eda2606fa..000000000 --- a/server/src/database/migrations/20231012121531_complete_comment_thread_migration/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `key` on the `api_keys` table. All the data in the column will be lost. - -*/ --- DropIndex -DROP INDEX "api_keys_key_key"; - --- AlterTable -ALTER TABLE "api_keys" DROP COLUMN "key", -ADD COLUMN "revokedAt" TIMESTAMP(3); diff --git a/server/src/database/migrations/20231019144904_complete_comment_thread_migration/migration.sql b/server/src/database/migrations/20231019144904_complete_comment_thread_migration/migration.sql deleted file mode 100644 index 183a15ae3..000000000 --- a/server/src/database/migrations/20231019144904_complete_comment_thread_migration/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ --- CreateTable -CREATE TABLE "hooks" ( - "id" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - "targetUrl" TEXT NOT NULL, - "operation" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - - CONSTRAINT "hooks_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "hooks" ADD CONSTRAINT "hooks_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20231019210329_add_position_to_favorite/migration.sql b/server/src/database/migrations/20231019210329_add_position_to_favorite/migration.sql deleted file mode 100644 index ecd0b314b..000000000 --- a/server/src/database/migrations/20231019210329_add_position_to_favorite/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `position` to the `favorites` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "favorites" ADD COLUMN "position" DOUBLE PRECISION NOT NULL; diff --git a/server/src/database/migrations/20231024123425_rename_hooks_table_to_web_hooks/migration.sql b/server/src/database/migrations/20231024123425_rename_hooks_table_to_web_hooks/migration.sql deleted file mode 100644 index 43ef82be9..000000000 --- a/server/src/database/migrations/20231024123425_rename_hooks_table_to_web_hooks/migration.sql +++ /dev/null @@ -1,27 +0,0 @@ -/* - Warnings: - - - You are about to drop the `hooks` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "hooks" DROP CONSTRAINT "hooks_workspaceId_fkey"; - --- DropTable -DROP TABLE "hooks"; - --- CreateTable -CREATE TABLE "web_hooks" ( - "id" TEXT NOT NULL, - "workspaceId" TEXT NOT NULL, - "targetUrl" TEXT NOT NULL, - "operation" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - - CONSTRAINT "web_hooks_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "web_hooks" ADD CONSTRAINT "web_hooks_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/migrations/20231028153754_refactor_views_positions/migration.sql b/server/src/database/migrations/20231028153754_refactor_views_positions/migration.sql deleted file mode 100644 index cd0219d7c..000000000 --- a/server/src/database/migrations/20231028153754_refactor_views_positions/migration.sql +++ /dev/null @@ -1,52 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `index` on the `pipeline_stages` table. All the data in the column will be lost. - - You are about to drop the `viewFields` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `viewFilters` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `viewSorts` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `views` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "viewFields" DROP CONSTRAINT "viewFields_viewId_fkey"; - --- DropForeignKey -ALTER TABLE "viewFields" DROP CONSTRAINT "viewFields_workspaceId_fkey"; - --- DropForeignKey -ALTER TABLE "viewFilters" DROP CONSTRAINT "viewFilters_viewId_fkey"; - --- DropForeignKey -ALTER TABLE "viewFilters" DROP CONSTRAINT "viewFilters_workspaceId_fkey"; - --- DropForeignKey -ALTER TABLE "viewSorts" DROP CONSTRAINT "viewSorts_viewId_fkey"; - --- DropForeignKey -ALTER TABLE "viewSorts" DROP CONSTRAINT "viewSorts_workspaceId_fkey"; - --- DropForeignKey -ALTER TABLE "views" DROP CONSTRAINT "views_workspaceId_fkey"; - --- AlterTable -ALTER TABLE "pipeline_stages" DROP COLUMN "index", -ADD COLUMN "position" INTEGER; - --- DropTable -DROP TABLE "viewFields"; - --- DropTable -DROP TABLE "viewFilters"; - --- DropTable -DROP TABLE "viewSorts"; - --- DropTable -DROP TABLE "views"; - --- DropEnum -DROP TYPE "ViewFilterOperand"; - --- DropEnum -DROP TYPE "ViewSortDirection"; diff --git a/server/src/database/migrations/20231115084929_remove_user_workspace_member_relation/migration.sql b/server/src/database/migrations/20231115084929_remove_user_workspace_member_relation/migration.sql deleted file mode 100644 index 9ff25723b..000000000 --- a/server/src/database/migrations/20231115084929_remove_user_workspace_member_relation/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- DropForeignKey -ALTER TABLE "workspace_members" DROP CONSTRAINT "workspace_members_userId_fkey"; - --- AlterTable -ALTER TABLE "users" ADD COLUMN "defaultWorkspaceId" TEXT; diff --git a/server/src/database/migrations/20231115123209_remove_user_settings/migration.sql b/server/src/database/migrations/20231115123209_remove_user_settings/migration.sql deleted file mode 100644 index 0674f52fe..000000000 --- a/server/src/database/migrations/20231115123209_remove_user_settings/migration.sql +++ /dev/null @@ -1,20 +0,0 @@ -/* - 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; diff --git a/server/src/database/migrations/20231115130536_remove_user_settings/migration.sql b/server/src/database/migrations/20231115130536_remove_user_settings/migration.sql deleted file mode 100644 index c2804c5eb..000000000 --- a/server/src/database/migrations/20231115130536_remove_user_settings/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - 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"; diff --git a/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql b/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql deleted file mode 100644 index 16d5238ab..000000000 --- a/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ -/* - Warnings: - - - The `currency` column on the `pipelines` table would be dropped and recreated. This will lead to data loss if there is data in the column. - -*/ --- CreateEnum -CREATE TYPE "CurrencyCode" AS ENUM ('AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP', 'CNY', 'COP', 'COU', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDD', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STD', 'STN', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMM', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XOF', 'XPF', 'XSU', 'XUA', 'YER', 'ZAR', 'ZMW', 'ZWL'); - --- AlterTable -ALTER TABLE "pipelines" DROP COLUMN "currency", -ADD COLUMN "currency" "CurrencyCode" NOT NULL DEFAULT 'USD'; - --- DropEnum -DROP TYPE "Currency"; diff --git a/server/src/database/migrations/migration_lock.toml b/server/src/database/migrations/migration_lock.toml deleted file mode 100644 index fbffa92c2..000000000 --- a/server/src/database/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file diff --git a/server/src/database/prisma.module.ts b/server/src/database/prisma.module.ts deleted file mode 100644 index 54327ba02..000000000 --- a/server/src/database/prisma.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { PrismaService } from './prisma.service'; - -@Module({ - providers: [PrismaService], - exports: [PrismaService], -}) -export class PrismaModule {} diff --git a/server/src/database/prisma.service.ts b/server/src/database/prisma.service.ts deleted file mode 100644 index 15b806b33..000000000 --- a/server/src/database/prisma.service.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - INestApplication, - Injectable, - Logger, - OnModuleDestroy, - OnModuleInit, -} from '@nestjs/common'; - -import { Prisma, PrismaClient } from '@prisma/client'; -import { createPrismaQueryEventHandler } from 'prisma-query-log'; - -import { EnvironmentService } from 'src/integrations/environment/environment.service'; - -// Prepare Prisma extenstion ability -const createPrismaClient = (options: Prisma.PrismaClientOptions) => { - const client = new PrismaClient(options); - - return client; -}; - -type ExtendedPrismaClient = ReturnType; - -@Injectable() -export class PrismaService implements OnModuleInit, OnModuleDestroy { - private readonly logger = new Logger(PrismaService.name); - private prismaClient!: ExtendedPrismaClient; - - public get client(): ExtendedPrismaClient { - return this.prismaClient; - } - - constructor(private readonly environmentService: EnvironmentService) { - const debugMode = environmentService.isDebugMode(); - - this.prismaClient = createPrismaClient({ - errorFormat: 'minimal', - log: debugMode - ? [ - { - level: 'query', - emit: 'event', - }, - ] - : undefined, - }); - - if (debugMode) { - const logHandler = createPrismaQueryEventHandler({ - logger: (query: string) => { - this.logger.log(query, 'PrismaClient'); - }, - format: false, - colorQuery: '\u001B[96m', - colorParameter: '\u001B[90m', - }); - - this.prismaClient.$on('query' as any, logHandler); - } - } - - async onModuleInit(): Promise { - await this.prismaClient.$connect(); - } - - async onModuleDestroy(): Promise { - await this.prismaClient.$disconnect(); - } - - async enableShutdownHooks(app: INestApplication) { - this.prismaClient.$on('beforeExit', async () => { - await app.close(); - }); - } -} diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma deleted file mode 100644 index 6da983ad6..000000000 --- a/server/src/database/schema.prisma +++ /dev/null @@ -1,831 +0,0 @@ -generator client { - provider = "prisma-client-js" - engineType = "binary" -} - -datasource db { - provider = "postgresql" - url = env("PG_DATABASE_URL") -} - -generator nestgraphql { - provider = "node node_modules/prisma-nestjs-graphql" - output = "../../src/core/@generated" - noAtomicOperations = true - - // field validator - fields_Validator_input = true - fields_Validator_output = true - fields_Validator_model = true - fields_Validator_from = "class-validator" - - // All relations, only allow connect - decorate_all_type = "!(ActivityTarget*Input|UserSettingsUpdateOneRequiredWithoutUserNestedInput)" - decorate_all_field = "*(create|connectOrCreate|update|upsert|delete|createMany|updateMany|deleteMany)" - decorate_all_name = "HideField" - decorate_all_from = "@nestjs/graphql" - decorate_all_arguments = "[]" - - // Activity: Only Allow targets createOrConnect / createMany - decorate_activityTargets_type = "*ActivityTarget*Input" - decorate_activityTargets_field = "*(update|upsert|updateMany)" - decorate_activityTargets_name = "HideField" - decorate_activityTargets_from = "@nestjs/graphql" - decorate_activityTargets_arguments = "[]" - - // User Settings: Only Allow targets createOrConnect / createMany - decorate_userSettings_type = "*UserSettingsUpdateOneRequiredWithoutUserNestedInput" - decorate_userSettings_field = "!(update)" - decorate_userSettings_name = "HideField" - decorate_userSettings_from = "@nestjs/graphql" - decorate_userSettings_arguments = "[]" - - // Disable _count on all models except Aggregation use case - decorate_count_type = "!(*Aggregate*|*GroupBy*|*OrderBy*)" - decorate_count_field = "_count" - decorate_count_name = "HideField" - decorate_count_from = "@nestjs/graphql" - decorate_count_arguments = "[]" - - // create data validator - decorate_classValidator_type = "@(Create|Update|Upsert)*Args" - decorate_classValidator_field = "@(data|[A-Z]*)" - decorate_classValidator_name = ValidateNested - decorate_classValidator_from = "class-validator" - decorate_classValidator_arguments = "['{each: true}']" - - // create data transformer - decorate_classTransformer_type = "@(Create|Update|Upsert)*Args" - decorate_classTransformer_field = "@(data|[A-Z]*)" - decorate_classTransformer_from = "class-transformer" - decorate_classTransformer_arguments = "['() => {propertyType.0}']" - decorate_classTransformer_name = Type -} - -model User { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - firstName String? - /// @Validator.IsString() - /// @Validator.IsOptional() - lastName String? - /// @Validator.IsEmail() - /// @Validator.IsOptional() - email String @unique - /// @Validator.IsBoolean() - /// @Validator.IsOptional() - emailVerified Boolean @default(false) - /// @Validator.IsString() - /// @Validator.IsOptional() - avatarUrl String? - /// @Validator.IsString() - /// @Validator.IsOptional() - locale String - /// @Validator.IsString() - /// @Validator.IsOptional() - phoneNumber String? - /// @Validator.IsDate() - /// @Validator.IsOptional() - lastSeen DateTime? - /// @Validator.IsBoolean() - /// @Validator.IsOptional() - disabled Boolean @default(false) - /// @TypeGraphQL.omit(input: true, output: true) - passwordHash String? - /// @Validator.IsJSON() - /// @Validator.IsOptional() - metadata Json? - /// @Validator.IsBoolean() - /// @Validator.IsOptional() - canImpersonate Boolean @default(false) - - companies Company[] - /// @TypeGraphQL.omit(input: true, output: true) - refreshTokens RefreshToken[] - comments Comment[] - defaultWorkspaceId String? - - authoredActivities Activity[] @relation(name: "authoredActivities") - assignedActivities Activity[] @relation(name: "assignedActivities") - authoredAttachments Attachment[] @relation(name: "authoredAttachments") - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("users") -} - -enum ColorScheme { - Light - Dark - System -} - -model UserSettings { - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - colorScheme ColorScheme @default(System) - /// @Validator.IsString() - locale String - - WorkspaceMember WorkspaceMember[] - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("user_settings") -} - -/// @TypeGraphQL.omit(input: true) -model Workspace { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - domainName String? - /// @Validator.IsString() - /// @Validator.IsOptional() - displayName String? - /// @Validator.IsString() - /// @Validator.IsOptional() - logo String? - /// @Validator.IsString() - /// @Validator.IsOptional() - inviteHash String? - - workspaceMember WorkspaceMember[] - companies Company[] - people Person[] - activities Activity[] - comments Comment[] - pipelines Pipeline[] - pipelineStages PipelineStage[] - pipelineProgresses PipelineProgress[] - activityTargets ActivityTarget[] - apiKeys ApiKey[] - webHooks WebHook[] - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - Attachment Attachment[] - - @@map("workspaces") -} - -model WorkspaceMember { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsBoolean() - /// @Validator.IsOptional() - allowImpersonation Boolean @default(true) - - userId String @unique - /// @TypeGraphQL.omit(input: true, output: false) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - Favorite Favorite[] - - authoredActivities Activity[] @relation(name: "authoredActivities") - assignedActivities Activity[] @relation(name: "assignedActivities") - authoredAttachments Attachment[] @relation(name: "authoredAttachments") - settings UserSettings? @relation(fields: [settingsId], references: [id]) - settingsId String? - - companies Company[] - comments Comment[] - - @@map("workspace_members") -} - -model Company { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - name String - /// @Validator.IsString() - /// @Validator.IsOptional() - domainName String - /// @Validator.IsString() - /// @Validator.IsOptional() - linkedinUrl String? - /// @Validator.IsNumber() - /// @Validator.IsOptional() - annualRecurringRevenue Int? - /// @Validator.IsBoolean() - /// @Validator.IsOptional() - idealCustomerProfile Boolean @default(false) - /// @Validator.IsString() - /// @Validator.IsOptional() - xUrl String? - /// @Validator.IsString() - /// @Validator.IsOptional() - address String - /// @Validator.IsNumber() - /// @Validator.IsOptional() - employees Int? - - people Person[] - accountOwner User? @relation(fields: [accountOwnerId], references: [id], onDelete: SetNull) - accountOwnerId String? - workspaceMemberAccountOwner WorkspaceMember? @relation(fields: [workspaceMemberAccountOwnerId], references: [id], onDelete: SetNull) - workspaceMemberAccountOwnerId String? - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - ActivityTarget ActivityTarget[] - PipelineProgress PipelineProgress[] - Favorite Favorite[] - Attachment Attachment[] - - @@map("companies") -} - -model Person { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - firstName String? - /// @Validator.IsString() - /// @Validator.IsOptional() - lastName String? - /// @Validator.IsString() - /// @Validator.IsOptional() - email String? - /// @Validator.IsString() - /// @Validator.IsOptional() - linkedinUrl String? - /// @Validator.IsString() - /// @Validator.IsOptional() - xUrl String? - /// @Validator.IsString() - /// @Validator.IsOptional() - jobTitle String? - /// @Validator.IsString() - /// @Validator.IsOptional() - phone String? - /// @Validator.IsString() - /// @Validator.IsOptional() - city String? - /// @Validator.IsString() - /// @Validator.IsOptional() - avatarUrl String? - - company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull) - companyId String? - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - contactPipelineProgresses PipelineProgress[] @relation("PointOfContactPipelineProgress") - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - ActivityTarget ActivityTarget[] - PipelineProgress PipelineProgress[] - Favorite Favorite[] - Attachment Attachment[] - - @@map("people") -} - -model RefreshToken { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - - /// @TypeGraphQL.omit(input: true, output: true) - user User @relation(fields: [userId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - userId String - - expiresAt DateTime - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - /// @TypeGraphQL.omit(input: true, output: true) - revokedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("refresh_tokens") -} - -enum ActivityType { - Note - Task -} - -model Activity { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - body String? - title String? - type ActivityType @default(Note) - reminderAt DateTime? - dueAt DateTime? - completedAt DateTime? - - activityTargets ActivityTarget[] - comments Comment[] - attachments Attachment[] - author User @relation(fields: [authorId], references: [id], name: "authoredActivities", onDelete: Cascade) - authorId String - - workspaceMemberAuthor WorkspaceMember? @relation(fields: [workspaceMemberAuthorId], references: [id], name: "authoredActivities", onDelete: Cascade) - workspaceMemberAuthorId String? - - assignee User? @relation(fields: [assigneeId], references: [id], name: "assignedActivities", onDelete: SetNull) - assigneeId String? - - workspaceMemberAssignee WorkspaceMember? @relation(fields: [workspaceMemberAssigneeId], references: [id], name: "assignedActivities", onDelete: SetNull) - workspaceMemberAssigneeId String? - - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("activities") -} - -model Comment { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - body String - - author User @relation(fields: [authorId], references: [id], onDelete: Cascade) - authorId String - - workspaceMemberAuthor WorkspaceMember? @relation(fields: [workspaceMemberAuthorId], references: [id], onDelete: Cascade) - workspaceMemberAuthorId String? - - activity Activity? @relation(fields: [activityId], references: [id], onDelete: Cascade) - activityId String? - commentThreadId String? - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("comments") -} - -model ActivityTarget { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - - activity Activity @relation(fields: [activityId], references: [id], onDelete: Cascade) - activityId String - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - personId String? - person Person? @relation(fields: [personId], references: [id], onDelete: Cascade) - - companyId String? - company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade) - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("activity_targets") -} - -// All of the world's currently active currencies based on the ISO 4217 standard -enum CurrencyCode { - AED - AFN - ALL - AMD - ANG - AOA - ARS - AUD - AWG - AZN - BAM - BBD - BDT - BGN - BHD - BIF - BMD - BND - BOB - BOV - BRL - BSD - BTN - BWP - BYN - BZD - CAD - CDF - CHF - CLF - CLP - CNY - COP - COU - CRC - CUC - CUP - CVE - CZK - DJF - DKK - DOP - DZD - EGP - ERN - ETB - EUR - FJD - FKP - GBP - GEL - GHS - GIP - GMD - GNF - GTQ - GYD - HKD - HNL - HRK - HTG - HUF - IDR - ILS - INR - IQD - IRR - ISK - JMD - JOD - JPY - KES - KGS - KHR - KMF - KPW - KRW - KWD - KYD - KZT - LAK - LBP - LKR - LRD - LSL - LYD - MAD - MDL - MGA - MKD - MMK - MNT - MOP - MRO - MRU - MUR - MVR - MWK - MXN - MXV - MYR - MZN - NAD - NGN - NIO - NOK - NPR - NZD - OMR - PAB - PEN - PGK - PHP - PKR - PLN - PYG - QAR - RON - RSD - RUB - RWF - SAR - SBD - SCR - SDD - SDG - SEK - SGD - SHP - SLL - SOS - SRD - SSP - STD - STN - SVC - SYP - SZL - THB - TJS - TMM - TMT - TND - TOP - TRY - TTD - TWD - TZS - UAH - UGX - USD - UYU - UZS - VEF - VES - VND - VUV - WST - XAF - XCD - XOF - XPF - XSU - XUA - YER - ZAR - ZMW - ZWL - - @@map("CurrencyCode") -} - -model Pipeline { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - name String - /// @Validator.IsString() - icon String - - pipelineStages PipelineStage[] - pipelineProgresses PipelineProgress[] - pipelineProgressableType PipelineProgressableType @default(Company) - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - currency CurrencyCode @default(USD) - - @@map("pipelines") -} - -model PipelineStage { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @Validator.IsString() - /// @Validator.IsOptional() - name String - /// @Validator.IsString() - /// @Validator.IsOptional() - type String - /// @Validator.IsOptional() - /// @Validator.IsString() - color String - /// @Validator.IsNumber() - /// @Validator.IsOptional() - position Int? - - pipelineProgresses PipelineProgress[] - /// - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - pipelineId String - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("pipeline_stages") -} - -enum PipelineProgressableType { - Person - Company -} - -model PipelineProgress { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - amount Int? - closeDate DateTime? - probability Int? - - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - pipelineId String - pipelineStage PipelineStage @relation(fields: [pipelineStageId], references: [id], onDelete: Cascade) - pipelineStageId String - pointOfContact Person? @relation("PointOfContactPipelineProgress", fields: [pointOfContactId], references: [id], onDelete: SetNull) - pointOfContactId String? - - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - companyId String? - company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade) - - personId String? - person Person? @relation(fields: [personId], references: [id], onDelete: Cascade) - - @@map("pipeline_progresses") -} - -enum AttachmentType { - Image - Audio - Video - TextDocument - Spreadsheet - Archive - Other -} - -model Attachment { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - - fullPath String - type AttachmentType - name String - - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - - author User @relation(fields: [authorId], references: [id], name: "authoredAttachments", onDelete: Cascade) - authorId String - - workspaceMemberAuthor WorkspaceMember? @relation(fields: [workspaceMemberAuthorId], references: [id], name: "authoredAttachments", onDelete: Cascade) - workspaceMemberAuthorId String? - - activity Activity? @relation(fields: [activityId], references: [id], onDelete: Cascade) - activityId String? - - /// @TypeGraphQL.omit(input: true, output: false) - person Person? @relation(fields: [personId], references: [id], onDelete: Cascade) - personId String? - /// @TypeGraphQL.omit(input: true, output: false) - company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade) - companyId String? - - /// @TypeGraphQL.omit(input: true, output: false) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("attachments") -} - -model Favorite { - id String @id @default(uuid()) - workspaceId String? - /// @TypeGraphQL.omit(input: true, output: false) - person Person? @relation(fields: [personId], references: [id], onDelete: Cascade) - personId String? - /// @TypeGraphQL.omit(input: true, output: false) - company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade) - companyId String? - /// @TypeGraphQL.omit(input: true, output: false) - workspaceMember WorkspaceMember? @relation(fields: [workspaceMemberId], references: [id]) - workspaceMemberId String? - position Float - - @@map("favorites") -} - -enum ViewType { - Table - Pipeline -} - -model ApiKey { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - name String - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - expiresAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - /// @TypeGraphQL.omit(input: true, output: true) - revokedAt DateTime? - - @@map("api_keys") -} - -model WebHook { - /// @Validator.IsString() - /// @Validator.IsOptional() - id String @id @default(uuid()) - /// @TypeGraphQL.omit(input: true, output: true) - workspace Workspace @relation(fields: [workspaceId], references: [id]) - /// @TypeGraphQL.omit(input: true, output: true) - workspaceId String - targetUrl String - operation String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - /// @TypeGraphQL.omit(input: true, output: true) - deletedAt DateTime? - - @@map("web_hooks") -} diff --git a/server/src/database/seeds/comments.ts b/server/src/database/seeds/comments.ts deleted file mode 100644 index f51d64373..000000000 --- a/server/src/database/seeds/comments.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedComments = async (prisma: PrismaClient) => { - await prisma.activity.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - title: 'Performance update', - type: 'Note', - body: '[{"id":"555df0c3-ab88-4c62-abae-c9b557c37c5b","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"In the North American region, we have observed a strong growth rate of 18% in sales. Europe followed suit with a significant 14% increase, while Asia-Pacific sustained its performance with a steady 10% rise. Special kudos to the North American team for the excellent work done in penetrating new markets and establishing stronger footholds in the existing ones.","styles":{}}],"children":[]},{"id":"13530934-b3ce-4332-9238-3760aa4acb3e","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]}]', - authorId: '20202020-c231-45c5-b9f2-cf8b70191f6d', - }, - }); - - await prisma.activityTarget.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb600', - personId: null, - companyId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408', - activityId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.comment.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb200' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb200', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - body: 'Hi Félix ! How do you like your Twenty workspace?', - activityId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - commentThreadId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - authorId: '20202020-c231-45c5-b9f2-cf8b70191f6d', - }, - }); - - await prisma.comment.upsert({ - where: { id: 'twenty-fe256b40-3ec3-4fe3-8997-b76aa0bfb200' }, - update: {}, - create: { - id: 'twenty-fe256b40-3ec3-4fe3-8997-b76aa0bfb200', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - body: 'I love it!', - activityId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - commentThreadId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb400', - authorId: '20202020-ef2e-45df-b677-32fa06d4bd2a', - }, - }); - - await prisma.activity.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfc408' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfc408', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - title: 'Buyout Proposal', - type: 'Task', - assigneeId: '20202020-c231-45c5-b9f2-cf8b70191f6d', - dueAt: new Date('2021-03-01T00:00:00.000Z'), - body: '[{"id":"333df0c3-ab88-4c62-abae-c9b557c37c5b","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"We are considering the potential acquisition of [Company], a leading company in [Industry/Specific Technology]. This company has demonstrated remarkable success and pioneering advancements in their field, paralleling our own commitment to progress. By integrating their expertise with our own, we believe that we can amplify our growth, broaden our offerings, and fortify our position at the forefront of technology. This prospective partnership could help to ensure our continued leadership in the industry and allow us to deliver even more innovative solutions for our customers.","styles":{}}],"children":[]},{"id":"13530934-b3ce-4332-9238-3760aa4acb3e","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]}]', - authorId: '20202020-c231-45c5-b9f2-cf8b70191f6d', - }, - }); - - await prisma.activityTarget.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-a76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-a76aa0bfb600', - personId: 'twenty-755035db-623d-41fe-92e7-dd45b7c568e1', - companyId: null, - activityId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfc408', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.comment.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb100' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfb100', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - body: 'I really like this comment thread feature!', - activityId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfc408', - commentThreadId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfc408', - authorId: '20202020-c231-45c5-b9f2-cf8b70191f6d', - }, - }); - - await prisma.activity.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aaabfb408' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aaabfb408', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - title: 'Call summary', - body: '[{"id":"555df0c3-ab88-4c62-abae-c9b557c37c5b","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"Valuation & Due Diligence: The CFO highlighted the financial implications, pointing out that the acquisition will be accretive to earnings. The M&A team has been directed to commence due diligence and work closely with legal counsel to assess all aspects of the acquisition.","styles":{}}],"children":[]},{"id":"13530934-b3ce-4332-9238-3760aa4acb3e","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]}]', - authorId: 'twenty-dev-gk256b39-3ec3-4fe3-8997-b76aa0boa408', - }, - }); - - await prisma.activityTarget.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-a76aa0bfba00' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-a76aa0bfba00', - personId: null, - companyId: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e', - activityId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aaabfb408', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.comment.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aa0bfb000' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aa0bfb000', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - body: 'I really like this comment thread feature!', - activityId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aaabfb408', - commentThreadId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b76aaabfb408', - authorId: 'twenty-dev-gk256b39-3ec3-4fe3-8997-b76aa0boa408', - }, - }); -}; diff --git a/server/src/database/seeds/companies.ts b/server/src/database/seeds/companies.ts deleted file mode 100644 index 5dbfa73f8..000000000 --- a/server/src/database/seeds/companies.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedCompanies = async (prisma: PrismaClient) => { - await prisma.company.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408', - name: 'Linkedin', - domainName: 'linkedin.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-118995f3-5d81-46d6-bf83-f7fd33ea6102' }, - update: {}, - create: { - id: 'twenty-118995f3-5d81-46d6-bf83-f7fd33ea6102', - name: 'Facebook', - domainName: 'facebook.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-04b2e9f5-0713-40a5-8216-82802401d33e' }, - update: {}, - create: { - id: 'twenty-04b2e9f5-0713-40a5-8216-82802401d33e', - name: 'Qonto', - domainName: 'qonto.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4' }, - update: {}, - create: { - id: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4', - name: 'Microsoft', - domainName: 'microsoft.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-89bb825c-171e-4bcc-9cf7-43448d6fb278' }, - update: {}, - create: { - id: 'twenty-89bb825c-171e-4bcc-9cf7-43448d6fb278', - name: 'Airbnb', - domainName: 'airbnb.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025' }, - update: {}, - create: { - id: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025', - name: 'Google', - domainName: 'google.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-1d3a1c6e-707e-44dc-a1d2-30030bf1a944' }, - update: {}, - create: { - id: 'twenty-1d3a1c6e-707e-44dc-a1d2-30030bf1a944', - name: 'Netflix', - domainName: 'netflix.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-7a93d1e5-3f74-492d-a101-2a70f50a1645' }, - update: {}, - create: { - id: 'twenty-7a93d1e5-3f74-492d-a101-2a70f50a1645', - name: 'Libeo', - domainName: 'libeo.io', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - - await prisma.company.upsert({ - where: { id: 'twenty-9d162de6-cfbf-4156-a790-e39854dcd4eb' }, - update: {}, - create: { - id: 'twenty-9d162de6-cfbf-4156-a790-e39854dcd4eb', - name: 'Claap', - domainName: 'claap.io', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - - await prisma.company.upsert({ - where: { id: 'twenty-aaffcfbd-f86b-419f-b794-02319abe8637' }, - update: {}, - create: { - id: 'twenty-aaffcfbd-f86b-419f-b794-02319abe8637', - name: 'Hasura', - domainName: 'hasura.io', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - - await prisma.company.upsert({ - where: { id: 'twenty-f33dc242-5518-4553-9433-42d8eb82834b' }, - update: {}, - create: { - id: 'twenty-f33dc242-5518-4553-9433-42d8eb82834b', - name: 'Wework', - domainName: 'wework.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - - await prisma.company.upsert({ - where: { id: 'twenty-a7bc68d5-f79e-40dd-bd06-c36e6abb4678' }, - update: {}, - create: { - id: 'twenty-a7bc68d5-f79e-40dd-bd06-c36e6abb4678', - name: 'Samsung', - domainName: 'samsung.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - await prisma.company.upsert({ - where: { id: 'twenty-a674fa6c-1455-4c57-afaf-dd5dc086361d' }, - update: {}, - create: { - id: 'twenty-a674fa6c-1455-4c57-afaf-dd5dc086361d', - name: 'Algolia', - domainName: 'algolia.com', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - address: '', - }, - }); - - await prisma.company.upsert({ - where: { id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e' }, - update: {}, - create: { - id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e', - name: 'Instagram', - domainName: 'instagram.com', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - address: '', - }, - }); -}; diff --git a/server/src/database/seeds/index.ts b/server/src/database/seeds/index.ts deleted file mode 100644 index 4bb4d6515..000000000 --- a/server/src/database/seeds/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -import { seedCompanies } from './companies'; -import { seedWorkspaces } from './workspaces'; -import { seedPeople } from './people'; -import { seedComments } from './comments'; -import { seedUsers } from './users'; -import { seedPipelines } from './pipelines'; -import { seedMetadata } from './metadata'; - -const seed = async () => { - const prisma = new PrismaClient(); - await seedWorkspaces(prisma); - await seedUsers(prisma); - await seedCompanies(prisma); - await seedPeople(prisma); - await seedComments(prisma); - await seedPipelines(prisma); - await seedMetadata(prisma); - await prisma.$disconnect(); -}; - -seed(); diff --git a/server/src/database/seeds/metadata.ts b/server/src/database/seeds/metadata.ts deleted file mode 100644 index 8ed6cb20d..000000000 --- a/server/src/database/seeds/metadata.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -export const SeedDataSourceId = '20202020-7f63-47a9-b1b3-6c7290ca9fb1'; -export const SeedWorkspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419'; -export const SeedWorkspaceSchemaName = 'workspace_1wgvd1injqtife6y4rvfbu3h5'; - -export const seedMetadata = async (prisma: PrismaClient) => { - await prisma.$queryRawUnsafe( - `CREATE SCHEMA IF NOT EXISTS ${SeedWorkspaceSchemaName}`, - ); - await prisma.$queryRawUnsafe( - `INSERT INTO metadata."dataSource"( - id, schema, type, "workspaceId" - ) - VALUES ( - '${SeedDataSourceId}', '${SeedWorkspaceSchemaName}', 'postgres', '${SeedWorkspaceId}' - ) ON CONFLICT DO NOTHING`, - ); -}; diff --git a/server/src/database/seeds/people.ts b/server/src/database/seeds/people.ts deleted file mode 100644 index 9816f6e96..000000000 --- a/server/src/database/seeds/people.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedPeople = async (prisma: PrismaClient) => { - await prisma.person.upsert({ - where: { id: 'twenty-86083141-1c0e-494c-a1b6-85b1c6fefaa5' }, - update: {}, - create: { - id: 'twenty-86083141-1c0e-494c-a1b6-85b1c6fefaa5', - firstName: 'Christoph', - lastName: 'Callisto', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33789012345', - city: 'Seattle', - companyId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408', - email: 'christoph.calisto@linkedin.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-0aa00beb-ac73-4797-824e-87a1f5aea9e0' }, - update: {}, - create: { - id: 'twenty-0aa00beb-ac73-4797-824e-87a1f5aea9e0', - firstName: 'Sylvie', - lastName: 'Palmer', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33780123456', - city: 'Los Angeles', - companyId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408', - email: 'sylvie.palmer@linkedin.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-93c72d2e-f517-42fd-80ae-14173b3b70ae' }, - update: {}, - create: { - id: 'twenty-93c72d2e-f517-42fd-80ae-14173b3b70ae', - firstName: 'Christopher', - lastName: 'Gonzalez', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33789012345', - city: 'Seattle', - companyId: 'twenty-04b2e9f5-0713-40a5-8216-82802401d33e', - email: 'christopher.gonzalez@qonto.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-eeeacacf-eee1-4690-ad2c-8619e5b56a2e' }, - update: {}, - create: { - id: 'twenty-eeeacacf-eee1-4690-ad2c-8619e5b56a2e', - firstName: 'Ashley', - lastName: 'Parker', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33780123456', - city: 'Los Angeles', - companyId: 'twenty-04b2e9f5-0713-40a5-8216-82802401d33e', - email: 'ashley.parker@qonto.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-9b324a88-6784-4449-afdf-dc62cb8702f2' }, - update: {}, - create: { - id: 'twenty-9b324a88-6784-4449-afdf-dc62cb8702f2', - firstName: 'Nicholas', - lastName: 'Wright', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33781234567', - city: 'Seattle', - companyId: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4', - email: 'nicholas.wright@microsoft.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-1d151852-490f-4466-8391-733cfd66a0c8' }, - update: {}, - create: { - id: 'twenty-1d151852-490f-4466-8391-733cfd66a0c8', - firstName: 'Isabella', - lastName: 'Scott', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33782345678', - city: 'New York', - companyId: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4', - email: 'isabella.scott@microsoft.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-98406e26-80f1-4dff-b570-a74942528de3' }, - update: {}, - create: { - id: 'twenty-98406e26-80f1-4dff-b570-a74942528de3', - firstName: 'Matthew', - lastName: 'Green', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33783456789', - city: 'Seattle', - companyId: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4', - email: 'matthew.green@microsoft.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-a2e78a5f-338b-46df-8811-fa08c7d19d35' }, - update: {}, - create: { - id: 'twenty-a2e78a5f-338b-46df-8811-fa08c7d19d35', - firstName: 'Elizabeth', - lastName: 'Baker', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33784567890', - city: 'New York', - companyId: 'twenty-89bb825c-171e-4bcc-9cf7-43448d6fb278', - email: 'elizabeth.baker@airbnb.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-ca1f5bf3-64ad-4b0e-bbfd-e9fd795b7016' }, - update: {}, - create: { - id: 'twenty-ca1f5bf3-64ad-4b0e-bbfd-e9fd795b7016', - firstName: 'Christopher', - lastName: 'Nelson', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33785678901', - city: 'San Francisco', - companyId: 'twenty-89bb825c-171e-4bcc-9cf7-43448d6fb278', - email: 'christopher.nelson@airbnb.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-56955422-5d54-41b7-ba36-f0d20e1417ae' }, - update: {}, - create: { - id: 'twenty-56955422-5d54-41b7-ba36-f0d20e1417ae', - firstName: 'Avery', - lastName: 'Carter', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33786789012', - city: 'New York', - companyId: 'twenty-89bb825c-171e-4bcc-9cf7-43448d6fb278', - email: 'avery.carter@airbnb.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-755035db-623d-41fe-92e7-dd45b7c568e1' }, - update: {}, - create: { - id: 'twenty-755035db-623d-41fe-92e7-dd45b7c568e1', - firstName: 'Ethan', - lastName: 'Mitchell', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33787890123', - city: 'Los Angeles', - companyId: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025', - email: 'ethan.mitchell@google.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190ef' }, - update: {}, - create: { - id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190ef', - firstName: 'Madison', - lastName: 'Perez', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33788901234', - city: 'Seattle', - companyId: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025', - email: 'madison.perez@google.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190df' }, - update: {}, - create: { - id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190df', - firstName: 'Bertrand', - lastName: 'Voulzy', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33788901234', - city: 'Seattle', - companyId: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025', - email: 'bertrand.voulzy@google.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190dg' }, - update: {}, - create: { - id: 'twenty-240da2ec-2d40-4e49-8df4-9c6a049190dg', - firstName: 'Louis', - lastName: 'Duss', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - phone: '+33788901234', - city: 'Seattle', - companyId: 'twenty-0d940997-c21e-4ec2-873b-de4264d89025', - email: 'louis.duss@google.com', - }, - }); - - await prisma.person.upsert({ - where: { id: 'twenty-dev-240da2ec-2d40-4e49-8df4-9c6a049190dh' }, - update: {}, - create: { - id: 'twenty-dev-240da2ec-2d40-4e49-8df4-9c6a049190dh', - firstName: 'Lorie', - lastName: 'Vladim', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - phone: '+33788901235', - city: 'Seattle', - companyId: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e', - email: 'lorie.vladim@google.com', - }, - }); -}; diff --git a/server/src/database/seeds/pipelines.ts b/server/src/database/seeds/pipelines.ts deleted file mode 100644 index 48cc3dfb5..000000000 --- a/server/src/database/seeds/pipelines.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedPipelines = async (prisma: PrismaClient) => { - await prisma.pipeline.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - name: 'Sales pipeline', - icon: '💰', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - pipelineProgressableType: 'Company', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - name: 'New', - color: 'red', - position: 0, - type: 'open', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe4-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe4-8998-b76aa0bfb600', - name: 'Screening', - color: 'purple', - position: 1, - type: 'ongoing', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe5-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe5-8998-b76aa0bfb600', - name: 'Meeting', - color: 'sky', - position: 2, - type: 'ongoing', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe6-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe6-8998-b76aa0bfb600', - name: 'Proposal', - color: 'turquoise', - position: 3, - type: 'ongoing', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - name: 'Customer', - color: 'yellow', - position: 4, - type: 'won', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineProgress.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - pipelineStageId: 'twenty-fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - companyId: 'twenty-fe256b39-3ec3-4fe3-8997-b76aa0bfa408', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineProgress.upsert({ - where: { id: 'twenty-4a886c90-f4f2-4984-8222-882ebbb905d6' }, - update: {}, - create: { - id: 'twenty-4a886c90-f4f2-4984-8222-882ebbb905d6', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - pipelineStageId: 'twenty-fe256b39-3ec3-4fe4-8998-b76aa0bfb600', - companyId: 'twenty-118995f3-5d81-46d6-bf83-f7fd33ea6102', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineProgress.upsert({ - where: { id: 'twenty-af92f3eb-d51d-4528-9b97-b8f132865b00' }, - update: {}, - create: { - id: 'twenty-af92f3eb-d51d-4528-9b97-b8f132865b00', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - pipelineStageId: 'twenty-fe256b39-3ec3-4fe5-8998-b76aa0bfb600', - companyId: 'twenty-04b2e9f5-0713-40a5-8216-82802401d33e', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineProgress.upsert({ - where: { id: 'twenty-08369b1a-acdb-43d6-95f9-67ac7436941a' }, - update: {}, - create: { - id: 'twenty-08369b1a-acdb-43d6-95f9-67ac7436941a', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - pipelineStageId: 'twenty-fe256b39-3ec3-4fe5-8998-b76aa0bfb600', - companyId: 'twenty-460b6fb1-ed89-413a-b31a-962986e67bb4', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipeline.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8997-b74aa0bfb400' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8997-b74aa0bfb400', - name: 'Customer support pipeline', - icon: '📔', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - pipelineProgressableType: 'Person', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe3-8998-a76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe3-8998-a76aa0bfb600', - name: 'New', - color: 'red', - position: 1, - type: 'open', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b74aa0bfb400', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipelineProgress.upsert({ - where: { id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - pipelineId: 'twenty-fe256b39-3ec3-4fe3-8997-b74aa0bfb400', - pipelineStageId: 'twenty-fe256b39-3ec3-4fe3-8998-a76aa0bfb600', - personId: 'twenty-755035db-623d-41fe-92e7-dd45b7c568e1', - workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.pipeline.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - name: 'Sales pipeline', - icon: '💰', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe3-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe3-8998-b76aa0bfb600', - name: 'New', - color: 'red', - position: 0, - type: 'open', - pipelineId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe4-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe4-8998-b76aa0bfb600', - name: 'Screening', - color: 'purple', - position: 1, - type: 'ongoing', - pipelineId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe5-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe5-8998-b76aa0bfb600', - name: 'Meeting', - color: 'sky', - position: 2, - type: 'ongoing', - pipelineId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe6-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe6-8998-b76aa0bfb600', - name: 'Proposal', - color: 'turquoise', - position: 3, - type: 'ongoing', - pipelineId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); - - await prisma.pipelineStage.upsert({ - where: { id: 'twenty-dev-fe256b39-3ec3-4fe7-8998-b76aa0bfb600' }, - update: {}, - create: { - id: 'twenty-dev-fe256b39-3ec3-4fe7-8998-b76aa0bfb600', - name: 'Customer', - color: 'yellow', - position: 4, - type: 'won', - pipelineId: 'twenty-dev-fe256b39-3ec3-4fe3-8997-b75aa0bfb400', - workspaceId: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - }, - }); -}; diff --git a/server/src/database/seeds/users.ts b/server/src/database/seeds/users.ts deleted file mode 100644 index a4bebb379..000000000 --- a/server/src/database/seeds/users.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedUsers = async (prisma: PrismaClient) => { - await prisma.userSettings.upsert({ - where: { id: 'twenty-ge256b39-3ec3-4fe3-8997-9dcb1084c109' }, - update: {}, - create: { - id: 'twenty-ge256b39-3ec3-4fe3-8997-9dcb1084c109', - locale: 'en', - }, - }); - await prisma.user.upsert({ - where: { id: '20202020-a838-4fa9-b59b-96409b9a1c30' }, - update: {}, - create: { - id: '20202020-a838-4fa9-b59b-96409b9a1c30', - firstName: 'Tim', - lastName: 'Apple', - email: 'tim@apple.dev', - locale: 'en', - passwordHash: - '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 - avatarUrl: null, - defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.userSettings.upsert({ - where: { id: 'twenty-ge256b39-3ec3-4fe3-8997-2c4a2035a215' }, - update: {}, - create: { - id: 'twenty-ge256b39-3ec3-4fe3-8997-2c4a2035a215', - locale: 'en', - }, - }); - await prisma.user.upsert({ - where: { id: '20202020-c231-45c5-b9f2-cf8b70191f6d' }, - update: {}, - create: { - id: '20202020-c231-45c5-b9f2-cf8b70191f6d', - firstName: 'Jony', - lastName: 'Ive', - email: 'jony.ive@apple.dev', - locale: 'en', - avatarUrl: null, - defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.userSettings.upsert({ - where: { id: 'twenty-ge256b39-3ec3-4fe3-8997-8e1f2097b328' }, - update: {}, - create: { - id: 'twenty-ge256b39-3ec3-4fe3-8997-8e1f2097b328', - locale: 'en', - }, - }); - await prisma.user.upsert({ - where: { id: '20202020-ef2e-45df-b677-32fa06d4bd2a' }, - update: {}, - create: { - id: '20202020-ef2e-45df-b677-32fa06d4bd2a', - firstName: 'Phil', - lastName: 'Schiler', - email: 'phil.schiler@apple.dev', - locale: 'en', - avatarUrl: null, - defaultWorkspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419', - }, - }); - - await prisma.userSettings.upsert({ - where: { id: 'twenty-ge256b39-3ec3-4fe3-8997-5e2d1049c430' }, - update: {}, - create: { - id: 'twenty-ge256b39-3ec3-4fe3-8997-5e2d1049c430', - locale: 'en', - }, - }); - await prisma.user.upsert({ - where: { id: 'twenty-dev-gk256b39-3ec3-4fe3-8997-b76aa0boa408' }, - update: {}, - create: { - id: 'twenty-dev-gk256b39-3ec3-4fe3-8997-b76aa0boa408', - firstName: 'Charles', - lastName: 'Bochet', - email: 'charles@twenty.dev', - locale: 'en', - }, - }); -}; diff --git a/server/src/database/seeds/workspaces.ts b/server/src/database/seeds/workspaces.ts deleted file mode 100644 index 6af274f61..000000000 --- a/server/src/database/seeds/workspaces.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const seedWorkspaces = async (prisma: PrismaClient) => { - await prisma.workspace.upsert({ - where: { id: '20202020-1c25-4d02-bf25-6aeccf7ea419' }, - update: {}, - create: { - id: '20202020-1c25-4d02-bf25-6aeccf7ea419', - displayName: 'Apple', - domainName: 'apple.dev', - inviteHash: 'apple.dev-invite-hash', - logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAELpJREFUeF7tnXnwr3MVx1+WS5Hthoss1R0lNSTUKGQdt6EscVVCKVPKUqmUKcu0WJI2ppJUt0kNwmRN0dBCtolKpqIVIdl3qXnX8xs/1+937/d5vp/lnOc5n3++/zyfzznnfc77+zyf7ZxFiBYIBALTIrBIYBMIBALTIxAEiegIBBaAQBAkwiMQCIJEDIyJgP5IlwRmAreOOZar7vEGceWuYsrOBg4E5gKzgMlxMqiYGZSxxcLLnyDFwU7AF4A1FqL+osB//JnYTeMgSDfc+tLrhcBZwHotDFoMeLLF864fDYK4dl9n5XcBTm3mFW0HWRz4d9tOXp8Pgnj1XDe9d2+Ioc+kri3eIF2Ri35mEdgAuLzjG2N+o2IOYtbNoVhbBGYA1wPrtO24gOcH9dUxKGMTBomHofYE5iVWVKtX43yeJVYn/3BBkPwY15BwXcuVqVF1fBB4zqgP9+G5IEgfvPiUDSsAdwBaacrRrgY2zjGw1TGDIFY9016vjYCr2ndr1eMQ4NhWPZw/HARx7sBG/Z2BMwuY8nzgLwXkmBERBDHjis6KaG/je517t+s4uHgZnMHt4sH809sCFxXS8l5g+UKyzIgJgphxRWtFdI7qpta9unc4Ejiie3efPYMgPv2muxmPFFZdy7ta5h1UC4L4dPcDwNIFVX8YWKqgPDOigiBmXDGyIhcAc0Z+Os2D+wFfSTOUr1GCIL78tTXw4woqD+qA4mR8gyAVoq2jSAVpjXsY2l95Y0ed3XcLgvhx4S+BV1ZQdwng8QpyTYgMgphww0KVeDFw40KfSv/AD4Ad0w/rZ8QgiA9fPQQ8u4Kqg7o9OBW+QZAKUddSpLKNKLFC6XYocFRpodbkBUGseeSZ+uj7P9fx9ems1yZkjTeWOW8EQcy55GkKab9D+x6l2+rALaWFWpQXBLHolad0Kr1jLsknAAfYhqWcdkGQcli3lbQKcFvbTmM+fxew4phj9Kp7EMSuOy8Btiys3qD3PKbCOghSOAJbiCud//alwA0t9BvEo0EQm25+GfDrgqrtC5xcUJ4bUUEQm666ENiukGrK6P6+QrLciQmC2HTZE4B2sXO305saILnluB0/CGLPdSKGCJK7nQu8PrcQ7+MHQex5cENACdpytu8Cb8kpoC9jB0HsefI44OCMaul8lc5ZRRsBgSDICCAVfuQ3gJZcczQVzqlx8DGHLUXGDIIUgbmVEGUOSZ0gQSXTdL6q9M58K8MtPhwEsecVBXNKvyjTuwrolN54tIdsB41SOqKD+OgyBQIpA/kNwDmBcncEgiDdscvVMwVBzmuWcFOMlctOF+MGQey5aZyg/hWwGaBj8tESIBAESQBi4iG6EOQ0YO8K6UgTm25vuCCIPZ+MMkkXiZQGSBebcm8q2kOooEZBkIJgjyhKV11nNitZIoI+l/4O/Aw4A7gCeHTEscZ5TLExcRdeeihpXZe32zg6VO87ZILoctDzgPWbZdC1gdWAZRqv3An8Dris+bfWHkLfAkQEWA94E7A9oJIKz1pIVAoDJXX4M/DTZuNRNdhVP6R3bSgEUSAor+37m0ls1404ff4ogdvnmqpO3ibDKpugNKIfbXbrU/tfxPkRcHTzphNerltqgCyBMQs4vjnOnSttjv5N9S8q4l1ryfhJumgHXee7di10hH4yDDoVINnHACqh4K71jSAigv69dAGoxH2K+R3+W+Cdzb9nzWBYFfgqsEPiXflxbBJZDgJO8fSp2heCKCBUFmDdcTyYuO9PgL2aCXbioaccTnOHTzVBWOPPoY2Nyvk7t9BiQxu9nvGsd4JoUq3a4Pq12rT6oznLYRk+M0QEvbH0GaMSad6aVua2sUwUrwTRZPPKZgXGU1BoUi+iKDlb15ICqhOiVSeRbmVPxi9A1283b1tz5ngkyKebVRhzYLZUSGTRP/9nRzgaoiXpPZv5VV8Tu2nBQyuN+jQ10zwRRP+WWnvvY1JlBYdWwU5s5lLaU9ClKS02KLu7CDKUphMCm1iZyHshyOFDrNE9FEZMYafmbWtZSKBtnSDS7w/A7AEHy5BNf3OzIVsNA8sEWRZQMuVcm3zVQA/BrRComtjOKkFq1eRr5bl4uBgC1SrtWiTIps3xjWLohyAXCFQpKGqNIFtYW+ZzETrDUfIbwD4lzbVEkI2aXfGS9ocsfwh8oNkkLaK5FYLoXoYuBUULBEZBQH+m14zy4LjPWCCINsF0j8CCLuPiGf3LIaDDmdlvVloIyvudHrQrFwohaSoE7m6uJmdFpzZBdERd52+iBQJtECh2bqsmQXYEzm6DSjwbCDQ5ArTaWSQ/QC2CzAAeC3cHAi0R0N2Ri1v2GevxWgS5qcmgMZby0XkwCNwDKMdA8T/VGgSZA1wwGNeGoeMioDeG3hxVWg2CjJI5sAoYIdQcAp8EPl5Tq9IE+Vpzh7qmzSHbBwLKNTyvtqolCaINwewbO7UBDflJEFByO53grd5KEuRSYPPqFocC1hHYAzjVipKlCKJjAS4z61lx1ED00HxD8w4zrRRBLgS2M2N1KGIRgfObBNqmdCtBEOVx0iX8aIHAdAgUOVfVBf4SBImMJF08M6w+SgRYfBNwFIhLEOSJSomkR7E/nqmPwM6Wz+TlJojS9fyxvg9CA6MI3Gw9pVNugig58WuMOifUqo+AsmTqspzZlpsgRY4km0U3FFsQAqoT8g7rEOUkyDpNjT/rGIR+dRDQ6qb5P9CcBDnX4rp2nVgIqfMhoOpX7/aASk6CxOqVhwioo6PSybrYG8tFkDiYWCfwPEi9vim97UHXbKl2VDzyHBcIhJKlEVDe5d+XFtpVXq43iG6BbdVVqejXWwQ0Kdfk3E3LRRCtbev4QLRAYDICKq/m6o8zF0HML99F3FZBYGPg6iqSOwrNQZBlgPs66hPd+o2Ai72PyS7IQZAtgUv67eewrgMCOq3r7rM7B0FU2vjgDgBGl34j8HNAxZFctRwE0Tfmhq5QCGVLILB/U+a6hKxkMnIQRFnwlkumYQzUFwRe1FQsdmVPDoLoCIGrtW5XHvOrbJF6HqnhyUGQWOJN7aV+jJcj1rIjk0PpIEh2t7kUkCPWsgORWunFAJ3ijRYITEbA3RGTCeVTE0Tr3KavUEbcVkFACcv15+mupSZI7KK7C4EiCuurQkWT3LXUBFkJuMMdCqFwbgSCIA3CqwK35kY7xneHQHxiNS5bDbjFnftC4dwIxCS9QXgV4LbcaMf4LhFI/TlfBITUSsccpIjbXApxd9RdKKcmyLLAvS7dF0rnRsB8FsWpAEhNkCiUkzvM/I7vKlnDBMypCRI76X4DOLfm7wG+nFtI6vFTE0TjaUkvWiAwPwKXAa/1Bktqgsj+OKzoLQrK6KsKx/oEd9VyEERvkBzjugI2lJ0SAXcrWTkCOXJiBTumQ2Bdbxn/cxBEO+naUY8WCMyPwBnAbp5gyUGQSDvqKQLK6qrr2Mrs7qblIMhhwJFuEAhFSyOg0xb/LC20q7wcBNkcuLSrQtGv9wicDaiyrYuWgyDLAyoMHy0QmA6BHHGXBe0cisZmYRZX9WrQvYF5HizKQRDZHXshHrxfT0c3NwxzEUR3QnQ3JFogMB0CmodoPmK65SLIyR5qYJv2TP+Vc3ENNxdBYiWr/wGewsKjgENTDJRrjFwEifxYuTzWv3GXAh62alYugsjeONVr1eu29Lrd8nw1J0H+BqxuyxehjVEEjrB6+iInQQ4HZHi0QGAUBEzWD8lJkEgiN0pYxDMTCOiTXHPXxy1BkpMgMQ+x5Gkfumiyrkm7mZabIP8AZpmxNhTxgIA2mc3cJ8pNkA8Cn/HgldDRFAI3A7MtaJSbIJFIzoKXfeqgVdA1a6uemyCyL4p61vayX/m6NvHcmntqJQhyEbCtXx+F5pUR0Mlf3TF6sIYeJQjyEuCGGsaFzF4h8Grg8tIWlSBILPeW9mp/5emU+L4lzStFkGuBDUoaFrJ6i8ADzeS9yLXuUgTZCLiqty4Lw2ogcBLwrtyCSxEkPrNye3KY4+t4ylxACemytJIEUXbvzbJYEYMOHQGd3xJRkl/hLUmQFwDaIY0WCORCQG8UbU5rnpKklSSIFI5NwyRui0GmQSB5tpTSBDkOODjcGwhkQuD41PFVmiBLACqkEi0QyIFA8kKhpQkiUP4KrJEDnRhz0AhoX2RmagRqEOQVwDWpDYnxBo/ALsBZqVGoQRDZoMmUKuJGCwRSIZAllrMMOoLFHwaOGeG5eCQQGAWBC4HXjfJg22dqESQywLf1VDy/IARWAO7JAVEtgsiW07zVq8vhgBhzbAT+1VyqGnugqQaoSZBY8s3i0sENmvWeSE2CyJO/ADYZnEvD4FQIJN85n1+x2gRZOuW5mVSoxzhuEHgr8J2c2tYmiGy7Gtgwp5Exdi8R0MHERXNbZoEg8RbJ7eV+jr8/cGJu0ywQRDaqbLSK7kQLBEZBoMjbQ4pYIcgM4LFRkIlnAoGmvN8pJZCwQhDZKoPfXsLokOEagewrV5PRsUQQ6RVVqVzHbhHltwYuKSLJ0CfWhL17Ad8qZXzIcYdA1l3zqdCw9gaRjvcBy7hzXShcAgGVRVB5hGLNIkGiMlUx97sSpM8qfV4VbRYJIgB08WWnokiEMOsI6P7Qk6WVtEoQ4RAZUEpHg115ewCn1lDPMkEiXWmNiLAns2pJNssEkasuBray57PQqCACKuqp4p5VmnWCCJS4v14lNEwIPQA4oaYmHggSKUtrRkg92UoPtVY98f+X7IEg0lOVclUxN9pwEND5PH09VG1eCCKQ7gBWqopWCC+FwBbNCe9S8qaV44kgceK3ergUUeB8YPsikkYQ4okgMkf313WPPVo/EdBqlVatzDRvBBFw3wT2NoNgKJISgeWas3gpxxxrLI8EkcG3AyuPZXl0tobA7k2uNFN6eSWIzuWo7JZX/U0FgQFlTM07JuPhOcBif8RAZCdQQSlDlTrUZPNMEAGquYjmJNF8IqAbpEs2XwMmLfBOEIGqG4i6iRjNHwKzrRd27QNBFBbXAev5i49Ba7wr8H3rCPSFIML5TmBF64CHfv9D4CjgUA9Y9IkgskX1sU1tNHkIgsI6ng7MLSyzs7g+EUQgKFfrQ83ErzMo0TEbAlXulY9jTd8IMkGS++NNMk5YZOn7Q2BOlpEzDtpHgggu2XUrsEpG7HIMraQE+kzUfEqnlx9shCwLzGpOM6sWuDe/nQzsmwOw3GN6A7otHio3rbLTFpvyf50JnARcCzzaUkltru0AvBfYuEQpgJb6TTx+EPDFjn2rd+s7QQTw5wE5qXbT2+Ec4CPAjRmU0YabNk4/Yeic2vrA9RlsLTbkEAgiMF8FXFEM1acLOq/5vCiZEVCLFfs0fw6qv1K6/QlYu0ndVFp2UnlDIYhAU9Dok+vlSRGcerC7AJUHU/3u2k2fYvOaz7HcuujoyG4eNgBHBWJIBJnARK/9ywFNdlM23Z/+UrMB9kjKgROOtQ3wdWDNhGNODHUscEiGcasOOUSCTAC+aTMnWH4MD2hirYD7GHD3GOOU7iq/K8/tcc0Rna5xoIWG/WplPSwBWldgSuhWSoZ23j8EHAjMXIhQXQm9DDi+qVFRPetGIpA0T9EexdsA1R3XZ9lUsaFN2Csb+y+wkHUkkf3TDhMEeSY0izcBoqDRypM2HfVPqVzBQ2yKkcEWNgqCDDHkw+aREQiCjAxVPDhEBIIgQ/R62DwyAkGQkaGKB4eIwH8BiW3y2J/F45oAAAAASUVORK5CYII=', - }, - }); - - await prisma.workspace.upsert({ - where: { id: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420' }, - update: {}, - create: { - id: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', - displayName: 'Twenty', - domainName: 'twenty.com', - inviteHash: 'twenty.com-invite-hash', - 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=', - }, - }); -}; diff --git a/server/src/database/typeorm-seeds/core/index.ts b/server/src/database/typeorm-seeds/core/index.ts new file mode 100644 index 000000000..3cb929163 --- /dev/null +++ b/server/src/database/typeorm-seeds/core/index.ts @@ -0,0 +1,10 @@ +import { DataSource } from 'typeorm'; + +import { seedUsers } from 'src/database/typeorm-seeds/core/users'; +import { seedWorkspaces } from 'src/database/typeorm-seeds/core/workspaces'; + +export const seedCoreSchema = async (workspaceDataSource: DataSource) => { + const schemaName = 'core'; + await seedWorkspaces(workspaceDataSource, schemaName); + await seedUsers(workspaceDataSource, schemaName); +}; diff --git a/server/src/database/typeorm-seeds/core/users.ts b/server/src/database/typeorm-seeds/core/users.ts new file mode 100644 index 000000000..a41fe384c --- /dev/null +++ b/server/src/database/typeorm-seeds/core/users.ts @@ -0,0 +1,60 @@ +import { DataSource } from 'typeorm'; + +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; + +const tableName = 'user'; + +export enum SeedUserIds { + Tim = '20202020-9e3b-46d4-a556-88b9ddc2b034', + Jony = '20202020-3957-4908-9c36-2929a23f8357', + Phil = '20202020-7169-42cf-bc47-1cfef15264b8', +} + +export const seedUsers = async ( + workspaceDataSource: DataSource, + schemaName: string, +) => { + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, [ + 'id', + 'firstName', + 'lastName', + 'email', + 'passwordHash', + 'defaultWorkspaceId', + ]) + .orIgnore() + .values([ + { + id: SeedUserIds.Tim, + firstName: 'Tim', + lastName: 'Apple', + email: 'tim@apple.dev', + passwordHash: + '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 + defaultWorkspaceId: SeedWorkspaceId, + }, + { + id: SeedUserIds.Jony, + firstName: 'Jony', + lastName: 'Ive', + email: 'jony.ive@apple.dev', + passwordHash: + '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 + defaultWorkspaceId: SeedWorkspaceId, + }, + , + { + id: SeedUserIds.Phil, + firstName: 'Phil', + lastName: 'Schiler', + email: 'phil.schiler@apple.dev', + passwordHash: + '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 + defaultWorkspaceId: SeedWorkspaceId, + }, + ]) + .execute(); +}; diff --git a/server/src/database/typeorm-seeds/core/workspaces.ts b/server/src/database/typeorm-seeds/core/workspaces.ts new file mode 100644 index 000000000..30de1a908 --- /dev/null +++ b/server/src/database/typeorm-seeds/core/workspaces.ts @@ -0,0 +1,32 @@ +import { DataSource } from 'typeorm'; + +const tableName = 'workspace'; + +export const SeedWorkspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419'; + +export const seedWorkspaces = async ( + workspaceDataSource: DataSource, + schemaName: string, +) => { + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, [ + 'id', + 'displayName', + 'domainName', + 'inviteHash', + 'logo', + ]) + .orIgnore() + .values([ + { + id: SeedWorkspaceId, + displayName: 'Apple', + domainName: 'apple.dev', + inviteHash: 'apple.dev-invite-hash', + logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAELpJREFUeF7tnXnwr3MVx1+WS5Hthoss1R0lNSTUKGQdt6EscVVCKVPKUqmUKcu0WJI2ppJUt0kNwmRN0dBCtolKpqIVIdl3qXnX8xs/1+937/d5vp/lnOc5n3++/zyfzznnfc77+zyf7ZxFiBYIBALTIrBIYBMIBALTIxAEiegIBBaAQBAkwiMQCIJEDIyJgP5IlwRmAreOOZar7vEGceWuYsrOBg4E5gKzgMlxMqiYGZSxxcLLnyDFwU7AF4A1FqL+osB//JnYTeMgSDfc+tLrhcBZwHotDFoMeLLF864fDYK4dl9n5XcBTm3mFW0HWRz4d9tOXp8Pgnj1XDe9d2+Ioc+kri3eIF2Ri35mEdgAuLzjG2N+o2IOYtbNoVhbBGYA1wPrtO24gOcH9dUxKGMTBomHofYE5iVWVKtX43yeJVYn/3BBkPwY15BwXcuVqVF1fBB4zqgP9+G5IEgfvPiUDSsAdwBaacrRrgY2zjGw1TGDIFY9016vjYCr2ndr1eMQ4NhWPZw/HARx7sBG/Z2BMwuY8nzgLwXkmBERBDHjis6KaG/je517t+s4uHgZnMHt4sH809sCFxXS8l5g+UKyzIgJgphxRWtFdI7qpta9unc4Ejiie3efPYMgPv2muxmPFFZdy7ta5h1UC4L4dPcDwNIFVX8YWKqgPDOigiBmXDGyIhcAc0Z+Os2D+wFfSTOUr1GCIL78tTXw4woqD+qA4mR8gyAVoq2jSAVpjXsY2l95Y0ed3XcLgvhx4S+BV1ZQdwng8QpyTYgMgphww0KVeDFw40KfSv/AD4Ad0w/rZ8QgiA9fPQQ8u4Kqg7o9OBW+QZAKUddSpLKNKLFC6XYocFRpodbkBUGseeSZ+uj7P9fx9ems1yZkjTeWOW8EQcy55GkKab9D+x6l2+rALaWFWpQXBLHolad0Kr1jLsknAAfYhqWcdkGQcli3lbQKcFvbTmM+fxew4phj9Kp7EMSuOy8Btiys3qD3PKbCOghSOAJbiCud//alwA0t9BvEo0EQm25+GfDrgqrtC5xcUJ4bUUEQm666ENiukGrK6P6+QrLciQmC2HTZE4B2sXO305saILnluB0/CGLPdSKGCJK7nQu8PrcQ7+MHQex5cENACdpytu8Cb8kpoC9jB0HsefI44OCMaul8lc5ZRRsBgSDICCAVfuQ3gJZcczQVzqlx8DGHLUXGDIIUgbmVEGUOSZ0gQSXTdL6q9M58K8MtPhwEsecVBXNKvyjTuwrolN54tIdsB41SOqKD+OgyBQIpA/kNwDmBcncEgiDdscvVMwVBzmuWcFOMlctOF+MGQey5aZyg/hWwGaBj8tESIBAESQBi4iG6EOQ0YO8K6UgTm25vuCCIPZ+MMkkXiZQGSBebcm8q2kOooEZBkIJgjyhKV11nNitZIoI+l/4O/Aw4A7gCeHTEscZ5TLExcRdeeihpXZe32zg6VO87ZILoctDzgPWbZdC1gdWAZRqv3An8Dris+bfWHkLfAkQEWA94E7A9oJIKz1pIVAoDJXX4M/DTZuNRNdhVP6R3bSgEUSAor+37m0ls1404ff4ogdvnmqpO3ibDKpugNKIfbXbrU/tfxPkRcHTzphNerltqgCyBMQs4vjnOnSttjv5N9S8q4l1ryfhJumgHXee7di10hH4yDDoVINnHACqh4K71jSAigv69dAGoxH2K+R3+W+Cdzb9nzWBYFfgqsEPiXflxbBJZDgJO8fSp2heCKCBUFmDdcTyYuO9PgL2aCXbioaccTnOHTzVBWOPPoY2Nyvk7t9BiQxu9nvGsd4JoUq3a4Pq12rT6oznLYRk+M0QEvbH0GaMSad6aVua2sUwUrwTRZPPKZgXGU1BoUi+iKDlb15ICqhOiVSeRbmVPxi9A1283b1tz5ngkyKebVRhzYLZUSGTRP/9nRzgaoiXpPZv5VV8Tu2nBQyuN+jQ10zwRRP+WWnvvY1JlBYdWwU5s5lLaU9ClKS02KLu7CDKUphMCm1iZyHshyOFDrNE9FEZMYafmbWtZSKBtnSDS7w/A7AEHy5BNf3OzIVsNA8sEWRZQMuVcm3zVQA/BrRComtjOKkFq1eRr5bl4uBgC1SrtWiTIps3xjWLohyAXCFQpKGqNIFtYW+ZzETrDUfIbwD4lzbVEkI2aXfGS9ocsfwh8oNkkLaK5FYLoXoYuBUULBEZBQH+m14zy4LjPWCCINsF0j8CCLuPiGf3LIaDDmdlvVloIyvudHrQrFwohaSoE7m6uJmdFpzZBdERd52+iBQJtECh2bqsmQXYEzm6DSjwbCDQ5ArTaWSQ/QC2CzAAeC3cHAi0R0N2Ri1v2GevxWgS5qcmgMZby0XkwCNwDKMdA8T/VGgSZA1wwGNeGoeMioDeG3hxVWg2CjJI5sAoYIdQcAp8EPl5Tq9IE+Vpzh7qmzSHbBwLKNTyvtqolCaINwewbO7UBDflJEFByO53grd5KEuRSYPPqFocC1hHYAzjVipKlCKJjAS4z61lx1ED00HxD8w4zrRRBLgS2M2N1KGIRgfObBNqmdCtBEOVx0iX8aIHAdAgUOVfVBf4SBImMJF08M6w+SgRYfBNwFIhLEOSJSomkR7E/nqmPwM6Wz+TlJojS9fyxvg9CA6MI3Gw9pVNugig58WuMOifUqo+AsmTqspzZlpsgRY4km0U3FFsQAqoT8g7rEOUkyDpNjT/rGIR+dRDQ6qb5P9CcBDnX4rp2nVgIqfMhoOpX7/aASk6CxOqVhwioo6PSybrYG8tFkDiYWCfwPEi9vim97UHXbKl2VDzyHBcIhJKlEVDe5d+XFtpVXq43iG6BbdVVqejXWwQ0Kdfk3E3LRRCtbev4QLRAYDICKq/m6o8zF0HML99F3FZBYGPg6iqSOwrNQZBlgPs66hPd+o2Ai72PyS7IQZAtgUv67eewrgMCOq3r7rM7B0FU2vjgDgBGl34j8HNAxZFctRwE0Tfmhq5QCGVLILB/U+a6hKxkMnIQRFnwlkumYQzUFwRe1FQsdmVPDoLoCIGrtW5XHvOrbJF6HqnhyUGQWOJN7aV+jJcj1rIjk0PpIEh2t7kUkCPWsgORWunFAJ3ijRYITEbA3RGTCeVTE0Tr3KavUEbcVkFACcv15+mupSZI7KK7C4EiCuurQkWT3LXUBFkJuMMdCqFwbgSCIA3CqwK35kY7xneHQHxiNS5bDbjFnftC4dwIxCS9QXgV4LbcaMf4LhFI/TlfBITUSsccpIjbXApxd9RdKKcmyLLAvS7dF0rnRsB8FsWpAEhNkCiUkzvM/I7vKlnDBMypCRI76X4DOLfm7wG+nFtI6vFTE0TjaUkvWiAwPwKXAa/1Bktqgsj+OKzoLQrK6KsKx/oEd9VyEERvkBzjugI2lJ0SAXcrWTkCOXJiBTumQ2Bdbxn/cxBEO+naUY8WCMyPwBnAbp5gyUGQSDvqKQLK6qrr2Mrs7qblIMhhwJFuEAhFSyOg0xb/LC20q7wcBNkcuLSrQtGv9wicDaiyrYuWgyDLAyoMHy0QmA6BHHGXBe0cisZmYRZX9WrQvYF5HizKQRDZHXshHrxfT0c3NwxzEUR3QnQ3JFogMB0CmodoPmK65SLIyR5qYJv2TP+Vc3ENNxdBYiWr/wGewsKjgENTDJRrjFwEifxYuTzWv3GXAh62alYugsjeONVr1eu29Lrd8nw1J0H+BqxuyxehjVEEjrB6+iInQQ4HZHi0QGAUBEzWD8lJkEgiN0pYxDMTCOiTXHPXxy1BkpMgMQ+x5Gkfumiyrkm7mZabIP8AZpmxNhTxgIA2mc3cJ8pNkA8Cn/HgldDRFAI3A7MtaJSbIJFIzoKXfeqgVdA1a6uemyCyL4p61vayX/m6NvHcmntqJQhyEbCtXx+F5pUR0Mlf3TF6sIYeJQjyEuCGGsaFzF4h8Grg8tIWlSBILPeW9mp/5emU+L4lzStFkGuBDUoaFrJ6i8ADzeS9yLXuUgTZCLiqty4Lw2ogcBLwrtyCSxEkPrNye3KY4+t4ylxACemytJIEUXbvzbJYEYMOHQGd3xJRkl/hLUmQFwDaIY0WCORCQG8UbU5rnpKklSSIFI5NwyRui0GmQSB5tpTSBDkOODjcGwhkQuD41PFVmiBLACqkEi0QyIFA8kKhpQkiUP4KrJEDnRhz0AhoX2RmagRqEOQVwDWpDYnxBo/ALsBZqVGoQRDZoMmUKuJGCwRSIZAllrMMOoLFHwaOGeG5eCQQGAWBC4HXjfJg22dqESQywLf1VDy/IARWAO7JAVEtgsiW07zVq8vhgBhzbAT+1VyqGnugqQaoSZBY8s3i0sENmvWeSE2CyJO/ADYZnEvD4FQIJN85n1+x2gRZOuW5mVSoxzhuEHgr8J2c2tYmiGy7Gtgwp5Exdi8R0MHERXNbZoEg8RbJ7eV+jr8/cGJu0ywQRDaqbLSK7kQLBEZBoMjbQ4pYIcgM4LFRkIlnAoGmvN8pJZCwQhDZKoPfXsLokOEagewrV5PRsUQQ6RVVqVzHbhHltwYuKSLJ0CfWhL17Ad8qZXzIcYdA1l3zqdCw9gaRjvcBy7hzXShcAgGVRVB5hGLNIkGiMlUx97sSpM8qfV4VbRYJIgB08WWnokiEMOsI6P7Qk6WVtEoQ4RAZUEpHg115ewCn1lDPMkEiXWmNiLAns2pJNssEkasuBray57PQqCACKuqp4p5VmnWCCJS4v14lNEwIPQA4oaYmHggSKUtrRkg92UoPtVY98f+X7IEg0lOVclUxN9pwEND5PH09VG1eCCKQ7gBWqopWCC+FwBbNCe9S8qaV44kgceK3ergUUeB8YPsikkYQ4okgMkf313WPPVo/EdBqlVatzDRvBBFw3wT2NoNgKJISgeWas3gpxxxrLI8EkcG3AyuPZXl0tobA7k2uNFN6eSWIzuWo7JZX/U0FgQFlTM07JuPhOcBif8RAZCdQQSlDlTrUZPNMEAGquYjmJNF8IqAbpEs2XwMmLfBOEIGqG4i6iRjNHwKzrRd27QNBFBbXAev5i49Ba7wr8H3rCPSFIML5TmBF64CHfv9D4CjgUA9Y9IkgskX1sU1tNHkIgsI6ng7MLSyzs7g+EUQgKFfrQ83ErzMo0TEbAlXulY9jTd8IMkGS++NNMk5YZOn7Q2BOlpEzDtpHgggu2XUrsEpG7HIMraQE+kzUfEqnlx9shCwLzGpOM6sWuDe/nQzsmwOw3GN6A7otHio3rbLTFpvyf50JnARcCzzaUkltru0AvBfYuEQpgJb6TTx+EPDFjn2rd+s7QQTw5wE5qXbT2+Ec4CPAjRmU0YabNk4/Yeic2vrA9RlsLTbkEAgiMF8FXFEM1acLOq/5vCiZEVCLFfs0fw6qv1K6/QlYu0ndVFp2UnlDIYhAU9Dok+vlSRGcerC7AJUHU/3u2k2fYvOaz7HcuujoyG4eNgBHBWJIBJnARK/9ywFNdlM23Z/+UrMB9kjKgROOtQ3wdWDNhGNODHUscEiGcasOOUSCTAC+aTMnWH4MD2hirYD7GHD3GOOU7iq/K8/tcc0Rna5xoIWG/WplPSwBWldgSuhWSoZ23j8EHAjMXIhQXQm9DDi+qVFRPetGIpA0T9EexdsA1R3XZ9lUsaFN2Csb+y+wkHUkkf3TDhMEeSY0izcBoqDRypM2HfVPqVzBQ2yKkcEWNgqCDDHkw+aREQiCjAxVPDhEBIIgQ/R62DwyAkGQkaGKB4eIwH8BiW3y2J/F45oAAAAASUVORK5CYII=', + }, + ]) + .execute(); +}; diff --git a/server/src/database/typeorm-seeds/metadata/data-source.ts b/server/src/database/typeorm-seeds/metadata/data-source.ts new file mode 100644 index 000000000..48bc6d181 --- /dev/null +++ b/server/src/database/typeorm-seeds/metadata/data-source.ts @@ -0,0 +1,33 @@ +import { DataSource } from 'typeorm'; + +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; + +export const SeedWorkspaceSchemaName = 'workspace_1wgvd1injqtife6y4rvfbu3h5'; + +const tableName = 'dataSource'; + +export const SeedDataSourceId = '20202020-7f63-47a9-b1b3-6c7290ca9fb1'; + +export const seedDataSource = async ( + workspaceDataSource: DataSource, + schemaName: string, +) => { + await workspaceDataSource.query( + `CREATE SCHEMA IF NOT EXISTS ${SeedWorkspaceSchemaName}`, + ); + + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, ['id', 'schema', 'type', 'workspaceId']) + .orIgnore() + .values([ + { + id: SeedDataSourceId, + schema: SeedWorkspaceSchemaName, + type: 'postgres', + workspaceId: SeedWorkspaceId, + }, + ]) + .execute(); +}; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/activity-target.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/activity-target.ts index 03432e098..e16cd8ea3 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/activity-target.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/activity-target.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/activity.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/activity.ts index 8c2335f15..9440bd580 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/activity.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/activity.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/api-key.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/api-key.ts index 6be643f82..2fe62c37d 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/api-key.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/api-key.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/attachment.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/attachment.ts index 0db186598..6d0bcc2d7 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/attachment.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/attachment.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/comment.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/comment.ts index 753416f23..4dfa110f8 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/comment.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/comment.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/company.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/company.ts index cb884e53d..fecd9558b 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/company.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/company.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/favorite.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/favorite.ts index dcb59c268..615943bbf 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/favorite.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/favorite.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; @@ -17,8 +17,7 @@ export enum SeedFavoriteFieldMetadataIds { WorkspaceMemberForeignKey = '20202020-0f4c-4b9a-9b9a-917a68161a4f', Person = '20202020-0876-4735-8974-ff4d51aafa07', PersonForeignKey = '20202020-0876-4735-9473-ff4d51aa4e7b', - Company = '20202020-09e1-4384-ae3e-39e7956396fe', - CompanyV2 = '20202020-09e1-4384-ae3e-39e7956396ff', + Company = '20202020-09e1-4384-ae3e-39e7956396ff', CompanyForeignKey = '20202020-09e1-4384-ae3e-45e79563d528', } diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/opportunity.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/opportunity.ts index 69f00c8f8..a503628b5 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/opportunity.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/opportunity.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/person.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/person.ts index 535d2f52c..b3a028c58 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/person.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/person.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/pipeline-step.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/pipeline-step.ts index 244c069fc..b66fb3085 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/pipeline-step.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/pipeline-step.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/view-field.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/view-field.ts index f85e747bb..19a0c60f1 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/view-field.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/view-field.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/view-filter.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/view-filter.ts index 73056d454..958386e94 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/view-filter.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/view-filter.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/view-sort.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/view-sort.ts index 708e312da..ccf971fb5 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/view-sort.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/view-sort.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/view.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/view.ts index 257c0e123..1e85d3512 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/view.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/view.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/webhook.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/webhook.ts index a657cf158..e8cf14bb7 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/webhook.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/webhook.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata/workspace-member.ts b/server/src/database/typeorm-seeds/metadata/field-metadata/workspace-member.ts index cc969ab85..36e68510e 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata/workspace-member.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata/workspace-member.ts @@ -1,8 +1,8 @@ import { DataSource } from 'typeorm'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const fieldMetadataTableName = 'fieldMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/index.ts b/server/src/database/typeorm-seeds/metadata/index.ts index b4277f129..37fe3aebd 100644 --- a/server/src/database/typeorm-seeds/metadata/index.ts +++ b/server/src/database/typeorm-seeds/metadata/index.ts @@ -22,11 +22,11 @@ import { seedActivityRelationMetadata } from 'src/database/typeorm-seeds/metadat import { seedPipelineStepRelationMetadata } from 'src/database/typeorm-seeds/metadata/relation-metadata/pipeline-step'; import { seedPersonRelationMetadata } from 'src/database/typeorm-seeds/metadata/relation-metadata/person'; import { seedWorkspaceMemberRelationMetadata } from 'src/database/typeorm-seeds/metadata/relation-metadata/workspace-member'; +import { seedDataSource } from 'src/database/typeorm-seeds/metadata/data-source'; -export const seedMetadataSchema = async ( - workspaceDataSource: DataSource, - schemaName: string, -) => { +export const seedMetadataSchema = async (workspaceDataSource: DataSource) => { + const schemaName = 'metadata'; + await seedDataSource(workspaceDataSource, schemaName); await seedObjectMetadata(workspaceDataSource, schemaName); await seedActivityTargetFieldMetadata(workspaceDataSource, schemaName); diff --git a/server/src/database/typeorm-seeds/metadata/object-metadata.ts b/server/src/database/typeorm-seeds/metadata/object-metadata.ts index 1952fbffe..4d02be734 100644 --- a/server/src/database/typeorm-seeds/metadata/object-metadata.ts +++ b/server/src/database/typeorm-seeds/metadata/object-metadata.ts @@ -1,6 +1,7 @@ import { DataSource } from 'typeorm'; -import { SeedDataSourceId, SeedWorkspaceId } from 'src/database/seeds/metadata'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; +import { SeedDataSourceId } from 'src/database/typeorm-seeds/metadata/data-source'; const tableName = 'objectMetadata'; @@ -48,8 +49,8 @@ export const seedObjectMetadata = async ( .values([ { id: SeedObjectMetadataIds.Company, - nameSingular: 'companyV2', - namePlural: 'companiesV2', + nameSingular: 'company', + namePlural: 'companies', labelSingular: 'Company', labelPlural: 'Companies', targetTableName: 'company', @@ -62,8 +63,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Person, - nameSingular: 'personV2', - namePlural: 'peopleV2', + nameSingular: 'person', + namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', targetTableName: 'person', @@ -76,8 +77,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Opportunity, - nameSingular: 'opportunityV2', - namePlural: 'opportunitiesV2', + nameSingular: 'opportunity', + namePlural: 'opportunities', labelSingular: 'Opportunity', labelPlural: 'Opportunities', targetTableName: 'opportunity', @@ -90,8 +91,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.PipelineStep, - nameSingular: 'pipelineStepV2', - namePlural: 'pipelineStepsV2', + nameSingular: 'pipelineStep', + namePlural: 'pipelineSteps', labelSingular: 'Pipeline Step', labelPlural: 'Pipeline Steps', targetTableName: 'pipelineStep', @@ -104,8 +105,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.WorkspaceMember, - nameSingular: 'workspaceMemberV2', - namePlural: 'workspaceMembersV2', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', labelSingular: 'Workspace Member', labelPlural: 'Workspace Members', targetTableName: 'workspaceMember', @@ -118,8 +119,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Webhook, - nameSingular: 'webhookV2', - namePlural: 'webhooksV2', + nameSingular: 'webhook', + namePlural: 'webhooks', labelSingular: 'Webhook', labelPlural: 'Webhooks', targetTableName: 'webhook', @@ -132,8 +133,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.ApiKey, - nameSingular: 'apiKeyV2', - namePlural: 'apiKeysV2', + nameSingular: 'apiKey', + namePlural: 'apiKeys', labelSingular: 'Api Key', labelPlural: 'Api Keys', targetTableName: 'apiKey', @@ -146,8 +147,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Activity, - nameSingular: 'activityV2', - namePlural: 'activitiesV2', + nameSingular: 'activity', + namePlural: 'activities', labelSingular: 'Activity', labelPlural: 'Activities', targetTableName: 'activity', @@ -160,8 +161,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.ActivityTarget, - nameSingular: 'activityTargetV2', - namePlural: 'activityTargetsV2', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', labelSingular: 'Activity Target', labelPlural: 'Activity Targets', targetTableName: 'activityTarget', @@ -174,8 +175,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Comment, - nameSingular: 'commentV2', - namePlural: 'commentsV2', + nameSingular: 'comment', + namePlural: 'comments', labelSingular: 'Comment', labelPlural: 'Comments', targetTableName: 'comment', @@ -188,8 +189,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Attachment, - nameSingular: 'attachmentV2', - namePlural: 'attachmentsV2', + nameSingular: 'attachment', + namePlural: 'attachments', labelSingular: 'Attachment', labelPlural: 'Attachments', targetTableName: 'attachment', @@ -202,8 +203,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.Favorite, - nameSingular: 'favoriteV2', - namePlural: 'favoritesV2', + nameSingular: 'favorite', + namePlural: 'favorites', labelSingular: 'Favorite', labelPlural: 'Favorites', targetTableName: 'favorite', @@ -216,8 +217,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.View, - nameSingular: 'viewV2', - namePlural: 'viewsV2', + nameSingular: 'view', + namePlural: 'views', labelSingular: 'View', labelPlural: 'Views', targetTableName: 'view', @@ -230,8 +231,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.ViewField, - nameSingular: 'viewFieldV2', - namePlural: 'viewFieldsV2', + nameSingular: 'viewField', + namePlural: 'viewFields', labelSingular: 'View Field', labelPlural: 'View Fields', targetTableName: 'viewField', @@ -244,8 +245,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.ViewFilter, - nameSingular: 'viewFilterV2', - namePlural: 'viewFiltersV2', + nameSingular: 'viewFilter', + namePlural: 'viewFilters', labelSingular: 'View Filter', labelPlural: 'View Filters', targetTableName: 'viewFilter', @@ -258,8 +259,8 @@ export const seedObjectMetadata = async ( }, { id: SeedObjectMetadataIds.ViewSort, - nameSingular: 'viewSortV2', - namePlural: 'viewSortsV2', + nameSingular: 'viewSort', + namePlural: 'viewSorts', labelSingular: 'View Sort', labelPlural: 'View Sorts', targetTableName: 'viewSort', diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/activity.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/activity.ts index 1abf0d9ab..c507e0e97 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/activity.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/activity.ts @@ -2,11 +2,11 @@ import { DataSource } from 'typeorm'; import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedActivityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/activity'; import { SeedActivityTargetFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/activity-target'; import { SeedAttachmentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/attachment'; import { SeedCommentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/comment'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/company.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/company.ts index 9bf05755c..78a660d55 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/company.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/company.ts @@ -2,13 +2,13 @@ import { DataSource } from 'typeorm'; import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedCompanyFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/company'; import { SeedPersonFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/person'; import { SeedFavoriteFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/favorite'; import { SeedAttachmentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/attachment'; import { SeedOpportunityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/opportunity'; import { SeedActivityTargetFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/activity-target'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/person.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/person.ts index a51516769..cb51e0b45 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/person.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/person.ts @@ -2,12 +2,12 @@ import { DataSource } from 'typeorm'; import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedFavoriteFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/favorite'; import { SeedPersonFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/person'; import { SeedActivityTargetFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/activity-target'; import { SeedAttachmentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/attachment'; import { SeedOpportunityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/opportunity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/pipeline-step.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/pipeline-step.ts index 0c531f17d..baa4c449b 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/pipeline-step.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/pipeline-step.ts @@ -2,9 +2,9 @@ import { DataSource } from 'typeorm'; import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedPipelineStepFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/pipeline-step'; import { SeedOpportunityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/opportunity'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/view.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/view.ts index d418c254b..2a2c0d07f 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/view.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/view.ts @@ -4,9 +4,9 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; import { SeedViewFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/view'; import { SeedViewFieldFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/view-field'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedViewFilterFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/view-filter'; import { SeedViewSortFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/view-sort'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/metadata/relation-metadata/workspace-member.ts b/server/src/database/typeorm-seeds/metadata/relation-metadata/workspace-member.ts index 4c179ad8b..404df06b3 100644 --- a/server/src/database/typeorm-seeds/metadata/relation-metadata/workspace-member.ts +++ b/server/src/database/typeorm-seeds/metadata/relation-metadata/workspace-member.ts @@ -2,13 +2,13 @@ import { DataSource } from 'typeorm'; import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; import { SeedCompanyFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/company'; import { SeedWorkspaceMemberFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/workspace-member'; import { SeedFavoriteFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/favorite'; import { SeedActivityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/activity'; import { SeedCommentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/comment'; import { SeedAttachmentFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/attachment'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; const tableName = 'relationMetadata'; diff --git a/server/src/database/typeorm-seeds/workspace/workspaceMember.ts b/server/src/database/typeorm-seeds/workspace/workspaceMember.ts index 6430125e8..03e8508f8 100644 --- a/server/src/database/typeorm-seeds/workspace/workspaceMember.ts +++ b/server/src/database/typeorm-seeds/workspace/workspaceMember.ts @@ -1,5 +1,7 @@ import { DataSource } from 'typeorm'; +import { SeedUserIds } from 'src/database/typeorm-seeds/core/users'; + const tableName = 'workspaceMember'; const WorkspaceMemberIds = { @@ -8,12 +10,6 @@ const WorkspaceMemberIds = { Phil: '20202020-1553-45c6-a028-5a9064cce07f', }; -const WorkspaceMemberUserIds = { - Tim: '20202020-a838-4fa9-b59b-96409b9a1c30', - Jony: '20202020-c231-45c5-b9f2-cf8b70191f6d', - Phil: '20202020-ef2e-45df-b677-32fa06d4bd2a', -}; - export const seedWorkspaceMember = async ( workspaceDataSource: DataSource, schemaName: string, @@ -39,7 +35,7 @@ export const seedWorkspaceMember = async ( locale: 'en', colorScheme: 'Light', allowImpersonation: true, - userId: WorkspaceMemberUserIds.Tim, + userId: SeedUserIds.Tim, }, { id: WorkspaceMemberIds.Jony, @@ -48,7 +44,7 @@ export const seedWorkspaceMember = async ( locale: 'en', colorScheme: 'Light', allowImpersonation: true, - userId: WorkspaceMemberUserIds.Jony, + userId: SeedUserIds.Jony, }, { id: WorkspaceMemberIds.Phil, @@ -57,7 +53,7 @@ export const seedWorkspaceMember = async ( locale: 'en', colorScheme: 'Light', allowImpersonation: true, - userId: WorkspaceMemberUserIds.Tim, + userId: SeedUserIds.Phil, }, ]) .execute(); diff --git a/server/src/database/typeorm/core/migrations/1700324860820-setupCoreTables.ts b/server/src/database/typeorm/core/migrations/1700324860820-setupCoreTables.ts new file mode 100644 index 000000000..abbcd1748 --- /dev/null +++ b/server/src/database/typeorm/core/migrations/1700324860820-setupCoreTables.ts @@ -0,0 +1,35 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class SetupCoreTables implements MigrationInterface { + name = 'SetupCoreTables1700324860820'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "core"."refreshToken" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "deletedAt" TIMESTAMP WITH TIME ZONE, "revokedAt" TIMESTAMP WITH TIME ZONE, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_7d8bee0204106019488c4c50ffa" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "core"."workspace" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "domainName" character varying, "displayName" character varying, "logo" character varying, "inviteHash" character varying, "deletedAt" TIMESTAMP, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_098656ae401f3e1a4586f47fd8e" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "core"."user" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "firstName" character varying NOT NULL DEFAULT '', "lastName" character varying NOT NULL DEFAULT '', "email" character varying NOT NULL, "emailVerified" boolean NOT NULL DEFAULT false, "disabled" boolean NOT NULL DEFAULT false, "passwordHash" character varying, "canImpersonate" boolean NOT NULL DEFAULT false, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP, "defaultWorkspaceId" uuid, CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "core"."refreshToken" ADD CONSTRAINT "FK_610102b60fea1455310ccd299de" FOREIGN KEY ("userId") REFERENCES "core"."user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "core"."user" ADD CONSTRAINT "FK_5d77e050eabd28d203b301235a7" FOREIGN KEY ("defaultWorkspaceId") REFERENCES "core"."workspace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "core"."user" DROP CONSTRAINT "FK_5d77e050eabd28d203b301235a7"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."refreshToken" DROP CONSTRAINT "FK_610102b60fea1455310ccd299de"`, + ); + await queryRunner.query(`DROP TABLE "core"."user"`); + await queryRunner.query(`DROP TABLE "core"."workspace"`); + await queryRunner.query(`DROP TABLE "core"."refreshToken"`); + } +} diff --git a/server/src/database/typeorm/metadata/metadata.datasource.ts b/server/src/database/typeorm/metadata/metadata.datasource.ts index 9be4ff2db..a0d50e630 100644 --- a/server/src/database/typeorm/metadata/metadata.datasource.ts +++ b/server/src/database/typeorm/metadata/metadata.datasource.ts @@ -10,11 +10,17 @@ export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = { type: 'postgres', logging: ['error'], schema: 'metadata', - entities: ['dist/src/metadata/**/*.entity{.ts,.js}'], + entities: [ + 'dist/src/metadata/**/*.entity{.ts,.js}', + 'dist/src/core/**/*.entity{.ts,.js}', + ], synchronize: false, migrationsRun: false, migrationsTableName: '_typeorm_migrations', - migrations: [__dirname + '/migrations/*{.ts,.js}'], + migrations: [ + 'dist/src/database/typeorm/metadata/migrations/*{.ts,.js}', + 'dist/src/database/typeorm/core/migrations/*{.ts,.js}', + ], }; export const connectionSource = new DataSource( typeORMMetadataModuleOptions as DataSourceOptions, diff --git a/server/src/database/typeorm/typeorm.service.ts b/server/src/database/typeorm/typeorm.service.ts index 5159d8d90..3fb17f016 100644 --- a/server/src/database/typeorm/typeorm.service.ts +++ b/server/src/database/typeorm/typeorm.service.ts @@ -4,6 +4,9 @@ import { DataSource } from 'typeorm'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity'; +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; +import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; @Injectable() export class TypeORMService implements OnModuleInit, OnModuleDestroy { @@ -15,10 +18,15 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { url: environmentService.getPGDatabaseUrl(), type: 'postgres', logging: false, - schema: 'public', + schema: 'core', + entities: [User, Workspace, RefreshToken], }); } + public async getMainDataSource(): Promise { + return this.mainDataSource; + } + /** * Connects to a data source using metadata. Returns a cached connection if it exists. * @param dataSource DataSourceEntity diff --git a/server/src/decorators/check-abilities.decorator.ts b/server/src/decorators/check-abilities.decorator.ts deleted file mode 100644 index f50916d6c..000000000 --- a/server/src/decorators/check-abilities.decorator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { SetMetadata } from '@nestjs/common'; - -import { AbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -export const CHECK_ABILITIES_KEY = 'check_abilities'; -export const CheckAbilities = (...handlers: AbilityHandler[]) => - SetMetadata(CHECK_ABILITIES_KEY, handlers); diff --git a/server/src/decorators/prisma-select.decorator.ts b/server/src/decorators/prisma-select.decorator.ts deleted file mode 100644 index 7984dc2c1..000000000 --- a/server/src/decorators/prisma-select.decorator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { createParamDecorator, ExecutionContext } from '@nestjs/common'; -import { GqlExecutionContext } from '@nestjs/graphql'; - -import merge from 'lodash.merge'; - -import { - PrismaSelect, - ModelSelectMap, - DefaultFieldsMap, -} from 'src/utils/prisma-select'; - -export { PrismaSelect }; - -const globalDefaultFields: DefaultFieldsMap = { - User: { - // Needed for displayName resolve field - firstName: true, - lastName: true, - }, - Person: { - // Needed for displayName resolve field - firstName: true, - lastName: true, - }, -}; - -export const PrismaSelector = createParamDecorator( - ( - data: { - modelName: keyof ModelSelectMap; - defaultFields?: DefaultFieldsMap; - }, - ctx: ExecutionContext, - ): PrismaSelect => { - const gqlCtx = GqlExecutionContext.create(ctx); - const info = gqlCtx.getInfo(); - - return new PrismaSelect(data.modelName, info, { - defaultFields: merge(globalDefaultFields, data.defaultFields), - }); - }, -); diff --git a/server/src/filters/exception.filter.ts b/server/src/filters/exception.filter.ts index a55f9a3be..f175e48cd 100644 --- a/server/src/filters/exception.filter.ts +++ b/server/src/filters/exception.filter.ts @@ -1,19 +1,11 @@ import { Catch, UnauthorizedException } from '@nestjs/common'; import { GqlExceptionFilter } from '@nestjs/graphql'; -import { Prisma } from '@prisma/client'; import { GraphQLError } from 'graphql'; @Catch() export class ExceptionFilter implements GqlExceptionFilter { catch(exception: Error) { - if (exception instanceof Prisma.PrismaClientValidationError) { - throw new GraphQLError('Invalid request', { - extensions: { - code: 'INVALID_REQUEST', - }, - }); - } if (exception instanceof UnauthorizedException) { throw new GraphQLError('Unauthorized', { extensions: { diff --git a/server/src/guards/ability.guard.ts b/server/src/guards/ability.guard.ts deleted file mode 100644 index 4b7a626e7..000000000 --- a/server/src/guards/ability.guard.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - CanActivate, - ExecutionContext, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; -import { ModuleRef, Reflector } from '@nestjs/core'; - -import { AbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; - -import { PassportUser } from 'src/core/auth/strategies/jwt.auth.strategy'; -import { CHECK_ABILITIES_KEY } from 'src/decorators/check-abilities.decorator'; -import { AbilityFactory, AppAbility } from 'src/ability/ability.factory'; -import { assert } from 'src/utils/assert'; -import { getRequest } from 'src/utils/extract-request'; - -@Injectable() -export class AbilityGuard implements CanActivate { - constructor( - private readonly reflector: Reflector, - private readonly abilityFactory: AbilityFactory, - private readonly moduleRef: ModuleRef, - ) {} - - async canActivate(context: ExecutionContext): Promise { - const handlers = - this.reflector.get( - CHECK_ABILITIES_KEY, - context.getHandler(), - ) || []; - - const request = getRequest(context); - const passportUser = request?.user as PassportUser | null | undefined; - - assert(passportUser, '', UnauthorizedException); - - const ability = this.abilityFactory.defineAbility( - passportUser.workspace, - passportUser.user, - ); - - request.ability = ability; - - for (const handler of handlers) { - const result = await this._execAbilityHandler(handler, ability, context); - - if (!result) { - return false; - } - } - - return true; - } - - private async _execAbilityHandler( - abilityHandler: AbilityHandler, - ability: AppAbility, - context: ExecutionContext, - ) { - const handler = this.moduleRef.get(abilityHandler, { strict: false }); - - if (!handler) { - throw new Error(`Handler of type ${abilityHandler.name} not provided`); - } - - const res = await handler.handle(ability, context); - - return res; - } -} diff --git a/server/src/health/health.controller.spec.ts b/server/src/health/health.controller.spec.ts index b94903842..796656f80 100644 --- a/server/src/health/health.controller.spec.ts +++ b/server/src/health/health.controller.spec.ts @@ -2,7 +2,6 @@ import { HealthCheckService, HttpHealthIndicator } from '@nestjs/terminus'; import { Test, TestingModule } from '@nestjs/testing'; import { HealthController } from 'src/health/health.controller'; -import { PrismaHealthIndicator } from 'src/health/indicators/prisma-health-indicator'; describe('HealthController', () => { let healthController: HealthController; @@ -16,10 +15,6 @@ describe('HealthController', () => { provide: HealthCheckService, useValue: {}, }, - { - provide: PrismaHealthIndicator, - useValue: {}, - }, { provide: HttpHealthIndicator, useValue: {}, diff --git a/server/src/health/health.controller.ts b/server/src/health/health.controller.ts index 76f412d49..ee106fc38 100644 --- a/server/src/health/health.controller.ts +++ b/server/src/health/health.controller.ts @@ -1,20 +1,13 @@ import { Controller, Get } from '@nestjs/common'; import { HealthCheck, HealthCheckService } from '@nestjs/terminus'; -import { PrismaHealthIndicator } from 'src/health/indicators/prisma-health-indicator'; - @Controller('healthz') export class HealthController { - constructor( - private health: HealthCheckService, - private prismaHealthIndicator: PrismaHealthIndicator, - ) {} + constructor(private health: HealthCheckService) {} @Get() @HealthCheck() check() { - return this.health.check([ - () => this.prismaHealthIndicator.isDatabaseInstanceHealthy('database'), - ]); + return this.health.check([]); } } diff --git a/server/src/health/health.module.ts b/server/src/health/health.module.ts index 17bbcc6ad..bbdb35114 100644 --- a/server/src/health/health.module.ts +++ b/server/src/health/health.module.ts @@ -1,13 +1,10 @@ import { Module } from '@nestjs/common'; import { TerminusModule } from '@nestjs/terminus'; -import { PrismaModule } from 'src/database/prisma.module'; import { HealthController } from 'src/health/health.controller'; -import { PrismaHealthIndicator } from 'src/health/indicators/prisma-health-indicator'; @Module({ - imports: [TerminusModule, PrismaModule], + imports: [TerminusModule], controllers: [HealthController], - providers: [PrismaHealthIndicator], }) export class HealthModule {} diff --git a/server/src/health/indicators/prisma-health-indicator.ts b/server/src/health/indicators/prisma-health-indicator.ts deleted file mode 100644 index 316a0bc50..000000000 --- a/server/src/health/indicators/prisma-health-indicator.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { - HealthCheckError, - HealthIndicator, - HealthIndicatorResult, -} from '@nestjs/terminus'; - -import { PrismaService } from 'src/database/prisma.service'; - -@Injectable() -export class PrismaHealthIndicator extends HealthIndicator { - constructor(private readonly prismaService: PrismaService) { - super(); - } - - async isDatabaseInstanceHealthy(key: string): Promise { - try { - await this.prismaService.client.$queryRaw`SELECT 1`; - return this.getStatus(key, true); - } catch (e) { - throw new HealthCheckError('Prisma check failed', e); - } - } -} diff --git a/server/src/integrations/environment/environment.module-definition.ts b/server/src/integrations/environment/environment.module-definition.ts index 588556499..242e2ef3c 100644 --- a/server/src/integrations/environment/environment.module-definition.ts +++ b/server/src/integrations/environment/environment.module-definition.ts @@ -2,7 +2,7 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder({ - moduleName: 'Prisma', + moduleName: 'Environment', }) .setClassMethodName('forRoot') .build(); diff --git a/server/src/metadata/field-metadata/dtos/create-field.input.ts b/server/src/metadata/field-metadata/dtos/create-field.input.ts index a3a492007..831c5c982 100644 --- a/server/src/metadata/field-metadata/dtos/create-field.input.ts +++ b/server/src/metadata/field-metadata/dtos/create-field.input.ts @@ -9,7 +9,7 @@ import { IsString, IsUUID, } from 'class-validator'; -import { GraphQLJSONObject } from 'graphql-type-json'; +import graphqlTypeJson from 'graphql-type-json'; import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; import { FieldMetadataDefaultValue } from 'src/metadata/field-metadata/interfaces/field-metadata-default-value.interface'; @@ -57,7 +57,7 @@ export class CreateFieldInput { @IsDefaultValue({ message: 'Invalid default value for the specified type' }) @IsOptional() - @Field(() => GraphQLJSONObject, { nullable: true }) + @Field(() => graphqlTypeJson, { nullable: true }) defaultValue: FieldMetadataDefaultValue; @HideField() diff --git a/server/src/metadata/object-metadata/object-metadata.module.ts b/server/src/metadata/object-metadata/object-metadata.module.ts index 685f233d4..a68e00fa7 100644 --- a/server/src/metadata/object-metadata/object-metadata.module.ts +++ b/server/src/metadata/object-metadata/object-metadata.module.ts @@ -11,6 +11,7 @@ import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; import { WorkspaceMigrationRunnerModule } from 'src/workspace/workspace-migration-runner/workspace-migration-runner.module'; import { WorkspaceMigrationModule } from 'src/metadata/workspace-migration/workspace-migration.module'; import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; +import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { ObjectMetadataService } from './object-metadata.service'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -23,6 +24,7 @@ import { ObjectMetadataDTO } from './dtos/object-metadata.dto'; imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ + TypeORMModule, NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), DataSourceModule, WorkspaceMigrationModule, diff --git a/server/src/metadata/object-metadata/object-metadata.service.ts b/server/src/metadata/object-metadata/object-metadata.service.ts index 6b57f273a..b6dcb0a16 100644 --- a/server/src/metadata/object-metadata/object-metadata.service.ts +++ b/server/src/metadata/object-metadata/object-metadata.service.ts @@ -16,6 +16,8 @@ import { WorkspaceMigrationTableAction, } from 'src/metadata/workspace-migration/workspace-migration.entity'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -27,6 +29,8 @@ export class ObjectMetadataService extends TypeOrmQueryService, + private readonly dataSourceService: DataSourceService, + private readonly typeORMService: TypeORMService, private readonly workspaceMigrationService: WorkspaceMigrationService, private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, ) { @@ -74,7 +78,7 @@ export class ObjectMetadataService extends TypeOrmQueryService { + if (field.name === 'id') { + return; + } + + await workspaceDataSource?.query( + `INSERT INTO ${dataSourceMetadata.schema}."viewField" + ("fieldMetadataId", "position", "isVisible", "size", "viewId") + VALUES ('${field.id}', '${index}', true, 180, '${view[0].id}') RETURNING *`, + ); + }); + return createdObjectMetadata; } diff --git a/server/src/utils/prisma-select/index.ts b/server/src/utils/prisma-select/index.ts deleted file mode 100644 index 525c5168a..000000000 --- a/server/src/utils/prisma-select/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { PrismaSelect as PalJSPrismaSelect } from '@paljs/plugins'; -import { DMMF } from '@prisma/client/runtime'; -import { GraphQLResolveInfo } from 'graphql'; - -import { ModelSelectMap } from './model-select-map'; - -export type DefaultFieldsMap = { - readonly [K in keyof ModelSelectMap]?: - | ModelSelectMap[K] - | ((select: any) => ModelSelectMap[K]); -}; - -export { ModelSelectMap }; - -export class PrismaSelect< - K extends keyof ModelSelectMap, -> extends PalJSPrismaSelect { - private modelName: K; - - constructor( - modelName: K, - info: GraphQLResolveInfo, - options?: { - readonly defaultFields?: DefaultFieldsMap; - readonly dmmf?: readonly Pick[]; - }, - ) { - super(info, options as any); - this.modelName = modelName; - } - - get value(): ModelSelectMap[K] { - return super.value; - } - - valueOf(field: string, mergeObject?: any): ModelSelectMap[K]; - valueOf( - field: string, - filterBy: SubKey, - mergeObject?: any, - ): ModelSelectMap[SubKey]; - valueOf( - field: string, - filterByOrMergeObject?: keyof ModelSelectMap | any, - mergeObject?: any, - ) { - if (typeof filterByOrMergeObject === 'string') { - return super.valueOf(field, filterByOrMergeObject, mergeObject).select; - } else { - return super.valueOf(field, this.modelName, filterByOrMergeObject).select; - } - } - - valueWithFilter(modelName: K): ModelSelectMap[K] { - return super.valueWithFilter(modelName).select; - } -} diff --git a/server/src/utils/prisma-select/model-select-map.ts b/server/src/utils/prisma-select/model-select-map.ts deleted file mode 100644 index 76c65a6cb..000000000 --- a/server/src/utils/prisma-select/model-select-map.ts +++ /dev/null @@ -1,22 +0,0 @@ -// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -import { Prisma } from '@prisma/client'; - -export type ModelSelectMap = { - User: Prisma.UserSelect; - UserSettings: Prisma.UserSettingsSelect; - Workspace: Prisma.WorkspaceSelect; - WorkspaceMember: Prisma.WorkspaceMemberSelect; - Company: Prisma.CompanySelect; - Person: Prisma.PersonSelect; - RefreshToken: Prisma.RefreshTokenSelect; - Activity: Prisma.ActivitySelect; - Comment: Prisma.CommentSelect; - ActivityTarget: Prisma.ActivityTargetSelect; - Pipeline: Prisma.PipelineSelect; - PipelineStage: Prisma.PipelineStageSelect; - PipelineProgress: Prisma.PipelineProgressSelect; - Attachment: Prisma.AttachmentSelect; - Favorite: Prisma.FavoriteSelect; - ApiKey: Prisma.ApiKeySelect; - WebHook: Prisma.WebHookSelect; -}; diff --git a/server/src/workspace/workspace-manager/standard-objects-prefill-data/view.ts b/server/src/workspace/workspace-manager/standard-objects-prefill-data/view.ts index 1affd9083..c7918e1b5 100644 --- a/server/src/workspace/workspace-manager/standard-objects-prefill-data/view.ts +++ b/server/src/workspace/workspace-manager/standard-objects-prefill-data/view.ts @@ -30,18 +30,18 @@ export const viewPrefillData = async ( type: 'kanban', }, { - name: 'All Companies (V2)', - objectMetadataId: objectMetadataMap['companyV2'].id, + name: 'All Companies', + objectMetadataId: objectMetadataMap['company'].id, type: 'table', }, { - name: 'All People (V2)', - objectMetadataId: objectMetadataMap['personV2'].id, + name: 'All People', + objectMetadataId: objectMetadataMap['person'].id, type: 'table', }, { - name: 'All Opportunities (V2)', - objectMetadataId: objectMetadataMap['companyV2'].id, + name: 'All Opportunities', + objectMetadataId: objectMetadataMap['company'].id, type: 'kanban', }, ]) @@ -66,116 +66,88 @@ export const viewPrefillData = async ( ]) .orIgnore() .values([ - // CompanyV2 + // Company { - fieldMetadataId: objectMetadataMap['companyV2'].fields['name'], - viewId: viewIdMap['All Companies (V2)'], + fieldMetadataId: objectMetadataMap['company'].fields['name'], + viewId: viewIdMap['All Companies'], position: 0, isVisible: true, size: 180, }, { - fieldMetadataId: objectMetadataMap['companyV2'].fields['domainName'], - viewId: viewIdMap['All Companies (V2)'], + fieldMetadataId: objectMetadataMap['company'].fields['domainName'], + viewId: viewIdMap['All Companies'], 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)'], + fieldMetadataId: objectMetadataMap['company'].fields['employees'], + viewId: viewIdMap['All Companies'], position: 4, isVisible: true, size: 150, }, { - fieldMetadataId: objectMetadataMap['companyV2'].fields['linkedinLink'], - viewId: viewIdMap['All Companies (V2)'], + fieldMetadataId: objectMetadataMap['company'].fields['linkedinLink'], + viewId: viewIdMap['All Companies'], position: 5, isVisible: true, size: 170, }, { - fieldMetadataId: objectMetadataMap['companyV2'].fields['address'], - viewId: viewIdMap['All Companies (V2)'], + fieldMetadataId: objectMetadataMap['company'].fields['address'], + viewId: viewIdMap['All Companies'], position: 6, isVisible: true, size: 170, }, - // PeopleV2 + // Person { - fieldMetadataId: objectMetadataMap['personV2'].fields['firstName'], // TODO: change to displayName once we have name field type - viewId: viewIdMap['All People (V2)'], + fieldMetadataId: objectMetadataMap['person'].fields['firstName'], // TODO: change to displayName once we have name field type + viewId: viewIdMap['All People'], position: 0, isVisible: true, size: 210, }, { - fieldMetadataId: objectMetadataMap['personV2'].fields['email'], - viewId: viewIdMap['All People (V2)'], + fieldMetadataId: objectMetadataMap['person'].fields['email'], + viewId: viewIdMap['All People'], 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)'], + fieldMetadataId: objectMetadataMap['person'].fields['phone'], + viewId: viewIdMap['All People'], 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)'], + fieldMetadataId: objectMetadataMap['person'].fields['city'], + viewId: viewIdMap['All People'], position: 5, isVisible: true, size: 150, }, { - fieldMetadataId: objectMetadataMap['personV2'].fields['jobTitle'], - viewId: viewIdMap['All People (V2)'], + fieldMetadataId: objectMetadataMap['person'].fields['jobTitle'], + viewId: viewIdMap['All People'], position: 6, isVisible: true, size: 150, }, { - fieldMetadataId: objectMetadataMap['personV2'].fields['linkedinLink'], - viewId: viewIdMap['All People (V2)'], + fieldMetadataId: objectMetadataMap['person'].fields['linkedinLink'], + viewId: viewIdMap['All People'], position: 7, isVisible: true, size: 150, }, { - fieldMetadataId: objectMetadataMap['personV2'].fields['xLink'], - viewId: viewIdMap['All People (V2)'], + fieldMetadataId: objectMetadataMap['person'].fields['xLink'], + viewId: viewIdMap['All People'], position: 8, isVisible: true, size: 150, @@ -230,7 +202,7 @@ export const viewPrefillData = async ( isVisible: true, size: 170, }, - // Opportunities + // Opportunity { fieldMetadataId: 'amount', viewId: viewIdMap['All opportunities'], diff --git a/server/src/workspace/workspace-manager/standard-objects/activity-target.ts b/server/src/workspace/workspace-manager/standard-objects/activity-target.ts index 16af730e9..71b5af94b 100644 --- a/server/src/workspace/workspace-manager/standard-objects/activity-target.ts +++ b/server/src/workspace/workspace-manager/standard-objects/activity-target.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const activityTargetMetadata = { - nameSingular: 'activityTargetV2', - namePlural: 'activityTargetsV2', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', labelSingular: 'Activity Target', labelPlural: 'Activity Targets', targetTableName: 'activityTarget', diff --git a/server/src/workspace/workspace-manager/standard-objects/activity.ts b/server/src/workspace/workspace-manager/standard-objects/activity.ts index ff508859a..f2df68512 100644 --- a/server/src/workspace/workspace-manager/standard-objects/activity.ts +++ b/server/src/workspace/workspace-manager/standard-objects/activity.ts @@ -1,9 +1,9 @@ -import { SeedWorkspaceId } from 'src/database/seeds/metadata'; +import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const activityMetadata = { - nameSingular: 'activityV2', - namePlural: 'activitiesV2', + nameSingular: 'activity', + namePlural: 'activities', labelSingular: 'Activity', labelPlural: 'Activities', targetTableName: 'activity', diff --git a/server/src/workspace/workspace-manager/standard-objects/api-key.ts b/server/src/workspace/workspace-manager/standard-objects/api-key.ts index 8cee9d86e..5901e6850 100644 --- a/server/src/workspace/workspace-manager/standard-objects/api-key.ts +++ b/server/src/workspace/workspace-manager/standard-objects/api-key.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const apiKeyMetadata = { - nameSingular: 'apiKeyV2', - namePlural: 'apiKeysV2', + nameSingular: 'apiKey', + namePlural: 'apiKeys', labelSingular: 'Api Key', labelPlural: 'Api Keys', targetTableName: 'apiKey', diff --git a/server/src/workspace/workspace-manager/standard-objects/attachment.ts b/server/src/workspace/workspace-manager/standard-objects/attachment.ts index 769200efb..94cea327a 100644 --- a/server/src/workspace/workspace-manager/standard-objects/attachment.ts +++ b/server/src/workspace/workspace-manager/standard-objects/attachment.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const attachmentMetadata = { - nameSingular: 'attachmentV2', - namePlural: 'attachmentsV2', + nameSingular: 'attachment', + namePlural: 'attachments', labelSingular: 'Attachment', labelPlural: 'Attachments', targetTableName: 'attachment', diff --git a/server/src/workspace/workspace-manager/standard-objects/comment.ts b/server/src/workspace/workspace-manager/standard-objects/comment.ts index 4f0395190..9bb772cd2 100644 --- a/server/src/workspace/workspace-manager/standard-objects/comment.ts +++ b/server/src/workspace/workspace-manager/standard-objects/comment.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const commentMetadata = { - nameSingular: 'commentV2', - namePlural: 'commentsV2', + nameSingular: 'comment', + namePlural: 'comments', labelSingular: 'Comment', labelPlural: 'Comments', targetTableName: 'comment', diff --git a/server/src/workspace/workspace-manager/standard-objects/company.ts b/server/src/workspace/workspace-manager/standard-objects/company.ts index 496a90688..e28607eec 100644 --- a/server/src/workspace/workspace-manager/standard-objects/company.ts +++ b/server/src/workspace/workspace-manager/standard-objects/company.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const companyMetadata = { - nameSingular: 'companyV2', - namePlural: 'companiesV2', + nameSingular: 'company', + namePlural: 'companies', labelSingular: 'Company', labelPlural: 'Companies', targetTableName: 'company', diff --git a/server/src/workspace/workspace-manager/standard-objects/favorite.ts b/server/src/workspace/workspace-manager/standard-objects/favorite.ts index 62ca19568..8e5858fcf 100644 --- a/server/src/workspace/workspace-manager/standard-objects/favorite.ts +++ b/server/src/workspace/workspace-manager/standard-objects/favorite.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const favoriteMetadata = { - nameSingular: 'favoriteV2', - namePlural: 'favoritesV2', + nameSingular: 'favorite', + namePlural: 'favorites', labelSingular: 'Favorite', labelPlural: 'Favorites', targetTableName: 'favorite', diff --git a/server/src/workspace/workspace-manager/standard-objects/opportunity.ts b/server/src/workspace/workspace-manager/standard-objects/opportunity.ts index 1275d0d2d..c5ed0a164 100644 --- a/server/src/workspace/workspace-manager/standard-objects/opportunity.ts +++ b/server/src/workspace/workspace-manager/standard-objects/opportunity.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const opportunityMetadata = { - nameSingular: 'opportunityV2', - namePlural: 'opportunitiesV2', + nameSingular: 'opportunity', + namePlural: 'opportunities', labelSingular: 'Opportunity', labelPlural: 'Opportunities', targetTableName: 'opportunity', diff --git a/server/src/workspace/workspace-manager/standard-objects/person.ts b/server/src/workspace/workspace-manager/standard-objects/person.ts index f2b83fb33..8e57511b8 100644 --- a/server/src/workspace/workspace-manager/standard-objects/person.ts +++ b/server/src/workspace/workspace-manager/standard-objects/person.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const personMetadata = { - nameSingular: 'personV2', - namePlural: 'peopleV2', + nameSingular: 'person', + namePlural: 'people', labelSingular: 'Person', labelPlural: 'People', targetTableName: 'person', diff --git a/server/src/workspace/workspace-manager/standard-objects/pipeline-step.ts b/server/src/workspace/workspace-manager/standard-objects/pipeline-step.ts index efdb19932..428dabf1e 100644 --- a/server/src/workspace/workspace-manager/standard-objects/pipeline-step.ts +++ b/server/src/workspace/workspace-manager/standard-objects/pipeline-step.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const pipelineStepMetadata = { - nameSingular: 'pipelineStepV2', - namePlural: 'pipelineStepsV2', + nameSingular: 'pipelineStep', + namePlural: 'pipelineSteps', labelSingular: 'Pipeline Step', labelPlural: 'Pipeline Steps', targetTableName: 'pipelineStep', diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/activity.ts b/server/src/workspace/workspace-manager/standard-objects/relations/activity.ts index 6e05b4709..b728b7f57 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/activity.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/activity.ts @@ -3,22 +3,22 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const activityRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'activityV2', - toObjectNameSingular: 'activityTargetV2', + fromObjectNameSingular: 'activity', + toObjectNameSingular: 'activityTarget', fromFieldMetadataName: 'activityTargets', toFieldMetadataName: 'activity', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'activityV2', - toObjectNameSingular: 'attachmentV2', + fromObjectNameSingular: 'activity', + toObjectNameSingular: 'attachment', fromFieldMetadataName: 'attachments', toFieldMetadataName: 'activity', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'activityV2', - toObjectNameSingular: 'commentV2', + fromObjectNameSingular: 'activity', + toObjectNameSingular: 'comment', fromFieldMetadataName: 'comments', toFieldMetadataName: 'activity', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/company.ts b/server/src/workspace/workspace-manager/standard-objects/relations/company.ts index 7af62eb2c..880a4ab0b 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/company.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/company.ts @@ -3,36 +3,36 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const companyRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'companyV2', - toObjectNameSingular: 'personV2', + fromObjectNameSingular: 'company', + toObjectNameSingular: 'person', fromFieldMetadataName: 'people', toFieldMetadataName: 'company', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'companyV2', - toObjectNameSingular: 'favoriteV2', + fromObjectNameSingular: 'company', + toObjectNameSingular: 'favorite', fromFieldMetadataName: 'favorites', toFieldMetadataName: 'company', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'companyV2', - toObjectNameSingular: 'attachmentV2', + fromObjectNameSingular: 'company', + toObjectNameSingular: 'attachment', fromFieldMetadataName: 'attachments', toFieldMetadataName: 'company', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'companyV2', - toObjectNameSingular: 'opportunityV2', + fromObjectNameSingular: 'company', + toObjectNameSingular: 'opportunity', fromFieldMetadataName: 'opportunities', toFieldMetadataName: 'company', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'companyV2', - toObjectNameSingular: 'activityTargetV2', + fromObjectNameSingular: 'company', + toObjectNameSingular: 'activityTarget', fromFieldMetadataName: 'activityTargets', toFieldMetadataName: 'company', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/person.ts b/server/src/workspace/workspace-manager/standard-objects/relations/person.ts index eb1dfed1c..facfa8e43 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/person.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/person.ts @@ -3,36 +3,36 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const personRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'personV2', - toObjectNameSingular: 'favoriteV2', + fromObjectNameSingular: 'person', + toObjectNameSingular: 'favorite', fromFieldMetadataName: 'favorites', toFieldMetadataName: 'person', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'personV2', - toObjectNameSingular: 'attachmentV2', + fromObjectNameSingular: 'person', + toObjectNameSingular: 'attachment', fromFieldMetadataName: 'attachments', toFieldMetadataName: 'person', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'personV2', - toObjectNameSingular: 'opportunityV2', + fromObjectNameSingular: 'person', + toObjectNameSingular: 'opportunity', fromFieldMetadataName: 'opportunities', toFieldMetadataName: 'person', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'personV2', - toObjectNameSingular: 'opportunityV2', + fromObjectNameSingular: 'person', + toObjectNameSingular: 'opportunity', fromFieldMetadataName: 'pointOfContactForOpportunities', toFieldMetadataName: 'pointOfContact', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'personV2', - toObjectNameSingular: 'activityTargetV2', + fromObjectNameSingular: 'person', + toObjectNameSingular: 'activityTarget', fromFieldMetadataName: 'activityTargets', toFieldMetadataName: 'person', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/pipeline-step.ts b/server/src/workspace/workspace-manager/standard-objects/relations/pipeline-step.ts index 70194ad01..a590b598f 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/pipeline-step.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/pipeline-step.ts @@ -3,8 +3,8 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const pipelineStepRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'pipelineStepV2', - toObjectNameSingular: 'opportunityV2', + fromObjectNameSingular: 'pipelineStep', + toObjectNameSingular: 'opportunity', fromFieldMetadataName: 'opportunities', toFieldMetadataName: 'pipelineStep', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/view.ts b/server/src/workspace/workspace-manager/standard-objects/relations/view.ts index b58ee8400..658d90d52 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/view.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/view.ts @@ -3,22 +3,22 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const viewRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'viewV2', - toObjectNameSingular: 'viewFieldV2', + fromObjectNameSingular: 'view', + toObjectNameSingular: 'viewField', fromFieldMetadataName: 'viewFields', toFieldMetadataName: 'view', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'viewV2', - toObjectNameSingular: 'viewFilterV2', + fromObjectNameSingular: 'view', + toObjectNameSingular: 'viewFilter', fromFieldMetadataName: 'viewFilters', toFieldMetadataName: 'view', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'viewV2', - toObjectNameSingular: 'viewSortV2', + fromObjectNameSingular: 'view', + toObjectNameSingular: 'viewSort', fromFieldMetadataName: 'viewSorts', toFieldMetadataName: 'view', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/relations/workspace-member.ts b/server/src/workspace/workspace-manager/standard-objects/relations/workspace-member.ts index 1aa3acec7..5959f383a 100644 --- a/server/src/workspace/workspace-manager/standard-objects/relations/workspace-member.ts +++ b/server/src/workspace/workspace-manager/standard-objects/relations/workspace-member.ts @@ -3,43 +3,43 @@ import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-me const workspaceMemberRelationMetadata = [ { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'companyV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'company', fromFieldMetadataName: 'accountOwnerForCompanies', toFieldMetadataName: 'accountOwner', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'favoriteV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'favorite', fromFieldMetadataName: 'favorites', toFieldMetadataName: 'workspaceMember', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'activityV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'activity', fromFieldMetadataName: 'authoredActivities', toFieldMetadataName: 'author', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'activityV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'activity', fromFieldMetadataName: 'assignedActivities', toFieldMetadataName: 'assignee', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'commentV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'comment', fromFieldMetadataName: 'authoredComments', toFieldMetadataName: 'author', }, { type: RelationMetadataType.ONE_TO_MANY, - fromObjectNameSingular: 'workspaceMemberV2', - toObjectNameSingular: 'attachmentV2', + fromObjectNameSingular: 'workspaceMember', + toObjectNameSingular: 'attachment', fromFieldMetadataName: 'authoredAttachments', toFieldMetadataName: 'author', }, diff --git a/server/src/workspace/workspace-manager/standard-objects/standard-object-metadata.ts b/server/src/workspace/workspace-manager/standard-objects/standard-object-metadata.ts index c2341f15f..614d065b3 100644 --- a/server/src/workspace/workspace-manager/standard-objects/standard-object-metadata.ts +++ b/server/src/workspace/workspace-manager/standard-objects/standard-object-metadata.ts @@ -20,22 +20,22 @@ import { } from 'src/metadata/field-metadata/field-metadata.entity'; export const standardObjectsMetadata = { - activityTargetV2: activityTargetMetadata, - activityV2: activityMetadata, - apiKeyV2: apiKeyMetadata, - attachmentV2: attachmentMetadata, - commentV2: commentMetadata, - companyV2: companyMetadata, - favoriteV2: favoriteMetadata, - opportunityV2: opportunityMetadata, - personV2: personMetadata, - pipelineStepV2: pipelineStepMetadata, - viewFieldV2: viewFieldMetadata, - viewFilterV2: viewFilterMetadata, - viewSortV2: viewSortMetadata, - viewV2: viewMetadata, - webhookV2: webhookMetadata, - workspaceMemberV2: workspaceMemberMetadata, + activityTarget: activityTargetMetadata, + activity: activityMetadata, + apiKey: apiKeyMetadata, + attachment: attachmentMetadata, + comment: commentMetadata, + company: companyMetadata, + favorite: favoriteMetadata, + opportunity: opportunityMetadata, + person: personMetadata, + pipelineStep: pipelineStepMetadata, + viewField: viewFieldMetadata, + viewFilter: viewFilterMetadata, + viewSort: viewSortMetadata, + view: viewMetadata, + webhook: webhookMetadata, + workspaceMember: workspaceMemberMetadata, }; export const basicFieldsMetadata: Partial[] = [ diff --git a/server/src/workspace/workspace-manager/standard-objects/view-field.ts b/server/src/workspace/workspace-manager/standard-objects/view-field.ts index 391b783f9..4dc58fc5d 100644 --- a/server/src/workspace/workspace-manager/standard-objects/view-field.ts +++ b/server/src/workspace/workspace-manager/standard-objects/view-field.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const viewFieldMetadata = { - nameSingular: 'viewFieldV2', - namePlural: 'viewFieldsV2', + nameSingular: 'viewField', + namePlural: 'viewFields', labelSingular: 'View Field', labelPlural: 'View Fields', targetTableName: 'viewField', diff --git a/server/src/workspace/workspace-manager/standard-objects/view-filter.ts b/server/src/workspace/workspace-manager/standard-objects/view-filter.ts index 1fae60b02..33382e6d4 100644 --- a/server/src/workspace/workspace-manager/standard-objects/view-filter.ts +++ b/server/src/workspace/workspace-manager/standard-objects/view-filter.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const viewFilterMetadata = { - nameSingular: 'viewFilterV2', - namePlural: 'viewFiltersV2', + nameSingular: 'viewFilter', + namePlural: 'viewFilters', labelSingular: 'View Filter', labelPlural: 'View Filters', targetTableName: 'viewFilter', diff --git a/server/src/workspace/workspace-manager/standard-objects/view-sort.ts b/server/src/workspace/workspace-manager/standard-objects/view-sort.ts index 1640bfdf9..87338f562 100644 --- a/server/src/workspace/workspace-manager/standard-objects/view-sort.ts +++ b/server/src/workspace/workspace-manager/standard-objects/view-sort.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const viewSortMetadata = { - nameSingular: 'viewSortV2', - namePlural: 'viewSortsV2', + nameSingular: 'viewSort', + namePlural: 'viewSorts', labelSingular: 'View Sort', labelPlural: 'View Sorts', targetTableName: 'viewSort', diff --git a/server/src/workspace/workspace-manager/standard-objects/view.ts b/server/src/workspace/workspace-manager/standard-objects/view.ts index 39100c64d..1cbefc2ef 100644 --- a/server/src/workspace/workspace-manager/standard-objects/view.ts +++ b/server/src/workspace/workspace-manager/standard-objects/view.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const viewMetadata = { - nameSingular: 'viewV2', - namePlural: 'viewsV2', + nameSingular: 'view', + namePlural: 'views', labelSingular: 'View', labelPlural: 'Views', targetTableName: 'view', diff --git a/server/src/workspace/workspace-manager/standard-objects/webhook.ts b/server/src/workspace/workspace-manager/standard-objects/webhook.ts index c3f2ec8e1..9eca96183 100644 --- a/server/src/workspace/workspace-manager/standard-objects/webhook.ts +++ b/server/src/workspace/workspace-manager/standard-objects/webhook.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const webhookMetadata = { - nameSingular: 'webhookV2', - namePlural: 'webhooksV2', + nameSingular: 'webhook', + namePlural: 'webhooks', labelSingular: 'Webhook', labelPlural: 'Webhooks', targetTableName: 'webhook', diff --git a/server/src/workspace/workspace-manager/standard-objects/workspace-member.ts b/server/src/workspace/workspace-manager/standard-objects/workspace-member.ts index 4cd13aa7d..e2d5b7997 100644 --- a/server/src/workspace/workspace-manager/standard-objects/workspace-member.ts +++ b/server/src/workspace/workspace-manager/standard-objects/workspace-member.ts @@ -1,8 +1,8 @@ import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const workspaceMemberMetadata = { - nameSingular: 'workspaceMemberV2', - namePlural: 'workspaceMembersV2', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', labelSingular: 'Workspace Member', labelPlural: 'Workspace Members', targetTableName: 'workspaceMember', diff --git a/server/yarn.lock b/server/yarn.lock index 9706ae9c1..a7b2e5534 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -1262,14 +1262,6 @@ dependencies: "@ucast/mongo2js" "^1.3.0" -"@casl/prisma@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@casl/prisma/-/prisma-1.4.0.tgz#0b446e272c2b1ab300de8958c39aa534e3a29db2" - integrity sha512-edDoBfm2aSww5HLyAqKmSYlGqCX06Bo8j+4P8hBNuIxmSO97Q1jEO8hkCzMThnucuGFEbNvUct1+K64CH2zTWQ== - dependencies: - "@ucast/core" "^1.10.0" - "@ucast/js" "^3.0.1" - "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz" @@ -2014,22 +2006,6 @@ "@paljs/types" "5.3.3" "@prisma/internals" "^4.15.0" -"@prisma/client@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.13.0.tgz#271d2b9756503ea17bbdb459c7995536cf2a6191" - integrity sha512-YaiiICcRB2hatxsbnfB66uWXjcRw3jsZdlAVxmx0cFcTc/Ad/sKdHCcWSnqyDX47vAewkjRFwiLwrOUjswVvmA== - dependencies: - "@prisma/engines-version" "4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a" - -"@prisma/debug@4.15.0": - version "4.15.0" - resolved "https://registry.npmjs.org/@prisma/debug/-/debug-4.15.0.tgz" - integrity sha512-dkbPz+gOVlWDBAaOEseSpAUz9NppT38UlwdryPyrwct6OClLirNC7wH+TpAQk5OZp9x59hNnfDz+T7XvL1v0/Q== - dependencies: - "@types/debug" "4.1.8" - debug "4.3.4" - strip-ansi "6.0.1" - "@prisma/debug@4.16.0": version "4.16.0" resolved "https://registry.npmjs.org/@prisma/debug/-/debug-4.16.0.tgz" @@ -2039,16 +2015,6 @@ debug "4.3.4" strip-ansi "6.0.1" -"@prisma/engines-version@4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a": - version "4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a.tgz#ae338908d11685dee50e7683502d75442b955bf9" - integrity sha512-fsQlbkhPJf08JOzKoyoD9atdUijuGBekwoOPZC3YOygXEml1MTtgXVpnUNchQlRSY82OQ6pSGQ9PxUe4arcSLQ== - -"@prisma/engines@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.13.0.tgz#582a6b90b6efeb0f465984f1fe0e72a4afaaa5ae" - integrity sha512-HrniowHRZXHuGT9XRgoXEaP2gJLXM5RMoItaY2PkjvuZ+iHc0Zjbm/302MB8YsPdWozAPHHn+jpFEcEn71OgPw== - "@prisma/engines@4.16.0": version "4.16.0" resolved "https://registry.npmjs.org/@prisma/engines/-/engines-4.16.0.tgz" @@ -2087,16 +2053,6 @@ cross-spawn "7.0.3" kleur "4.1.5" -"@prisma/generator-helper@^4.14.0": - version "4.15.0" - resolved "https://registry.npmjs.org/@prisma/generator-helper/-/generator-helper-4.15.0.tgz" - integrity sha512-JVHNgXr0LrcqXqmFrs+BzxfyRL6cFD5GLTMVWfCLU7kqSJdWuZxfoZW995tg6mOXnBgPTf6Ocv3RY4RLQq8k4g== - dependencies: - "@prisma/debug" "4.15.0" - "@types/cross-spawn" "6.0.2" - cross-spawn "7.0.3" - kleur "4.1.5" - "@prisma/get-platform@4.16.0": version "4.16.0" resolved "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-4.16.0.tgz" @@ -2718,7 +2674,7 @@ "@smithy/types" "^1.1.0" tslib "^2.5.0" -"@sqltools/formatter@^1.2.3", "@sqltools/formatter@^1.2.5": +"@sqltools/formatter@^1.2.5": version "1.2.5" resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== @@ -2728,16 +2684,6 @@ resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== -"@ts-morph/common@~0.17.0": - version "0.17.0" - resolved "https://registry.npmjs.org/@ts-morph/common/-/common-0.17.0.tgz" - integrity sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g== - dependencies: - fast-glob "^3.2.11" - minimatch "^5.1.0" - mkdirp "^1.0.4" - path-browserify "^1.0.1" - "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" @@ -3367,12 +3313,12 @@ "@typescript-eslint/types" "5.59.11" eslint-visitor-keys "^3.3.0" -"@ucast/core@^1.0.0", "@ucast/core@^1.10.0", "@ucast/core@^1.4.1", "@ucast/core@^1.6.1": +"@ucast/core@^1.0.0", "@ucast/core@^1.4.1", "@ucast/core@^1.6.1": version "1.10.2" resolved "https://registry.npmjs.org/@ucast/core/-/core-1.10.2.tgz" integrity sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g== -"@ucast/js@^3.0.0", "@ucast/js@^3.0.1": +"@ucast/js@^3.0.0": version "3.0.3" resolved "https://registry.npmjs.org/@ucast/js/-/js-3.0.3.tgz" integrity sha512-jBBqt57T5WagkAjqfCIIE5UYVdaXYgGkOFYv2+kjq2AVpZ2RIbwCo/TujJpDlwTVluUI+WpnRpoGU2tSGlEvFQ== @@ -3973,13 +3919,6 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -await-event-emitter@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/await-event-emitter/-/await-event-emitter-2.0.2.tgz" - integrity sha512-3+cjm1wr2MQz0bFM1f5F0pR9XUitF5/kaKUfeGXJWFKC57FgDY61BoQp/xzjjkxXCz8tw1S2fCpeHtxpTID9tA== - dependencies: - is-promise "^4.0.0" - axios@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz" @@ -4466,11 +4405,6 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -code-block-writer@^11.0.3: - version "11.0.3" - resolved "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz" - integrity sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw== - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz" @@ -5030,11 +4964,6 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" @@ -5045,7 +4974,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -5352,7 +5281,7 @@ fast-diff@^1.1.2: resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@3.2.12, fast-glob@^3.2.11, fast-glob@^3.2.9: +fast-glob@3.2.12, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -5441,20 +5370,6 @@ file-type@16.5.4: strtok3 "^6.2.4" token-types "^4.1.1" -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz" - integrity sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ== - -filenamify@4.X: - version "4.3.0" - resolved "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz" - integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.1" - trim-repeated "^1.0.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" @@ -5515,11 +5430,6 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - flatted@^3.1.0: version "3.2.7" resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" @@ -5730,11 +5640,6 @@ get-package-type@^0.1.0: resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-relative-path@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/get-relative-path/-/get-relative-path-1.0.2.tgz" - integrity sha512-dGkopYfmB4sXMTcZslq5SojEYakpdCSj/SVSHLhv7D6RBHzvDtd/3Q8lTEOAhVKxPPeAHu/YYkENbbz3PaH+8w== - get-stream@^5.0.0: version "5.2.0" resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" @@ -5857,7 +5762,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -6329,11 +6234,6 @@ is-path-inside@^3.0.2, is-path-inside@^3.0.3: resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-promise@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz" - integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -6899,7 +6799,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: +json5@^2.2.1, json5@^2.2.2: version "2.2.3" resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -7353,7 +7253,7 @@ mkdirp@^0.5.4: dependencies: minimist "^1.2.6" -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.3: version "1.0.4" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -7674,11 +7574,6 @@ os-tmpdir@~1.0.2: resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -outmatch@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/outmatch/-/outmatch-0.7.0.tgz" - integrity sha512-w1ybiTBffGiwxOO7JJBVVOsIiWwzcfSl/D80amWAU2UDe1o9/SySOUzAwDuN3+jGKQRs0UCDTS8rndFiroJgVQ== - p-filter@2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz" @@ -7859,11 +7754,6 @@ patch-package@^8.0.0: tmp "^0.0.33" yaml "^2.2.2" -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" @@ -8079,43 +7969,6 @@ pretty-format@^28.0.0, pretty-format@^28.1.3: ansi-styles "^5.0.0" react-is "^18.0.0" -prisma-graphql-type-decimal@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/prisma-graphql-type-decimal/-/prisma-graphql-type-decimal-3.0.0.tgz#f3fa524b9e7aeab4fa0f969829bdddf199eff9fe" - integrity sha512-jrALv8ShVZoBBNyIOBCxwRoLM/DAOSD/OBKTWeJa9UigQXUTZniNXvLd4fLXwm+3v00A7cOZ1fFh3b74Ndgxhw== - -prisma-nestjs-graphql@^18.0.2: - version "18.0.2" - resolved "https://registry.yarnpkg.com/prisma-nestjs-graphql/-/prisma-nestjs-graphql-18.0.2.tgz#852b9386d2c26bad0bd82254a5cc2e483a96d5b5" - integrity sha512-Gh7DDXyzJQBKWkQwKOpSsXygxNkfUO+Bq7q79HZgoKa+/oUzi84Fh4bjzU1REki9635rmZC8F5MoVNTzKaUrnw== - dependencies: - "@prisma/generator-helper" "^4.14.0" - await-event-emitter "^2.0.2" - filenamify "4.X" - flat "^5.0.2" - get-relative-path "^1.0.2" - graceful-fs "^4.2.11" - json5 "^2.2.3" - lodash "^4.17.21" - outmatch "^0.7.0" - pluralize "^8.0.0" - pupa "2.X" - ts-morph ">=11 <=16" - -prisma-query-log@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/prisma-query-log/-/prisma-query-log-3.2.0.tgz#6e620a7196456075b1eaddb7cb10b86cb7be2ab4" - integrity sha512-Em7u3eedHZR6JJSzEMDEwoyS9zy2MsdQLrKxkfTbLdJF2LwfMetRVDBtkGQdcxM4ntT3wFWGBi/zNR5Q107Jgw== - dependencies: - "@sqltools/formatter" "^1.2.3" - -prisma@4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.13.0.tgz#0b83f40acf50cd47d7463a135c4e9b275713e602" - integrity sha512-L9mqjnSmvWIRCYJ9mQkwCtj4+JDYYTdhoyo8hlsHNDXaZLh/b4hR0IoKIBbTKxZuyHQzLopb/+0Rvb69uGV7uA== - dependencies: - "@prisma/engines" "4.13.0" - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" @@ -8165,13 +8018,6 @@ punycode@^2.1.0: resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -pupa@2.X: - version "2.1.1" - resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - qs@6.11.0: version "6.11.0" resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" @@ -8843,13 +8689,6 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -strip-outer@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz" - integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== - dependencies: - escape-string-regexp "^1.0.2" - strnum@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" @@ -9128,13 +8967,6 @@ tree-kill@1.2.2: resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz" - integrity sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg== - dependencies: - escape-string-regexp "^1.0.2" - ts-essentials@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz" @@ -9164,14 +8996,6 @@ ts-loader@^9.2.3: micromatch "^4.0.0" semver "^7.3.4" -"ts-morph@>=11 <=16": - version "16.0.0" - resolved "https://registry.npmjs.org/ts-morph/-/ts-morph-16.0.0.tgz" - integrity sha512-jGNF0GVpFj0orFw55LTsQxVYEUOCWBAbR5Ls7fTYE5pQsbW18ssTb/6UXx/GYAEjS+DQTp8VoTw0vqYMiaaQuw== - dependencies: - "@ts-morph/common" "~0.17.0" - code-block-writer "^11.0.3" - ts-node@^10.0.0: version "10.9.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz"