diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 93a3d729b..a238b3e87 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -2,8 +2,12 @@ import { provideStates } from '@ngxs/store'; import { Routes } from '@angular/router'; -import { ResourceFiltersOptionsState } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.state'; -import { ResourceFiltersState } from '@shared/components/resources/resource-filters/store/resource-filters.state'; +import { MyProfileResourceFiltersOptionsState } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.state'; +import { MyProfileResourceFiltersState } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.state'; +import { MyProfileState } from '@osf/features/my-profile/store'; +import { ResourceFiltersOptionsState } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.state'; +import { ResourceFiltersState } from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.state'; +import { SearchState } from '@osf/features/search/store'; export const routes: Routes = [ { @@ -155,12 +159,14 @@ export const routes: Routes = [ { path: 'search', loadComponent: () => import('./features/search/search.component').then((mod) => mod.SearchComponent), - providers: [provideStates([ResourceFiltersState, ResourceFiltersOptionsState])], + providers: [provideStates([ResourceFiltersState, ResourceFiltersOptionsState, SearchState])], }, { path: 'my-profile', loadComponent: () => import('./features/my-profile/my-profile.component').then((mod) => mod.MyProfileComponent), - providers: [provideStates([ResourceFiltersState, ResourceFiltersOptionsState])], + providers: [ + provideStates([MyProfileResourceFiltersState, MyProfileResourceFiltersOptionsState, MyProfileState]), + ], }, { path: 'confirm/:userId/:emailId', diff --git a/src/app/core/constants/nav-items.constant.ts b/src/app/core/constants/nav-items.constant.ts index b7858502d..d0a748cbd 100644 --- a/src/app/core/constants/nav-items.constant.ts +++ b/src/app/core/constants/nav-items.constant.ts @@ -28,6 +28,12 @@ export const NAV_ITEMS: NavItem[] = [ icon: 'my-projects', useExactMatch: true, }, + { + path: '/my-profile', + label: 'navigation.profile', + icon: 'profile', + useExactMatch: true, + }, { path: '/meetings', label: 'navigation.meetings', diff --git a/src/app/core/constants/ngxs-states.constant.ts b/src/app/core/constants/ngxs-states.constant.ts index 4fb90850f..7cc1b0bf2 100644 --- a/src/app/core/constants/ngxs-states.constant.ts +++ b/src/app/core/constants/ngxs-states.constant.ts @@ -3,7 +3,6 @@ import { UserState } from '@core/store/user'; import { InstitutionsState } from '@osf/features/institutions/store'; import { MyProjectsState } from '@osf/features/my-projects/store'; import { AnalyticsState } from '@osf/features/project/analytics/store'; -import { SearchState } from '@osf/features/search/store'; import { AccountSettingsState } from '@osf/features/settings/account-settings/store/account-settings.state'; import { AddonsState } from '@osf/features/settings/addons/store'; import { DeveloperAppsState } from '@osf/features/settings/developer-apps/store'; @@ -15,7 +14,6 @@ export const STATES = [ TokensState, AddonsState, UserState, - SearchState, MyProjectsState, InstitutionsState, ProfileSettingsState, diff --git a/src/app/core/services/user/user.entity.ts b/src/app/core/services/user/user.entity.ts index e90d83eb5..701e1a52f 100644 --- a/src/app/core/services/user/user.entity.ts +++ b/src/app/core/services/user/user.entity.ts @@ -16,15 +16,6 @@ export interface User { dateRegistered: Date; link?: string; iri?: string; - socials?: { - orcid?: string; - github?: string; - scholar?: string; - twitter?: string; - linkedIn?: string; - impactStory?: string; - researcherId?: string; - }; defaultRegionId: string; allowIndexing: boolean | undefined; } diff --git a/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.html b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.html new file mode 100644 index 000000000..4d18ad32b --- /dev/null +++ b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.html @@ -0,0 +1,94 @@ +
+ better-research + +
+ +
+ + @if (!isMobile()) { + + All + Projects + Registrations + Preprints + Files + + } + + + + + + + + + + +
+ + + @if (currentStep === 1) { +
+

Improved OSF Search

+

+ Enter any term in the search box and filter by specific object types. More information is available on our + help guides. +

+
+

1 of 3

+
+ + Next +
+
+
+ } + + @if (currentStep === 2) { +
+

Refine Your Search

+

+ Narrow the source, discipline, and more. For example, find content supported by a specific funder or view only + datasets. +

+
+

2 of 3

+
+ + Next +
+
+
+ } + + @if (currentStep === 3) { +
+

Add Metadata

+

+ Remember to add metadata and resources to your own work on OSF to make it more discoverable! Learn more in our + help guides. +

+
+

3 of 3

+
+ Done +
+
+
+ } +
+
diff --git a/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.scss b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.scss new file mode 100644 index 000000000..ddd15a54e --- /dev/null +++ b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.scss @@ -0,0 +1,71 @@ +@use "assets/styles/variables" as var; + +:host { + .search-container { + margin: 3.4rem 1.7rem 0.4rem 1.7rem; + position: relative; + + img { + position: absolute; + right: 0.3rem; + top: 0.3rem; + z-index: 1; + } + } + + .resources { + position: relative; + background: white; + padding: 2rem; + } + + .stepper { + position: absolute; + padding: 1.7rem; + width: 32rem; + display: flex; + flex-direction: column; + row-gap: 1.7rem; + background: white; + border: 1px solid var.$grey-2; + border-radius: 12px; + h3 { + font-size: 1.3rem; + } + } + + .first-stepper { + top: 2rem; + left: 1.7rem; + } + + .second-stepper { + top: calc(2rem + 42px); + left: calc(1.5rem + 30%); + } + + .third-stepper { + top: calc(5rem + 42px); + left: calc(0.4rem + 30%); + } + + @media (max-width: 1000px) { + .search-container { + margin: 3.4rem 2.5rem 0.4rem 2.5rem; + } + + .resources { + padding: 2.5rem; + } + } + + @media (max-width: 600px) { + .search-container { + margin: 2.5rem 1.1rem 2.5rem 1.1rem; + } + + .resources { + padding: 1.1rem; + } + } +} diff --git a/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.spec.ts b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.spec.ts new file mode 100644 index 000000000..31aa477e4 --- /dev/null +++ b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileSearchComponent } from './my-profile-search.component'; + +describe('MyProfileSearchComponent', () => { + let component: MyProfileSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileSearchComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.ts b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.ts new file mode 100644 index 000000000..a4a488995 --- /dev/null +++ b/src/app/features/my-profile/components/my-profile-search/my-profile-search.component.ts @@ -0,0 +1,123 @@ +import { Store } from '@ngxs/store'; + +import { Button } from 'primeng/button'; +import { Tab, TabList, TabPanel, TabPanels, Tabs } from 'primeng/tabs'; + +import { debounceTime, skip } from 'rxjs'; + +import { NgOptimizedImage } from '@angular/common'; +import { ChangeDetectionStrategy, Component, effect, inject, signal, untracked } from '@angular/core'; +import { toObservable, toSignal } from '@angular/core/rxjs-interop'; + +import { UserSelectors } from '@core/store/user/user.selectors'; +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { MyProfileResourcesComponent } from '@osf/features/my-profile/components/resources/my-profile-resources.component'; +import { GetResources, SetResourceTab, SetSearchText } from '@osf/features/my-profile/store/my-profile.actions'; +import { MyProfileSelectors } from '@osf/features/my-profile/store/my-profile.selectors'; +import { SearchInputComponent } from '@shared/components/search-input/search-input.component'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; + +@Component({ + selector: 'osf-my-profile-search', + imports: [ + Button, + NgOptimizedImage, + SearchInputComponent, + Tab, + TabList, + TabPanel, + TabPanels, + Tabs, + MyProfileResourcesComponent, + ], + templateUrl: './my-profile-search.component.html', + styleUrl: './my-profile-search.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileSearchComponent { + readonly #store = inject(Store); + + protected searchValue = signal(''); + protected readonly isMobile = toSignal(inject(IS_XSMALL)); + + protected readonly dateCreatedFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getDateCreated); + protected readonly funderFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getFunder); + protected readonly subjectFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getSubject); + protected readonly licenseFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getLicense); + protected readonly resourceTypeFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getResourceType); + protected readonly institutionFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getInstitution); + protected readonly providerFilter = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getProvider); + protected readonly partOfCollectionFilter = this.#store.selectSignal( + MyProfileResourceFiltersSelectors.getPartOfCollection + ); + protected searchStoreValue = this.#store.selectSignal(MyProfileSelectors.getSearchText); + protected resourcesTabStoreValue = this.#store.selectSignal(MyProfileSelectors.getResourceTab); + protected sortByStoreValue = this.#store.selectSignal(MyProfileSelectors.getSortBy); + readonly isMyProfilePage = this.#store.selectSignal(MyProfileSelectors.getIsMyProfile); + readonly currentUser = this.#store.select(UserSelectors.getCurrentUser); + + protected selectedTab: ResourceTab = ResourceTab.All; + protected readonly ResourceTab = ResourceTab; + protected currentStep = 0; + private skipInitializationEffects = 0; + + constructor() { + this.currentUser.subscribe((user) => { + if (user?.id) { + this.#store.dispatch(GetAllOptions); + this.#store.dispatch(GetResources); + } + }); + + effect(() => { + this.dateCreatedFilter(); + this.funderFilter(); + this.subjectFilter(); + this.licenseFilter(); + this.resourceTypeFilter(); + this.institutionFilter(); + this.providerFilter(); + this.partOfCollectionFilter(); + this.searchStoreValue(); + this.resourcesTabStoreValue(); + this.sortByStoreValue(); + if (this.skipInitializationEffects > 0) { + this.#store.dispatch(GetResources); + } + this.skipInitializationEffects += 1; + }); + + // put search value in store and update resources, filters + toObservable(this.searchValue) + .pipe(skip(1), debounceTime(500)) + .subscribe((searchText) => { + this.#store.dispatch(new SetSearchText(searchText)); + this.#store.dispatch(GetAllOptions); + }); + + // sync search with query parameters if search is empty and parameters are not + effect(() => { + const storeValue = this.searchStoreValue(); + const currentInput = untracked(() => this.searchValue()); + + if (storeValue && currentInput !== storeValue) { + this.searchValue.set(storeValue); + } + }); + + // sync resource tabs with store + effect(() => { + if (this.selectedTab !== this.resourcesTabStoreValue()) { + this.selectedTab = this.resourcesTabStoreValue(); + } + }); + } + + onTabChange(index: ResourceTab): void { + this.#store.dispatch(new SetResourceTab(index)); + this.selectedTab = index; + this.#store.dispatch(GetAllOptions); + } +} diff --git a/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.html b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.html new file mode 100644 index 000000000..bfdf735af --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.html @@ -0,0 +1,119 @@ +@if (filters().dateCreated.value) { + @let dateCreated = filters().dateCreated.filterName + ': ' + filters().dateCreated.label; + + + + + +} + +@if (filters().funder.value) { + @let funder = filters().funder.filterName + ': ' + filters().funder.label; + + + + + +} + +@if (filters().subject.value) { + @let subject = filters().subject.filterName + ': ' + filters().subject.label; + + + + + +} + +@if (filters().license.value) { + @let license = filters().license.filterName + ': ' + filters().license.label; + + + + + +} + +@if (filters().resourceType.value) { + @let resourceType = filters().resourceType.filterName + ': ' + filters().resourceType.label; + + + + + +} + +@if (filters().institution.value) { + @let institution = filters().institution.filterName + ': ' + filters().institution.label; + + + + + +} + +@if (filters().provider.value) { + @let provider = filters().provider.filterName + ': ' + filters().provider.label; + + + + + +} + +@if (filters().partOfCollection.value) { + @let partOfCollection = filters().partOfCollection.filterName + ': ' + filters().partOfCollection.label; + + + + + +} diff --git a/src/app/shared/components/resources/filter-chips/filter-chips.component.scss b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.scss similarity index 100% rename from src/app/shared/components/resources/filter-chips/filter-chips.component.scss rename to src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.scss diff --git a/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.spec.ts b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.spec.ts new file mode 100644 index 000000000..86201f510 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileFilterChipsComponent } from './my-profile-filter-chips.component'; + +describe('FilterChipsComponent', () => { + let component: MyProfileFilterChipsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileFilterChipsComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileFilterChipsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.ts b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.ts new file mode 100644 index 000000000..84fa7f603 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component.ts @@ -0,0 +1,68 @@ +import { Store } from '@ngxs/store'; + +import { PrimeTemplate } from 'primeng/api'; +import { Chip } from 'primeng/chip'; + +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { + SetDateCreated, + SetFunder, + SetInstitution, + SetLicense, + SetPartOfCollection, + SetProvider, + SetResourceType, + SetSubject, +} from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { MyProfileSelectors } from '@osf/features/my-profile/store/my-profile.selectors'; +import { FilterType } from '@shared/entities/filters/filter-type.enum'; + +@Component({ + selector: 'osf-my-profile-filter-chips', + imports: [Chip, PrimeTemplate], + templateUrl: './my-profile-filter-chips.component.html', + styleUrl: './my-profile-filter-chips.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileFilterChipsComponent { + readonly #store = inject(Store); + + protected filters = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getAllFilters); + + readonly isMyProfilePage = this.#store.selectSignal(MyProfileSelectors.getIsMyProfile); + + clearFilter(filter: FilterType) { + switch (filter) { + case FilterType.DateCreated: + this.#store.dispatch(new SetDateCreated('')); + break; + case FilterType.Funder: + this.#store.dispatch(new SetFunder('', '')); + break; + case FilterType.Subject: + this.#store.dispatch(new SetSubject('', '')); + break; + case FilterType.License: + this.#store.dispatch(new SetLicense('', '')); + break; + case FilterType.ResourceType: + this.#store.dispatch(new SetResourceType('', '')); + break; + case FilterType.Institution: + this.#store.dispatch(new SetInstitution('', '')); + break; + case FilterType.Provider: + this.#store.dispatch(new SetProvider('', '')); + break; + case FilterType.PartOfCollection: + this.#store.dispatch(new SetPartOfCollection('', '')); + break; + } + this.#store.dispatch(GetAllOptions); + } + + protected readonly FilterType = FilterType; +} diff --git a/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.html b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.html new file mode 100644 index 000000000..abdacb37e --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.html @@ -0,0 +1,183 @@ +
+ + + +
+ @if (item()?.resourceType && item()?.resourceType === ResourceType.Agent) { +

User

+ } @else if (item()?.resourceType) { +

{{ ResourceType[item()?.resourceType!] }}

+ } + +
+ @if (item()?.resourceType === ResourceType.File && item()?.fileName) { + {{ item()?.fileName }} + } @else if (item()?.title && item()?.title) { + @let id = item()?.id; + @let url = id ? '/my-projects/' + id.split('/')?.pop() + '/overview' : ''; + {{ item()?.title }} + } + @if (item()?.orcid) { + + orcid + + } +
+ + @if (item()?.creators?.length) { +
+ @for (creator of item()?.creators!.slice(0, 4); track creator.id; let i = $index) { + {{ creator.name }} + @if (i < (item()?.creators)!.length - 1 && i < 3) { + , + } + } + @if ((item()?.creators)!.length > 4) { +

 and {{ (item()?.creators)!.length - 4 }} more

+ } +
+ } + + @if (item()?.from?.id && item()?.from?.name) { + + } + + @if (item()?.dateCreated && item()?.dateModified) { +

+ @if (!isSmall()) { + Date created: {{ item()?.dateCreated | date: 'MMMM d, y' }} | Date modified: + {{ item()?.dateModified | date: 'MMMM d, y' }} + } @else { +

+

Date created: {{ item()?.dateCreated | date: 'MMMM d, y' }}

+

+ Date modified: + {{ item()?.dateModified | date: 'MMMM d, y' }} +

+
+ } +

+ } + + @if (item()?.resourceType === ResourceType.Registration) { + + } +
+
+ +
+ @if (item()?.description) { +

Description: {{ item()?.description }}

+ } + + @if (item()?.provider?.id) { + +

Registration provider: 

+ {{ item()?.provider?.name }} +
+ } + + @if (item()?.license?.id) { + +

License: 

+ {{ item()?.license?.name }} +
+ } + + @if (item()?.registrationTemplate) { +

Registration Template: {{ item()?.registrationTemplate }}

+ } + + @if (item()?.provider?.id) { + +

Provider: 

+ {{ item()?.provider?.name }} +
+ } + + @if (item()?.conflictOfInterestResponse && item()?.conflictOfInterestResponse === 'no-conflict-of-interest') { +

Conflict of Interest response: Author asserted no Conflict of Interest

+ } + + @if (item()?.resourceType !== ResourceType.Agent && item()?.id) { + +

URL: 

+ {{ item()?.id }} +
+ } + + @if (item()?.doi) { + +

DOI: 

+ {{ item()?.doi }} +
+ } + + @if (item()?.resourceType === ResourceType.Agent) { + @if (loading) { + + + + } @else { +

Public projects: {{ item()?.publicProjects ?? 0 }}

+

Public registrations: {{ item()?.publicRegistrations ?? 0 }}

+

Public preprints: {{ item()?.publicPreprints ?? 0 }}

+ } + } + + @if (item()?.employment) { +

Employment: {{ item()?.employment }}

+ } + + @if (item()?.education) { +

Education: {{ item()?.education }}

+ } +
+
+
+
+
diff --git a/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.scss b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.scss new file mode 100644 index 000000000..f5e99a7c1 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.scss @@ -0,0 +1 @@ +@use "/app/shared/styles/resource-card/resource-card.scss" as resource-card; diff --git a/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.spec.ts new file mode 100644 index 000000000..58d77776e --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileResourceCardComponent } from './my-profile-resource-card.component'; + +describe('MyProfileResourceCardComponent', () => { + let component: MyProfileResourceCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileResourceCardComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileResourceCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.ts b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.ts new file mode 100644 index 000000000..53b100192 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component.ts @@ -0,0 +1,74 @@ +import { Accordion, AccordionContent, AccordionHeader, AccordionPanel } from 'primeng/accordion'; +import { Skeleton } from 'primeng/skeleton'; + +import { finalize } from 'rxjs'; + +import { DatePipe, NgOptimizedImage } from '@angular/common'; +import { ChangeDetectionStrategy, Component, inject, model } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { RouterLink } from '@angular/router'; + +import { ResourceCardService } from '@osf/features/search/components/resources/components/resource-card/services/resource-card.service'; +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceType } from '@shared/entities/resource-card/resource-type.enum'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; + +import { environment } from '../../../../../../../environments/environment'; + +@Component({ + selector: 'osf-my-profile-resource-card', + imports: [ + Accordion, + AccordionContent, + AccordionHeader, + AccordionPanel, + DatePipe, + NgOptimizedImage, + Skeleton, + RouterLink, + ], + templateUrl: './my-profile-resource-card.component.html', + styleUrl: './my-profile-resource-card.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileResourceCardComponent { + item = model(undefined); + readonly #resourceCardService = inject(ResourceCardService); + loading = false; + dataIsLoaded = false; + isSmall = toSignal(inject(IS_XSMALL)); + + protected readonly ResourceType = ResourceType; + + onOpen() { + if (this.item() && !this.dataIsLoaded) { + const userIri = this.item()?.id.split('/').pop(); + if (userIri) { + this.loading = true; + this.#resourceCardService + .getUserRelatedCounts(userIri) + .pipe( + finalize(() => { + this.loading = false; + this.dataIsLoaded = true; + }) + ) + .subscribe((res) => { + this.item.update( + (current) => + ({ + ...current, + publicProjects: res.projects, + publicPreprints: res.preprints, + publicRegistrations: res.registrations, + education: res.education, + employment: res.employment, + }) as Resource + ); + }); + } + } + } + + protected readonly environment = environment; +} diff --git a/src/app/features/my-profile/components/resources/components/resource-card/services/my-profile-resource-card.service.ts b/src/app/features/my-profile/components/resources/components/resource-card/services/my-profile-resource-card.service.ts new file mode 100644 index 000000000..ea786529b --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-card/services/my-profile-resource-card.service.ts @@ -0,0 +1,27 @@ +import { map, Observable } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { JsonApiService } from '@core/services/json-api/json-api.service'; +import { UserCountsResponse } from '@shared/entities/resource-card/user-counts-response.entity'; +import { UserRelatedDataCounts } from '@shared/entities/resource-card/user-related-data-counts.entity'; +import { MapUserCounts } from '@shared/helpers/mappers/resource-card/user-counts.mapper'; + +import { environment } from '../../../../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class ResourceCardService { + #jsonApiService = inject(JsonApiService); + + getUserRelatedCounts(userIri: string): Observable { + const params: Record = { + related_counts: 'nodes,registrations,preprints', + }; + + return this.#jsonApiService + .get(`${environment.apiUrl}/users/${userIri}`, params) + .pipe(map((response) => MapUserCounts(response))); + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/index.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/index.ts new file mode 100644 index 000000000..91d233e60 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/index.ts @@ -0,0 +1,8 @@ +export * from './my-profile-date-created-filter/my-profile-date-created-filter.component'; +export * from './my-profile-funder-filter/my-profile-funder-filter.component'; +export * from './my-profile-institution-filter/my-profile-institution-filter.component'; +export * from './my-profile-license-filter/my-profile-license-filter.component'; +export * from './my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component'; +export * from './my-profile-provider-filter/my-profile-provider-filter.component'; +export * from './my-profile-resource-type-filter/my-profile-resource-type-filter.component'; +export * from './my-profile-subject-filter/my-profile-subject-filter.component'; diff --git a/src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.spec.ts new file mode 100644 index 000000000..410fca7e8 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileDateCreatedFilterComponent } from './my-profile-date-created-filter.component'; + +describe('MyProfileDateCreatedFilterComponent', () => { + let component: MyProfileDateCreatedFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileDateCreatedFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileDateCreatedFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.ts new file mode 100644 index 000000000..2d9c0ee31 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-date-created-filter/my-profile-date-created-filter.component.ts @@ -0,0 +1,52 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetDateCreated } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-date-created-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-date-created-filter.component.html', + styleUrl: './my-profile-date-created-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileDateCreatedFilterComponent { + readonly #store = inject(Store); + + protected availableDates = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getDatesCreated); + protected dateCreatedState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getDateCreated); + protected inputDate = signal(null); + protected datesOptions = computed(() => { + return this.availableDates().map((date) => ({ + label: date.value + ' (' + date.count + ')', + value: date.value, + })); + }); + + constructor() { + effect(() => { + const storeValue = this.dateCreatedState().label; + const currentInput = untracked(() => this.inputDate()); + + if (!storeValue && currentInput !== null) { + this.inputDate.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputDate.set(storeValue); + } + }); + } + + setDateCreated(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId) { + this.#store.dispatch(new SetDateCreated(event.value)); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.spec.ts new file mode 100644 index 000000000..ee95da25e --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileFunderFilterComponent } from './my-profile-funder-filter.component'; + +describe('MyProfileFunderFilterComponent', () => { + let component: MyProfileFunderFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileFunderFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileFunderFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.ts new file mode 100644 index 000000000..40b253436 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-funder-filter/my-profile-funder-filter.component.ts @@ -0,0 +1,74 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetFunder } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-funder-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-funder-filter.component.html', + styleUrl: './my-profile-funder-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileFunderFilterComponent { + readonly #store = inject(Store); + + protected funderState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getFunder); + protected availableFunders = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getFunders); + protected inputText = signal(null); + protected fundersOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableFunders() + .filter((funder) => funder.label.toLowerCase().includes(search)) + .map((funder) => ({ + labelCount: funder.label + ' (' + funder.count + ')', + label: funder.label, + id: funder.id, + })); + } + + const res = this.availableFunders().map((funder) => ({ + labelCount: funder.label + ' (' + funder.count + ')', + label: funder.label, + id: funder.id, + })); + + return res; + }); + + constructor() { + effect(() => { + const storeValue = this.funderState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + loading = signal(false); + + setFunders(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const funder = this.fundersOptions()?.find((funder) => funder.label.includes(event.value)); + if (funder) { + this.#store.dispatch(new SetFunder(funder.label, funder.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetFunder('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.spec.ts new file mode 100644 index 000000000..c50ffcc68 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileInstitutionFilterComponent } from './my-profile-institution-filter.component'; + +describe('MyProfileInstitutionFilterComponent', () => { + let component: MyProfileInstitutionFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileInstitutionFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileInstitutionFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.ts new file mode 100644 index 000000000..a11c70d70 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-institution-filter/my-profile-institution-filter.component.ts @@ -0,0 +1,74 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetInstitution } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-institution-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-institution-filter.component.html', + styleUrl: './my-profile-institution-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileInstitutionFilterComponent { + readonly #store = inject(Store); + + protected institutionState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getInstitution); + protected availableInstitutions = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getInstitutions); + protected inputText = signal(null); + protected institutionsOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableInstitutions() + .filter((institution) => institution.label.toLowerCase().includes(search)) + .map((institution) => ({ + labelCount: institution.label + ' (' + institution.count + ')', + label: institution.label, + id: institution.id, + })); + } + + const res = this.availableInstitutions().map((institution) => ({ + labelCount: institution.label + ' (' + institution.count + ')', + label: institution.label, + id: institution.id, + })); + + return res; + }); + + constructor() { + effect(() => { + const storeValue = this.institutionState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + loading = signal(false); + + setInstitutions(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const institution = this.institutionsOptions()?.find((institution) => institution.label.includes(event.value)); + if (institution) { + this.#store.dispatch(new SetInstitution(institution.label, institution.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetInstitution('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.spec.ts new file mode 100644 index 000000000..9424d6b4a --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileLicenseFilterComponent } from './my-profile-license-filter.component'; + +describe('MyProfileLicenseFilterComponent', () => { + let component: MyProfileLicenseFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileLicenseFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileLicenseFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.ts new file mode 100644 index 000000000..c2009e775 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-license-filter/my-profile-license-filter.component.ts @@ -0,0 +1,72 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetLicense } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-license-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-license-filter.component.html', + styleUrl: './my-profile-license-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileLicenseFilterComponent { + readonly #store = inject(Store); + + protected availableLicenses = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getLicenses); + protected licenseState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getLicense); + protected inputText = signal(null); + protected licensesOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableLicenses() + .filter((license) => license.label.toLowerCase().includes(search)) + .map((license) => ({ + labelCount: license.label + ' (' + license.count + ')', + label: license.label, + id: license.id, + })); + } + + return this.availableLicenses().map((license) => ({ + labelCount: license.label + ' (' + license.count + ')', + label: license.label, + id: license.id, + })); + }); + + loading = signal(false); + + constructor() { + effect(() => { + const storeValue = this.licenseState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + setLicenses(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const license = this.licensesOptions().find((license) => license.label.includes(event.value)); + if (license) { + this.#store.dispatch(new SetLicense(license.label, license.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetLicense('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.spec.ts new file mode 100644 index 000000000..6ab3d0fe8 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfilePartOfCollectionFilterComponent } from './my-profile-part-of-collection-filter.component'; + +describe('MyProfilePartOfCollectionFilterComponent', () => { + let component: MyProfilePartOfCollectionFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfilePartOfCollectionFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfilePartOfCollectionFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.ts new file mode 100644 index 000000000..7bab21c6d --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-part-of-collection-filter/my-profile-part-of-collection-filter.component.ts @@ -0,0 +1,63 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetPartOfCollection } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-part-of-collection-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-part-of-collection-filter.component.html', + styleUrl: './my-profile-part-of-collection-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfilePartOfCollectionFilterComponent { + readonly #store = inject(Store); + + protected availablePartOfCollections = this.#store.selectSignal( + MyProfileResourceFiltersOptionsSelectors.getPartOfCollection + ); + protected partOfCollectionState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getPartOfCollection); + protected inputText = signal(null); + protected partOfCollectionsOptions = computed(() => { + return this.availablePartOfCollections().map((partOfCollection) => ({ + labelCount: partOfCollection.label + ' (' + partOfCollection.count + ')', + label: partOfCollection.label, + id: partOfCollection.id, + })); + }); + + loading = signal(false); + + constructor() { + effect(() => { + const storeValue = this.partOfCollectionState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + setPartOfCollections(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const part = this.partOfCollectionsOptions().find((p) => p.label.includes(event.value)); + if (part) { + this.#store.dispatch(new SetPartOfCollection(part.label, part.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetPartOfCollection('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.spec.ts new file mode 100644 index 000000000..897e75514 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileProviderFilterComponent } from './my-profile-provider-filter.component'; + +describe('MyProfileProviderFilterComponent', () => { + let component: MyProfileProviderFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileProviderFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileProviderFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.ts new file mode 100644 index 000000000..23ba707cb --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-provider-filter/my-profile-provider-filter.component.ts @@ -0,0 +1,72 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetProvider } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-provider-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-provider-filter.component.html', + styleUrl: './my-profile-provider-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileProviderFilterComponent { + readonly #store = inject(Store); + + protected availableProviders = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getProviders); + protected providerState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getProvider); + protected inputText = signal(null); + protected providersOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableProviders() + .filter((provider) => provider.label.toLowerCase().includes(search)) + .map((provider) => ({ + labelCount: provider.label + ' (' + provider.count + ')', + label: provider.label, + id: provider.id, + })); + } + + return this.availableProviders().map((provider) => ({ + labelCount: provider.label + ' (' + provider.count + ')', + label: provider.label, + id: provider.id, + })); + }); + + loading = signal(false); + + constructor() { + effect(() => { + const storeValue = this.providerState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + setProviders(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const provider = this.providersOptions().find((p) => p.label.includes(event.value)); + if (provider) { + this.#store.dispatch(new SetProvider(provider.label, provider.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetProvider('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.spec.ts new file mode 100644 index 000000000..a716ca8a3 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileResourceTypeFilterComponent } from './my-profile-resource-type-filter.component'; + +describe('MyProfileResourceTypeFilterComponent', () => { + let component: MyProfileResourceTypeFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileResourceTypeFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileResourceTypeFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.ts new file mode 100644 index 000000000..fb4414672 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-resource-type-filter/my-profile-resource-type-filter.component.ts @@ -0,0 +1,74 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { SetResourceType } from '@osf/features/search/components/resources/components/resource-filters/store'; + +@Component({ + selector: 'osf-my-profile-resource-type-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-resource-type-filter.component.html', + styleUrl: './my-profile-resource-type-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileResourceTypeFilterComponent { + readonly #store = inject(Store); + + protected availableResourceTypes = this.#store.selectSignal( + MyProfileResourceFiltersOptionsSelectors.getResourceTypes + ); + protected resourceTypeState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getResourceType); + protected inputText = signal(null); + protected resourceTypesOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableResourceTypes() + .filter((resourceType) => resourceType.label.toLowerCase().includes(search)) + .map((resourceType) => ({ + labelCount: resourceType.label + ' (' + resourceType.count + ')', + label: resourceType.label, + id: resourceType.id, + })); + } + + return this.availableResourceTypes().map((resourceType) => ({ + labelCount: resourceType.label + ' (' + resourceType.count + ')', + label: resourceType.label, + id: resourceType.id, + })); + }); + + loading = signal(false); + + constructor() { + effect(() => { + const storeValue = this.resourceTypeState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + setResourceTypes(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const resourceType = this.resourceTypesOptions().find((p) => p.label.includes(event.value)); + if (resourceType) { + this.#store.dispatch(new SetResourceType(resourceType.label, resourceType.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetResourceType('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.html rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.html diff --git a/src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.spec.ts new file mode 100644 index 000000000..c2df28347 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileSubjectFilterComponent } from './my-profile-subject-filter.component'; + +describe('MyProfileSubjectFilterComponent', () => { + let component: MyProfileSubjectFilterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileSubjectFilterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileSubjectFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.ts new file mode 100644 index 000000000..4902d3c51 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/my-profile-subject-filter/my-profile-subject-filter.component.ts @@ -0,0 +1,72 @@ +import { Store } from '@ngxs/store'; + +import { Select, SelectChangeEvent } from 'primeng/select'; + +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { GetAllOptions } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { SetSubject } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; + +@Component({ + selector: 'osf-my-profile-subject-filter', + imports: [Select, FormsModule], + templateUrl: './my-profile-subject-filter.component.html', + styleUrl: './my-profile-subject-filter.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileSubjectFilterComponent { + readonly #store = inject(Store); + + protected availableSubjects = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getSubjects); + protected subjectState = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getSubject); + protected inputText = signal(null); + protected subjectsOptions = computed(() => { + if (this.inputText() !== null) { + const search = this.inputText()!.toLowerCase(); + return this.availableSubjects() + .filter((subject) => subject.label.toLowerCase().includes(search)) + .map((subject) => ({ + labelCount: subject.label + ' (' + subject.count + ')', + label: subject.label, + id: subject.id, + })); + } + + return this.availableSubjects().map((subject) => ({ + labelCount: subject.label + ' (' + subject.count + ')', + label: subject.label, + id: subject.id, + })); + }); + + loading = signal(false); + + constructor() { + effect(() => { + const storeValue = this.subjectState().label; + const currentInput = untracked(() => this.inputText()); + + if (!storeValue && currentInput !== null) { + this.inputText.set(null); + } else if (storeValue && currentInput !== storeValue) { + this.inputText.set(storeValue); + } + }); + } + + setSubject(event: SelectChangeEvent): void { + if ((event.originalEvent as PointerEvent).pointerId && event.value) { + const subject = this.subjectsOptions().find((p) => p.label.includes(event.value)); + if (subject) { + this.#store.dispatch(new SetSubject(subject.label, subject.id)); + this.#store.dispatch(GetAllOptions); + } + } else { + this.#store.dispatch(new SetSubject('', '')); + this.#store.dispatch(GetAllOptions); + } + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions.ts new file mode 100644 index 000000000..246240616 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions.ts @@ -0,0 +1,35 @@ +export class GetDatesCreatedOptions { + static readonly type = '[My Profile Resource Filters Options] Get Dates Created'; +} + +export class GetFundersOptions { + static readonly type = '[My Profile Resource Filters Options] Get Funders'; +} + +export class GetSubjectsOptions { + static readonly type = '[My Profile Resource Filters Options] Get Subjects'; +} + +export class GetLicensesOptions { + static readonly type = '[My Profile Resource Filters Options] Get Licenses'; +} + +export class GetResourceTypesOptions { + static readonly type = '[My Profile Resource Filters Options] Get Resource Types'; +} + +export class GetInstitutionsOptions { + static readonly type = '[My Profile Resource Filters Options] Get Institutions'; +} + +export class GetProvidersOptions { + static readonly type = '[My Profile Resource Filters Options] Get Providers'; +} + +export class GetPartOfCollectionOptions { + static readonly type = '[My Profile Resource Filters Options] Get Part Of Collection Options'; +} + +export class GetAllOptions { + static readonly type = '[My Profile Resource Filters Options] Get All Options'; +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.model.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.model.ts new file mode 100644 index 000000000..6d6399f93 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.model.ts @@ -0,0 +1,19 @@ +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { InstitutionFilter } from '@shared/entities/filters/institution/institution-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; + +export interface MyProfileResourceFiltersOptionsStateModel { + datesCreated: DateCreated[]; + funders: FunderFilter[]; + subjects: SubjectFilter[]; + licenses: LicenseFilter[]; + resourceTypes: ResourceTypeFilter[]; + institutions: InstitutionFilter[]; + providers: ProviderFilter[]; + partOfCollection: PartOfCollectionFilter[]; +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors.ts new file mode 100644 index 000000000..a8e6d3dee --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors.ts @@ -0,0 +1,62 @@ +import { Selector } from '@ngxs/store'; + +import { MyProfileResourceFiltersOptionsStateModel } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.model'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { InstitutionFilter } from '@shared/entities/filters/institution/institution-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; + +import { MyProfileResourceFiltersOptionsState } from './my-profile-resource-filters-options.state'; + +export class MyProfileResourceFiltersOptionsSelectors { + @Selector([MyProfileResourceFiltersOptionsState]) + static getDatesCreated(state: MyProfileResourceFiltersOptionsStateModel): DateCreated[] { + return state.datesCreated; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getFunders(state: MyProfileResourceFiltersOptionsStateModel): FunderFilter[] { + return state.funders; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getSubjects(state: MyProfileResourceFiltersOptionsStateModel): SubjectFilter[] { + return state.subjects; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getLicenses(state: MyProfileResourceFiltersOptionsStateModel): LicenseFilter[] { + return state.licenses; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getResourceTypes(state: MyProfileResourceFiltersOptionsStateModel): ResourceTypeFilter[] { + return state.resourceTypes; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getInstitutions(state: MyProfileResourceFiltersOptionsStateModel): InstitutionFilter[] { + return state.institutions; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getProviders(state: MyProfileResourceFiltersOptionsStateModel): ProviderFilter[] { + return state.providers; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getPartOfCollection(state: MyProfileResourceFiltersOptionsStateModel): PartOfCollectionFilter[] { + return state.partOfCollection; + } + + @Selector([MyProfileResourceFiltersOptionsState]) + static getAllOptions(state: MyProfileResourceFiltersOptionsStateModel): MyProfileResourceFiltersOptionsStateModel { + return { + ...state, + }; + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.state.ts b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.state.ts new file mode 100644 index 000000000..deb5aa3bd --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.state.ts @@ -0,0 +1,122 @@ +import { Action, State, StateContext, Store } from '@ngxs/store'; + +import { tap } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { + GetAllOptions, + GetDatesCreatedOptions, + GetFundersOptions, + GetInstitutionsOptions, + GetLicensesOptions, + GetPartOfCollectionOptions, + GetProvidersOptions, + GetResourceTypesOptions, + GetSubjectsOptions, +} from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.actions'; +import { MyProfileResourceFiltersOptionsStateModel } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.model'; +import { MyProfileFiltersOptionsService } from '@osf/features/my-profile/components/resources/components/resource-filters/services/my-profile-resource-filters.service'; +import { ResourceFiltersOptionsStateModel } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model'; + +@State({ + name: 'myProfileResourceFiltersOptions', + defaults: { + datesCreated: [], + funders: [], + subjects: [], + licenses: [], + resourceTypes: [], + institutions: [], + providers: [], + partOfCollection: [], + }, +}) +@Injectable() +export class MyProfileResourceFiltersOptionsState { + readonly #store = inject(Store); + readonly #filtersOptionsService = inject(MyProfileFiltersOptionsService); + + @Action(GetDatesCreatedOptions) + getDatesCreated(ctx: StateContext) { + return this.#filtersOptionsService.getDates().pipe( + tap((datesCreated) => { + ctx.patchState({ datesCreated: datesCreated }); + }) + ); + } + + @Action(GetFundersOptions) + getFunders(ctx: StateContext) { + return this.#filtersOptionsService.getFunders().pipe( + tap((funders) => { + ctx.patchState({ funders: funders }); + }) + ); + } + + @Action(GetSubjectsOptions) + getSubjects(ctx: StateContext) { + return this.#filtersOptionsService.getSubjects().pipe( + tap((subjects) => { + ctx.patchState({ subjects: subjects }); + }) + ); + } + + @Action(GetLicensesOptions) + getLicenses(ctx: StateContext) { + return this.#filtersOptionsService.getLicenses().pipe( + tap((licenses) => { + ctx.patchState({ licenses: licenses }); + }) + ); + } + + @Action(GetResourceTypesOptions) + getResourceTypes(ctx: StateContext) { + return this.#filtersOptionsService.getResourceTypes().pipe( + tap((resourceTypes) => { + ctx.patchState({ resourceTypes: resourceTypes }); + }) + ); + } + + @Action(GetInstitutionsOptions) + getInstitutions(ctx: StateContext) { + return this.#filtersOptionsService.getInstitutions().pipe( + tap((institutions) => { + ctx.patchState({ institutions: institutions }); + }) + ); + } + + @Action(GetProvidersOptions) + getProviders(ctx: StateContext) { + return this.#filtersOptionsService.getProviders().pipe( + tap((providers) => { + ctx.patchState({ providers: providers }); + }) + ); + } + @Action(GetPartOfCollectionOptions) + getPartOfCollection(ctx: StateContext) { + return this.#filtersOptionsService.getPartOtCollections().pipe( + tap((partOfCollection) => { + ctx.patchState({ partOfCollection: partOfCollection }); + }) + ); + } + + @Action(GetAllOptions) + getAllOptions() { + this.#store.dispatch(GetDatesCreatedOptions); + this.#store.dispatch(GetFundersOptions); + this.#store.dispatch(GetSubjectsOptions); + this.#store.dispatch(GetLicensesOptions); + this.#store.dispatch(GetResourceTypesOptions); + this.#store.dispatch(GetInstitutionsOptions); + this.#store.dispatch(GetProvidersOptions); + this.#store.dispatch(GetPartOfCollectionOptions); + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.html b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.html new file mode 100644 index 000000000..05c15b5f1 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.html @@ -0,0 +1,77 @@ +@if (anyOptionsCount()) { +
+ + @if (datesOptionsCount() > 0) { + + Date Created + + + + + } + + @if (funderOptionsCount() > 0) { + + Funder + + + + + } + + @if (subjectOptionsCount() > 0) { + + Subject + + + + + } + + @if (licenseOptionsCount() > 0) { + + License + + + + + } + + @if (resourceTypeOptionsCount() > 0) { + + Resource Type + + + + + } + + @if (institutionOptionsCount() > 0) { + + Institution + + + + + } + + @if (providerOptionsCount() > 0) { + + Provider + + + + + } + + @if (partOfCollectionOptionsCount() > 0) { + + Part of Collection + + + + + } + +
+} diff --git a/src/app/shared/components/resources/resource-filters/resource-filters.component.scss b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/resource-filters.component.scss rename to src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.scss diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.spec.ts b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.spec.ts new file mode 100644 index 000000000..f6396d507 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileResourceFiltersComponent } from './my-profile-resource-filters.component'; + +describe('MyProfileResourceFiltersComponent', () => { + let component: MyProfileResourceFiltersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileResourceFiltersComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileResourceFiltersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.ts b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.ts new file mode 100644 index 000000000..c80d5b07a --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component.ts @@ -0,0 +1,105 @@ +import { Store } from '@ngxs/store'; + +import { Accordion, AccordionContent, AccordionHeader, AccordionPanel } from 'primeng/accordion'; + +import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core'; + +import { + MyProfileDateCreatedFilterComponent, + MyProfileFunderFilterComponent, + MyProfileInstitutionFilterComponent, + MyProfileLicenseFilterComponent, + MyProfilePartOfCollectionFilterComponent, + MyProfileProviderFilterComponent, + MyProfileResourceTypeFilterComponent, + MyProfileSubjectFilterComponent, +} from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { MyProfileSelectors } from '@osf/features/my-profile/store/my-profile.selectors'; + +@Component({ + selector: 'osf-my-profile-resource-filters', + imports: [ + Accordion, + AccordionContent, + AccordionHeader, + AccordionPanel, + MyProfileDateCreatedFilterComponent, + MyProfileFunderFilterComponent, + MyProfileSubjectFilterComponent, + MyProfileLicenseFilterComponent, + MyProfileResourceTypeFilterComponent, + MyProfileInstitutionFilterComponent, + MyProfileProviderFilterComponent, + MyProfilePartOfCollectionFilterComponent, + ], + templateUrl: './my-profile-resource-filters.component.html', + styleUrl: './my-profile-resource-filters.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileResourceFiltersComponent { + readonly #store = inject(Store); + + readonly datesOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getDatesCreated)() + .reduce((accumulator, date) => accumulator + date.count, 0); + }); + + readonly funderOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getFunders)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly subjectOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getSubjects)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly licenseOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getLicenses)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly resourceTypeOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getResourceTypes)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly institutionOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getInstitutions)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly providerOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getProviders)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly partOfCollectionOptionsCount = computed(() => { + return this.#store + .selectSignal(MyProfileResourceFiltersOptionsSelectors.getPartOfCollection)() + .reduce((acc, item) => acc + item.count, 0); + }); + + readonly isMyProfilePage = this.#store.selectSignal(MyProfileSelectors.getIsMyProfile); + + readonly anyOptionsCount = computed(() => { + return ( + this.datesOptionsCount() > 0 || + this.funderOptionsCount() > 0 || + this.subjectOptionsCount() > 0 || + this.licenseOptionsCount() > 0 || + this.resourceTypeOptionsCount() > 0 || + this.institutionOptionsCount() > 0 || + this.providerOptionsCount() > 0 || + this.partOfCollectionOptionsCount() > 0 + ); + }); +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/services/my-profile-resource-filters.service.ts b/src/app/features/my-profile/components/resources/components/resource-filters/services/my-profile-resource-filters.service.ts new file mode 100644 index 000000000..e1d1610ca --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/services/my-profile-resource-filters.service.ts @@ -0,0 +1,80 @@ +import { Store } from '@ngxs/store'; + +import { Observable } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { UserSelectors } from '@core/store/user/user.selectors'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { MyProfileSelectors } from '@osf/features/my-profile/store/my-profile.selectors'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; +import { FiltersOptionsService } from '@shared/services/filters-options.service'; +import { addFiltersParams } from '@shared/utils/add-filters-params.helper'; +import { getResourceTypes } from '@shared/utils/get-resource-types.helper'; + +@Injectable({ + providedIn: 'root', +}) +export class MyProfileFiltersOptionsService { + #store = inject(Store); + #filtersOptions = inject(FiltersOptionsService); + + #getFilterParams(): Record { + return addFiltersParams(this.#store.selectSignal(MyProfileResourceFiltersSelectors.getAllFilters)()); + } + + #getParams(): Record { + const params: Record = {}; + const resourceTab = this.#store.selectSnapshot(MyProfileSelectors.getResourceTab); + const resourceTypes = getResourceTypes(resourceTab); + const searchText = this.#store.selectSnapshot(MyProfileSelectors.getSearchText); + const sort = this.#store.selectSnapshot(MyProfileSelectors.getSortBy); + const user = this.#store.selectSnapshot(UserSelectors.getCurrentUser); + + params['cardSearchFilter[resourceType]'] = resourceTypes; + params['cardSearchFilter[accessService]'] = 'https://staging4.osf.io/'; + params['cardSearchText[*,creator.name,isContainedBy.creator.name]'] = searchText; + params['page[size]'] = '10'; + params['sort'] = sort; + params['cardSearchFilter[creator][]'] = user?.id ?? ''; + return params; + } + + getDates(): Observable { + return this.#filtersOptions.getDates(this.#getParams(), this.#getFilterParams()); + } + + getFunders(): Observable { + return this.#filtersOptions.getFunders(this.#getParams(), this.#getFilterParams()); + } + + getSubjects(): Observable { + return this.#filtersOptions.getSubjects(this.#getParams(), this.#getFilterParams()); + } + + getLicenses(): Observable { + return this.#filtersOptions.getLicenses(this.#getParams(), this.#getFilterParams()); + } + + getResourceTypes(): Observable { + return this.#filtersOptions.getResourceTypes(this.#getParams(), this.#getFilterParams()); + } + + getInstitutions(): Observable { + return this.#filtersOptions.getInstitutions(this.#getParams(), this.#getFilterParams()); + } + + getProviders(): Observable { + return this.#filtersOptions.getProviders(this.#getParams(), this.#getFilterParams()); + } + + getPartOtCollections(): Observable { + return this.#filtersOptions.getPartOtCollections(this.#getParams(), this.#getFilterParams()); + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions.ts b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions.ts new file mode 100644 index 000000000..9ff219206 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions.ts @@ -0,0 +1,68 @@ +export class SetCreator { + static readonly type = '[ My Profile Resource Filters] Set Creator'; + constructor( + public name: string, + public id: string + ) {} +} + +export class SetDateCreated { + static readonly type = '[ My Profile Resource Filters] Set DateCreated'; + constructor(public date: string) {} +} + +export class SetFunder { + static readonly type = '[ My Profile Resource Filters] Set Funder'; + constructor( + public funder: string, + public id: string + ) {} +} + +export class SetSubject { + static readonly type = '[ My Profile Resource Filters] Set Subject'; + constructor( + public subject: string, + public id: string + ) {} +} + +export class SetLicense { + static readonly type = '[ My Profile Resource Filters] Set License'; + constructor( + public license: string, + public id: string + ) {} +} + +export class SetResourceType { + static readonly type = '[ My Profile Resource Filters] Set Resource Type'; + constructor( + public resourceType: string, + public id: string + ) {} +} + +export class SetInstitution { + static readonly type = '[ My Profile Resource Filters] Set Institution'; + constructor( + public institution: string, + public id: string + ) {} +} + +export class SetProvider { + static readonly type = '[ My Profile Resource Filters] Set Provider'; + constructor( + public provider: string, + public id: string + ) {} +} + +export class SetPartOfCollection { + static readonly type = '[ My Profile Resource Filters] Set PartOfCollection'; + constructor( + public partOfCollection: string, + public id: string + ) {} +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.model.ts b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.model.ts new file mode 100644 index 000000000..e1b20d42a --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.model.ts @@ -0,0 +1,17 @@ +export interface MyProfileResourceFiltersStateModel { + creator: ResourceFilterLabel; + dateCreated: ResourceFilterLabel; + funder: ResourceFilterLabel; + subject: ResourceFilterLabel; + license: ResourceFilterLabel; + resourceType: ResourceFilterLabel; + institution: ResourceFilterLabel; + provider: ResourceFilterLabel; + partOfCollection: ResourceFilterLabel; +} + +export interface ResourceFilterLabel { + filterName: string; + label?: string; + value?: string; +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors.ts b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors.ts new file mode 100644 index 000000000..08e6625a3 --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors.ts @@ -0,0 +1,61 @@ +import { Selector } from '@ngxs/store'; + +import { MyProfileResourceFiltersState } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.state'; +import { + ResourceFilterLabel, + ResourceFiltersStateModel, +} from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.model'; + +export class MyProfileResourceFiltersSelectors { + @Selector([MyProfileResourceFiltersState]) + static getAllFilters(state: ResourceFiltersStateModel): ResourceFiltersStateModel { + return { + ...state, + }; + } + + @Selector([MyProfileResourceFiltersState]) + static getCreator(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.creator; + } + + @Selector([MyProfileResourceFiltersState]) + static getDateCreated(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.dateCreated; + } + + @Selector([MyProfileResourceFiltersState]) + static getFunder(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.funder; + } + + @Selector([MyProfileResourceFiltersState]) + static getSubject(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.subject; + } + + @Selector([MyProfileResourceFiltersState]) + static getLicense(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.license; + } + + @Selector([MyProfileResourceFiltersState]) + static getResourceType(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.resourceType; + } + + @Selector([MyProfileResourceFiltersState]) + static getInstitution(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.institution; + } + + @Selector([MyProfileResourceFiltersState]) + static getProvider(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.provider; + } + + @Selector([MyProfileResourceFiltersState]) + static getPartOfCollection(state: ResourceFiltersStateModel): ResourceFilterLabel { + return state.partOfCollection; + } +} diff --git a/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.state.ts b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.state.ts new file mode 100644 index 000000000..b4993f04b --- /dev/null +++ b/src/app/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.state.ts @@ -0,0 +1,142 @@ +import { Action, NgxsOnInit, State, StateContext, Store } from '@ngxs/store'; + +import { inject, Injectable } from '@angular/core'; + +import { UserSelectors } from '@core/store/user/user.selectors'; +import { + SetCreator, + SetDateCreated, + SetFunder, + SetInstitution, + SetLicense, + SetPartOfCollection, + SetProvider, + SetResourceType, + SetSubject, +} from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.actions'; +import { MyProfileResourceFiltersStateModel } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.model'; +import { FilterLabelsModel } from '@shared/utils/filter-labels.model'; +import { resourceFiltersDefaultsModel } from '@shared/utils/resource-filters-defaults.model'; + +// Store for user selected filters values +@State({ + name: 'myProfileResourceFilters', + defaults: resourceFiltersDefaultsModel, +}) +@Injectable() +export class MyProfileResourceFiltersState implements NgxsOnInit { + #store = inject(Store); + #currentUser = this.#store.select(UserSelectors.getCurrentUser); + + ngxsOnInit(ctx: StateContext) { + this.#currentUser.subscribe((user) => { + if (user) { + ctx.patchState({ + creator: { + filterName: FilterLabelsModel.creator, + label: undefined, + value: user.iri, + }, + }); + } + }); + } + @Action(SetCreator) + setCreator(ctx: StateContext, action: SetCreator) { + ctx.patchState({ + creator: { + filterName: FilterLabelsModel.creator, + label: action.name, + value: action.id, + }, + }); + } + + @Action(SetDateCreated) + setDateCreated(ctx: StateContext, action: SetDateCreated) { + ctx.patchState({ + dateCreated: { + filterName: FilterLabelsModel.dateCreated, + label: action.date, + value: action.date, + }, + }); + } + + @Action(SetFunder) + setFunder(ctx: StateContext, action: SetFunder) { + ctx.patchState({ + funder: { + filterName: FilterLabelsModel.funder, + label: action.funder, + value: action.id, + }, + }); + } + + @Action(SetSubject) + setSubject(ctx: StateContext, action: SetSubject) { + ctx.patchState({ + subject: { + filterName: FilterLabelsModel.subject, + label: action.subject, + value: action.id, + }, + }); + } + + @Action(SetLicense) + setLicense(ctx: StateContext, action: SetLicense) { + ctx.patchState({ + license: { + filterName: FilterLabelsModel.license, + label: action.license, + value: action.id, + }, + }); + } + + @Action(SetResourceType) + setResourceType(ctx: StateContext, action: SetResourceType) { + ctx.patchState({ + resourceType: { + filterName: FilterLabelsModel.resourceType, + label: action.resourceType, + value: action.id, + }, + }); + } + + @Action(SetInstitution) + setInstitution(ctx: StateContext, action: SetInstitution) { + ctx.patchState({ + institution: { + filterName: FilterLabelsModel.institution, + label: action.institution, + value: action.id, + }, + }); + } + + @Action(SetProvider) + setProvider(ctx: StateContext, action: SetProvider) { + ctx.patchState({ + provider: { + filterName: FilterLabelsModel.provider, + label: action.provider, + value: action.id, + }, + }); + } + + @Action(SetPartOfCollection) + setPartOfCollection(ctx: StateContext, action: SetPartOfCollection) { + ctx.patchState({ + partOfCollection: { + filterName: FilterLabelsModel.partOfCollection, + label: action.partOfCollection, + value: action.id, + }, + }); + } +} diff --git a/src/app/features/my-profile/components/resources/my-profile-resources.component.html b/src/app/features/my-profile/components/resources/my-profile-resources.component.html new file mode 100644 index 000000000..2d705ec17 --- /dev/null +++ b/src/app/features/my-profile/components/resources/my-profile-resources.component.html @@ -0,0 +1,149 @@ +
+
+ @if (isMobile()) { + + } + @if (searchCount() > 10000) { +

10 000+ results

+ } @else if (searchCount() > 0) { +

{{ searchCount() }} results

+ } @else { +

0 results

+ } +
+ +
+ @if (isWeb()) { +

Sort by:

+ + } @else { + @if (isAnyFilterOptions()) { + filter by + } + sort by + } +
+
+ +@if (isFiltersOpen()) { +
+ +
+} @else if (isSortingOpen()) { +
+ @for (option of sortTabOptions; track option.value) { +
+ {{ option.label }} +
+ } +
+} @else { + @if (isAnyFilterSelected()) { +
+ +
+ } + +
+ @if (isWeb() && isAnyFilterOptions()) { + + } + + + +
+ @if (items.length > 0) { + @for (item of items; track item.id) { + + } + +
+ @if (first() && prev()) { + + + + } + + + + + + + + +
+ } +
+
+
+
+} diff --git a/src/app/shared/components/resources/resources.component.scss b/src/app/features/my-profile/components/resources/my-profile-resources.component.scss similarity index 100% rename from src/app/shared/components/resources/resources.component.scss rename to src/app/features/my-profile/components/resources/my-profile-resources.component.scss diff --git a/src/app/features/my-profile/components/resources/my-profile-resources.component.spec.ts b/src/app/features/my-profile/components/resources/my-profile-resources.component.spec.ts new file mode 100644 index 000000000..424043086 --- /dev/null +++ b/src/app/features/my-profile/components/resources/my-profile-resources.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyProfileResourcesComponent } from './my-profile-resources.component'; + +describe('MyProfileResourcesComponent', () => { + let component: MyProfileResourcesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MyProfileResourcesComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(MyProfileResourcesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/my-profile/components/resources/my-profile-resources.component.ts b/src/app/features/my-profile/components/resources/my-profile-resources.component.ts new file mode 100644 index 000000000..9ea8c9105 --- /dev/null +++ b/src/app/features/my-profile/components/resources/my-profile-resources.component.ts @@ -0,0 +1,159 @@ +import { Store } from '@ngxs/store'; + +import { DataView } from 'primeng/dataview'; +import { Select } from 'primeng/select'; + +import { NgOptimizedImage } from '@angular/common'; +import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { FormsModule } from '@angular/forms'; + +import { MyProfileFilterChipsComponent } from '@osf/features/my-profile/components/resources/components/filter-chips/my-profile-filter-chips.component'; +import { MyProfileResourceCardComponent } from '@osf/features/my-profile/components/resources/components/resource-card/my-profile-resource-card.component'; +import { MyProfileResourceFiltersOptionsSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/components/filters/store/my-profile-resource-filters-options.selectors'; +import { MyProfileResourceFiltersComponent } from '@osf/features/my-profile/components/resources/components/resource-filters/my-profile-resource-filters.component'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { GetResourcesByLink, SetResourceTab, SetSortBy } from '@osf/features/my-profile/store/my-profile.actions'; +import { MyProfileSelectors } from '@osf/features/my-profile/store/my-profile.selectors'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; +import { IS_WEB, IS_XSMALL } from '@shared/utils/breakpoints.tokens'; + +@Component({ + selector: 'osf-my-profile-resources', + imports: [ + DataView, + MyProfileFilterChipsComponent, + NgOptimizedImage, + MyProfileResourceCardComponent, + MyProfileResourceFiltersComponent, + Select, + FormsModule, + ], + templateUrl: './my-profile-resources.component.html', + styleUrl: './my-profile-resources.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class MyProfileResourcesComponent { + readonly #store = inject(Store); + + selectedTabStore = this.#store.selectSignal(MyProfileSelectors.getResourceTab); + searchCount = this.#store.selectSignal(MyProfileSelectors.getResourcesCount); + resources = this.#store.selectSignal(MyProfileSelectors.getResources); + sortBy = this.#store.selectSignal(MyProfileSelectors.getSortBy); + first = this.#store.selectSignal(MyProfileSelectors.getFirst); + next = this.#store.selectSignal(MyProfileSelectors.getNext); + prev = this.#store.selectSignal(MyProfileSelectors.getPrevious); + + isWeb = toSignal(inject(IS_WEB)); + + isFiltersOpen = signal(false); + isSortingOpen = signal(false); + + protected filters = this.#store.selectSignal(MyProfileResourceFiltersSelectors.getAllFilters); + protected filtersOptions = this.#store.selectSignal(MyProfileResourceFiltersOptionsSelectors.getAllOptions); + protected isAnyFilterSelected = computed(() => { + return ( + this.filters().dateCreated.value || + this.filters().funder.value || + this.filters().subject.value || + this.filters().license.value || + this.filters().resourceType.value || + this.filters().institution.value || + this.filters().provider.value || + this.filters().partOfCollection.value + ); + }); + protected isAnyFilterOptions = computed(() => { + return ( + this.filtersOptions().datesCreated.length > 0 || + this.filtersOptions().funders.length > 0 || + this.filtersOptions().subjects.length > 0 || + this.filtersOptions().licenses.length > 0 || + this.filtersOptions().resourceTypes.length > 0 || + this.filtersOptions().institutions.length > 0 || + this.filtersOptions().providers.length > 0 || + this.filtersOptions().partOfCollection.length > 0 + ); + }); + + protected readonly isMobile = toSignal(inject(IS_XSMALL)); + + protected selectedSort = signal(''); + protected readonly sortTabOptions = [ + { label: 'Relevance', value: '-relevance' }, + { label: 'Date created (newest)', value: '-dateCreated' }, + { label: 'Date created (oldest)', value: 'dateCreated' }, + { label: 'Date modified (newest)', value: '-dateModified' }, + { label: 'Date modified (oldest)', value: 'dateModified' }, + ]; + + protected selectedTab = signal(ResourceTab.All); + protected readonly tabsOptions = [ + { label: 'All', value: ResourceTab.All }, + { label: 'Projects', value: ResourceTab.Projects }, + { label: 'Registrations', value: ResourceTab.Registrations }, + { label: 'Preprints', value: ResourceTab.Preprints }, + { label: 'Files', value: ResourceTab.Files }, + { label: 'Users', value: ResourceTab.Users }, + ]; + + constructor() { + // if new value for sorting in store, update value in dropdown + effect(() => { + const storeValue = this.sortBy(); + const currentInput = untracked(() => this.selectedSort()); + + if (storeValue && currentInput !== storeValue) { + this.selectedSort.set(storeValue); + } + }); + + // if the sorting was changed, set new value to store + effect(() => { + const chosenValue = this.selectedSort(); + const storeValue = untracked(() => this.sortBy()); + + if (chosenValue !== storeValue) { + this.#store.dispatch(new SetSortBy(chosenValue)); + } + }); + + effect(() => { + const storeValue = this.selectedTabStore(); + const currentInput = untracked(() => this.selectedTab()); + + if (storeValue && currentInput !== storeValue) { + this.selectedTab.set(storeValue); + } + }); + + effect(() => { + const chosenValue = this.selectedTab(); + const storeValue = untracked(() => this.selectedTabStore()); + + if (chosenValue !== storeValue) { + this.#store.dispatch(new SetResourceTab(chosenValue)); + } + }); + } + + // pagination + switchPage(link: string) { + this.#store.dispatch(new GetResourcesByLink(link)); + } + + openFilters() { + this.isFiltersOpen.set(!this.isFiltersOpen()); + this.isSortingOpen.set(false); + } + + openSorting() { + this.isSortingOpen.set(!this.isSortingOpen()); + this.isFiltersOpen.set(false); + } + + selectSort(value: string) { + this.selectedSort.set(value); + this.openSorting(); + } +} diff --git a/src/app/features/my-profile/my-profile.component.html b/src/app/features/my-profile/my-profile.component.html index 5afdbd793..1ae168688 100644 --- a/src/app/features/my-profile/my-profile.component.html +++ b/src/app/features/my-profile/my-profile.component.html @@ -17,12 +17,14 @@

Member since: {{ currentUser()?.dateRegistered | date: '
- + @if (currentUser()?.social?.orcid) { + + }
cos-shield @@ -46,6 +48,59 @@

+
+ @if (currentUser()?.social?.github) { + github + } + @if (currentUser()?.social?.scholar) { + scholar + } + @if (currentUser()?.social?.twitter) { + twitter + } + @if (currentUser()?.social?.linkedIn) { + linkedin + } + @if (currentUser()?.social?.impactStory) { + impactstory + } + @if (currentUser()?.social?.baiduScholar) { + baidu + } + @if (currentUser()?.social?.researchGate) { + researchGate + } + @if (currentUser()?.social?.researcherId) { + researchId + } + @if (currentUser()?.social?.ssrn) { + ssrn + } + @if (currentUser()?.social?.academiaProfileID) { + ssrn + } +
+ @if (isMobile()) {
@@ -65,8 +120,12 @@

Employment

{{ employment.institution }}

- - + {{ createDate(employment.startYear, employment.startMonth) | date: 'MMM yyyy' }} - + @if (employment.ongoing) { + ongoing + } @else { + {{ createDate(employment.endYear!, employment.endMonth!) | date: 'MMM yyyy' }} + }

@@ -87,12 +146,12 @@

Education

{{ education.institution }}

- - - - - - + {{ createDate(education.startYear, education.startMonth) | date: 'MMM yyyy' }} - + @if (education.ongoing) { + ongoing + } @else { + {{ createDate(education.endYear!, education.endMonth!) | date: 'MMM yyyy' }} + }

@@ -106,4 +165,4 @@

Education

- + diff --git a/src/app/features/my-profile/my-profile.component.spec.ts b/src/app/features/my-profile/my-profile.component.spec.ts index 79717a06a..b99ac472b 100644 --- a/src/app/features/my-profile/my-profile.component.spec.ts +++ b/src/app/features/my-profile/my-profile.component.spec.ts @@ -14,7 +14,6 @@ import { Router } from '@angular/router'; import { SearchComponent } from '@osf/features/search/search.component'; import { ResetSearchState, SetIsMyProfile } from '@osf/features/search/store'; -import { ResetFiltersState } from '@osf/shared/components/resources/resource-filters/store/resource-filters.actions'; import { IS_XSMALL } from '@osf/shared/utils/breakpoints.tokens'; import { MyProfileComponent } from './my-profile.component'; diff --git a/src/app/features/my-profile/my-profile.component.ts b/src/app/features/my-profile/my-profile.component.ts index b4912e5aa..a8b541d79 100644 --- a/src/app/features/my-profile/my-profile.component.ts +++ b/src/app/features/my-profile/my-profile.component.ts @@ -4,25 +4,30 @@ import { AccordionModule } from 'primeng/accordion'; import { Button } from 'primeng/button'; import { DatePipe, NgOptimizedImage } from '@angular/common'; -import { ChangeDetectionStrategy, Component, effect, inject, OnDestroy, signal } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, OnDestroy, signal } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { UserSelectors } from '@osf/core/store/user/user.selectors'; +import { MyProfileSearchComponent } from '@osf/features/my-profile/components/my-profile-search/my-profile-search.component'; +import { ResetFiltersState } from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.actions'; import { ResetSearchState, SetIsMyProfile } from '@osf/features/search/store'; -import { - ResetFiltersState, - SetCreator, -} from '@osf/shared/components/resources/resource-filters/store/resource-filters.actions'; import { IS_XSMALL } from '@osf/shared/utils/breakpoints.tokens'; - -import { ResourceTab } from '../search/models/resource-tab.enum'; -import { SearchComponent } from '../search/search.component'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; @Component({ selector: 'osf-my-profile', - imports: [Button, DatePipe, NgOptimizedImage, AccordionModule, FormsModule, ReactiveFormsModule, SearchComponent], + standalone: true, + imports: [ + Button, + DatePipe, + NgOptimizedImage, + AccordionModule, + FormsModule, + ReactiveFormsModule, + MyProfileSearchComponent, + ], templateUrl: './my-profile.component.html', styleUrl: './my-profile.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, @@ -43,11 +48,11 @@ export class MyProfileComponent implements OnDestroy { } constructor() { - this.#store.dispatch(new SetIsMyProfile(true)); - - effect(() => { - this.#store.dispatch(new SetCreator(this.currentUser()?.fullName ?? '', this.currentUser()?.iri ?? '')); - }); + // this.#store.dispatch(new SetIsMyProfile(true)); + // + // effect(() => { + // this.#store.dispatch(new SetCreator(this.currentUser()?.fullName ?? '', this.currentUser()?.iri ?? '')); + // }); } ngOnDestroy(): void { @@ -55,4 +60,8 @@ export class MyProfileComponent implements OnDestroy { this.#store.dispatch(ResetSearchState); this.#store.dispatch(new SetIsMyProfile(false)); } + + protected createDate(year: number | string, month: number): Date { + return new Date(+year, month - 1); + } } diff --git a/src/app/features/my-profile/store/index.ts b/src/app/features/my-profile/store/index.ts new file mode 100644 index 000000000..98e372ac9 --- /dev/null +++ b/src/app/features/my-profile/store/index.ts @@ -0,0 +1,4 @@ +export * from './my-profile.actions'; +export * from './my-profile.model'; +export * from './my-profile.selectors'; +export * from './my-profile.state'; diff --git a/src/app/features/my-profile/store/my-profile.actions.ts b/src/app/features/my-profile/store/my-profile.actions.ts new file mode 100644 index 000000000..56a9b7df9 --- /dev/null +++ b/src/app/features/my-profile/store/my-profile.actions.ts @@ -0,0 +1,39 @@ +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; + +export class GetResources { + static readonly type = '[My Profile] Get Resources'; +} + +export class GetResourcesByLink { + static readonly type = '[My Profile] Get Resources By Link'; + + constructor(public link: string) {} +} + +export class GetResourcesCount { + static readonly type = '[My Profile] Get Resources Count'; +} + +export class SetSearchText { + static readonly type = '[My Profile] Set Search Text'; + + constructor(public searchText: string) {} +} + +export class SetSortBy { + static readonly type = '[My Profile] Set SortBy'; + + constructor(public sortBy: string) {} +} + +export class SetResourceTab { + static readonly type = '[My Profile] Set Resource Tab'; + + constructor(public resourceTab: ResourceTab) {} +} + +export class SetIsMyProfile { + static readonly type = '[My Profile] Set IsMyProfile'; + + constructor(public isMyProfile: boolean) {} +} diff --git a/src/app/features/my-profile/store/my-profile.model.ts b/src/app/features/my-profile/store/my-profile.model.ts new file mode 100644 index 000000000..038414d0f --- /dev/null +++ b/src/app/features/my-profile/store/my-profile.model.ts @@ -0,0 +1,14 @@ +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; + +export interface MyProfileStateModel { + resources: Resource[]; + resourcesCount: number; + searchText: string; + sortBy: string; + resourceTab: ResourceTab; + first: string; + next: string; + previous: string; + isMyProfile: boolean; +} diff --git a/src/app/features/my-profile/store/my-profile.selectors.ts b/src/app/features/my-profile/store/my-profile.selectors.ts new file mode 100644 index 000000000..ec37c5fdf --- /dev/null +++ b/src/app/features/my-profile/store/my-profile.selectors.ts @@ -0,0 +1,53 @@ +import { Selector } from '@ngxs/store'; + +import { MyProfileStateModel } from '@osf/features/my-profile/store/my-profile.model'; +import { MyProfileState } from '@osf/features/my-profile/store/my-profile.state'; +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; + +export class MyProfileSelectors { + @Selector([MyProfileState]) + static getResources(state: MyProfileStateModel): Resource[] { + return state.resources; + } + + @Selector([MyProfileState]) + static getResourcesCount(state: MyProfileStateModel): number { + return state.resourcesCount; + } + + @Selector([MyProfileState]) + static getSearchText(state: MyProfileStateModel): string { + return state.searchText; + } + + @Selector([MyProfileState]) + static getSortBy(state: MyProfileStateModel): string { + return state.sortBy; + } + + @Selector([MyProfileState]) + static getResourceTab(state: MyProfileStateModel): ResourceTab { + return state.resourceTab; + } + + @Selector([MyProfileState]) + static getFirst(state: MyProfileStateModel): string { + return state.first; + } + + @Selector([MyProfileState]) + static getNext(state: MyProfileStateModel): string { + return state.next; + } + + @Selector([MyProfileState]) + static getPrevious(state: MyProfileStateModel): string { + return state.previous; + } + + @Selector([MyProfileState]) + static getIsMyProfile(state: MyProfileStateModel): boolean { + return state.isMyProfile; + } +} diff --git a/src/app/features/my-profile/store/my-profile.state.ts b/src/app/features/my-profile/store/my-profile.state.ts new file mode 100644 index 000000000..9c3d9dd3f --- /dev/null +++ b/src/app/features/my-profile/store/my-profile.state.ts @@ -0,0 +1,90 @@ +import { Action, State, StateContext, Store } from '@ngxs/store'; + +import { tap } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { UserSelectors } from '@core/store/user/user.selectors'; +import { MyProfileResourceFiltersSelectors } from '@osf/features/my-profile/components/resources/components/resource-filters/store/my-profile-resource-filters.selectors'; +import { + GetResources, + GetResourcesByLink, + MyProfileSelectors, + MyProfileStateModel, + SetIsMyProfile, + SetResourceTab, + SetSearchText, + SetSortBy, +} from '@osf/features/my-profile/store'; +import { searchStateDefaults } from '@osf/features/search/utils/data'; +import { SearchService } from '@shared/services/search.service'; +import { addFiltersParams } from '@shared/utils/add-filters-params.helper'; +import { getResourceTypes } from '@shared/utils/get-resource-types.helper'; + +@Injectable() +@State({ + name: 'myProfile', + defaults: searchStateDefaults, +}) +export class MyProfileState { + searchService = inject(SearchService); + store = inject(Store); + currentUser = this.store.selectSignal(UserSelectors.getCurrentUser); + + @Action(GetResources) + getResources(ctx: StateContext) { + const filters = this.store.selectSnapshot(MyProfileResourceFiltersSelectors.getAllFilters); + const filtersParams = addFiltersParams(filters); + const searchText = this.store.selectSnapshot(MyProfileSelectors.getSearchText); + const sortBy = this.store.selectSnapshot(MyProfileSelectors.getSortBy); + const resourceTab = this.store.selectSnapshot(MyProfileSelectors.getResourceTab); + const resourceTypes = getResourceTypes(resourceTab); + const iri = this.currentUser()?.iri; + if (iri) { + filtersParams['cardSearchFilter[creator][]'] = iri; + } + + return this.searchService.getResources(filtersParams, searchText, sortBy, resourceTypes).pipe( + tap((response) => { + ctx.patchState({ resources: response.resources }); + ctx.patchState({ resourcesCount: response.count }); + ctx.patchState({ first: response.first }); + ctx.patchState({ next: response.next }); + ctx.patchState({ previous: response.previous }); + }) + ); + } + + @Action(GetResourcesByLink) + getResourcesByLink(ctx: StateContext, action: GetResourcesByLink) { + return this.searchService.getResourcesByLink(action.link).pipe( + tap((response) => { + ctx.patchState({ resources: response.resources }); + ctx.patchState({ resourcesCount: response.count }); + ctx.patchState({ first: response.first }); + ctx.patchState({ next: response.next }); + ctx.patchState({ previous: response.previous }); + }) + ); + } + + @Action(SetSearchText) + setSearchText(ctx: StateContext, action: SetSearchText) { + ctx.patchState({ searchText: action.searchText }); + } + + @Action(SetSortBy) + setSortBy(ctx: StateContext, action: SetSortBy) { + ctx.patchState({ sortBy: action.sortBy }); + } + + @Action(SetResourceTab) + setResourceTab(ctx: StateContext, action: SetResourceTab) { + ctx.patchState({ resourceTab: action.resourceTab }); + } + + @Action(SetIsMyProfile) + setIsMyProfile(ctx: StateContext, action: SetIsMyProfile) { + ctx.patchState({ isMyProfile: action.isMyProfile }); + } +} diff --git a/src/app/features/my-profile/utils/data.ts b/src/app/features/my-profile/utils/data.ts new file mode 100644 index 000000000..b76ff86d5 --- /dev/null +++ b/src/app/features/my-profile/utils/data.ts @@ -0,0 +1,13 @@ +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; + +export const myProfileStateDefaults = { + resources: [], + resourcesCount: 0, + searchText: '', + sortBy: '-relevance', + resourceTab: ResourceTab.All, + first: '', + next: '', + previous: '', + isMyProfile: false, +}; diff --git a/src/app/shared/components/resources/filter-chips/filter-chips.component.html b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.html similarity index 100% rename from src/app/shared/components/resources/filter-chips/filter-chips.component.html rename to src/app/features/search/components/resources/components/filter-chips/filter-chips.component.html diff --git a/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.scss b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.scss new file mode 100644 index 000000000..97920b501 --- /dev/null +++ b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.scss @@ -0,0 +1,13 @@ +:host { + display: flex; + flex-direction: column; + gap: 0.4rem; + + @media (max-width: 1200px) { + flex-direction: row; + } + + @media (max-width: 600px) { + flex-direction: column; + } +} diff --git a/src/app/shared/components/resources/filter-chips/filter-chips.component.spec.ts b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/filter-chips/filter-chips.component.spec.ts rename to src/app/features/search/components/resources/components/filter-chips/filter-chips.component.spec.ts diff --git a/src/app/shared/components/resources/filter-chips/filter-chips.component.ts b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.ts similarity index 86% rename from src/app/shared/components/resources/filter-chips/filter-chips.component.ts rename to src/app/features/search/components/resources/components/filter-chips/filter-chips.component.ts index 30a8dfd42..3d1c0144c 100644 --- a/src/app/shared/components/resources/filter-chips/filter-chips.component.ts +++ b/src/app/features/search/components/resources/components/filter-chips/filter-chips.component.ts @@ -5,9 +5,10 @@ import { Chip } from 'primeng/chip'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; import { SearchSelectors } from '@osf/features/search/store'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { FilterType } from '@shared/components/resources/resource-filters/models/filter-type.enum'; +import { FilterType } from '@shared/entities/filters/filter-type.enum'; + import { ResourceFiltersSelectors, SetCreator, @@ -19,7 +20,7 @@ import { SetProvider, SetResourceType, SetSubject, -} from '@shared/components/resources/resource-filters/store'; +} from 'src/app/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-filter-chips', diff --git a/src/app/shared/components/resources/resource-card/resource-card.component.html b/src/app/features/search/components/resources/components/resource-card/resource-card.component.html similarity index 100% rename from src/app/shared/components/resources/resource-card/resource-card.component.html rename to src/app/features/search/components/resources/components/resource-card/resource-card.component.html diff --git a/src/app/features/search/components/resources/components/resource-card/resource-card.component.scss b/src/app/features/search/components/resources/components/resource-card/resource-card.component.scss new file mode 100644 index 000000000..5859dee06 --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-card/resource-card.component.scss @@ -0,0 +1,5 @@ +@use "/app/shared/styles/resource-card/resource-card.scss" as resource-card; + +//:host { +// @extend .resource; +//} diff --git a/src/app/shared/components/resources/resource-card/resource-card.component.spec.ts b/src/app/features/search/components/resources/components/resource-card/resource-card.component.spec.ts similarity index 95% rename from src/app/shared/components/resources/resource-card/resource-card.component.spec.ts rename to src/app/features/search/components/resources/components/resource-card/resource-card.component.spec.ts index 5ab43c3c6..84c168f40 100644 --- a/src/app/shared/components/resources/resource-card/resource-card.component.spec.ts +++ b/src/app/features/search/components/resources/components/resource-card/resource-card.component.spec.ts @@ -9,7 +9,7 @@ import { IS_XSMALL } from '@osf/shared/utils/breakpoints.tokens'; import { ResourceCardComponent } from './resource-card.component'; import { ResourceCardService } from './resource-card.service'; -describe('ResourceCardComponent', () => { +describe('MyProfileResourceCardComponent', () => { let component: ResourceCardComponent; let fixture: ComponentFixture; diff --git a/src/app/shared/components/resources/resource-card/resource-card.component.ts b/src/app/features/search/components/resources/components/resource-card/resource-card.component.ts similarity index 83% rename from src/app/shared/components/resources/resource-card/resource-card.component.ts rename to src/app/features/search/components/resources/components/resource-card/resource-card.component.ts index 009c158f6..f52184319 100644 --- a/src/app/shared/components/resources/resource-card/resource-card.component.ts +++ b/src/app/features/search/components/resources/components/resource-card/resource-card.component.ts @@ -7,10 +7,10 @@ import { DatePipe, NgOptimizedImage } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject, model } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; -import { Resource } from '@osf/features/search/models/resource.entity'; -import { ResourceType } from '@osf/features/search/models/resource-type.enum'; -import { IS_XSMALL } from '@osf/shared/utils/breakpoints.tokens'; -import { ResourceCardService } from '@shared/components/resources/resource-card/resource-card.service'; +import { ResourceCardService } from '@osf/features/search/components/resources/components/resource-card/services/resource-card.service'; +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceType } from '@shared/entities/resource-card/resource-type.enum'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; @Component({ selector: 'osf-resource-card', diff --git a/src/app/shared/components/resources/resource-card/resource-card.service.ts b/src/app/features/search/components/resources/components/resource-card/services/resource-card.service.ts similarity index 61% rename from src/app/shared/components/resources/resource-card/resource-card.service.ts rename to src/app/features/search/components/resources/components/resource-card/services/resource-card.service.ts index 02c5ca5d0..ea786529b 100644 --- a/src/app/shared/components/resources/resource-card/resource-card.service.ts +++ b/src/app/features/search/components/resources/components/resource-card/services/resource-card.service.ts @@ -3,11 +3,11 @@ import { map, Observable } from 'rxjs'; import { inject, Injectable } from '@angular/core'; import { JsonApiService } from '@core/services/json-api/json-api.service'; -import { MapUserCounts } from '@shared/components/resources/resource-card/mappers/user-counts.mapper'; -import { UserCountsResponse } from '@shared/components/resources/resource-card/models/user-counts-response.entity'; -import { UserRelatedDataCounts } from '@shared/components/resources/resource-card/models/user-related-data-counts.entity'; +import { UserCountsResponse } from '@shared/entities/resource-card/user-counts-response.entity'; +import { UserRelatedDataCounts } from '@shared/entities/resource-card/user-related-data-counts.entity'; +import { MapUserCounts } from '@shared/helpers/mappers/resource-card/user-counts.mapper'; -import { environment } from '../../../../../environments/environment'; +import { environment } from '../../../../../../../../environments/environment'; @Injectable({ providedIn: 'root', diff --git a/src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.html rename to src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.html diff --git a/src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.scss rename to src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.scss diff --git a/src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.ts similarity index 85% rename from src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.ts index b9305ecef..701b5307d 100644 --- a/src/app/shared/components/resources/resource-filters/filters/creators/creators-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component.ts @@ -20,9 +20,12 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { GetAllOptions, GetCreatorsOptions, -} from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetCreator } from '@shared/components/resources/resource-filters/store'; +} from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetCreator, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-creators-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.html new file mode 100644 index 000000000..b6188ece4 --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.html @@ -0,0 +1,13 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.ts similarity index 77% rename from src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.ts index 3b0b094c0..47216d48c 100644 --- a/src/app/shared/components/resources/resource-filters/filters/date-created/date-created-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetDateCreated } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetDateCreated, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-date-created-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.html new file mode 100644 index 000000000..f2bba5e1f --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.ts similarity index 82% rename from src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.ts index 74645e052..7cbaf8f4f 100644 --- a/src/app/shared/components/resources/resource-filters/filters/funder/funder-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetFunder } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetFunder, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-funder-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.html new file mode 100644 index 000000000..0f59afc86 --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.scss similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.scss rename to src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.scss diff --git a/src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.ts similarity index 83% rename from src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.ts index 028067bf6..2611d1a58 100644 --- a/src/app/shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetInstitution } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetInstitution, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-institution-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.html new file mode 100644 index 000000000..ce0d34b4d --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.ts similarity index 82% rename from src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.ts index a6eeb7d0c..002dc831e 100644 --- a/src/app/shared/components/resources/resource-filters/filters/license-filter/license-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetLicense } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetLicense, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-license-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.html new file mode 100644 index 000000000..cd1ea9e8c --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.html @@ -0,0 +1,16 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.ts similarity index 81% rename from src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.ts index 1af25a598..0ac785fb7 100644 --- a/src/app/shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetPartOfCollection } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetPartOfCollection, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-part-of-collection-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.html new file mode 100644 index 000000000..3d299cdde --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.ts similarity index 82% rename from src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.ts index 81d2c15df..3278b0790 100644 --- a/src/app/shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetProvider } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetProvider, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-provider-filter', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.html new file mode 100644 index 000000000..d001451ad --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.ts similarity index 83% rename from src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.ts index 2c914a26e..cb9595569 100644 --- a/src/app/shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetResourceType } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetResourceType, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-resource-type-filter', diff --git a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.actions.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.actions.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions.ts diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model.ts new file mode 100644 index 000000000..eca6adc2d --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model.ts @@ -0,0 +1,21 @@ +import { Creator } from '@shared/entities/filters/creator/creator.entity'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { InstitutionFilter } from '@shared/entities/filters/institution/institution-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; + +export interface ResourceFiltersOptionsStateModel { + creators: Creator[]; + datesCreated: DateCreated[]; + funders: FunderFilter[]; + subjects: SubjectFilter[]; + licenses: LicenseFilter[]; + resourceTypes: ResourceTypeFilter[]; + institutions: InstitutionFilter[]; + providers: ProviderFilter[]; + partOfCollection: PartOfCollectionFilter[]; +} diff --git a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors.ts similarity index 55% rename from src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors.ts index 3165f0140..bf83d1f01 100644 --- a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors.ts @@ -1,16 +1,16 @@ import { Selector } from '@ngxs/store'; -import { ResourceFiltersOptionsStateModel } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.model'; -import { ResourceFiltersOptionsState } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.state'; -import { Creator } from '@shared/components/resources/resource-filters/models/creator/creator.entity'; -import { DateCreated } from '@shared/components/resources/resource-filters/models/dateCreated/date-created.entity'; -import { FunderFilter } from '@shared/components/resources/resource-filters/models/funder/funder-filter.entity'; -import { InstitutionFilter } from '@shared/components/resources/resource-filters/models/institution/institution-filter.entity'; -import { LicenseFilter } from '@shared/components/resources/resource-filters/models/license/license-filter.entity'; -import { PartOfCollectionFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity'; -import { ProviderFilter } from '@shared/components/resources/resource-filters/models/provider/provider-filter.entity'; -import { ResourceTypeFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type.entity'; -import { SubjectFilter } from '@shared/components/resources/resource-filters/models/subject/subject-filter.entity'; +import { ResourceFiltersOptionsStateModel } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model'; +import { ResourceFiltersOptionsState } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.state'; +import { Creator } from '@shared/entities/filters/creator/creator.entity'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { InstitutionFilter } from '@shared/entities/filters/institution/institution-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; export class ResourceFiltersOptionsSelectors { @Selector([ResourceFiltersOptionsState]) diff --git a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.state.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.state.ts similarity index 89% rename from src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.state.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.state.ts index 2329c5709..2a4967d6d 100644 --- a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.state.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.state.ts @@ -15,9 +15,9 @@ import { GetProvidersOptions, GetResourceTypesOptions, GetSubjectsOptions, -} from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsStateModel } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.model'; -import { ResourceFiltersService } from '@shared/components/resources/resource-filters/resource-filters.service'; +} from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsStateModel } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.model'; +import { ResourceFiltersService } from '@osf/features/search/components/resources/components/resource-filters/services/resource-filters.service'; @State({ name: 'resourceFiltersOptions', diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.html b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.html new file mode 100644 index 000000000..a33f1f7af --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.html @@ -0,0 +1,17 @@ + diff --git a/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.scss b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.spec.ts diff --git a/src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.ts b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.ts similarity index 82% rename from src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.ts rename to src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.ts index 1ecb03f2a..6214fb9a2 100644 --- a/src/app/shared/components/resources/resource-filters/filters/subject/subject-filter.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component.ts @@ -5,9 +5,12 @@ import { Select, SelectChangeEvent } from 'primeng/select'; import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { ResourceFiltersSelectors, SetSubject } from '@shared/components/resources/resource-filters/store'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { + ResourceFiltersSelectors, + SetSubject, +} from '@osf/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-subject-filter', diff --git a/src/app/shared/components/resources/resource-filters/resource-filters.component.html b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.html similarity index 100% rename from src/app/shared/components/resources/resource-filters/resource-filters.component.html rename to src/app/features/search/components/resources/components/resource-filters/resource-filters.component.html diff --git a/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.scss b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.scss new file mode 100644 index 000000000..1ab98caa2 --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.scss @@ -0,0 +1,15 @@ +@use "../../../../../../../assets/styles/variables" as var; + +:host { + width: 30%; + + .filters { + border: 1px solid var.$grey-2; + border-radius: 12px; + padding: 0 1.7rem 0 1.7rem; + display: flex; + flex-direction: column; + row-gap: 0.8rem; + height: fit-content; + } +} diff --git a/src/app/shared/components/resources/resource-filters/resource-filters.component.spec.ts b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.spec.ts similarity index 98% rename from src/app/shared/components/resources/resource-filters/resource-filters.component.spec.ts rename to src/app/features/search/components/resources/components/resource-filters/resource-filters.component.spec.ts index 01e32f265..678eb520f 100644 --- a/src/app/shared/components/resources/resource-filters/resource-filters.component.spec.ts +++ b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.spec.ts @@ -19,7 +19,7 @@ import { SubjectFilterComponent } from '@shared/components/resources/resource-fi import { ResourceFiltersComponent } from './resource-filters.component'; -describe('ResourceFiltersComponent', () => { +describe('MyProfileResourceFiltersComponent', () => { let component: ResourceFiltersComponent; let fixture: ComponentFixture; diff --git a/src/app/shared/components/resources/resource-filters/resource-filters.component.ts b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.ts similarity index 64% rename from src/app/shared/components/resources/resource-filters/resource-filters.component.ts rename to src/app/features/search/components/resources/components/resource-filters/resource-filters.component.ts index ed56a3991..c27fc65fb 100644 --- a/src/app/shared/components/resources/resource-filters/resource-filters.component.ts +++ b/src/app/features/search/components/resources/components/resource-filters/resource-filters.component.ts @@ -6,17 +6,17 @@ import { AutoCompleteModule } from 'primeng/autocomplete'; import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; +import { CreatorsFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/creators/creators-filter.component'; +import { DateCreatedFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/date-created/date-created-filter.component'; +import { FunderFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/funder/funder-filter.component'; +import { InstitutionFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/institution-filter/institution-filter.component'; +import { LicenseFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/license-filter/license-filter.component'; +import { PartOfCollectionFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/part-of-collection-filter/part-of-collection-filter.component'; +import { ProviderFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/provider-filter/provider-filter.component'; +import { ResourceTypeFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/resource-type-filter/resource-type-filter.component'; +import { ResourceFiltersOptionsSelectors } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.selectors'; +import { SubjectFilterComponent } from '@osf/features/search/components/resources/components/resource-filters/components/filters/subject/subject-filter.component'; import { SearchSelectors } from '@osf/features/search/store'; -import { CreatorsFilterComponent } from '@shared/components/resources/resource-filters/filters/creators/creators-filter.component'; -import { DateCreatedFilterComponent } from '@shared/components/resources/resource-filters/filters/date-created/date-created-filter.component'; -import { FunderFilterComponent } from '@shared/components/resources/resource-filters/filters/funder/funder-filter.component'; -import { InstitutionFilterComponent } from '@shared/components/resources/resource-filters/filters/institution-filter/institution-filter.component'; -import { LicenseFilterComponent } from '@shared/components/resources/resource-filters/filters/license-filter/license-filter.component'; -import { PartOfCollectionFilterComponent } from '@shared/components/resources/resource-filters/filters/part-of-collection-filter/part-of-collection-filter.component'; -import { ProviderFilterComponent } from '@shared/components/resources/resource-filters/filters/provider-filter/provider-filter.component'; -import { ResourceTypeFilterComponent } from '@shared/components/resources/resource-filters/filters/resource-type-filter/resource-type-filter.component'; -import { ResourceFiltersOptionsSelectors } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.selectors'; -import { SubjectFilterComponent } from '@shared/components/resources/resource-filters/filters/subject/subject-filter.component'; @Component({ selector: 'osf-resource-filters', diff --git a/src/app/features/search/components/resources/components/resource-filters/services/resource-filters.service.ts b/src/app/features/search/components/resources/components/resource-filters/services/resource-filters.service.ts new file mode 100644 index 000000000..46d68b119 --- /dev/null +++ b/src/app/features/search/components/resources/components/resource-filters/services/resource-filters.service.ts @@ -0,0 +1,83 @@ +import { Store } from '@ngxs/store'; + +import { Observable } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { SearchSelectors } from '@osf/features/search/store/search.selectors'; +import { FiltersOptionsService } from '@osf/shared/services/filters-options.service'; +import { Creator } from '@shared/entities/filters/creator/creator.entity'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; +import { addFiltersParams } from '@shared/utils/add-filters-params.helper'; +import { getResourceTypes } from '@shared/utils/get-resource-types.helper'; + +import { ResourceFiltersSelectors } from '../store/resource-filters.selectors'; + +@Injectable({ + providedIn: 'root', +}) +export class ResourceFiltersService { + #store = inject(Store); + #filtersOptions = inject(FiltersOptionsService); + + #getFilterParams(): Record { + return addFiltersParams(this.#store.selectSignal(ResourceFiltersSelectors.getAllFilters)()); + } + + #getParams(): Record { + const params: Record = {}; + const resourceTab = this.#store.selectSnapshot(SearchSelectors.getResourceTab); + const resourceTypes = getResourceTypes(resourceTab); + const searchText = this.#store.selectSnapshot(SearchSelectors.getSearchText); + const sort = this.#store.selectSnapshot(SearchSelectors.getSortBy); + + params['cardSearchFilter[resourceType]'] = resourceTypes; + params['cardSearchFilter[accessService]'] = 'https://staging4.osf.io/'; + params['cardSearchText[*,creator.name,isContainedBy.creator.name]'] = searchText; + params['page[size]'] = '10'; + params['sort'] = sort; + return params; + } + + getCreators(valueSearchText: string): Observable { + return this.#filtersOptions.getCreators(valueSearchText, this.#getParams(), this.#getFilterParams()); + } + + getDates(): Observable { + return this.#filtersOptions.getDates(this.#getParams(), this.#getFilterParams()); + } + + getFunders(): Observable { + return this.#filtersOptions.getFunders(this.#getParams(), this.#getFilterParams()); + } + + getSubjects(): Observable { + return this.#filtersOptions.getSubjects(this.#getParams(), this.#getFilterParams()); + } + + getLicenses(): Observable { + return this.#filtersOptions.getLicenses(this.#getParams(), this.#getFilterParams()); + } + + getResourceTypes(): Observable { + return this.#filtersOptions.getResourceTypes(this.#getParams(), this.#getFilterParams()); + } + + getInstitutions(): Observable { + return this.#filtersOptions.getInstitutions(this.#getParams(), this.#getFilterParams()); + } + + getProviders(): Observable { + return this.#filtersOptions.getProviders(this.#getParams(), this.#getFilterParams()); + } + + getPartOtCollections(): Observable { + return this.#filtersOptions.getPartOtCollections(this.#getParams(), this.#getFilterParams()); + } +} diff --git a/src/app/shared/components/resources/resource-filters/store/index.ts b/src/app/features/search/components/resources/components/resource-filters/store/index.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/store/index.ts rename to src/app/features/search/components/resources/components/resource-filters/store/index.ts diff --git a/src/app/shared/components/resources/resource-filters/store/resource-filters.actions.ts b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.actions.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/store/resource-filters.actions.ts rename to src/app/features/search/components/resources/components/resource-filters/store/resource-filters.actions.ts diff --git a/src/app/shared/components/resources/resource-filters/store/resource-filters.model.ts b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.model.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/store/resource-filters.model.ts rename to src/app/features/search/components/resources/components/resource-filters/store/resource-filters.model.ts diff --git a/src/app/shared/components/resources/resource-filters/store/resource-filters.selectors.ts b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.selectors.ts similarity index 86% rename from src/app/shared/components/resources/resource-filters/store/resource-filters.selectors.ts rename to src/app/features/search/components/resources/components/resource-filters/store/resource-filters.selectors.ts index 69d1e5213..605c41531 100644 --- a/src/app/shared/components/resources/resource-filters/store/resource-filters.selectors.ts +++ b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.selectors.ts @@ -3,8 +3,8 @@ import { Selector } from '@ngxs/store'; import { ResourceFilterLabel, ResourceFiltersStateModel, -} from '@shared/components/resources/resource-filters/store/resource-filters.model'; -import { ResourceFiltersState } from '@shared/components/resources/resource-filters/store/resource-filters.state'; +} from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.model'; +import { ResourceFiltersState } from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.state'; export class ResourceFiltersSelectors { @Selector([ResourceFiltersState]) diff --git a/src/app/shared/components/resources/resource-filters/store/resource-filters.state.ts b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.state.ts similarity index 73% rename from src/app/shared/components/resources/resource-filters/store/resource-filters.state.ts rename to src/app/features/search/components/resources/components/resource-filters/store/resource-filters.state.ts index b81694382..1d7375171 100644 --- a/src/app/shared/components/resources/resource-filters/store/resource-filters.state.ts +++ b/src/app/features/search/components/resources/components/resource-filters/store/resource-filters.state.ts @@ -2,7 +2,6 @@ import { Action, State, StateContext } from '@ngxs/store'; import { Injectable } from '@angular/core'; -import { FilterLabels } from '@shared/components/resources/resource-filters/models/filter-labels'; import { ResetFiltersState, SetCreator, @@ -14,14 +13,15 @@ import { SetProvider, SetResourceType, SetSubject, -} from '@shared/components/resources/resource-filters/store/resource-filters.actions'; -import { ResourceFiltersStateModel } from '@shared/components/resources/resource-filters/store/resource-filters.model'; -import { resourceFiltersDefaults } from '@shared/components/resources/resource-filters/utils/data'; +} from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.actions'; +import { ResourceFiltersStateModel } from '@osf/features/search/components/resources/components/resource-filters/store/resource-filters.model'; +import { FilterLabelsModel } from '@shared/utils/filter-labels.model'; +import { resourceFiltersDefaultsModel } from '@shared/utils/resource-filters-defaults.model'; // Store for user selected filters values @State({ name: 'resourceFilters', - defaults: resourceFiltersDefaults, + defaults: resourceFiltersDefaultsModel, }) @Injectable() export class ResourceFiltersState { @@ -29,7 +29,7 @@ export class ResourceFiltersState { setCreator(ctx: StateContext, action: SetCreator) { ctx.patchState({ creator: { - filterName: FilterLabels.creator, + filterName: FilterLabelsModel.creator, label: action.name, value: action.id, }, @@ -40,7 +40,7 @@ export class ResourceFiltersState { setDateCreated(ctx: StateContext, action: SetDateCreated) { ctx.patchState({ dateCreated: { - filterName: FilterLabels.dateCreated, + filterName: FilterLabelsModel.dateCreated, label: action.date, value: action.date, }, @@ -51,7 +51,7 @@ export class ResourceFiltersState { setFunder(ctx: StateContext, action: SetFunder) { ctx.patchState({ funder: { - filterName: FilterLabels.funder, + filterName: FilterLabelsModel.funder, label: action.funder, value: action.id, }, @@ -62,7 +62,7 @@ export class ResourceFiltersState { setSubject(ctx: StateContext, action: SetSubject) { ctx.patchState({ subject: { - filterName: FilterLabels.subject, + filterName: FilterLabelsModel.subject, label: action.subject, value: action.id, }, @@ -73,7 +73,7 @@ export class ResourceFiltersState { setLicense(ctx: StateContext, action: SetLicense) { ctx.patchState({ license: { - filterName: FilterLabels.license, + filterName: FilterLabelsModel.license, label: action.license, value: action.id, }, @@ -84,7 +84,7 @@ export class ResourceFiltersState { setResourceType(ctx: StateContext, action: SetResourceType) { ctx.patchState({ resourceType: { - filterName: FilterLabels.resourceType, + filterName: FilterLabelsModel.resourceType, label: action.resourceType, value: action.id, }, @@ -95,7 +95,7 @@ export class ResourceFiltersState { setInstitution(ctx: StateContext, action: SetInstitution) { ctx.patchState({ institution: { - filterName: FilterLabels.institution, + filterName: FilterLabelsModel.institution, label: action.institution, value: action.id, }, @@ -106,7 +106,7 @@ export class ResourceFiltersState { setProvider(ctx: StateContext, action: SetProvider) { ctx.patchState({ provider: { - filterName: FilterLabels.provider, + filterName: FilterLabelsModel.provider, label: action.provider, value: action.id, }, @@ -117,7 +117,7 @@ export class ResourceFiltersState { setPartOfCollection(ctx: StateContext, action: SetPartOfCollection) { ctx.patchState({ partOfCollection: { - filterName: FilterLabels.partOfCollection, + filterName: FilterLabelsModel.partOfCollection, label: action.partOfCollection, value: action.id, }, @@ -126,6 +126,6 @@ export class ResourceFiltersState { @Action(ResetFiltersState) resetState(ctx: StateContext) { - ctx.patchState(resourceFiltersDefaults); + ctx.patchState(resourceFiltersDefaultsModel); } } diff --git a/src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.html b/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.html similarity index 100% rename from src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.html rename to src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.html diff --git a/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.scss b/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.spec.ts b/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.spec.ts similarity index 100% rename from src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.spec.ts rename to src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.spec.ts diff --git a/src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.ts b/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.ts similarity index 91% rename from src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.ts rename to src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.ts index 26175b31b..46632c8b5 100644 --- a/src/app/shared/components/resources/resources-wrapper/resources-wrapper.component.ts +++ b/src/app/features/search/components/resources/components/resources-wrapper/resources-wrapper.component.ts @@ -5,10 +5,12 @@ import { take } from 'rxjs'; import { ChangeDetectionStrategy, Component, effect, inject, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourcesComponent } from '@osf/features/search/components/resources/resources.component'; import { SearchSelectors, SetResourceTab, SetSearchText, SetSortBy } from '@osf/features/search/store'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { FilterLabels } from '@shared/components/resources/resource-filters/models/filter-labels'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; +import { FilterLabelsModel } from '@shared/utils/filter-labels.model'; + import { ResourceFilterLabel, ResourceFiltersSelectors, @@ -21,8 +23,7 @@ import { SetProvider, SetResourceType, SetSubject, -} from '@shared/components/resources/resource-filters/store'; -import { ResourcesComponent } from '@shared/components/resources/resources.component'; +} from 'src/app/features/search/components/resources/components/resource-filters/store'; @Component({ selector: 'osf-resources-wrapper', @@ -75,14 +76,14 @@ export class ResourcesWrapperComponent implements OnInit { const search = params.get('search'); const resourceTab = params.get('resourceTab'); - const creator = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.creator); + const creator = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.creator); const dateCreated = filters.find((p: ResourceFilterLabel) => p.filterName === 'DateCreated'); - const funder = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.funder); - const subject = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.subject); - const license = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.license); + const funder = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.funder); + const subject = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.subject); + const license = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.license); const resourceType = filters.find((p: ResourceFilterLabel) => p.filterName === 'ResourceType'); - const institution = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.institution); - const provider = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabels.provider); + const institution = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.institution); + const provider = filters.find((p: ResourceFilterLabel) => p.filterName === FilterLabelsModel.provider); const partOfCollection = filters.find((p: ResourceFilterLabel) => p.filterName === 'PartOfCollection'); if (creator) { diff --git a/src/app/shared/components/resources/resources.component.html b/src/app/features/search/components/resources/resources.component.html similarity index 97% rename from src/app/shared/components/resources/resources.component.html rename to src/app/features/search/components/resources/resources.component.html index 283248fa8..77eac6339 100644 --- a/src/app/shared/components/resources/resources.component.html +++ b/src/app/features/search/components/resources/resources.component.html @@ -24,7 +24,7 @@

Sort by:

} @else { @if (isAnyFilterOptions()) { filter bySort by:

/> } sort by { let component: SearchComponent; let fixture: ComponentFixture; diff --git a/src/app/features/search/search.component.ts b/src/app/features/search/search.component.ts index b7f9b80f4..c4a5795e1 100644 --- a/src/app/features/search/search.component.ts +++ b/src/app/features/search/search.component.ts @@ -14,7 +14,8 @@ import { ChangeDetectionStrategy, Component, effect, inject, OnDestroy, signal, import { toObservable, toSignal } from '@angular/core/rxjs-interop'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { GetAllOptions } from '@osf/features/search/components/resources/components/resource-filters/components/filters/store/resource-filters-options.actions'; +import { ResourcesWrapperComponent } from '@osf/features/search/components/resources/components/resources-wrapper/resources-wrapper.component'; import { GetResources, ResetSearchState, @@ -22,12 +23,15 @@ import { SetResourceTab, SetSearchText, } from '@osf/features/search/store'; -import { GetAllOptions } from '@shared/components/resources/resource-filters/filters/store/resource-filters-options.actions'; -import { ResetFiltersState, ResourceFiltersSelectors } from '@shared/components/resources/resource-filters/store'; -import { ResourcesWrapperComponent } from '@shared/components/resources/resources-wrapper/resources-wrapper.component'; import { SearchInputComponent } from '@shared/components/search-input/search-input.component'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; +import { + ResetFiltersState, + ResourceFiltersSelectors, +} from 'src/app/features/search/components/resources/components/resource-filters/store'; + @Component({ selector: 'osf-search', imports: [ diff --git a/src/app/features/search/store/search.actions.ts b/src/app/features/search/store/search.actions.ts index f04dc736a..578c49838 100644 --- a/src/app/features/search/store/search.actions.ts +++ b/src/app/features/search/store/search.actions.ts @@ -1,4 +1,4 @@ -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; export class GetResources { static readonly type = '[Search] Get Resources'; diff --git a/src/app/features/search/store/search.model.ts b/src/app/features/search/store/search.model.ts index 7155f2c63..5b37f54ca 100644 --- a/src/app/features/search/store/search.model.ts +++ b/src/app/features/search/store/search.model.ts @@ -1,5 +1,5 @@ -import { Resource } from '@osf/features/search/models/resource.entity'; -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; export interface SearchStateModel { resources: Resource[]; diff --git a/src/app/features/search/store/search.selectors.ts b/src/app/features/search/store/search.selectors.ts index f87cfa12f..16b2085a6 100644 --- a/src/app/features/search/store/search.selectors.ts +++ b/src/app/features/search/store/search.selectors.ts @@ -1,9 +1,9 @@ import { Selector } from '@ngxs/store'; -import { Resource } from '@osf/features/search/models/resource.entity'; -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; import { SearchStateModel } from '@osf/features/search/store/search.model'; import { SearchState } from '@osf/features/search/store/search.state'; +import { Resource } from '@shared/entities/resource-card/resource.entity'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; export class SearchSelectors { @Selector([SearchState]) diff --git a/src/app/features/search/store/search.state.ts b/src/app/features/search/store/search.state.ts index c1663c094..6e468ee40 100644 --- a/src/app/features/search/store/search.state.ts +++ b/src/app/features/search/store/search.state.ts @@ -4,7 +4,6 @@ import { tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; -import { SearchService } from '@osf/features/search/search.service'; import { GetResources, GetResourcesByLink, @@ -17,9 +16,11 @@ import { import { SearchStateModel } from '@osf/features/search/store/search.model'; import { SearchSelectors } from '@osf/features/search/store/search.selectors'; import { searchStateDefaults } from '@osf/features/search/utils/data'; -import { getResourceTypes } from '@osf/features/search/utils/helpers/get-resource-types.helper'; -import { ResourceFiltersSelectors } from '@shared/components/resources/resource-filters/store'; -import { addFiltersParams } from '@shared/components/resources/resource-filters/utils/add-filters-params.helper'; +import { SearchService } from '@shared/services/search.service'; +import { addFiltersParams } from '@shared/utils/add-filters-params.helper'; +import { getResourceTypes } from '@shared/utils/get-resource-types.helper'; + +import { ResourceFiltersSelectors } from 'src/app/features/search/components/resources/components/resource-filters/store'; @Injectable() @State({ diff --git a/src/app/features/search/utils/data.ts b/src/app/features/search/utils/data.ts index aaade4442..f030bdeb9 100644 --- a/src/app/features/search/utils/data.ts +++ b/src/app/features/search/utils/data.ts @@ -1,4 +1,4 @@ -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; export const searchStateDefaults = { resources: [], diff --git a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.model.ts b/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.model.ts deleted file mode 100644 index 428e66b94..000000000 --- a/src/app/shared/components/resources/resource-filters/filters/store/resource-filters-options.model.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Creator } from '@shared/components/resources/resource-filters/models/creator/creator.entity'; -import { DateCreated } from '@shared/components/resources/resource-filters/models/dateCreated/date-created.entity'; -import { FunderFilter } from '@shared/components/resources/resource-filters/models/funder/funder-filter.entity'; -import { InstitutionFilter } from '@shared/components/resources/resource-filters/models/institution/institution-filter.entity'; -import { LicenseFilter } from '@shared/components/resources/resource-filters/models/license/license-filter.entity'; -import { PartOfCollectionFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity'; -import { ProviderFilter } from '@shared/components/resources/resource-filters/models/provider/provider-filter.entity'; -import { ResourceTypeFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type.entity'; -import { SubjectFilter } from '@shared/components/resources/resource-filters/models/subject/subject-filter.entity'; - -export interface ResourceFiltersOptionsStateModel { - creators: Creator[]; - datesCreated: DateCreated[]; - funders: FunderFilter[]; - subjects: SubjectFilter[]; - licenses: LicenseFilter[]; - resourceTypes: ResourceTypeFilter[]; - institutions: InstitutionFilter[]; - providers: ProviderFilter[]; - partOfCollection: PartOfCollectionFilter[]; -} diff --git a/src/app/shared/components/resources/resource-filters/mappers/creators/creators.mappers.ts b/src/app/shared/components/resources/resource-filters/mappers/creators/creators.mappers.ts deleted file mode 100644 index 2615cc553..000000000 --- a/src/app/shared/components/resources/resource-filters/mappers/creators/creators.mappers.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Creator } from '@shared/components/resources/resource-filters/models/creator/creator.entity'; -import { CreatorItem } from '@shared/components/resources/resource-filters/models/creator/creator-item.entity'; - -export function MapCreators(rawItem: CreatorItem): Creator { - return { - id: rawItem?.['@id'], - name: rawItem?.name?.[0]?.['@value'], - }; -} diff --git a/src/app/shared/components/resources/resource-filters/models/funder/funder-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/funder/funder-index-value-search.entity.ts deleted file mode 100644 index db9e4d4f3..000000000 --- a/src/app/shared/components/resources/resource-filters/models/funder/funder-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FunderIndexCardFilter } from '@shared/components/resources/resource-filters/models/funder/funder-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type FunderIndexValueSearch = SearchResultCount | FunderIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/index-value-search.entity.ts deleted file mode 100644 index c09f5bbd3..000000000 --- a/src/app/shared/components/resources/resource-filters/models/index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { IndexCardFilter } from '@shared/components/resources/resource-filters/models/index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type IndexValueSearch = SearchResultCount | IndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/institution/institution-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/institution/institution-index-value-search.entity.ts deleted file mode 100644 index 75f4649f8..000000000 --- a/src/app/shared/components/resources/resource-filters/models/institution/institution-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { InstitutionIndexCardFilter } from '@shared/components/resources/resource-filters/models/institution/institution-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type InstitutionIndexValueSearch = SearchResultCount | InstitutionIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/license/license-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/license/license-index-value-search.entity.ts deleted file mode 100644 index 2f2275125..000000000 --- a/src/app/shared/components/resources/resource-filters/models/license/license-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { LicenseIndexCardFilter } from '@shared/components/resources/resource-filters/models/license/license-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type LicenseIndexValueSearch = SearchResultCount | LicenseIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-value-search.entity.ts deleted file mode 100644 index 18add9ae1..000000000 --- a/src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { PartOfCollectionIndexCardFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type PartOfCollectionIndexValueSearch = SearchResultCount | PartOfCollectionIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/provider/provider-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/provider/provider-index-value-search.entity.ts deleted file mode 100644 index 0a20d358d..000000000 --- a/src/app/shared/components/resources/resource-filters/models/provider/provider-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { ProviderIndexCardFilter } from '@shared/components/resources/resource-filters/models/provider/provider-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type ProviderIndexValueSearch = SearchResultCount | ProviderIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/resource-type/resource-type-index-value-search.entity.ts b/src/app/shared/components/resources/resource-filters/models/resource-type/resource-type-index-value-search.entity.ts deleted file mode 100644 index bc3dc6d4f..000000000 --- a/src/app/shared/components/resources/resource-filters/models/resource-type/resource-type-index-value-search.entity.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { ResourceTypeIndexCardFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type-index-card-filter.entity'; -import { SearchResultCount } from '@shared/components/resources/resource-filters/models/search-result-count.entity'; - -export type ResourceTypeIndexValueSearch = SearchResultCount | ResourceTypeIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/resource-filters.service.ts b/src/app/shared/components/resources/resource-filters/resource-filters.service.ts deleted file mode 100644 index 1582b78ac..000000000 --- a/src/app/shared/components/resources/resource-filters/resource-filters.service.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Store } from '@ngxs/store'; - -import { map, Observable } from 'rxjs'; - -import { inject, Injectable } from '@angular/core'; - -import { ApiData, JsonApiResponse } from '@core/services/json-api/json-api.entity'; -import { JsonApiService } from '@core/services/json-api/json-api.service'; -import { SearchSelectors } from '@osf/features/search/store'; -import { getResourceTypes } from '@osf/features/search/utils/helpers/get-resource-types.helper'; -import { MapCreators } from '@shared/components/resources/resource-filters/mappers/creators/creators.mappers'; -import { MapDateCreated } from '@shared/components/resources/resource-filters/mappers/dateCreated/date-created.mapper'; -import { MapFunders } from '@shared/components/resources/resource-filters/mappers/funder/funder.mapper'; -import { MapInstitutions } from '@shared/components/resources/resource-filters/mappers/institution/institution.mapper'; -import { MapLicenses } from '@shared/components/resources/resource-filters/mappers/license/license.mapper'; -import { MapPartOfCollections } from '@shared/components/resources/resource-filters/mappers/part-of-collection/part-of-collection.mapper'; -import { MapProviders } from '@shared/components/resources/resource-filters/mappers/provider/provider.mapper'; -import { MapResourceType } from '@shared/components/resources/resource-filters/mappers/resource-type/resource-type.mapper'; -import { MapSubject } from '@shared/components/resources/resource-filters/mappers/subject/subject.mapper'; -import { Creator } from '@shared/components/resources/resource-filters/models/creator/creator.entity'; -import { CreatorItem } from '@shared/components/resources/resource-filters/models/creator/creator-item.entity'; -import { DateCreated } from '@shared/components/resources/resource-filters/models/dateCreated/date-created.entity'; -import { FunderFilter } from '@shared/components/resources/resource-filters/models/funder/funder-filter.entity'; -import { FunderIndexValueSearch } from '@shared/components/resources/resource-filters/models/funder/funder-index-value-search.entity'; -import { IndexValueSearch } from '@shared/components/resources/resource-filters/models/index-value-search.entity'; -import { InstitutionIndexValueSearch } from '@shared/components/resources/resource-filters/models/institution/institution-index-value-search.entity'; -import { LicenseFilter } from '@shared/components/resources/resource-filters/models/license/license-filter.entity'; -import { LicenseIndexValueSearch } from '@shared/components/resources/resource-filters/models/license/license-index-value-search.entity'; -import { PartOfCollectionFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity'; -import { PartOfCollectionIndexValueSearch } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-value-search.entity'; -import { ProviderFilter } from '@shared/components/resources/resource-filters/models/provider/provider-filter.entity'; -import { ProviderIndexValueSearch } from '@shared/components/resources/resource-filters/models/provider/provider-index-value-search.entity'; -import { ResourceTypeFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type.entity'; -import { ResourceTypeIndexValueSearch } from '@shared/components/resources/resource-filters/models/resource-type/resource-type-index-value-search.entity'; -import { SubjectFilter } from '@shared/components/resources/resource-filters/models/subject/subject-filter.entity'; -import { ResourceFiltersSelectors } from '@shared/components/resources/resource-filters/store'; -import { addFiltersParams } from '@shared/components/resources/resource-filters/utils/add-filters-params.helper'; - -import { environment } from '../../../../../environments/environment'; - -@Injectable({ - providedIn: 'root', -}) -export class ResourceFiltersService { - #jsonApiService = inject(JsonApiService); - #store = inject(Store); - - #getFilterParams(): Record { - return addFiltersParams(this.#store.selectSignal(ResourceFiltersSelectors.getAllFilters)()); - } - - #getParams(): Record { - const params: Record = {}; - const resourceTab = this.#store.selectSnapshot(SearchSelectors.getResourceTab); - const resourceTypes = getResourceTypes(resourceTab); - const searchText = this.#store.selectSnapshot(SearchSelectors.getSearchText); - const sort = this.#store.selectSnapshot(SearchSelectors.getSortBy); - - params['cardSearchFilter[resourceType]'] = resourceTypes; - params['cardSearchFilter[accessService]'] = 'https://staging4.osf.io/'; - params['cardSearchText[*,creator.name,isContainedBy.creator.name]'] = searchText; - params['page[size]'] = '10'; - params['sort'] = sort; - return params; - } - - getCreators(valueSearchText: string): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'creator', - valueSearchText, - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse[]> - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe( - map((response) => { - const included = (response?.included ?? []) as ApiData<{ resourceMetadata: CreatorItem }, null, null>[]; - return included - .filter((item) => item.type === 'index-card') - .map((item) => MapCreators(item.attributes.resourceMetadata)); - }) - ); - } - - getDates(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'dateCreated', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get>(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapDateCreated(response?.included ?? []))); - } - - getFunders(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'funder', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapFunders(response?.included ?? []))); - } - - getSubjects(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'subject', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get>(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapSubject(response?.included ?? []))); - } - - getLicenses(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'rights', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapLicenses(response?.included ?? []))); - } - - getResourceTypes(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'resourceNature', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapResourceType(response?.included ?? []))); - } - - getInstitutions(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'affiliation', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapInstitutions(response?.included ?? []))); - } - - getProviders(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'publisher', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapProviders(response?.included ?? []))); - } - - getPartOtCollections(): Observable { - const dynamicParams = { - valueSearchPropertyPath: 'isPartOfCollection', - }; - - const fullParams = { - ...this.#getParams(), - ...this.#getFilterParams(), - ...dynamicParams, - }; - - return this.#jsonApiService - .get< - JsonApiResponse - >(`${environment.shareDomainUrl}/index-value-search`, fullParams) - .pipe(map((response) => MapPartOfCollections(response?.included ?? []))); - } -} diff --git a/src/app/shared/components/resources/resource-filters/models/creator/creator-item.entity.ts b/src/app/shared/entities/filters/creator/creator-item.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/creator/creator-item.entity.ts rename to src/app/shared/entities/filters/creator/creator-item.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/creator/creator.entity.ts b/src/app/shared/entities/filters/creator/creator.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/creator/creator.entity.ts rename to src/app/shared/entities/filters/creator/creator.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/dateCreated/date-created.entity.ts b/src/app/shared/entities/filters/dateCreated/date-created.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/dateCreated/date-created.entity.ts rename to src/app/shared/entities/filters/dateCreated/date-created.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/dateCreated/date-index-card.entity.ts b/src/app/shared/entities/filters/dateCreated/date-index-card.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/dateCreated/date-index-card.entity.ts rename to src/app/shared/entities/filters/dateCreated/date-index-card.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/filter-type.enum.ts b/src/app/shared/entities/filters/filter-type.enum.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/filter-type.enum.ts rename to src/app/shared/entities/filters/filter-type.enum.ts diff --git a/src/app/shared/components/resources/resource-filters/models/funder/funder-filter.entity.ts b/src/app/shared/entities/filters/funder/funder-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/funder/funder-filter.entity.ts rename to src/app/shared/entities/filters/funder/funder-filter.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/funder/funder-index-card-filter.entity.ts b/src/app/shared/entities/filters/funder/funder-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/funder/funder-index-card-filter.entity.ts rename to src/app/shared/entities/filters/funder/funder-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/funder/funder-index-value-search.entity.ts b/src/app/shared/entities/filters/funder/funder-index-value-search.entity.ts new file mode 100644 index 000000000..02abf1118 --- /dev/null +++ b/src/app/shared/entities/filters/funder/funder-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { FunderIndexCardFilter } from '@shared/entities/filters/funder/funder-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type FunderIndexValueSearch = SearchResultCount | FunderIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/index-card-filter.entity.ts b/src/app/shared/entities/filters/index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/index-card-filter.entity.ts rename to src/app/shared/entities/filters/index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/index-value-search.entity.ts b/src/app/shared/entities/filters/index-value-search.entity.ts new file mode 100644 index 000000000..d397bff51 --- /dev/null +++ b/src/app/shared/entities/filters/index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { IndexCardFilter } from '@shared/entities/filters/index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type IndexValueSearch = SearchResultCount | IndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/institution/institution-filter.entity.ts b/src/app/shared/entities/filters/institution/institution-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/institution/institution-filter.entity.ts rename to src/app/shared/entities/filters/institution/institution-filter.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/institution/institution-index-card-filter.entity.ts b/src/app/shared/entities/filters/institution/institution-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/institution/institution-index-card-filter.entity.ts rename to src/app/shared/entities/filters/institution/institution-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/institution/institution-index-value-search.entity.ts b/src/app/shared/entities/filters/institution/institution-index-value-search.entity.ts new file mode 100644 index 000000000..131adf260 --- /dev/null +++ b/src/app/shared/entities/filters/institution/institution-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { InstitutionIndexCardFilter } from '@shared/entities/filters/institution/institution-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type InstitutionIndexValueSearch = SearchResultCount | InstitutionIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/license/license-filter.entity.ts b/src/app/shared/entities/filters/license/license-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/license/license-filter.entity.ts rename to src/app/shared/entities/filters/license/license-filter.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/license/license-index-card-filter.entity.ts b/src/app/shared/entities/filters/license/license-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/license/license-index-card-filter.entity.ts rename to src/app/shared/entities/filters/license/license-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/license/license-index-value-search.entity.ts b/src/app/shared/entities/filters/license/license-index-value-search.entity.ts new file mode 100644 index 000000000..344b5ed80 --- /dev/null +++ b/src/app/shared/entities/filters/license/license-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { LicenseIndexCardFilter } from '@shared/entities/filters/license/license-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type LicenseIndexValueSearch = SearchResultCount | LicenseIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity.ts b/src/app/shared/entities/filters/part-of-collection/part-of-collection-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity.ts rename to src/app/shared/entities/filters/part-of-collection/part-of-collection-filter.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-card-filter.entity.ts b/src/app/shared/entities/filters/part-of-collection/part-of-collection-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-card-filter.entity.ts rename to src/app/shared/entities/filters/part-of-collection/part-of-collection-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/part-of-collection/part-of-collection-index-value-search.entity.ts b/src/app/shared/entities/filters/part-of-collection/part-of-collection-index-value-search.entity.ts new file mode 100644 index 000000000..41ba6fdb8 --- /dev/null +++ b/src/app/shared/entities/filters/part-of-collection/part-of-collection-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { PartOfCollectionIndexCardFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type PartOfCollectionIndexValueSearch = SearchResultCount | PartOfCollectionIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/provider/provider-filter.entity.ts b/src/app/shared/entities/filters/provider/provider-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/provider/provider-filter.entity.ts rename to src/app/shared/entities/filters/provider/provider-filter.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/provider/provider-index-card-filter.entity.ts b/src/app/shared/entities/filters/provider/provider-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/provider/provider-index-card-filter.entity.ts rename to src/app/shared/entities/filters/provider/provider-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/provider/provider-index-value-search.entity.ts b/src/app/shared/entities/filters/provider/provider-index-value-search.entity.ts new file mode 100644 index 000000000..aaf894550 --- /dev/null +++ b/src/app/shared/entities/filters/provider/provider-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { ProviderIndexCardFilter } from '@shared/entities/filters/provider/provider-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type ProviderIndexValueSearch = SearchResultCount | ProviderIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/resource-type/resource-type-index-card-filter.entity.ts b/src/app/shared/entities/filters/resource-type/resource-type-index-card-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/resource-type/resource-type-index-card-filter.entity.ts rename to src/app/shared/entities/filters/resource-type/resource-type-index-card-filter.entity.ts diff --git a/src/app/shared/entities/filters/resource-type/resource-type-index-value-search.entity.ts b/src/app/shared/entities/filters/resource-type/resource-type-index-value-search.entity.ts new file mode 100644 index 000000000..b05419104 --- /dev/null +++ b/src/app/shared/entities/filters/resource-type/resource-type-index-value-search.entity.ts @@ -0,0 +1,4 @@ +import { ResourceTypeIndexCardFilter } from '@shared/entities/filters/resource-type/resource-type-index-card-filter.entity'; +import { SearchResultCount } from '@shared/entities/filters/search-result-count.entity'; + +export type ResourceTypeIndexValueSearch = SearchResultCount | ResourceTypeIndexCardFilter; diff --git a/src/app/shared/components/resources/resource-filters/models/resource-type/resource-type.entity.ts b/src/app/shared/entities/filters/resource-type/resource-type.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/resource-type/resource-type.entity.ts rename to src/app/shared/entities/filters/resource-type/resource-type.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/search-result-count.entity.ts b/src/app/shared/entities/filters/search-result-count.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/search-result-count.entity.ts rename to src/app/shared/entities/filters/search-result-count.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/subject/subject-filter-response.entity.ts b/src/app/shared/entities/filters/subject/subject-filter-response.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/subject/subject-filter-response.entity.ts rename to src/app/shared/entities/filters/subject/subject-filter-response.entity.ts diff --git a/src/app/shared/components/resources/resource-filters/models/subject/subject-filter.entity.ts b/src/app/shared/entities/filters/subject/subject-filter.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-filters/models/subject/subject-filter.entity.ts rename to src/app/shared/entities/filters/subject/subject-filter.entity.ts diff --git a/src/app/features/search/models/resource-tab.enum.ts b/src/app/shared/entities/resource-card/resource-tab.enum.ts similarity index 100% rename from src/app/features/search/models/resource-tab.enum.ts rename to src/app/shared/entities/resource-card/resource-tab.enum.ts diff --git a/src/app/features/search/models/resource-type.enum.ts b/src/app/shared/entities/resource-card/resource-type.enum.ts similarity index 100% rename from src/app/features/search/models/resource-type.enum.ts rename to src/app/shared/entities/resource-card/resource-type.enum.ts diff --git a/src/app/features/search/models/resource.entity.ts b/src/app/shared/entities/resource-card/resource.entity.ts similarity index 90% rename from src/app/features/search/models/resource.entity.ts rename to src/app/shared/entities/resource-card/resource.entity.ts index 7329bd52d..0c513791b 100644 --- a/src/app/features/search/models/resource.entity.ts +++ b/src/app/shared/entities/resource-card/resource.entity.ts @@ -1,5 +1,5 @@ import { LinkItem } from '@osf/features/search/models/link-item.entity'; -import { ResourceType } from '@osf/features/search/models/resource-type.enum'; +import { ResourceType } from '@shared/entities/resource-card/resource-type.enum'; export interface Resource { id: string; diff --git a/src/app/shared/components/resources/resource-card/models/user-counts-response.entity.ts b/src/app/shared/entities/resource-card/user-counts-response.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-card/models/user-counts-response.entity.ts rename to src/app/shared/entities/resource-card/user-counts-response.entity.ts diff --git a/src/app/shared/components/resources/resource-card/models/user-related-data-counts.entity.ts b/src/app/shared/entities/resource-card/user-related-data-counts.entity.ts similarity index 100% rename from src/app/shared/components/resources/resource-card/models/user-related-data-counts.entity.ts rename to src/app/shared/entities/resource-card/user-related-data-counts.entity.ts diff --git a/src/app/shared/helpers/mappers/filters/creators/creators.mappers.ts b/src/app/shared/helpers/mappers/filters/creators/creators.mappers.ts new file mode 100644 index 000000000..20e779abc --- /dev/null +++ b/src/app/shared/helpers/mappers/filters/creators/creators.mappers.ts @@ -0,0 +1,9 @@ +import { Creator } from '@shared/entities/filters/creator/creator.entity'; +import { CreatorItem } from '@shared/entities/filters/creator/creator-item.entity'; + +export function MapCreators(rawItem: CreatorItem): Creator { + return { + id: rawItem?.['@id'], + name: rawItem?.name?.[0]?.['@value'], + }; +} diff --git a/src/app/shared/components/resources/resource-filters/mappers/dateCreated/date-created.mapper.ts b/src/app/shared/helpers/mappers/filters/dateCreated/date-created.mapper.ts similarity index 61% rename from src/app/shared/components/resources/resource-filters/mappers/dateCreated/date-created.mapper.ts rename to src/app/shared/helpers/mappers/filters/dateCreated/date-created.mapper.ts index 736d1769d..96050b7ce 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/dateCreated/date-created.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/dateCreated/date-created.mapper.ts @@ -1,6 +1,6 @@ -import { DateCreated } from '@shared/components/resources/resource-filters/models/dateCreated/date-created.entity'; -import { IndexCardFilter } from '@shared/components/resources/resource-filters/models/index-card-filter.entity'; -import { IndexValueSearch } from '@shared/components/resources/resource-filters/models/index-value-search.entity'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { IndexCardFilter } from '@shared/entities/filters/index-card-filter.entity'; +import { IndexValueSearch } from '@shared/entities/filters/index-value-search.entity'; export function MapDateCreated(items: IndexValueSearch[]): DateCreated[] { const datesCreated: DateCreated[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/funder/funder.mapper.ts b/src/app/shared/helpers/mappers/filters/funder/funder.mapper.ts similarity index 62% rename from src/app/shared/components/resources/resource-filters/mappers/funder/funder.mapper.ts rename to src/app/shared/helpers/mappers/filters/funder/funder.mapper.ts index 65062ed2b..a260e3c9e 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/funder/funder.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/funder/funder.mapper.ts @@ -1,6 +1,6 @@ -import { FunderFilter } from '@shared/components/resources/resource-filters/models/funder/funder-filter.entity'; -import { FunderIndexCardFilter } from '@shared/components/resources/resource-filters/models/funder/funder-index-card-filter.entity'; -import { FunderIndexValueSearch } from '@shared/components/resources/resource-filters/models/funder/funder-index-value-search.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { FunderIndexCardFilter } from '@shared/entities/filters/funder/funder-index-card-filter.entity'; +import { FunderIndexValueSearch } from '@shared/entities/filters/funder/funder-index-value-search.entity'; export function MapFunders(items: FunderIndexValueSearch[]): FunderFilter[] { const funders: FunderFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/institution/institution.mapper.ts b/src/app/shared/helpers/mappers/filters/institution/institution.mapper.ts similarity index 61% rename from src/app/shared/components/resources/resource-filters/mappers/institution/institution.mapper.ts rename to src/app/shared/helpers/mappers/filters/institution/institution.mapper.ts index e9c34df34..aa53aa3e6 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/institution/institution.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/institution/institution.mapper.ts @@ -1,6 +1,6 @@ -import { InstitutionFilter } from '@shared/components/resources/resource-filters/models/institution/institution-filter.entity'; -import { InstitutionIndexCardFilter } from '@shared/components/resources/resource-filters/models/institution/institution-index-card-filter.entity'; -import { InstitutionIndexValueSearch } from '@shared/components/resources/resource-filters/models/institution/institution-index-value-search.entity'; +import { InstitutionFilter } from '@shared/entities/filters/institution/institution-filter.entity'; +import { InstitutionIndexCardFilter } from '@shared/entities/filters/institution/institution-index-card-filter.entity'; +import { InstitutionIndexValueSearch } from '@shared/entities/filters/institution/institution-index-value-search.entity'; export function MapInstitutions(items: InstitutionIndexValueSearch[]): InstitutionFilter[] { const institutions: InstitutionFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/license/license.mapper.ts b/src/app/shared/helpers/mappers/filters/license/license.mapper.ts similarity index 61% rename from src/app/shared/components/resources/resource-filters/mappers/license/license.mapper.ts rename to src/app/shared/helpers/mappers/filters/license/license.mapper.ts index 287e8e2b0..8841c5a17 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/license/license.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/license/license.mapper.ts @@ -1,6 +1,6 @@ -import { LicenseFilter } from '@shared/components/resources/resource-filters/models/license/license-filter.entity'; -import { LicenseIndexCardFilter } from '@shared/components/resources/resource-filters/models/license/license-index-card-filter.entity'; -import { LicenseIndexValueSearch } from '@shared/components/resources/resource-filters/models/license/license-index-value-search.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { LicenseIndexCardFilter } from '@shared/entities/filters/license/license-index-card-filter.entity'; +import { LicenseIndexValueSearch } from '@shared/entities/filters/license/license-index-value-search.entity'; export function MapLicenses(items: LicenseIndexValueSearch[]): LicenseFilter[] { const licenses: LicenseFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/part-of-collection/part-of-collection.mapper.ts b/src/app/shared/helpers/mappers/filters/part-of-collection/part-of-collection.mapper.ts similarity index 59% rename from src/app/shared/components/resources/resource-filters/mappers/part-of-collection/part-of-collection.mapper.ts rename to src/app/shared/helpers/mappers/filters/part-of-collection/part-of-collection.mapper.ts index 397d166fe..27d2337ea 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/part-of-collection/part-of-collection.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/part-of-collection/part-of-collection.mapper.ts @@ -1,6 +1,6 @@ -import { PartOfCollectionFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-filter.entity'; -import { PartOfCollectionIndexCardFilter } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-card-filter.entity'; -import { PartOfCollectionIndexValueSearch } from '@shared/components/resources/resource-filters/models/part-of-collection/part-of-collection-index-value-search.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { PartOfCollectionIndexCardFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-index-card-filter.entity'; +import { PartOfCollectionIndexValueSearch } from '@shared/entities/filters/part-of-collection/part-of-collection-index-value-search.entity'; export function MapPartOfCollections(items: PartOfCollectionIndexValueSearch[]): PartOfCollectionFilter[] { const partOfCollections: PartOfCollectionFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/provider/provider.mapper.ts b/src/app/shared/helpers/mappers/filters/provider/provider.mapper.ts similarity index 61% rename from src/app/shared/components/resources/resource-filters/mappers/provider/provider.mapper.ts rename to src/app/shared/helpers/mappers/filters/provider/provider.mapper.ts index 46eca9156..de268c0be 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/provider/provider.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/provider/provider.mapper.ts @@ -1,6 +1,6 @@ -import { ProviderFilter } from '@shared/components/resources/resource-filters/models/provider/provider-filter.entity'; -import { ProviderIndexCardFilter } from '@shared/components/resources/resource-filters/models/provider/provider-index-card-filter.entity'; -import { ProviderIndexValueSearch } from '@shared/components/resources/resource-filters/models/provider/provider-index-value-search.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ProviderIndexCardFilter } from '@shared/entities/filters/provider/provider-index-card-filter.entity'; +import { ProviderIndexValueSearch } from '@shared/entities/filters/provider/provider-index-value-search.entity'; export function MapProviders(items: ProviderIndexValueSearch[]): ProviderFilter[] { const providers: ProviderFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/resource-type/resource-type.mapper.ts b/src/app/shared/helpers/mappers/filters/resource-type/resource-type.mapper.ts similarity index 61% rename from src/app/shared/components/resources/resource-filters/mappers/resource-type/resource-type.mapper.ts rename to src/app/shared/helpers/mappers/filters/resource-type/resource-type.mapper.ts index 9bd0c0e14..18a3a55a4 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/resource-type/resource-type.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/resource-type/resource-type.mapper.ts @@ -1,6 +1,6 @@ -import { ResourceTypeFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type.entity'; -import { ResourceTypeIndexCardFilter } from '@shared/components/resources/resource-filters/models/resource-type/resource-type-index-card-filter.entity'; -import { ResourceTypeIndexValueSearch } from '@shared/components/resources/resource-filters/models/resource-type/resource-type-index-value-search.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { ResourceTypeIndexCardFilter } from '@shared/entities/filters/resource-type/resource-type-index-card-filter.entity'; +import { ResourceTypeIndexValueSearch } from '@shared/entities/filters/resource-type/resource-type-index-value-search.entity'; export function MapResourceType(items: ResourceTypeIndexValueSearch[]): ResourceTypeFilter[] { const resourceTypes: ResourceTypeFilter[] = []; diff --git a/src/app/shared/components/resources/resource-filters/mappers/subject/subject.mapper.ts b/src/app/shared/helpers/mappers/filters/subject/subject.mapper.ts similarity index 64% rename from src/app/shared/components/resources/resource-filters/mappers/subject/subject.mapper.ts rename to src/app/shared/helpers/mappers/filters/subject/subject.mapper.ts index 77336572e..30319e1c1 100644 --- a/src/app/shared/components/resources/resource-filters/mappers/subject/subject.mapper.ts +++ b/src/app/shared/helpers/mappers/filters/subject/subject.mapper.ts @@ -1,6 +1,6 @@ -import { IndexCardFilter } from '@shared/components/resources/resource-filters/models/index-card-filter.entity'; -import { IndexValueSearch } from '@shared/components/resources/resource-filters/models/index-value-search.entity'; -import { SubjectFilter } from '@shared/components/resources/resource-filters/models/subject/subject-filter.entity'; +import { IndexCardFilter } from '@shared/entities/filters/index-card-filter.entity'; +import { IndexValueSearch } from '@shared/entities/filters/index-value-search.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; export function MapSubject(items: IndexValueSearch[]): SubjectFilter[] { const subjects: SubjectFilter[] = []; diff --git a/src/app/shared/components/resources/resource-card/mappers/user-counts.mapper.ts b/src/app/shared/helpers/mappers/resource-card/user-counts.mapper.ts similarity index 67% rename from src/app/shared/components/resources/resource-card/mappers/user-counts.mapper.ts rename to src/app/shared/helpers/mappers/resource-card/user-counts.mapper.ts index 0505be35a..198e311bc 100644 --- a/src/app/shared/components/resources/resource-card/mappers/user-counts.mapper.ts +++ b/src/app/shared/helpers/mappers/resource-card/user-counts.mapper.ts @@ -1,5 +1,5 @@ -import { UserCountsResponse } from '@shared/components/resources/resource-card/models/user-counts-response.entity'; -import { UserRelatedDataCounts } from '@shared/components/resources/resource-card/models/user-related-data-counts.entity'; +import { UserCountsResponse } from '@shared/entities/resource-card/user-counts-response.entity'; +import { UserRelatedDataCounts } from '@shared/entities/resource-card/user-related-data-counts.entity'; export function MapUserCounts(response: UserCountsResponse): UserRelatedDataCounts { return { diff --git a/src/app/shared/services/filters-options.service.ts b/src/app/shared/services/filters-options.service.ts new file mode 100644 index 000000000..812e9c529 --- /dev/null +++ b/src/app/shared/services/filters-options.service.ts @@ -0,0 +1,219 @@ +import { map, Observable } from 'rxjs'; + +import { inject, Injectable } from '@angular/core'; + +import { ApiData, JsonApiResponse } from '@core/services/json-api/json-api.entity'; +import { JsonApiService } from '@core/services/json-api/json-api.service'; +import { Creator } from '@shared/entities/filters/creator/creator.entity'; +import { CreatorItem } from '@shared/entities/filters/creator/creator-item.entity'; +import { DateCreated } from '@shared/entities/filters/dateCreated/date-created.entity'; +import { FunderFilter } from '@shared/entities/filters/funder/funder-filter.entity'; +import { FunderIndexValueSearch } from '@shared/entities/filters/funder/funder-index-value-search.entity'; +import { IndexValueSearch } from '@shared/entities/filters/index-value-search.entity'; +import { InstitutionIndexValueSearch } from '@shared/entities/filters/institution/institution-index-value-search.entity'; +import { LicenseFilter } from '@shared/entities/filters/license/license-filter.entity'; +import { LicenseIndexValueSearch } from '@shared/entities/filters/license/license-index-value-search.entity'; +import { PartOfCollectionFilter } from '@shared/entities/filters/part-of-collection/part-of-collection-filter.entity'; +import { PartOfCollectionIndexValueSearch } from '@shared/entities/filters/part-of-collection/part-of-collection-index-value-search.entity'; +import { ProviderFilter } from '@shared/entities/filters/provider/provider-filter.entity'; +import { ProviderIndexValueSearch } from '@shared/entities/filters/provider/provider-index-value-search.entity'; +import { ResourceTypeFilter } from '@shared/entities/filters/resource-type/resource-type.entity'; +import { ResourceTypeIndexValueSearch } from '@shared/entities/filters/resource-type/resource-type-index-value-search.entity'; +import { SubjectFilter } from '@shared/entities/filters/subject/subject-filter.entity'; +import { MapCreators } from '@shared/helpers/mappers/filters/creators/creators.mappers'; +import { MapDateCreated } from '@shared/helpers/mappers/filters/dateCreated/date-created.mapper'; +import { MapFunders } from '@shared/helpers/mappers/filters/funder/funder.mapper'; +import { MapInstitutions } from '@shared/helpers/mappers/filters/institution/institution.mapper'; +import { MapLicenses } from '@shared/helpers/mappers/filters/license/license.mapper'; +import { MapPartOfCollections } from '@shared/helpers/mappers/filters/part-of-collection/part-of-collection.mapper'; +import { MapProviders } from '@shared/helpers/mappers/filters/provider/provider.mapper'; +import { MapResourceType } from '@shared/helpers/mappers/filters/resource-type/resource-type.mapper'; +import { MapSubject } from '@shared/helpers/mappers/filters/subject/subject.mapper'; + +import { environment } from '../../../environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class FiltersOptionsService { + #jsonApiService = inject(JsonApiService); + + getCreators( + valueSearchText: string, + params: Record, + filterParams: Record + ): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'creator', + valueSearchText, + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse[]> + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe( + map((response) => { + const included = (response?.included ?? []) as ApiData<{ resourceMetadata: CreatorItem }, null, null>[]; + return included + .filter((item) => item.type === 'index-card') + .map((item) => MapCreators(item.attributes.resourceMetadata)); + }) + ); + } + + getDates(params: Record, filterParams: Record): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'dateCreated', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get>(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapDateCreated(response?.included ?? []))); + } + + getFunders(params: Record, filterParams: Record): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'funder', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapFunders(response?.included ?? []))); + } + + getSubjects(params: Record, filterParams: Record): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'subject', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get>(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapSubject(response?.included ?? []))); + } + + getLicenses(params: Record, filterParams: Record): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'rights', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapLicenses(response?.included ?? []))); + } + + getResourceTypes( + params: Record, + filterParams: Record + ): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'resourceNature', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapResourceType(response?.included ?? []))); + } + + getInstitutions( + params: Record, + filterParams: Record + ): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'affiliation', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapInstitutions(response?.included ?? []))); + } + + getProviders(params: Record, filterParams: Record): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'publisher', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapProviders(response?.included ?? []))); + } + + getPartOtCollections( + params: Record, + filterParams: Record + ): Observable { + const dynamicParams = { + valueSearchPropertyPath: 'isPartOfCollection', + }; + + const fullParams = { + ...params, + ...filterParams, + ...dynamicParams, + }; + + return this.#jsonApiService + .get< + JsonApiResponse + >(`${environment.shareDomainUrl}/index-value-search`, fullParams) + .pipe(map((response) => MapPartOfCollections(response?.included ?? []))); + } +} diff --git a/src/app/features/search/search.service.ts b/src/app/shared/services/search.service.ts similarity index 100% rename from src/app/features/search/search.service.ts rename to src/app/shared/services/search.service.ts diff --git a/src/app/shared/styles/filter-chips/filter-chips.scss b/src/app/shared/styles/filter-chips/filter-chips.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/components/resources/resource-card/resource-card.component.scss b/src/app/shared/styles/resource-card/resource-card.scss similarity index 96% rename from src/app/shared/components/resources/resource-card/resource-card.component.scss rename to src/app/shared/styles/resource-card/resource-card.scss index 6f9d51825..e0a92b726 100644 --- a/src/app/shared/components/resources/resource-card/resource-card.component.scss +++ b/src/app/shared/styles/resource-card/resource-card.scss @@ -1,4 +1,4 @@ -@use "../../../../../assets/styles/variables" as var; +@use "assets/styles/variables" as var; .resource { display: flex; diff --git a/src/app/shared/components/resources/resource-filters/utils/add-filters-params.helper.ts b/src/app/shared/utils/add-filters-params.helper.ts similarity index 66% rename from src/app/shared/components/resources/resource-filters/utils/add-filters-params.helper.ts rename to src/app/shared/utils/add-filters-params.helper.ts index 65d9d4b21..5068d86e6 100644 --- a/src/app/shared/components/resources/resource-filters/utils/add-filters-params.helper.ts +++ b/src/app/shared/utils/add-filters-params.helper.ts @@ -1,33 +1,33 @@ -import { ResourceFiltersStateModel } from '@shared/components/resources/resource-filters/store'; +import { ResourceFiltersStateModel } from '@osf/features/search/components/resources/components/resource-filters/store'; export function addFiltersParams(filters: ResourceFiltersStateModel): Record { const params: Record = {}; - if (filters.creator.value) { + if (filters.creator?.value) { params['cardSearchFilter[creator][]'] = filters.creator.value; } - if (filters.dateCreated.value) { + if (filters.dateCreated?.value) { params['cardSearchFilter[dateCreated][]'] = filters.dateCreated.value; } - if (filters.subject.value) { + if (filters.subject?.value) { params['cardSearchFilter[subject][]'] = filters.subject.value; } - if (filters.funder.value) { + if (filters.funder?.value) { params['cardSearchFilter[funder][]'] = filters.funder.value; } - if (filters.license.value) { + if (filters.license?.value) { params['cardSearchFilter[rights][]'] = filters.license.value; } - if (filters.resourceType.value) { + if (filters.resourceType?.value) { params['cardSearchFilter[resourceNature][]'] = filters.resourceType.value; } - if (filters.institution.value) { + if (filters.institution?.value) { params['cardSearchFilter[affiliation][]'] = filters.institution.value; } - if (filters.provider.value) { + if (filters.provider?.value) { params['cardSearchFilter[publisher][]'] = filters.provider.value; } - if (filters.partOfCollection.value) { + if (filters.partOfCollection?.value) { params['cardSearchFilter[isPartOfCollection][]'] = filters.partOfCollection.value; } diff --git a/src/app/shared/components/resources/resource-filters/models/filter-labels.ts b/src/app/shared/utils/filter-labels.model.ts similarity index 87% rename from src/app/shared/components/resources/resource-filters/models/filter-labels.ts rename to src/app/shared/utils/filter-labels.model.ts index 2b620967c..a5f03f7d7 100644 --- a/src/app/shared/components/resources/resource-filters/models/filter-labels.ts +++ b/src/app/shared/utils/filter-labels.model.ts @@ -1,4 +1,4 @@ -export const FilterLabels = { +export const FilterLabelsModel = { creator: 'Creator', dateCreated: 'Date Created', funder: 'Funder', diff --git a/src/app/features/search/utils/helpers/get-resource-types.helper.ts b/src/app/shared/utils/get-resource-types.helper.ts similarity index 86% rename from src/app/features/search/utils/helpers/get-resource-types.helper.ts rename to src/app/shared/utils/get-resource-types.helper.ts index 32e048eb0..3434c36dd 100644 --- a/src/app/features/search/utils/helpers/get-resource-types.helper.ts +++ b/src/app/shared/utils/get-resource-types.helper.ts @@ -1,4 +1,4 @@ -import { ResourceTab } from '@osf/features/search/models/resource-tab.enum'; +import { ResourceTab } from '@shared/entities/resource-card/resource-tab.enum'; export function getResourceTypes(resourceTab: ResourceTab): string { switch (resourceTab) { diff --git a/src/app/shared/components/resources/resource-filters/utils/data.ts b/src/app/shared/utils/resource-filters-defaults.model.ts similarity index 52% rename from src/app/shared/components/resources/resource-filters/utils/data.ts rename to src/app/shared/utils/resource-filters-defaults.model.ts index 4f4d3e0c7..e21262559 100644 --- a/src/app/shared/components/resources/resource-filters/utils/data.ts +++ b/src/app/shared/utils/resource-filters-defaults.model.ts @@ -1,48 +1,48 @@ -import { FilterLabels } from '@shared/components/resources/resource-filters/models/filter-labels'; +import { FilterLabelsModel } from '@shared/utils/filter-labels.model'; -export const resourceFiltersDefaults = { +export const resourceFiltersDefaultsModel = { creator: { - filterName: FilterLabels.creator, + filterName: FilterLabelsModel.creator, label: undefined, value: undefined, }, dateCreated: { - filterName: FilterLabels.dateCreated, + filterName: FilterLabelsModel.dateCreated, label: undefined, value: undefined, }, funder: { - filterName: FilterLabels.funder, + filterName: FilterLabelsModel.funder, label: undefined, value: undefined, }, subject: { - filterName: FilterLabels.subject, + filterName: FilterLabelsModel.subject, label: undefined, value: undefined, }, license: { - filterName: FilterLabels.license, + filterName: FilterLabelsModel.license, label: undefined, value: undefined, }, resourceType: { - filterName: FilterLabels.resourceType, + filterName: FilterLabelsModel.resourceType, label: undefined, value: undefined, }, institution: { - filterName: FilterLabels.institution, + filterName: FilterLabelsModel.institution, label: undefined, value: undefined, }, provider: { - filterName: FilterLabels.provider, + filterName: FilterLabelsModel.provider, label: undefined, value: undefined, }, partOfCollection: { - filterName: FilterLabels.partOfCollection, + filterName: FilterLabelsModel.partOfCollection, label: undefined, value: undefined, }, diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 3214a66c2..b9ff6f69a 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1,5 +1,6 @@ { "navigation": { + "profile": "Profile", "myProfile": "My profile", "settings": "Settings", "logOut": "Log out", diff --git a/src/assets/icons/socials/academia.svg b/src/assets/icons/socials/academia.svg new file mode 100644 index 000000000..2d9744546 --- /dev/null +++ b/src/assets/icons/socials/academia.svg @@ -0,0 +1,6 @@ + + + +academia + + \ No newline at end of file diff --git a/src/assets/icons/socials/baidu.png b/src/assets/icons/socials/baidu.png new file mode 100644 index 000000000..ee4fb1209 Binary files /dev/null and b/src/assets/icons/socials/baidu.png differ diff --git a/src/assets/icons/socials/github2.svg b/src/assets/icons/socials/github2.svg new file mode 100644 index 000000000..84e4d2f94 --- /dev/null +++ b/src/assets/icons/socials/github2.svg @@ -0,0 +1,19 @@ + + + + + github [#142] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/socials/impactstory.png b/src/assets/icons/socials/impactstory.png new file mode 100644 index 000000000..26b1ae756 Binary files /dev/null and b/src/assets/icons/socials/impactstory.png differ diff --git a/src/assets/icons/socials/linkedin2.svg b/src/assets/icons/socials/linkedin2.svg new file mode 100644 index 000000000..bf1448269 --- /dev/null +++ b/src/assets/icons/socials/linkedin2.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icons/socials/researchGate.svg b/src/assets/icons/socials/researchGate.svg new file mode 100644 index 000000000..122d8b666 --- /dev/null +++ b/src/assets/icons/socials/researchGate.svg @@ -0,0 +1 @@ +ResearchGate icon \ No newline at end of file diff --git a/src/assets/icons/socials/researcherID.png b/src/assets/icons/socials/researcherID.png new file mode 100644 index 000000000..150bc4c99 Binary files /dev/null and b/src/assets/icons/socials/researcherID.png differ diff --git a/src/assets/icons/socials/scholar.svg b/src/assets/icons/socials/scholar.svg new file mode 100644 index 000000000..775383090 --- /dev/null +++ b/src/assets/icons/socials/scholar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/socials/ssrn.svg b/src/assets/icons/socials/ssrn.svg new file mode 100644 index 000000000..c3ad32a35 --- /dev/null +++ b/src/assets/icons/socials/ssrn.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + diff --git a/src/assets/icons/socials/twitter.svg b/src/assets/icons/socials/twitter.svg new file mode 100644 index 000000000..50f120774 --- /dev/null +++ b/src/assets/icons/socials/twitter.svg @@ -0,0 +1,17 @@ + + + + + Twitter-color + Created with Sketch. + + + + + + + + + + + \ No newline at end of file