diff --git a/.vscode/extensions.json b/.vscode/extensions.json index cedc2cd1bfb..fde89b8355b 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 366fb922e97..3f4b28eeb8f 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 68bc67a9272..37143963650 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 c0b20d31cc9..d0c6f2e6d81 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 fe95edf6685..21c981377f3 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 4b79fc6bac6..b6cecf7bd09 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 d3e6daa5332..244109a4e81 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 08c7365dbab..48d3fd79c00 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 cd698080273..2139c4a910a 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 9e2955fc3d0..50c8202e487 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 55cf3c3bd35..00000000000 --- 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 6a17ed49a60..47de9f4659b 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 4728575cad6..e144c13c348 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 5deb9559cdd..f21c8ac000d 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 cc649bebb49..48470e31d15 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 238c38751b3..00000000000 --- 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 82fdef58de8..00000000000 --- 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 1187217ea86..00000000000 --- 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 ddf4efc7fb2..93158e9dac1 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 e880382d869..48a7f6e315f 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 5882e333838..9a9636acd7a 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 8807681ad1b..86aa3826a9d 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 61c1f5625ef..8bdbb2218a4 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 da979433f6c..b3d5aa4fb10 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 0285a8a5fb8..7f2e375c12d 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 0e8f931dced..a3ee0997909 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 abf5fbf7555..8f1558292ba 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 0c5db7a4a1d..012e45fa708 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 8eeac433825..d6e600b8ac7 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 b8664be7047..509c1e52f2d 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 5f09c8ba909..ee605de5d86 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 2158fc53a1b..32317eae62b 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 fae64ebb036..63240e01b5f 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 e2d66eb0e7d..b434bace788 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 a01a759e88f..457e4d16e4b 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 00000000000..657ce6b480f --- /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 f89b7683140..00000000000 --- 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 00000000000..c8df1e78bf6 --- /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 1afc69e304c..2d0b24e7b8d 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 e615d819496..94d104e00f3 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 8d76fd4bcd5..a4590991a52 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 67089d82f8a..dcc76e7fb12 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 447e6af2313..00000000000 --- 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 4ff4bd00ea4..6bfc08feb6c 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 3a72de199a0..2d830cf4493 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 85b624bb894..62d4e5959c5 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 7beeb9b6f47..c6d4a2dfbe1 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 e6bebfa562f..ba0f1c7696f 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 3a76334fb6a..de66283f09d 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 59eb2cc5023..00000000000 --- 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 c153d0233c4..00000000000 --- 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 e0dcc30480f..00000000000 --- 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 975f2bd56e5..00000000000 --- 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 096720737b5..00000000000 --- 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 9e99d3ea315..00000000000 --- 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 b705988f539..00000000000 --- 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 c30f4d4e49b..00000000000 --- 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 50c42beb479..00000000000 --- 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 b5059cd101b..00000000000 --- 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 55fd95265c7..00000000000 --- 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 18ff5696627..00000000000 --- 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 c464cefea9f..00000000000 --- 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 ff7dfc08f15..00000000000 --- 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 1fd8e8ad489..313069c264f 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 95e5f71b8d9..00000000000 --- 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 78bfbea3489..00000000000 --- 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 b512100f2ac..00000000000 --- 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 b714624163b..00000000000 --- 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 09a033e3c49..00000000000 --- 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 2834731975d..00000000000 --- 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 00000000000..f5cf7cb5e50 --- /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 ca981fed30b..6791fca1084 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 baa75ff4704..86f8402f34d 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 4e8f2d0c72c..00000000000 --- 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 e6cdc7a7c06..00000000000 --- 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 b18cb0ecdd1..00000000000 --- 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 f31aa560229..00000000000 --- 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 7102bed1e28..00000000000 --- 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 696f97bea37..145522b0dd9 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 7810ae26d67..3a26d4be607 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 00000000000..b4d55bcb577 --- /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 eed8e28e237..38f7b10d9b8 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 85c3427ec07..b74bf26a1a3 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 c736a142baf..c397aebe12c 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 10e8de47f55..00000000000 --- 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 977511bb9cc..00000000000 --- 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 b9a6bc39343..00000000000 --- 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 7f961ee7287..3894054e4e8 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 16f146f1c97..be0dccbf8e6 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 8f137b83fae..3ed609e72be 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 089d082d329..020418fea0a 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 3fcc36d42ad..c0e768ddd57 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 2d99f1b5b05..fb7ab109b62 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 56f570b0198..3af5a5d2b61 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 e105fb63b15..381fa5ad9ee 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 6d7123361c8..9f015d3d8bc 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 57ac25a6465..00000000000 --- 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 edf321409c8..4863ce6d283 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 a273d3226ed..46e20788b1b 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 60945e211d0..9c8ce3c431d 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 71e48499aa6..00000000000 --- 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 3c9cee6b8f7..00000000000 --- 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 9365386a04a..00000000000 --- 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 bc935cd0603..00000000000 --- 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 6156f42d05a..00000000000 --- 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 6c2af650ddd..00000000000 --- 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 a75a32363ef..00000000000 --- 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 d905c66a14c..00000000000 --- 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 01271ef3231..00000000000 --- 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 63617cf4f55..00000000000 --- 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 c609246bd52..00000000000 --- 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 3a07458e2d1..00000000000 --- 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 fd00ae78932..00000000000 --- 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 ef908c72e73..00000000000 --- 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 c24af2a245b..00000000000 --- 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 da001480503..00000000000 --- 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 b613607cdaf..00000000000 --- 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 04cd4982271..00000000000 --- 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 ece37e1b9b0..00000000000 --- 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 de9b9203c11..00000000000 --- 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 bea2279477c..00000000000 --- 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 5e4a76f16dd..00000000000 --- 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 a7caa3704ed..92584b5051c 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 eadf7ff08e3..00000000000 --- 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 78841d6a185..00000000000 --- 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 578e9794c47..00000000000 --- 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 f9c16d228c8..003cda2e515 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 8808ca711c0..00000000000 --- 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 b8882a870f4..00000000000 --- 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 1ef2d8abce4..00000000000 --- 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 dd392b6edd8..00000000000 --- 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 36eaaaa6104..00000000000 --- 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 c2f34302416..00000000000 --- 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 cf50f397dcc..00000000000 --- 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 763e9688c6d..00000000000 --- 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 209fdc2d243..00000000000 --- 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 c97d2adb0d2..00000000000 --- 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 00000000000..3048495fa1c --- /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 7d695224eb8..e0be2cee252 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 49834d68c4a..6a90a511193 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 e14d2c09777..032ec555c2a 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 c80fb078261..2de1a5e5fba 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 8f215f2f4e0..fc841efab04 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 48551e6246b..00000000000 --- 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 ae65c87c7c4..00000000000 --- 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 4ee3dbff449..00000000000 --- 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 d13a94ff3d3..00000000000 --- 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 443a2f9df09..00000000000 --- 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 d3d66748021..6e5b302d4d0 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 445ac3b8e61..5de4b90ba07 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 95510643fb2..a383fa3b799 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 68c53127a72..00000000000 --- 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 2a4a49ede84..00000000000 --- 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 b15f1a693e0..00000000000 --- 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 d2d0629cc58..00000000000 --- 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 e5dfe37ef75..00000000000 --- 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 fa03e756578..00000000000 --- 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 00000000000..f6f525f42ed --- /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 de85745dc11..80ff7427a6a 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 c0ef940050d..6570bc4126d 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 589a5dfcd93..df940993dfa 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 5141187b11e..7188b615ad3 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 47aba0a3bb4..d0f33e002b9 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 726b7a35139..34eb5a5fa1a 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 11f501e21d3..6367e829734 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 ed8c5825dea..86aacfa81cb 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 4a49887acb1..e1d14de01a0 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 711b6f13ef2..77d4e146919 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 597bb7180c0..a3cdb3da936 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 2f063042bca..f0cefc03f30 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 4738b84d7f3..741391b4a79 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 6f10c4f55a2..f786d5e86ae 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 dc970fd369c..458a9967e3e 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 0aaaab23d40..a0db150491c 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 13f7c869abf..fe137f70bfe 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 ba512eeaf16..b24268facaf 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 280439965ab..47344a771ea 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 a63bbc14dc9..772c033953e 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 9e64b94b764..38d6b8cb2ed 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 cf05e8a536d..7d57508d69b 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 76fa24092f3..966c239793c 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 79fe1496b14..60f8bc45f16 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 2028056a64f..5ee1a05c6a7 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 456096f634d..c22ba699fe3 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 dfd48f2b95a..0d34b93557b 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 9434539af43..66593718495 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 aaee9966242..c00d54696ed 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 dff16905a09..6047218f304 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 4ddcece8505..77341cb7127 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 55a82da563b..d0c2a09d7fc 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 1ed7d631a1b..e3082a79304 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 dbf58bc9600..1cba9a16996 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 f6e077451d8..513d41256b2 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 ed999cbb114..55b41b83496 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 59127459731..cdd9e5f7efa 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 eb9d7955588..bd5f5e4c12e 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 69f337a68f5..25a6f39501f 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 6455090aa00..d94e0813894 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 b32c898cbae..0c957c00423 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 18a0fab1574..3131b9db07d 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 4555b0e0605..b4b5c7b8d10 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 b96e25c4d92..a00e432cb9c 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 404d5b791be..49d1eeb19d1 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 af277da43a6..2927569c351 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 c8094a085ba..7c1b5eee125 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 195c7f0a7f7..548ea2b243c 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 b70efe0ea16..84f83e2b1f8 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 541d41c76f8..91ad36b8e06 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 6968c509ec3..d2dedea78d0 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 c0a9e666217..00000000000 --- 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 25345239d42..00000000000 --- 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 e5bc4a08513..00000000000 --- 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 0a3c667f930..8699d595d04 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 95d4664cce8..00000000000 --- 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 d3f84c94d5a..00000000000 --- 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 2be385f24c4..d47f6fd9ea7 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 f6c740245c8..00000000000 --- 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 965d4967c6f..a7d71e21f75 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 af44c712812..ef1921befb6 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 e17592bea99..9bb0ce82527 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 310691ff5fb..e7da03262a9 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 1fab91ccf0b..98aa2501d29 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 3c866934b6d..00000000000 --- 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 f013cb59b80..00000000000 --- 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 c9b3cba6e54..fcb71669263 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 7a55ebb082b..947825f9a06 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 943cc5d8732..a0f6def4432 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 ce17cc4ad34..ea9f02648ee 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 b334d142d4d..fdd577d4ff5 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 ed38cc22131..cb31acb0488 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 4a8f7db3425..00000000000 --- 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 00000000000..5cbcc2a0cc8 --- /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 feb1eedb7a4..9ed8df86577 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 906fd1d4708..00000000000 --- 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 62e06e7c8f7..00000000000 --- 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 8dfde4aace1..00000000000 --- 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 573fb878c39..711a1efc277 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 4e5efb9f6f1..a374d762bf9 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 8fcc6c7ca42..00000000000 --- 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 a362e50f74f..30a1791c348 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 c0980a72b4e..d97941824df 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 bcfe9a53772..005f4bd59ac 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 769a280bfa3..a4ad6e4dfe6 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 1789bbf1a27..43aacd17428 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 99f5e91b253..f4713ecfa3e 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 59e2d706569..62447d0d2f2 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 be4f299091b..5dada645963 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 d3119a6ee03..52c6432ea44 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 0a712376bfd..0f67e526e62 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 790743cdd58..20111a3eb5b 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 7f1b09623f1..00000000000 --- 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 8ed42c7a25e..d4c4021b72a 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 f89d18cb2d2..68435c50afc 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 78b10c55894..00000000000 --- 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 f886e1970a3..00000000000 --- 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 35d50ed0999..4515e225d38 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 38316987076..cd8c99ab610 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 af81aca7599..00000000000 --- 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 9d8ad59218f..f7d276c473e 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 36eb03d9c6c..00000000000 --- 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 e0d8bd0f77b..00000000000 --- 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 b151a356fae..00000000000 --- 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 5b1560db205..00000000000 --- 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 f78aa824d5c..00000000000 --- 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 9384c99e074..00000000000 --- 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 45389acfb25..00000000000 --- 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 ace176c23f9..00000000000 --- 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 284ababfb36..00000000000 --- 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 98e6b430ded..895e6c2e1eb 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 17218af0cfb..c52b0d8f1ab 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 5fe8606b2cb..00000000000 --- 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 777652bef66..00000000000 --- 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 c45e80d68ab..00000000000 --- 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 f0c680fa264..00000000000 --- 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 3b34d2c4b7a..00000000000 --- 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 751fb0b8606..00000000000 --- 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 80f7b699252..00000000000 --- 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 ae23274ebc3..00000000000 --- 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 08abc5ac779..00000000000 --- 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 be4ade7e117..00000000000 --- 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 6c9eff63085..00000000000 --- 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 24c1bc9cadd..64679d1e2b7 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 505a7e202c4..62e2544be86 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 c00fc4e555b..bdf0017c8aa 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 50aecad7f2e..8e9327fbbdb 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 1a6c2d9cceb..026b921ca13 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 7d3ea89b75a..c24ee718599 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 b6e2031e2cd..e34f18fdaed 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 2349693df67..75d63787104 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 6622e37caf3..1ccbebd2406 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 f8bf154ab24..34f7c45c16d 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 dd8b41c635b..ca17413d5a8 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 7e167ae2aad..880ab5223d2 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 0ec54e94577..a2099efa208 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 ab06463e900..50032bc854b 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 98e13d1002f..b459b9b2518 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 8f03f0923f2..00000000000 --- 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 216a36a7f0b..00000000000 --- 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 fcd426b690b..45216033c86 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 b7e779cd1ac..ff18aea4421 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 354183f28b8..955b79d5be7 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 1a6aa771883..48805968613 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 55a06ac2afc..e8e21e75f55 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 1ae2d964e87..59b1f41e82f 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 153603fdc64..cc37a46bf80 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 f36415e3d4d..afb3e0f3c59 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 41f245e10dc..00000000000 --- 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 4899ace777b..97add456178 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 d8845071f52..5a36c288961 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 da035d7bf61..00000000000 --- 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 57c8c9cfc83..00000000000 --- 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 e7fa87b0cca..00000000000 --- 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 abda5a30661..00000000000 --- 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 694fee47fe8..00000000000 --- 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 c161af2fa05..00000000000 --- 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 a72a6f4c667..00000000000 --- 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 6c2d33fd88a..00000000000 --- 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 1f8b5f74732..00000000000 --- 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 4727b4333b1..00000000000 --- 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 65fc4b3e1f4..00000000000 --- 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 c9fde0c4677..00000000000 --- 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 2b463061fbf..00000000000 --- 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 026f9b77d2d..00000000000 --- 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 e9aecfae77d..00000000000 --- 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 08f68a0cf1c..00000000000 --- 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 69bee102e51..00000000000 --- 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 c2b73fd6530..00000000000 --- 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 3a5d62ed96c..00000000000 --- 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 705d753934e..00000000000 --- 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 28cda745dac..00000000000 --- 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 b39a5ab4d68..960118275c5 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 e058fd45f66..00000000000 --- 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 63bf6ebb7d8..00000000000 --- 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 231df75902d..00000000000 --- 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 cc18cd67054..00000000000 --- 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 8c9398d5492..00000000000 --- 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 5a58ece2fd0..00000000000 --- 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 ce22974b089..00000000000 --- 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 dda499ff4d0..e4564e2339e 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 20ef2c377f4..76aa27c8e18 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 dc201f34522..a870673fe17 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 4f0073d4583..00000000000 --- 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 32f24e23ce5..00000000000 --- 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 4f633e14469..00000000000 --- 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 d3a7de114bb..00000000000 --- 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 59595bd06ea..00000000000 --- 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 5c2f2c19e36..00000000000 --- 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 add55e4a18a..00000000000 --- 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 f40eab92f39..00000000000 --- 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 9b70b073390..00000000000 --- 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 caebb345b72..e89e456c736 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 d242b0989d0..88b2cdb298b 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 96c83e2589e..96ca2957a73 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 0323c5c8b12..b427ad9744a 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 00000000000..c3dc2d6c154 --- /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 3ffdf442048..39150104172 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 ddf5e25b1a8..2035999312b 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 e575327b0e3..c0a55ae8087 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 c28e5be87a0..19aecaaedd3 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 13943c4a101..6aaab72d687 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 e12003fcd81..a03ef51ad06 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 8a2937584f1..00000000000 --- 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 ccc45ffabde..00000000000 --- 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 053ee74e197..00000000000 --- 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 049d0c6c204..00000000000 --- 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 8461127974f..00000000000 --- 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 7cb12bbda97..00000000000 --- 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 e432fddeea0..00000000000 --- 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 fd757a8ffaf..00000000000 --- 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 c1680b544e1..00000000000 --- 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 0ec462fdcb8..00000000000 --- 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 b5a09b25f9e..00000000000 --- 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 769510c7eb8..00000000000 --- 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 9d4c0aeadc8..00000000000 --- 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 3cce419bc72..71ff9e6da77 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 eb7349bf33f..00000000000 --- 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 2c6b05ecb60..00000000000 --- 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 e1a14d03430..00000000000 --- 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 683c7d84150..00000000000 --- 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 7eb96d46694..00000000000 --- 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 45d153bea2c..00000000000 --- 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 1344450c5db..00000000000 --- 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 0d3c23fe850..00000000000 --- 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 de97b94537f..00000000000 --- 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 dd20a722404..00000000000 --- 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 3048fe6a1f6..00000000000 --- 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 b04c3a03067..00000000000 --- 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 1a01f670914..00000000000 --- 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 d0579f81736..00000000000 --- 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 9cd09370155..00000000000 --- 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 b0790badc9a..00000000000 --- 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 0297a250e9b..00000000000 --- 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 486b073eb0f..00000000000 --- 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 aea1672925a..00000000000 --- 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 8084910ad5f..00000000000 --- 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 b85147fcbd8..00000000000 --- 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 1046eb6eb49..00000000000 --- 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 9295f6df0ba..00000000000 --- 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 f4052a7206f..00000000000 --- 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 17a110b10b1..00000000000 --- 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 2f3d017a543..00000000000 --- 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 cacc807e42f..ce9e3470c1d 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 fc4a774ff45..ff0de0e4470 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 b3f948efce4..b563ca5504c 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 acad308e382..faa99c3cbd3 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 00000000000..0b05f7ab655 --- /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 b73bfe936a9..7bfccb0fa99 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 00000000000..868de531268 --- /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 edc6c4887b8..e1303448550 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 3474992a646..0d9cdce2415 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 cbefde321bf..567b7e1b747 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 209ea872185..00000000000 --- 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 9e3a4b0ee32..2a0fba704c1 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 60afaa23e66..00000000000 --- 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 6d2afe01fac..00000000000 --- 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 f54f86fb0ee..00000000000 --- 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 0cf67a53a7d..00000000000 --- 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 e950ed2c72b..4ba333e0062 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 4e1a74e360d..00000000000 --- 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 30a0f2ed149..00000000000 --- 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 6388991813e..00000000000 --- 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 f1b42c0d9c7..00000000000 --- 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 2017a0b325e..00000000000 --- 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 15c043b4431..00000000000 --- 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 f782e8cbafa..51d3a7e6d7b 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 0cd817b4d8e..0662a07993f 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 f94a17ff161..3ff4f05944b 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 8602822789f..76f7cd53998 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 16123a1e5f6..3874dcc6d46 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 35bec01f8a2..790179dd2e0 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 1a4b0983f30..00000000000 --- 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 745206c88f8..00000000000 --- 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 469120791ad..00000000000 --- 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 a39a7ef86bf..00000000000 --- 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 de2c91ce358..00000000000 --- 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 3646c6ecaa3..00000000000 --- 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 736f1462611..00000000000 --- 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 0b2100c96ab..00000000000 --- 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 4c2ed752aa1..00000000000 --- 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 e7bf83a1d9c..939250da6d7 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 7e70ddfa302..f42f2efb3ac 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 5bc95ea1ec8..00000000000 --- 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 8f76ed2536e..00000000000 --- 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 46e9233a1bf..00000000000 --- 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 cba4df125a1..00000000000 --- 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 e5e9ec482e9..00000000000 --- 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 a21064dc386..00000000000 --- 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 6c6fd0a3c82..00000000000 --- 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 39d10c13bf4..00000000000 --- 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 84dd1cfebe6..00000000000 --- 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 f771e187639..00000000000 --- 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 d5558255664..00000000000 --- 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 31dddc6af5f..00000000000 --- 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 116ebd6722e..00000000000 --- 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 67a3839e695..00000000000 --- 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 8a7024a0045..00000000000 --- 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 6113bdb9a18..00000000000 --- 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 0b87aa98d04..00000000000 --- 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 2e333f05eb6..00000000000 --- 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 2402ca54a8b..00000000000 --- 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 e943e42095d..00000000000 --- 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 caa4532e56a..00000000000 --- 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 7ccb2342072..00000000000 --- 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 d603f329324..00000000000 --- 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 1b5d0bf38cd..00000000000 --- 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 e5aa554ffb1..00000000000 --- 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 1f3c7361d5a..00000000000 --- 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 d86a7d0069f..00000000000 --- 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 3f2b71c2738..00000000000 --- 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 25e2e1abea4..00000000000 --- 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 ec91a0a4a92..00000000000 --- 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 ef4086fa1f3..00000000000 --- 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 178c90ce818..00000000000 --- 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 f5a52f80e4b..00000000000 --- 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 8b75896dd87..00000000000 --- 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 6ee2aa23b4c..00000000000 --- 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 2a93c6ce617..00000000000 --- 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 ccc3c5c87d0..00000000000 --- 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 2cbb82a328d..00000000000 --- 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 a8596427d7e..00000000000 --- 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 df8c52e6c56..00000000000 --- 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 a57411345c4..00000000000 --- 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 4f3993584fa..00000000000 --- 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 08c77e595b2..00000000000 --- 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 870add1fa76..00000000000 --- 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 874c23506b5..00000000000 --- 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 63060a14b64..00000000000 --- 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 df5dc619b45..00000000000 --- 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 adbaa3f6ae8..00000000000 --- 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 271070b01f5..00000000000 --- 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 5352bde5dc7..00000000000 --- 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 161b7bda1e4..00000000000 --- 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 1f4e16edb0d..00000000000 --- 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 a836f5f793e..00000000000 --- 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 b7a78bbb885..00000000000 --- 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 b50fd78ecdf..00000000000 --- 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 60036a5cc74..00000000000 --- 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 1d60790dbed..00000000000 --- 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 da47f8520a6..00000000000 --- 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 12f941b0dad..00000000000 --- 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 d2ea6379e06..00000000000 --- 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 f30c55293a1..00000000000 --- 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 eda2606fa11..00000000000 --- 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 183a15ae3da..00000000000 --- 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 ecd0b314b44..00000000000 --- 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 43ef82be9d2..00000000000 --- 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 cd0219d7cdd..00000000000 --- 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 9ff25723b6d..00000000000 --- 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 0674f52feb4..00000000000 --- 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 c2804c5eb6f..00000000000 --- 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 16d5238aba6..00000000000 --- 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 fbffa92c2bb..00000000000 --- 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 54327ba02b4..00000000000 --- 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 15b806b332f..00000000000 --- 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 6da983ad633..00000000000 --- 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 f51d64373c2..00000000000 --- 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 5dbfa73f83b..00000000000 --- 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 4bb4d651575..00000000000 --- 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 8ed6cb20db6..00000000000 --- 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 9816f6e969b..00000000000 --- 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 48cc3dfb5a0..00000000000 --- 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 a4bebb379a5..00000000000 --- 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 6af274f615e..00000000000 --- 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 00000000000..3cb92916351 --- /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 00000000000..a41fe384c6b --- /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 00000000000..30de1a908f6 --- /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 00000000000..48bc6d181a1 --- /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 03432e098ed..e16cd8ea39e 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 8c2335f15d1..9440bd58083 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 6be643f827c..2fe62c37d3b 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 0db186598ea..6d0bcc2d7ad 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 753416f2350..4dfa110f8e0 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 cb884e53db7..fecd9558b2e 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 dcb59c268cc..615943bbf6a 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 69f00c8f828..a503628b5e1 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 535d2f52c97..b3a028c58ae 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 244c069fc31..b66fb3085a2 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 f85e747bb70..19a0c60f1cc 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 73056d454c3..958386e94c3 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 708e312daaa..ccf971fb5f5 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 257c0e12322..1e85d3512e8 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 a657cf15890..e8cf14bb747 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 cc969ab85d2..36e68510ed4 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 b4277f12976..37fe3aebd9a 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 1952fbffe28..4d02be734e7 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 1abf0d9ab34..c507e0e97c5 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 9bf05755c61..78a660d558a 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 a51516769b7..cb51e0b45f1 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 0c531f17d28..baa4c449b42 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 d418c254bd6..2a2c0d07f62 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 4c179ad8b73..404df06b32a 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 6430125e8d2..03e8508f893 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 00000000000..abbcd174835 --- /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 9be4ff2db45..a0d50e630d0 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 5159d8d9055..3fb17f01684 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 f50916d6c65..00000000000 --- 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 7984dc2c19d..00000000000 --- 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 a55f9a3becc..f175e48cd70 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 4b7a626e706..00000000000 --- 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 b94903842c7..796656f80d7 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 76f412d49fa..ee106fc3895 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 17bbcc6ad31..bbdb3511469 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 316a0bc50ba..00000000000 --- 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 58855649940..242e2ef3cdd 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 a3a49200722..831c5c98216 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 685f233d4dc..a68e00fa71a 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 6b57f273a8f..b6dcb0a16fd 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 525c5168a32..00000000000 --- 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 76c65a6cb20..00000000000 --- 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 1affd9083ad..c7918e1b5c7 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 16af730e9db..71b5af94b5f 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 ff508859a35..f2df6851230 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 8cee9d86e51..5901e68500e 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 769200efbe5..94cea327a03 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 4f03951907c..9bb772cd2a2 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 496a9068802..e28607eecd1 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 62ca195680d..8e5858fcfcb 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 1275d0d2d18..c5ed0a164cd 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 f2b83fb338c..8e57511b842 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 efdb1993261..428dabf1e40 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 6e05b470988..b728b7f5704 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 7af62eb2c61..880a4ab0b19 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 eb1dfed1c09..facfa8e43d5 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 70194ad0198..a590b598f50 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 b58ee8400d0..658d90d52fc 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 1aa3acec752..5959f383a1b 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 c2341f15f02..614d065b31e 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 391b783f9c0..4dc58fc5d51 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 1fae60b02a6..33382e6d494 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 1640bfdf982..87338f5626b 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 39100c64d22..1cbefc2ef55 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 c3f2ec8e121..9eca961838e 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 4cd13aa7d8f..e2d5b79971d 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 9706ae9c118..a7b2e55342b 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"