Commit 7fee466f authored by Oleksii Savran's avatar Oleksii Savran

List crop traits

parent dc66605e
......@@ -88,6 +88,23 @@
"previousState": "Previous State",
"newState": "New State"
},
"CropTrait": {
"categoryCode": "Category",
"codedName": "Name",
"crop": "Crop",
"dataTypeCode": "Data Type Code",
"id": "ID",
"isArchived": "Is archived",
"isCoded": "Is coded",
"isPeerReviewed": "Is peer reviewed",
"maxLength": "Maximum length",
"numericFormat": "Numeric format",
"numericMaximum": "Numeric maximum",
"numericMinimum": "Numeric minimum",
"ontologyUrl": "Ontology URL",
"originalValueFormat": "Original value format",
"originalValueTypeCode": "Original value Type Code"
},
"Geography": {
"geography": "Geography",
"currentGeography": "Current Valid Geography",
......
import Cooperator from '@gringlobal/client/model/gringlobal/Cooperator';
import Crop from '@gringlobal/client/model/gringlobal/Crop';
/**
* CropTrait
*
* GRIN-Global CE API
*/
class CropTrait {
public createdBy: number;
public createdDate: Date;
public modifiedBy: number;
public modifiedDate: Date;
public ownedBy: Cooperator;
public ownedDate: Date;
public categoryCode: string;
public codedName: string;
public crop: Crop; //
public dataTypeCode: string;
public id: number;
public isArchived: string;
public isCoded: string; //
public isPeerReviewed: string;
public maxLength: number;
public note: string;
public numericFormat: string;
public numericMaximum: number;
public numericMinimum: number;
public ontologyUrl: string;
public originalValueFormat: string;
public originalValueTypeCode: string;
public static CodeValues = {
dataTypeCode: 'CROP_TRAIT_DATA_TYPE',
categoryCode: 'DESCRIPTOR_CATEGORY',
}
}
export default CropTrait;
import Cooperator from '@gringlobal/client/model/gringlobal/Cooperator';
import CropTrait from '@gringlobal/client/model/gringlobal/CropTrait';
import RepositoryFile from '@gringlobal/client/model/repository/RepositoryFile';
/**
* CropTraitAttach
*
* GRIN-Global CE API
*/
class CropTraitAttach {
public createdBy: number;
public createdDate: Date;
public modifiedBy: number;
public modifiedDate: Date;
public ownedBy: Cooperator;
public ownedDate: Date;
public title: string;
public virtualPath: string;
public thumbnailVirtualPath: string;
public contentType: string;
public isWebVisible: string;
public sortOrder: number;
public note: string;
public repositoryFile: RepositoryFile;
public id: number;
public attachCooperator: Cooperator;
public attachDate: Date;
public attachDateCode: string;
public categoryCode: string;
public cropTrait: CropTrait;
public description: string;
}
export default CropTraitAttach;
import CropTraitAttach from '@gringlobal/client/model/gringlobal/CropTraitAttach';
import RepositoryFile from '@gringlobal/client/model/repository/RepositoryFile';
/**
* CropTraitAttachmentRequest
*
* GRIN-Global CE API
*/
class CropTraitAttachmentRequest {
public fileMetadata: RepositoryFile;
public attachMetadata: CropTraitAttach;
}
export default CropTraitAttachmentRequest;
import Cooperator from '@gringlobal/client/model/gringlobal/Cooperator';
import CropTrait from '@gringlobal/client/model/gringlobal/CropTrait';
/**
* CropTraitCode
*
* GRIN-Global CE API
*/
class CropTraitCode {
public createdBy: number;
public createdDate: Date;
public modifiedBy: number;
public modifiedDate: Date;
public ownedBy: Cooperator;
public ownedDate: Date;
public code: string;
public cropTrait: CropTrait;
public id: number;
}
export default CropTraitCode;
import Cooperator from '@gringlobal/client/model/gringlobal/Cooperator';
import CropTraitCode from '@gringlobal/client/model/gringlobal/CropTraitCode';
import RepositoryFile from '@gringlobal/client/model/repository/RepositoryFile';
/**
* CropTraitCodeAttach
*
* GRIN-Global CE API
*/
class CropTraitCodeAttach {
public createdBy: number;
public createdDate: Date;
public modifiedBy: number;
public modifiedDate: Date;
public ownedBy: Cooperator;
public ownedDate: Date;
public title: string;
public virtualPath: string;
public thumbnailVirtualPath: string;
public contentType: string;
public isWebVisible: string;
public sortOrder: number;
public note: string;
public repositoryFile: RepositoryFile;
public id: number;
public attachCooperator: Cooperator;
public attachDate: Date;
public attachDateCode: string;
public categoryCode: string;
public cropTraitCode: CropTraitCode;
public description: string;
}
export default CropTraitCodeAttach;
import CropTraitCodeAttach from '@gringlobal/client/model/gringlobal/CropTraitCodeAttach';
import RepositoryFile from '@gringlobal/client/model/repository/RepositoryFile';
/**
* CropTraitCodeAttachmentRequest
*
* GRIN-Global CE API
*/
class CropTraitCodeAttachmentRequest {
public fileMetadata: RepositoryFile;
public attachMetadata: CropTraitCodeAttach;
}
export default CropTraitCodeAttachmentRequest;
import CooperatorFilter from '@gringlobal/client/model/gringlobal/CooperatorFilter';
import DateFilter from '@gringlobal/client/model/common/DateFilter';
import StringFilter from '@gringlobal/client/model/common/StringFilter';
/**
* CropTraitFilter
*
* GRIN-Global CE API
*/
class CropTraitFilter {
public NOT: CropTraitFilter;
public NULL: string[];
public NOTNULL: string[];
public id: number[];
public createdBy: number[];
public createdDate: DateFilter;
public modifiedBy: number[];
public modifiedDate: DateFilter;
public ownedBy: CooperatorFilter;
public ownedDate: DateFilter;
public crop: number[];
public codedName: string[];
public categoryCode: string[];
public description: StringFilter;
}
export default CropTraitFilter;
......@@ -77,6 +77,23 @@
"previousState": "Previous State",
"newState": "New State"
},
"CropTrait": {
"categoryCode": "Category",
"codedName": "Name",
"crop": "Crop",
"dataTypeCode": "Data Type Code",
"id": "ID",
"isArchived": "Is archived",
"isCoded": "Is coded",
"isPeerReviewed": "Is peer reviewed",
"maxLength": "Maximum length",
"numericFormat": "Numeric format",
"numericMaximum": "Numeric maximum",
"numericMinimum": "Numeric minimum",
"ontologyUrl": "Ontology URL",
"originalValueFormat": "Original value format",
"originalValueTypeCode": "Original value Type Code"
},
"Geography": {
"geography": "Geography",
"currentGeography": "Current Valid Geography",
......
import * as UrlTemplate from 'url-template';
import * as QueryString from 'query-string';
import { AxiosInstance, AxiosRequestConfig } from 'axios';
import { IPageRequest } from '@gringlobal/client/model/page';
import CropTrait from '@gringlobal/client/model/gringlobal/CropTrait';
import CropTraitFilter from '@gringlobal/client/model/gringlobal/CropTraitFilter';
const URL_UPLOAD_FILE = UrlTemplate.parse('/api/v1/crop-trait/attach/{cropTraitId}');
const URL_GET_TRANSLATED = UrlTemplate.parse('/api/v1/crop-trait/{id}');
const URL_REMOVE = UrlTemplate.parse('/api/v1/crop-trait/{id}');
const URL_UPLOAD_TRAIT_CODE_FILE = UrlTemplate.parse('/api/v1/crop-trait/code/attach/{cropTraitCodeId}');
const URL_REMOVE_TRAIT_CODE_FILE = UrlTemplate.parse('/api/v1/crop-trait/code/attach/{cropTraitCodeId}/{attachmentId}');
const URL_REMOVE_FILE = UrlTemplate.parse('/api/v1/crop-trait/attach/{cropTraitId}/{attachmentId}');
const URL_UPDATE = '/api/v1/crop-trait';
const URL_CREATE = '/api/v1/crop-trait';
const URL_LIST = '/api/v1/crop-trait/list';
/**
* CropTrait service
*
* GRIN-Global CE API
*/
class CropTraitService {
private _axios: AxiosInstance;
public constructor(axios: AxiosInstance) {
this._axios = axios;
}
/**
* uploadFile at /api/v1/crop-trait/attach/{cropTraitId}
*
* @param data Request body
* @param cropTraitId undefined
* @param xhrConfig additional xhr config
*/
public uploadFile = (data: object, cropTraitId: number, xhrConfig?: AxiosRequestConfig): Promise<any> => { // todo: types
const apiUrl = URL_UPLOAD_FILE.expand({ cropTraitId });
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as undefined);
};
/**
* getTranslated at /api/v1/crop-trait/{id}
*
* @param id undefined
* @param xhrConfig additional xhr config
*/
public getTranslated = (id: number, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_GET_TRANSLATED.expand({ id });
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as undefined);
};
/**
* remove at /api/v1/crop-trait/{id}
*
* @param id undefined
* @param xhrConfig additional xhr config
*/
public remove = (id: number, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_REMOVE.expand({ id });
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as undefined);
};
/**
* uploadTraitCodeFile at /api/v1/crop-trait/code/attach/{cropTraitCodeId}
*
* @param data Request body
* @param cropTraitCodeId undefined
* @param xhrConfig additional xhr config
*/
public uploadTraitCodeFile = (data: object, cropTraitCodeId: number, xhrConfig?: AxiosRequestConfig): Promise<any> => { // todo: FormData
const apiUrl = URL_UPLOAD_TRAIT_CODE_FILE.expand({ cropTraitCodeId });
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as undefined);
};
/**
* removeTraitCodeFile at /api/v1/crop-trait/code/attach/{cropTraitCodeId}/{attachmentId}
*
* @param attachmentId undefined
* @param cropTraitCodeId undefined
* @param xhrConfig additional xhr config
*/
public removeTraitCodeFile = (attachmentId: number, cropTraitCodeId: number, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_REMOVE_TRAIT_CODE_FILE.expand({ attachmentId, cropTraitCodeId });
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as undefined);
};
/**
* removeFile at /api/v1/crop-trait/attach/{cropTraitId}/{attachmentId}
*
* @param attachmentId undefined
* @param cropTraitId undefined
* @param xhrConfig additional xhr config
*/
public removeFile = (attachmentId: number, cropTraitId: number, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_REMOVE_FILE.expand({ attachmentId, cropTraitId });
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as undefined);
};
/**
* update at /api/v1/crop-trait
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public update = (data: CropTrait, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_UPDATE;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'PUT',
...content,
}).then(({ data }) => data as undefined);
};
/**
* create at /api/v1/crop-trait
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public create = (data: CropTrait, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const apiUrl = URL_CREATE;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as undefined);
};
/**
* list at /api/v1/crop-trait/list
*
* @param data Request body
* @param page undefined
* @param xhrConfig additional xhr config
*/
public list = (data: CropTraitFilter, page?: IPageRequest, xhrConfig?: AxiosRequestConfig): Promise<any> => {
const qs = QueryString.stringify({
p: page.page || undefined,
l: page.size || undefined,
d: page.direction ? page.direction : undefined,
s: page.properties || undefined,
}, {});
const apiUrl = URL_LIST + (qs ? `?${qs}` : '');
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as undefined);
}
}
export default CropTraitService;
......@@ -15,6 +15,8 @@ import RepositoryService from '@gringlobal/client/service/RepositoryService';
import GeographyService from '@gringlobal/client/service/GeographyService';
import OAuthManagementService from '@gringlobal/client/service/OAuthManagementService';
import CropService from '@gringlobal/client/service/CropService';
import CropTraitService from '@gringlobal/client/service/CropTraitService';
import axios from 'axios';
import { clearCookies } from '@gringlobal/client/utilities';
import { ApiError } from '@gringlobal/client/model/common';
......@@ -103,6 +105,7 @@ const ConfiguredMethodService = new MethodService(serviceAxios);
const ConfiguredGeographyService = new GeographyService(serviceAxios);
const ConfiguredOAuthManagementService = new OAuthManagementService(serviceAxios);
const ConfiguredCropService = new CropService(serviceAxios);
const ConfiguredCropTraitService = new CropTraitService(serviceAxios);
export {
ConfiguredCooperatorService as CooperatorService,
......@@ -122,4 +125,5 @@ export {
ConfiguredGeographyService as GeographyService,
ConfiguredOAuthManagementService as OAuthManagementService,
ConfiguredCropService as CropService,
ConfiguredCropTraitService as CropTraitService,
}
......@@ -44,7 +44,7 @@ const styles = (theme) => ({
});
interface ISlotLayout extends React.ClassAttributes<any>, WithStyles {
fixedContent: React.ReactNode;
fixedContent?: React.ReactNode;
children: React.ReactNode; // scrollable content
}
......@@ -53,9 +53,11 @@ function SlotLayout(props: ISlotLayout): JSX.Element {
return (
<div className={ classes.layout }>
<div className={ classes.topWrapper }>
{ fixedContent }
</div>
{ fixedContent &&
<div className={ classes.topWrapper }>
{ fixedContent }
</div>
}
<div className={ classes.containerWrapper }>
{ children }
</div>
......
......@@ -209,6 +209,16 @@
"traits": "Traits",
"species": "Species"
}
},
"traitsDetails": {
"title": "Crop trait details"
}
}
},
"admin": {
"p": {
"traitsEdit": {
"title": "New crop trait"
}
}
}
......
import { put, takeEvery, call, take } from 'redux-saga/effects';
import { put, takeEvery, call, take, select } from 'redux-saga/effects';
// Constants
import {
ADMIN_RECEIVE_CROP,
ADMIN_RECEIVE_CROP_TRAIT,
SAGA_ADMIN_CREATE_CROP,
SAGA_ADMIN_RECEIVE_CROP,
SAGA_ADMIN_EDIT_CROP,
SAGA_ADMIN_CREATE_CROP_TRAIT,
SAGA_ADMIN_EDIT_CROP_TRAIT,
SAGA_ADMIN_RECEIVE_CROP_TRAIT,
} from 'crop/constants';
// Model
import Crop from '@gringlobal/client/model/gringlobal/Crop';
import CropTrait from '@gringlobal/client/model/gringlobal/CropTrait';
// Service
import { CropService } from '@gringlobal/client/service';
import { CropService, CropTraitService } from '@gringlobal/client/service';
// Action
import { sagaNavigate } from '@gringlobal/client/action/navigation';
import { receiveCropDetailsSaga } from './public';
......@@ -19,6 +25,9 @@ export const cropAdminSagas = [
takeEvery(SAGA_ADMIN_CREATE_CROP, createCropSaga),
takeEvery(SAGA_ADMIN_EDIT_CROP, editCropSaga),
takeEvery(SAGA_ADMIN_RECEIVE_CROP, getCropSaga),
takeEvery(SAGA_ADMIN_CREATE_CROP_TRAIT, createCropTraitSaga),
takeEvery(SAGA_ADMIN_EDIT_CROP_TRAIT, editCropTraitSaga),
takeEvery(SAGA_ADMIN_RECEIVE_CROP_TRAIT, getCropTraitSaga),
];
export const createCropAction = (crop: Crop) => ({
......@@ -36,6 +45,21 @@ export const getCropActionAdmin = (id: string | number) => ({
payload: { id },
});
export const createCropTraitAction = (cropTrait: CropTrait) => ({
type: SAGA_ADMIN_CREATE_CROP_TRAIT,
payload: { cropTrait },
});
export const editCropTraitAction = (cropTrait: CropTrait) => ({
type: SAGA_ADMIN_EDIT_CROP_TRAIT,
payload: { cropTrait },
});
export const getCropTraitAction = (id: string | number) => ({
type: SAGA_ADMIN_RECEIVE_CROP_TRAIT,
payload: { id },
});
function* createCropSaga(action) {
yield put({
type: 'API',
......@@ -98,3 +122,79 @@ function* getCropSaga(action) {
},
});
}
function* createCropTraitSaga(action) {
yield put({
type: 'API',
target: ADMIN_RECEIVE_CROP_TRAIT,
method: CropTraitService.create,
params: [action.payload.cropTrait],
onSuccess: (cropTrait: CropTrait) => {
return cropTrait;
},
});
yield take(ADMIN_RECEIVE_CROP);
const received = yield take(ADMIN_RECEIVE_CROP);