Commit adadcc2e authored by Matija Obreza's avatar Matija Obreza
Browse files

Subsets

- Subsets client services, actions and models
- BrowsePage
- DisplayPage
parent 123e998e
......@@ -16,7 +16,7 @@ stages:
before_script:
- npm install
# Needs to be uncommented if node:version us updated
# - npm rebuild node-sass
- npm rebuild node-sass
artifacts:
name: "${CI_PROJECT_NAME}-${CI_COMMIT_REF_NAME}"
expire_in: 1 day
......
......@@ -17,7 +17,9 @@
"label": {
"crop": "Crop",
"crop_plural": "Crops",
"metadata": "Record metadata"
"metadata": "Record metadata",
"subset": "Subset",
"subset_plural": "Subsets"
},
"m": {
"crop": {
......@@ -34,7 +36,8 @@
"Home": "Home",
"My Dashboard": "My dashboard",
"My profile": "My profile",
"Partners": "Partners"
"Partners": "Partners",
"Subsets": "Subsets"
},
"p": {
"crop": {
......@@ -109,6 +112,9 @@
"species": "Species",
"subtaxa": "Subtaxon"
}
},
"subsets": {
"title": "Title"
}
}
}
......@@ -17711,6 +17711,11 @@
"requires-port": "^1.0.0"
}
},
"url-template": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
"integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE="
},
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
......
import SubsetService from 'service/genesys/SubsetService';
import FilteredPage, { IPageRequest } from 'model/FilteredPage';
import Subset from 'model/Subset';
import SubsetFilter from 'model/SubsetFilter';
/**
* Action addAccessions
*
* @param UUID UUID
* @param version version
* @param accessionIds accessionIds
*/
export const addAccessions = (UUID: string, version: number, accessionIds: string[]) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.addAccessions(authorization, UUID, version, accessionIds);
};
/**
* Action create
*
* @param subset subset
*/
export const create = (subset: Subset) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.create(authorization, subset);
};
/**
* Action list
*
* @param filter filter
* @param d d
* @param l l
* @param p p
* @param s s
*/
export const list = (filter: string | SubsetFilter, page: IPageRequest) => (dispatch, getState): Promise<FilteredPage<Subset>> => {
const authorization = getState().login.access_token;
return SubsetService.list(authorization, filter, page);
};
/**
* Action removeAccessions
*
* @param UUID UUID
* @param version version
* @param accessionsUuids accessionsUuids
*/
export const removeAccessions = (UUID: string, version: number, accessionsUuids: string[]) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.removeAccessions(authorization, UUID, version, accessionsUuids);
};
/**
* Action update
*
* @param subset subset
*/
export const update = (subset: Subset) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.update(authorization, subset);
};
/**
* Action get
*
* @param UUID UUID
*/
export const get = (UUID: string) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.get(authorization, UUID);
};
/**
* Action delete
*
* @param UUID UUID
* @param version version
*/
export const remove = (UUID: string, version: number) => (dispatch, getState): Promise<Subset> => {
const authorization = getState().login.access_token;
return SubsetService.remove(authorization, UUID, version);
};
......@@ -4,9 +4,11 @@ import { stringify } from 'query-string';
export function navigateTo(path: string, query?: object) {
return (dispatch) => {
if (! query) {
dispatch(push(path));
dispatch(push(path ? path : ''));
} else {
dispatch(push(`${path}?` + stringify(query)));
dispatch(push(`${path ? path : ''}?` + stringify(query)));
}
};
}
export default navigateTo;
/**
* This is a top-level group for actions in /subsets/* routes.
*/
import navigateTo from 'actions/navigation';
import FilteredPage, { IPageRequest } from 'model/FilteredPage';
import Subset from 'model/Subset';
import SubsetFilter from 'model/SubsetFilter';
import { list as listSubsets, get } from 'actions/genesys/subsetService';
import { RECEIVE_SUBSETS, RECEIVE_SUBSET } from 'constants/subsets';
const receiveSubsets = (paged: FilteredPage<Subset>, error = null) => ({
type: RECEIVE_SUBSETS,
payload: { paged, error },
});
const receiveSubset = (subset: Subset, error = null) => ({
type: RECEIVE_SUBSET,
payload: { subset, error },
});
export { listSubsets as listSubsetsPromise };
export const updateRoute = (paged: FilteredPage<Subset>) => (dispatch) => {
const qs = {
f: paged.filterCode || undefined,
s: paged.sort[0].property === Subset.DEFAULT_SORT.property ? undefined : paged.sort[0].property,
d: paged.sort[0].direction === Subset.DEFAULT_SORT.direction ? undefined : paged.sort[0].direction,
};
dispatch(navigateTo(null, qs));
};
export const applyFilters = (filters: string | SubsetFilter, page: IPageRequest = { page: 0 }) => (dispatch) => {
console.log('Applying new filter', filters);
return dispatch(listSubsets(filters, page))
.then((paged) => {
dispatch(receiveSubsets(paged));
dispatch(updateRoute(paged));
}).catch((error) => {
console.log(`API response ${error.response.status}`, error.response);
dispatch(receiveSubsets(null, error.response));
});
};
export const loadSubsetsPage = (page: IPageRequest) => (dispatch, getState) => {
const filterCode = getState().subsets.paged.filterCode;
return dispatch(listSubsets(filterCode, page))
.then((paged) => {
dispatch(receiveSubsets(paged));
dispatch(updateRoute(paged));
}).catch((error: { response }) => {
console.log(`API response ${error.response.status}`, error.response);
dispatch(receiveSubsets(null, error.response));
});
};
export const loadSubset = (uuid: string) => (dispatch) => {
return dispatch(get(uuid))
.then((subset) => {
dispatch(receiveSubset(subset));
}).catch((error) => {
console.log(`API response ${error.response.status}`, error.response);
dispatch(receiveSubset(null, error.response));
});
};
export const RECEIVE_SUBSETS = 'subsets/RECEIVE_SUBSETS';
export const RECEIVE_SUBSET = 'subsets/RECEIVE_SUBSET';
export const SUBSET_FILTERFORM = 'Form/Subset/SUBSET_FILTERFORM';
export const SUBSET_FORM = 'Form/Subset/SUBSET_FORM';
/*
* Defined in OpenAPI as '#/definitions/DateFilter'
*/
class DateFilter {
public between: Date[];
public ge: Date;
public gt: Date;
public le: Date;
public lt: Date;
}
export default DateFilter;
import Page, { IPageRequest } from 'model/Page';
/*
* Defined in OpenAPI as '#/definitions/Page<T>'
*/
class FilteredPage<T> extends Page<T> {
filterCode: string;
filter: any;
}
export { FilteredPage as default, IPageRequest };
/*
* Defined in OpenAPI as '#/definitions/Page<T>'
*/
class Page<T> {
public content: T[];
public first: boolean;
public last: boolean;
public number: number;
public numberOfElements: number;
public size: number;
public sort: ISort[];
public totalElements: number;
public totalPages: number;
}
export interface ISort {
ascending: boolean;
descending: boolean;
direction: string;
property: string;
}
export interface IPageRequest {
page?: number; // page number
size?: number; // page size
direction?: string; // direction
properties?: string[]; // sort by properties
}
export default Page;
/*
* Defined in OpenAPI as '#/definitions/StringFilter'
*/
class StringFilter {
public contains: string;
public eq: string;
public sw: string;
}
export default StringFilter;
/*
* Defined in OpenAPI as '#/definitions/Subset'
*/
class Subset {
public accessionCount: number;
public accessionIds: any[];
public active: boolean;
public createdBy: number;
public createdDate: Date;
public dateCreated: string;
public description: string;
public id: number;
public lastModifiedBy: number;
public lastModifiedDate: Date;
public published: boolean;
public publisher: string;
public rights: string;
public title: string;
public uuid: string;
public version: number;
public wiewsCode: string;
public static DEFAULT_SORT = {
property: 'title',
direction: 'ASC',
};
public static SORT_OPTIONS = {
title: { label: 'Title', dir: 'ASC' },
accessionCount: { label: 'Number of accessions', dir: 'ASC' },
publisher: { label: 'Publisher', dir: 'ASC' },
lastModifiedDate: { label: 'Last updated', dir: 'DESC' },
};
}
export default Subset;
import DateFilter from 'model/DateFilter';
import StringFilter from 'model/StringFilter';
/*
* Defined in OpenAPI as '#/definitions/SubsetFilter'
*/
class SubsetFilter {
public active: boolean;
public createdBy: number[];
public createdDate: DateFilter;
public dateCreated: StringFilter;
public description: StringFilter;
public id: number[];
public institutes: string[];
public lastModifiedBy: number[];
public lastModifiedDate: DateFilter;
public published: boolean;
public publisher: string[];
public rights: string[];
public title: StringFilter;
public uuid: string[];
public version: number[];
}
export default SubsetFilter;
......@@ -99,3 +99,7 @@ export class SidPermissions extends Permissions {
return 'org.genesys.blocks.security.serialization.SidPermissions';
}
}
export interface IUserPermissions {
_permissions: Permissions;
}
import { fixDate, arraysEqual } from 'utilities';
import { fixDate } from 'utilities';
// import * as naturalCompare from 'string-natural-compare';
// Make sure we have compatible reducers
......@@ -100,136 +100,3 @@ export abstract class UuidModel extends AuditedVersionedModel {
super(obj);
}
}
export class ClassPK extends BasicModel {
public clazz: string = 'org.croptrust.auditlog.model.ClassPK';
public classname: string;
public constructor(obj?) {
super(obj);
}
}
/// Sort
export interface ISort {
direction: string;
ascending: boolean;
property: string;
}
/// Paginated list
export class Page<T> {
public content: T[];
public first: boolean;
public last: boolean;
public number: number;
public numberOfElements: number;
public size: number;
public totalElements: number;
public totalPages: number;
public sort?: ISort[];
public filter?: object;
public filterCode?: string;
public constructor(obj?, conv?: (o: any) => T) {
if (obj !== null && obj !== undefined) {
const props = Object.keys(obj);
for (const prop of props) { this[prop] = obj[prop]; }
if (this.content !== null && this.content && conv !== undefined) {
this.content = this.content.map((x) => conv(x));
}
}
}
public static from(list: object[], total: number = 0, page: number = 0, results: number = 10, sortBy: string = null): Page<object> {
if (list === undefined || list === null) {
return null;
}
// const items = [ ...list ];
// items.sort((a, b) => naturalCompare(a[sortBy], b[sortBy]));
const startPos: number = page * results;
const endPos: number = startPos + results;
const content = list.slice(startPos, endPos);
const x = new Page<object>({
size: results,
totalElements: total,
totalPages: Math.ceil(total / results),
number: page,
numberOfElements: content.length,
first: page === 0,
last: total <= endPos,
sort: [{ property: sortBy }],
content,
});
// console.log('Done', x);
return x;
}
}
export class Pagination<T> extends EmptyModel {
public page: number;
public size: number;
// TODO Should we be using DataOrder (below)?
public sort: string[] | string;
public dir: string[] | string;
public filter: T;
public filterCode: string;
public constructor(obj?) {
super(obj);
}
public equals(other: Pagination<T>): boolean {
if (other === null) {
return false;
}
if (this.page !== other.page) {
return false;
}
if (this.size !== other.size) {
return false;
}
if (this.filterCode !== other.filterCode) {
return false;
}
if (JSON.stringify(this.sort) !== JSON.stringify(other.sort)) {
return false;
}
return JSON.stringify(this.dir) === JSON.stringify(other.dir);
}
}
export class DataOrder {
public direction: string = 'ASC';
public sort: string[];
public constructor(sort: string = '', direction: string = 'ASC') {
this.sort = [sort];
this.direction = direction;
}
public equals(other: DataOrder): boolean {
return other !== null && other !== undefined && other.direction === this.direction && arraysEqual(other.sort, this.sort);
}
}
export class CurrentPermissions extends EmptyModel {
public create: boolean;
public read: boolean;
public write: boolean;
public delete: boolean;
public manage: boolean;
public constructor(obj?) {
if (obj) {
super(obj);
}
}
}
export interface IUserPermissions {
_permissions: CurrentPermissions;
}
......@@ -8,6 +8,7 @@ import history from './history';
import pageTitle from './pageTitle';
import snackbar from './snackbar';
import filterCode from './filterCode';
import subsets from './subsets';
const rootReducer = combineReducers({
login,
......@@ -19,6 +20,7 @@ const rootReducer = combineReducers({
filterCode,
routing: routerReducer,
form: formReducer,
subsets,
});
export default rootReducer;
import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model';
import { RECEIVE_SUBSETS, RECEIVE_SUBSET } from 'constants/subsets';
import FilteredPage from 'model/FilteredPage';
import Subset from 'model/Subset';
const INITIAL_STATE: {
subset: Subset;
subsetError: any;
paged: FilteredPage<Subset>;
pagedError: any;
} = {
subset: null,
subsetError: null,
paged: null,
pagedError: null,
};
function subsets(state = INITIAL_STATE, action: IReducerAction) {
switch (action.type) {
case RECEIVE_SUBSET: {
const { subset, error } = action.payload;
return update(state, {
subset: { $set: subset },
subsetError: { $set: error },
});
}
case RECEIVE_SUBSETS: {
const { paged, error } = action.payload;
return update(state, {
paged: { $set: paged },
pagedError: { $set: error },
});
}
default:
return state;
}
}
export default subsets;
import authenticatedRequest from 'utilities/requestUtils';
import * as _ from 'lodash';
import {API_BASE_URL} from 'constants/apiURLS';
import {Page} from 'model/common.model';
import Page from 'model/Page