From 8cda4923e51ebe7cbb98bab31b7434bb0fb91218 Mon Sep 17 00:00:00 2001 From: crisnicandrei <62384997+crisnicandrei@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:00:52 +0300 Subject: [PATCH 1/3] Separate the archive creation Pr This PR is a follow-up to the PR #1. It separates the archive creation feature into a separate PR. --- .../components/button/button.component.html | 6 +- .../components/button/button.component.scss | 57 ++++++- .../button/button.component.spec.ts | 6 +- .../components/button/button.component.ts | 9 +- .../components/button/button.stories.ts | 2 +- .../form-input/form-input.component.html | 9 +- .../form-input/form-input.component.scss | 14 +- .../form-input/form-input.component.spec.ts | 6 +- .../form-input/form-input.component.ts | 10 +- .../form-input/form-input.stories.ts | 2 +- ...chive-creation-start-screen.component.html | 38 +++++ ...chive-creation-start-screen.component.scss | 60 +++++++ ...ve-creation-start-screen.component.spec.ts | 67 ++++++++ ...archive-creation-start-screen.component.ts | 25 +++ .../create-new-archive.component.html | 152 +++++++++++------- .../create-new-archive.component.scss | 19 +++ .../create-new-archive.component.spec.ts | 63 ++------ .../create-new-archive.component.ts | 96 ++++++++--- .../components/glam/types/archive-types.ts | 70 ++++++++ .../name-archive-screen.component.html | 47 ++++++ .../name-archive-screen.component.scss | 87 ++++++++++ .../name-archive-screen.component.spec.ts | 102 ++++++++++++ .../name-archive-screen.component.ts | 40 +++++ .../onboarding/onboarding.component.scss | 42 +++-- .../onboarding/onboarding.component.ts | 24 ++- .../select-archive-type-screen.component.html | 26 +++ .../select-archive-type-screen.component.scss | 60 +++++++ ...lect-archive-type-screen.component.spec.ts | 75 +++++++++ .../select-archive-type-screen.component.ts | 45 ++++++ src/app/onboarding/onboarding.module.ts | 12 ++ src/app/onboarding/utils/utils.ts | 6 + src/assets/svg/onboarding/arrow-right.svg | 3 + src/assets/svg/onboarding/back.svg | 3 + src/assets/svg/onboarding/plus.svg | 3 + src/styles/_mixins.scss | 21 +++ src/styles/_variables.scss | 2 + 36 files changed, 1124 insertions(+), 185 deletions(-) create mode 100644 src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.html create mode 100644 src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.scss create mode 100644 src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.spec.ts create mode 100644 src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.ts create mode 100644 src/app/onboarding/components/name-archive-screen/name-archive-screen.component.html create mode 100644 src/app/onboarding/components/name-archive-screen/name-archive-screen.component.scss create mode 100644 src/app/onboarding/components/name-archive-screen/name-archive-screen.component.spec.ts create mode 100644 src/app/onboarding/components/name-archive-screen/name-archive-screen.component.ts create mode 100644 src/app/onboarding/components/select-archive-type-screen/select-archive-type-screen.component.html create mode 100644 src/app/onboarding/components/select-archive-type-screen/select-archive-type-screen.component.scss create mode 100644 src/app/onboarding/components/select-archive-type-screen/select-archive-type-screen.component.spec.ts create mode 100644 src/app/onboarding/components/select-archive-type-screen/select-archive-type-screen.component.ts create mode 100644 src/app/onboarding/utils/utils.ts create mode 100644 src/assets/svg/onboarding/arrow-right.svg create mode 100644 src/assets/svg/onboarding/back.svg create mode 100644 src/assets/svg/onboarding/plus.svg create mode 100644 src/styles/_mixins.scss diff --git a/src/app/component-library/components/button/button.component.html b/src/app/component-library/components/button/button.component.html index f076e6388..8dc721da5 100644 --- a/src/app/component-library/components/button/button.component.html +++ b/src/app/component-library/components/button/button.component.html @@ -1,12 +1,14 @@ + diff --git a/src/app/component-library/components/button/button.component.scss b/src/app/component-library/components/button/button.component.scss index b8c7ea124..738f6035f 100644 --- a/src/app/component-library/components/button/button.component.scss +++ b/src/app/component-library/components/button/button.component.scss @@ -1,24 +1,33 @@ + /* @format */ @import 'variables'; -@mixin darkButton { - background-color: rgba(19, 27, 74, 1); - border: 1px solid rgba(19, 27, 74, 1); +@mixin darkButton($isLink: false) { + background-color: rgba(255, 255, 255, 0); + border: 1px solid rgba(255, 255, 255, 0.32); & > .button-text { color: white; margin: 0; @include bodyMedium; + + @if $isLink { + font-size: 14px; + } } } -@mixin lightButton { +@mixin lightButton($isLink: false) { background-color: $white; border: 1px solid rgba(184, 187, 201, 1); & > .button-text { color: rgba(19, 27, 74, 1); margin: 0; @include bodyMedium; + + @if $isLink { + font-size: 14px; + } } & > .icon { @@ -27,6 +36,11 @@ } .button { + &:disabled { + cursor: not-allowed; + opacity: 0.5; + } + &:focus { outline: none; } @@ -53,8 +67,10 @@ &-primary { &.button-light { - //the button on a white background will be blue @include darkButton(); + &:focus { + border: 2px solid white; + } } &.button-dark { @include lightButton(); @@ -64,6 +80,9 @@ &-secondary { &.button-light { @include lightButton(); + &:focus { + border: 2px solid black; + } } &.button-dark { @include darkButton(); @@ -88,8 +107,12 @@ &-fill { width: 100%; - padding: 0px 24px; + padding: 12px 24px; height: 56px; + justify-content: space-between; + &-no-icon { + justify-content: center; + } } &-fill.button-large { @@ -101,4 +124,26 @@ margin: 0; @include bodyMedium; } + + &-link { + margin-left: 4px; + padding: 0px; + &.button-dark { + @include darkButton(true); + font-size: 14px; + border: 1px solid transparent; + } + &.button-light { + @include lightButton(true); + font-size: 14px; + border: 1px solid transparent; + } + + &:focus { + outline: none; + background-color: #e0e0e0; + box-shadow: 0 0 0 3px rgba(21, 156, 228, 0.4); + border-color: #159ce4; + } + } } diff --git a/src/app/component-library/components/button/button.component.spec.ts b/src/app/component-library/components/button/button.component.spec.ts index 5a6566fc4..4ff6d5eae 100644 --- a/src/app/component-library/components/button/button.component.spec.ts +++ b/src/app/component-library/components/button/button.component.spec.ts @@ -105,14 +105,14 @@ describe('ButtonComponent', () => { expect(button.nativeElement.type).toEqual('button'); - instance.attr = 'submit'; + instance.buttonType = 'submit'; fixture.detectChanges(); expect(button.nativeElement.type).toEqual('submit'); - instance.attr = 'reset'; + instance.buttonType = 'reset'; fixture.detectChanges(); expect(button.nativeElement.type).toEqual('reset'); }); -}); +}); \ No newline at end of file diff --git a/src/app/component-library/components/button/button.component.ts b/src/app/component-library/components/button/button.component.ts index 4cbf7ce9c..f932be230 100644 --- a/src/app/component-library/components/button/button.component.ts +++ b/src/app/component-library/components/button/button.component.ts @@ -1,12 +1,12 @@ /* @format */ import { Component, EventEmitter, Input, Output } from '@angular/core'; -type VARIANT = 'primary' | 'secondary' | 'tertiary'; +type VARIANT = 'primary' | 'secondary' | 'tertiary' | 'link'; type MODE = 'light' | 'dark'; type SIZE = 'hug' | 'fill'; type ORIENTATION = 'left' | 'right'; type HEIGHT = 'medium' | 'large'; -type ATTR = 'submit' | 'reset' | 'button'; +type TYPE = 'submit' | 'reset' | 'button'; @Component({ selector: 'pr-button', @@ -15,7 +15,6 @@ type ATTR = 'submit' | 'reset' | 'button'; }) export class ButtonComponent { //Inputs - @Input() text: string = ''; @Input() variant: VARIANT = 'primary'; @Input() height: HEIGHT = 'medium'; @Input() mode: MODE = 'light'; @@ -24,7 +23,7 @@ export class ButtonComponent { @Input() icon: string = ''; @Input() orientation: ORIENTATION = 'left'; @Input() faIcon: string = ''; - @Input() attr: ATTR = 'button'; + @Input() buttonType: TYPE = 'button'; //Outputs @Output() buttonClick = new EventEmitter(); @@ -32,4 +31,4 @@ export class ButtonComponent { onClick($event) { this.buttonClick.emit($event); } -} +} \ No newline at end of file diff --git a/src/app/component-library/components/button/button.stories.ts b/src/app/component-library/components/button/button.stories.ts index 46c7e7fe6..ba055fe90 100644 --- a/src/app/component-library/components/button/button.stories.ts +++ b/src/app/component-library/components/button/button.stories.ts @@ -106,4 +106,4 @@ export const DarkModeSecondary: ButtonStory = { export const TertiaryButton: ButtonStory = { args: { variant: 'tertiary', text: 'Tertiary' }, -}; +}; \ No newline at end of file diff --git a/src/app/component-library/components/form-input/form-input.component.html b/src/app/component-library/components/form-input/form-input.component.html index 26c5789a8..1a20e62b1 100644 --- a/src/app/component-library/components/form-input/form-input.component.html +++ b/src/app/component-library/components/form-input/form-input.component.html @@ -1,7 +1,7 @@
@@ -14,16 +14,19 @@ >
{{ errors }} -
+
\ No newline at end of file diff --git a/src/app/component-library/components/form-input/form-input.component.scss b/src/app/component-library/components/form-input/form-input.component.scss index 4c47eea5e..230cbc069 100644 --- a/src/app/component-library/components/form-input/form-input.component.scss +++ b/src/app/component-library/components/form-input/form-input.component.scss @@ -13,9 +13,13 @@ line-height: 24px; font-weight: 600; border: 1px solid $form-border; - padding: 12px; + padding: 14px 24px 14px 24px; height: 48px; + &-with-text { + padding: 28px 24px 14px 24px; + } + &-light.form-input-errors { background-color: $form-background-error; border: 1px solid $form-border-error; @@ -41,7 +45,7 @@ } &-dark { - background-color: $form-background-dark; + background: rgba(255, 255, 255, 0.08); opacity: 0.8; color: white; border: 1px solid transparent; @@ -62,8 +66,8 @@ font-size: 10px; font-weight: 400; text-transform: uppercase; - left: 12px; - top: 4px; + left: 24px; + top: 7px; &-dark { color: $form-label-dark; } @@ -90,4 +94,4 @@ right: 20px; top: 12px; color: $form-error-red; -} +} \ No newline at end of file diff --git a/src/app/component-library/components/form-input/form-input.component.spec.ts b/src/app/component-library/components/form-input/form-input.component.spec.ts index 5ac5468b2..204c6bc93 100644 --- a/src/app/component-library/components/form-input/form-input.component.spec.ts +++ b/src/app/component-library/components/form-input/form-input.component.spec.ts @@ -11,7 +11,7 @@ describe('FormInputComponent', () => { beforeEach(async () => { shallow = new Shallow(FormInputComponent, ComponentsModule).import( - ReactiveFormsModule, + ReactiveFormsModule ); }); @@ -92,7 +92,7 @@ describe('FormInputComponent', () => { expect(inputElement.getAttribute('autocorrect')).toBe(config.autocorrect); expect(inputElement.getAttribute('autocapitalize')).toBe( - config.autocapitalize, + config.autocapitalize ); expect(inputElement.getAttribute('spellcheck')).toBe(config.spellcheck); @@ -159,4 +159,4 @@ describe('FormInputComponent', () => { expect(errorMessage).toBe('Must be at least 3 characters'); }); -}); +}); \ No newline at end of file diff --git a/src/app/component-library/components/form-input/form-input.component.ts b/src/app/component-library/components/form-input/form-input.component.ts index 99ee179f2..14a422bf6 100644 --- a/src/app/component-library/components/form-input/form-input.component.ts +++ b/src/app/component-library/components/form-input/form-input.component.ts @@ -32,7 +32,7 @@ export interface FormInputConfig { } @Component({ - selector: 'pr-form-input-comp', + selector: 'pr-form-input-glam', templateUrl: './form-input.component.html', styleUrls: ['./form-input.component.scss'], }) @@ -48,6 +48,8 @@ export class FormInputComponent implements OnInit, AfterViewInit { message: string; value?: number | string; }[] = []; + @Input() styling = {}; + @Input() hideLabel: boolean = false; @HostBinding('class.right-align') rightAlign = false; @HostBinding('class.input-vertical') inputVertical = true; @@ -157,7 +159,7 @@ export class FormInputComponent implements OnInit, AfterViewInit { inputField.setAttribute('spellcheck', this.config.spellcheck); } - if ((this.config.autoselect && this.control.value) || this.value) { + if (this.config.autoselect && (this.control.value || this.value)) { inputField.addEventListener('focus', (event) => { inputField.setSelectionRange(0, inputField.value.length); }); @@ -184,7 +186,7 @@ export class FormInputComponent implements OnInit, AfterViewInit { } else { control = new FormControl( value, - Validators[validator.validation](validator.value), + Validators[validator.validation](validator.value) ); } if (control.invalid) { @@ -194,4 +196,4 @@ export class FormInputComponent implements OnInit, AfterViewInit { return errorMessages.pop(); } -} +} \ No newline at end of file diff --git a/src/app/component-library/components/form-input/form-input.stories.ts b/src/app/component-library/components/form-input/form-input.stories.ts index 2addbeb2b..2d16d4ad3 100644 --- a/src/app/component-library/components/form-input/form-input.stories.ts +++ b/src/app/component-library/components/form-input/form-input.stories.ts @@ -85,4 +85,4 @@ export const LightDarkBackground: FormInputStory = { export const Dark = { args: { type: 'text', placeholder: 'Text', variant: 'dark' }, -}; +}; \ No newline at end of file diff --git a/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.html b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.html new file mode 100644 index 000000000..8e6598074 --- /dev/null +++ b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.html @@ -0,0 +1,38 @@ + +
+

+ Hello, {{ name }}. +

+

Welcome to Permanent!

+
+
+
+

We’re so glad you’re here!

+

+ At Permanent, it is our mission to provide a safe and secure place to + store, preserve, and share the digital legacy of all people, whether + that's for you or for your friends, family, interests or organizations. +

+

+ We know that starting this journey can sometimes be overwhelming, but + don’t worry. We’re here to help you every step of the way. +

+
+
+ Create archive for me + Get started +
+
\ No newline at end of file diff --git a/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.scss b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.scss new file mode 100644 index 000000000..6b491aaae --- /dev/null +++ b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.scss @@ -0,0 +1,60 @@ +/* @format */ +@import 'fonts'; + +:host { + display: flex; + flex-direction: row; + justify-content: space-evenly; + gap: 64px; + margin-top: 64px; + + @media screen and (max-width: 600px) { + flex-direction: column; + } + + @media screen and (min-width: 602px) and (max-width: 900px) { + height: 100vh; + } + + @media screen and (max-width: 364px) { + height: 106vh; + } +} + +p { + color: white; +} + +.greetings-container { + width: 50%; + + @media screen and (max-width: 600px) { + width: 100%; + } + & > p { + font-size: 50px; + font-family: 'UsualRegular', sans-serif; + } +} + +.text-buttons-container { + flex-direction: column; + justify-content: space-between; + width: 50%; + display: flex; + height: 75vh; + + @media screen and (max-width: 600px) { + height: 60vh; + } + + & > .text > p { + font-size: 16px; + font-family: 'UsualLight', sans-serif; + } + + & > .buttons { + display: flex; + gap: 32px; + } +} \ No newline at end of file diff --git a/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.spec.ts b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.spec.ts new file mode 100644 index 000000000..edaeb18f4 --- /dev/null +++ b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.spec.ts @@ -0,0 +1,67 @@ +/* @format */ +import { Shallow } from 'shallow-render'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { AccountService } from '@shared/services/account/account.service'; +import { By } from '@angular/platform-browser'; +import { OnboardingModule } from '../../onboarding.module'; +import { ArchiveCreationStartScreenComponent } from './archive-creation-start-screen.component'; + +const mockAccountService = { + getAccount: () => ({ fullName: 'John Doe' }), +}; + +describe('ArchiveCreationStartScreenComponent', () => { + let shallow: Shallow; + + beforeEach(() => { + shallow = new Shallow(ArchiveCreationStartScreenComponent, OnboardingModule) + .mock(AccountService, mockAccountService) + .import(HttpClientTestingModule); + }); + + it('should create', async () => { + const { instance } = await shallow.render(); + + expect(instance).toBeTruthy(); + }); + + it('should initialize with the account name', async () => { + const { instance } = await shallow.render(); + + expect(instance.name).toBe('John Doe'); + }); + + it('should render the account name in the greeting', async () => { + const { fixture } = await shallow.render(); + const greetingElement = fixture.debugElement.query( + By.css('.greetings-container b') + ).nativeElement; + + expect(greetingElement.textContent).toContain('John Doe'); + }); + + it('should emit getStartedOutput event when Get Started button is clicked', async () => { + const { fixture, instance, outputs } = await shallow.render(); + spyOn(instance, 'getStarted').and.callThrough(); + + const getStartedButton = fixture.debugElement.query(By.css('.get-started')); + + getStartedButton.triggerEventHandler('buttonClick', null); + + expect(instance.getStarted).toHaveBeenCalled(); + expect(outputs.getStartedOutput.emit).toHaveBeenCalled(); + }); + + it('should emit createArchiveForMeOutput event when Create Archive for Me button is clicked', async () => { + const { fixture, instance, outputs } = await shallow.render(); + spyOn(instance, 'createArchiveForMe').and.callThrough(); + + const createArchiveButton = fixture.debugElement.query( + By.css('.create-archive-for-me') + ); + createArchiveButton.triggerEventHandler('buttonClick', null); + + expect(instance.createArchiveForMe).toHaveBeenCalled(); + expect(outputs.createArchiveForMeOutput.emit).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.ts b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.ts new file mode 100644 index 000000000..f69553922 --- /dev/null +++ b/src/app/onboarding/components/archive-creation-start-screen/archive-creation-start-screen.component.ts @@ -0,0 +1,25 @@ +import { Component, Output, EventEmitter } from '@angular/core'; +import { AccountService } from '@shared/services/account/account.service'; + +@Component({ + selector: 'pr-archive-creation-start-screen', + templateUrl: './archive-creation-start-screen.component.html', + styleUrl: './archive-creation-start-screen.component.scss', +}) +export class ArchiveCreationStartScreenComponent { + @Output() public getStartedOutput = new EventEmitter(); + @Output() public createArchiveForMeOutput = new EventEmitter(); + public name: string = ''; + + constructor(private account:AccountService){ + this.name = this.account.getAccount().fullName; + } + + public getStarted() { + this.getStartedOutput.emit(); + } + + public createArchiveForMe(): void { + this.createArchiveForMeOutput.emit(); + } +} \ No newline at end of file diff --git a/src/app/onboarding/components/create-new-archive/create-new-archive.component.html b/src/app/onboarding/components/create-new-archive/create-new-archive.component.html index ecd0d5720..230430dd5 100644 --- a/src/app/onboarding/components/create-new-archive/create-new-archive.component.html +++ b/src/app/onboarding/components/create-new-archive/create-new-archive.component.html @@ -1,8 +1,13 @@