Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/core/interceptors/auth.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const authInterceptor: HttpInterceptorFn = (

if (!req.url.includes('/api.crossref.org/funders')) {
const headers: Record<string, string> = {
Accept: req.responseType === 'text' ? '*/*' : 'application/vnd.api+json',
Accept: req.responseType === 'text' ? '*/*' : 'application/vnd.api+json;version=2.20',
'Content-Type': 'application/vnd.api+json',
};

Expand Down
8 changes: 4 additions & 4 deletions src/app/core/models/json-api.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export interface JsonApiResponseWithMeta<Data, Meta, Included> extends JsonApiRe
meta: Meta;
}

export interface JsonApiResponseWithPaging<Data, Included> extends JsonApiResponse<Data, Included> {
links: {
meta: MetaJsonApi;
};
export interface ResponseJsonApi<Data> {
data: Data;
links: PaginationLinksJsonApi;
meta: MetaJsonApi;
}

export interface ApiData<Attributes, Embeds, Relationships, Links> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { UserState } from '@core/store/user';
import { AdminTableComponent } from '@osf/features/admin-institutions/components';
import { InstitutionsAdminState } from '@osf/features/admin-institutions/store';
import { ToastService } from '@osf/shared/services';
import { LoadingSpinnerComponent, SelectComponent } from '@shared/components';
import { TranslateServiceMock } from '@shared/mocks';

Expand All @@ -33,6 +34,7 @@ describe('InstitutionsUsersComponent', () => {
MockProvider(ActivatedRoute, { queryParams: of({}) }),
MockProvider(Router),
TranslateServiceMock,
MockProvider(ToastService),
provideStore([InstitutionsAdminState, UserState]),
provideHttpClient(),
provideHttpClientTesting(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '@osf/features/admin-institutions/store/institutions-admin.actions';
import { InstitutionsAdminSelectors } from '@osf/features/admin-institutions/store/institutions-admin.selectors';
import { LoadingSpinnerComponent, SelectComponent } from '@osf/shared/components';
import { ToastService } from '@osf/shared/services';
import { TABLE_PARAMS } from '@shared/constants';
import { SortOrder } from '@shared/enums';
import { QueryParams } from '@shared/models';
Expand Down Expand Up @@ -63,6 +64,7 @@ export class InstitutionsUsersComponent implements OnInit {
private readonly translate = inject(TranslateService);
private readonly dialogService = inject(DialogService);
private readonly destroyRef = inject(DestroyRef);
private readonly toastService = inject(ToastService);

private readonly actions = createDispatchMap({
fetchInstitutionUsers: FetchInstitutionUsers,
Expand Down Expand Up @@ -268,12 +270,14 @@ export class InstitutionsUsersComponent implements OnInit {
private sendEmailToUser(userRowData: TableCellData, emailData: SendEmailDialogData): void {
const userId = (userRowData['userLink'] as TableCellLink).text as string;

this.actions.sendUserMessage(
userId,
this.institutionId,
emailData.emailContent,
emailData.ccSender,
emailData.allowReplyToSender
);
this.actions
.sendUserMessage(
userId,
this.institutionId,
emailData.emailContent,
emailData.ccSender,
emailData.allowReplyToSender
)
.subscribe(() => this.toastService.showSuccess('adminInstitutions.institutionUsers.messageSent'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class InstitutionsAdminService {
const payload = sendMessageRequestMapper(request);

return this.jsonApiService.post<SendMessageResponseJsonApi>(
`${environment.apiUrl}/institutions/messages/`,
`${environment.apiUrl}/users/${request.userId}/messages/`,
payload
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
export class FetchInstitutionById {
static readonly type = '[InstitutionsAdmin] Fetch Institution By Id';
constructor(public institutionId: string) {}
}

export class FetchInstitutionDepartments {
static readonly type = '[InstitutionsAdmin] Fetch Institution Departments';
constructor(public institutionId: string) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncStateModel, AsyncStateWithLinksModel, AsyncStateWithTotalCount } from '@shared/models';
import { AsyncStateModel, AsyncStateWithLinksModel, AsyncStateWithTotalCount, Institution } from '@shared/models';

import {
InstitutionDepartment,
Expand All @@ -24,4 +24,21 @@ export interface InstitutionsAdminModel {
sendMessage: AsyncStateModel<SendMessageResponseJsonApi | null>;
selectedInstitutionId: string | null;
currentSearchPropertyPath: string | null;
institution: AsyncStateModel<Institution>;
}

export const INSTITUTIONS_ADMIN_STATE_DEFAULTS: InstitutionsAdminModel = {
departments: { data: [], isLoading: false, error: null },
summaryMetrics: { data: {} as InstitutionSummaryMetrics, isLoading: false, error: null },
hasOsfAddonSearch: { data: [], isLoading: false, error: null },
storageRegionSearch: { data: [], isLoading: false, error: null },
searchResults: { data: [], isLoading: false, error: null },
users: { data: [], totalCount: 0, isLoading: false, error: null },
projects: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
registrations: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
preprints: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
sendMessage: { data: null, isLoading: false, error: null },
selectedInstitutionId: null,
currentSearchPropertyPath: null,
institution: { data: {} as Institution, isLoading: false, error: null },
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Action, State, StateContext } from '@ngxs/store';
import { patch } from '@ngxs/store/operators';

import { catchError, tap } from 'rxjs';

import { inject, Injectable } from '@angular/core';

import { handleSectionError } from '@core/handlers';
import { Institution } from '@osf/shared/models';
import { InstitutionsService } from '@osf/shared/services';

import { InstitutionPreprint, InstitutionProject, InstitutionRegistration, InstitutionSummaryMetrics } from '../models';
import { InstitutionPreprint, InstitutionProject, InstitutionRegistration } from '../models';
import { InstitutionsAdminService } from '../services/institutions-admin.service';

import {
FetchHasOsfAddonSearch,
FetchInstitutionById,
FetchInstitutionDepartments,
FetchInstitutionSearchResults,
FetchInstitutionSummaryMetrics,
Expand All @@ -21,29 +25,33 @@ import {
FetchStorageRegionSearch,
SendUserMessage,
} from './institutions-admin.actions';
import { InstitutionsAdminModel } from './institutions-admin.model';
import { INSTITUTIONS_ADMIN_STATE_DEFAULTS, InstitutionsAdminModel } from './institutions-admin.model';

@State<InstitutionsAdminModel>({
name: 'institutionsAdmin',
defaults: {
departments: { data: [], isLoading: false, error: null },
summaryMetrics: { data: {} as InstitutionSummaryMetrics, isLoading: false, error: null },
hasOsfAddonSearch: { data: [], isLoading: false, error: null },
storageRegionSearch: { data: [], isLoading: false, error: null },
searchResults: { data: [], isLoading: false, error: null },
users: { data: [], totalCount: 0, isLoading: false, error: null },
projects: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
registrations: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
preprints: { data: [], totalCount: 0, isLoading: false, error: null, links: undefined },
sendMessage: { data: null, isLoading: false, error: null },
selectedInstitutionId: null,
currentSearchPropertyPath: null,
},
defaults: INSTITUTIONS_ADMIN_STATE_DEFAULTS,
})
@Injectable()
export class InstitutionsAdminState {
private readonly institutionsService = inject(InstitutionsService);
private readonly institutionsAdminService = inject(InstitutionsAdminService);

@Action(FetchInstitutionById)
fetchInstitutionById(ctx: StateContext<InstitutionsAdminModel>, action: FetchInstitutionById) {
ctx.patchState({ institution: { data: {} as Institution, isLoading: true, error: null } });

return this.institutionsService.getInstitutionById(action.institutionId).pipe(
tap((response) => {
ctx.setState(
patch({
institution: patch({ data: response, error: null, isLoading: false }),
})
);
}),
catchError((error) => handleSectionError(ctx, 'institution', error))
);
}

@Action(FetchInstitutionDepartments)
fetchDepartments(ctx: StateContext<InstitutionsAdminModel>, action: FetchInstitutionDepartments) {
const state = ctx.getState();
Expand Down
12 changes: 5 additions & 7 deletions src/app/features/meetings/mappers/meetings.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JsonApiResponseWithPaging } from '@core/models';
import { ResponseJsonApi } from '@core/models';

import {
MeetingGetResponseJsonApi,
Expand All @@ -8,9 +8,7 @@ import {
} from '../models';

export class MeetingsMapper {
static fromMeetingsGetResponse(
response: JsonApiResponseWithPaging<MeetingGetResponseJsonApi[], null>
): MeetingsWithPaging {
static fromMeetingsGetResponse(response: ResponseJsonApi<MeetingGetResponseJsonApi[]>): MeetingsWithPaging {
return {
data: response.data.map((item) => ({
id: item.id,
Expand All @@ -20,12 +18,12 @@ export class MeetingsMapper {
endDate: item.attributes.end_date,
submissionsCount: item.attributes.submissions_count,
})),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}

static fromMeetingSubmissionGetResponse(
response: JsonApiResponseWithPaging<MeetingSubmissionGetResponseJsonApi[], null>
response: ResponseJsonApi<MeetingSubmissionGetResponseJsonApi[]>
): MeetingSubmissionsWithPaging {
return {
data: response.data.map((item) => ({
Expand All @@ -37,7 +35,7 @@ export class MeetingsMapper {
meetingCategory: item.attributes.meeting_category,
downloadLink: item.links.download,
})),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}

Expand Down
8 changes: 3 additions & 5 deletions src/app/features/meetings/services/meetings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { map, Observable } from 'rxjs';
import { inject, Injectable } from '@angular/core';

import { JsonApiService } from '@core/services';
import { JsonApiResponse, JsonApiResponseWithPaging } from '@osf/core/models';
import { JsonApiResponse, ResponseJsonApi } from '@osf/core/models';
import { MeetingsMapper } from '@osf/features/meetings/mappers';
import {
MeetingGetResponseJsonApi,
Expand Down Expand Up @@ -35,7 +35,7 @@ export class MeetingsService {
);

return this.jsonApiService
.get<JsonApiResponseWithPaging<MeetingGetResponseJsonApi[], null>>(this.baseUrl, params)
.get<ResponseJsonApi<MeetingGetResponseJsonApi[]>>(this.baseUrl, params)
.pipe(map((response) => MeetingsMapper.fromMeetingsGetResponse(response)));
}

Expand All @@ -54,9 +54,7 @@ export class MeetingsService {
);

return this.jsonApiService
.get<
JsonApiResponseWithPaging<MeetingSubmissionGetResponseJsonApi[], null>
>(`${this.baseUrl}${meetingId}/submissions/`, params)
.get<ResponseJsonApi<MeetingSubmissionGetResponseJsonApi[]>>(`${this.baseUrl}${meetingId}/submissions/`, params)
.pipe(map((response) => MeetingsMapper.fromMeetingSubmissionGetResponse(response)));
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/features/moderation/mappers/moderation.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JsonApiResponseWithPaging, UserGetResponse } from '@osf/core/models';
import { ResponseJsonApi, UserGetResponse } from '@osf/core/models';
import { PaginatedData } from '@osf/shared/models';

import { AddModeratorType, ModeratorPermission } from '../enums';
Expand All @@ -17,7 +17,7 @@ export class ModerationMapper {
}

static fromUsersWithPaginationGetResponse(
response: JsonApiResponseWithPaging<UserGetResponse[], null>
response: ResponseJsonApi<UserGetResponse[]>
): PaginatedData<ModeratorAddModel[]> {
return {
data: response.data.map(
Expand All @@ -28,7 +28,7 @@ export class ModerationMapper {
permission: ModeratorPermission.Moderator,
}) as ModeratorAddModel
),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JsonApiResponseWithPaging } from '@osf/core/models';
import { ResponseJsonApi } from '@osf/core/models';
import { PaginatedData } from '@osf/shared/models';

import {
Expand Down Expand Up @@ -35,11 +35,11 @@ export class PreprintModerationMapper {
}

static fromResponseWithPagination(
response: JsonApiResponseWithPaging<ReviewActionJsonApi[], null>
response: ResponseJsonApi<ReviewActionJsonApi[]>
): PaginatedData<PreprintReviewActionModel[]> {
return {
data: response.data.map((x) => this.fromResponse(x)),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class RegistryModerationMapper {
static fromResponseWithPagination(response: RegistryResponseJsonApi): PaginatedData<RegistryModeration[]> {
return {
data: response.data.map((x) => this.fromResponse(x)),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/features/moderation/models/registry-json-api.model.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JsonApiResponseWithPaging } from '@osf/core/models';
import { ResponseJsonApi } from '@osf/core/models';
import { RegistrationReviewStates, RevisionReviewStates } from '@osf/shared/enums';

export type RegistryResponseJsonApi = JsonApiResponseWithPaging<RegistryDataJsonApi[], null>;
export type RegistryResponseJsonApi = ResponseJsonApi<RegistryDataJsonApi[]>;

export interface RegistryDataJsonApi {
id: string;
Expand Down
4 changes: 2 additions & 2 deletions src/app/features/moderation/services/moderators.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { map, Observable } from 'rxjs';

import { inject, Injectable } from '@angular/core';

import { JsonApiResponse, JsonApiResponseWithPaging, UserGetResponse } from '@osf/core/models';
import { JsonApiResponse, ResponseJsonApi, UserGetResponse } from '@osf/core/models';
import { JsonApiService } from '@osf/core/services';
import { ResourceType } from '@osf/shared/enums';
import { PaginatedData } from '@osf/shared/models';
Expand Down Expand Up @@ -63,7 +63,7 @@ export class ModeratorsService {
const baseUrl = `${environment.apiUrl}/users/?filter[full_name]=${value}&page=${page}`;

return this.jsonApiService
.get<JsonApiResponseWithPaging<UserGetResponse[], null>>(baseUrl)
.get<ResponseJsonApi<UserGetResponse[]>>(baseUrl)
.pipe(map((response) => ModerationMapper.fromUsersWithPaginationGetResponse(response)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { map, Observable } from 'rxjs';

import { inject, Injectable } from '@angular/core';

import { JsonApiResponse, JsonApiResponseWithPaging } from '@osf/core/models';
import { JsonApiResponse, ResponseJsonApi } from '@osf/core/models';
import { JsonApiService } from '@osf/core/services';
import { PaginatedData } from '@osf/shared/models';

Expand Down Expand Up @@ -49,7 +49,7 @@ export class PreprintModerationService {
const baseUrl = `${environment.apiUrl}/actions/reviews/?embed=provider&embed=target&page=${page}`;

return this.jsonApiService
.get<JsonApiResponseWithPaging<ReviewActionJsonApi[], null>>(baseUrl)
.get<ResponseJsonApi<ReviewActionJsonApi[]>>(baseUrl)
.pipe(map((response) => PreprintModerationMapper.fromResponseWithPagination(response)));
}

Expand Down
9 changes: 4 additions & 5 deletions src/app/features/preprints/mappers/preprints.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApiData, JsonApiResponseWithMeta, JsonApiResponseWithPaging } from '@core/models';
import { ApiData, JsonApiResponseWithMeta, ResponseJsonApi } from '@core/models';
import {
Preprint,
PreprintAttributesJsonApi,
Expand Down Expand Up @@ -155,9 +155,8 @@ export class PreprintsMapper {
}

static fromMyPreprintJsonApi(
response: JsonApiResponseWithPaging<
ApiData<PreprintAttributesJsonApi, PreprintEmbedsJsonApi, PreprintRelationshipsJsonApi, null>[],
null
response: ResponseJsonApi<
ApiData<PreprintAttributesJsonApi, PreprintEmbedsJsonApi, PreprintRelationshipsJsonApi, null>[]
>
): PreprintShortInfoWithTotalCount {
return {
Expand All @@ -175,7 +174,7 @@ export class PreprintsMapper {
providerId: preprintData.relationships.provider.data.id,
};
}),
totalCount: response.links.meta.total,
totalCount: response.meta.total,
};
}
}
Loading