diff --git a/src/actions.js b/src/actions.js index 8e9d199..dcb61bd 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,7 +1,14 @@ import { graphql, formatMutation, formatPageQueryWithCount, formatGQLString, formatPageQuery, - baseApiUrl, decodeId, openBlob + baseApiUrl, decodeId, openBlob, formatQuery, } from "@openimis/fe-core"; +import {ACTION_TYPE} from "./reducer"; + +const GRIEVANCE_CONFIGURATION_PROJECTION = () => [ + 'grievanceTypes', + 'grievanceFlags', + 'grievanceChannels', +]; const CATEGORY_FULL_PROJECTION = (mm) => [ "id", @@ -212,7 +219,6 @@ export function fetchInsureeTicket(mm, chfId) { return graphql(payload, 'TICKET_TICKET'); } - export function fetchInsureeTickets(mm, filters) { if (filters.filter((f) => f.startsWith("chfId")).length !== 0) { qry = "ticketsByInsuree"; @@ -225,3 +231,8 @@ export function fetchInsureeTickets(mm, filters) { ); return graphql(payload, RDX); } + +export function fetchGrievanceConfiguration(params) { + const payload = formatQuery('grievanceConfig', params, GRIEVANCE_CONFIGURATION_PROJECTION()) + return graphql(payload, ACTION_TYPE.GET_GRIEVANCE_CONFIGURATION); +} diff --git a/src/constants.js b/src/constants.js index 041064f..ac65503 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,9 +1,11 @@ -export const TICKET_STATUS = ["Waiting", "Todo", "Inprogress", "Review", "Close"] +export const TICKET_STATUS = ['Waiting', 'Todo', 'Inprogress', 'Review', 'Close']; -export const TICKET_PRIORITY = ["Critical", "High", "Normal", "Low"] +export const TICKET_PRIORITY = ['Critical', 'High', 'Normal', 'Low']; export const RIGHT_TICKET = 123000; export const RIGHT_TICKET_SEARCH = 123000; export const RIGHT_TICKET_ADD = 123001; export const RIGHT_TICKET_EDIT = 123002; -export const RIGHT_TICKET_DELETE = 123003; \ No newline at end of file +export const RIGHT_TICKET_DELETE = 123003; + +export const MODULE_NAME = 'grievanceSocialProtection'; diff --git a/src/dialogs/GrievanceConfigurationDialog.js b/src/dialogs/GrievanceConfigurationDialog.js new file mode 100644 index 0000000..625a266 --- /dev/null +++ b/src/dialogs/GrievanceConfigurationDialog.js @@ -0,0 +1,68 @@ +import React, { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { + coreAlert, + useModulesManager, + useTranslations, +} from '@openimis/fe-core'; +import { fetchGrievanceConfiguration } from '../actions'; +import { + MODULE_NAME, + RIGHT_TICKET, + RIGHT_TICKET_ADD, + RIGHT_TICKET_DELETE, + RIGHT_TICKET_EDIT, + RIGHT_TICKET_SEARCH, +} from '../constants'; + +function GrievanceConfigurationDialog({ + rights, +}) { + const modulesManager = useModulesManager(); + const { formatMessage, formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager); + const dispatch = useDispatch(); + const grievanceConfiguration = useSelector((state) => state?.grievanceSocialProtection?.grievanceConfig); + const fetchedGrievanceConfig = useSelector((state) => state?.grievanceSocialProtection?.fetchedGrievanceConfig); + + const doesUserHaveRights = () => { + const rightsArray = [ + RIGHT_TICKET, + RIGHT_TICKET_SEARCH, + RIGHT_TICKET_ADD, + RIGHT_TICKET_EDIT, + RIGHT_TICKET_DELETE, + ]; + return rightsArray.every((right) => rights.includes(right)); + }; + const isMatchingConfigObject = (obj) => !(typeof obj !== 'object' || obj === null || Array.isArray(obj)); + + const isConfigMissing = (config) => Object.values(config).some((field) => !field); + + const shouldDisplay = () => grievanceConfiguration + && doesUserHaveRights() + && isMatchingConfigObject(grievanceConfiguration) + && isConfigMissing(grievanceConfiguration); + + useEffect(() => { + if (shouldDisplay()) { + const configString = JSON.stringify(grievanceConfiguration); + dispatch(coreAlert( + formatMessage('grievanceSocialProtection.dialogs.GrievanceConfigurationDialog.dialogHeader'), + formatMessageWithValues( + 'grievanceSocialProtection.dialogs.GrievanceConfigurationDialog.dialogBody', + { configString }, + ), + )); + } + }, [grievanceConfiguration]); + + useEffect(() => { + if (!fetchedGrievanceConfig) { + dispatch(fetchGrievanceConfiguration()); + } + }, [fetchedGrievanceConfig]); + + return null; +} + +export default GrievanceConfigurationDialog; diff --git a/src/index.js b/src/index.js index 617d9a7..af909bf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,54 +1,56 @@ -import React from "react"; -import messages_en from "./translations/en.json"; -import reducer from "./reducer"; -import { ListAlt } from "@material-ui/icons"; -import { FormattedMessage } from "@openimis/fe-core"; -import TicketMainMenu from "./menu/TicketMainMenu"; -import TicketsPage from "./pages/TicketsPage"; -import TicketPage from "./pages/TicketPage"; -import TicketSearcher from "./components/TicketSearcher"; -import TicketPriorityPicker from "./pickers/TicketPriorityPicker"; -import TicketStatusPicker from "./pickers/TicketStatusPicker"; -import DropDownCategoryPicker from "./pickers/DropDownCategoryPicker"; -import CategoryPicker from "./pickers/CategoryPicker"; - -const ROUTE_TICKET_TICKETS = "ticket/tickets"; -const ROUTE_TICKET_TICKET = "ticket/ticket"; +// Disable due to core architecture +/* eslint-disable camelcase */ +/* eslint-disable import/prefer-default-export */ +import React from 'react'; +import { ListAlt } from '@material-ui/icons'; +import { FormattedMessage } from '@openimis/fe-core'; +import messages_en from './translations/en.json'; +import reducer from './reducer'; +import TicketMainMenu from './menu/TicketMainMenu'; +import TicketsPage from './pages/TicketsPage'; +import TicketPage from './pages/TicketPage'; +import TicketSearcher from './components/TicketSearcher'; +import TicketPriorityPicker from './pickers/TicketPriorityPicker'; +import TicketStatusPicker from './pickers/TicketStatusPicker'; +import DropDownCategoryPicker from './pickers/DropDownCategoryPicker'; +import CategoryPicker from './pickers/CategoryPicker'; +import GrievanceConfigurationDialog from './dialogs/GrievanceConfigurationDialog'; +import { MODULE_NAME } from './constants'; + +const ROUTE_TICKET_TICKETS = 'ticket/tickets'; +const ROUTE_TICKET_TICKET = 'ticket/ticket'; const DEFAULT_CONFIG = { - "translations": [{ key: "en", messages: messages_en }], - "reducers": [{ key: 'grievance', reducer }], + translations: [{ key: 'en', messages: messages_en }], + reducers: [{ key: 'grievanceSocialProtection', reducer }], - "refs": [ - { key: "grievance.route.tickets", ref: ROUTE_TICKET_TICKETS }, - { key: "grievance.route.ticket", ref: ROUTE_TICKET_TICKET }, + refs: [ + { key: 'grievanceSocialProtection.route.tickets', ref: ROUTE_TICKET_TICKETS }, + { key: 'grievanceSocialProtection.route.ticket', ref: ROUTE_TICKET_TICKET }, - { key: "grievance.route.ticketSearcher", ref: TicketSearcher }, + { key: 'grievanceSocialProtection.route.ticketSearcher', ref: TicketSearcher }, - { key: "grievance.TicketStatusPicker", ref: TicketStatusPicker }, - { key: "grievance.TicketPriorityPicker", ref: TicketPriorityPicker }, - { key: "grievance.DropDownCategoryPicker", ref: DropDownCategoryPicker }, - { key: "grievance.CategoryPicker", ref: CategoryPicker }, + { key: 'grievanceSocialProtection.TicketStatusPicker', ref: TicketStatusPicker }, + { key: 'grievanceSocialProtection.TicketPriorityPicker', ref: TicketPriorityPicker }, + { key: 'grievanceSocialProtection.DropDownCategoryPicker', ref: DropDownCategoryPicker }, + { key: 'grievanceSocialProtection.CategoryPicker', ref: CategoryPicker }, + { key: 'grievanceSocialProtection.GrievanceConfigurationDialog', ref: GrievanceConfigurationDialog }, ], - "core.Router": [ + 'core.Router': [ { path: ROUTE_TICKET_TICKETS, component: TicketsPage }, - { path: ROUTE_TICKET_TICKET+ "/:ticket_uuid?", component: TicketPage }, + { path: `${ROUTE_TICKET_TICKET}/:ticket_uuid?`, component: TicketPage }, ], - "admin.MainMenu": [ + 'admin.MainMenu': [ { - text: , + text: , icon: , - route: "/" + ROUTE_TICKET_TICKETS, + route: `/${ROUTE_TICKET_TICKETS}`, }, ], - "core.MainMenu": [TicketMainMenu], - - -} + 'core.MainMenu': [TicketMainMenu], -export const GrievanceSocialProtectionModule = (cfg) => { - return { ...DEFAULT_CONFIG, ...cfg }; -} +}; +export const GrievanceSocialProtectionModule = (cfg) => ({ ...DEFAULT_CONFIG, ...cfg }); diff --git a/src/reducer.js b/src/reducer.js index 3f2a95a..4558c87 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -1,175 +1,206 @@ +// Disabled due to consistency with other modules +/* eslint-disable default-param-last */ + import { - parseData, pageInfo, formatServerError, formatGraphQLError, - dispatchMutationReq, dispatchMutationResp, dispatchMutationErr, + parseData, pageInfo, formatServerError, formatGraphQLError, + dispatchMutationReq, dispatchMutationResp, dispatchMutationErr, } from '@openimis/fe-core'; +import { ERROR, REQUEST, SUCCESS } from './utils/action-type'; + +export const ACTION_TYPE = { + GET_GRIEVANCE_CONFIGURATION: 'GET_GRIEVANCE_CONFIGURATION', +}; function reducer( - state = { - fetchingTickets: false, - errorTickets: null, + state = { + fetchingTickets: false, + errorTickets: null, + fetchedTickets: false, + tickets: [], + ticketsPageInfo: { totalCount: 0 }, + + fetchingTicket: false, + errorTicket: null, + fetchedTicket: false, + ticket: null, + ticketPageInfo: { totalCount: 0 }, + + fetchingCategory: false, + fetchedCategory: false, + errorCategory: null, + category: [], + categoryPageInfo: { totalCount: 0 }, + + fetchingTicketAttachments: false, + fetchedTicketAttachments: false, + errorTicketAttachments: null, + ticketAttachments: null, + + fetchingGrievanceConfig: false, + fetchedGrievanceConfig: false, + errorGrievanceConfig: null, + grievanceConfig: null, + + submittingMutation: false, + mutation: {}, + }, + action, +) { + switch (action.type) { + case 'TICKET_TICKETS_REQ': + return { + ...state, + fetchingTickets: true, fetchedTickets: false, tickets: [], ticketsPageInfo: { totalCount: 0 }, - - fetchingTicket: false, - errorTicket: null, + errorTickets: null, + }; + case 'TICKET_TICKETS_RESP': + return { + ...state, + fetchingTickets: false, + fetchedTickets: true, + tickets: parseData(action.payload.data.tickets), + ticketsPageInfo: pageInfo(action.payload.data.tickets), + errorTickets: formatGraphQLError(action.payload), + }; + case 'TICKET_TICKETS_ERR': + return { + ...state, + fetching: false, + error: formatServerError(action.payload), + }; + case 'TICKET_TICKET_REQ': + return { + ...state, + fetchingTicket: true, fetchedTicket: false, ticket: null, - ticketPageInfo: { totalCount: 0 }, + errorTicket: null, + }; + case 'TICKET_TICKET_RESP': + var tickt = parseData(action.payload.data.ticketDetails); + return { - fetchingCategory: false, + ...state, + fetchingTicket: false, + fetchedTicket: true, + ticket: (!!tickt && tickt.length > 0) ? tickt[0] : null, + errorTicket: formatGraphQLError(action.payload), + }; + case 'CATEGORY_CATEGORY_REQ': + return { + ...state, + fetchingCategory: true, fetchedCategory: false, - errorCategory: null, category: [], - categoryPageInfo: { totalCount: 0 }, - - fetchingTicketAttachments: false, + errorCategory: null, + }; + case 'CATEGORY_CATEGORY_RESP': + return { + ...state, + fetchingCategory: false, + fetchedCategory: true, + category: parseData(action.payload.data.category), + categoryPageInfo: pageInfo(action.payload.data.category), + errorCategory: formatGraphQLError(action.payload), + }; + case 'CATEGORY_CATEGORY_ERR': + return { + ...state, + fetching: false, + error: formatServerError(action.payload), + }; + case 'TICKET_TICKET_ATTACHMENTS_REQ': + return { + ...state, + fetchingTicketAttachments: true, fetchedTicketAttachments: false, - errorTicketAttachments: null, ticketAttachments: null, - - submittingMutation: false, - mutation: {}, - }, - action, -) { - switch (action.type) { - case 'TICKET_TICKETS_REQ': - return { - ...state, - fetchingTickets: true, - fetchedTickets: false, - tickets: [], - ticketsPageInfo: { totalCount: 0 }, - errorTickets: null, - }; - case 'TICKET_TICKETS_RESP': - return { - ...state, - fetchingTickets: false, - fetchedTickets: true, - tickets: parseData(action.payload.data.tickets), - ticketsPageInfo: pageInfo(action.payload.data.tickets), - errorTickets: formatGraphQLError(action.payload) - }; - case 'TICKET_TICKETS_ERR': - return { - ...state, - fetching: false, - error: formatServerError(action.payload) - }; - case 'TICKET_TICKET_REQ': - return { - ...state, - fetchingTicket: true, - fetchedTicket: false, - ticket: null, - errorTicket: null, - }; - case 'TICKET_TICKET_RESP': - var tickt = parseData(action.payload.data.ticketDetails); - return { - - ...state, - fetchingTicket: false, - fetchedTicket: true, - ticket: (!!tickt && tickt.length > 0) ? tickt[0] : null, - errorTicket: formatGraphQLError(action.payload) - }; - case 'TICKET_TICKETS_ERR': - return { - ...state, - fetching: false, - error: formatServerError(action.payload) - }; - case "CATEGORY_CATEGORY_REQ": - return { - ...state, - fetchingCategory: true, - fetchedCategory: false, - category: [], - errorCategory: null, - }; - case "CATEGORY_CATEGORY_RESP": - return { - ...state, - fetchingCategory: false, - fetchedCategory: true, - category: parseData(action.payload.data.category), - categoryPageInfo: pageInfo(action.payload.data.category), - errorCategory: formatGraphQLError(action.payload), - }; - case "CATEGORY_CATEGORY_ERR": - return { - ...state, - fetching: false, - error: formatServerError(action.payload), - }; - case "TICKET_TICKET_ATTACHMENTS_REQ": - return { - ...state, - fetchingTicketAttachments: true, - fetchedTicketAttachments: false, - ticketAttachments: null, - errorTicketAttachments: null, - }; - case "TICKET_TICKET_ATTACHMENTS_RESP": - return { - ...state, - fetchingTicketAttachments: false, - fetchedTicketAttachments: true, - ticketAttachments: parseData(action.payload.data.ticketAttachments), - errorTicketAttachments: formatGraphQLError(action.payload), - }; - case "TICKET_TICKET_ATTACHMENTS_ERR": - return { - ...state, - fetchingTicketAttachments: false, - errorTicketAttachments: formatServerError(action.payload), - }; - case 'TICKET_INSUREE_TICKETS_REQ': - return { - ...state, - fetchingTickets: true, - fetchedTickets: false, - tickets: null, - policy: null, - errorTickets: null, - }; - case 'TICKET_INSUREE_TICKETS_RESP': - return { - ...state, - fetchingTickets: false, - fetchedTickets: true, - tickets: parseData(action.payload.data.ticketsByInsuree), - ticketsPageInfo: pageInfo(action.payload.data.ticketsByInsuree), - errorTickets: formatGraphQLError(action.payload) - }; - case 'TICKET_INSUREE_TICKETS_ERR': - return { - ...state, - fetchingTickets: false, - errorTickets: formatServerError(action.payload), - }; - case "TICKET_MUTATION_REQ": - return dispatchMutationReq(state, action); - case "TICKET_MUTATION_ERR": - return dispatchMutationErr(state, action); - case "TICKET_CREATE_TICKET_RESP": - return dispatchMutationResp(state, "createTicket", action); - case "TICKET_UPDATE_TICKET_RESP": - return dispatchMutationResp(state, "updateTicket", action); - case "TICKET_DELETE_TICKET_RESP": - return dispatchMutationResp(state, "deleteTicket", action); - case "TICKET_ATTACHMENT_MUTATION_REQ": - return dispatchMutationReq(state, action); - case "TICKET_ATTACHMENT_MUTATION_ERR": - return dispatchMutationErr(state, action); - case "TICKET_CREATE_TICKET_ATTACHMENT_RESP": - return dispatchMutationResp(state, "createTicketAttachment", action); - default: - return state; - } + errorTicketAttachments: null, + }; + case 'TICKET_TICKET_ATTACHMENTS_RESP': + return { + ...state, + fetchingTicketAttachments: false, + fetchedTicketAttachments: true, + ticketAttachments: parseData(action.payload.data.ticketAttachments), + errorTicketAttachments: formatGraphQLError(action.payload), + }; + case 'TICKET_TICKET_ATTACHMENTS_ERR': + return { + ...state, + fetchingTicketAttachments: false, + errorTicketAttachments: formatServerError(action.payload), + }; + case 'TICKET_INSUREE_TICKETS_REQ': + return { + ...state, + fetchingTickets: true, + fetchedTickets: false, + tickets: null, + policy: null, + errorTickets: null, + }; + case 'TICKET_INSUREE_TICKETS_RESP': + return { + ...state, + fetchingTickets: false, + fetchedTickets: true, + tickets: parseData(action.payload.data.ticketsByInsuree), + ticketsPageInfo: pageInfo(action.payload.data.ticketsByInsuree), + errorTickets: formatGraphQLError(action.payload), + }; + case 'TICKET_INSUREE_TICKETS_ERR': + return { + ...state, + fetchingTickets: false, + errorTickets: formatServerError(action.payload), + }; + case REQUEST(ACTION_TYPE.GET_GRIEVANCE_CONFIGURATION): + return { + ...state, + fetchingGrievanceConfig: true, + fetchedGrievanceConfig: false, + errorGrievanceConfig: null, + grievanceConfig: null, + }; + case SUCCESS(ACTION_TYPE.GET_GRIEVANCE_CONFIGURATION): + return { + ...state, + fetchingGrievanceConfig: false, + fetchedGrievanceConfig: true, + errorGrievanceConfig: null, + grievanceConfig: action.payload.data.grievanceConfig, + }; + case ERROR(ACTION_TYPE.GET_GRIEVANCE_CONFIGURATION): + return { + ...state, + fetchingGrievanceConfig: false, + fetchedGrievanceConfig: false, + errorGrievanceConfig: formatGraphQLError(action.payload), + grievanceConfig: null, + }; + case 'TICKET_MUTATION_REQ': + return dispatchMutationReq(state, action); + case 'TICKET_MUTATION_ERR': + return dispatchMutationErr(state, action); + case 'TICKET_CREATE_TICKET_RESP': + return dispatchMutationResp(state, 'createTicket', action); + case 'TICKET_UPDATE_TICKET_RESP': + return dispatchMutationResp(state, 'updateTicket', action); + case 'TICKET_DELETE_TICKET_RESP': + return dispatchMutationResp(state, 'deleteTicket', action); + case 'TICKET_ATTACHMENT_MUTATION_REQ': + return dispatchMutationReq(state, action); + case 'TICKET_ATTACHMENT_MUTATION_ERR': + return dispatchMutationErr(state, action); + case 'TICKET_CREATE_TICKET_ATTACHMENT_RESP': + return dispatchMutationResp(state, 'createTicketAttachment', action); + default: + return state; + } } export default reducer; diff --git a/src/translations/en.json b/src/translations/en.json index 09bf396..8704db4 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -72,5 +72,7 @@ "ticket.ticketCode":"Code", "ticket.ticketPriority":"Priority", "ticket.ticketStatus":"Status", - "ticket.ticketGrievanct" : "Grievant" + "ticket.ticketGrievanct" : "Grievant", + "grievanceSocialProtection.dialogs.GrievanceConfigurationDialog.dialogHeader": "Please fill the config.", + "grievanceSocialProtection.dialogs.GrievanceConfigurationDialog.dialogBody": "Go to django admin panel and set up missing values: {configString}" } \ No newline at end of file diff --git a/src/utils/action-type.js b/src/utils/action-type.js new file mode 100644 index 0000000..788e71a --- /dev/null +++ b/src/utils/action-type.js @@ -0,0 +1,5 @@ +export const REQUEST = (actionTypeName) => `${actionTypeName}_REQ`; +export const SUCCESS = (actionTypeName) => `${actionTypeName}_RESP`; +export const ERROR = (actionTypeName) => `${actionTypeName}_ERR`; +export const CLEAR = (actionTypeName) => `${actionTypeName}_CLEAR`; +export const VALID = (actionTypeName) => `${actionTypeName}_VALID`;