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: 2 additions & 0 deletions spa/src/app/_ngrx/app.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FileManifestEffects } from "../files/_ngrx/file-manifest/file-manifest.
import { IntegrationEffects } from "../files/_ngrx/integration/integration.effects";
import { MatrixEffects } from "../files/_ngrx/matrix/matrix.effects";
import { ProjectEffects } from "../files/_ngrx/project/project.effects";
import { ProjectEditsEffects } from "../files/_ngrx/project-edits/project-edits.effects";
import { ReleaseEffects } from "../files/_ngrx/release/release.effects";
import { SystemEffects } from "../system/_ngrx/system.effects";
import { TableEffects } from "../files/_ngrx/table/table.effects";
Expand All @@ -26,6 +27,7 @@ export const AppEffects = [
IntegrationEffects,
MatrixEffects,
ProjectEffects,
ProjectEditsEffects,
ReleaseEffects,
SystemEffects,
TableEffects,
Expand Down
12 changes: 11 additions & 1 deletion spa/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { filter, map, takeUntil } from "rxjs/operators";
import { Config } from "./config/config.model";
import { selectConfigConfig } from "./config/_ngrx/config.selectors";
import { SetViewStateAction } from "./files/_ngrx/file-facet-list/set-view-state.action";
import { ClearReleaseReferrerAction } from "./files/_ngrx/release/clear-release-referrer.action";
import { FetchProjectEditsRequestAction } from "./files/_ngrx/project-edits/fetch-project-edits-request.action";
import { EntityName } from "./files/shared/entity-name.model";
import { FileFacetName } from "./files/shared/file-facet-name.model";
import { QueryStringFacet } from "./files/shared/query-string-facet.model";
Expand All @@ -28,7 +30,6 @@ import { HealthRequestAction } from "./system/_ngrx/health/health-request.action
import { selectHealth, selectIndex } from "./system/_ngrx/system.selectors";
import { IndexRequestAction } from "./system/_ngrx/index/index-request.action";
import { SystemState } from "./system.state";
import { ClearReleaseReferrerAction } from "./files/_ngrx/release/clear-release-referrer.action";

@Component({
selector: "app-root",
Expand Down Expand Up @@ -125,6 +126,14 @@ export class AppComponent implements OnInit, OnDestroy {
return !!params["filter"];
}

/**
* Load project edits data from local JSON files.
*/
private loadProjectEditsData(): void {

this.store.dispatch(new FetchProjectEditsRequestAction());
}

/**
* Load release data from local JSON files.
*/
Expand Down Expand Up @@ -285,6 +294,7 @@ export class AppComponent implements OnInit, OnDestroy {
this.setAppStateFromURL();
this.systemCheck();
this.loadReleaseData();
this.loadProjectEditsData();
this.initReleaseReferrerListener();

this.config$ = this.store.pipe(
Expand Down
2 changes: 2 additions & 0 deletions spa/src/app/files/_ngrx/file.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as fileManifestReducer from "./file-manifest/file-manifest.reducer";
import * as integrationReducer from "./integration/integration.reducer";
import * as matrixReducer from "./matrix/matrix.reducer";
import * as projectReducer from "./project/project.reducer";
import * as projectEditsReducer from "./project-edits/project-edits.reducer";
import * as releaseReducer from "./release/release.reducer";
import * as tableReducer from "./table/table.reducer";
import * as searchReducer from "./search/search.reducer";
Expand All @@ -23,6 +24,7 @@ export const reducer = {
integration: integrationReducer.reducer,
matrix: matrixReducer.reducer,
project: projectReducer.reducer,
projectEdits: projectEditsReducer.reducer,
release: releaseReducer.reducer,
search: searchReducer.reducer,
tableState: tableReducer.reducer
Expand Down
2 changes: 2 additions & 0 deletions spa/src/app/files/_ngrx/file.state.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { EntityName } from "../shared/entity-name.model";
import * as searchStateMock from "./search/search.state.mock";
import { IntegrationState } from "./integration/integration.state";
import { ReleaseState } from "./release/release.state";
import { ProjectEditsState } from "./project-edits/project-edits.state";

/**
* Default project state - current tab is projects, no selected search terms
Expand All @@ -30,6 +31,7 @@ export const DEFAULT_PROJECTS_STATE = {
integration: IntegrationState.getDefaultState(),
matrix: MatrixState.getDefaultState(),
project: ProjectState.getDefaultState(),
projectEdits: ProjectEditsState.getDefaultState(),
release: ReleaseState.getDefaultState(),
search: SearchState.getDefaultState(),
tableState: getDefaultTableState(),
Expand Down
2 changes: 2 additions & 0 deletions spa/src/app/files/_ngrx/file.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FileSummaryState } from "./file-summary/file-summary.state";
import { IntegrationState } from "./integration/integration.state";
import { MatrixState } from "./matrix/matrix.state";
import { ProjectState } from "./project/project.state";
import { ProjectEditsState } from "./project-edits/project-edits.state";
import { ReleaseState } from "./release/release.state";
import { SearchState } from "./search/search.state";
import { TableState } from "./table/table.state";
Expand All @@ -25,6 +26,7 @@ export interface FileState {
integration: IntegrationState,
matrix: MatrixState;
project: ProjectState;
projectEdits: ProjectEditsState,
release: ReleaseState,
search: SearchState;
tableState: TableState;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Action that is triggered on load of app, to read local JSON project edits data into store.
*/

// Core dependencies
import { Action } from "@ngrx/store";

export class FetchProjectEditsRequestAction implements Action {
public static ACTION_TYPE = "PROJECT.FETCH_EDITS_REQUEST";
public readonly type = FetchProjectEditsRequestAction.ACTION_TYPE;
constructor() {}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Action that is triggered when project edits data has been successfully read from local JSON.
*/

// Core dependencies
import { Action } from "@ngrx/store";

// App dependencies
import { Project } from "../../shared/project.model";

export class FetchProjectEditsSuccessAction implements Action {
public static ACTION_TYPE = "PROJECT.FETCH_EDITS_SUCCESS";
public readonly type = FetchProjectEditsSuccessAction.ACTION_TYPE;
constructor(public readonly projects: Project[]) {}
}

50 changes: 50 additions & 0 deletions spa/src/app/files/_ngrx/project-edits/project-edits.effects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Coordination of side effects from project edits-related functionality.
*/

// Core dependencies
import { Injectable } from "@angular/core";
import { Actions, Effect, ofType } from "@ngrx/effects";
import { Action, select, Store } from "@ngrx/store";
import { Observable, of } from "rxjs";
import { map, switchMap, take } from "rxjs/operators";

// App dependencies
import { FetchProjectEditsRequestAction } from "./fetch-project-edits-request.action";
import { FetchProjectEditsSuccessAction } from "./fetch-project-edits-success.action";
import { AppState } from "../../../_ngrx/app.state";
import { ProjectEditsService } from "../../shared/project-edits.service";

@Injectable()
export class ProjectEditsEffects {

/**
* @param {Store<AppState>} store
* @param {Actions} actions$
* @param {ProjectEditsService} projectEditsService
*/
constructor(private store: Store<AppState>,
private actions$: Actions,
private projectEditsService: ProjectEditsService) {
}

/**
* Trigger fetch of project edits.
*/
@Effect()
fetchProjectEdits: Observable<Action> = this.actions$
.pipe(
ofType(FetchProjectEditsRequestAction.ACTION_TYPE),
switchMap(() => {

return this.projectEditsService.fetchProjectEdits();
}),
map((projects) => {

return new FetchProjectEditsSuccessAction(projects);
})
);
}
14 changes: 14 additions & 0 deletions spa/src/app/files/_ngrx/project-edits/project-edits.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Model of project edits-related state, persisted in local store.
*/

// App dependencies
import { Project } from "../../shared/project.model";

export interface ProjectEdits {
projects: Project[];
projectsById: Map<string, Project>;
}
29 changes: 29 additions & 0 deletions spa/src/app/files/_ngrx/project-edits/project-edits.reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Reducer responsible for updating project edits-related state.
*/

// Core dependencies
import { Action } from "@ngrx/store";

// App dependencies
import { FetchProjectEditsRequestAction } from "./fetch-project-edits-request.action";
import { FetchProjectEditsSuccessAction } from "./fetch-project-edits-success.action";
import { ProjectEditsState } from "./project-edits.state";

export function reducer(state: ProjectEditsState = ProjectEditsState.getDefaultState(), action: Action): ProjectEditsState {

switch (action.type) {

case FetchProjectEditsRequestAction.ACTION_TYPE:
return state.fetchProjectEditsRequest();

case FetchProjectEditsSuccessAction.ACTION_TYPE:
return state.fetchProjectEditsSuccess(action as FetchProjectEditsSuccessAction);

default:
return state;
}
}
33 changes: 33 additions & 0 deletions spa/src/app/files/_ngrx/project-edits/project-edits.selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Selectors for querying project edits-related state from the file store.
*/

// Core dependencies
import { createFeatureSelector, createSelector } from "@ngrx/store";
import { ProjectEditsState } from "./project-edits.state";

// App dependencies

/**
* Returns the project edits-related slice of state.
*/
export const selectProjectEdits = createFeatureSelector<ProjectEditsState>("projectEdits");

/**
* Returns all projects.
*/
export const selectProjects =
createSelector(selectProjectEdits, (state) => state.projects);

/**
* Returns the project with the specified ID.
*/
export const selectProjectById =
createSelector(selectProjectEdits, (state, props) => {
return state.projectsById.get(props.id) || {};
});


54 changes: 54 additions & 0 deletions spa/src/app/files/_ngrx/project-edits/project-edits.state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Human Cell Atlas
* https://www.humancellatlas.org/
*
* Representation of project edits-related state persisted in local store.
*/

// App dependencies
import { FetchProjectEditsSuccessAction } from "./fetch-project-edits-success.action";
import { ProjectEdits } from "./project-edits.model";
import { Project } from "../../shared/project.model";

export class ProjectEditsState implements ProjectEdits {

projects: Project[];
projectsById: Map<string, Project>;

/**
* @param {Project[]} projects
*/
constructor(projects) {

this.projects = projects;
this.projectsById = projects.reduce((accum, project) => {
accum.set(project.entryId, project);
return accum;
}, new Map<string, Project>());
}

/**
* @returns {ProjectEditsState}
*/
public fetchProjectEditsRequest(): ProjectEditsState {
return this;
}

/**
* Project edits data has been successfully read from local JSON, store it.
*
* @param {FetchProjectEditsSuccessAction} action
* @returns {ProjectEditsState}
*/
public fetchProjectEditsSuccess(action: FetchProjectEditsSuccessAction): ProjectEditsState {

return new ProjectEditsState(action.projects);
}

/**
* @returns {ProjectEditsState}
*/
public static getDefaultState() {
return new ProjectEditsState([]);
}
}
20 changes: 17 additions & 3 deletions spa/src/app/files/_ngrx/table/table.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ import {
FetchProjectSuccessAction,
} from "./table.actions";
import { FetchFileFacetsRequestAction } from "../file-facet-list/file-facet-list.actions";
import { selectTableQueryParams } from "../file.selectors";
import { FetchFileSummaryRequestAction } from "../file-summary/file-summary.actions";
import { FetchTableDataRequestAction } from "./fetch-table-data-request.action";
import { FetchTableDataSuccessAction } from "./fetch-table-data-success.action";
import { FetchTableModelRequestAction } from "./fetch-table-model-request.action";
import { FetchTableModelSuccessAction } from "./fetch-table-model-success.action";
import { selectProjectById } from "../project-edits/project-edits.selectors";
import { EntityName } from "../../shared/entity-name.model";
import { SelectProjectIdAction } from "../search/select-project-id.action";
import { selectTableQueryParams } from "../file.selectors";
import { EntitySearchResults } from "../../shared/entity-search-results.model";
import { DEFAULT_TABLE_PARAMS } from "../../table/table-params.model";
import { FilesService } from "../../shared/files.service";
Expand Down Expand Up @@ -114,13 +115,26 @@ export class TableEffects {
);

/**
* Trigger fetch and display of project, when selected from the project table.
* Trigger fetch and display of project, when selected from the project table. Must also grab projects edit data from
* the store to update publication and contributor details, where specifed.
*/
@Effect()
fetchProject: Observable<Action> = this.actions$
.pipe(
ofType(FetchProjectRequestAction.ACTION_TYPE),
switchMap((action: FetchProjectRequestAction) => this.projectService.fetchProjectById(action.projectId)),
switchMap((action: FetchProjectRequestAction) => {

return this.store.pipe(
select(selectProjectById, {id: action.projectId}),
map((updatedProject: Project) => {

// Grab the project from the release
return {action, updatedProject};
})
);
}),
switchMap(({action, updatedProject}) =>
this.projectService.fetchProjectById(action.projectId, updatedProject)),
map((project: Project) => new FetchProjectSuccessAction(project))
);

Expand Down
2 changes: 2 additions & 0 deletions spa/src/app/files/files.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import { ProjectNavComponent } from "./project-nav/project-nav.component";
import { ProjectOverviewComponent } from "./project-overview/project-overview.component";
import { ProjectOverviewDataSummaryComponent } from "./project-overview-data-summary/project-overview-data-summary.component";
import { ProjectReleaseComponent } from "./project-release/project-release.component";
import { ProjectEditsService } from "./shared/project-edits.service";
import { ProjectService } from "./project/project.service";
import { ProjectSummaryStatsComponent } from "./project-summary-stats-component/project-summary-stats.component";
import { ProjectViewFactory } from "./project-view/project-view.factory";
Expand Down Expand Up @@ -239,6 +240,7 @@ import { ReleaseVisualizationsModalContainerComponent } from "./releases/visuali
IntegrationService,
MatrixService,
ProjectService,
ProjectEditsService,
ProjectViewFactory,
ReleaseService,
SearchTermService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { GTMService } from "../../../shared/gtm/gtm.service";
import { GACategory } from "../../../shared/gtm/ga-category.model";
import { GAAction } from "../../../shared/gtm/ga-action.model";
import { GADimension } from "../../../shared/gtm/ga-dimension.model";
import { ReleaseName } from "../../releases/release-name.model";
import { ToolName } from "../../shared/tool-name.model";

@Component({
Expand Down
Loading