diff --git a/index.html b/index.html index 5bad140fe..bdfca044a 100644 --- a/index.html +++ b/index.html @@ -48,7 +48,7 @@
- +
diff --git a/package.json b/package.json index bd382f344..d6a122f25 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "i18n-iso-countries": "^7.3.0", "i18next": "^23.15.1", "i18next-browser-languagedetector": "^8.0.0", + "motion": "^12.15.0", "qs": "^6.10.3", "query-string": "^7.1.1", "react": "^18.3.1", diff --git a/src/assets/icons/password-check-v.svg b/src/assets/icons/password-check-v.svg new file mode 100644 index 000000000..4438467b7 --- /dev/null +++ b/src/assets/icons/password-check-v.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/password-check-x.svg b/src/assets/icons/password-check-x.svg new file mode 100644 index 000000000..7fc25b025 --- /dev/null +++ b/src/assets/icons/password-check-x.svg @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/src/assets/join-bg-1.png b/src/assets/join-bg-1.png new file mode 100644 index 000000000..b2a8b7c45 Binary files /dev/null and b/src/assets/join-bg-1.png differ diff --git a/src/assets/join-bg-1.webp b/src/assets/join-bg-1.webp new file mode 100644 index 000000000..b1e72f235 Binary files /dev/null and b/src/assets/join-bg-1.webp differ diff --git a/src/assets/join-bg-2.png b/src/assets/join-bg-2.png new file mode 100644 index 000000000..1e66db7e9 Binary files /dev/null and b/src/assets/join-bg-2.png differ diff --git a/src/assets/join-bg-2.webp b/src/assets/join-bg-2.webp new file mode 100644 index 000000000..67d4964cb Binary files /dev/null and b/src/assets/join-bg-2.webp differ diff --git a/src/assets/join-bg-3.png b/src/assets/join-bg-3.png new file mode 100644 index 000000000..9aac47a70 Binary files /dev/null and b/src/assets/join-bg-3.png differ diff --git a/src/assets/join-bg-3.webp b/src/assets/join-bg-3.webp new file mode 100644 index 000000000..4a695fcfe Binary files /dev/null and b/src/assets/join-bg-3.webp differ diff --git a/src/assets/join-loghi.png b/src/assets/join-loghi.png new file mode 100644 index 000000000..77eb16ddf Binary files /dev/null and b/src/assets/join-loghi.png differ diff --git a/src/assets/join-loghi.webp b/src/assets/join-loghi.webp new file mode 100644 index 000000000..95b364565 Binary files /dev/null and b/src/assets/join-loghi.webp differ diff --git a/src/assets/join-step-1.svg b/src/assets/join-step-1.svg new file mode 100644 index 000000000..69f3ef230 --- /dev/null +++ b/src/assets/join-step-1.svg @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/join-step-1.webp b/src/assets/join-step-1.webp new file mode 100644 index 000000000..84e6575fa Binary files /dev/null and b/src/assets/join-step-1.webp differ diff --git a/src/assets/join-step-2.png b/src/assets/join-step-2.png new file mode 100644 index 000000000..4ce18d7fd Binary files /dev/null and b/src/assets/join-step-2.png differ diff --git a/src/assets/join-step-2.webp b/src/assets/join-step-2.webp new file mode 100644 index 000000000..a4b9b2b78 Binary files /dev/null and b/src/assets/join-step-2.webp differ diff --git a/src/assets/join-step-3.png b/src/assets/join-step-3.png new file mode 100644 index 000000000..f37baa8ff Binary files /dev/null and b/src/assets/join-step-3.png differ diff --git a/src/assets/join-step-3.webp b/src/assets/join-step-3.webp new file mode 100644 index 000000000..97a00ad33 Binary files /dev/null and b/src/assets/join-step-3.webp differ diff --git a/src/common/Pages.tsx b/src/common/Pages.tsx index dbf64772b..c1411416c 100644 --- a/src/common/Pages.tsx +++ b/src/common/Pages.tsx @@ -17,6 +17,7 @@ import CampaignPreview from 'src/pages/Campaign/preview'; import Dashboard from 'src/pages/Dashboard'; import Project from 'src/pages/Dashboard/Project'; import InsightsPage from 'src/pages/Insights'; +import JoinPage from 'src/pages/JoinPage'; import LoginPage from 'src/pages/LoginPage'; import Manual from 'src/pages/Manual'; import MediaNotFound from 'src/pages/NotFound/MediaNotFound'; @@ -66,6 +67,12 @@ const Pages = () => { path={`/${langPrefix}/login`} element={} /> + } /> + } + /> + } @@ -146,6 +153,21 @@ const Pages = () => { } errorElement={} /> + + { + if (!searchParams || !searchParams.get('redirect')) + return '/oops'; + return `/campaigns/${searchParams.get('cid')}/bugform`; + }} + /> + } + errorElement={} + /> + } /> ) diff --git a/src/common/schema.ts b/src/common/schema.ts index 75eee33f2..7cadc5d89 100644 --- a/src/common/schema.ts +++ b/src/common/schema.ts @@ -9,10 +9,6 @@ export interface paths { get: operations['get-root']; parameters: {}; }; - '/authenticate': { - /** A request to login with your username and password */ - post: operations['post-authenticate']; - }; '/analytics/views/campaigns/{cid}': { post: operations['post-analytics-views-campaigns-cid']; parameters: { @@ -22,9 +18,9 @@ export interface paths { }; }; }; - '/campaigns': { - post: operations['post-campaigns']; - parameters: {}; + '/authenticate': { + /** A request to login with your username and password */ + post: operations['post-authenticate']; }; '/campaigns/{cid}': { get: operations['get-campaign']; @@ -78,25 +74,25 @@ export interface paths { }; }; }; - '/campaigns/{cid}/bugs/{bid}/media': { - post: operations['post-campaigns-cid-bugs-bid-media']; + '/campaigns/{cid}/bugs/{bid}/comments/{cmid}': { + post: operations['post-campaigns-cid-bugs-bid-comments-cmid-media']; + delete: operations['delete-campaigns-cid-bugs-bid-comments-cmid']; parameters: { path: { - /** Campaign id */ cid: string; - /** Defines an identifier for the bug object (BUG ID) */ bid: string; + cmid: string; }; }; }; - '/campaigns/{cid}/bugs/{bid}/comments/{cmid}': { - post: operations['post-campaigns-cid-bugs-bid-comments-cmid-media']; - delete: operations['delete-campaigns-cid-bugs-bid-comments-cmid']; + '/campaigns/{cid}/bugs/{bid}/media': { + post: operations['post-campaigns-cid-bugs-bid-media']; parameters: { path: { + /** Campaign id */ cid: string; + /** Defines an identifier for the bug object (BUG ID) */ bid: string; - cmid: string; }; }; }; @@ -320,11 +316,12 @@ export interface paths { }; }; }; - '/media/{id}': { - get: operations['get-media-id']; + '/invites/{profile}/{token}': { + get: operations['get-invites-profile-token']; parameters: { path: { - id: string; + profile: string; + token: string; }; }; }; @@ -337,6 +334,33 @@ export interface paths { }; }; }; + '/media/{id}': { + get: operations['get-media-id']; + parameters: { + path: { + id: string; + }; + }; + }; + '/plans/{pid}': { + get: operations['get-workspaces-wid-plans-pid']; + delete: operations['delete-workspaces-wid-plans-pid']; + patch: operations['patch-workspaces-wid-plans-pid']; + parameters: { + path: { + pid: string; + }; + }; + }; + '/plans/{pid}/status': { + /** */ + patch: operations['patch-workspaces-wid-plans-pid-status']; + parameters: { + path: { + pid: string; + }; + }; + }; '/projects': { post: operations['post-projects']; }; @@ -376,9 +400,17 @@ export interface paths { }; }; }; - '/templates': { - /** Retrieve all available use case templates */ - get: operations['get-templates']; + '/users': { + post: operations['post-users']; + parameters: {}; + }; + '/users/by-email/{email}': { + head: operations['head-users-by-email-email']; + parameters: { + path: { + email: string; + }; + }; }; '/users/me': { get: operations['get-users-me']; @@ -394,6 +426,10 @@ export interface paths { }; }; }; + '/users/roles': { + get: operations['get-users-roles']; + parameters: {}; + }; '/videos/{vid}': { /** Retrive single video data */ get: operations['get-videos-vid']; @@ -506,31 +542,34 @@ export interface paths { }; }; }; - '/plans/{pid}': { - get: operations['get-workspaces-wid-plans-pid']; - delete: operations['delete-workspaces-wid-plans-pid']; - patch: operations['patch-workspaces-wid-plans-pid']; + '/workspaces/{wid}/projects': { + get: operations['get-workspace-projects']; parameters: { path: { - pid: string; + /** Workspace (company, customer) id */ + wid: components['parameters']['wid']; }; }; }; - '/plans/{pid}/status': { - /** */ - patch: operations['patch-workspaces-wid-plans-pid-status']; + '/workspaces/{wid}/projects/{pid}': { + get: operations['get-workspace-project']; parameters: { path: { - pid: string; + /** Workspace (company, customer) id */ + wid: components['parameters']['wid']; + /** Project id */ + pid: components['parameters']['pid']; }; }; }; - '/workspaces/{wid}/projects': { - get: operations['get-workspace-projects']; + '/workspaces/{wid}/projects/{pid}/campaigns': { + get: operations['get-workspace-project-campaigns']; parameters: { path: { /** Workspace (company, customer) id */ wid: components['parameters']['wid']; + /** Project id */ + pid: components['parameters']['pid']; }; }; }; @@ -553,28 +592,6 @@ export interface paths { }; }; }; - '/workspaces/{wid}/projects/{pid}': { - get: operations['get-workspace-project']; - parameters: { - path: { - /** Workspace (company, customer) id */ - wid: components['parameters']['wid']; - /** Project id */ - pid: components['parameters']['pid']; - }; - }; - }; - '/workspaces/{wid}/projects/{pid}/campaigns': { - get: operations['get-workspace-project-campaigns']; - parameters: { - path: { - /** Workspace (company, customer) id */ - wid: components['parameters']['wid']; - /** Project id */ - pid: components['parameters']['pid']; - }; - }; - }; '/workspaces/{wid}/users': { /** Return a list of users from a specific workspace */ get: operations['get-workspaces-users']; @@ -595,48 +612,56 @@ export interface components { schemas: { /** Authentication */ Authentication: { - id: number; /** Format: email */ email: string; - role: string; + exp?: number; + iat?: number; + id: number; name: string; picture?: string; + role: string; token: string; - iat?: number; - exp?: number; }; + /** + * BannerType + * @enum {string} + */ + BannerType: + | 'banner_testing_automation' + | 'banner_user_experience' + | 'banner_cyber_security'; /** Bug */ Bug: { - id: number; - internal_id: string; + application_section: { + id?: number; + prefix_title?: string; + simple_title?: string; + title?: string; + }; campaign_id: number; - title: components['schemas']['BugTitle']; - step_by_step: string; - expected_result: string; + created: string; current_result: string; - status: components['schemas']['BugStatus']; - severity: components['schemas']['BugSeverity']; - type: components['schemas']['BugType']; - replicability: components['schemas']['BugReplicability']; - priority: components['schemas']['BugPriority']; custom_status: components['schemas']['BugCustomStatus']; - created: string; - occurred_date: string; - updated?: string; - note?: string; device: | components['schemas']['Smartphone'] | components['schemas']['Tablet'] | components['schemas']['Desktop']; - application_section: { - id?: number; - prefix_title?: string; - title?: string; - simple_title?: string; - }; duplicated_of_id?: number; + expected_result: string; + id: number; + internal_id: string; is_favorite?: number; + note?: string; + occurred_date: string; + priority: components['schemas']['BugPriority']; read?: boolean; + replicability: components['schemas']['BugReplicability']; + severity: components['schemas']['BugSeverity']; + status: components['schemas']['BugStatus']; + step_by_step: string; + title: components['schemas']['BugTitle']; + type: components['schemas']['BugType']; + updated?: string; }; /** * BugAdditionalField @@ -652,39 +677,39 @@ export interface components { ); /** BugAdditionalFieldRegex */ BugAdditionalFieldRegex: { - validation: string; /** @enum {string} */ kind: 'regex'; + validation: string; }; /** BugAdditionalFieldSelect */ BugAdditionalFieldSelect: { - options: string[]; /** @enum {string} */ kind: 'select'; + options: string[]; }; /** BugComment */ BugComment: { - id: number; - text: string; creation_date: string; creator: { id: number; - name: string; isInternal: boolean; + name: string; }; + id: number; media?: { - url: string; id: number; type: string; + url: string; }[]; + text: string; }; /** BugCustomStatus */ BugCustomStatus: { + color: string; id: number; + is_default: number; name: string; - color: string; phase: components['schemas']['BugCustomStatusPhase']; - is_default: number; }; /** BugCustomStatusPhase */ BugCustomStatusPhase: { @@ -693,14 +718,14 @@ export interface components { }; /** BugMedia */ BugMedia: { + creation_date: string; mime_type: { + extension: string; /** @enum {string} */ type: 'video' | 'image' | 'other'; - extension: string; }; /** Format: uri */ url: string; - creation_date: string; }; /** BugPriority */ BugPriority: { @@ -724,23 +749,23 @@ export interface components { }; /** BugTag */ BugTag: { - id: number; - tag_id: number; - name: string; - slug: string; + author_tid?: number; + author_wp_id?: number; bug_id: number; campaign_id: number; - author_wp_id?: number; - author_tid?: number; creation_date: string; + id: number; is_visible_to_customer?: number; + name: string; + slug: string; + tag_id: number; }; /** BugTitle */ BugTitle: { - full: string; /** @description Bug title without context. */ compact: string; context?: string[]; + full: string; }; /** BugType */ BugType: { @@ -749,32 +774,34 @@ export interface components { }; /** Campaign */ Campaign: { - id: number; - start_date: string; - end_date: string; - close_date: string; - title: string; - customer_title: string; - is_public: number; + base_bug_internal_id?: string; /** * @description -1: no bug form; * 0: only bug form; * 1: bug form with bug parade; */ bug_form?: number; - type: { + close_date: string; + customer_title: string; + description?: string; + end_date: string; + family: { id: number; name: string; }; - family: { + id: number; + is_public: number; + project: { id: number; name: string; }; + start_date: string; status: { id: number; name: string; }; - project: { + title: string; + type: { id: number; name: string; }; @@ -782,8 +809,6 @@ export interface components { id: number; name: string; }; - description?: string; - base_bug_internal_id?: string; }; /** CampaignWithOutput */ CampaignWithOutput: components['schemas']['Campaign'] & { @@ -800,21 +825,31 @@ export interface components { * The coin only valid currency in order to run an express campaign (no matter what type of express) */ Coin: { - id: number; - customer_id: number; + agreement_id?: number; /** @description Number of available coin */ amount: number; - agreement_id?: number; + created_on?: string; + customer_id: number; + id: number; /** * Format: float * @description This is the single coin price * @default 0 */ price?: number; - created_on?: string; /** @description On each coin use, the related package will be updated */ updated_on?: string; }; + /** CpReqTemplate */ + CpReqTemplate: { + config: string; + description?: string; + id: number; + name: string; + price?: string; + strapi?: components['schemas']['StrapiTemplate']; + workspace_id?: number; + }; /** Desktop */ Desktop: { desktop_type: string; @@ -825,17 +860,17 @@ export interface components { }; /** Error */ Error: { - message: string; code: number; error: boolean; + message: string; }; /** * Feature * @description Flags used to enable functionality to some users */ Feature: { - slug?: string; name?: string; + slug?: string; }; /** Generic Device */ GenericDevice: { @@ -845,46 +880,46 @@ export interface components { }; /** Grape */ Grapes: { - title: string; - severity: string; - usersNumber: number; observations: (components['schemas']['Observation'] & { - uploaderId: number; - mediaId: number; deviceType: string; + mediaId: number; + uploaderId: number; usecaseTitle: string; })[]; + severity: string; + title: string; + usersNumber: number; }; /** Insight */ Insight: { - id: number; - title: string; + comment?: string; description: string; + id: number; + observations: (components['schemas']['Observation'] & { + uploaderId: number; + usecaseTitle: string; + video: { + deviceType: string; + id: number; + }; + })[]; severity: { id: number; name: string; style: string; }; + title: string; visible?: number; - comment?: string; - observations: (components['schemas']['Observation'] & { - video: { - id: number; - deviceType: string; - }; - uploaderId: number; - usecaseTitle: string; - })[]; }; MediaSentiment: { - value: number; - reason: string; paragraphs: { - start: number; end: number; - value: number; reason: string; + start: number; + value: number; }[]; + reason: string; + value: number; }; Module: | components['schemas']['ModuleTitle'] @@ -903,128 +938,128 @@ export interface components { | components['schemas']['ModuleSetupNote'] | components['schemas']['ModuleTouchpoints'] | components['schemas']['ModuleAdditionalTarget']; - ModuleDate: { + /** ModuleAdditionalTarget */ + ModuleAdditionalTarget: { + output: string; /** @enum {string} */ - type: 'dates'; + type: 'additional_target'; variant: string; - output: { - start: string; - }; }; - ModuleGoal: { + /** ModuleAge */ + ModuleAge: { + output: components['schemas']['OutputModuleAge']; /** @enum {string} */ - type: 'goal'; + type: 'age'; variant: string; - output: string; }; - ModuleOutOfScope: { + /** ModuleBrowser */ + ModuleBrowser: { + output: components['schemas']['OutputModuleBrowser']; /** @enum {string} */ - type: 'out_of_scope'; + type: 'browser'; variant: string; - output: string; }; - ModuleTitle: { + ModuleDate: { + output: { + start: string; + }; /** @enum {string} */ - type: 'title'; + type: 'dates'; variant: string; - output: string; }; - /** ModuleTask */ - ModuleTask: { + /** ModuleGender */ + ModuleGender: { + output: components['schemas']['OutputModuleGender']; /** @enum {string} */ - type: 'tasks'; + type: 'gender'; variant: string; - output: components['schemas']['OutputModuleTask'][]; }; - /** ModuleTouchpoints */ - ModuleTouchpoints: { + ModuleGoal: { + output: string; /** @enum {string} */ - type: 'touchpoints'; + type: 'goal'; variant: string; - output: components['schemas']['OutputModuleTouchpoints'][]; }; - /** ModuleAge */ - ModuleAge: { + /** ModuleInstructionNote */ + ModuleInstructionNote: { + output: string; /** @enum {string} */ - type: 'age'; + type: 'instruction_note'; variant: string; - output: components['schemas']['OutputModuleAge']; }; - /** ModuleGender */ - ModuleGender: { + /** ModuleLanguage */ + ModuleLanguage: { + output: string; /** @enum {string} */ - type: 'gender'; + type: 'language'; variant: string; - output: components['schemas']['OutputModuleGender']; }; /** ModuleLiteracy */ ModuleLiteracy: { + output: components['schemas']['OutputModuleLiteracy']; /** @enum {string} */ type: 'literacy'; variant: string; - output: components['schemas']['OutputModuleLiteracy']; }; - /** ModuleLanguage */ - ModuleLanguage: { + ModuleOutOfScope: { + output: string; /** @enum {string} */ - type: 'language'; + type: 'out_of_scope'; variant: string; + }; + /** ModuleSetupNote */ + ModuleSetupNote: { output: string; + /** @enum {string} */ + type: 'setup_note'; + variant: string; }; /** ModuleTarget */ ModuleTarget: { + output: number; /** @enum {string} */ type: 'target'; variant: string; - output: number; }; /** ModuleTargetNote */ ModuleTargetNote: { + output: string; /** @enum {string} */ type: 'target_note'; variant: string; - output: string; }; - /** ModuleSetupNote */ - ModuleSetupNote: { + /** ModuleTask */ + ModuleTask: { + output: components['schemas']['OutputModuleTask'][]; /** @enum {string} */ - type: 'setup_note'; + type: 'tasks'; variant: string; - output: string; }; - /** ModuleInstructionNote */ - ModuleInstructionNote: { - /** @enum {string} */ - type: 'instruction_note'; - variant: string; + ModuleTitle: { output: string; - }; - /** ModuleBrowser */ - ModuleBrowser: { /** @enum {string} */ - type: 'browser'; + type: 'title'; variant: string; - output: components['schemas']['OutputModuleBrowser']; }; - /** ModuleAdditionalTarget */ - ModuleAdditionalTarget: { + /** ModuleTouchpoints */ + ModuleTouchpoints: { + output: components['schemas']['OutputModuleTouchpoints'][]; /** @enum {string} */ - type: 'additional_target'; + type: 'touchpoints'; variant: string; - output: string; }; /** Observation */ Observation: { - id: number; - title: string; description: string; /** Format: float */ - start: number; - /** Format: float */ end: number; + id: number; quotes: string; - uxNote?: string; + /** Format: float */ + start: number; tags: components['schemas']['VideoTag'][]; + title: string; + uxNote?: string; }; /** * Output @@ -1032,59 +1067,241 @@ export interface components { * @enum {string} */ Output: 'bugs' | 'media' | 'insights'; - /** PaginationData */ - PaginationData: { - start?: number; - size?: number; - limit?: number; - total?: number; + /** OutputModuleAge */ + OutputModuleAge: { + max: number; + min: number; + percentage: number; + }[]; + /** OutputModuleBrowser */ + OutputModuleBrowser: { + /** @enum {string} */ + name: 'firefox' | 'edge' | 'chrome' | 'safari'; + percentage: number; + }[]; + /** OutputModuleGender */ + OutputModuleGender: { + /** @enum {string} */ + gender: 'male' | 'female'; + percentage: number; + }[]; + /** OutputModuleLiteracy */ + OutputModuleLiteracy: { + /** @enum {string} */ + level: 'beginner' | 'intermediate' | 'expert'; + percentage: number; + }[]; + /** SubcomponentTask */ + OutputModuleTask: + | components['schemas']['OutputModuleTaskVideo'] + | components['schemas']['OutputModuleTaskBug'] + | components['schemas']['OutputModuleTaskSurvey'] + | components['schemas']['OutputModuleTaskModerateVideo'] + | components['schemas']['OutputModuleTaskExplorativeBug'] + | components['schemas']['OutputModuleTaskAccessibility']; + /** OutputModuleTaskAccessibility */ + OutputModuleTaskAccessibility: { + description?: string; + /** @enum {string} */ + kind: 'accessibility'; + title: string; + /** Format: uri */ + url?: string; }; - Paragraph: { - text: string; - start: number; - end: number; - /** @description Id Of speaker */ - speaker?: number; - words: components['schemas']['Word'][]; + /** SubcomponentTaskBug */ + OutputModuleTaskBug: { + description?: string; + /** @enum {string} */ + kind: 'bug'; + title: string; + /** Format: uri */ + url?: string; }; - /** Platform Object */ - Platform: { - /** @description os */ - id: number; - /** - * @description form_factor - * - * 0 => smartphone, - * 1 => tablet - * 2 => pc - * 3 => smartwatch - * 4 => console - * 5 => tv - */ - deviceType: number; + /** OutputModuleTaskExplorativeBug */ + OutputModuleTaskExplorativeBug: { + description?: string; + /** @enum {string} */ + kind: 'explorative-bug'; + title: string; + /** Format: uri */ + url?: string; }; - /** Project */ - Project: { - id: number; - name: string; - campaigns_count: number; - workspaceId: number; + /** OutputModuleTaskModerateVideo */ + OutputModuleTaskModerateVideo: { description?: string; - is_archive?: number; + /** @enum {string} */ + kind: 'moderate-video'; + title: string; + /** Format: uri */ + url?: string; }; - /** Report */ - Report: { - id?: number; - title?: string; + /** SubcomponentTaskSurvey */ + OutputModuleTaskSurvey: { description?: string; - url: string; - file_type?: { - extension?: components['schemas']['ReportExtensions']; - type: string; - domain_name?: string; + /** @enum {string} */ + kind: 'survey'; + title: string; + /** Format: uri */ + url?: string; + }; + /** SubcomponentTaskVideo */ + OutputModuleTaskVideo: { + description?: string; + /** @enum {string} */ + kind: 'video'; + title: string; + /** Format: uri */ + url?: string; + }; + /** SubcomponentTouchpoints */ + OutputModuleTouchpoints: + | components['schemas']['OutputModuleTouchpointsAppDesktop'] + | components['schemas']['OutputModuleTouchpointsAppTablet'] + | components['schemas']['OutputModuleTouchpointsAppSmartphone'] + | components['schemas']['OutputModuleTouchpointsWebDesktop'] + | components['schemas']['OutputModuleTouchpointsWebTablet'] + | components['schemas']['OutputModuleTouchpointsWebSmartphone']; + /** OutputModuleTouchpointsAppDesktop */ + OutputModuleTouchpointsAppDesktop: { + /** @enum {undefined} */ + form_factor: 'desktop'; + /** @enum {undefined} */ + kind: 'app'; + os: { + linux?: string; + macos?: string; + windows?: string; + }; + }; + /** OutputModuleTouchpointsAppSmartphone */ + OutputModuleTouchpointsAppSmartphone: { + /** @enum {undefined} */ + form_factor: 'smartphone'; + /** @enum {undefined} */ + kind: 'app'; + os: { + android?: string; + ios?: string; + }; + }; + /** OutputModuleTouchpointsAppTablet */ + OutputModuleTouchpointsAppTablet: { + /** @enum {undefined} */ + form_factor: 'tablet'; + /** @enum {undefined} */ + kind: 'app'; + os: { + ios?: string; + linux?: string; + windows?: string; + }; + }; + /** OutputModuleTouchpointsWebDesktop */ + OutputModuleTouchpointsWebDesktop: { + /** @enum {undefined} */ + form_factor: 'desktop'; + /** @enum {undefined} */ + kind: 'web'; + os: { + linux?: string; + macos?: string; + windows?: string; + }; + }; + /** OutputModuleTouchpointsWebSmartphone */ + OutputModuleTouchpointsWebSmartphone: { + /** @enum {undefined} */ + form_factor: 'smartphone'; + /** @enum {undefined} */ + kind: 'web'; + os: { + android?: string; + ios?: string; }; + }; + /** OutputModuleTouchpointsWebTablet */ + OutputModuleTouchpointsWebTablet: { + /** @enum {undefined} */ + form_factor: 'tablet'; + /** @enum {undefined} */ + kind: 'web'; + os: { + android?: string; + ios?: string; + }; + }; + /** PaginationData */ + PaginationData: { + limit?: number; + size?: number; + start?: number; + total?: number; + }; + Paragraph: { + end: number; + /** @description Id Of speaker */ + speaker?: number; + start: number; + text: string; + words: components['schemas']['Word'][]; + }; + /** + * PlanStatus + * @enum {string} + */ + PlanStatus: 'pending_review' | 'draft' | 'approved'; + /** Platform Object */ + Platform: { + /** + * @description form_factor + * + * 0 => smartphone, + * 1 => tablet + * 2 => pc + * 3 => smartwatch + * 4 => console + * 5 => tv + */ + deviceType: number; + /** @description os */ + id: number; + }; + /** Data for post-users request for invited user */ + PostUserInviteData: { + profileId: number; + token: string; + /** @enum {string} */ + type: 'invite'; + }; + /** Data for post-users request for new user */ + PostUserNewData: { + email: string; + /** @enum {string} */ + type: 'new'; + workspace: string; + }; + /** Project */ + Project: { + campaigns_count: number; + description?: string; + id: number; + is_archive?: number; + name: string; + workspaceId: number; + }; + /** Report */ + Report: { creation_date?: string; + description?: string; + file_type?: { + domain_name?: string; + extension?: components['schemas']['ReportExtensions']; + type: string; + }; + id?: number; + title?: string; update_date?: string; + url: string; }; /** * ReportExtensions @@ -1114,6 +1331,50 @@ export interface components { /** @enum {string} */ type: 'smartphone'; }; + StrapiTemplate: { + background?: string; + description: string; + how?: { + description: string; + /** Format: uri */ + icon: string; + title: string; + }[]; + /** Format: uri */ + image?: string; + /** Format: uri */ + output_image?: string; + pre_title: string; + price?: { + /** @default 0 */ + is_strikethrough?: number; + previous_price?: string; + price: string; + }; + requirements?: { + description: string; + list: string[]; + }; + tags: { + /** Format: uri */ + icon: string; + text: string; + }[]; + title: string; + what?: { + description: string; + goal: string; + }; + why?: { + advantages: string[]; + reasons: { + description: string; + /** Format: uri */ + icon: string; + title: string; + }[]; + }; + }; /** Tablet */ Tablet: { manufacturer: string; @@ -1123,111 +1384,74 @@ export interface components { /** @enum {string} */ type: 'tablet'; }; - /** - * Template - * @description Template of a usecase object - */ - Template: { - title: string; - /** @description Short description used as preview of template or in templates dropdown */ - description?: string; - /** @description HTML content used to pre-fill the use case editor */ - content?: string; - category?: components['schemas']['TemplateCategory']; - /** @enum {string} */ - device_type?: 'webapp' | 'mobileapp'; - /** - * @default en - * @enum {string} - */ - locale?: 'en' | 'it'; - /** Format: uri */ - image?: string; - /** - * @description The use case created by this template needs a login or not? - * @default false - */ - requiresLogin?: boolean; - }; - /** - * TemplateCategory - * @description Group different templates - */ - TemplateCategory: { - id?: number; - name: string; - }; /** Tenant */ Tenant: { + email: string; /** @description tryber wp_user_id */ id: number; - profile_id: number; - name: string; - email: string; invitationPending: boolean; + name: string; permissionFrom?: { + id?: number; /** @enum {string} */ type?: 'workspace' | 'project'; - id?: number; }; + profile_id: number; }; Transcript: { + paragraphs: components['schemas']['Paragraph'][]; /** @description Number of spekers */ speakers: number; - paragraphs: components['schemas']['Paragraph'][]; }; /** UseCase */ UseCase: { - title: string; description: string; - /** @description Optional in experiential campaigns */ - functionality?: { - id?: number; - } & components['schemas']['Template']; - logged?: boolean; link?: string; + logged?: boolean; + title: string; }; /** User */ User: { - /** @description This is the main id of the user. Currently is equal to tryber_wp_user_id */ - id: number; + customer_role: string; /** Format: email */ email: string; - role: string; + features?: components['schemas']['Feature'][]; + /** @description This is the main id of the user. Currently is equal to tryber_wp_user_id */ + id: number; name: string; + picture?: string; profile_id: number; + role: string; tryber_wp_user_id: number; unguess_wp_user_id: number; - picture?: string; - features?: components['schemas']['Feature'][]; }; /** UserPreference */ UserPreference: { + name: string; preference_id: number; value: string; - name: string; }; /** * Video * @description Video uploaded from a user */ Video: { + duration?: number; id: number; - url: string; - streamUrl?: string; poster?: string; - duration?: number; + sentiment?: components['schemas']['MediaSentiment']; + streamUrl?: string; tester: { - id: number; - name: string; - surname: string; device: { /** @enum {string} */ type: 'smartphone' | 'tablet' | 'desktop' | 'other'; }; + id: number; + name: string; + surname: string; }; transcript?: components['schemas']['Transcript']; - sentiment?: components['schemas']['MediaSentiment']; + url: string; }; /** VideoTag */ VideoTag: { @@ -1252,9 +1476,9 @@ export interface components { | components['schemas']['Desktop'] | components['schemas']['Tablet'] ) & { - unique_bugs: number; /** @description Unique bugs */ bugs: number; + unique_bugs: number; })[]; /** * @default bugsByDevice @@ -1280,15 +1504,15 @@ export interface components { */ WidgetBugsByUseCase: { data: { + bugs: number; + description: string; title: { full: string; - simple?: string; - prefix?: string; info?: string; + prefix?: string; + simple?: string; }; - description: string; uniqueBugs?: number; - bugs: number; usecase_completion?: number; usecase_id: number; }[]; @@ -1305,18 +1529,18 @@ export interface components { */ WidgetCampaignProgress: { data: { - start_date: string; end_date: string; + /** @description Expected amount of hours required to complete the campaign */ + expected_duration: number; + start_date: string; + /** @description Number of hours from start_date */ + time_elapsed: number; /** * Format: float * @description Percentage fixed rate of completion * @enum {number} */ usecase_completion: 12.5 | 37.5 | 62.5 | 87.5 | 100; - /** @description Number of hours from start_date */ - time_elapsed: number; - /** @description Expected amount of hours required to complete the campaign */ - expected_duration: number; }; /** * @default campaignProgress @@ -1331,9 +1555,9 @@ export interface components { */ WidgetCampaignUniqueBugs: { data: { - unique: number; total: number; trend: number; + unique: number; }; /** * @default campaignUniqueBugs @@ -1342,29 +1566,41 @@ export interface components { */ kind: 'campaignUniqueBugs'; }; + /** WidgetCampaignUxMostUsedTitles */ + WidgetCampaignUxMostUsedTitles: { + data: { + mostUsedTitles: { + mainSeverityAssignment: string; + title: string; + usage: number; + }[]; + }; + /** @enum {undefined} */ + kind: 'uxMostUsedTitles'; + }; /** * WidgetCampaignUxProgress * @description Used to show an overview of Ux progress */ WidgetCampaignUxProgress: { data: { - countMediaWithObservation?: number; countMedia?: number; - countTitleTag?: number; + countMediaWithObservation?: number; countObservation?: number; countObservationNoTitle?: number; countRecurrentTitles?: number; - severitiesDistribution?: { - countPositiveFindings: number; - countMinorIssue: number; - countMajorIssue: number; - countObservations: number; - }; + countTitleTag?: number; mostUsedTitles?: { + mainSeverityAssignment: string; title: string; usage: number; - mainSeverityAssignment: string; }[]; + severitiesDistribution?: { + countMajorIssue: number; + countMinorIssue: number; + countObservations: number; + countPositiveFindings: number; + }; }; /** * @default uxTaggingVideoCompletion @@ -1377,312 +1613,70 @@ export interface components { | 'uxSeveritiesDistribution' | 'uxMostUsedTitles'; }; - Word: { - start: number; - end: number; - /** @description Id of Speaker */ - speaker?: number; - word: string; - }; - /** - * Workspace - * @description A workspace is the company area with projects and campaigns - */ - Workspace: { - id: number; - company: string; - tokens: number; - logo?: string; - csm: { - id: number; - email: string; - name: string; - profile_id: number; - tryber_wp_user_id: number; - picture?: string; - url?: string; - }; - /** @description express coins */ - coins?: number; - /** @description Do this workspace have shared items? */ - isShared?: boolean; - /** @description Number of shared items */ - sharedItems?: number; - }; - /** WidgetCampaignUxTaggingVideoCompletionData */ - WidgetCampaignUxTaggingVideoCompletionData: { - data: { - countMediaWithObservation: number; - countMedia: number; - }; - /** @enum {undefined} */ - kind: 'uxTaggingVideoCompletion'; - }; - /** WidgetCampaignUxTotalTitlesVsRecurrentTitles */ - WidgetCampaignUxTotalTitlesVsRecurrentTitles: { - data: { - countTitleTag: number; - countObservationNoTitle: number; - countRecurrentTitles: number; - }; - /** @enum {undefined} */ - kind: 'uxTotalTitlesVsRecurrentTitles'; - }; /** WidgetCampaignUxSeveritiesDistribution */ WidgetCampaignUxSeveritiesDistribution: { data: { countObservations: number; severitiesDistribution: { - countPositiveFindings: number; - countMinorIssue: number; countMajorIssue: number; + countMinorIssue: number; countObservationSeverity: number; + countPositiveFindings: number; }; }; /** @enum {undefined} */ kind: 'uxSeveritiesDistribution'; }; - /** WidgetCampaignUxMostUsedTitles */ - WidgetCampaignUxMostUsedTitles: { + /** WidgetCampaignUxTaggingVideoCompletionData */ + WidgetCampaignUxTaggingVideoCompletionData: { data: { - mostUsedTitles: { - title: string; - usage: number; - mainSeverityAssignment: string; - }[]; - }; - /** @enum {undefined} */ - kind: 'uxMostUsedTitles'; - }; - /** - * BannerType - * @enum {string} - */ - BannerType: - | 'banner_testing_automation' - | 'banner_user_experience' - | 'banner_cyber_security'; - /** CpReqTemplate */ - CpReqTemplate: { - id: number; - name: string; - description?: string; - config: string; - workspace_id?: number; - price?: string; - strapi?: components['schemas']['StrapiTemplate']; - }; - /** SubcomponentTaskBug */ - OutputModuleTaskBug: { - /** @enum {string} */ - kind: 'bug'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** OutputModuleAge */ - OutputModuleAge: { - min: number; - max: number; - percentage: number; - }[]; - /** SubcomponentTaskVideo */ - OutputModuleTaskVideo: { - /** @enum {string} */ - kind: 'video'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** SubcomponentTaskSurvey */ - OutputModuleTaskSurvey: { - /** @enum {string} */ - kind: 'survey'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** OutputModuleTaskModerateVideo */ - OutputModuleTaskModerateVideo: { - /** @enum {string} */ - kind: 'moderate-video'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** OutputModuleTaskExplorativeBug */ - OutputModuleTaskExplorativeBug: { - /** @enum {string} */ - kind: 'explorative-bug'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** OutputModuleTaskAccessibility */ - OutputModuleTaskAccessibility: { - /** @enum {string} */ - kind: 'accessibility'; - title: string; - description?: string; - /** Format: uri */ - url?: string; - }; - /** SubcomponentTask */ - OutputModuleTask: - | components['schemas']['OutputModuleTaskVideo'] - | components['schemas']['OutputModuleTaskBug'] - | components['schemas']['OutputModuleTaskSurvey'] - | components['schemas']['OutputModuleTaskModerateVideo'] - | components['schemas']['OutputModuleTaskExplorativeBug'] - | components['schemas']['OutputModuleTaskAccessibility']; - /** SubcomponentTouchpoints */ - OutputModuleTouchpoints: - | components['schemas']['OutputModuleTouchpointsAppDesktop'] - | components['schemas']['OutputModuleTouchpointsAppTablet'] - | components['schemas']['OutputModuleTouchpointsAppSmartphone'] - | components['schemas']['OutputModuleTouchpointsWebDesktop'] - | components['schemas']['OutputModuleTouchpointsWebTablet'] - | components['schemas']['OutputModuleTouchpointsWebSmartphone']; - /** OutputModuleTouchpointsAppDesktop */ - OutputModuleTouchpointsAppDesktop: { - /** @enum {undefined} */ - kind: 'app'; - /** @enum {undefined} */ - form_factor: 'desktop'; - os: { - linux?: string; - macos?: string; - windows?: string; - }; - }; - /** OutputModuleTouchpointsAppTablet */ - OutputModuleTouchpointsAppTablet: { - /** @enum {undefined} */ - kind: 'app'; - /** @enum {undefined} */ - form_factor: 'tablet'; - os: { - linux?: string; - ios?: string; - windows?: string; + countMedia: number; + countMediaWithObservation: number; }; - }; - /** OutputModuleTouchpointsAppSmartphone */ - OutputModuleTouchpointsAppSmartphone: { - /** @enum {undefined} */ - kind: 'app'; /** @enum {undefined} */ - form_factor: 'smartphone'; - os: { - android?: string; - ios?: string; - }; + kind: 'uxTaggingVideoCompletion'; }; - /** OutputModuleTouchpointsWebDesktop */ - OutputModuleTouchpointsWebDesktop: { - /** @enum {undefined} */ - kind: 'web'; - /** @enum {undefined} */ - form_factor: 'desktop'; - os: { - linux?: string; - macos?: string; - windows?: string; + /** WidgetCampaignUxTotalTitlesVsRecurrentTitles */ + WidgetCampaignUxTotalTitlesVsRecurrentTitles: { + data: { + countObservationNoTitle: number; + countRecurrentTitles: number; + countTitleTag: number; }; - }; - /** OutputModuleTouchpointsWebTablet */ - OutputModuleTouchpointsWebTablet: { - /** @enum {undefined} */ - kind: 'web'; /** @enum {undefined} */ - form_factor: 'tablet'; - os: { - android?: string; - ios?: string; - }; + kind: 'uxTotalTitlesVsRecurrentTitles'; }; - /** OutputModuleTouchpointsWebSmartphone */ - OutputModuleTouchpointsWebSmartphone: { - /** @enum {undefined} */ - kind: 'web'; - /** @enum {undefined} */ - form_factor: 'smartphone'; - os: { - android?: string; - ios?: string; - }; + Word: { + end: number; + /** @description Id of Speaker */ + speaker?: number; + start: number; + word: string; }; - /** OutputModuleLiteracy */ - OutputModuleLiteracy: { - /** @enum {string} */ - level: 'beginner' | 'intermediate' | 'expert'; - percentage: number; - }[]; - /** OutputModuleGender */ - OutputModuleGender: { - /** @enum {string} */ - gender: 'male' | 'female'; - percentage: number; - }[]; - /** OutputModuleBrowser */ - OutputModuleBrowser: { - /** @enum {string} */ - name: 'firefox' | 'edge' | 'chrome' | 'safari'; - percentage: number; - }[]; /** - * PlanStatus - * @enum {string} + * Workspace + * @description A workspace is the company area with projects and campaigns */ - PlanStatus: 'pending_review' | 'draft' | 'approved'; - StrapiTemplate: { - title: string; - description: string; - pre_title: string; - /** Format: uri */ - image?: string; - /** Format: uri */ - output_image?: string; - requirements?: { - description: string; - list: string[]; - }; - tags: { - /** Format: uri */ - icon: string; - text: string; - }[]; - why?: { - reasons: { - /** Format: uri */ - icon: string; - title: string; - description: string; - }[]; - advantages: string[]; - }; - what?: { - description: string; - goal: string; - }; - how?: { - /** Format: uri */ - icon: string; - title: string; - description: string; - }[]; - price?: { - price: string; - previous_price?: string; - /** @default 0 */ - is_strikethrough?: number; + Workspace: { + /** @description express coins */ + coins?: number; + company: string; + csm: { + email: string; + id: number; + name: string; + picture?: string; + profile_id: number; + tryber_wp_user_id: number; + url?: string; }; - background?: string; + id: number; + /** @description Do this workspace have shared items? */ + isShared?: boolean; + logo?: string; + /** @description Number of shared items */ + sharedItems?: number; + tokens: number; }; }; responses: { @@ -1691,27 +1685,33 @@ export interface components { content: { 'application/json': components['schemas']['Error']; }; - }; - }; - parameters: { - /** @description Workspace (company, customer) id */ - wid: string; - /** @description Project id */ - pid: string; + }; + }; + parameters: { + /** @description Defines an identifier for the bug object (BUG ID) */ + bid: string; + /** @description Campaign id */ + cid: string; + /** @description Custom Status id */ + csid: string; + /** @description filterBy[]= */ + filterBy: unknown; + /** @description Insight id */ + iid: string; /** @description Limit pagination parameter */ limit: number; - /** @description Start pagination parameter */ - start: number; /** @description Order value (ASC, DESC) */ order: string; /** @description Order by accepted field */ orderBy: string; - /** @description filterBy[]= */ - filterBy: unknown; - /** @description Campaign id */ - cid: string; - /** @description Defines an identifier for the bug object (BUG ID) */ - bid: string; + /** @description Project id */ + pid: string; + /** @description keywords to search */ + search: string; + /** @description Start pagination parameter */ + start: number; + /** @description Workspace (company, customer) id */ + wid: string; /** @description Campaign widget slug */ wslug: | 'bugs-by-usecase' @@ -1723,67 +1723,51 @@ export interface components { | 'ux-total-titles-vs-recurrent-titles' | 'ux-severities-distribution' | 'ux-most-used-titles'; - /** @description keywords to search */ - search: string; - /** @description Custom Status id */ - csid: string; - /** @description Insight id */ - iid: string; }; requestBodies: { - Credentials: { - content: { - 'application/json': { - username: string; - password: string; - }; - }; - }; Campaign: { content: { 'application/json': { - title: string; - start_date: string; - end_date: string; - close_date: string; - customer_title?: string; - status_id?: number; - is_public?: number; + base_bug_internal_id?: string; + browsers?: number[]; campaign_type_id: number; - project_id: number; - pm_id: number; - platforms: components['schemas']['Platform'][]; - /** @description Da togliere */ - page_preview_id?: number; - /** @description Da togliere */ - page_manual_id?: number; + close_date: string; /** @description Used to check available coins */ customer_id: number; + customer_title?: string; + description?: string; + end_date: string; + goal?: string; has_bug_form?: number; /** @description if has_bug_form is 0 this has to be 0 */ has_bug_parade?: number; - description?: string; - base_bug_internal_id?: string; - express_slug: string; - use_cases?: components['schemas']['UseCase'][]; - productType?: number; - productLink?: string; - browsers?: number[]; + is_public?: number; languages?: string[]; outOfScope?: string; - testerRequirements?: string; + /** @description Da togliere */ + page_manual_id?: number; + /** @description Da togliere */ + page_preview_id?: number; + platforms: components['schemas']['Platform'][]; + pm_id: number; + productLink?: string; + productType?: number; + project_id: number; + start_date: string; + status_id?: number; targetSize?: number; - goal?: string; testDescription?: string; + testerRequirements?: string; + title: string; + use_cases?: components['schemas']['UseCase'][]; }; }; }; - Project: { + Credentials: { content: { 'application/json': { - name: string; - customer_id: number; - description?: string; + password: string; + username: string; }; }; }; @@ -1791,12 +1775,21 @@ export interface components { content: { 'application/json': { email: string; - name?: string; - surname?: string; - locale?: string; event_name?: string; - redirect_url?: string; + locale?: string; message?: string; + name?: string; + redirect_url?: string; + surname?: string; + }; + }; + }; + Project: { + content: { + 'application/json': { + customer_id: number; + description?: string; + name: string; }; }; }; @@ -1817,20 +1810,6 @@ export interface operations { 500: components['responses']['Error']; }; }; - /** A request to login with your username and password */ - 'post-authenticate': { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - 'application/json': components['schemas']['Authentication']; - }; - }; - 500: components['responses']['Error']; - }; - requestBody: components['requestBodies']['Credentials']; - }; 'post-analytics-views-campaigns-cid': { parameters: { path: { @@ -1850,21 +1829,19 @@ export interface operations { 500: components['responses']['Error']; }; }; - 'post-campaigns': { + /** A request to login with your username and password */ + 'post-authenticate': { parameters: {}; responses: { /** OK */ 200: { content: { - 'application/json': components['schemas']['Campaign']; + 'application/json': components['schemas']['Authentication']; }; }; - 400: components['responses']['Error']; - 403: components['responses']['Error']; - 404: components['responses']['Error']; 500: components['responses']['Error']; }; - requestBody: components['requestBodies']['Campaign']; + requestBody: components['requestBodies']['Credentials']; }; 'get-campaign': { parameters: { @@ -1955,21 +1932,21 @@ export interface operations { content: { 'application/json': { items?: (components['schemas']['Bug'] & { - tags?: { - tag_id: number; - tag_name: string; - }[]; - siblings: number; - comments: number; additional_fields?: { + name: string; slug: string; value: string; - name: string; + }[]; + comments: number; + siblings: number; + tags?: { + tag_id: number; + tag_name: string; }[]; })[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -1994,13 +1971,13 @@ export interface operations { 200: { content: { 'application/json': components['schemas']['Bug'] & { - media: components['schemas']['BugMedia'][]; - tags: components['schemas']['BugTag'][]; additional_fields: components['schemas']['BugAdditionalField'][]; + media: components['schemas']['BugMedia'][]; reporter: { - tester_id: number; name: string; + tester_id: number; }; + tags: components['schemas']['BugTag'][]; }; }; }; @@ -2024,12 +2001,12 @@ export interface operations { 200: { content: { 'application/json': { + custom_status?: components['schemas']['BugCustomStatus']; + priority?: components['schemas']['BugPriority']; tags?: { tag_id: number; tag_name: string; }[]; - priority?: components['schemas']['BugPriority']; - custom_status?: components['schemas']['BugCustomStatus']; }; }; }; @@ -2037,6 +2014,8 @@ export interface operations { requestBody: { content: { 'application/json': { + custom_status_id?: number; + priority_id?: number; tags?: ( | { tag_id: number; @@ -2045,8 +2024,6 @@ export interface operations { tag_name: string; } )[]; - priority_id?: number; - custom_status_id?: number; }; }; }; @@ -2097,24 +2074,23 @@ export interface operations { requestBody: { content: { 'application/json': { - text: string; - mentioned?: { + media_id?: { id: number; }[]; - media_id?: { + mentioned?: { id: number; }[]; + text: string; }; }; }; }; - 'post-campaigns-cid-bugs-bid-media': { + 'post-campaigns-cid-bugs-bid-comments-cmid-media': { parameters: { path: { - /** Campaign id */ cid: string; - /** Defines an identifier for the bug object (BUG ID) */ bid: string; + cmid: string; }; }; responses: { @@ -2123,12 +2099,16 @@ export interface operations { content: { 'application/json': { failed?: { - name: string; /** @enum {string} */ errorCode: | 'FILE_TOO_BIG' | 'INVALID_FILE_EXTENSION' | 'GENERIC_ERROR'; + name: string; + }[]; + files?: { + name: string; + path: string; }[]; uploaded_ids?: { id: number; @@ -2145,7 +2125,7 @@ export interface operations { }; }; }; - 'post-campaigns-cid-bugs-bid-comments-cmid-media': { + 'delete-campaigns-cid-bugs-bid-comments-cmid': { parameters: { path: { cid: string; @@ -2153,22 +2133,40 @@ export interface operations { cmid: string; }; }; + responses: { + /** OK */ + 200: unknown; + 400: components['responses']['Error']; + 403: components['responses']['Error']; + 500: components['responses']['Error']; + }; + requestBody: { + content: { + 'application/json': { [key: string]: unknown }; + }; + }; + }; + 'post-campaigns-cid-bugs-bid-media': { + parameters: { + path: { + /** Campaign id */ + cid: string; + /** Defines an identifier for the bug object (BUG ID) */ + bid: string; + }; + }; responses: { /** OK */ 200: { content: { 'application/json': { - files?: { - name: string; - path: string; - }[]; failed?: { - name: string; /** @enum {string} */ errorCode: | 'FILE_TOO_BIG' | 'INVALID_FILE_EXTENSION' | 'GENERIC_ERROR'; + name: string; }[]; uploaded_ids?: { id: number; @@ -2185,27 +2183,6 @@ export interface operations { }; }; }; - 'delete-campaigns-cid-bugs-bid-comments-cmid': { - parameters: { - path: { - cid: string; - bid: string; - cmid: string; - }; - }; - responses: { - /** OK */ - 200: unknown; - 400: components['responses']['Error']; - 403: components['responses']['Error']; - 500: components['responses']['Error']; - }; - requestBody: { - content: { - 'application/json': { [key: string]: unknown }; - }; - }; - }; 'get-campaigns-bug-siblings': { parameters: { path: { @@ -2221,32 +2198,32 @@ export interface operations { content: { 'application/json': { father?: { - id: number; - title: { - full: string; - compact: string; - context?: string[]; - }; context?: string; device: string; + id: number; os: { name: string; version: string; }; - }; - siblings: { - id: number; title: { - full: string; compact: string; context?: string[]; + full: string; }; + }; + siblings: { context?: string; device: string; + id: number; os: { name: string; version: string; }; + title: { + compact: string; + context?: string[]; + full: string; + }; }[]; }; }; @@ -2340,10 +2317,10 @@ export interface operations { requestBody: { content: { 'application/json': { + color: string; /** @description se esiste già questo parametro viene passato nel request body\r\nse invece non esiste ed il custom status deve essere creato, non viene passato */ custom_status_id?: number; name: string; - color: string; }[]; }; }; @@ -2435,11 +2412,11 @@ export interface operations { requestBody: { content: { 'application/json': { - title: string; + comment?: string; description?: string; - severity_id: number; observations_ids: number[]; - comment?: string; + severity_id: number; + title: string; visible?: number; }; }; @@ -2458,9 +2435,9 @@ export interface operations { 200: { content: { 'application/json': components['schemas']['Campaign'] & { - selected_testers: number; /** @description Array of form factors */ allowed_devices: string[]; + selected_testers: number; }; }; }; @@ -2489,37 +2466,37 @@ export interface operations { content: { 'application/json': | { + /** + * @default usecase-grapes + * @example usecase-grapes + * @enum {string} + */ + kind: 'usecase-grapes'; results: { - usecaseId: number; - usecaseTitle: string; grapes: components['schemas']['Grapes'][]; ungrouped: (components['schemas']['Observation'] & { - uploaderId: number; - mediaId: number; deviceType: string; + mediaId: number; + uploaderId: number; usecaseTitle: string; })[]; + usecaseId: number; + usecaseTitle: string; }[]; - /** - * @default usecase-grapes - * @example usecase-grapes - * @enum {string} - */ - kind: 'usecase-grapes'; } | { - results: (components['schemas']['Observation'] & { - uploaderId: number; - mediaId: number; - deviceType: string; - usecaseTitle: string; - })[]; /** * @default ungrouped * @example ungrouped * @enum {string} */ kind: 'ungrouped'; + results: (components['schemas']['Observation'] & { + deviceType: string; + mediaId: number; + uploaderId: number; + usecaseTitle: string; + })[]; }; }; }; @@ -2635,9 +2612,9 @@ export interface operations { content: { 'application/json': { suggestion?: { - slug: components['schemas']['BannerType']; /** @description ServiceId from strapi */ serviceId?: number; + slug: components['schemas']['BannerType']; }; }; }; @@ -2682,10 +2659,10 @@ export interface operations { 200: { content: { 'application/json': { - tag_id: number; display_name: string; - slug: string; is_public?: number; + slug: string; + tag_id: number; }[]; }; }; @@ -2710,14 +2687,15 @@ export interface operations { 200: { content: { 'application/json': { + completion: number; + content?: string; id: number; title: { full: string; - simple?: string; - prefix?: string; info?: string; + prefix?: string; + simple?: string; }; - completion: number; }[]; }; }; @@ -2750,9 +2728,9 @@ export interface operations { content: { 'application/json': { items: components['schemas']['Tenant'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -2775,9 +2753,9 @@ export interface operations { 200: { content: { 'application/json': { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; }; }; @@ -2834,49 +2812,49 @@ export interface operations { 200: { content: { 'application/json': { - goal?: string; - users?: number; findings?: { + cluster: + | { + id: number; + name: string; + }[] + | 'all'; + comment?: string; + description: string; /** @description this field is the Finding ID */ id: number; - title: string; - description: string; - comment?: string; severity: { id: number; name: string; style: string; }; - cluster: - | { - id: number; - name: string; - }[] - | 'all'; + title: string; video?: { - url: string; - streamUrl: string; + description?: string; + end: number; poster?: string; start: number; - end: number; - description?: string; + streamUrl: string; + url: string; }[]; }[]; + goal?: string; + methodology?: { + description: string; + type: string; + }; + questions?: { + text: string; + }[]; sentiment?: { cluster: { id: number; name: string; }; - value: number; comment: string; + value: number; }[]; - methodology?: { - type: string; - description: string; - }; - questions?: { - text: string; - }[]; + users?: number; }; }; }; @@ -3065,25 +3043,37 @@ export interface operations { requestBody: { content: { 'application/json': { - title?: string; + comment?: string; description?: string; - severity_id?: number; observations_ids?: number[]; - comment?: string; + severity_id?: number; + title?: string; visible?: number; }; }; }; }; - 'get-media-id': { + 'get-invites-profile-token': { parameters: { path: { - id: string; + profile: string; + token: string; }; }; responses: { - /** Found */ - 302: never; + /** OK */ + 200: { + content: { + 'application/json': { + email: string; + name: string; + surname: string; + workspace: string; + }; + }; + }; + /** Bad Request */ + 400: unknown; }; }; /** Delete a media-comment */ @@ -3106,6 +3096,113 @@ export interface operations { 404: unknown; }; }; + 'get-media-id': { + parameters: { + path: { + id: string; + }; + }; + responses: { + /** Found */ + 302: never; + }; + }; + 'get-workspaces-wid-plans-pid': { + parameters: { + path: { + pid: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + 'application/json': { + campaign?: { + id: number; + startDate: string; + /** @description CustomerTitle ?? Title */ + title: string; + }; + config: { + modules: components['schemas']['Module'][]; + }; + id: number; + project: { + id: number; + name: string; + }; + quote?: { + id: number; + /** @enum {string} */ + status: 'pending' | 'proposed' | 'approved' | 'rejected'; + value: string; + }; + status: components['schemas']['PlanStatus']; + workspace_id: number; + }; + }; + }; + }; + }; + 'delete-workspaces-wid-plans-pid': { + parameters: { + path: { + pid: string; + }; + }; + responses: { + /** OK */ + 200: unknown; + }; + }; + 'patch-workspaces-wid-plans-pid': { + parameters: { + path: { + pid: string; + }; + }; + responses: { + /** OK */ + 200: unknown; + /** Forbidden */ + 403: unknown; + /** Not Found */ + 404: unknown; + }; + requestBody: { + content: { + 'application/json': { + config: { + modules: components['schemas']['Module'][]; + }; + }; + }; + }; + }; + /** */ + 'patch-workspaces-wid-plans-pid-status': { + parameters: { + path: { + pid: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + 'application/json': { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + 'application/json': { + status: components['schemas']['PlanStatus']; + }; + }; + }; + }; 'post-projects': { responses: { /** OK */ @@ -3214,9 +3311,9 @@ export interface operations { content: { 'application/json': { items?: components['schemas']['CampaignWithOutput'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3252,9 +3349,9 @@ export interface operations { content: { 'application/json': { items: components['schemas']['Tenant'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3277,9 +3374,9 @@ export interface operations { 200: { content: { 'application/json': { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; }; }; @@ -3298,52 +3395,69 @@ export interface operations { }; }; responses: { - /** OK */ - 200: { + /** OK */ + 200: { + content: { + 'application/json': { + items: components['schemas']['Tenant'][]; + }; + }; + }; + 400: components['responses']['Error']; + 403: components['responses']['Error']; + 500: components['responses']['Error']; + }; + requestBody: { + content: { + 'application/json': { + include_shared?: boolean; + /** @description Tryber WP USER ID */ + user_id: number; + }; + }; + }; + }; + 'post-users': { + parameters: {}; + responses: { + /** Created */ + 201: { content: { 'application/json': { - items: components['schemas']['Tenant'][]; + projectId?: number; + workspaceId: number; }; }; }; 400: components['responses']['Error']; - 403: components['responses']['Error']; - 500: components['responses']['Error']; }; requestBody: { content: { 'application/json': { - /** @description Tryber WP USER ID */ - user_id: number; - include_shared?: boolean; - }; + name: string; + password: string; + roleId: number; + surname: string; + } & ( + | components['schemas']['PostUserInviteData'] + | components['schemas']['PostUserNewData'] + ); }; }; }; - /** Retrieve all available use case templates */ - 'get-templates': { + 'head-users-by-email-email': { parameters: { - query: { - /** filterBy[]= */ - filterBy?: components['parameters']['filterBy']; - /** Order value (ASC, DESC) */ - order?: components['parameters']['order']; - /** Order by accepted field */ - orderBy?: components['parameters']['orderBy']; + path: { + email: string; }; }; responses: { /** OK */ - 200: { - content: { - 'application/json': ({ - id?: number; - } & components['schemas']['Template'])[]; - }; - }; - 400: components['responses']['Error']; - 403: components['responses']['Error']; - 500: components['responses']['Error']; + 200: unknown; + /** Bad Request */ + 400: unknown; + /** Not Found */ + 404: unknown; }; }; 'get-users-me': { @@ -3397,6 +3511,20 @@ export interface operations { }; }; }; + 'get-users-roles': { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + 'application/json': { + id: number; + name: string; + }[]; + }; + }; + }; + }; /** Retrive single video data */ 'get-videos-vid': { parameters: { @@ -3453,10 +3581,10 @@ export interface operations { requestBody: { content: { 'application/json': { - /** Format: float */ - start: number; /** Format: float */ end: number; + /** Format: float */ + start: number; }; }; }; @@ -3493,14 +3621,14 @@ export interface operations { requestBody: { content: { 'application/json': { - title?: string; description?: string; /** Format: float */ - start?: number; - /** Format: float */ end?: number; quotes?: string; + /** Format: float */ + start?: number; tags?: number[]; + title?: string; }; }; }; @@ -3525,9 +3653,9 @@ export interface operations { /** @default 0 */ processing: number; sentences: { - text: string; - start: number; end: number; + start: number; + text: string; }[]; }; }; @@ -3593,9 +3721,9 @@ export interface operations { content: { 'application/json': { items?: components['schemas']['Workspace'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3613,8 +3741,8 @@ export interface operations { 200: { content: { 'application/json': { - id: number; company: string; + id: number; }; }; }; @@ -3664,10 +3792,10 @@ export interface operations { 200: { content: { 'application/json': { + campaignsCounter: number; + description: string; id: number; name: string; - description: string; - campaignsCounter: number; }; }; }; @@ -3701,9 +3829,9 @@ export interface operations { content: { 'application/json': { items?: components['schemas']['CampaignWithOutput'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3737,9 +3865,9 @@ export interface operations { content: { 'application/json': { items?: components['schemas']['Coin'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3779,9 +3907,6 @@ export interface operations { content: { 'application/json': { id: number; - title: string; - /** @enum {string} */ - status: 'draft' | 'pending_review' | 'approved'; project: { id: number; title: string; @@ -3791,6 +3916,9 @@ export interface operations { /** @enum {string} */ status: 'pending' | 'proposed' | 'approved' | 'rejected'; }; + /** @enum {string} */ + status: 'draft' | 'pending_review' | 'approved'; + title: string; }[]; }; }; @@ -3819,16 +3947,23 @@ export interface operations { requestBody: { content: { 'application/json': { - template_id: number; project_id: number; + template_id: number; }; }; }; }; - 'get-workspaces-wid-plans-pid': { + 'get-workspace-projects': { parameters: { path: { - pid: string; + /** Workspace (company, customer) id */ + wid: components['parameters']['wid']; + }; + query: { + /** Limit pagination parameter */ + limit?: components['parameters']['limit']; + /** Start pagination parameter */ + start?: components['parameters']['start']; }; }; responses: { @@ -3836,96 +3971,49 @@ export interface operations { 200: { content: { 'application/json': { - id: number; - config: { - modules: components['schemas']['Module'][]; - }; - status: components['schemas']['PlanStatus']; - project: { - id: number; - name: string; - }; - quote?: { - id: number; - /** @enum {string} */ - status: 'pending' | 'proposed' | 'approved' | 'rejected'; - value: string; - }; - campaign?: { - id: number; - /** @description CustomerTitle ?? Title */ - title: string; - startDate: string; - }; - workspace_id: number; - }; - }; - }; - }; - }; - 'delete-workspaces-wid-plans-pid': { - parameters: { - path: { - pid: string; - }; - }; - responses: { - /** OK */ - 200: unknown; - }; - }; - 'patch-workspaces-wid-plans-pid': { - parameters: { - path: { - pid: string; - }; - }; - responses: { - /** OK */ - 200: unknown; - /** Forbidden */ - 403: unknown; - /** Not Found */ - 404: unknown; - }; - requestBody: { - content: { - 'application/json': { - config: { - modules: components['schemas']['Module'][]; + items?: components['schemas']['Project'][]; + limit?: number; + size?: number; + start?: number; + total?: number; }; }; }; + 400: components['responses']['Error']; + 403: components['responses']['Error']; + 404: components['responses']['Error']; + 500: components['responses']['Error']; }; }; - /** */ - 'patch-workspaces-wid-plans-pid-status': { + 'get-workspace-project': { parameters: { path: { - pid: string; + /** Workspace (company, customer) id */ + wid: components['parameters']['wid']; + /** Project id */ + pid: components['parameters']['pid']; }; }; responses: { /** OK */ 200: { content: { - 'application/json': { [key: string]: unknown }; - }; - }; - }; - requestBody: { - content: { - 'application/json': { - status: components['schemas']['PlanStatus']; + 'application/json': components['schemas']['Project']; }; }; + 400: components['responses']['Error']; + 403: components['responses']['Error']; + 404: components['responses']['Error']; + 500: components['responses']['Error']; }; }; - 'get-workspace-projects': { + 'get-workspace-project-campaigns': { parameters: { path: { /** Workspace (company, customer) id */ wid: components['parameters']['wid']; + /** Project id */ + pid: components['parameters']['pid']; }; query: { /** Limit pagination parameter */ @@ -3939,10 +4027,10 @@ export interface operations { 200: { content: { 'application/json': { - items?: components['schemas']['Project'][]; - start?: number; + items?: components['schemas']['CampaignWithOutput'][]; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -3999,13 +4087,13 @@ export interface operations { 200: { content: { 'application/json': { + config: string; + description?: string; id: number; name: string; - description?: string; - config: string; - workspace_id?: number; price?: string; strapi?: components['schemas']['StrapiTemplate']; + workspace_id?: number; }; }; }; @@ -4033,62 +4121,6 @@ export interface operations { 404: unknown; }; }; - 'get-workspace-project': { - parameters: { - path: { - /** Workspace (company, customer) id */ - wid: components['parameters']['wid']; - /** Project id */ - pid: components['parameters']['pid']; - }; - }; - responses: { - /** OK */ - 200: { - content: { - 'application/json': components['schemas']['Project']; - }; - }; - 400: components['responses']['Error']; - 403: components['responses']['Error']; - 404: components['responses']['Error']; - 500: components['responses']['Error']; - }; - }; - 'get-workspace-project-campaigns': { - parameters: { - path: { - /** Workspace (company, customer) id */ - wid: components['parameters']['wid']; - /** Project id */ - pid: components['parameters']['pid']; - }; - query: { - /** Limit pagination parameter */ - limit?: components['parameters']['limit']; - /** Start pagination parameter */ - start?: components['parameters']['start']; - }; - }; - responses: { - /** OK */ - 200: { - content: { - 'application/json': { - items?: components['schemas']['CampaignWithOutput'][]; - start?: number; - limit?: number; - size?: number; - total?: number; - }; - }; - }; - 400: components['responses']['Error']; - 403: components['responses']['Error']; - 404: components['responses']['Error']; - 500: components['responses']['Error']; - }; - }; /** Return a list of users from a specific workspace */ 'get-workspaces-users': { parameters: { @@ -4113,9 +4145,9 @@ export interface operations { content: { 'application/json': { items: components['schemas']['Tenant'][]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; }; @@ -4138,9 +4170,9 @@ export interface operations { 200: { content: { 'application/json': { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; }; }; @@ -4174,9 +4206,9 @@ export interface operations { requestBody: { content: { 'application/json': { + include_shared?: boolean; /** @description Tryber WP USER ID */ user_id: number; - include_shared?: boolean; }; }; }; diff --git a/src/features/api/api.ts b/src/features/api/api.ts index a8050af93..0f2071819 100644 --- a/src/features/api/api.ts +++ b/src/features/api/api.ts @@ -1,6 +1,5 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { stringify } from 'qs'; -import { Template } from '.'; export const apiSlice = createApi({ reducerPath: 'api', @@ -39,7 +38,3 @@ export const apiSlice = createApi({ ], endpoints: () => ({}), }); - -export interface UseCaseTemplate extends Template { - id?: number; -} diff --git a/src/features/api/apiTags.ts b/src/features/api/apiTags.ts index 578b553c5..fc7e2e19c 100644 --- a/src/features/api/apiTags.ts +++ b/src/features/api/apiTags.ts @@ -29,9 +29,6 @@ unguessApi.enhanceEndpoints({ patchProjectsByPid: { invalidatesTags: ['Projects'], }, - postCampaigns: { - invalidatesTags: ['Campaigns'], - }, patchCampaignsByCid: { invalidatesTags: ['Campaigns', 'Projects', 'Archive', 'Users'], }, @@ -53,9 +50,6 @@ unguessApi.enhanceEndpoints({ getWorkspacesByWidCoins: { providesTags: ['Workspaces'], }, - getTemplates: { - providesTags: ['Templates'], - }, getCampaignsByCidReports: { providesTags: ['Reports'], }, diff --git a/src/features/api/index.ts b/src/features/api/index.ts index a95c87b53..e38021afb 100644 --- a/src/features/api/index.ts +++ b/src/features/api/index.ts @@ -4,16 +4,6 @@ const injectedRtkApi = api.injectEndpoints({ $get: build.query<$getApiResponse, $getApiArg>({ query: () => ({ url: `/` }), }), - postAuthenticate: build.mutation< - PostAuthenticateApiResponse, - PostAuthenticateApiArg - >({ - query: (queryArg) => ({ - url: `/authenticate`, - method: 'POST', - body: queryArg.body, - }), - }), postAnalyticsViewsCampaignsByCid: build.mutation< PostAnalyticsViewsCampaignsByCidApiResponse, PostAnalyticsViewsCampaignsByCidApiArg @@ -23,16 +13,22 @@ const injectedRtkApi = api.injectEndpoints({ method: 'POST', }), }), - postCampaigns: build.mutation< - PostCampaignsApiResponse, - PostCampaignsApiArg + postAuthenticate: build.mutation< + PostAuthenticateApiResponse, + PostAuthenticateApiArg >({ query: (queryArg) => ({ - url: `/campaigns`, + url: `/authenticate`, method: 'POST', body: queryArg.body, }), }), + getCampaignsByCid: build.query< + GetCampaignsByCidApiResponse, + GetCampaignsByCidApiArg + >({ + query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}` }), + }), patchCampaignsByCid: build.mutation< PatchCampaignsByCidApiResponse, PatchCampaignsByCidApiArg @@ -43,12 +39,6 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - getCampaignsByCid: build.query< - GetCampaignsByCidApiResponse, - GetCampaignsByCidApiArg - >({ - query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}` }), - }), getCampaignsByCidBugTypes: build.query< GetCampaignsByCidBugTypesApiResponse, GetCampaignsByCidBugTypesApiArg @@ -107,13 +97,13 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - postCampaignsByCidBugsAndBidMedia: build.mutation< - PostCampaignsByCidBugsAndBidMediaApiResponse, - PostCampaignsByCidBugsAndBidMediaApiArg + deleteCampaignsByCidBugsAndBidCommentsCmid: build.mutation< + DeleteCampaignsByCidBugsAndBidCommentsCmidApiResponse, + DeleteCampaignsByCidBugsAndBidCommentsCmidApiArg >({ query: (queryArg) => ({ - url: `/campaigns/${queryArg.cid}/bugs/${queryArg.bid}/media`, - method: 'POST', + url: `/campaigns/${queryArg.cid}/bugs/${queryArg.bid}/comments/${queryArg.cmid}`, + method: 'DELETE', body: queryArg.body, }), }), @@ -127,13 +117,13 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteCampaignsByCidBugsAndBidCommentsCmid: build.mutation< - DeleteCampaignsByCidBugsAndBidCommentsCmidApiResponse, - DeleteCampaignsByCidBugsAndBidCommentsCmidApiArg + postCampaignsByCidBugsAndBidMedia: build.mutation< + PostCampaignsByCidBugsAndBidMediaApiResponse, + PostCampaignsByCidBugsAndBidMediaApiArg >({ query: (queryArg) => ({ - url: `/campaigns/${queryArg.cid}/bugs/${queryArg.bid}/comments/${queryArg.cmid}`, - method: 'DELETE', + url: `/campaigns/${queryArg.cid}/bugs/${queryArg.bid}/media`, + method: 'POST', body: queryArg.body, }), }), @@ -151,6 +141,16 @@ const injectedRtkApi = api.injectEndpoints({ >({ query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}/clusters` }), }), + deleteCampaignsByCidCustomStatuses: build.mutation< + DeleteCampaignsByCidCustomStatusesApiResponse, + DeleteCampaignsByCidCustomStatusesApiArg + >({ + query: (queryArg) => ({ + url: `/campaigns/${queryArg.cid}/custom_statuses`, + method: 'DELETE', + body: queryArg.body, + }), + }), getCampaignsByCidCustomStatuses: build.query< GetCampaignsByCidCustomStatusesApiResponse, GetCampaignsByCidCustomStatusesApiArg @@ -169,16 +169,6 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteCampaignsByCidCustomStatuses: build.mutation< - DeleteCampaignsByCidCustomStatusesApiResponse, - DeleteCampaignsByCidCustomStatusesApiArg - >({ - query: (queryArg) => ({ - url: `/campaigns/${queryArg.cid}/custom_statuses`, - method: 'DELETE', - body: queryArg.body, - }), - }), getCampaignsByCidDevices: build.query< GetCampaignsByCidDevicesApiResponse, GetCampaignsByCidDevicesApiArg @@ -195,6 +185,12 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), + getCampaignsByCidInsights: build.query< + GetCampaignsByCidInsightsApiResponse, + GetCampaignsByCidInsightsApiArg + >({ + query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}/insights` }), + }), postCampaignsByCidInsights: build.mutation< PostCampaignsByCidInsightsApiResponse, PostCampaignsByCidInsightsApiArg @@ -205,12 +201,6 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - getCampaignsByCidInsights: build.query< - GetCampaignsByCidInsightsApiResponse, - GetCampaignsByCidInsightsApiArg - >({ - query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}/insights` }), - }), getCampaignsByCidMeta: build.query< GetCampaignsByCidMetaApiResponse, GetCampaignsByCidMetaApiArg @@ -289,6 +279,16 @@ const injectedRtkApi = api.injectEndpoints({ params: { filterBy: queryArg.filterBy }, }), }), + deleteCampaignsByCidUsers: build.mutation< + DeleteCampaignsByCidUsersApiResponse, + DeleteCampaignsByCidUsersApiArg + >({ + query: (queryArg) => ({ + url: `/campaigns/${queryArg.cid}/users`, + method: 'DELETE', + body: queryArg.body, + }), + }), getCampaignsByCidUsers: build.query< GetCampaignsByCidUsersApiResponse, GetCampaignsByCidUsersApiArg @@ -313,16 +313,6 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteCampaignsByCidUsers: build.mutation< - DeleteCampaignsByCidUsersApiResponse, - DeleteCampaignsByCidUsersApiArg - >({ - query: (queryArg) => ({ - url: `/campaigns/${queryArg.cid}/users`, - method: 'DELETE', - body: queryArg.body, - }), - }), getCampaignsByCidUx: build.query< GetCampaignsByCidUxApiResponse, GetCampaignsByCidUxApiArg @@ -375,12 +365,6 @@ const injectedRtkApi = api.injectEndpoints({ params: { s: queryArg.s, updateTrend: queryArg.updateTrend }, }), }), - getInsightsByIid: build.query< - GetInsightsByIidApiResponse, - GetInsightsByIidApiArg - >({ - query: (queryArg) => ({ url: `/insights/${queryArg.iid}` }), - }), deleteInsightsByIid: build.mutation< DeleteInsightsByIidApiResponse, DeleteInsightsByIidApiArg @@ -390,6 +374,12 @@ const injectedRtkApi = api.injectEndpoints({ method: 'DELETE', }), }), + getInsightsByIid: build.query< + GetInsightsByIidApiResponse, + GetInsightsByIidApiArg + >({ + query: (queryArg) => ({ url: `/insights/${queryArg.iid}` }), + }), patchInsightsByIid: build.mutation< PatchInsightsByIidApiResponse, PatchInsightsByIidApiArg @@ -400,8 +390,13 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - getMediaById: build.query({ - query: (queryArg) => ({ url: `/media/${queryArg.id}` }), + getInvitesByProfileAndToken: build.query< + GetInvitesByProfileAndTokenApiResponse, + GetInvitesByProfileAndTokenApiArg + >({ + query: (queryArg) => ({ + url: `/invites/${queryArg.profile}/${queryArg.token}`, + }), }), deleteMediaCommentByMcid: build.mutation< DeleteMediaCommentByMcidApiResponse, @@ -412,6 +407,41 @@ const injectedRtkApi = api.injectEndpoints({ method: 'DELETE', }), }), + getMediaById: build.query({ + query: (queryArg) => ({ url: `/media/${queryArg.id}` }), + }), + deletePlansByPid: build.mutation< + DeletePlansByPidApiResponse, + DeletePlansByPidApiArg + >({ + query: (queryArg) => ({ + url: `/plans/${queryArg.pid}`, + method: 'DELETE', + }), + }), + getPlansByPid: build.query({ + query: (queryArg) => ({ url: `/plans/${queryArg.pid}` }), + }), + patchPlansByPid: build.mutation< + PatchPlansByPidApiResponse, + PatchPlansByPidApiArg + >({ + query: (queryArg) => ({ + url: `/plans/${queryArg.pid}`, + method: 'PATCH', + body: queryArg.body, + }), + }), + patchPlansByPidStatus: build.mutation< + PatchPlansByPidStatusApiResponse, + PatchPlansByPidStatusApiArg + >({ + query: (queryArg) => ({ + url: `/plans/${queryArg.pid}/status`, + method: 'PATCH', + body: queryArg.body, + }), + }), postProjects: build.mutation({ query: (queryArg) => ({ url: `/projects`, @@ -419,6 +449,15 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), + deleteProjectsByPid: build.mutation< + DeleteProjectsByPidApiResponse, + DeleteProjectsByPidApiArg + >({ + query: (queryArg) => ({ + url: `/projects/${queryArg.pid}`, + method: 'DELETE', + }), + }), getProjectsByPid: build.query< GetProjectsByPidApiResponse, GetProjectsByPidApiArg @@ -435,15 +474,6 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteProjectsByPid: build.mutation< - DeleteProjectsByPidApiResponse, - DeleteProjectsByPidApiArg - >({ - query: (queryArg) => ({ - url: `/projects/${queryArg.pid}`, - method: 'DELETE', - }), - }), getProjectsByPidCampaigns: build.query< GetProjectsByPidCampaignsApiResponse, GetProjectsByPidCampaignsApiArg @@ -458,6 +488,16 @@ const injectedRtkApi = api.injectEndpoints({ }, }), }), + deleteProjectsByPidUsers: build.mutation< + DeleteProjectsByPidUsersApiResponse, + DeleteProjectsByPidUsersApiArg + >({ + query: (queryArg) => ({ + url: `/projects/${queryArg.pid}/users`, + method: 'DELETE', + body: queryArg.body, + }), + }), getProjectsByPidUsers: build.query< GetProjectsByPidUsersApiResponse, GetProjectsByPidUsersApiArg @@ -482,24 +522,20 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteProjectsByPidUsers: build.mutation< - DeleteProjectsByPidUsersApiResponse, - DeleteProjectsByPidUsersApiArg - >({ + postUsers: build.mutation({ query: (queryArg) => ({ - url: `/projects/${queryArg.pid}/users`, - method: 'DELETE', + url: `/users`, + method: 'POST', body: queryArg.body, }), }), - getTemplates: build.query({ + headUsersByEmailByEmail: build.mutation< + HeadUsersByEmailByEmailApiResponse, + HeadUsersByEmailByEmailApiArg + >({ query: (queryArg) => ({ - url: `/templates`, - params: { - filterBy: queryArg.filterBy, - order: queryArg.order, - orderBy: queryArg.orderBy, - }, + url: `/users/by-email/${queryArg.email}`, + method: 'HEAD', }), }), getUsersMe: build.query({ @@ -521,6 +557,9 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), + getUsersRoles: build.query({ + query: () => ({ url: `/users/roles` }), + }), getVideosByVid: build.query< GetVideosByVidApiResponse, GetVideosByVidApiArg @@ -543,23 +582,23 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - patchVideosByVidObservationsAndOid: build.mutation< - PatchVideosByVidObservationsAndOidApiResponse, - PatchVideosByVidObservationsAndOidApiArg + deleteVideosByVidObservationsAndOid: build.mutation< + DeleteVideosByVidObservationsAndOidApiResponse, + DeleteVideosByVidObservationsAndOidApiArg >({ query: (queryArg) => ({ url: `/videos/${queryArg.vid}/observations/${queryArg.oid}`, - method: 'PATCH', - body: queryArg.body, + method: 'DELETE', }), }), - deleteVideosByVidObservationsAndOid: build.mutation< - DeleteVideosByVidObservationsAndOidApiResponse, - DeleteVideosByVidObservationsAndOidApiArg + patchVideosByVidObservationsAndOid: build.mutation< + PatchVideosByVidObservationsAndOidApiResponse, + PatchVideosByVidObservationsAndOidApiArg >({ query: (queryArg) => ({ url: `/videos/${queryArg.vid}/observations/${queryArg.oid}`, - method: 'DELETE', + method: 'PATCH', + body: queryArg.body, }), }), getVideosByVidTranslation: build.query< @@ -643,16 +682,6 @@ const injectedRtkApi = api.injectEndpoints({ }, }), }), - postWorkspacesByWidPlans: build.mutation< - PostWorkspacesByWidPlansApiResponse, - PostWorkspacesByWidPlansApiArg - >({ - query: (queryArg) => ({ - url: `/workspaces/${queryArg.wid}/plans`, - method: 'POST', - body: queryArg.body, - }), - }), getWorkspacesByWidPlans: build.query< GetWorkspacesByWidPlansApiResponse, GetWorkspacesByWidPlansApiArg @@ -667,35 +696,13 @@ const injectedRtkApi = api.injectEndpoints({ }, }), }), - deletePlansByPid: build.mutation< - DeletePlansByPidApiResponse, - DeletePlansByPidApiArg - >({ - query: (queryArg) => ({ - url: `/plans/${queryArg.pid}`, - method: 'DELETE', - }), - }), - getPlansByPid: build.query({ - query: (queryArg) => ({ url: `/plans/${queryArg.pid}` }), - }), - patchPlansByPid: build.mutation< - PatchPlansByPidApiResponse, - PatchPlansByPidApiArg - >({ - query: (queryArg) => ({ - url: `/plans/${queryArg.pid}`, - method: 'PATCH', - body: queryArg.body, - }), - }), - patchPlansByPidStatus: build.mutation< - PatchPlansByPidStatusApiResponse, - PatchPlansByPidStatusApiArg + postWorkspacesByWidPlans: build.mutation< + PostWorkspacesByWidPlansApiResponse, + PostWorkspacesByWidPlansApiArg >({ query: (queryArg) => ({ - url: `/plans/${queryArg.pid}/status`, - method: 'PATCH', + url: `/workspaces/${queryArg.wid}/plans`, + method: 'POST', body: queryArg.body, }), }), @@ -708,10 +715,27 @@ const injectedRtkApi = api.injectEndpoints({ params: { limit: queryArg.limit, start: queryArg.start }, }), }), - getWorkspacesByWidTemplates: build.query< - GetWorkspacesByWidTemplatesApiResponse, - GetWorkspacesByWidTemplatesApiArg - >({ + getWorkspacesByWidProjectsAndPid: build.query< + GetWorkspacesByWidProjectsAndPidApiResponse, + GetWorkspacesByWidProjectsAndPidApiArg + >({ + query: (queryArg) => ({ + url: `/workspaces/${queryArg.wid}/projects/${queryArg.pid}`, + }), + }), + getWorkspacesByWidProjectsAndPidCampaigns: build.query< + GetWorkspacesByWidProjectsAndPidCampaignsApiResponse, + GetWorkspacesByWidProjectsAndPidCampaignsApiArg + >({ + query: (queryArg) => ({ + url: `/workspaces/${queryArg.wid}/projects/${queryArg.pid}/campaigns`, + params: { limit: queryArg.limit, start: queryArg.start }, + }), + }), + getWorkspacesByWidTemplates: build.query< + GetWorkspacesByWidTemplatesApiResponse, + GetWorkspacesByWidTemplatesApiArg + >({ query: (queryArg) => ({ url: `/workspaces/${queryArg.wid}/templates`, params: { @@ -740,21 +764,14 @@ const injectedRtkApi = api.injectEndpoints({ url: `/workspaces/${queryArg.wid}/templates/${queryArg.tid}`, }), }), - getWorkspacesByWidProjectsAndPid: build.query< - GetWorkspacesByWidProjectsAndPidApiResponse, - GetWorkspacesByWidProjectsAndPidApiArg - >({ - query: (queryArg) => ({ - url: `/workspaces/${queryArg.wid}/projects/${queryArg.pid}`, - }), - }), - getWorkspacesByWidProjectsAndPidCampaigns: build.query< - GetWorkspacesByWidProjectsAndPidCampaignsApiResponse, - GetWorkspacesByWidProjectsAndPidCampaignsApiArg + deleteWorkspacesByWidUsers: build.mutation< + DeleteWorkspacesByWidUsersApiResponse, + DeleteWorkspacesByWidUsersApiArg >({ query: (queryArg) => ({ - url: `/workspaces/${queryArg.wid}/projects/${queryArg.pid}/campaigns`, - params: { limit: queryArg.limit, start: queryArg.start }, + url: `/workspaces/${queryArg.wid}/users`, + method: 'DELETE', + body: queryArg.body, }), }), getWorkspacesByWidUsers: build.query< @@ -781,29 +798,12 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), - deleteWorkspacesByWidUsers: build.mutation< - DeleteWorkspacesByWidUsersApiResponse, - DeleteWorkspacesByWidUsersApiArg - >({ - query: (queryArg) => ({ - url: `/workspaces/${queryArg.wid}/users`, - method: 'DELETE', - body: queryArg.body, - }), - }), }), overrideExisting: false, }); export { injectedRtkApi as unguessApi }; export type $getApiResponse = /** status 200 OK */ {}; export type $getApiArg = void; -export type PostAuthenticateApiResponse = /** status 200 OK */ Authentication; -export type PostAuthenticateApiArg = { - body: { - username: string; - password: string; - }; -}; export type PostAnalyticsViewsCampaignsByCidApiResponse = /** status 200 OK */ { success?: boolean; }; @@ -811,51 +811,11 @@ export type PostAnalyticsViewsCampaignsByCidApiArg = { /** Campaign id */ cid: string; }; -export type PostCampaignsApiResponse = /** status 200 OK */ Campaign; -export type PostCampaignsApiArg = { - body: { - title: string; - start_date: string; - end_date: string; - close_date: string; - customer_title?: string; - status_id?: number; - is_public?: number; - campaign_type_id: number; - project_id: number; - pm_id: number; - platforms: PlatformObject[]; - /** Da togliere */ - page_preview_id?: number; - /** Da togliere */ - page_manual_id?: number; - /** Used to check available coins */ - customer_id: number; - has_bug_form?: number; - /** if has_bug_form is 0 this has to be 0 */ - has_bug_parade?: number; - description?: string; - base_bug_internal_id?: string; - express_slug: string; - use_cases?: UseCase[]; - productType?: number; - productLink?: string; - browsers?: number[]; - languages?: string[]; - outOfScope?: string; - testerRequirements?: string; - targetSize?: number; - goal?: string; - testDescription?: string; - }; -}; -export type PatchCampaignsByCidApiResponse = /** status 200 OK */ Campaign; -export type PatchCampaignsByCidApiArg = { - /** Campaign id */ - cid: string; +export type PostAuthenticateApiResponse = /** status 200 OK */ Authentication; +export type PostAuthenticateApiArg = { body: { - customer_title?: string; - project_id?: number; + password: string; + username: string; }; }; export type GetCampaignsByCidApiResponse = @@ -867,6 +827,15 @@ export type GetCampaignsByCidApiArg = { /** Campaign id */ cid: string; }; +export type PatchCampaignsByCidApiResponse = /** status 200 OK */ Campaign; +export type PatchCampaignsByCidApiArg = { + /** Campaign id */ + cid: string; + body: { + customer_title?: string; + project_id?: number; + }; +}; export type GetCampaignsByCidBugTypesApiResponse = /** status 200 OK */ BugType[]; export type GetCampaignsByCidBugTypesApiArg = { @@ -875,21 +844,21 @@ export type GetCampaignsByCidBugTypesApiArg = { }; export type GetCampaignsByCidBugsApiResponse = /** status 200 OK */ { items?: (Bug & { - tags?: { - tag_id: number; - tag_name: string; - }[]; - siblings: number; - comments: number; additional_fields?: { + name: string; slug: string; value: string; - name: string; + }[]; + comments: number; + siblings: number; + tags?: { + tag_id: number; + tag_name: string; }[]; })[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetCampaignsByCidBugsApiArg = { @@ -910,13 +879,13 @@ export type GetCampaignsByCidBugsApiArg = { }; export type GetCampaignsByCidBugsAndBidApiResponse = /** status 200 OK */ Bug & { - media: BugMedia[]; - tags: BugTag[]; additional_fields: BugAdditionalField[]; + media: BugMedia[]; reporter: { - tester_id: number; name: string; + tester_id: number; }; + tags: BugTag[]; }; export type GetCampaignsByCidBugsAndBidApiArg = { /** Campaign id */ @@ -925,12 +894,12 @@ export type GetCampaignsByCidBugsAndBidApiArg = { bid: string; }; export type PatchCampaignsByCidBugsAndBidApiResponse = /** status 200 OK */ { + custom_status?: BugCustomStatus; + priority?: BugPriority; tags?: { tag_id: number; tag_name: string; }[]; - priority?: BugPriority; - custom_status?: BugCustomStatus; }; export type PatchCampaignsByCidBugsAndBidApiArg = { /** Campaign id */ @@ -938,6 +907,8 @@ export type PatchCampaignsByCidBugsAndBidApiArg = { /** Defines an identifier for the bug object (BUG ID) */ bid: string; body: { + custom_status_id?: number; + priority_id?: number; tags?: ( | { tag_id: number; @@ -946,8 +917,6 @@ export type PatchCampaignsByCidBugsAndBidApiArg = { tag_name: string; } )[]; - priority_id?: number; - custom_status_id?: number; }; }; export type GetCampaignsByCidBugsAndBidCommentsApiResponse = @@ -968,93 +937,93 @@ export type PostCampaignsByCidBugsAndBidCommentsApiArg = { /** Defines an identifier for the bug object (BUG ID) */ bid: string; body: { - text: string; - mentioned?: { + media_id?: { id: number; }[]; - media_id?: { + mentioned?: { id: number; }[]; + text: string; }; }; -export type PostCampaignsByCidBugsAndBidMediaApiResponse = +export type DeleteCampaignsByCidBugsAndBidCommentsCmidApiResponse = + /** status 200 OK */ string; +export type DeleteCampaignsByCidBugsAndBidCommentsCmidApiArg = { + cid: string; + bid: string; + cmid: string; + body: {}; +}; +export type PostCampaignsByCidBugsAndBidCommentsCmidApiResponse = /** status 200 OK */ { failed?: { - name: string; errorCode: 'FILE_TOO_BIG' | 'INVALID_FILE_EXTENSION' | 'GENERIC_ERROR'; + name: string; + }[]; + files?: { + name: string; + path: string; }[]; uploaded_ids?: { id: number; }[]; }; -export type PostCampaignsByCidBugsAndBidMediaApiArg = { - /** Campaign id */ +export type PostCampaignsByCidBugsAndBidCommentsCmidApiArg = { cid: string; - /** Defines an identifier for the bug object (BUG ID) */ bid: string; + cmid: string; body: { media: string | string[]; }; }; -export type PostCampaignsByCidBugsAndBidCommentsCmidApiResponse = +export type PostCampaignsByCidBugsAndBidMediaApiResponse = /** status 200 OK */ { - files?: { - name: string; - path: string; - }[]; failed?: { - name: string; errorCode: 'FILE_TOO_BIG' | 'INVALID_FILE_EXTENSION' | 'GENERIC_ERROR'; + name: string; }[]; uploaded_ids?: { id: number; }[]; }; -export type PostCampaignsByCidBugsAndBidCommentsCmidApiArg = { +export type PostCampaignsByCidBugsAndBidMediaApiArg = { + /** Campaign id */ cid: string; + /** Defines an identifier for the bug object (BUG ID) */ bid: string; - cmid: string; body: { media: string | string[]; }; }; -export type DeleteCampaignsByCidBugsAndBidCommentsCmidApiResponse = - /** status 200 OK */ string; -export type DeleteCampaignsByCidBugsAndBidCommentsCmidApiArg = { - cid: string; - bid: string; - cmid: string; - body: {}; -}; export type GetCampaignsByCidBugsAndBidSiblingsApiResponse = /** status 200 OK */ { father?: { - id: number; - title: { - full: string; - compact: string; - context?: string[]; - }; context?: string; device: string; + id: number; os: { name: string; version: string; }; - }; - siblings: { - id: number; title: { - full: string; compact: string; context?: string[]; + full: string; }; + }; + siblings: { context?: string; device: string; + id: number; os: { name: string; version: string; }; + title: { + compact: string; + context?: string[]; + full: string; + }; }[]; }; export type GetCampaignsByCidBugsAndBidSiblingsApiArg = { @@ -1069,6 +1038,18 @@ export type GetCampaignsByCidClustersApiResponse = /** status 200 OK */ { export type GetCampaignsByCidClustersApiArg = { cid: string; }; +export type DeleteCampaignsByCidCustomStatusesApiResponse = + /** status 200 OK */ { + status?: boolean; + }; +export type DeleteCampaignsByCidCustomStatusesApiArg = { + /** Campaign id */ + cid: string; + body: { + custom_status_id: number; + to_custom_status_id?: number; + }[]; +}; export type GetCampaignsByCidCustomStatusesApiResponse = /** status 200 OK */ BugCustomStatus[]; export type GetCampaignsByCidCustomStatusesApiArg = { @@ -1081,22 +1062,10 @@ export type PatchCampaignsByCidCustomStatusesApiArg = { /** Campaign id */ cid: string; body: { + color: string; /** se esiste già questo parametro viene passato nel request body\r\nse invece non esiste ed il custom status deve essere creato, non viene passato */ custom_status_id?: number; name: string; - color: string; - }[]; -}; -export type DeleteCampaignsByCidCustomStatusesApiResponse = - /** status 200 OK */ { - status?: boolean; - }; -export type DeleteCampaignsByCidCustomStatusesApiArg = { - /** Campaign id */ - cid: string; - body: { - custom_status_id: number; - to_custom_status_id?: number; }[]; }; export type GetCampaignsByCidDevicesApiResponse = /** status 200 OK */ { @@ -1116,20 +1085,6 @@ export type PutCampaignsByCidFindingsAndFidApiArg = { comment: string; }; }; -export type PostCampaignsByCidInsightsApiResponse = - /** status 200 OK */ Insight; -export type PostCampaignsByCidInsightsApiArg = { - /** Campaign id */ - cid: string; - body: { - title: string; - description?: string; - severity_id: number; - observations_ids: number[]; - comment?: string; - visible?: number; - }; -}; export type GetCampaignsByCidInsightsApiResponse = /** status 200 OK */ (Insight & { usecases: { @@ -1141,10 +1096,24 @@ export type GetCampaignsByCidInsightsApiArg = { /** Campaign id */ cid: string; }; +export type PostCampaignsByCidInsightsApiResponse = + /** status 200 OK */ Insight; +export type PostCampaignsByCidInsightsApiArg = { + /** Campaign id */ + cid: string; + body: { + comment?: string; + description?: string; + observations_ids: number[]; + severity_id: number; + title: string; + visible?: number; + }; +}; export type GetCampaignsByCidMetaApiResponse = /** status 200 OK */ Campaign & { - selected_testers: number; /** Array of form factors */ allowed_devices: string[]; + selected_testers: number; }; export type GetCampaignsByCidMetaApiArg = { /** Campaign id */ @@ -1153,27 +1122,27 @@ export type GetCampaignsByCidMetaApiArg = { export type GetCampaignsByCidObservationsApiResponse = /** status 200 OK */ | { + kind: 'usecase-grapes'; results: { - usecaseId: number; - usecaseTitle: string; grapes: Grape[]; ungrouped: (Observation & { - uploaderId: number; - mediaId: number; deviceType: string; + mediaId: number; + uploaderId: number; usecaseTitle: string; })[]; + usecaseId: number; + usecaseTitle: string; }[]; - kind: 'usecase-grapes'; } | { + kind: 'ungrouped'; results: (Observation & { - uploaderId: number; - mediaId: number; deviceType: string; + mediaId: number; + uploaderId: number; usecaseTitle: string; })[]; - kind: 'ungrouped'; }; export type GetCampaignsByCidObservationsApiArg = { cid: string; @@ -1211,9 +1180,9 @@ export type GetCampaignsByCidSeveritiesApiArg = { }; export type GetCampaignsByCidSuggestionsApiResponse = /** status 200 OK */ { suggestion?: { - slug: BannerType; /** ServiceId from strapi */ serviceId?: number; + slug: BannerType; }; }; export type GetCampaignsByCidSuggestionsApiArg = { @@ -1229,24 +1198,25 @@ export type PostCampaignsByCidSuggestionsApiArg = { }; }; export type GetCampaignsByCidTagsApiResponse = /** status 200 OK */ { - tag_id: number; display_name: string; - slug: string; is_public?: number; + slug: string; + tag_id: number; }[]; export type GetCampaignsByCidTagsApiArg = { /** Campaign id */ cid: string; }; export type GetCampaignsByCidUsecasesApiResponse = /** status 200 OK */ { + completion: number; + content?: string; id: number; title: { full: string; - simple?: string; - prefix?: string; info?: string; + prefix?: string; + simple?: string; }; - completion: number; }[]; export type GetCampaignsByCidUsecasesApiArg = { /** Campaign id */ @@ -1254,11 +1224,22 @@ export type GetCampaignsByCidUsecasesApiArg = { /** bugs, videos */ filterBy?: string; }; +export type DeleteCampaignsByCidUsersApiResponse = /** status 200 OK */ { + items: Tenant[]; +}; +export type DeleteCampaignsByCidUsersApiArg = { + /** Campaign id */ + cid: string; + body: { + /** Tryber WP USER ID */ + user_id: number; + }; +}; export type GetCampaignsByCidUsersApiResponse = /** status 200 OK */ { items: Tenant[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetCampaignsByCidUsersApiArg = { @@ -1274,78 +1255,67 @@ export type GetCampaignsByCidUsersApiArg = { orderBy?: string; }; export type PostCampaignsByCidUsersApiResponse = /** status 200 OK */ { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; export type PostCampaignsByCidUsersApiArg = { /** Campaign id */ cid: string; body: { email: string; - name?: string; - surname?: string; - locale?: string; event_name?: string; - redirect_url?: string; + locale?: string; message?: string; - }; -}; -export type DeleteCampaignsByCidUsersApiResponse = /** status 200 OK */ { - items: Tenant[]; -}; -export type DeleteCampaignsByCidUsersApiArg = { - /** Campaign id */ - cid: string; - body: { - /** Tryber WP USER ID */ - user_id: number; + name?: string; + redirect_url?: string; + surname?: string; }; }; export type GetCampaignsByCidUxApiResponse = /** status 200 OK */ { - goal?: string; - users?: number; findings?: { + cluster: + | { + id: number; + name: string; + }[] + | 'all'; + comment?: string; + description: string; /** this field is the Finding ID */ id: number; - title: string; - description: string; - comment?: string; severity: { id: number; name: string; style: string; }; - cluster: - | { - id: number; - name: string; - }[] - | 'all'; + title: string; video?: { - url: string; - streamUrl: string; + description?: string; + end: number; poster?: string; start: number; - end: number; - description?: string; + streamUrl: string; + url: string; }[]; }[]; + goal?: string; + methodology?: { + description: string; + type: string; + }; + questions?: { + text: string; + }[]; sentiment?: { cluster: { id: number; name: string; }; - value: number; comment: string; + value: number; }[]; - methodology?: { - type: string; - description: string; - }; - questions?: { - text: string; - }[]; + users?: number; }; export type GetCampaignsByCidUxApiArg = { /** Campaign id */ @@ -1430,13 +1400,13 @@ export type GetCampaignsByCidWidgetsApiArg = { /** should update bug trend after request resolves? */ updateTrend?: boolean; }; -export type GetInsightsByIidApiResponse = /** status 200 OK */ Insight; -export type GetInsightsByIidApiArg = { +export type DeleteInsightsByIidApiResponse = /** status 200 OK */ void; +export type DeleteInsightsByIidApiArg = { /** Insight id */ iid: string; }; -export type DeleteInsightsByIidApiResponse = /** status 200 OK */ void; -export type DeleteInsightsByIidApiArg = { +export type GetInsightsByIidApiResponse = /** status 200 OK */ Insight; +export type GetInsightsByIidApiArg = { /** Insight id */ iid: string; }; @@ -1445,30 +1415,91 @@ export type PatchInsightsByIidApiArg = { /** Insight id */ iid: string; body: { - title?: string; + comment?: string; description?: string; - severity_id?: number; observations_ids?: number[]; - comment?: string; + severity_id?: number; + title?: string; visible?: number; }; }; -export type GetMediaByIdApiResponse = unknown; -export type GetMediaByIdApiArg = { - id: string; +export type GetInvitesByProfileAndTokenApiResponse = /** status 200 OK */ { + email: string; + name: string; + surname: string; + workspace: string; +}; +export type GetInvitesByProfileAndTokenApiArg = { + profile: string; + token: string; }; export type DeleteMediaCommentByMcidApiResponse = /** status 200 OK */ object; export type DeleteMediaCommentByMcidApiArg = { mcid: string; }; +export type GetMediaByIdApiResponse = unknown; +export type GetMediaByIdApiArg = { + id: string; +}; +export type DeletePlansByPidApiResponse = unknown; +export type DeletePlansByPidApiArg = { + pid: string; +}; +export type GetPlansByPidApiResponse = /** status 200 OK */ { + campaign?: { + id: number; + startDate: string; + /** CustomerTitle ?? Title */ + title: string; + }; + config: { + modules: Module[]; + }; + id: number; + project: { + id: number; + name: string; + }; + quote?: { + id: number; + status: 'pending' | 'proposed' | 'approved' | 'rejected'; + value: string; + }; + status: PlanStatus; + workspace_id: number; +}; +export type GetPlansByPidApiArg = { + pid: string; +}; +export type PatchPlansByPidApiResponse = unknown; +export type PatchPlansByPidApiArg = { + pid: string; + body: { + config: { + modules: Module[]; + }; + }; +}; +export type PatchPlansByPidStatusApiResponse = /** status 200 OK */ {}; +export type PatchPlansByPidStatusApiArg = { + pid: string; + body: { + status: PlanStatus; + }; +}; export type PostProjectsApiResponse = /** status 200 OK */ Project; export type PostProjectsApiArg = { body: { - name: string; customer_id: number; description?: string; + name: string; }; }; +export type DeleteProjectsByPidApiResponse = /** status 200 OK */ void; +export type DeleteProjectsByPidApiArg = { + /** Project id */ + pid: string; +}; export type GetProjectsByPidApiResponse = /** status 200 OK */ Project; export type GetProjectsByPidApiArg = { /** Project id */ @@ -1486,16 +1517,11 @@ export type PatchProjectsByPidApiArg = { description: string; }; }; -export type DeleteProjectsByPidApiResponse = /** status 200 OK */ void; -export type DeleteProjectsByPidApiArg = { - /** Project id */ - pid: string; -}; export type GetProjectsByPidCampaignsApiResponse = /** status 200 OK */ { items?: CampaignWithOutput[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetProjectsByPidCampaignsApiArg = { @@ -1510,11 +1536,23 @@ export type GetProjectsByPidCampaignsApiArg = { /** Order by accepted field */ orderBy?: string; }; +export type DeleteProjectsByPidUsersApiResponse = /** status 200 OK */ { + items: Tenant[]; +}; +export type DeleteProjectsByPidUsersApiArg = { + /** Project id */ + pid: string; + body: { + include_shared?: boolean; + /** Tryber WP USER ID */ + user_id: number; + }; +}; export type GetProjectsByPidUsersApiResponse = /** status 200 OK */ { items: Tenant[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetProjectsByPidUsersApiArg = { @@ -1530,45 +1568,41 @@ export type GetProjectsByPidUsersApiArg = { orderBy?: string; }; export type PostProjectsByPidUsersApiResponse = /** status 200 OK */ { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; export type PostProjectsByPidUsersApiArg = { /** Project id */ pid: string; body: { email: string; - name?: string; - surname?: string; - locale?: string; event_name?: string; - redirect_url?: string; + locale?: string; message?: string; + name?: string; + redirect_url?: string; + surname?: string; }; }; -export type DeleteProjectsByPidUsersApiResponse = /** status 200 OK */ { - items: Tenant[]; +export type PostUsersApiResponse = /** status 201 Created */ { + projectId?: number; + workspaceId: number; }; -export type DeleteProjectsByPidUsersApiArg = { - /** Project id */ - pid: string; +export type PostUsersApiArg = { body: { - /** Tryber WP USER ID */ - user_id: number; - include_shared?: boolean; - }; + name: string; + password: string; + roleId: number; + surname: string; + } & ( + | DataForPostUsersRequestForInvitedUser + | DataForPostUsersRequestForNewUser + ); }; -export type GetTemplatesApiResponse = /** status 200 OK */ ({ - id?: number; -} & Template)[]; -export type GetTemplatesApiArg = { - /** filterBy[]= */ - filterBy?: any; - /** Order value (ASC, DESC) */ - order?: string; - /** Order by accepted field */ - orderBy?: string; +export type HeadUsersByEmailByEmailApiResponse = unknown; +export type HeadUsersByEmailByEmailApiArg = { + email: string; }; export type GetUsersMeApiResponse = /** status 200 */ User; export type GetUsersMeApiArg = void; @@ -1584,6 +1618,11 @@ export type PutUsersMePreferencesBySlugApiArg = { value: string; }; }; +export type GetUsersRolesApiResponse = /** status 200 OK */ { + id: number; + name: string; +}[]; +export type GetUsersRolesApiArg = void; export type GetVideosByVidApiResponse = /** status 200 OK */ Video & { usecase: { id: number; @@ -1605,36 +1644,36 @@ export type PostVideosByVidObservationsApiResponse = export type PostVideosByVidObservationsApiArg = { vid: string; body: { - start: number; end: number; + start: number; }; }; +export type DeleteVideosByVidObservationsAndOidApiResponse = unknown; +export type DeleteVideosByVidObservationsAndOidApiArg = { + vid: string; + oid: string; +}; export type PatchVideosByVidObservationsAndOidApiResponse = /** status 200 OK */ Observation; export type PatchVideosByVidObservationsAndOidApiArg = { vid: string; oid: string; body: { - title?: string; description?: string; - start?: number; end?: number; quotes?: string; + start?: number; tags?: number[]; + title?: string; }; }; -export type DeleteVideosByVidObservationsAndOidApiResponse = unknown; -export type DeleteVideosByVidObservationsAndOidApiArg = { - vid: string; - oid: string; -}; export type GetVideosByVidTranslationApiResponse = /** status 200 OK */ { language: string; processing: number; sentences: { - text: string; - start: number; end: number; + start: number; + text: string; }[]; }; export type GetVideosByVidTranslationApiArg = { @@ -1651,9 +1690,9 @@ export type PostVideosByVidTranslationApiArg = { }; export type GetWorkspacesApiResponse = /** status 200 OK */ { items?: Workspace[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetWorkspacesApiArg = { @@ -1667,8 +1706,8 @@ export type GetWorkspacesApiArg = { orderBy?: string; }; export type PostWorkspacesApiResponse = /** status 200 OK */ { - id: number; company: string; + id: number; }; export type PostWorkspacesApiArg = { body: { @@ -1682,10 +1721,10 @@ export type GetWorkspacesByWidApiArg = { wid: string; }; export type GetWorkspacesByWidArchiveApiResponse = /** status 200 OK */ { + campaignsCounter: number; + description: string; id: number; name: string; - description: string; - campaignsCounter: number; }; export type GetWorkspacesByWidArchiveApiArg = { /** Workspace (company, customer) id */ @@ -1693,9 +1732,9 @@ export type GetWorkspacesByWidArchiveApiArg = { }; export type GetWorkspacesByWidCampaignsApiResponse = /** status 200 OK */ { items?: CampaignWithOutput[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetWorkspacesByWidCampaignsApiArg = { @@ -1714,9 +1753,9 @@ export type GetWorkspacesByWidCampaignsApiArg = { }; export type GetWorkspacesByWidCoinsApiResponse = /** status 200 OK */ { items?: Coin[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetWorkspacesByWidCoinsApiArg = { @@ -1731,20 +1770,8 @@ export type GetWorkspacesByWidCoinsApiArg = { /** Order by accepted field */ orderBy?: string; }; -export type PostWorkspacesByWidPlansApiResponse = /** status 201 Created */ { - id: number; -}; -export type PostWorkspacesByWidPlansApiArg = { - wid: string; - body: { - template_id: number; - project_id: number; - }; -}; export type GetWorkspacesByWidPlansApiResponse = /** status 200 OK */ { id: number; - title: string; - status: 'draft' | 'pending_review' | 'approved'; project: { id: number; title: string; @@ -1753,6 +1780,8 @@ export type GetWorkspacesByWidPlansApiResponse = /** status 200 OK */ { id: number; status: 'pending' | 'proposed' | 'approved' | 'rejected'; }; + status: 'draft' | 'pending_review' | 'approved'; + title: string; }[]; export type GetWorkspacesByWidPlansApiArg = { wid: string; @@ -1765,57 +1794,21 @@ export type GetWorkspacesByWidPlansApiArg = { /** Limit pagination parameter */ limit?: number; }; -export type DeletePlansByPidApiResponse = unknown; -export type DeletePlansByPidApiArg = { - pid: string; -}; -export type GetPlansByPidApiResponse = /** status 200 OK */ { +export type PostWorkspacesByWidPlansApiResponse = /** status 201 Created */ { id: number; - config: { - modules: Module[]; - }; - status: PlanStatus; - project: { - id: number; - name: string; - }; - quote?: { - id: number; - status: 'pending' | 'proposed' | 'approved' | 'rejected'; - value: string; - }; - campaign?: { - id: number; - /** CustomerTitle ?? Title */ - title: string; - startDate: string; - }; - workspace_id: number; -}; -export type GetPlansByPidApiArg = { - pid: string; -}; -export type PatchPlansByPidApiResponse = unknown; -export type PatchPlansByPidApiArg = { - pid: string; - body: { - config: { - modules: Module[]; - }; - }; }; -export type PatchPlansByPidStatusApiResponse = /** status 200 OK */ {}; -export type PatchPlansByPidStatusApiArg = { - pid: string; +export type PostWorkspacesByWidPlansApiArg = { + wid: string; body: { - status: PlanStatus; + project_id: number; + template_id: number; }; }; export type GetWorkspacesByWidProjectsApiResponse = /** status 200 OK */ { items?: Project[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetWorkspacesByWidProjectsApiArg = { @@ -1826,6 +1819,32 @@ export type GetWorkspacesByWidProjectsApiArg = { /** Start pagination parameter */ start?: number; }; +export type GetWorkspacesByWidProjectsAndPidApiResponse = + /** status 200 OK */ Project; +export type GetWorkspacesByWidProjectsAndPidApiArg = { + /** Workspace (company, customer) id */ + wid: string; + /** Project id */ + pid: string; +}; +export type GetWorkspacesByWidProjectsAndPidCampaignsApiResponse = + /** status 200 OK */ { + items?: CampaignWithOutput[]; + limit?: number; + size?: number; + start?: number; + total?: number; + }; +export type GetWorkspacesByWidProjectsAndPidCampaignsApiArg = { + /** Workspace (company, customer) id */ + wid: string; + /** Project id */ + pid: string; + /** Limit pagination parameter */ + limit?: number; + /** Start pagination parameter */ + start?: number; +}; export type GetWorkspacesByWidTemplatesApiResponse = /** status 200 OK */ { items: CpReqTemplate[]; } & PaginationData; @@ -1851,49 +1870,35 @@ export type DeleteWorkspacesByWidTemplatesAndTidApiArg = { }; export type GetWorkspacesByWidTemplatesAndTidApiResponse = /** status 200 OK */ { + config: string; + description?: string; id: number; name: string; - description?: string; - config: string; - workspace_id?: number; price?: string; strapi?: StrapiTemplate; + workspace_id?: number; }; export type GetWorkspacesByWidTemplatesAndTidApiArg = { wid: string; tid: string; }; -export type GetWorkspacesByWidProjectsAndPidApiResponse = - /** status 200 OK */ Project; -export type GetWorkspacesByWidProjectsAndPidApiArg = { - /** Workspace (company, customer) id */ - wid: string; - /** Project id */ - pid: string; +export type DeleteWorkspacesByWidUsersApiResponse = /** status 200 OK */ { + items: Tenant[]; }; -export type GetWorkspacesByWidProjectsAndPidCampaignsApiResponse = - /** status 200 OK */ { - items?: CampaignWithOutput[]; - start?: number; - limit?: number; - size?: number; - total?: number; - }; -export type GetWorkspacesByWidProjectsAndPidCampaignsApiArg = { +export type DeleteWorkspacesByWidUsersApiArg = { /** Workspace (company, customer) id */ wid: string; - /** Project id */ - pid: string; - /** Limit pagination parameter */ - limit?: number; - /** Start pagination parameter */ - start?: number; + body: { + include_shared?: boolean; + /** Tryber WP USER ID */ + user_id: number; + }; }; export type GetWorkspacesByWidUsersApiResponse = /** status 200 OK */ { items: Tenant[]; - start?: number; limit?: number; size?: number; + start?: number; total?: number; }; export type GetWorkspacesByWidUsersApiArg = { @@ -1909,75 +1914,65 @@ export type GetWorkspacesByWidUsersApiArg = { orderBy?: string; }; export type PostWorkspacesByWidUsersApiResponse = /** status 200 OK */ { + email: string; profile_id: number; tryber_wp_user_id: number; - email: string; }; export type PostWorkspacesByWidUsersApiArg = { /** Workspace (company, customer) id */ wid: string; body: { email: string; - name?: string; - surname?: string; - locale?: string; event_name?: string; - redirect_url?: string; + locale?: string; message?: string; - }; -}; -export type DeleteWorkspacesByWidUsersApiResponse = /** status 200 OK */ { - items: Tenant[]; -}; -export type DeleteWorkspacesByWidUsersApiArg = { - /** Workspace (company, customer) id */ - wid: string; - body: { - /** Tryber WP USER ID */ - user_id: number; - include_shared?: boolean; + name?: string; + redirect_url?: string; + surname?: string; }; }; export type Error = { - message: string; code: number; error: boolean; + message: string; }; export type Authentication = { - id: number; email: string; - role: string; + exp?: number; + iat?: number; + id: number; name: string; picture?: string; + role: string; token: string; - iat?: number; - exp?: number; }; export type Campaign = { - id: number; - start_date: string; - end_date: string; - close_date: string; - title: string; - customer_title: string; - is_public: number; + base_bug_internal_id?: string; /** -1: no bug form; 0: only bug form; 1: bug form with bug parade; */ bug_form?: number; - type: { + close_date: string; + customer_title: string; + description?: string; + end_date: string; + family: { id: number; name: string; }; - family: { + id: number; + is_public: number; + project: { id: number; name: string; }; + start_date: string; status: { id: number; name: string; }; - project: { + title: string; + type: { id: number; name: string; }; @@ -1985,48 +1980,6 @@ export type Campaign = { id: number; name: string; }; - description?: string; - base_bug_internal_id?: string; -}; -export type PlatformObject = { - /** os */ - id: number; - /** form_factor - - 0 => smartphone, - 1 => tablet - 2 => pc - 3 => smartwatch - 4 => console - 5 => tv */ - deviceType: number; -}; -export type TemplateCategory = { - id?: number; - name: string; -}; -export type Template = { - title: string; - /** Short description used as preview of template or in templates dropdown */ - description?: string; - /** HTML content used to pre-fill the use case editor */ - content?: string; - category?: TemplateCategory; - device_type?: 'webapp' | 'mobileapp'; - locale?: 'en' | 'it'; - image?: string; - /** The use case created by this template needs a login or not? */ - requiresLogin?: boolean; -}; -export type UseCase = { - title: string; - description: string; - /** Optional in experiential campaigns */ - functionality?: { - id?: number; - } & Template; - logged?: boolean; - link?: string; }; export type Output = 'bugs' | 'media' | 'insights'; export type CampaignWithOutput = Campaign & { @@ -2036,38 +1989,16 @@ export type BugType = { id: number; name: string; }; -export type BugTitle = { - full: string; - /** Bug title without context. */ - compact: string; - context?: string[]; -}; -export type BugStatus = { - id: number; - name: string; -}; -export type BugSeverity = { - id: number; - name: string; -}; -export type BugReplicability = { - id: number; - name: string; -}; -export type BugPriority = { - id: number; - name: string; -}; export type BugCustomStatusPhase = { id: number; name: string; }; export type BugCustomStatus = { + color: string; id: number; + is_default: number; name: string; - color: string; phase: BugCustomStatusPhase; - is_default: number; }; export type Smartphone = { manufacturer: string; @@ -2089,82 +2020,104 @@ export type Desktop = { os_version: string; type: 'desktop'; }; -export type Bug = { +export type BugPriority = { id: number; - internal_id: string; - campaign_id: number; - title: BugTitle; - step_by_step: string; - expected_result: string; - current_result: string; - status: BugStatus; - severity: BugSeverity; - type: BugType; - replicability: BugReplicability; - priority: BugPriority; - custom_status: BugCustomStatus; - created: string; - occurred_date: string; - updated?: string; - note?: string; - device: Smartphone | Tablet | Desktop; - application_section: { - id?: number; - prefix_title?: string; - title?: string; - simple_title?: string; - }; - duplicated_of_id?: number; - is_favorite?: number; - read?: boolean; + name: string; }; -export type BugMedia = { - mime_type: { - type: 'video' | 'image' | 'other'; - extension: string; - }; - url: string; - creation_date: string; +export type BugReplicability = { + id: number; + name: string; }; -export type BugTag = { +export type BugSeverity = { id: number; - tag_id: number; name: string; - slug: string; - bug_id: number; +}; +export type BugStatus = { + id: number; + name: string; +}; +export type BugTitle = { + /** Bug title without context. */ + compact: string; + context?: string[]; + full: string; +}; +export type Bug = { + application_section: { + id?: number; + prefix_title?: string; + simple_title?: string; + title?: string; + }; campaign_id: number; - author_wp_id?: number; - author_tid?: number; - creation_date: string; - is_visible_to_customer?: number; + created: string; + current_result: string; + custom_status: BugCustomStatus; + device: Smartphone | Tablet | Desktop; + duplicated_of_id?: number; + expected_result: string; + id: number; + internal_id: string; + is_favorite?: number; + note?: string; + occurred_date: string; + priority: BugPriority; + read?: boolean; + replicability: BugReplicability; + severity: BugSeverity; + status: BugStatus; + step_by_step: string; + title: BugTitle; + type: BugType; + updated?: string; }; export type BugAdditionalFieldRegex = { - validation: string; kind: 'regex'; + validation: string; }; export type BugAdditionalFieldSelect = { - options: string[]; kind: 'select'; + options: string[]; }; export type BugAdditionalField = { id: number; name: string; value: string; } & (BugAdditionalFieldRegex | BugAdditionalFieldSelect); -export type BugComment = { +export type BugMedia = { + creation_date: string; + mime_type: { + extension: string; + type: 'video' | 'image' | 'other'; + }; + url: string; +}; +export type BugTag = { + author_tid?: number; + author_wp_id?: number; + bug_id: number; + campaign_id: number; + creation_date: string; id: number; - text: string; + is_visible_to_customer?: number; + name: string; + slug: string; + tag_id: number; +}; +export type BugComment = { creation_date: string; creator: { id: number; - name: string; isInternal: boolean; + name: string; }; + id: number; media?: { - url: string; id: number; type: string; + url: string; }[]; + text: string; }; export type Cluster = { id: number; @@ -2183,45 +2136,45 @@ export type VideoTag = { }; }; export type Observation = { - id: number; - title: string; description: string; - start: number; end: number; + id: number; quotes: string; - uxNote?: string; + start: number; tags: VideoTag[]; + title: string; + uxNote?: string; }; export type Insight = { - id: number; - title: string; + comment?: string; description: string; + id: number; + observations: (Observation & { + uploaderId: number; + usecaseTitle: string; + video: { + deviceType: string; + id: number; + }; + })[]; severity: { id: number; name: string; style: string; }; + title: string; visible?: number; - comment?: string; - observations: (Observation & { - video: { - id: number; - deviceType: string; - }; - uploaderId: number; - usecaseTitle: string; - })[]; }; export type Grape = { - title: string; - severity: string; - usersNumber: number; observations: (Observation & { - uploaderId: number; - mediaId: number; deviceType: string; + mediaId: number; + uploaderId: number; usecaseTitle: string; })[]; + severity: string; + title: string; + usersNumber: number; }; export type ReportExtensions = | 'pdf' @@ -2239,98 +2192,98 @@ export type ReportExtensions = | 'gz' | '7z'; export type Report = { - id?: number; - title?: string; + creation_date?: string; description?: string; - url: string; file_type?: { + domain_name?: string; extension?: ReportExtensions; type: string; - domain_name?: string; }; - creation_date?: string; + id?: number; + title?: string; update_date?: string; + url: string; }; export type BannerType = | 'banner_testing_automation' | 'banner_user_experience' | 'banner_cyber_security'; export type Tenant = { + email: string; /** tryber wp_user_id */ id: number; - profile_id: number; - name: string; - email: string; invitationPending: boolean; + name: string; permissionFrom?: { - type?: 'workspace' | 'project'; id?: number; + type?: 'workspace' | 'project'; }; + profile_id: number; +}; +export type MediaSentiment = { + paragraphs: { + end: number; + reason: string; + start: number; + value: number; + }[]; + reason: string; + value: number; }; export type Word = { - start: number; end: number; /** Id of Speaker */ speaker?: number; + start: number; word: string; }; export type Paragraph = { - text: string; - start: number; end: number; /** Id Of speaker */ speaker?: number; + start: number; + text: string; words: Word[]; }; export type Transcript = { + paragraphs: Paragraph[]; /** Number of spekers */ speakers: number; - paragraphs: Paragraph[]; -}; -export type MediaSentiment = { - value: number; - reason: string; - paragraphs: { - start: number; - end: number; - value: number; - reason: string; - }[]; }; export type Video = { + duration?: number; id: number; - url: string; - streamUrl?: string; poster?: string; - duration?: number; + sentiment?: MediaSentiment; + streamUrl?: string; tester: { - id: number; - name: string; - surname: string; device: { type: 'smartphone' | 'tablet' | 'desktop' | 'other'; }; + id: number; + name: string; + surname: string; }; transcript?: Transcript; - sentiment?: MediaSentiment; + url: string; }; export type PaginationData = { - start?: number; - size?: number; limit?: number; + size?: number; + start?: number; total?: number; }; export type WidgetBugsByUseCase = { data: { + bugs: number; + description: string; title: { full: string; - simple?: string; - prefix?: string; info?: string; + prefix?: string; + simple?: string; }; - description: string; uniqueBugs?: number; - bugs: number; usecase_completion?: number; usecase_id: number; }[]; @@ -2338,30 +2291,30 @@ export type WidgetBugsByUseCase = { }; export type WidgetBugsByDevice = { data: ((Smartphone | Desktop | Tablet) & { - unique_bugs: number; /** Unique bugs */ bugs: number; + unique_bugs: number; })[]; kind: 'bugsByDevice'; }; export type WidgetCampaignProgress = { data: { - start_date: string; end_date: string; - /** Percentage fixed rate of completion */ - usecase_completion: 12.5 | 37.5 | 62.5 | 87.5 | 100; - /** Number of hours from start_date */ - time_elapsed: number; /** Expected amount of hours required to complete the campaign */ expected_duration: number; + start_date: string; + /** Number of hours from start_date */ + time_elapsed: number; + /** Percentage fixed rate of completion */ + usecase_completion: 12.5 | 37.5 | 62.5 | 87.5 | 100; }; kind: 'campaignProgress'; }; export type WidgetCampaignUniqueBugs = { data: { - unique: number; total: number; trend: number; + unique: number; }; kind: 'campaignUniqueBugs'; }; @@ -2373,149 +2326,87 @@ export type WidgetBugsByDuplicates = { }; export type WidgetCampaignUxTaggingVideoCompletionData = { data: { - countMediaWithObservation: number; countMedia: number; + countMediaWithObservation: number; }; kind: 'uxTaggingVideoCompletion'; }; -export type WidgetCampaignUxTotalTitlesVsRecurrentTitles = { - data: { - countTitleTag: number; - countObservationNoTitle: number; - countRecurrentTitles: number; - }; - kind: 'uxTotalTitlesVsRecurrentTitles'; -}; -export type WidgetCampaignUxSeveritiesDistribution = { - data: { - countObservations: number; - severitiesDistribution: { - countPositiveFindings: number; - countMinorIssue: number; - countMajorIssue: number; - countObservationSeverity: number; - }; - }; - kind: 'uxSeveritiesDistribution'; -}; -export type WidgetCampaignUxMostUsedTitles = { - data: { - mostUsedTitles: { - title: string; - usage: number; - mainSeverityAssignment: string; - }[]; - }; - kind: 'uxMostUsedTitles'; -}; -export type Project = { - id: number; - name: string; - campaigns_count: number; - workspaceId: number; - description?: string; - is_archive?: number; -}; -export type Feature = { - slug?: string; - name?: string; -}; -export type User = { - /** This is the main id of the user. Currently is equal to tryber_wp_user_id */ - id: number; - email: string; - role: string; - name: string; - profile_id: number; - tryber_wp_user_id: number; - unguess_wp_user_id: number; - picture?: string; - features?: Feature[]; -}; -export type UserPreference = { - preference_id: number; - value: string; - name: string; -}; -export type Workspace = { - id: number; - company: string; - tokens: number; - logo?: string; - csm: { - id: number; - email: string; - name: string; - profile_id: number; - tryber_wp_user_id: number; - picture?: string; - url?: string; +export type WidgetCampaignUxTotalTitlesVsRecurrentTitles = { + data: { + countObservationNoTitle: number; + countRecurrentTitles: number; + countTitleTag: number; }; - /** express coins */ - coins?: number; - /** Do this workspace have shared items? */ - isShared?: boolean; - /** Number of shared items */ - sharedItems?: number; + kind: 'uxTotalTitlesVsRecurrentTitles'; }; -export type Coin = { - id: number; - customer_id: number; - /** Number of available coin */ - amount: number; - agreement_id?: number; - /** This is the single coin price */ - price?: number; - created_on?: string; - /** On each coin use, the related package will be updated */ - updated_on?: string; +export type WidgetCampaignUxSeveritiesDistribution = { + data: { + countObservations: number; + severitiesDistribution: { + countMajorIssue: number; + countMinorIssue: number; + countObservationSeverity: number; + countPositiveFindings: number; + }; + }; + kind: 'uxSeveritiesDistribution'; +}; +export type WidgetCampaignUxMostUsedTitles = { + data: { + mostUsedTitles: { + mainSeverityAssignment: string; + title: string; + usage: number; + }[]; + }; + kind: 'uxMostUsedTitles'; }; export type ModuleTitle = { + output: string; type: 'title'; variant: string; - output: string; }; export type ModuleDate = { - type: 'dates'; - variant: string; output: { start: string; }; + type: 'dates'; + variant: string; }; export type SubcomponentTaskVideo = { + description?: string; kind: 'video'; title: string; - description?: string; url?: string; }; export type SubcomponentTaskBug = { + description?: string; kind: 'bug'; title: string; - description?: string; url?: string; }; export type SubcomponentTaskSurvey = { + description?: string; kind: 'survey'; title: string; - description?: string; url?: string; }; export type OutputModuleTaskModerateVideo = { + description?: string; kind: 'moderate-video'; title: string; - description?: string; url?: string; }; export type OutputModuleTaskExplorativeBug = { + description?: string; kind: 'explorative-bug'; title: string; - description?: string; url?: string; }; export type OutputModuleTaskAccessibility = { + description?: string; kind: 'accessibility'; title: string; - description?: string; url?: string; }; export type SubcomponentTask = @@ -2526,85 +2417,85 @@ export type SubcomponentTask = | OutputModuleTaskExplorativeBug | OutputModuleTaskAccessibility; export type ModuleTask = { + output: SubcomponentTask[]; type: 'tasks'; variant: string; - output: SubcomponentTask[]; }; export type OutputModuleAge = { - min: number; max: number; + min: number; percentage: number; }[]; export type ModuleAge = { + output: OutputModuleAge; type: 'age'; variant: string; - output: OutputModuleAge; }; export type ModuleLanguage = { + output: string; type: 'language'; variant: string; - output: string; }; export type OutputModuleLiteracy = { level: 'beginner' | 'intermediate' | 'expert'; percentage: number; }[]; export type ModuleLiteracy = { + output: OutputModuleLiteracy; type: 'literacy'; variant: string; - output: OutputModuleLiteracy; }; export type ModuleTarget = { + output: number; type: 'target'; variant: string; - output: number; }; export type ModuleGoal = { + output: string; type: 'goal'; variant: string; - output: string; }; export type OutputModuleGender = { gender: 'male' | 'female'; percentage: number; }[]; export type ModuleGender = { + output: OutputModuleGender; type: 'gender'; variant: string; - output: OutputModuleGender; }; export type ModuleOutOfScope = { + output: string; type: 'out_of_scope'; variant: string; - output: string; }; export type OutputModuleBrowser = { name: 'firefox' | 'edge' | 'chrome' | 'safari'; percentage: number; }[]; export type ModuleBrowser = { + output: OutputModuleBrowser; type: 'browser'; variant: string; - output: OutputModuleBrowser; }; export type ModuleTargetNote = { + output: string; type: 'target_note'; variant: string; - output: string; }; export type ModuleInstructionNote = { + output: string; type: 'instruction_note'; variant: string; - output: string; }; export type ModuleSetupNote = { + output: string; type: 'setup_note'; variant: string; - output: string; }; export type OutputModuleTouchpointsAppDesktop = { - kind: 'app'; form_factor: 'desktop'; + kind: 'app'; os: { linux?: string; macos?: string; @@ -2612,25 +2503,25 @@ export type OutputModuleTouchpointsAppDesktop = { }; }; export type OutputModuleTouchpointsAppTablet = { - kind: 'app'; form_factor: 'tablet'; + kind: 'app'; os: { - linux?: string; ios?: string; + linux?: string; windows?: string; }; }; export type OutputModuleTouchpointsAppSmartphone = { - kind: 'app'; form_factor: 'smartphone'; + kind: 'app'; os: { android?: string; ios?: string; }; }; export type OutputModuleTouchpointsWebDesktop = { - kind: 'web'; form_factor: 'desktop'; + kind: 'web'; os: { linux?: string; macos?: string; @@ -2638,16 +2529,16 @@ export type OutputModuleTouchpointsWebDesktop = { }; }; export type OutputModuleTouchpointsWebTablet = { - kind: 'web'; form_factor: 'tablet'; + kind: 'web'; os: { android?: string; ios?: string; }; }; export type OutputModuleTouchpointsWebSmartphone = { - kind: 'web'; form_factor: 'smartphone'; + kind: 'web'; os: { android?: string; ios?: string; @@ -2661,14 +2552,14 @@ export type SubcomponentTouchpoints = | OutputModuleTouchpointsWebTablet | OutputModuleTouchpointsWebSmartphone; export type ModuleTouchpoints = { + output: SubcomponentTouchpoints[]; type: 'touchpoints'; variant: string; - output: SubcomponentTouchpoints[]; }; export type ModuleAdditionalTarget = { + output: string; type: 'additional_target'; variant: string; - output: string; }; export type Module = | ModuleTitle @@ -2688,12 +2579,95 @@ export type Module = | ModuleTouchpoints | ModuleAdditionalTarget; export type PlanStatus = 'pending_review' | 'draft' | 'approved'; +export type Project = { + campaigns_count: number; + description?: string; + id: number; + is_archive?: number; + name: string; + workspaceId: number; +}; +export type DataForPostUsersRequestForInvitedUser = { + profileId: number; + token: string; + type: 'invite'; +}; +export type DataForPostUsersRequestForNewUser = { + email: string; + type: 'new'; + workspace: string; +}; +export type Feature = { + name?: string; + slug?: string; +}; +export type User = { + customer_role: string; + email: string; + features?: Feature[]; + /** This is the main id of the user. Currently is equal to tryber_wp_user_id */ + id: number; + name: string; + picture?: string; + profile_id: number; + role: string; + tryber_wp_user_id: number; + unguess_wp_user_id: number; +}; +export type UserPreference = { + name: string; + preference_id: number; + value: string; +}; +export type Workspace = { + /** express coins */ + coins?: number; + company: string; + csm: { + email: string; + id: number; + name: string; + picture?: string; + profile_id: number; + tryber_wp_user_id: number; + url?: string; + }; + id: number; + /** Do this workspace have shared items? */ + isShared?: boolean; + logo?: string; + /** Number of shared items */ + sharedItems?: number; + tokens: number; +}; +export type Coin = { + agreement_id?: number; + /** Number of available coin */ + amount: number; + created_on?: string; + customer_id: number; + id: number; + /** This is the single coin price */ + price?: number; + /** On each coin use, the related package will be updated */ + updated_on?: string; +}; export type StrapiTemplate = { - title: string; + background?: string; description: string; - pre_title: string; + how?: { + description: string; + icon: string; + title: string; + }[]; image?: string; output_image?: string; + pre_title: string; + price?: { + is_strikethrough?: number; + previous_price?: string; + price: string; + }; requirements?: { description: string; list: string[]; @@ -2702,64 +2676,53 @@ export type StrapiTemplate = { icon: string; text: string; }[]; + title: string; + what?: { + description: string; + goal: string; + }; why?: { + advantages: string[]; reasons: { + description: string; icon: string; title: string; - description: string; }[]; - advantages: string[]; - }; - what?: { - description: string; - goal: string; - }; - how?: { - icon: string; - title: string; - description: string; - }[]; - price?: { - price: string; - previous_price?: string; - is_strikethrough?: number; }; - background?: string; }; export type CpReqTemplate = { + config: string; + description?: string; id: number; name: string; - description?: string; - config: string; - workspace_id?: number; price?: string; strapi?: StrapiTemplate; + workspace_id?: number; }; export const { use$getQuery, - usePostAuthenticateMutation, usePostAnalyticsViewsCampaignsByCidMutation, - usePostCampaignsMutation, - usePatchCampaignsByCidMutation, + usePostAuthenticateMutation, useGetCampaignsByCidQuery, + usePatchCampaignsByCidMutation, useGetCampaignsByCidBugTypesQuery, useGetCampaignsByCidBugsQuery, useGetCampaignsByCidBugsAndBidQuery, usePatchCampaignsByCidBugsAndBidMutation, useGetCampaignsByCidBugsAndBidCommentsQuery, usePostCampaignsByCidBugsAndBidCommentsMutation, - usePostCampaignsByCidBugsAndBidMediaMutation, - usePostCampaignsByCidBugsAndBidCommentsCmidMutation, useDeleteCampaignsByCidBugsAndBidCommentsCmidMutation, + usePostCampaignsByCidBugsAndBidCommentsCmidMutation, + usePostCampaignsByCidBugsAndBidMediaMutation, useGetCampaignsByCidBugsAndBidSiblingsQuery, useGetCampaignsByCidClustersQuery, + useDeleteCampaignsByCidCustomStatusesMutation, useGetCampaignsByCidCustomStatusesQuery, usePatchCampaignsByCidCustomStatusesMutation, - useDeleteCampaignsByCidCustomStatusesMutation, useGetCampaignsByCidDevicesQuery, usePutCampaignsByCidFindingsAndFidMutation, - usePostCampaignsByCidInsightsMutation, useGetCampaignsByCidInsightsQuery, + usePostCampaignsByCidInsightsMutation, useGetCampaignsByCidMetaQuery, useGetCampaignsByCidObservationsQuery, useGetCampaignsByCidOsQuery, @@ -2771,36 +2734,43 @@ export const { usePostCampaignsByCidSuggestionsMutation, useGetCampaignsByCidTagsQuery, useGetCampaignsByCidUsecasesQuery, + useDeleteCampaignsByCidUsersMutation, useGetCampaignsByCidUsersQuery, usePostCampaignsByCidUsersMutation, - useDeleteCampaignsByCidUsersMutation, useGetCampaignsByCidUxQuery, useGetCampaignsByCidVideoTagsQuery, usePostCampaignsByCidVideoTagsMutation, useGetCampaignsByCidVideosQuery, useGetCampaignsByCidWidgetsQuery, - useGetInsightsByIidQuery, useDeleteInsightsByIidMutation, + useGetInsightsByIidQuery, usePatchInsightsByIidMutation, - useGetMediaByIdQuery, + useGetInvitesByProfileAndTokenQuery, useDeleteMediaCommentByMcidMutation, + useGetMediaByIdQuery, + useDeletePlansByPidMutation, + useGetPlansByPidQuery, + usePatchPlansByPidMutation, + usePatchPlansByPidStatusMutation, usePostProjectsMutation, + useDeleteProjectsByPidMutation, useGetProjectsByPidQuery, usePatchProjectsByPidMutation, - useDeleteProjectsByPidMutation, useGetProjectsByPidCampaignsQuery, + useDeleteProjectsByPidUsersMutation, useGetProjectsByPidUsersQuery, usePostProjectsByPidUsersMutation, - useDeleteProjectsByPidUsersMutation, - useGetTemplatesQuery, + usePostUsersMutation, + useHeadUsersByEmailByEmailMutation, useGetUsersMeQuery, useGetUsersMePreferencesQuery, usePutUsersMePreferencesBySlugMutation, + useGetUsersRolesQuery, useGetVideosByVidQuery, useGetVideosByVidObservationsQuery, usePostVideosByVidObservationsMutation, - usePatchVideosByVidObservationsAndOidMutation, useDeleteVideosByVidObservationsAndOidMutation, + usePatchVideosByVidObservationsAndOidMutation, useGetVideosByVidTranslationQuery, usePostVideosByVidTranslationMutation, useGetWorkspacesQuery, @@ -2809,19 +2779,15 @@ export const { useGetWorkspacesByWidArchiveQuery, useGetWorkspacesByWidCampaignsQuery, useGetWorkspacesByWidCoinsQuery, - usePostWorkspacesByWidPlansMutation, useGetWorkspacesByWidPlansQuery, - useDeletePlansByPidMutation, - useGetPlansByPidQuery, - usePatchPlansByPidMutation, - usePatchPlansByPidStatusMutation, + usePostWorkspacesByWidPlansMutation, useGetWorkspacesByWidProjectsQuery, + useGetWorkspacesByWidProjectsAndPidQuery, + useGetWorkspacesByWidProjectsAndPidCampaignsQuery, useGetWorkspacesByWidTemplatesQuery, useDeleteWorkspacesByWidTemplatesAndTidMutation, useGetWorkspacesByWidTemplatesAndTidQuery, - useGetWorkspacesByWidProjectsAndPidQuery, - useGetWorkspacesByWidProjectsAndPidCampaignsQuery, + useDeleteWorkspacesByWidUsersMutation, useGetWorkspacesByWidUsersQuery, usePostWorkspacesByWidUsersMutation, - useDeleteWorkspacesByWidUsersMutation, } = injectedRtkApi; diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 6cf4337a4..15929df48 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -704,6 +704,7 @@ "__PAGE_NOT_ACCESIBLE_DESCRIPTION": "It seems that your access is no longer active. You can log out or contact our support center. We are here to help you!", "__PAGE_NOT_ACCESIBLE_TITLE": "You cannot access this page at the moment.", "__PAGE_TITLE_BUGS_COLLECTION": "Bug collection", + "__PAGE_TITLE_JOIN": "join page", "__PAGE_TITLE_LOGIN": "Log in", "__PAGE_TITLE_PRIMARY_DASHBOARD": "My activities", "__PAGE_TITLE_PRIMARY_DASHBOARD_ARCHIVE": "Archive", @@ -1197,6 +1198,11 @@ "INSIGHT_PAGE_COLLECTION_USECASE_SUBTITTLE": "Recurring Themes", "INSIGHTS_PAGE_COLLECTION_SUBTITLE": "Here you can find all the observations collected so far.", "INSIGHTS_PAGE_COLLECTION_TITLE": "Themes and Observations", + "PASSWORD_VALIDATOR_CONTAIN_A_LOWERCASE_LETTER": "One lowercase character", + "PASSWORD_VALIDATOR_CONTAIN_A_NUMBER": "One numeric digit", + "PASSWORD_VALIDATOR_CONTAIN_AN_UPPERCASE_LETTER": "One uppercase character", + "PASSWORD_VALIDATOR_MINIMUM_OF_6_CHARACTERS": "Contain\u00a06 characters minimum", + "PASSWORD_VALIDATOR_PASSWORD_REQUIREMENTS": "Your password must:", "PLAN_GLOBAL_ALERT_APPROVED_STATE_MESSAGE": "You will be notified when the first data is available on your dashboard", "PLAN_GLOBAL_ALERT_APPROVED_STATE_TITLE": "The activity has been successfully launched!", "PLAN_GLOBAL_ALERT_AWATING_STATE_MESSAGE": "Review details and confirm to launch.", @@ -1205,6 +1211,46 @@ "PLAN_GLOBAL_ALERT_SUBMITTED_STATE_TITLE": "Activity submitted for review", "Severity ({{count}})_one": "Severity ({{count}})", "Severity ({{count}})_other": "Severities ({{count}})", + "SIGNUP_FORM_CTA_RETURN_TO_UNGUESS_LANDING": "Go to the UNGUESS website", + "SIGNUP_FORM_EMAIL_ALREADY_TAKEN": "Error: User with provided email already exists", + "SIGNUP_FORM_EMAIL_ERROR_SERVER_MAIL_CHECK": "Oops! Check your email format", + "SIGNUP_FORM_EMAIL_IS_REQUIRED": "This field is required", + "SIGNUP_FORM_EMAIL_LABEL": "Work Email", + "SIGNUP_FORM_EMAIL_MUST_BE_A_VALID_EMAIL": "Oops! Check your email format", + "SIGNUP_FORM_EMAIL_PLACEHOLDER": "Insert Email", + "SIGNUP_FORM_GO_TO_STEP_2": "Create my account", + "SIGNUP_FORM_GO_TO_STEP_3": "Next", + "SIGNUP_FORM_NAME_IS_REQUIRED": "This field is required", + "SIGNUP_FORM_NAME_LABEL": "First name", + "SIGNUP_FORM_NAME_PLACEHOLDER": "Insert name", + "SIGNUP_FORM_PASSWORD_HIDE": "hide", + "SIGNUP_FORM_PASSWORD_IS_A_REQUIRED_FIELD": "This field is required", + "SIGNUP_FORM_PASSWORD_LABEL": "Insert password", + "SIGNUP_FORM_PASSWORD_MUST_BE_AT_LEAST_6_CHARACTER_LONG": "The password must be at least 6 characters long", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_LOWERCASE_LETTER": "The password must contain at least one lowercase letter", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_NUMBER": "The password must contain at least one number", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_AN_UPPERCASE_LETTER": "The password must contain at least one uppercase letter", + "SIGNUP_FORM_PASSWORD_PLACEHOLDER": "Insert password", + "SIGNUP_FORM_PASSWORD_SHOW": "show", + "SIGNUP_FORM_RETURN_TO_STEP_1": "Back", + "SIGNUP_FORM_RETURN_TO_STEP_2": "Back", + "SIGNUP_FORM_ROLE_IS_REQUIRED": "This field is required", + "SIGNUP_FORM_ROLE_LABEL": "Job title", + "SIGNUP_FORM_STEP_1_DESCRIPTION": "Start personalizing your experience, it only takes a few minutes.", + "SIGNUP_FORM_STEP_1_TITLE": "Welcome!
Get started with your account!", + "SIGNUP_FORM_STEP_2_DESCRIPTION": "So we can tailor the experience to fit your role and needs.", + "SIGNUP_FORM_STEP_2_TITLE": "Tell us a bit about yourself", + "SIGNUP_FORM_STEP_3_DESCRIPTION": "Choose a name that represents your team — it’ll shape your personalized experience.", + "SIGNUP_FORM_STEP_3_TITLE": "Create your workspace", + "SIGNUP_FORM_SUBMIT": "Let's start!", + "SIGNUP_FORM_SURNAME_IS_REQUIRED": "This field is required", + "SIGNUP_FORM_SURNAME_LABEL": "Last name", + "SIGNUP_FORM_SURNAME_PLACEHOLDER": "Insert last name", + "SIGNUP_FORM_TERMS_AND_CONDITIONS": "By signing up, you agree to our Terms and Conditions", + "SIGNUP_FORM_WAITING_FOR_SIGNUP": "Setting up your accountThis will take just a few seconds.", + "SIGNUP_FORM_WORKSPACE_IS_REQUIRED": "This field is required", + "SIGNUP_FORM_WORKSPACE_LABEL": "Name your Workspace", + "SIGNUP_FORM_WORKSPACE_PLACEHOLDER": "Insert Workspace name", "UseCase ({{count}})_one": "Use Case ({{count}})", "UseCase ({{count}})_other": "Use Cases ({{count}})", "UX_SHORTCUT_ADD_OBSERVATION": "Start/Stop new observation", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 651b368a0..ee9fdac0f 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -734,6 +734,7 @@ "__PAGE_NOT_ACCESIBLE_DESCRIPTION": "Sembra che tu non abbia più accesso al workspace. Se hai bisogno di aiuto, contatta il nostro centro assistenza. ", "__PAGE_NOT_ACCESIBLE_TITLE": "Al momento non è possibile accedere a questa pagina.", "__PAGE_TITLE_BUGS_COLLECTION": "Raccolta bug", + "__PAGE_TITLE_JOIN": "", "__PAGE_TITLE_LOGIN": "Accedi", "__PAGE_TITLE_PRIMARY_DASHBOARD": "Le mie campagne", "__PAGE_TITLE_PRIMARY_DASHBOARD_ARCHIVE": "", @@ -1235,6 +1236,11 @@ "INSIGHT_PAGE_COLLECTION_USECASE_SUBTITTLE": "Titoli ricorrenti", "INSIGHTS_PAGE_COLLECTION_SUBTITLE": "Qui trovi tutte le tue osservazioni che hai collezionato fin ad ora.", "INSIGHTS_PAGE_COLLECTION_TITLE": "Temi e osservazioni", + "PASSWORD_VALIDATOR_CONTAIN_A_LOWERCASE_LETTER": "", + "PASSWORD_VALIDATOR_CONTAIN_A_NUMBER": "", + "PASSWORD_VALIDATOR_CONTAIN_AN_UPPERCASE_LETTER": "", + "PASSWORD_VALIDATOR_MINIMUM_OF_6_CHARACTERS": "", + "PASSWORD_VALIDATOR_PASSWORD_REQUIREMENTS": "", "PLAN_GLOBAL_ALERT_APPROVED_STATE_MESSAGE": "", "PLAN_GLOBAL_ALERT_APPROVED_STATE_TITLE": "", "PLAN_GLOBAL_ALERT_AWATING_STATE_MESSAGE": "", @@ -1244,6 +1250,46 @@ "Severity ({{count}})_one": "Gravità ({{count}})", "Severity ({{count}})_many": "", "Severity ({{count}})_other": "Gravità ({{count}})", + "SIGNUP_FORM_CTA_RETURN_TO_UNGUESS_LANDING": "", + "SIGNUP_FORM_EMAIL_ALREADY_TAKEN": "", + "SIGNUP_FORM_EMAIL_ERROR_SERVER_MAIL_CHECK": "", + "SIGNUP_FORM_EMAIL_IS_REQUIRED": "", + "SIGNUP_FORM_EMAIL_LABEL": "", + "SIGNUP_FORM_EMAIL_MUST_BE_A_VALID_EMAIL": "", + "SIGNUP_FORM_EMAIL_PLACEHOLDER": "", + "SIGNUP_FORM_GO_TO_STEP_2": "", + "SIGNUP_FORM_GO_TO_STEP_3": "", + "SIGNUP_FORM_NAME_IS_REQUIRED": "", + "SIGNUP_FORM_NAME_LABEL": "", + "SIGNUP_FORM_NAME_PLACEHOLDER": "", + "SIGNUP_FORM_PASSWORD_HIDE": "", + "SIGNUP_FORM_PASSWORD_IS_A_REQUIRED_FIELD": "", + "SIGNUP_FORM_PASSWORD_LABEL": "", + "SIGNUP_FORM_PASSWORD_MUST_BE_AT_LEAST_6_CHARACTER_LONG": "", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_LOWERCASE_LETTER": "", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_NUMBER": "", + "SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_AN_UPPERCASE_LETTER": "", + "SIGNUP_FORM_PASSWORD_PLACEHOLDER": "", + "SIGNUP_FORM_PASSWORD_SHOW": "", + "SIGNUP_FORM_RETURN_TO_STEP_1": "", + "SIGNUP_FORM_RETURN_TO_STEP_2": "", + "SIGNUP_FORM_ROLE_IS_REQUIRED": "", + "SIGNUP_FORM_ROLE_LABEL": "", + "SIGNUP_FORM_STEP_1_DESCRIPTION": "", + "SIGNUP_FORM_STEP_1_TITLE": "", + "SIGNUP_FORM_STEP_2_DESCRIPTION": "", + "SIGNUP_FORM_STEP_2_TITLE": "", + "SIGNUP_FORM_STEP_3_DESCRIPTION": "", + "SIGNUP_FORM_STEP_3_TITLE": "", + "SIGNUP_FORM_SUBMIT": "", + "SIGNUP_FORM_SURNAME_IS_REQUIRED": "", + "SIGNUP_FORM_SURNAME_LABEL": "", + "SIGNUP_FORM_SURNAME_PLACEHOLDER": "", + "SIGNUP_FORM_TERMS_AND_CONDITIONS": "", + "SIGNUP_FORM_WAITING_FOR_SIGNUP": "", + "SIGNUP_FORM_WORKSPACE_IS_REQUIRED": "", + "SIGNUP_FORM_WORKSPACE_LABEL": "", + "SIGNUP_FORM_WORKSPACE_PLACEHOLDER": "", "UseCase ({{count}})_one": "Use Case ({{count}})", "UseCase ({{count}})_many": "", "UseCase ({{count}})_other": "Use Case ({{count}})", diff --git a/src/pages/JoinPage/FormProvider.tsx b/src/pages/JoinPage/FormProvider.tsx new file mode 100644 index 000000000..af34e65c2 --- /dev/null +++ b/src/pages/JoinPage/FormProvider.tsx @@ -0,0 +1,51 @@ +import { Formik, Form, FormikProps } from 'formik'; +import { useMemo } from 'react'; +import { useValidationSchema } from './validationSchema'; +import { useJoinSubmit } from './useJoinSubmit'; +import { JoinFormValues } from './valuesType'; + +interface FormProviderProps { + children: (props: FormikProps) => React.ReactNode; + email?: string; + name?: string; + surname?: string; + workspace?: string; +} + +export const FormProvider = ({ + children, + email, + name, + surname, + workspace, +}: FormProviderProps) => { + const initialValues: JoinFormValues = { + step: 1, + email: email || '', + password: '', + name: name || '', + surname: surname || '', + roleId: 0, + workspace: workspace || '', + }; + + // logic to check if the user is invited + // for the time being we are checking if the mail is not empty + const isInvited = useMemo(() => !!email, [email]); + const validationSchema = useValidationSchema(); + const { onSubmit } = useJoinSubmit(isInvited); + + return ( + + {(props) =>
{children(props)}
} +
+ ); +}; diff --git a/src/pages/JoinPage/ImagesColumn.tsx b/src/pages/JoinPage/ImagesColumn.tsx new file mode 100644 index 000000000..fadbf548a --- /dev/null +++ b/src/pages/JoinPage/ImagesColumn.tsx @@ -0,0 +1,82 @@ +import { useFormikContext } from 'formik'; +import { AnimatePresence } from 'motion/react'; +import * as motion from 'motion/react-client'; +import { useEffect, useMemo, useState } from 'react'; +import logoImgs from 'src/assets/join-loghi.png'; +import logoImgsWebp from 'src/assets/join-loghi.webp'; +import joinImg1 from 'src/assets/join-step-1.svg'; +import joinImg1webp from 'src/assets/join-step-1.webp'; +import joinImg2 from 'src/assets/join-step-2.png'; +import joinImg2webp from 'src/assets/join-step-2.webp'; +import joinImg3 from 'src/assets/join-step-3.png'; +import joinImg3webp from 'src/assets/join-step-3.webp'; +import styled from 'styled-components'; +import { JoinFormValues } from './valuesType'; + +const ImagesWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + width: 100%; + height: calc(100vh - ${({ theme }) => theme.space.xl} * 2); + overflow: hidden; +`; + +const LogoPicture = styled.picture` + position: absolute; + bottom: 0; + left: 0; + width: 100%; +`; + +export const ImagesColumn = () => { + const { values } = useFormikContext(); + const [step, setStep] = useState(values.step); + const forwardAnimation = useMemo( + () => values.step - step * 10, + [values.step, step] + ); + useEffect(() => { + setStep(values.step); + }, [values.step]); + return ( + + + + {step === 1 && ( + + + Unguess Join Step 1 + + )} + {step === 2 && ( + + + Unguess Join Step 2 + + )} + {step === 3 && ( + + + Unguess Join Step 3 + + )} + + + {step === 1 && ( + + + Unguess partners + + )} + + ); +}; diff --git a/src/pages/JoinPage/JoinForm.tsx b/src/pages/JoinPage/JoinForm.tsx new file mode 100644 index 000000000..5a9b0492d --- /dev/null +++ b/src/pages/JoinPage/JoinForm.tsx @@ -0,0 +1,53 @@ +import { Paragraph, XL } from '@appquality/unguess-design-system'; +import { useFormikContext } from 'formik'; +import { Trans, useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import styled from 'styled-components'; +import { Step1 } from './Steps/Step1'; +import { Step2 } from './Steps/Step2'; +import { Step3 } from './Steps/Step3'; +import { JoinFormValues } from './valuesType'; + +const FieldContainer = styled.div` + display: flex; + flex-direction: column; + gap: ${(p) => p.theme.space.md}; +`; + +const FormContainer = styled.div` + @media (min-width: ${(p) => p.theme.breakpoints.md}) { + padding: 0 ${(p) => p.theme.space.xxl}; + } +`; + +export const JoinForm = () => { + const { + values: { step }, + } = useFormikContext(); + const { t } = useTranslation(); + return ( + +
+ + {step === 1 && ( + }} + /> + )} + {step === 2 && t('SIGNUP_FORM_STEP_2_TITLE')} + {step === 3 && t('SIGNUP_FORM_STEP_3_TITLE')} + + + {step === 2 && t('SIGNUP_FORM_STEP_2_DESCRIPTION')} + {step === 3 && t('SIGNUP_FORM_STEP_3_DESCRIPTION')} + +
+ + {step === 1 && } + {step === 2 && } + {step === 3 && } + +
+ ); +}; diff --git a/src/pages/JoinPage/JoinPageError.tsx b/src/pages/JoinPage/JoinPageError.tsx new file mode 100644 index 000000000..c56bbe0fe --- /dev/null +++ b/src/pages/JoinPage/JoinPageError.tsx @@ -0,0 +1,91 @@ +import { Button, MD, XL } from '@appquality/unguess-design-system'; +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; +import { appTheme } from 'src/app/theme'; +import { ReactComponent as BackgroundImage } from 'src/assets/icons/lost-in-the-space.svg'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; +import styled from 'styled-components'; + +const Wrapper = styled.div` + width: 100%; + height: 100vh; + background-color: ${appTheme.palette.grey[100]}; + display: flex; + align-items: center; +`; + +const StyledRow = styled.div` + margin-left: auto; + margin-right: auto; + display: flex; + flex-direction: column; + align-items: center; + gap: ${appTheme.space.md}; + + @media (min-width: ${appTheme.breakpoints.xl}) { + flex-direction: row; + max-width: 1200px; + } +`; +const ButtonWrapper = styled.div` + display: flex; + gap: ${appTheme.space.sm}; + margin-top: ${appTheme.space.md}; +`; + +export const JoinPageError = () => { + const { t } = useTranslation(); + const sendGTMevent = useSendGTMevent(); + const { profile, token } = useParams(); + const isInvited = profile && token; + + useEffect(() => { + sendGTMevent({ + event: 'sign-up-flow', + category: 'not set', + action: 'not set', + content: 'error page', + target: `is invited: ${isInvited}`, + }); + }, []); + + return ( + + + + +
+ + {t('JOIN_PAGE_ERROR_TITLE')} + + {t('JOIN_PAGE_ERROR_DESCRIPTION')} + + + + +
+
+
+ ); +}; diff --git a/src/pages/JoinPage/JoinPageLoading.tsx b/src/pages/JoinPage/JoinPageLoading.tsx new file mode 100644 index 000000000..31f6a1d66 --- /dev/null +++ b/src/pages/JoinPage/JoinPageLoading.tsx @@ -0,0 +1,7 @@ +export const JoinPageLoading = () => ( +
+
+ loading +
+
+); diff --git a/src/pages/JoinPage/Steps/ButtonContainer.tsx b/src/pages/JoinPage/Steps/ButtonContainer.tsx new file mode 100644 index 000000000..7690d97e5 --- /dev/null +++ b/src/pages/JoinPage/Steps/ButtonContainer.tsx @@ -0,0 +1,9 @@ +import styled from 'styled-components'; + +export const ButtonContainer = styled.div` + display: flex; + gap: ${(p) => p.theme.space.sm}; + align-items: center; + justify-content: flex-end; + padding-top: ${(p) => p.theme.space.md}; +`; diff --git a/src/pages/JoinPage/Steps/PasswordRequirements.tsx b/src/pages/JoinPage/Steps/PasswordRequirements.tsx new file mode 100644 index 000000000..795147968 --- /dev/null +++ b/src/pages/JoinPage/Steps/PasswordRequirements.tsx @@ -0,0 +1,63 @@ +import { MD, theme } from '@appquality/unguess-design-system'; +import { ReactComponent as X } from 'src/assets/icons/password-check-x.svg'; +import { ReactComponent as Check } from 'src/assets/icons/password-check-v.svg'; +import { useFormikContext } from 'formik'; +import { useTranslation } from 'react-i18next'; +import { JoinFormValues } from '../valuesType'; + +const PasswordRequirement = ({ + check, + children, +}: { + check: () => boolean; + children: React.ReactNode; +}) => ( +
  • + {check() ? ( +
  • +); + +const PasswordRequirements = () => { + const { values } = useFormikContext(); + const { t } = useTranslation(); + + return ( +
    + {t('PASSWORD_VALIDATOR_PASSWORD_REQUIREMENTS')} +
      + values.password.length >= 6}> + {t('PASSWORD_VALIDATOR_MINIMUM_OF_6_CHARACTERS')} + + values.password.match(/[A-Z]/) !== null} + > + {t('PASSWORD_VALIDATOR_CONTAIN_AN_UPPERCASE_LETTER')} + + values.password.match(/[a-z]/) !== null} + > + {t('PASSWORD_VALIDATOR_CONTAIN_A_LOWERCASE_LETTER')} + + values.password.match(/[0-9]/) !== null} + > + {t('PASSWORD_VALIDATOR_CONTAIN_A_NUMBER')} + +
    +
    + ); +}; + +export { PasswordRequirements }; diff --git a/src/pages/JoinPage/Steps/Step1.tsx b/src/pages/JoinPage/Steps/Step1.tsx new file mode 100644 index 000000000..7e9c83895 --- /dev/null +++ b/src/pages/JoinPage/Steps/Step1.tsx @@ -0,0 +1,210 @@ +import { + Anchor, + Button, + FormField, + Input, + Label, + MediaInput, + Message, + Paragraph, + Span, +} from '@appquality/unguess-design-system'; +import { ReactComponent as LinkIcon } from '@zendeskgarden/svg-icons/src/16/chevron-left-stroke.svg'; +import { ReactComponent as Eye } from '@zendeskgarden/svg-icons/src/16/eye-fill.svg'; +import { ReactComponent as EyeHide } from '@zendeskgarden/svg-icons/src/16/eye-hide-fill.svg'; +import { Field, FieldProps, useFormikContext } from 'formik'; +import { useEffect, useState } from 'react'; +import { Trans, useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; +import { JoinFormValues } from '../valuesType'; +import { ButtonContainer } from './ButtonContainer'; +import { PasswordRequirements } from './PasswordRequirements'; + +export const Step1 = () => { + const { setFieldValue, validateForm, setTouched, status, values } = + useFormikContext(); + const sendGTMevent = useSendGTMevent(); + const { t } = useTranslation(); + const [inputType, setInputType] = useState('password'); + const handleChangeInputType = () => { + setInputType((prev) => (prev === 'password' ? 'text' : 'password')); + }; + + useEffect(() => { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + content: 'step 1 rendered', + }); + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + action: 'start', + }); + }, []); + + const goToNextStep = async () => { + await setTouched({ + email: true, + password: true, + }); + const errors = await validateForm(); + if (Object.keys(errors).length > 0) { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + action: 'step 1 validation error', + content: `error count: ${Object.keys(errors).length}`, + }); + return; + } + setFieldValue('step', 2); + }; + + const validateEmail = async (value: string) => { + let error; + let error_event; + if (status?.isInvited) return error; + const res = await fetch( + `${process.env.REACT_APP_API_URL}/users/by-email/${value}`, + { + method: 'HEAD', + } + ); + + if (res.status === 200) { + error = t('SIGNUP_FORM_EMAIL_ALREADY_TAKEN'); + error_event = 'SIGNUP_FORM_EMAIL_ALREADY_TAKEN'; + } else if (res.status === 404) { + error = undefined; + error_event = 'no error'; + } else { + error = t('SIGNUP_FORM_EMAIL_ERROR_SERVER_MAIL_CHECK'); + error_event = 'SIGNUP_FORM_EMAIL_ERROR_SERVER_MAIL_CHECK'; + } + sendGTMevent({ + event: 'sign-up-flow', + category: 'not set', + action: 'validate email', + content: `error: ${error_event}`, + target: `is invited: ${status?.isInvited}`, + }); + return error; + }; + + return ( + <> + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( + + + + {hasError && ( + + {meta.error} + + )} + + ); + }} + + + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( + + + + ) : ( + + ) + } + {...field} + placeholder={t('SIGNUP_FORM_PASSWORD_PLACEHOLDER')} + {...(hasError && { validation: 'error' })} + /> + {hasError && ( + + {meta.error} + + )} + + ); + }} + + + + + + + + ), + }} + /> + +
    + + + {t('SIGNUP_FORM_CTA_RETURN_TO_UNGUESS_LANDING')} + +
    + + ); +}; diff --git a/src/pages/JoinPage/Steps/Step2.tsx b/src/pages/JoinPage/Steps/Step2.tsx new file mode 100644 index 000000000..7b0d715ba --- /dev/null +++ b/src/pages/JoinPage/Steps/Step2.tsx @@ -0,0 +1,170 @@ +import { + Button, + FormField, + Input, + Label, + Message, + Select, + Span, +} from '@appquality/unguess-design-system'; +import { Field, FieldProps, useFormikContext } from 'formik'; +import { useEffect, useMemo, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import { useGetUsersRolesQuery } from 'src/features/api'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; +import { JoinFormValues } from '../valuesType'; +import { ButtonContainer } from './ButtonContainer'; + +export const Step2 = () => { + const { setFieldValue, validateForm, setTouched, status } = + useFormikContext(); + const { t } = useTranslation(); + const sendGTMevent = useSendGTMevent(); + const { data, isLoading } = useGetUsersRolesQuery(); + const selectRef = useRef(null); + + useEffect(() => { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + content: 'step 2 rendered', + }); + }, []); + + const renderOptions = useMemo( + () => + isLoading || !data ? ( + loading... + ) : ( + data?.map((role) => ( + + {role.name} + + )) + ), + [data] + ); + const goToNextStep = async () => { + await setTouched({ + name: true, + surname: true, + roleId: true, + }); + const errors = await validateForm(); + if (Object.keys(errors).length > 0) { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + action: 'step 2 validation error', + content: `error count: ${Object.keys(errors).length}`, + }); + return; + } + setFieldValue('step', 3); + }; + const goToPreviousStep = () => { + setFieldValue('step', 1); + }; + return ( + <> + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( + + + + {hasError && ( + + {meta.error} + + )} + + ); + }} + + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( + + + + {hasError && ( + + {meta.error} + + )} + + ); + }} + + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( +
    + + {hasError && ( + + {meta.error} + + )} +
    + ); + }} +
    + + + + + + ); +}; diff --git a/src/pages/JoinPage/Steps/Step3.tsx b/src/pages/JoinPage/Steps/Step3.tsx new file mode 100644 index 000000000..abd257389 --- /dev/null +++ b/src/pages/JoinPage/Steps/Step3.tsx @@ -0,0 +1,68 @@ +import { + Button, + FormField, + Input, + Label, + Message, + Span, +} from '@appquality/unguess-design-system'; +import { Field, FieldProps, useFormikContext } from 'formik'; +import { useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; +import { JoinFormValues } from '../valuesType'; +import { ButtonContainer } from './ButtonContainer'; +import { useEffect } from 'react'; + +export const Step3 = () => { + const { setFieldValue, values, status } = useFormikContext(); + const { t } = useTranslation(); + const sendGTMevent = useSendGTMevent(); + useEffect(() => { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${status?.isInvited}`, + content: 'step 3 rendered', + }); + }, []); + const goToPreviousStep = () => { + setFieldValue('step', 2); + }; + return ( + <> + + {({ field, meta }: FieldProps) => { + const hasError = meta.touched && Boolean(meta.error); + return ( + + + + {hasError && ( + + {meta.error} + + )} + + ); + }} + + + + + + + ); +}; diff --git a/src/pages/JoinPage/WaitModal.tsx b/src/pages/JoinPage/WaitModal.tsx new file mode 100644 index 000000000..7edf07625 --- /dev/null +++ b/src/pages/JoinPage/WaitModal.tsx @@ -0,0 +1,37 @@ +import { Modal, LG, XL, Skeleton } from '@appquality/unguess-design-system'; +import { Trans } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; + +export const WaitModal = () => ( + + , + XL: ( + + ), + }} + /> + + +); diff --git a/src/pages/JoinPage/index.tsx b/src/pages/JoinPage/index.tsx new file mode 100644 index 000000000..3c72fbb83 --- /dev/null +++ b/src/pages/JoinPage/index.tsx @@ -0,0 +1,146 @@ +import { Col, Grid, Logo, Row } from '@appquality/unguess-design-system'; +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import { useAppSelector } from 'src/app/hooks'; +import joinBg from 'src/assets/join-bg-1.png'; +import joingBgwebp from 'src/assets/join-bg-1.webp'; +import joinBg2 from 'src/assets/join-bg-2.png'; +import joinBg2webp from 'src/assets/join-bg-2.webp'; +import joinBg3 from 'src/assets/join-bg-3.png'; +import joinBg3webp from 'src/assets/join-bg-3.webp'; +import { GoogleTagManager } from 'src/common/GoogleTagManager'; +import { useGetInvitesByProfileAndTokenQuery } from 'src/features/api'; +import styled from 'styled-components'; +import { FormProvider } from './FormProvider'; +import { JoinForm } from './JoinForm'; +import { JoinPageError } from './JoinPageError'; +import { JoinPageLoading } from './JoinPageLoading'; +import { WaitModal } from './WaitModal'; +import { ImagesColumn } from './ImagesColumn'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; + +const CenteredXYContainer = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + margin: 0 auto; + padding: 0 ${({ theme }) => theme.space.md}; + max-width: ${({ theme }) => theme.breakpoints.md}; + @media (min-width: ${({ theme }) => theme.breakpoints.xl}) { + padding: 0 ${({ theme }) => theme.space.xl}; + max-width: ${({ theme }) => theme.breakpoints.xxl}; + } +`; + +const Background = styled.div<{ step: string }>` + // Default background + @media (min-width: ${({ theme }) => theme.breakpoints.xl}) { + ${({ step }) => + step === '1' && + ` + background-image: url(${joinBg}); + @supports (background-image: url(${joingBgwebp})) { + background-image: url(${joingBgwebp}); + } + `} + ${({ step }) => + step === '2' && + ` + background-image: url(${joinBg2}); + @supports (background-image: url(${joinBg2webp})) { + background-image: url(${joinBg2webp}); + } + `} + ${({ step }) => + step === '3' && + ` + background-image: url(${joinBg3}); + @supports (background-image: url(${joinBg3webp})) { + background-image: url(${joinBg3webp}); + } + `} + background-repeat: no-repeat; + background-position: right top; + background-size: 61%; + } + position: relative; + width: 100%; + min-height: calc(100vh - ${({ theme }) => theme.space.xl} * 2); + padding: ${({ theme }) => theme.space.xl} 0 ${({ theme }) => theme.space.md}; +`; + +const StyledCol = styled(Col)` + margin-bottom: 0; +`; + +const LogoWrapper = styled.div` + text-align: center; + margin-bottom: ${(p) => p.theme.space.lg}; +`; + +const JoinPage = () => { + const { t } = useTranslation(); + const [searchParams] = useSearchParams(); + const { status } = useAppSelector((state) => state.user); + const navigate = useNavigate(); + const { profile, token } = useParams(); + const sendGTMevent = useSendGTMevent(); + const shouldSkipQuery = + status === 'logged' || status === 'loading' || !(profile && token); + + const { isLoading, data, error } = useGetInvitesByProfileAndTokenQuery( + { + profile: profile || '', + token: token || '', + }, + { + skip: shouldSkipQuery, + } + ); + + useEffect(() => { + if (status === 'logged') { + navigate(searchParams.get('redirectTo') || '/'); + } + }, [navigate, status, searchParams]); + + if (isLoading || (shouldSkipQuery && profile && token)) { + return ; + } + + if (error) return ; + + return ( + + + {({ isSubmitting, values: { step } }) => ( + + + {isSubmitting ? ( + + ) : ( + + + + + + + + + + + + + + )} + + + )} + + + ); +}; + +export default JoinPage; diff --git a/src/pages/JoinPage/useJoinSubmit.tsx b/src/pages/JoinPage/useJoinSubmit.tsx new file mode 100644 index 000000000..2ccbd053c --- /dev/null +++ b/src/pages/JoinPage/useJoinSubmit.tsx @@ -0,0 +1,122 @@ +import { Notification, useToast } from '@appquality/unguess-design-system'; +import { FormikHelpers } from 'formik'; +import { useCallback } from 'react'; +import { useParams, useSearchParams } from 'react-router-dom'; +import WPAPI from 'src/common/wpapi'; +import { usePostUsersMutation } from 'src/features/api'; +import { useSendGTMevent } from 'src/hooks/useGTMevent'; +import { JoinFormValues } from './valuesType'; + +export function useJoinSubmit(isInvited: boolean) { + const [postFormValues] = usePostUsersMutation(); + const { addToast } = useToast(); + const [searchParams] = useSearchParams(); + const redirectTo = searchParams.get('redirect'); + const { token, profile } = useParams(); + const sendGTMevent = useSendGTMevent(); + + const onSubmit = useCallback( + async ( + values: JoinFormValues, + { setSubmitting }: FormikHelpers + ) => { + setSubmitting(true); + const basicInfo = { + email: values.email, + password: values.password, + name: values.name, + surname: values.surname, + roleId: values.roleId, + }; + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${isInvited}`, + action: 'start submit', + content: `role: ${values.roleId}`, + }); + try { + let res; + if (isInvited) { + if (!token || !profile) + throw new Error('Token or profile is missing'); + res = await postFormValues({ + body: { + type: 'invite', + ...basicInfo, + profileId: Number(profile), + token, + }, + }).unwrap(); + } else { + res = await postFormValues({ + body: { + type: 'new', + ...basicInfo, + email: values.email, + workspace: values.workspace, + }, + }).unwrap(); + } + const nonce = await WPAPI.getNonce(); + const login = await WPAPI.login({ + username: values.email, + password: values.password, + security: nonce, + }); + + if (login) { + if (redirectTo) { + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${isInvited}`, + action: 'submit success', + content: 'redirect', + }); + window.location.href = redirectTo; + } else if (res.projectId) { + document.location.href = `/projects/${res.projectId}`; + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${isInvited}`, + action: 'submit success', + content: 'project', + }); + } else { + document.location.href = '/'; + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${isInvited}`, + action: 'submit success', + content: 'home', + }); + } + } else document.location.href = '/oops'; + } catch (err) { + const message = `Error creating user: ${ + err instanceof Error && err.message ? err.message : 'Unknown error' + }`; + sendGTMevent({ + event: 'sign-up-flow', + category: `is invited: ${isInvited}`, + action: 'submit error', + content: message, + }); + addToast( + ({ close }) => ( + + ), + { placement: 'top' } + ); + } + setSubmitting(false); + }, + [postFormValues, token, profile, isInvited] + ); + + return { onSubmit }; +} diff --git a/src/pages/JoinPage/validationSchema.ts b/src/pages/JoinPage/validationSchema.ts new file mode 100644 index 000000000..af4191c9e --- /dev/null +++ b/src/pages/JoinPage/validationSchema.ts @@ -0,0 +1,51 @@ +import * as yup from 'yup'; +import { useTranslation } from 'react-i18next'; + +export const useValidationSchema = () => { + const { t } = useTranslation(); + + return yup.object({ + email: yup.string().when('step', { + is: 1, + then: yup + .string() + .required(t('SIGNUP_FORM_EMAIL_IS_REQUIRED')) + .email(t('SIGNUP_FORM_EMAIL_MUST_BE_A_VALID_EMAIL')), + }), + password: yup.string().when('step', { + is: 1, + then: yup + .string() + .min(6, t('SIGNUP_FORM_PASSWORD_MUST_BE_AT_LEAST_6_CHARACTER_LONG')) + .matches( + /[0-9]/, + t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_NUMBER') + ) + .matches( + /[A-Z]/, + t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_AN_UPPERCASE_LETTER') + ) + .matches( + /[a-z]/, + t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_LOWERCASE_LETTER') + ) + .required(t('SIGNUP_FORM_PASSWORD_IS_A_REQUIRED_FIELD')), + }), + name: yup.string().when('step', { + is: 2, + then: yup.string().required(t('SIGNUP_FORM_NAME_IS_REQUIRED')), + }), + surname: yup.string().when('step', { + is: 2, + then: yup.string().required(t('SIGNUP_FORM_SURNAME_IS_REQUIRED')), + }), + roleId: yup.number().when('step', { + is: 2, + then: yup.number().positive(t('SIGNUP_FORM_ROLE_IS_REQUIRED')), + }), + workspace: yup.string().when('step', { + is: 3, + then: yup.string().required(t('SIGNUP_FORM_WORKSPACE_IS_REQUIRED')), + }), + }); +}; diff --git a/src/pages/JoinPage/valuesType.ts b/src/pages/JoinPage/valuesType.ts new file mode 100644 index 000000000..44cac27c8 --- /dev/null +++ b/src/pages/JoinPage/valuesType.ts @@ -0,0 +1,9 @@ +export type JoinFormValues = { + step: number; + email: string; + password: string; + name: string; + surname: string; + workspace: string; + roleId: number; +}; diff --git a/src/pages/LoginPage/index.tsx b/src/pages/LoginPage/index.tsx index b05589f8d..17e6224ab 100644 --- a/src/pages/LoginPage/index.tsx +++ b/src/pages/LoginPage/index.tsx @@ -21,6 +21,8 @@ const StyledLogo = styled(Logo)` const CenteredXYContainer = styled.div` display: flex; align-items: center; + justify-content: center; + text-align: center; flex-direction: column; height: 100vh; @@ -99,8 +101,6 @@ const LoginPage = () => { if (!values.password) { errors.password = t('__FORM_FIELD_REQUIRED_MESSAGE'); - } else if (values.password.length < 5) { - errors.password = t('__LOGIN_FORM_PASSWORD_FIELD_LENGTH_INVALID'); } return errors; diff --git a/tests/api/invites/profile/token/_get/200_Example_1.json b/tests/api/invites/profile/token/_get/200_Example_1.json new file mode 100644 index 000000000..adf5c4c70 --- /dev/null +++ b/tests/api/invites/profile/token/_get/200_Example_1.json @@ -0,0 +1,6 @@ +{ + "name": "John", + "surname": "Doe", + "email": "jhon.doe@example.com", + "workspace": "My new workspace" +} \ No newline at end of file diff --git a/tests/api/plans/pid/_get/200_pending_review.json b/tests/api/plans/pid/_get/200_pending_review.json new file mode 100644 index 000000000..a5c182490 --- /dev/null +++ b/tests/api/plans/pid/_get/200_pending_review.json @@ -0,0 +1,41 @@ +{ + "id": 13, + "workspace_id": 1, + "status": "pending_review", + "project": { + "id": 90, + "name": "MyProject" + }, + "config": { + "modules": [ + { + "type": "title", + "variant": "default", + "output": "My Plan" + }, + { + "type": "dates", + "variant": "default", + "output": { + "start": "2041-12-17T08:00:00.000Z" + } + }, + { + "type": "tasks", + "variant": "default", + "output": [ + { + "kind": "bug", + "title": "Search for bugs", + "description": "description kind bug" + }, + { + "kind": "video", + "title": "Think aloud", + "description": "description kind video" + } + ] + } + ] + } +} diff --git a/tests/api/users/_post/200_Example_1.json b/tests/api/users/_post/200_Example_1.json new file mode 100644 index 000000000..824b2d03c --- /dev/null +++ b/tests/api/users/_post/200_Example_1.json @@ -0,0 +1,3 @@ +{ + "workspaceId": 123 +} diff --git a/tests/api/users/_post/200_projectId.json b/tests/api/users/_post/200_projectId.json new file mode 100644 index 000000000..97b998b8e --- /dev/null +++ b/tests/api/users/_post/200_projectId.json @@ -0,0 +1,4 @@ +{ + "workspaceId": 1, + "projectId": 1 +} diff --git a/tests/api/users/roles/_get/200_Example_1.json b/tests/api/users/roles/_get/200_Example_1.json new file mode 100644 index 000000000..b8d0b4232 --- /dev/null +++ b/tests/api/users/roles/_get/200_Example_1.json @@ -0,0 +1,14 @@ +[ + { + "id": 1, + "name": "Developer" + }, + { + "id": 2, + "name": "Designer" + }, + { + "id": 3, + "name": "Project Manager" + } +] diff --git a/tests/e2e/join/index.spec.ts b/tests/e2e/join/index.spec.ts new file mode 100644 index 000000000..ba0629f12 --- /dev/null +++ b/tests/e2e/join/index.spec.ts @@ -0,0 +1,202 @@ +import { test, expect } from '../../fixtures/app'; +import { Join } from '../../fixtures/pages/Join'; +import { Step1 } from '../../fixtures/pages/Join/Step1'; +import { Step2 } from '../../fixtures/pages/Join/Step2'; +import { Step3 } from '../../fixtures/pages/Join/Step3'; + +test.describe('The Join page first step - case new user', () => { + let join: Join; + let step1: Step1; + let step2: Step2; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + step1 = new Step1(page); + step2 = new Step2(page); + await join.open(); + }); + + test('display a form with user email and password input, a CTA to go to the next step', async () => { + await expect(step1.elements().container()).toBeVisible(); + await expect(step1.elements().emailInput()).toBeVisible(); + await expect(step1.elements().passwordInput()).toBeVisible(); + await expect(step1.elements().buttonGoToStep2()).toBeVisible(); + }); + + test('the password input check if the password is strong enough', async ({ + page, + i18n, + }) => { + await step1.elements().buttonGoToStep2().click(); + await expect(step1.elements().passwordError()).toHaveText( + i18n.t('SIGNUP_FORM_PASSWORD_IS_A_REQUIRED_FIELD') + ); + + await expect(step1.elements().passwordRequirements()).toBeVisible(); + + await step1.fillPassword('weak'); + await expect( + page.getByText( + i18n.t('SIGNUP_FORM_PASSWORD_MUST_BE_AT_LEAST_6_CHARACTER_LONG') + ) + ).toBeVisible(); + + await step1.fillPassword('weakpassword'); + await expect( + page.getByText( + i18n.t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_NUMBER') + ) + ).toBeVisible(); + + await step1.fillPassword('weakpassword123'); + await expect( + page.getByText( + i18n.t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_AN_UPPERCASE_LETTER') + ) + ).toBeVisible(); + + await step1.fillPassword('WEAKPASSWORD123'); + await expect( + page.getByText( + i18n.t('SIGNUP_FORM_PASSWORD_MUST_CONTAIN_AT_LEAST_A_LOWERCASE_LETTER') + ) + ).toBeVisible(); + + await step1.fillValidPassword(); + await expect(page.getByTestId('message-error-password')).not.toBeVisible(); + }); + + test('the email input check if the email is valid', async ({ + page, + i18n, + }) => { + await step1.elements().buttonGoToStep2().click(); + await expect(step1.elements().emailError()).toHaveText( + i18n.t('SIGNUP_FORM_EMAIL_IS_REQUIRED') + ); + await step1.fillEmail('invalid-email'); + await expect( + page.getByText(i18n.t('SIGNUP_FORM_EMAIL_MUST_BE_A_VALID_EMAIL')) + ).toBeVisible(); + + await step1.fillRegisteredEmail(); + await expect( + page.getByText(i18n.t('SIGNUP_FORM_EMAIL_ALREADY_TAKEN')) + ).toBeVisible(); + + await step1.fillValidEmail(); + await expect(page.getByTestId('message-error-email')).not.toBeVisible(); + }); + + test('when the user click the next step cta we validate current inputs and if ok goes to the next step', async () => { + await step1.goToNextStep(); + await expect(step1.elements().container()).not.toBeVisible(); + await expect(step2.elements().container()).toBeVisible(); + }); + test('display two links to go to app.unguess and a link to terms and conditions', async () => {}); +}); + +test.describe('The Join page second step', () => { + let join: Join; + let step1: Step1; + let step2: Step2; + let step3: Step3; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + step1 = new Step1(page); + step2 = new Step2(page); + step3 = new Step3(page); + + await step2.mockGetRoles(); + await join.open(); + await step1.goToNextStep(); + }); + test('display required inputs for name, surname and a job role dropdown populated from api userRole', async ({ + i18n, + }) => { + await expect(step2.elements().nameInput()).toBeVisible(); + await expect(step2.elements().surnameInput()).toBeVisible(); + await expect(step2.elements().roleSelect()).toBeVisible(); + await step2.elements().roleSelect().click(); + await expect(step2.elements().roleSelectOptions()).toHaveCount(3); + await step2.elements().buttonGoToStep3().click(); + await expect(step2.elements().nameError()).toHaveText( + i18n.t('SIGNUP_FORM_NAME_IS_REQUIRED') + ); + await expect(step2.elements().surnameError()).toHaveText( + i18n.t('SIGNUP_FORM_SURNAME_IS_REQUIRED') + ); + await expect(step2.elements().roleSelectError()).toHaveText( + i18n.t('SIGNUP_FORM_ROLE_IS_REQUIRED') + ); + await step2.fillValidFields(); + await expect(step2.elements().nameError()).not.toBeVisible(); + await expect(step2.elements().surnameError()).not.toBeVisible(); + await expect(step2.elements().roleSelectError()).not.toBeVisible(); + }); + test('display back and next navigation, clicking on next validate this step and goes to step 3', async () => { + await expect(step2.elements().buttonBackToStep1()).toBeVisible(); + await expect(step2.elements().buttonGoToStep3()).toBeVisible(); + await step2.goToNextStep(); + await expect(step2.elements().container()).not.toBeVisible(); + await expect(step3.elements().container()).toBeVisible(); + }); +}); + +test.describe('The Join page third step', () => { + let join: Join; + let step1: Step1; + let step2: Step2; + let step3: Step3; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + step1 = new Step1(page); + step2 = new Step2(page); + step3 = new Step3(page); + + await join.open(); + await join.mockPostNewUser(); + await step1.goToNextStep(); + await step2.goToNextStep(); + }); + test('display a required text input for the workspace name and a back button to return to step 2', async () => { + await expect(step3.elements().workspaceInput()).toBeVisible(); + await expect(step3.elements().buttonBackToStep2()).toBeVisible(); + await step3.elements().buttonBackToStep2().click(); + await expect(step3.elements().container()).not.toBeVisible(); + await expect(step2.elements().container()).toBeVisible(); + }); + test('display a submit-button, clicking on submit-button validate the whole form and calls the api post', async ({ + page, + i18n, + }) => { + const postPromise = page.waitForResponse( + (response) => + /\/api\/users/.test(response.url()) && + response.status() === 200 && + response.request().method() === 'POST' + ); + await step3.elements().buttonSubmit().click(); + await expect(step3.elements().workspaceError()).toHaveText( + i18n.t('SIGNUP_FORM_WORKSPACE_IS_REQUIRED') + ); + await step3.fillValidWorkspace(); + await expect(step3.elements().workspaceError()).not.toBeVisible(); + await step3.elements().buttonSubmit().click(); + const response = await postPromise; + const data = response.request().postDataJSON(); + expect(data).toEqual( + expect.objectContaining({ + type: 'new', + email: 'new.user@example.com', + password: 'ValidPassword123', + name: step2.name, + surname: step2.surname, + roleId: step2.roleId, + workspace: step3.workspace, + }) + ); + }); +}); diff --git a/tests/e2e/join/invited-user.spec.ts b/tests/e2e/join/invited-user.spec.ts new file mode 100644 index 000000000..6f9876bf5 --- /dev/null +++ b/tests/e2e/join/invited-user.spec.ts @@ -0,0 +1,110 @@ +import { test, expect } from '../../fixtures/app'; +import { Join } from '../../fixtures/pages/Join'; +import { Step1 } from '../../fixtures/pages/Join/Step1'; +import { Step2 } from '../../fixtures/pages/Join/Step2'; +import { Step3 } from '../../fixtures/pages/Join/Step3'; + +test.describe('The Join page if the get invites respond 400', () => { + let join: Join; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + await join.mockGetInvitedUserError(); + await page.goto(join.urlInvitedUser); + }); + test('should render an error state', async () => { + await expect(join.elements().errorState()).toBeVisible(); + }); +}); + +test.describe('The Join page first step - case valid invited user only', () => { + let join: Join; + let step1: Step1; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + step1 = new Step1(page); + + await join.mockGetInvitedUser(); + await page.goto(join.urlInvitedUser); + }); + + test('before rendering page evaluate invited parameters from the url', async ({ + page, + }) => { + const getPromise = page.waitForResponse( + (response) => + response + .url() + .includes(`api/invites/${join.profileId}/${join.token}`) && + response.status() === 200 && + response.request().method() === 'GET' + ); + await page.goto(join.urlInvitedUser); + + const response = await getPromise; + expect(response).toBeDefined(); + }); + + test('the email input, is precompiled (with invited user email from api) and disabled', async () => { + await expect(step1.elements().emailInput()).toBeDisabled(); + await expect(step1.elements().emailInput()).toHaveValue( + join.validInvitedUser.email + ); + }); +}); + +test.describe('The Join page second step - case invited user only', () => { + let join: Join; + let step2: Step2; + let step1: Step1; + test.beforeEach(async ({ page }) => { + join = new Join(page); + step2 = new Step2(page); + step1 = new Step1(page); + + await join.mockGetInvitedUser(); + await step2.mockGetRoles(); + await page.goto(join.urlInvitedUser); + await step1.goToNextStepAsInvitedUser(); + }); + test('display two inputs for name and surname precopiled if present in api response', async () => { + await expect(step2.elements().nameInput()).toBeEnabled(); + await expect(step2.elements().nameInput()).toHaveValue( + join.validInvitedUser.name + ); + await expect(step2.elements().surnameInput()).toBeEnabled(); + await expect(step2.elements().surnameInput()).toHaveValue( + join.validInvitedUser.surname + ); + }); +}); + +test.describe('The Join page third step - case invited user only', () => { + let join: Join; + let step1: Step1; + let step2: Step2; + let step3: Step3; + test.beforeEach(async ({ page }) => { + join = new Join(page); + step2 = new Step2(page); + step1 = new Step1(page); + step3 = new Step3(page); + + await join.mockGetInvitedUser(); + await step2.mockGetRoles(); + await page.goto(join.urlInvitedUser); + await step1.goToNextStepAsInvitedUser(); + await step2.elements().roleSelect().click(); + await step2.elements().roleSelectOptions().first().click(); + await step2.elements().buttonGoToStep3().click(); + }); + + test('display the workspace name input precompiled from api and disabled', async () => { + await expect(step3.elements().workspaceInput()).not.toBeEnabled(); + await expect(step3.elements().workspaceInput()).toHaveValue( + join.validInvitedUser.workspace + ); + }); + test('the POST should NOT answer with a projectId therefore submitting the form redirect to the homepage', async () => {}); +}); diff --git a/tests/e2e/join/logged-in-user.spec.ts b/tests/e2e/join/logged-in-user.spec.ts new file mode 100644 index 000000000..0c91be9f1 --- /dev/null +++ b/tests/e2e/join/logged-in-user.spec.ts @@ -0,0 +1,28 @@ +import { test, expect } from '../../fixtures/app'; +import { Join } from '../../fixtures/pages/Join'; + +test.describe('The Join page - already logged in user:', () => { + let join: Join; + + test.beforeEach(async ({ page }) => { + join = new Join(page); + + await join.loggedIn(); + await join.mockPreferences(); + await join.mockWorkspace(); + await join.mockWorkspacesList(); + await join.mockExperientialCampaign(); + }); + test('If there is not a query parameter redirectTo the user is redirected to home', async ({ + page, + }) => { + await join.open(); + await expect(page).toHaveURL('/'); + }); + test('If there is a query parameter redirectTo, the user is redirected to a specific page', async ({ + page, + }) => { + await page.goto('/join?redirectTo=/campaigns/1'); + await expect(page).toHaveURL('/campaigns/1'); + }); +}); diff --git a/tests/fixtures/pages/Join/Step1.ts b/tests/fixtures/pages/Join/Step1.ts new file mode 100644 index 000000000..dec48ac2d --- /dev/null +++ b/tests/fixtures/pages/Join/Step1.ts @@ -0,0 +1,103 @@ +import { Page } from '@playwright/test'; +import { i18n } from 'i18next'; +import { getI18nInstance } from 'playwright-i18next-fixture'; + +export class Step1 { + readonly page: Page; + + readonly i18n: i18n; + + constructor(page: Page) { + this.page = page; + this.i18n = getI18nInstance() as unknown as i18n; + } + + elements() { + return { + container: () => this.page.getByTestId('step-1'), + emailInput: () => this.page.getByRole('textbox', { name: 'Email' }), + emailError: () => this.page.getByTestId('message-error-email'), + passwordInput: () => this.page.getByRole('textbox', { name: 'Password' }), + passwordError: () => this.page.getByTestId('message-error-password'), + buttonGoToStep2: () => + this.page.getByRole('button', { + name: this.i18n.t('SIGNUP_FORM_GO_TO_STEP_2'), + }), + passwordRequirements: () => + this.page.getByTestId('password-requirements'), + termsLink: () => this.page.getByTestId('terms-and-conditions'), + }; + } + + expectToBeVisible() { + const tab = this.elements().container(); + return tab.isVisible(); + } + + async goToNextStep() { + await this.fillValidEmail(); + await this.fillValidPassword(); + await this.elements().buttonGoToStep2().click(); + } + + async fillPassword(pass: string) { + const passwordInput = this.elements().passwordInput(); + await passwordInput.fill(pass); + await passwordInput.blur(); + } + + async goToNextStepAsInvitedUser() { + await this.fillValidPassword(); + await this.elements().buttonGoToStep2().click(); + } + + async fillValidPassword() { + const passwordInput = this.elements().passwordInput(); + await passwordInput.fill('ValidPassword123'); + await passwordInput.blur(); + } + + async fillEmail(email: string) { + const emailInput = this.elements().emailInput(); + await emailInput.fill(email); + await emailInput.blur(); + } + + async fillRegisteredEmail() { + await this.mockMailExist(); + const emailInput = this.elements().emailInput(); + await emailInput.fill('user.registerd@example.com'); + await emailInput.blur(); + } + + async fillValidEmail() { + await this.mockMailDoesNotExist(); + const emailInput = this.elements().emailInput(); + await emailInput.fill('new.user@example.com'); + await emailInput.blur(); + } + + async mockMailExist() { + await this.page.route( + `*/**/api/users/by-email/user.registerd@example.com`, + async (route) => { + await route.fulfill({ + body: '{}', + status: 200, + }); + } + ); + } + + async mockMailDoesNotExist() { + await this.page.route( + `*/**/api/users/by-email/new.user@example.com`, + async (route) => { + await route.fulfill({ + body: '{}', + status: 404, + }); + } + ); + } +} diff --git a/tests/fixtures/pages/Join/Step2.ts b/tests/fixtures/pages/Join/Step2.ts new file mode 100644 index 000000000..4cd71030b --- /dev/null +++ b/tests/fixtures/pages/Join/Step2.ts @@ -0,0 +1,65 @@ +import { Page } from '@playwright/test'; +import { i18n } from 'i18next'; +import { getI18nInstance } from 'playwright-i18next-fixture'; +import roles from '../../../api/users/roles/_get/200_Example_1.json'; + +export class Step2 { + readonly page: Page; + + readonly i18n: i18n; + + readonly name = 'John'; + + readonly surname = 'Doe'; + + readonly roleId = roles[0].id; + + constructor(page: Page) { + this.page = page; + this.i18n = getI18nInstance() as unknown as i18n; + } + + elements() { + return { + container: () => this.page.getByTestId('step-2'), + nameInput: () => + this.page.getByLabel(this.i18n.t('SIGNUP_FORM_NAME_LABEL')), + nameError: () => this.page.getByTestId('signup-name-error'), + surnameInput: () => + this.page.getByLabel(this.i18n.t('SIGNUP_FORM_SURNAME_LABEL')), + surnameError: () => this.page.getByTestId('signup-surname-error'), + roleSelect: () => this.page.getByTestId('roleId-select'), + roleSelectOptions: () => this.elements().roleSelect().getByRole('option'), + roleSelectError: () => this.page.getByTestId('signup-role-error'), + buttonBackToStep1: () => + this.page.getByRole('button', { + name: this.i18n.t('SIGNUP_FORM_RETURN_TO_STEP_1'), + }), + buttonGoToStep3: () => + this.page.getByRole('button', { + name: this.i18n.t('SIGNUP_FORM_GO_TO_STEP_3'), + }), + }; + } + + async fillValidFields() { + await this.elements().roleSelect().click(); + await this.elements().roleSelectOptions().first().click(); + await this.elements().surnameInput().fill(this.surname); + await this.elements().nameInput().fill(this.name); + await this.elements().nameInput().blur(); + } + + async goToNextStep() { + await this.fillValidFields(); + await this.elements().buttonGoToStep3().click(); + } + + async mockGetRoles() { + await this.page.route('*/**/api/users/roles', async (route) => { + await route.fulfill({ + path: 'tests/api/users/roles/_get/200_Example_1.json', + }); + }); + } +} diff --git a/tests/fixtures/pages/Join/Step3.ts b/tests/fixtures/pages/Join/Step3.ts new file mode 100644 index 000000000..8b11244be --- /dev/null +++ b/tests/fixtures/pages/Join/Step3.ts @@ -0,0 +1,38 @@ +import { Page } from '@playwright/test'; +import { i18n } from 'i18next'; +import { getI18nInstance } from 'playwright-i18next-fixture'; + +export class Step3 { + readonly page: Page; + + readonly i18n: i18n; + + readonly workspace = 'Test Workspace'; + + constructor(page: Page) { + this.page = page; + this.i18n = getI18nInstance() as unknown as i18n; + } + + elements() { + return { + container: () => this.page.getByTestId('step-3'), + workspaceInput: () => + this.page.getByRole('textbox', { name: 'workspace' }), + workspaceError: () => this.page.getByTestId('signup-workspace-error'), + buttonBackToStep2: () => + this.page.getByRole('button', { + name: this.i18n.t('SIGNUP_FORM_RETURN_TO_STEP_2'), + }), + buttonSubmit: () => + this.page.getByRole('button', { + name: this.i18n.t('SIGNUP_FORM_SUBMIT'), + }), + }; + } + + async fillValidWorkspace() { + await this.elements().workspaceInput().fill(this.workspace); + await this.elements().workspaceInput().blur(); + } +} diff --git a/tests/fixtures/pages/Join/index.ts b/tests/fixtures/pages/Join/index.ts new file mode 100644 index 000000000..4a06a2942 --- /dev/null +++ b/tests/fixtures/pages/Join/index.ts @@ -0,0 +1,86 @@ +import { type Page } from '@playwright/test'; +import { UnguessPage } from '../../UnguessPage'; +import validInvitedUser from '../../../api/invites/profile/token/_get/200_Example_1.json'; + +export class Join extends UnguessPage { + readonly page: Page; + + readonly url = '/join'; + + readonly profileId = '1'; + + readonly token = 'token123'; + + readonly urlInvitedUser = `${this.url}/invites/${this.profileId}/${this.token}`; + + readonly validInvitedUser = validInvitedUser; + + constructor(page: Page) { + super(page); + this.page = page; + } + + elements() { + return { + ...super.elements(), + loader: () => this.page.getByTestId('join-page-loader'), + errorState: () => this.page.getByTestId('join-page-error'), + }; + } + + async mockGetInvitedUser() { + await this.page.route( + `*/**/api/invites/${this.profileId}/${this.token}`, + async (route) => { + if (route.request().method() === 'GET') { + await route.fulfill({ + path: 'tests/api/invites/profile/token/_get/200_Example_1.json', + }); + } else { + await route.fallback(); + } + } + ); + } + + async mockGetInvitedUserError() { + await this.page.route( + `*/**/api/invites/${this.profileId}/${this.token}`, + async (route) => { + if (route.request().method() === 'GET') { + await route.fulfill({ + status: 400, + }); + } else { + await route.fallback(); + } + } + ); + } + + // new user response has a welcome project id for the redirect + async mockPostNewUser() { + await this.page.route(`*/**/api/users`, async (route) => { + if (route.request().method() === 'POST') { + await route.fulfill({ + path: 'tests/api/users/_post/200_projectId.json', + }); + } else { + await route.fallback(); + } + }); + } + + // existing user response has no project id + async mockPostExistingUser() { + await this.page.route(`*/**/api/users`, async (route) => { + if (route.request().method() === 'POST') { + await route.fulfill({ + path: 'tests/api/users/_post/200_Example_1.json', + }); + } else { + await route.fallback(); + } + }); + } +} diff --git a/yarn.lock b/yarn.lock index 8fb6399f6..98574dacb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4628,6 +4628,15 @@ formik@^2.2.9: tiny-warning "^1.0.2" tslib "^2.0.0" +framer-motion@^12.15.0: + version "12.15.0" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-12.15.0.tgz#6892283fc7967b071f537d6d160ab49e3d5e73ae" + integrity sha512-XKg/LnKExdLGugZrDILV7jZjI599785lDIJZLxMiiIFidCsy0a4R2ZEf+Izm67zyOuJgQYTHOmodi7igQsw3vg== + dependencies: + motion-dom "^12.15.0" + motion-utils "^12.12.1" + tslib "^2.4.0" + fs-extra@9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -6059,6 +6068,26 @@ modern-normalize@^2.0.0: resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-2.0.0.tgz#3d04ed01c81a3d4e0a0fd9ceba6abd1b16f5964b" integrity sha512-CxBoEVKh5U4DH3XuNbc5ONLF6dQBc8dSc7pdZ1957FGbIO5JBqGqqchhET9dTexri8/pk9xBL6+5ceOtCIp1QA== +motion-dom@^12.15.0: + version "12.15.0" + resolved "https://registry.yarnpkg.com/motion-dom/-/motion-dom-12.15.0.tgz#eca7c9d8c28976b8c920f175f92d5288f5a17785" + integrity sha512-D2ldJgor+2vdcrDtKJw48k3OddXiZN1dDLLWrS8kiHzQdYVruh0IoTwbJBslrnTXIPgFED7PBN2Zbwl7rNqnhA== + dependencies: + motion-utils "^12.12.1" + +motion-utils@^12.12.1: + version "12.12.1" + resolved "https://registry.yarnpkg.com/motion-utils/-/motion-utils-12.12.1.tgz#63e28751325cb9d1cd684f3c273a570022b0010e" + integrity sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w== + +motion@^12.15.0: + version "12.15.0" + resolved "https://registry.yarnpkg.com/motion/-/motion-12.15.0.tgz#dbfc09a0c3c60e9b40aa5f2f855a8822bb5d36de" + integrity sha512-HLouXyIb1uQFiZgJTYGrtEzbatPc6vK+HP+Qt6afLQjaudiGiLLVsoy71CwzD/Stlh06FUd5OpyiXqn6XvqjqQ== + dependencies: + framer-motion "^12.15.0" + tslib "^2.4.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8199,7 +8228,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==