Commit c081c364 authored by Maksym Tishchenko's avatar Maksym Tishchenko Committed by Matija Obreza
Browse files

Admin: Managing SysLang

parent bc6ff00f
......@@ -95,6 +95,8 @@
"Site_plural": "Sites",
"SysGroup": "User group",
"SysGroup_plural": "User groups",
"SysLang": "Language",
"SysLang_plural": "Languages",
"User": "User",
"User_plural": "Users",
"WebUser": "Web User",
......@@ -1237,6 +1239,14 @@
"sysLang": "Language",
"title": "Title",
"description": "Description"
},
"SysLang": {
"iso6393Tag": "ISO 639 3 Tag",
"ietfTag": "IEFT Tag",
"scriptDirection": "Script Direction",
"title": "Title",
"description": "Description",
"isEnabled": "Is Enabled?"
}
}
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ class SysLang {
public ownedBy: string;
public ownedDate: Date;
public description: string;
public isEnabled: string;
public id: number;
public ietfTag: string;
public iso6393Tag: string;
......
......@@ -80,6 +80,8 @@
"Site_plural": "Sites",
"SysGroup": "User group",
"SysGroup_plural": "User groups",
"SysLang": "Language",
"SysLang_plural": "Languages",
"User": "User",
"User_plural": "Users",
"WebUser": "Web User",
......@@ -1225,5 +1227,13 @@
"sysLang": "Language",
"title": "Title",
"description": "Description"
},
"SysLang": {
"iso6393Tag": "ISO 639 3 Tag",
"ietfTag": "IEFT Tag",
"scriptDirection": "Script Direction",
"title": "Title",
"description": "Description",
"isEnabled": "Is Enabled?"
}
}
......@@ -6,6 +6,7 @@ import { AxiosInstance, AxiosRequestConfig } from 'axios';
import CodeValueInfo from '@gringlobal-ce/client/model/gringlobal/CodeValueInfo';
import SysLang from '@gringlobal-ce/client/model/gringlobal/SysLang';
import AppSetting from '@gringlobal-ce/client/model/gringlobal/AppSetting';
import { Page } from '@gringlobal-ce/client/model/page';
const URL_CODE_VALUES_LIST = '/api/v1/app/codes';
// const URL_APP_RESOURCES_LIST = UrlTemplate.parse('/api/v1/app/resources/{appName}/{lang}');
......@@ -155,7 +156,7 @@ class ApplicationService {
*
* @param xhrConfig additional xhr config
*/
public appSettingsList = (xhrConfig?: AxiosRequestConfig): Promise<AppSetting> => {
public appSettingsList = (xhrConfig?: AxiosRequestConfig): Promise<Page<AppSetting>> => {
const apiUrl = URL_APP_SETTINGS_LIST;
// console.log(`Fetching from ${apiUrl}`);
......@@ -166,7 +167,7 @@ class ApplicationService {
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as AppSetting);
}).then(({ data }) => data as Page<AppSetting>);
}
/**
......
import * as UrlTemplate from 'url-template';
import * as QueryString from 'query-string';
import { AxiosInstance, AxiosRequestConfig } from 'axios';
import { SysLang } from '@gringlobal-ce/client/model/gringlobal';
import { IPageRequest, Page } from '@gringlobal-ce/client/model/page';
const URL_UPDATE = `/api/v1/admin/syslang`;
const URL_CREATE = `/api/v1/admin/syslang`;
const URL_UPSERT_MANY = `/api/v1/admin/syslang/upsert`;
const URL_UPDATE_MANY = `/api/v1/admin/syslang/many`;
const URL_CREATE_MANY = `/api/v1/admin/syslang/many`;
const URL_REMOVE_MANY = `/api/v1/admin/syslang/many`;
const URL_GET = UrlTemplate.parse(`/api/v1/admin/syslang/{id}`);
const URL_REMOVE = UrlTemplate.parse(`/api/v1/admin/syslang/{id}`);
const URL_LIST = `/api/v1/admin/syslang/list`;
/**
* SysLangAdmin service
*
* GRIN-Global CE API
*/
class SysLangAdminService {
private _axios: AxiosInstance;
public constructor(axios: AxiosInstance) {
this._axios = axios;
}
/**
* update at /api/v1/admin/syslang
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public update = (data: SysLang, xhrConfig?: AxiosRequestConfig): Promise<SysLang> => {
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 SysLang);
}
/**
* create at /api/v1/admin/syslang
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public create = (data: SysLang, xhrConfig?: AxiosRequestConfig): Promise<SysLang> => {
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 SysLang);
}
/**
* upsertMany at /api/v1/admin/syslang/upsert
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public upsertMany = (data: SysLang[], xhrConfig?: AxiosRequestConfig): Promise<SysLang[]> => {
const apiUrl = URL_UPSERT_MANY;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'PUT',
...content,
}).then(({ data }) => data as SysLang[]);
}
/**
* updateMany at /api/v1/admin/syslang/many
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public updateMany = (data: SysLang[], xhrConfig?: AxiosRequestConfig): Promise<SysLang[]> => {
const apiUrl = URL_UPDATE_MANY;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'PUT',
...content,
}).then(({ data }) => data as SysLang[]);
}
/**
* createMany at /api/v1/admin/syslang/many
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public createMany = (data: SysLang[], xhrConfig?: AxiosRequestConfig): Promise<SysLang[]> => {
const apiUrl = URL_CREATE_MANY;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as SysLang[]);
}
/**
* removeMany at /api/v1/admin/syslang/many
*
* @param data Request body
* @param xhrConfig additional xhr config
*/
public removeMany = (data: SysLang[], xhrConfig?: AxiosRequestConfig): Promise<SysLang[]> => {
const apiUrl = URL_REMOVE_MANY;
// console.log(`Fetching from ${apiUrl}`);
const content = { data };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as SysLang[]);
}
/**
* get at /api/v1/admin/syslang/{id}
*
* @param id undefined
* @param xhrConfig additional xhr config
*/
public get = (id: number, xhrConfig?: AxiosRequestConfig): Promise<SysLang> => {
const apiUrl = URL_GET.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 SysLang);
}
/**
* remove at /api/v1/admin/syslang/{id}
*
* @param id undefined
* @param xhrConfig additional xhr config
*/
public remove = (id: number, xhrConfig?: AxiosRequestConfig): Promise<SysLang> => {
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 SysLang);
}
/**
* list at /api/v1/admin/syslang/list
*
* @param page
* @param xhrConfig additional xhr config
*/
public list = (page: IPageRequest = {}, xhrConfig?: AxiosRequestConfig): Promise<Page<SysLang>> => {
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 = { /* No content in request body */ };
return this._axios.request({
...xhrConfig,
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as Page<SysLang>);
}
}
export default SysLangAdminService;
......@@ -27,6 +27,7 @@ import AppResourceService from '@gringlobal-ce/client/service/AppResourceService
import NameGroupService from '@gringlobal-ce/client/service/NameGroupService';
import SecuredActionService from '@gringlobal-ce/client/service/SecuredActionService';
import AdminAlertsService from '@gringlobal-ce/client/service/AdminAlertsService';
import SysLangAdminService from '@gringlobal-ce/client/service/SysLangAdminService';
import SourceDescriptorService from '@gringlobal-ce/client/service/SourceDescriptorService';
import SecurityService, { makeUISecurity } from '@gringlobal-ce/client/service/SecurityService';
import GenesysService from './GenesysService';
......@@ -138,6 +139,7 @@ const ConfiguredNameGroupService = new NameGroupService(serviceAxios);
const ConfiguredSecuredActionService = new SecuredActionService(serviceAxios)
const ConfiguredSourceDescriptorService = new SourceDescriptorService(serviceAxios);
const ConfiguredAdminAlertsService = new AdminAlertsService(serviceAxios)
const ConfiguredSysLangAdminService = new SysLangAdminService(serviceAxios)
const ConfiguredGenesysService = new GenesysService(serviceAxios)
......@@ -175,5 +177,6 @@ export {
ConfiguredSecuredActionService as SecuredActionService,
ConfiguredSourceDescriptorService as SourceDescriptorService,
ConfiguredAdminAlertsService as AdminAlertsService,
ConfiguredSysLangAdminService as SysLangAdminService,
ConfiguredGenesysService as GenesysService,
}
......@@ -1061,6 +1061,19 @@
}
}
},
"syslang": {
"admin": {
"p": {
"browse": {
"title": "Languages",
"label": {
"edit": "Edit language",
"add": "Add language"
}
}
}
}
},
"taxonomy": {
"navigation": {
"genus": "Genera",
......
......@@ -5,10 +5,11 @@ import { ApiCall } from '@gringlobal-ce/client/model/common';
import AppSetting from '@gringlobal-ce/client/model/gringlobal/AppSetting';
import { RECEIVE_APP_SETTING_ITEM, RECEIVE_APP_SETTING_LIST, REMOVE_APP_SETTING } from '_core/constants/appSetting';
import { Page } from '@gringlobal-ce/client/model/page';
const INITIAL_STATE: {
appSettingCall: ApiCall<AppSetting>,
appSettingListCall: ApiCall<AppSetting[]>,
appSettingListCall: ApiCall<Page<AppSetting>>,
} = {
appSettingCall: null,
appSettingListCall: null,
......@@ -29,14 +30,16 @@ export default (state = INITIAL_STATE, action: { type?: string, payload?: any }
const { data: appSettingList } = state.appSettingListCall;
const appSetting = apiCall.data;
const updatedIndex = appSettingList && appSettingList.findIndex((stateSetting) => +stateSetting.id === +appSetting.id);
const updatedIndex = appSettingList?.content?.findIndex((stateSetting) => +stateSetting.id === +appSetting.id);
if (updatedIndex !== undefined && updatedIndex !== -1) {
return update(state, {
appSettingCall: { $set: null },
appSettingListCall: {
data: {
[updatedIndex]: { $set: appSetting },
content: {
[updatedIndex]: { $set: appSetting },
}
},
},
});
......@@ -45,7 +48,9 @@ export default (state = INITIAL_STATE, action: { type?: string, payload?: any }
appSettingCall: { $set: null },
appSettingListCall: {
data: {
$set: [ ...appSettingList, appSetting ],
content: {
$set: [ ...appSettingList.content, appSetting ],
}
},
},
});
......@@ -58,12 +63,17 @@ export default (state = INITIAL_STATE, action: { type?: string, payload?: any }
case REMOVE_APP_SETTING: {
const { apiCall: { data } } = action.payload;
if (data) {
if (state.appSettingListCall && state.appSettingListCall.data) {
const updatedSettings = state.appSettingListCall.data.filter((setting) => setting.id !== data.id);
if (state.appSettingListCall?.data?.content) {
const updatedSettings = state.appSettingListCall.data.content.filter((setting) => setting.id !== data.id);
return update(state, {
appSettingListCall: {
data: {
$set: updatedSettings,
content: {
$set: updatedSettings,
},
totalElements: {
$apply: (total) => total - 1,
},
},
},
});
......
......@@ -95,6 +95,12 @@ function AdminMenu({ currentPath }: { currentPath: string }): JSX.Element {
</ListItem>
</Link>
<Divider />
<Link to="/admin/syslang">
<ListItem button className={ currentPath?.match('^/admin/syslang(/[0-9]+$|$)') && classes.selectedRoute }>
<ListItemText primary={ t('syslang.admin.p.browse.title') } />
</ListItem>
</Link>
<Divider />
<Link to="/admin/auditlog">
<ListItem button className={ currentPath?.match('^/admin/auditlog(/[0-9]+$|$)') && classes.selectedRoute }>
<ListItemText primary={ t('auditlog.admin.p.browse.title') } />
......
......@@ -21,10 +21,11 @@ import { showSnackbar } from '@gringlobal-ce/client/action/snackbar';
import CancelOutlinedIcon from '@material-ui/icons/CancelOutlined';
import EditIcon from '@material-ui/icons/Edit';
import FABMenu from '@gringlobal-ce/client/ui/common/button/FABMenu';
import { Page } from '@gringlobal-ce/client/model/page';
interface IBrowsePageProps extends React.ClassAttributes<any>, WithTranslation {
appSettingListCall: ApiCall<AppSetting[]>
getAppSettingList: () => AppSetting[];
appSettingListCall: ApiCall<Page<AppSetting>>
getAppSettingList: () => Page<AppSetting>;
receiveAppSettingSuccessAction: (appSetting: AppSetting) => void;
removeAppSettingsAction: (ids: number[]) => void;
showSnackbar: (snack: string) => void;
......@@ -65,7 +66,7 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
private rowsToggled = (selectedRows: number[]) => {
const { appSettingListCall } = this.props;
const selectedIds = selectedRows.map((rowIndex) => appSettingListCall.data[rowIndex].id)
const selectedIds = selectedRows.map((rowIndex) => appSettingListCall.data.content[rowIndex].id)
this.setState({ selected: selectedIds });
}
......@@ -144,9 +145,9 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
type="AppSetting"
onRowsToggled={ this.rowsToggled }
columns={ AppSettingsTableConfig.defaultColumns }
data={ appSettingListCall?.data }
data={ appSettingListCall?.data?.content }
tableConfig={ AppSettingsTableConfig }
total={ appSettingListCall?.data?.length }
total={ appSettingListCall?.data?.totalElements }
/>
{ selected.length === 0 &&
<AddNewButton action={ this.openAppSettingDialog }/>
......@@ -162,7 +163,7 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
? t('appsetting.admin.p.browse.label.edit')
: t('appsetting.admin.p.browse.label.add')
}
initialValues={ ! createNew ? appSettingListCall?.data?.find((setting) => +setting.id === +selected[0]) : {} }
initialValues={ ! createNew ? appSettingListCall?.data?.content?.find((setting) => +setting.id === +selected[0]) : {} }
size="sm"
/>
{ selected.length > 0 &&
......
......@@ -28,6 +28,7 @@ import appresource from 'appresource/reducer';
import sysGroup from 'sysgroup/reducer';
import securedAction from 'securedaction/reducer'
import method from 'method/reducer'
import sysLang from 'syslang/reducer'
const rootReducer = (history?) => (combineReducers({
// express reducers
......@@ -58,6 +59,7 @@ const rootReducer = (history?) => (combineReducers({
sysGroup,
securedAction,
method,
sysLang,
...coreReducers(history),
}));
......
......@@ -25,6 +25,7 @@ import { appResourceAdminRoutes } from 'appresource/routes';
import { sysGroupAdminRoutes } from 'sysgroup/routes';
import { securedActionAdminRoutes } from 'securedaction/routes';
import { appSettingsAdminRoutes } from 'appsetting/routes';
import { sysLangAdminRoutes } from 'syslang/routes';
import { auditLogAdminRoutes } from 'auditlog/routes'
import { invitroRoutes } from 'invitro/routes';
import { viabilityRoutes } from 'viability/routes';
......@@ -97,6 +98,7 @@ export const routes: IRoute[] = [
...securedActionAdminRoutes,
...appSettingsAdminRoutes,
...auditLogAdminRoutes,
...sysLangAdminRoutes,
],
},
{
......
......@@ -28,6 +28,7 @@ import { webUserAdminSagas } from 'webuser/action/admin';
import { appResourceAdminSagas } from 'appresource/action/admin';
import { sysGroupAdminSagas } from 'sysgroup/action/admin';
import { securedActionAdminSagas } from 'securedaction/action/admin';
import { sysLangAdminSagas } from "syslang/action/admin"
import { auditLogAdminSagas } from 'auditlog/action/admin';
import axios, { AxiosRequestConfig } from 'axios';
import { createUploader, watchOnProgress } from '_core/util/fileUploadUtil';
......@@ -61,6 +62,7 @@ export default function* () {
...appResourceAdminSagas,
...sysGroupAdminSagas,
...securedActionAdminSagas,
...sysLangAdminSagas,
...auditLogAdminSagas,
// if action has method
......
import { call, put, takeEvery } from 'redux-saga/effects';
// Constants
export const SAGA_RECEIVE_SYSLANG = 'saga/syslang/admin/RECEIVE_SYSLANG';
export const SAGA_LIST_SYSLANGS = 'saga/syslang/admin/LIST';
export const SAGA_REMOVE_SYSLANG = 'saga/syslang/admin/REMOVE_SYSLANG';
export const RECEIVE_SYSLANG = 'success/syslang/admin/RECEIVE_SYSLANG';
export const RECEIVE_SYSLANGS_LIST = 'success/syslang/admin/LIST';
export const REMOVE_SYSLANG = 'success/syslang/admin/REMOVE_SYSLANG';
// Model
import { IPageRequest, Page } from '@gringlobal-ce/client/model/page';
// Service
import { SysLangAdminService } from '@gringlobal-ce/client/service';
import { dereferenceReferences3 } from '@gringlobal-ce/client/utilities';
import { ApiCall } from '@gringlobal-ce/client/model/common';
import { sagaNavigate } from '@gringlobal-ce/client/action/navigation';
import { SysLang } from '@gringlobal-ce/client/model/gringlobal';
export const sysLangAdminSagas = [
takeEvery(SAGA_RECEIVE_SYSLANG, getSysLangSaga),
takeEvery(SAGA_LIST_SYSLANGS, listSysLangsSaga),
takeEvery(SAGA_REMOVE_SYSLANG, removeSysLangSaga),
];
function* getSysLangSaga(action) {
yield put({
type: 'API',
target: RECEIVE_SYSLANG,
method: SysLangAdminService.get,
params: [ action.payload.id ],
onSuccess: (sysLang: SysLang) => {
return sysLang;
},
});
}
export const receiveSysLang = (sysLang: SysLang) => (dispatch) => {
dispatch({
type: RECEIVE_SYSLANG,
payload: { apiCall: ApiCall.success(sysLang) },
});
};
export const getSysLangAction = (id: number) => ({
type: SAGA_RECEIVE_SYSLANG,
payload: { id },
});
function * listSysLangsSaga(action) {
yield put({
type: 'API',
target: RECEIVE_SYSLANGS_LIST,
method: SysLangAdminService.list,
params: [ action.payload.pageR ],
onSuccess: (sysLangs: Page<SysLang>) => {
dereferenceReferences3(sysLangs.content, {
coo: { id: [ 'ownedBy', 'createdBy', 'modifiedBy' ] },
});
return sysLangs;
},
});
}
export const listSysLangsAction = (pageR: IPageRequest = { page: 0, size: 100 }) => ({
type: SAGA_LIST_SYSLANGS,
payload: {
pageR,
},
});
export const loadMoreSysLangsAction = (sysLangs: Page<SysLang>) => {
return {