diff --git a/src/app/features/settings/profile-settings/data.ts b/src/app/features/settings/profile-settings/data.ts new file mode 100644 index 000000000..88951c1c6 --- /dev/null +++ b/src/app/features/settings/profile-settings/data.ts @@ -0,0 +1,62 @@ +export const socials = [ + { + id: 0, + label: 'ResearcherID', + address: 'http://researchers.com/rid/', + placeholder: 'x-xxxx-xxxx', + }, + { + id: 1, + label: 'LinkedIn', + address: 'https://linkedin.com/', + placeholder: 'in/userID, profie/view?profileID, or pub/pubID', + }, + { + id: 2, + label: 'ORCID', + address: 'http://orcid.org/', + placeholder: 'xxxx-xxxx-xxxx', + }, + { + id: 3, + label: 'Twitter', + address: '@', + placeholder: 'twitterhandle', + }, + { + id: 4, + label: 'GitHub', + address: 'https://github.com/', + placeholder: 'username', + }, + { + id: 5, + label: 'ImpactStory', + address: 'https://impactstory.org/u/', + placeholder: 'profileID', + }, + { + id: 6, + label: 'Google Scholar', + address: 'http://scholar.google.com/citations?user=', + placeholder: 'profileID', + }, + { + id: 7, + label: 'ResearchGate', + address: 'https://researchgate.net/profile/', + placeholder: 'profileID', + }, + { + id: 8, + label: 'Baidu Scholar', + address: 'http://xueshu.baidu.com/scholarID/', + placeholder: 'profileID', + }, + { + id: 9, + label: 'SSRN', + address: 'http://papers.ssrn.com/sol3/cf_dev/AbsByAuth.cfm?per_id=', + placeholder: 'profileID', + }, +]; diff --git a/src/app/features/settings/profile-settings/entities/user-social-link.entity.ts b/src/app/features/settings/profile-settings/entities/user-social-link.entity.ts new file mode 100644 index 000000000..b0d065430 --- /dev/null +++ b/src/app/features/settings/profile-settings/entities/user-social-link.entity.ts @@ -0,0 +1,4 @@ +export interface UserSocialLink { + socialOutput: number; + webAddress: string; +} diff --git a/src/app/features/settings/profile-settings/profile-settings.component.html b/src/app/features/settings/profile-settings/profile-settings.component.html index faf75e1b6..d01fe042c 100644 --- a/src/app/features/settings/profile-settings/profile-settings.component.html +++ b/src/app/features/settings/profile-settings/profile-settings.component.html @@ -14,7 +14,8 @@ - + +

Your full name is the name that will be displayed in your profile. @@ -28,7 +29,7 @@

-
+
@@ -90,18 +91,90 @@

Doe, John T.

- + +
+ +
+
+
+ + + +
+ +
+ + + +
+
- +
- + employment + education diff --git a/src/app/features/settings/profile-settings/profile-settings.component.scss b/src/app/features/settings/profile-settings/profile-settings.component.scss index 1d9c6cc93..222634a5c 100644 --- a/src/app/features/settings/profile-settings/profile-settings.component.scss +++ b/src/app/features/settings/profile-settings/profile-settings.component.scss @@ -1,6 +1,10 @@ @use "assets/styles/variables" as var; +@use "assets/styles/mixins" as mix; :host { + @include mix.flex-column; + flex: 1; + .name-container { border: 1px solid var.$grey-2; border-radius: 8px; @@ -16,7 +20,6 @@ .name-input { width: 100%; - height: 2.77rem; border: 1px solid var.$grey-2; border-radius: 8px; } diff --git a/src/app/features/settings/profile-settings/profile-settings.component.ts b/src/app/features/settings/profile-settings/profile-settings.component.ts index 5c1cb2c01..6a52effa7 100644 --- a/src/app/features/settings/profile-settings/profile-settings.component.ts +++ b/src/app/features/settings/profile-settings/profile-settings.component.ts @@ -1,7 +1,24 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + OnInit, +} from '@angular/core'; import { SubHeaderComponent } from '@shared/components/sub-header/sub-header.component'; import { Tab, TabList, TabPanel, TabPanels, Tabs } from 'primeng/tabs'; import { Button } from 'primeng/button'; +import { DropdownModule } from 'primeng/dropdown'; +import { InputText } from 'primeng/inputtext'; +import { UserSocialLink } from '@osf/features/settings/profile-settings/entities/user-social-link.entity'; +import { + FormArray, + FormBuilder, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { InputGroup } from 'primeng/inputgroup'; +import { InputGroupAddon } from 'primeng/inputgroupaddon'; +import { socials } from '@osf/features/settings/profile-settings/data'; @Component({ selector: 'osf-profile-settings', @@ -13,11 +30,54 @@ import { Button } from 'primeng/button'; TabPanel, TabPanels, Button, + DropdownModule, + InputText, + ReactiveFormsModule, + InputGroup, + InputGroupAddon, ], templateUrl: './profile-settings.component.html', styleUrl: './profile-settings.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ProfileSettingsComponent { +export class ProfileSettingsComponent implements OnInit { defaultTabValue = 0; + #fb: FormBuilder = inject(FormBuilder); + socials = socials; + + userSocialLinks: UserSocialLink[] = []; + socialLinksForm = this.#fb.group({ + links: this.#fb.array([]), + }); + + ngOnInit(): void { + if (this.userSocialLinks.length) { + this.addLink(); + } + } + + get links(): FormArray { + return this.socialLinksForm.get('links') as FormArray; + } + + addLink(): void { + const linkGroup = this.#fb.group({ + socialOutput: [this.socials[0], Validators.required], + webAddress: ['', Validators.required], + }); + + this.links.push(linkGroup); + } + + removeLink(index: number): void { + this.links.removeAt(index); + } + + getDomain(index: number): string { + return this.links.at(index).get('socialOutput')?.value.address; + } + + getPlaceholder(index: number): string { + return this.links.at(index).get('socialOutput')?.value.placeholder; + } } diff --git a/src/app/shared/components/search-input/search-input.component.ts b/src/app/shared/components/search-input/search-input.component.ts index 78d5a7c5a..ba50cde32 100644 --- a/src/app/shared/components/search-input/search-input.component.ts +++ b/src/app/shared/components/search-input/search-input.component.ts @@ -16,8 +16,8 @@ import { FormsModule } from '@angular/forms'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SearchInputComponent { - protected readonly placeholder = input(''); - protected readonly searchValue = model.required(); + placeholder = input(''); + searchValue = model.required(); onSearchChange(value: string): void { this.searchValue.set(value); diff --git a/src/assets/styles/overrides/button.scss b/src/assets/styles/overrides/button.scss index 29f265659..d48874bcf 100644 --- a/src/assets/styles/overrides/button.scss +++ b/src/assets/styles/overrides/button.scss @@ -191,8 +191,21 @@ } } +.high-m-button { + button { + height: 3.125rem; + } +} + .learn-more { button { padding: 0.71rem 1.39rem; } } + +.remove-button { + .p-button { + background: var.$white; + color: var.$red-1; + } +} diff --git a/src/assets/styles/overrides/input-group-addon.scss b/src/assets/styles/overrides/input-group-addon.scss new file mode 100644 index 000000000..fce6d09ce --- /dev/null +++ b/src/assets/styles/overrides/input-group-addon.scss @@ -0,0 +1,12 @@ +@use "../variables" as var; + +.p-inputgroupaddon { + padding: 0 0 0 12px; + color: var.$dark-blue-1; + border: 1px solid var.$grey-2; + border-right-style: none; + border-bottom-right-radius: 0; + border-top-right-radius: 0; + font-size: 16px; + min-width: auto; +} diff --git a/src/assets/styles/overrides/input.scss b/src/assets/styles/overrides/input.scss index 670571845..e9f6e0cc1 100644 --- a/src/assets/styles/overrides/input.scss +++ b/src/assets/styles/overrides/input.scss @@ -56,3 +56,19 @@ p-password.ng-touched.ng-invalid { padding-left: 2.86rem; } } + +.addon-input { + .p-inputtext { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-left-style: none; + } + + .p-inputtext.ng-touched.ng-invalid, + .p-inputtext.ng-dirty.ng-invalid { + border-color: var.$grey-2; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-left-style: none; + } +} diff --git a/src/assets/styles/styles.scss b/src/assets/styles/styles.scss index 10e18939d..8a09902d7 100644 --- a/src/assets/styles/styles.scss +++ b/src/assets/styles/styles.scss @@ -17,8 +17,10 @@ @use "./overrides/radio"; @use "./overrides/dropdown"; @use "./overrides/confirmation-dialog"; +@use "./overrides/input-group-addon"; @use "./overrides/iconfield"; + @layer base, primeng, reset; @layer base {