-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CM-138: User Groups Management implementation (#1)
* CM-139: base project configuration, eslint, main route * CM-139: basic structure of tasks view * CM-139: basic view of task traiage * CM-139: basic view of task triage * CM-139: task preview improvements * CM-139: import fix * CM-138: user groups management page and basic searcher * CM-138: reducer, actions, fetchTaskGroups, searcher * CM-138: taskExecutorsPicker, taskGroupPage, taskGroupHeadPanel * CM-138: fetch task group, clear on unmount * OTC-138: remove package-lock json * CM-138: implementation of create/update mutation, executors picker fix * CM-138: removal of console log * CM-138: filtering, sorting, searching improvements, executorsPicker fixes * CM-138: create PERFORM_MUTATION and adjust existing logic, constants fix * CM-138: name of function changed * CM-138: TaskExecutorsPicker fixes * CM-138: component name changed - TaskDetailsPage
- Loading branch information
1 parent
15162dc
commit 71d904b
Showing
28 changed files
with
1,906 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,24 @@ | ||
{ | ||
"parser": "babel-eslint", | ||
"extends": [ | ||
"standard", | ||
"standard-react" | ||
], | ||
"env": { | ||
"es6": true | ||
}, | ||
"plugins": [ | ||
"react" | ||
], | ||
"parserOptions": { | ||
"sourceType": "module" | ||
}, | ||
"rules": { | ||
// don't force es6 functions to include space before paren | ||
"space-before-function-paren": 0, | ||
|
||
// allow specifying true explicitly for boolean props | ||
"react/jsx-boolean-value": 0 | ||
"parser": "babel-eslint", | ||
"extends": [ | ||
"standard", | ||
"standard-react" | ||
], | ||
"env": { | ||
"es6": true | ||
}, | ||
"plugins": [ | ||
"react" | ||
], | ||
"parserOptions": { | ||
"sourceType": "module" | ||
}, | ||
"rules": { | ||
// don't force es6 functions to include space before paren | ||
"space-before-function-paren": 0, | ||
|
||
// allow specifying true explicitly for boolean props | ||
"react/jsx-boolean-value": 0 | ||
} | ||
} | ||
} | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"es2021": true | ||
}, | ||
"extends": [ | ||
"plugin:react/recommended", | ||
"airbnb" | ||
], | ||
"overrides": [ | ||
], | ||
"parserOptions": { | ||
"ecmaVersion": "latest", | ||
"sourceType": "module" | ||
}, | ||
"plugins": [ | ||
"react" | ||
], | ||
"rules": { | ||
"react/prop-types": "off", | ||
"no-shadow": "off", // disabled due to use of bindActionCreators | ||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], // disabled due to naming consistency with other modules | ||
"import/no-unresolved": "off", // disable due to module architecture. For modules most references are marked as unresolved | ||
"max-len": ["error", { "code": 120 }] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
name: ESLint | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
- develop | ||
pull_request: | ||
branches: | ||
- main | ||
- develop | ||
|
||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
|
||
- name: Setup Node.js | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: 14 | ||
|
||
- name: Install dependencies | ||
run: yarn install | ||
|
||
- name: Run ESLint | ||
run: npx eslint src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { | ||
graphql, | ||
formatPageQueryWithCount, | ||
formatMutation, | ||
formatGQLString, | ||
decodeId, | ||
graphqlWithVariables, | ||
} from '@openimis/fe-core'; | ||
import { ACTION_TYPE, MUTATION_SERVICE } from './reducer'; | ||
import { | ||
REQUEST, SUCCESS, ERROR, CLEAR, | ||
} from './utils/action-type'; | ||
|
||
const TASK_GROUP_PROJECTION = () => [ | ||
'id', | ||
'uuid', | ||
'code', | ||
'completionPolicy', | ||
'taskexecutorSet { edges { node { user { id username lastName } } } }', | ||
]; | ||
|
||
export const formatTaskGroupGQL = (taskGroup) => { | ||
const executors = taskGroup?.executors?.map((executor) => decodeId(executor.id)); | ||
const executorsString = executors ? `[${executors.map((executorUuid) => `"${executorUuid}"`).join(', ')}]` : '[]'; | ||
const GQLString = ` | ||
${taskGroup?.code ? `code: "${formatGQLString(taskGroup.code)}"` : ''} | ||
${taskGroup?.completionPolicy ? `completionPolicy: ${taskGroup.completionPolicy}` : ''} | ||
${taskGroup?.id ? `id: "${decodeId(taskGroup.id)}"` : ''} | ||
${taskGroup?.executors ? `userIds: ${executorsString}` : 'userIds: []'} | ||
`; | ||
return GQLString; | ||
}; | ||
|
||
const PERFORM_MUTATION = (mutationType, mutationInput, ACTION, clientMutationLabel) => { | ||
const mutation = formatMutation(mutationType, mutationInput, ACTION); | ||
const requestedDateTime = new Date(); | ||
return graphql( | ||
mutation.payload, | ||
[REQUEST(ACTION_TYPE.MUTATION), SUCCESS(ACTION_TYPE[ACTION]), ERROR(ACTION_TYPE.MUTATION)], | ||
{ | ||
actionType: ACTION_TYPE[ACTION], | ||
clientMutationId: mutation.clientMutationId, | ||
clientMutationLabel, | ||
requestedDateTime, | ||
}, | ||
); | ||
}; | ||
|
||
export function fetchTaskGroups(modulesManager, params) { | ||
const payload = formatPageQueryWithCount('taskGroup', params, TASK_GROUP_PROJECTION()); | ||
return graphql(payload, ACTION_TYPE.SEARCH_TASK_GROUPS); | ||
} | ||
|
||
export function fetchTaskGroup(modulesManager, variables) { | ||
return graphqlWithVariables( | ||
` | ||
query getTaskGroup ($taskGroupUuid: ID ) { | ||
taskGroup(id: $taskGroupUuid) { | ||
edges { | ||
node { | ||
id | ||
uuid | ||
code | ||
completionPolicy | ||
taskexecutorSet { edges { node { user { id username lastName } } } }, | ||
} | ||
} | ||
} | ||
} | ||
`, | ||
variables, | ||
ACTION_TYPE.GET_TASK_GROUP, | ||
); | ||
} | ||
|
||
export const clearTaskGroup = () => (dispatch) => { | ||
dispatch({ | ||
type: CLEAR(ACTION_TYPE.GET_TASK_GROUP), | ||
}); | ||
}; | ||
|
||
export function deleteTaskGroup(taskGroup, clientMutationLabel) { | ||
const taskGroupsUuids = `ids: ["${decodeId(taskGroup?.id)}"]`; | ||
return PERFORM_MUTATION( | ||
MUTATION_SERVICE.TASK_GROUP.DELETE, | ||
taskGroupsUuids, | ||
'DELETE_TASK_GROUP', | ||
clientMutationLabel, | ||
); | ||
} | ||
|
||
export function createTaskGroup(taskGroup, clientMutationLabel) { | ||
return PERFORM_MUTATION( | ||
MUTATION_SERVICE.TASK_GROUP.CREATE, | ||
formatTaskGroupGQL(taskGroup), | ||
'CREATE_TASK_GROUP', | ||
clientMutationLabel, | ||
); | ||
} | ||
|
||
export function updateTaskGroup(taskGroup, clientMutationLabel) { | ||
return PERFORM_MUTATION( | ||
MUTATION_SERVICE.TASK_GROUP.UPDATE, | ||
formatTaskGroupGQL(taskGroup), | ||
'UPDATE_TASK_GROUP', | ||
clientMutationLabel, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import React from 'react'; | ||
import { Grid } from '@material-ui/core'; | ||
import { makeStyles } from '@material-ui/styles'; | ||
import _debounce from 'lodash/debounce'; | ||
import { TextInput } from '@openimis/fe-core'; | ||
import { | ||
CONTAINS_LOOKUP, DEFAULT_DEBOUNCE_TIME, EMPTY_STRING, TASK_STATUS_LIST, | ||
} from '../constants'; | ||
import StatusPicker from '../pickers/StatusPicker'; | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
form: { | ||
padding: '0 0 10px 0', | ||
width: '100%', | ||
}, | ||
item: { | ||
padding: theme.spacing(1), | ||
}, | ||
})); | ||
|
||
function BenefitPlanTasksFilter({ | ||
filters, | ||
onChangeFilters, | ||
formatMessage, | ||
}) { | ||
const classes = useStyles(); | ||
|
||
const debouncedOnChangeFilters = _debounce(onChangeFilters, DEFAULT_DEBOUNCE_TIME); | ||
|
||
const filterValue = (filterName) => filters?.[filterName]?.value; | ||
|
||
const filterTextFieldValue = (filterName) => filters?.[filterName]?.value ?? EMPTY_STRING; | ||
|
||
const onChangeStringFilter = (filterName, lookup = null) => (value) => { | ||
if (lookup) { | ||
debouncedOnChangeFilters([ | ||
{ | ||
id: filterName, | ||
value, | ||
filter: `${filterName}_${lookup}: "${value}"`, | ||
}, | ||
]); | ||
} else { | ||
onChangeFilters([ | ||
{ | ||
id: filterName, | ||
value, | ||
filter: `${filterName}: "${value}"`, | ||
}, | ||
]); | ||
} | ||
}; | ||
|
||
return ( | ||
<Grid container className={classes.form}> | ||
<Grid item xs={3} className={classes.item}> | ||
<TextInput | ||
module="tasksManagement" | ||
label="benefitPlanTask.source" | ||
value={filterTextFieldValue('source')} | ||
onChange={onChangeStringFilter('source', CONTAINS_LOOKUP)} | ||
/> | ||
</Grid> | ||
<Grid item xs={3} className={classes.item}> | ||
<TextInput | ||
module="tasksManagement" | ||
label="benefitPlanTask.type" | ||
value={filterTextFieldValue('type')} | ||
onChange={onChangeStringFilter('type', CONTAINS_LOOKUP)} | ||
/> | ||
</Grid> | ||
<Grid item xs={3} className={classes.item}> | ||
<TextInput | ||
module="tasksManagement" | ||
label="benefitPlanTask.entity" | ||
value={filterTextFieldValue('entity')} | ||
onChange={onChangeStringFilter('entity', CONTAINS_LOOKUP)} | ||
/> | ||
</Grid> | ||
<Grid item xs={3} className={classes.item}> | ||
<TextInput | ||
module="tasksManagement" | ||
label="benefitPlanTask.assignee" | ||
value={filterTextFieldValue('assignee')} | ||
onChange={onChangeStringFilter('assignee', CONTAINS_LOOKUP)} | ||
/> | ||
</Grid> | ||
<Grid item xs={3} className={classes.item}> | ||
<TextInput | ||
module="tasksManagement" | ||
label="benefitPlanTask.businessStatus" | ||
value={filterTextFieldValue('businessStatus')} | ||
onChange={onChangeStringFilter('businessStatus', CONTAINS_LOOKUP)} | ||
/> | ||
</Grid> | ||
<Grid item xs={3} className={classes.item}> | ||
<StatusPicker | ||
label="benefitPlanTask.status" | ||
constants={TASK_STATUS_LIST} | ||
withLabel | ||
nullLabel={formatMessage('defaultValue.any')} | ||
withNull | ||
value={filterValue('status')} | ||
onChange={(value) => onChangeFilters([ | ||
{ | ||
id: 'status', | ||
value, | ||
filter: `status: ${value}`, | ||
}, | ||
])} | ||
/> | ||
</Grid> | ||
</Grid> | ||
); | ||
} | ||
|
||
export default BenefitPlanTasksFilter; |
Oops, something went wrong.