diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index dbc0556de..683d06f2c 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -164,8 +164,8 @@ export const routes: Routes = [ }, { path: 'addons', - loadComponent: () => - import('./features/project/addons/addons.component').then((mod) => mod.AddonsComponent), + loadChildren: () => + import('./features/project/addons/constants/addons.routes').then((mod) => mod.addonsRoutes), }, ], }, diff --git a/src/app/core/constants/ngxs-states.constant.ts b/src/app/core/constants/ngxs-states.constant.ts index 7014a5980..7f622dcdd 100644 --- a/src/app/core/constants/ngxs-states.constant.ts +++ b/src/app/core/constants/ngxs-states.constant.ts @@ -10,11 +10,11 @@ import { RegistrationsState } from '@osf/features/project/registrations/store'; import { SettingsState } from '@osf/features/project/settings/store'; import { WikiState } from '@osf/features/project/wiki/store/wiki.state'; 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'; import { NotificationSubscriptionState } from '@osf/features/settings/notifications/store'; import { ProfileSettingsState } from '@osf/features/settings/profile-settings/store/profile-settings.state'; import { TokensState } from '@osf/features/settings/tokens/store'; +import { AddonsState } from '@shared/stores/addons'; export const STATES = [ AuthState, diff --git a/src/app/core/interceptors/auth.interceptor.ts b/src/app/core/interceptors/auth.interceptor.ts index 0ddb43ab9..174408c69 100644 --- a/src/app/core/interceptors/auth.interceptor.ts +++ b/src/app/core/interceptors/auth.interceptor.ts @@ -7,7 +7,6 @@ export const authInterceptor: HttpInterceptorFn = ( next: HttpHandlerFn ): Observable> => { const authToken = 'UlO9O9GNKgVzJD7pUeY53jiQTKJ4U2znXVWNvh0KZQruoENuILx0IIYf9LoDz7Duq72EIm'; - // OBJoUomBgbUuDgQo5JoaSKNya6XaYcd0ojAX1XOLmWi6J2arQPzByxyEi81fHE60drQUWv // UlO9O9GNKgVzJD7pUeY53jiQTKJ4U2znXVWNvh0KZQruoENuILx0IIYf9LoDz7Duq72EIm kyrylo // 2rjFZwmdDG4rtKj7hGkEMO6XyHBM2lN7XBbsA1e8OqcFhOWu6Z7fQZiheu9RXtzSeVrgOt roman nastyuk diff --git a/src/app/core/store/user/user.model.ts b/src/app/core/store/user/user.model.ts index 9b567a611..fdb6aec8e 100644 --- a/src/app/core/store/user/user.model.ts +++ b/src/app/core/store/user/user.model.ts @@ -3,6 +3,6 @@ import { AsyncStateModel } from '@shared/models/store'; import { User, UserSettings } from '../../models'; export interface UserStateModel { - currentUser: User | null; + currentUser: AsyncStateModel; currentUserSettings: AsyncStateModel; } diff --git a/src/app/core/store/user/user.selectors.ts b/src/app/core/store/user/user.selectors.ts index 257ba64df..bd0782e77 100644 --- a/src/app/core/store/user/user.selectors.ts +++ b/src/app/core/store/user/user.selectors.ts @@ -8,23 +8,28 @@ import { Social } from '@osf/shared/models'; export class UserSelectors { @Selector([UserState]) static getCurrentUser(state: UserStateModel): User | null { - return state.currentUser; + return state.currentUser.data; + } + + @Selector([UserState]) + static getCurrentUserLoading(state: UserStateModel): boolean { + return state.currentUser.isLoading; } @Selector([UserState]) static getProfileSettings(state: UserStateModel): ProfileSettingsStateModel { return { - education: state.currentUser?.education ?? [], - employment: state.currentUser?.employment ?? [], - social: state.currentUser?.social ?? ({} as Social), + education: state.currentUser.data?.education ?? [], + employment: state.currentUser.data?.employment ?? [], + social: state.currentUser.data?.social ?? ({} as Social), user: { - middleNames: state.currentUser?.middleNames ?? '', - suffix: state.currentUser?.suffix ?? '', - id: state.currentUser?.id ?? '', - fullName: state.currentUser?.fullName ?? '', - email: state.currentUser?.email ?? '', - givenName: state.currentUser?.givenName ?? '', - familyName: state.currentUser?.familyName ?? '', + middleNames: state.currentUser.data?.middleNames ?? '', + suffix: state.currentUser.data?.suffix ?? '', + id: state.currentUser.data?.id ?? '', + fullName: state.currentUser.data?.fullName ?? '', + email: state.currentUser.data?.email ?? '', + givenName: state.currentUser.data?.givenName ?? '', + familyName: state.currentUser.data?.familyName ?? '', }, } satisfies ProfileSettingsStateModel; } diff --git a/src/app/core/store/user/user.state.ts b/src/app/core/store/user/user.state.ts index 3bec0a0eb..be4743f2c 100644 --- a/src/app/core/store/user/user.state.ts +++ b/src/app/core/store/user/user.state.ts @@ -15,7 +15,11 @@ import { UserStateModel } from './user.model'; @State({ name: 'user', defaults: { - currentUser: null, + currentUser: { + data: null, + isLoading: false, + error: null, + }, currentUserSettings: { data: null, isLoading: false, @@ -30,10 +34,21 @@ export class UserState { @Action(GetCurrentUser) getCurrentUser(ctx: StateContext) { + ctx.patchState({ + currentUser: { + ...ctx.getState().currentUser, + isLoading: true, + }, + }); + return this.userService.getCurrentUser().pipe( tap((user) => { ctx.patchState({ - currentUser: user, + currentUser: { + data: user, + isLoading: false, + error: null, + }, }); ctx.dispatch(new SetupProfileSettings()); }) @@ -43,7 +58,11 @@ export class UserState { @Action(SetCurrentUser) setCurrentUser(ctx: StateContext, action: SetCurrentUser) { ctx.patchState({ - currentUser: action.user, + currentUser: { + data: action.user, + isLoading: false, + error: null, + }, }); } diff --git a/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.html b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.html new file mode 100644 index 000000000..6b2db0376 --- /dev/null +++ b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.html @@ -0,0 +1 @@ +

add-to-collection-form works!

diff --git a/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.scss b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.spec.ts b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.spec.ts new file mode 100644 index 000000000..f1cd32c58 --- /dev/null +++ b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddToCollectionFormComponent } from './add-to-collection-form.component'; + +describe('AddToCollectionFormComponent', () => { + let component: AddToCollectionFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddToCollectionFormComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(AddToCollectionFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.ts b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.ts new file mode 100644 index 000000000..38a7ebba4 --- /dev/null +++ b/src/app/features/collections/components/add-to-collection-form/add-to-collection-form.component.ts @@ -0,0 +1,10 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'osf-add-to-collection-form', + imports: [], + templateUrl: './add-to-collection-form.component.html', + styleUrl: './add-to-collection-form.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AddToCollectionFormComponent {} diff --git a/src/app/features/collections/components/collections-main-content/index.ts b/src/app/features/collections/components/collections-main-content/index.ts new file mode 100644 index 000000000..1dc736ffc --- /dev/null +++ b/src/app/features/collections/components/collections-main-content/index.ts @@ -0,0 +1 @@ +export { CollectionsMainContentComponent } from './collections-main-content.component'; diff --git a/src/app/features/my-projects/mappers/my-projects.mapper.ts b/src/app/features/my-projects/mappers/my-projects.mapper.ts index 79128fbf3..c2579892a 100644 --- a/src/app/features/my-projects/mappers/my-projects.mapper.ts +++ b/src/app/features/my-projects/mappers/my-projects.mapper.ts @@ -1,7 +1,7 @@ -import { MyProjectsItem, MyProjectsItemGetResponse } from '../models'; +import { MyProjectsItem, MyProjectsItemGetResponseJsonApi } from '../models'; export class MyProjectsMapper { - static fromResponse(response: MyProjectsItemGetResponse): MyProjectsItem { + static fromResponse(response: MyProjectsItemGetResponseJsonApi): MyProjectsItem { return { id: response.id, type: response.type, diff --git a/src/app/features/my-projects/models/create-project.model.ts b/src/app/features/my-projects/models/create-project.model.ts index ea95d68ef..71dc48c8e 100644 --- a/src/app/features/my-projects/models/create-project.model.ts +++ b/src/app/features/my-projects/models/create-project.model.ts @@ -1,4 +1,4 @@ -export interface CreateProjectPayload { +export interface CreateProjectPayloadJsoApi { data: { type: 'nodes'; attributes: { diff --git a/src/app/features/my-projects/models/my-projects.models.ts b/src/app/features/my-projects/models/my-projects.models.ts index 0a0a9ab19..215e0c4fc 100644 --- a/src/app/features/my-projects/models/my-projects.models.ts +++ b/src/app/features/my-projects/models/my-projects.models.ts @@ -1,6 +1,6 @@ import { JsonApiResponse } from '@osf/core/models'; -export interface MyProjectsItemGetResponse { +export interface MyProjectsItemGetResponseJsonApi { id: string; type: string; attributes: { @@ -50,7 +50,7 @@ export interface MyProjectsItem { contributors: MyProjectsContributor[]; } -export interface MyProjectsItemResponse { +export interface MyProjectsItemResponseJsonApi { data: MyProjectsItem[]; links: { meta: { @@ -60,7 +60,7 @@ export interface MyProjectsItemResponse { }; } -export interface MyProjectsJsonApiResponse extends JsonApiResponse { +export interface MyProjectsResponseJsonApi extends JsonApiResponse { links: { meta: { total: number; diff --git a/src/app/features/my-projects/services/my-projects.service.ts b/src/app/features/my-projects/services/my-projects.service.ts index 8d0bc708c..3ad8cf027 100644 --- a/src/app/features/my-projects/services/my-projects.service.ts +++ b/src/app/features/my-projects/services/my-projects.service.ts @@ -10,12 +10,12 @@ import { NodeResponseModel, UpdateNodeRequestModel } from '@shared/models'; import { MyProjectsMapper } from '../mappers'; import { - CreateProjectPayload, + CreateProjectPayloadJsoApi, EndpointType, MyProjectsItem, - MyProjectsItemGetResponse, - MyProjectsItemResponse, - MyProjectsJsonApiResponse, + MyProjectsItemGetResponseJsonApi, + MyProjectsItemResponseJsonApi, + MyProjectsResponseJsonApi, MyProjectsSearchFilters, } from '../models'; @@ -38,7 +38,7 @@ export class MyProjectsService { filters?: MyProjectsSearchFilters, pageNumber?: number, pageSize?: number - ): Observable { + ): Observable { const params: Record = { 'embed[]': ['bibliographic_contributors'], [`fields[${endpoint}]`]: 'title,date_modified,public,bibliographic_contributors', @@ -69,9 +69,9 @@ export class MyProjectsService { ? environment.apiUrl + '/' + endpoint : environment.apiUrl + '/users/me/' + endpoint; - return this.jsonApiService.get(url, params).pipe( - map((response: MyProjectsJsonApiResponse) => ({ - data: response.data.map((item: MyProjectsItemGetResponse) => MyProjectsMapper.fromResponse(item)), + return this.jsonApiService.get(url, params).pipe( + map((response: MyProjectsResponseJsonApi) => ({ + data: response.data.map((item: MyProjectsItemGetResponseJsonApi) => MyProjectsMapper.fromResponse(item)), links: response.links, })) ); @@ -81,7 +81,7 @@ export class MyProjectsService { filters?: MyProjectsSearchFilters, pageNumber?: number, pageSize?: number - ): Observable { + ): Observable { return this.getMyItems('nodes', filters, pageNumber, pageSize); } @@ -104,7 +104,7 @@ export class MyProjectsService { filters?: MyProjectsSearchFilters, pageNumber?: number, pageSize?: number - ): Observable { + ): Observable { return this.getMyItems('registrations', filters, pageNumber, pageSize); } @@ -112,7 +112,7 @@ export class MyProjectsService { filters?: MyProjectsSearchFilters, pageNumber?: number, pageSize?: number - ): Observable { + ): Observable { return this.getMyItems('preprints', filters, pageNumber, pageSize); } @@ -121,7 +121,7 @@ export class MyProjectsService { filters?: MyProjectsSearchFilters, pageNumber?: number, pageSize?: number - ): Observable { + ): Observable { return this.getMyItems(`collections/${collectionId}/linked_nodes/`, filters, pageNumber, pageSize); } @@ -132,7 +132,7 @@ export class MyProjectsService { region: string, affiliations: string[] ): Observable { - const payload: CreateProjectPayload = { + const payload: CreateProjectPayloadJsoApi = { data: { type: 'nodes', attributes: { @@ -167,7 +167,7 @@ export class MyProjectsService { }; return this.jsonApiService - .post(`${environment.apiUrl}/nodes/`, payload, params) + .post(`${environment.apiUrl}/nodes/`, payload, params) .pipe(map((response) => MyProjectsMapper.fromResponse(response))); } diff --git a/src/app/features/project/addons/addons.component.html b/src/app/features/project/addons/addons.component.html index f084b1d45..688500c52 100644 --- a/src/app/features/project/addons/addons.component.html +++ b/src/app/features/project/addons/addons.component.html @@ -1,7 +1,7 @@ - +
-