Compare commits

...

12 Commits

15 changed files with 82 additions and 64 deletions
Split View
  1. +0
    -14
      src/layout/MainLayout/Header/index.js
  2. +2
    -2
      src/pages/GFMIS/TransactionDataGrid.js
  3. +11
    -10
      src/pages/GFMIS/index.js
  4. +1
    -1
      src/pages/Payment/MultiPaymentWindow.js
  5. +3
    -3
      src/pages/Payment/Search_GLD/SearchForm.js
  6. +1
    -2
      src/pages/Payment/Search_Public/DataGrid.js
  7. +1
    -1
      src/pages/Payment/Search_Public/SearchForm.js
  8. +2
    -2
      src/pages/Recon/SearchForm.js
  9. +1
    -2
      src/pages/Setting/HkidKeyMigration/index.js
  10. +1
    -1
      src/pages/Setting/UserPiiEncryption/index.js
  11. +51
    -21
      src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js
  12. +2
    -2
      src/pages/authentication/auth-forms/CustomFormWizard.js
  13. +4
    -3
      src/translations/en.json
  14. +1
    -0
      src/translations/zh-CN.json
  15. +1
    -0
      src/translations/zh-HK.json

+ 0
- 14
src/layout/MainLayout/Header/index.js View File

@@ -516,20 +516,6 @@ function Header(props) {

{isGranted("MAINTAIN_SETTING") ? (
<>
<li>
<Link className="systemSetting" to="/setting/hkidKeyMigration">
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>
HKID Key Migration
</Typography>
</Link>
</li>
<li>
<Link className="systemSetting" to="/setting/userPiiEncryption">
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>
User PII Encryption
</Typography>
</Link>
</li>
<li>
<Link className="systemSetting" to="/setting/sys">
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>


+ 2
- 2
src/pages/GFMIS/TransactionDataGrid.js View File

@@ -61,7 +61,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a
},
{
field: 'actions',
headerName: 'Transaction No.',
headerName: 'Payment No.',
flex: 1,
minWidth: 200,
cellClassName: 'actions',
@@ -72,7 +72,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a
{
id: 'transDateTime',
field: 'transDateTime',
headerName: 'Transaction Date',
headerName: 'Payment Date',
flex: 1,
minWidth: 150,
// sorting/filtering uses this value


+ 11
- 10
src/pages/GFMIS/index.js View File

@@ -126,20 +126,21 @@ const Index = () => {
const xmlDoc = parser.parseFromString(responseData, 'application/xml');
const dcbHeader = xmlDoc.querySelector("DCBHeader");

const receiptElement = dcbHeader.querySelector("Receipt");
const allocationElement = dcbHeader.querySelector("Allocation");
const receiptElements = Array.from(dcbHeader.querySelectorAll("Receipt"));
const allocationElements = Array.from(dcbHeader.querySelectorAll("Allocation"));
const paymentMethodElements = Array.from(dcbHeader.querySelectorAll("PaymentMethod"));

dcbHeader.innerHTML = "";

dcbHeader.appendChild(receiptElement);
dcbHeader.appendChild(allocationElement);

if (paymentMethodElements) {
paymentMethodElements.forEach((paymentMethodElement) => {
dcbHeader.appendChild(paymentMethodElement);
});
}
receiptElements.forEach((receiptElement) => {
dcbHeader.appendChild(receiptElement);
});
allocationElements.forEach((allocationElement) => {
dcbHeader.appendChild(allocationElement);
});
paymentMethodElements.forEach((paymentMethodElement) => {
dcbHeader.appendChild(paymentMethodElement);
});

const updatedXmlString = new XMLSerializer().serializeToString(xmlDoc);
const filename = xmlDoc.querySelector('FileHeader').getAttribute('H_Filename');


+ 1
- 1
src/pages/Payment/MultiPaymentWindow.js View File

@@ -291,7 +291,7 @@ const MultiPaymentWindow = (props) => {
<form>
<DialogContent>
<DialogContentText>
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "left", ml:1}}>
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "left", width: "100%", whiteSpace: "pre-line", paddingLeft: 0 }}>
<FormattedMessage id="paymentProcessLimited"/>
</FormLabel>
<Grid item xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%' }} width="100%">


+ 3
- 3
src/pages/Payment/Search_GLD/SearchForm.js View File

@@ -158,7 +158,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) =>
// },
}}
format="DD/MM/YYYY"
label="Transaction Date (From)"
label="Payment Date (From)"
value={minDate === null ? null : dayjs(minDate)}
maxDate={maxDate === null ? null : dayjs(maxDate)}
onChange={(newValue) => {
@@ -184,7 +184,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) =>
// },
}}
format="DD/MM/YYYY"
label="Transaction Date (To)"
label="Payment Date (To)"
value={maxDate === null ? null : dayjs(maxDate)}
minDate={minDate === null ? null : dayjs(minDate)}
onChange={(newValue) => {
@@ -205,7 +205,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) =>
fullWidth
{...register("transNo")}
id='transNo'
label="Transaction No."
label="Payment No. / Payment Reference No."
defaultValue={searchCriteria.transNo}
InputLabelProps={{
shrink: true


+ 1
- 2
src/pages/Payment/Search_Public/DataGrid.js View File

@@ -90,8 +90,7 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea
width: isMdOrLg ? 'auto' : 160,
flex: isMdOrLg ? 1 : undefined,
valueGetter: (params) => {
// console.log(params)
return DateUtils.dateStr(params?.value?params.value:params.row.created);
return params?.value ? DateUtils.dateStr(params.value) : "";
}
},
{


+ 1
- 1
src/pages/Payment/Search_Public/SearchForm.js View File

@@ -224,7 +224,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) =>
fullWidth
{...register("transNo")}
id='transNo'
label={intl.formatMessage({id: 'payId'})}
label={intl.formatMessage({id: 'payIdNRefer'})}
defaultValue={searchCriteria.transNo}
InputLabelProps={{
shrink: true


+ 2
- 2
src/pages/Recon/SearchForm.js View File

@@ -256,7 +256,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateReport, onLoad }) => {
},
}}
format="DD/MM/YYYY"
label="PNSPS Transaction Date (From)"
label="PNSPS Payment Date (From)"
value={sysTxnMinDate === null ? null : dayjs(sysTxnMinDate)}
maxDate={sysTxnMaxDate === null ? null : dayjs(sysTxnMaxDate)}
onChange={(newValue) => {
@@ -280,7 +280,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateReport, onLoad }) => {
},
}}
format="DD/MM/YYYY"
label="PNSPS Transaction Date (To)"
label="PNSPS Payment Date (To)"
value={sysTxnMaxDate === null ? null : dayjs(sysTxnMaxDate)}
minDate={sysTxnMinDate === null ? null : dayjs(sysTxnMinDate)}
onChange={(newValue) => {


+ 1
- 2
src/pages/Setting/HkidKeyMigration/index.js View File

@@ -64,7 +64,7 @@ const HkidKeyMigration = () => {
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="space-between" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}>
HKID Key Migration
Encryption Key Migration
</Typography>
</Stack>
</div>
@@ -74,7 +74,6 @@ const HkidKeyMigration = () => {
<Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}>
<Typography variant="body1" sx={{ mb: 2 }}>
Re-encrypt identification and checkDigit from the legacy key to the new key.
Ensure Tomcat has both <code>security.hkid-secret</code> and <code>security.hkid-secret-legacy</code> configured before running.
</Typography>
<Stack direction="row" spacing={2}>
<Button variant="outlined" size="large" disabled={wait} onClick={() => runMigration(true)}>


+ 1
- 1
src/pages/Setting/UserPiiEncryption/index.js View File

@@ -94,7 +94,7 @@ const UserPiiEncryption = () => {
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="space-between" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}>
User PII Encryption
User Fields Encryption
</Typography>
</Stack>
</div>


+ 51
- 21
src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js View File

@@ -6,7 +6,7 @@ import {
IconButton
} from '@mui/material';
import MainCard from "components/MainCard";
import { useEffect, useState, lazy } from "react";
import { useEffect, useState, useRef, lazy } from "react";
import * as yup from 'yup';

import { useFormik } from 'formik';
@@ -14,6 +14,7 @@ import * as FieldUtils from "utils/FieldUtils";
import * as HttpUtils from 'utils/HttpUtils';
import * as UrlUtils from "utils/ApiPathConst";
import * as ComboData from "utils/ComboData";
import en from "translations/en.json";
const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
import Loadable from 'components/Loadable';
import { notifyActiveSuccess, notifyLockSuccess, notifySaveSuccess, notifyVerifySuccess } from 'utils/CommonFunction';
@@ -34,7 +35,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
const [onReady, setOnReady] = useState(false);
const [errorMsg, setErrorMsg] = useState("");
const [showId, setshowId] = useState(false);
const [selectedIdDocInputType, setSelectedIdDocInputType] = useState("");
const selectedIdDocInputTypeRef = useRef("");

const handleClickShowId = () => {
setshowId(!showId);
@@ -44,11 +45,20 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
event.preventDefault();
};

const getIdDocTypeLabel = (option) => {
if (!option) return "";
if (typeof option === "string") {
const item = ComboData.idDocType.find((o) => o.type === option);
return item?.label ? (en[item.label] ?? option) : option;
}
return option.label ? (en[option.label] ?? "") : "";
};

useEffect(() => {
//if state data are ready and assign to different field
// console.log(currentApplicationDetailData)
if (Object.keys(currentUserData).length > 0) {
setSelectedIdDocInputType(currentUserData.idDocType)
selectedIdDocInputTypeRef.current = currentUserData.idDocType;
setOnReady(true);
}
}, [currentUserData]);
@@ -66,6 +76,22 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
return <Typography variant="errorMessage1">{errorMsg}</Typography>
}

function getIdDocTypeDisplayName(docType) {
if (!docType) return "";
switch (docType) {
case "HKID":
return "Hong Kong ID Card";
case "passport":
return "Passport";
case "CNID":
return "Mainland ID Card";
case "otherCert":
return "Professional Practice Certificate";
default:
return docType;
}
}

const formik = useFormik({
enableReinitialize: true,
initialValues: currentUserData,
@@ -84,16 +110,16 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
is: (verifiedBy) => verifiedBy != null,
then: (schema) => schema.notRequired(),
otherwise: (schema) => schema.required(getRequiredErrStr('number'))
.matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) })
.matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpace' })}`) })
.test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${selectedIdDocInputType}${intl.formatMessage({ id: 'number' })}`), function (value) {
.matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputTypeRef.current}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) })
.matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputTypeRef.current}${intl.formatMessage({ id: 'noSpace' })}`) })
.test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${getIdDocTypeDisplayName(selectedIdDocInputTypeRef.current)}${intl.formatMessage({ id: 'number' })}`), function (value) {
var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/;
var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/;
var pattern_passport = /^[A-Z]{1}[0-9]{8}$/;
var pattern_passport = /^[A-Za-z0-9]{6,9}$/;
var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/;
var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/;
if (value !== undefined) {
switch (selectedIdDocInputType) {
switch (selectedIdDocInputTypeRef.current) {
case "HKID":
if (value.match(pattern_HKIDv1)) {
return true
@@ -141,11 +167,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
is: (verifiedBy) => verifiedBy != null,
then: (schema) => schema.notRequired(),
otherwise: (schema) => schema.max(1, getMaxErrStr(1)).nullable()
.matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) })
.matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputTypeRef.current}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) })
.test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredNumberInQuote' })}`), function (value) {
// console.log(selectedIdDocInputType)
if (value != undefined || value != null) {
switch (selectedIdDocInputType) {
switch (selectedIdDocInputTypeRef.current) {
case "HKID":
if (value.length == 1) {
return true
@@ -162,7 +187,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
break;
}
} else {
if (selectedIdDocInputType != "HKID"){
if (selectedIdDocInputTypeRef.current != "HKID"){
return true
} else {
return false
@@ -392,28 +417,33 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {

<Grid item xs={12} sm={12} md={12} lg={4}>
{FieldUtils.getComboField({
label: "ID Type:",
label: `${en.idDocType}:`,
valueName: "idDocType",
disabled: (!editMode),
disabled: !editMode || currentUserData.verifiedBy != null,
dataList: ComboData.idDocType,
filterOptions: (options) => options,
getOptionLabel: (item) => item ? typeof item === 'string' ? item : (item["type"] ? item["type"] + "-" + item["label"] : "") : "",
getOptionLabel: getIdDocTypeLabel,
isOptionEqualToValue: (option, value) => {
if (typeof value === "string") {
return option?.type === value;
}
return option?.type === value?.type;
},
onInputChange: (event, newValue, setInputValue) => {
if (newValue == null) {
setInputValue("");
return;
}
let _val = newValue.split("-");
if (_val[0]) {
setInputValue(_val[0]);
}
setInputValue(newValue);
},
onChange: (event, newValue) => {
if (newValue == null) {
formik.setFieldValue("idDocType", "");
selectedIdDocInputTypeRef.current = "";
return;
}
formik.setFieldValue("idDocType", newValue.type);
setSelectedIdDocInputType(newValue.type);
selectedIdDocInputTypeRef.current = newValue.type;
if (newValue.type !== "HKID") {
formik.setFieldValue("checkDigit", "")
}
@@ -496,7 +526,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
form: formik,
placeholder: intl.formatMessage({ id: 'idDocNumber' }),
inputProps: {
maxLength: 7,
maxLength: 8,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();


+ 2
- 2
src/pages/authentication/auth-forms/CustomFormWizard.js View File

@@ -633,7 +633,7 @@ const CustomFormWizard = (props) => {
// var pattern = /^[A-Z][0-9]*$/;
var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/;
var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/;
var pattern_passport = /^[A-Z]{1}[0-9]{8}$/;
var pattern_passport = /^[A-Za-z0-9]{6,9}$/;
var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/;
var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/;
// var space = /\s/;
@@ -808,7 +808,7 @@ const CustomFormWizard = (props) => {
const idDocType = selectedIdDocType.type;
var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/;
var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/;
var pattern_passport = /^[A-Z]{1}[0-9]{8}$/;
var pattern_passport = /^[A-Za-z0-9]{6,9}$/;
var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/;
var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/;
if (value !== undefined) {


+ 4
- 3
src/translations/en.json View File

@@ -346,8 +346,8 @@
"passport": "Passport",
"HKIDcard": "Hong Kong ID Card",
"HKID": "Hong Kong ID Card",
"mainlandIDCard": "Mainland ID card",
"CNID": "Mainland ID card",
"mainlandIDCard": "Mainland ID Card",
"CNID": "Mainland ID Card",
"proCert": "Professional Practice Certificate",
"otherCert": "Professional Practice Certificate",
"idDocType": "Document Category",
@@ -413,6 +413,7 @@
"payDateTo": "Payment Date (To)",
"payStatus": "Payment Status",
"payId": "Payment No.",
"payIdNRefer": "Payment No. / Payment Reference No.",
"payConfirm": "Confirm payment",
"payCancel": "Cancel payment",
"payAlert": "Please don’t close this window, you may either complete this payment or cancel this payment by the button at the bottom of this page.",
@@ -536,7 +537,7 @@
"paymentNo": "Payment No.",
"paymentDate": "Payment Date",
"paymentTime": "Payment Time",
"paymentRefCode": "Payment Reference Number",
"paymentRefCode": "Payment Reference No.",

"paymentInfoRecord": "Payment Notice Record",
"paymentRecordId": "Payment Record No.",


+ 1
- 0
src/translations/zh-CN.json View File

@@ -446,6 +446,7 @@
"payDateTo": "付款日期 (到)",
"payStatus": "付款状况",
"payId": "付款编号",
"payIdNRefer": "付款编号 / 付款参考编号",
"payConfirm": "确认付款",
"payCancel": "取消付款",
"payAlert": "请不要关闭此窗口,您可以通过此页面底部的按钮完成此付款或取消此付款。",


+ 1
- 0
src/translations/zh-HK.json View File

@@ -447,6 +447,7 @@
"payDateTo": "付款日期 (到)",
"payStatus": "付款狀況",
"payId": "付款編號",
"payIdNRefer": "付款編號 / 付款參考編號",
"payConfirm": "確認付款",
"payCancel": "取消付款",
"payAlert": "請不要關閉此窗口,您可以透過本頁底部的按鈕完成此付款或取消本付款。",


Loading…
Cancel
Save