refactor: change variable from isDisableOTP to isEnableOTP

This commit is contained in:
prafull-opensignlabs
2024-09-18 14:32:45 +05:30
parent cc11848346
commit 4caf9f598a
28 changed files with 156 additions and 73 deletions
@@ -639,8 +639,8 @@
"sent-this-month":"Sent this month",
"available-seats":"Available seats",
"buy-users":"Buy more users",
"isdisable-otp": "Enable OTP verification",
"isdisable-otp-help": {
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
@@ -638,8 +638,8 @@
"sent-this-month":"envoyé ce mois-ci",
"available-seats":"Disponible sièges",
"buy-users":"Acheter plus d'utilisateurs",
"isdisable-otp": "Activer la vérification OTP",
"isdisable-otp-help": {
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
@@ -3,6 +3,8 @@ import { checkIsSubscribed, getFileName } from "../../constant/Utils";
import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const";
import { useTranslation } from "react-i18next";
import { Tooltip } from "react-tooltip";
// import SelectFolder from "../../premitives/SelectFolder";
const EditTemplate = ({ template, onSuccess }) => {
@@ -14,7 +16,8 @@ const EditTemplate = ({ template, onSuccess }) => {
Description: template?.Description || "",
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
AutomaticReminders: template?.AutomaticReminders || false,
RemindOnceInEvery: template?.RemindOnceInEvery || 5
RemindOnceInEvery: template?.RemindOnceInEvery || 5,
IsEnableOTP: template?.IsEnableOTP ? `${template?.IsEnableOTP}` : "false"
});
const [isSubscribe, setIsSubscribe] = useState(false);
useEffect(() => {
@@ -184,6 +187,70 @@ const EditTemplate = ({ template, onSuccess }) => {
/>
</div>
)}
{isEnableSubscription && (
<div className="text-xs mt-2">
<label className="block">
<span className={isSubscribe ? "" : " text-gray-300"}>
{t("isenable-otp")}{" "}
<a data-tooltip-id="isenableotp-tooltip" className="ml-1">
<sup>
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
</sup>
</a>{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<Tooltip id="isenableotp-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">{t("isenable-otp")}</p>
<p>{t("isenable-otp-help.p1")}</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">{t("yes")}: </span>
<span>{t("isenable-otp-help.p2")}</span>
</li>
<li>
<span className="font-bold">{t("no")}: </span>
<span>{t("isenable-otp-help.p3")}</span>
</li>
</ol>
</p>
<p>{t("isenable-otp-help.p4")}</p>
</div>
</Tooltip>
</label>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsEnableOTP"
checked={formData.IsEnableOTP === "true"}
onChange={handleStrInput}
/>
<div className="text-center">{t("yes")}</div>
</div>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"false"}
name="IsEnableOTP"
className="op-radio op-radio-xs"
checked={formData.IsEnableOTP === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
</div>
</div>
)}
<div className="mt-[1rem] flex justify-start">
<button type="submit" className="op-btn op-btn-primary">
{t("submit")}
+2 -4
View File
@@ -2045,7 +2045,7 @@ export const handleDownloadPdf = async (
) => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
setIsDownloading("pdf");
const docId = pdfDetails?.[0]?.IsDisableOTP ? pdfDetails?.[0]?.objectId : "";
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
@@ -2082,10 +2082,8 @@ export const handleToPrint = async (
) => {
event.preventDefault();
setIsDownloading("pdf");
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
try {
const docId = pdfDetails?.[0]?.IsDisableOTP
? pdfDetails?.[0]?.objectId
: "";
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
//`localStorage.getItem("baseUrl")` is also use in public-profile flow for public-sign
//if we give this `appInfo.baseUrl` as a base url then in public-profile it will create base url of it's window.location.origin ex- opensign.me which is not base url
+29 -28
View File
@@ -62,7 +62,7 @@ const Forms = (props) => {
file: "",
remindOnceInEvery: 5,
autoreminder: false,
IsDisableOTP: "false"
IsEnableOTP: "false"
});
const [fileupload, setFileUpload] = useState("");
const [fileload, setfileload] = useState(false);
@@ -404,11 +404,11 @@ const Forms = (props) => {
object.set("AutomaticReminders", formData.autoreminder);
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
if (isEnableSubscription) {
const IsDisableOTP =
formData.IsDisableOTP === "false" ? true : false;
object.set("IsDisableOTP", IsDisableOTP);
const IsEnableOTP =
formData?.IsEnableOTP === "false" ? false : true;
object.set("IsEnableOTP", IsEnableOTP);
} else {
object.set("IsDisableOTP", true);
object.set("IsEnableOTP", false);
}
}
object.set("URL", fileupload);
@@ -446,7 +446,7 @@ const Forms = (props) => {
file: "",
remindOnceInEvery: 5,
autoreminder: false,
IsDisableOTP: "false"
IsEnableOTP: "false"
});
setFileUpload("");
setpercentage(0);
@@ -496,7 +496,7 @@ const Forms = (props) => {
file: "",
remindOnceInEvery: 5,
autoreminder: false,
IsDisableOTP: "false"
IsEnableOTP: "false"
});
setFileUpload("");
setpercentage(0);
@@ -896,9 +896,9 @@ const Forms = (props) => {
<div className="text-xs mt-2">
<label className="block">
<span className={isSubscribe ? "" : " text-gray-300"}>
{t("isdisable-otp")}{" "}
{t("isenable-otp")}{" "}
<a
data-tooltip-id="isdisableotp-tooltip"
data-tooltip-id="isenableotp-tooltip"
className="ml-1"
>
<sup>
@@ -909,27 +909,27 @@ const Forms = (props) => {
<Upgrade />
)}
</span>
<Tooltip id="isdisableotp-tooltip" className="z-50">
<Tooltip id="isenableotp-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">{t("isdisable-otp")}</p>
<p>{t("isdisable-otp-help.p1")}</p>
<p className="font-bold">{t("isenable-otp")}</p>
<p>{t("isenable-otp-help.p1")}</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">
{t("yes")}:{" "}
</span>
<span>{t("isdisable-otp-help.p2")}</span>
<span>{t("isenable-otp-help.p2")}</span>
</li>
<li>
<span className="font-bold">
{t("no")}:{" "}
</span>
<span>{t("isdisable-otp-help.p3")}</span>
<span>{t("isenable-otp-help.p3")}</span>
</li>
</ol>
</p>
<p>{t("isdisable-otp-help.p4")}</p>
<p>{t("isenable-otp-help.p4")}</p>
</div>
</Tooltip>
</label>
@@ -942,8 +942,8 @@ const Forms = (props) => {
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsDisableOTP"
checked={formData.IsDisableOTP === "true"}
name="IsEnableOTP"
checked={formData.IsEnableOTP === "true"}
onChange={handleStrInput}
/>
<div className="text-center">{t("yes")}</div>
@@ -956,9 +956,9 @@ const Forms = (props) => {
<input
type="radio"
value={"false"}
name="IsDisableOTP"
name="IsEnableOTP"
className="op-radio op-radio-xs"
checked={formData.IsDisableOTP === "false"}
checked={formData.IsEnableOTP === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
@@ -969,15 +969,16 @@ const Forms = (props) => {
)}
</div>
)}
<div
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
className={`mt-2.5 op-link op-link-primary text-sm`}
>
{isAdvanceOpt
? t("hide-advanced-options")
: t("advanced-options")}
</div>
{props.title !== "Sign Yourself" && (
<div
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
className={`mt-2.5 op-link op-link-primary text-sm`}
>
{isAdvanceOpt
? t("hide-advanced-options")
: t("advanced-options")}
</div>
)}
<div className="flex items-center mt-3 gap-2">
<button
className={`${
+2 -2
View File
@@ -194,11 +194,11 @@ function GuestLogin() {
setLoading(true);
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
setContactId(linkContactRes.contactId);
const isDisableOTP = await navigateToDoc(
const IsEnableOTP = await navigateToDoc(
documentId,
linkContactRes.contactId
);
if (!isDisableOTP) {
if (!IsEnableOTP) {
setEnterOtp(true);
await SendOtp();
}
+7 -7
View File
@@ -579,8 +579,8 @@ function PdfRequestFiles(props) {
) {
setRequestSignTour(true);
} else {
const isDisableOTP = documentData?.[0]?.IsDisableOTP || false;
if (isDisableOTP) {
const isEnableOTP = documentData?.[0]?.IsEnableOTP || false;
if (!isEnableOTP) {
try {
const resContact = await axios.post(
`${localStorage.getItem("baseUrl")}functions/getcontact`,
@@ -682,9 +682,9 @@ function PdfRequestFiles(props) {
);
let currentUser = JSON.parse(localuser);
let isEmailVerified = currentUser?.emailVerified;
const isDisableOTP = pdfDetails?.[0]?.IsDisableOTP || false;
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
//if emailVerified data is not present in local user details then fetch again in _User class
if (!isDisableOTP) {
if (isEnableOTP) {
try {
if (!currentUser?.emailVerified) {
const userQuery = new Parse.Query(Parse.User);
@@ -704,7 +704,7 @@ function PdfRequestFiles(props) {
}
}
//check if isEmailVerified then go on next step
if (isDisableOTP || isEmailVerified) {
if (!isEnableOTP || isEmailVerified) {
try {
const checkUser = signerPos.filter(
(data) => data.signerObjId === signerObjectId
@@ -1318,8 +1318,8 @@ function PdfRequestFiles(props) {
const closeRequestSignTour = async () => {
setRequestSignTour(true);
if (isDontShow) {
const isDisableOTP = pdfDetails?.[0]?.IsDisableOTP || false;
if (isDisableOTP) {
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
if (!isEnableOTP) {
try {
await axios.post(
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
@@ -267,7 +267,7 @@ const ReportTable = (props) => {
SendinOrder: Doc?.SendinOrder || false,
AutomaticReminders: Doc?.AutomaticReminders || false,
RemindOnceInEvery: Doc?.RemindOnceInEvery || 5,
IsDisableOTP: Doc?.IsDisableOTP || false
IsEnableOTP: Doc?.IsEnableOTP || false
};
try {
const res = await axios.post(
@@ -636,8 +636,8 @@
"sent-this-month": "Sent this month",
"available-seats": "Available seats",
"buy-users": "Buy more users",
"isdisable-otp": "Enable OTP verification",
"isdisable-otp-help": {
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
@@ -635,8 +635,8 @@
"sent-this-month": "envoyé ce mois-ci",
"available-seats": "Disponible sièges",
"buy-users": "Acheter plus d'utilisateurs",
"isdisable-otp": "Activer la vérification OTP",
"isdisable-otp-help": {
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
@@ -196,8 +196,9 @@ export default async function createDocumentWithTemplate(request, response) {
if (TimeToCompleteDays) {
object.set('TimeToCompleteDays', TimeToCompleteDays);
}
const isDisableOTP = template?.IsDisableOTP || request.body?.isDisableOTP || false;
object.set('IsDisableOTP', isDisableOTP);
const enableOTP = request.body?.enableOTP === true ? true : false;
const IsEnableOTP = template?.IsEnableOTP || enableOTP;
object.set('IsEnableOTP', IsEnableOTP);
object.set('CreatedBy', template.CreatedBy);
object.set('ExtUserPtr', {
__type: 'Pointer',
@@ -63,7 +63,7 @@ export default async function createDocumentwithCoordinate(request, response) {
const email_body = request.body.email_body;
const sendInOrder = request.body.sendInOrder || false;
const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
const isDisableOTP = request.body.isDisableOTP || false;
const IsEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData);
const protocol = customAPIurl();
const baseUrl = new URL(process.env.PUBLIC_URL);
@@ -163,7 +163,7 @@ export default async function createDocumentwithCoordinate(request, response) {
if (TimeToCompleteDays) {
object.set('TimeToCompleteDays', TimeToCompleteDays);
}
object.set('IsDisableOTP', isDisableOTP);
object.set('IsEnableOTP', IsEnableOTP);
object.set('IsSendMail', send_email);
let contact = [];
if (signers && signers.length > 0) {
@@ -9,6 +9,7 @@ export default async function createTemplate(request, response) {
const SendinOrder = request.body.sendInOrder || false;
const fileData = request.files?.[0] ? request.files[0].buffer : null;
const baseUrl = new URL(process.env.PUBLIC_URL);
const isEnableOTP = request.body?.enableOTP === true ? true : false;
try {
const reqToken = request.headers['x-api-token'];
@@ -65,6 +66,7 @@ export default async function createTemplate(request, response) {
object.set('URL', fileUrl);
object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr);
object.set('IsEnableOTP', isEnableOTP);
if (SendinOrder) {
object.set('SendinOrder', SendinOrder);
}
@@ -17,7 +17,7 @@ export default async function createTemplatewithCoordinate(request, response) {
const base64File = request.body.file;
const fileData = request.files?.[0] ? request.files[0].buffer : null;
const SendinOrder = request.body.sendInOrder || false;
const isDisableOTP = request.body.isDisableOTP || false;
const isEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData);
const protocol = customAPIurl();
@@ -82,7 +82,7 @@ export default async function createTemplatewithCoordinate(request, response) {
object.set('URL', fileUrl);
object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr);
object.set('IsDisableOTP', isDisableOTP);
object.set('IsEnableOTP', isEnableOTP);
let contact = [];
if (signers && signers.length > 0) {
let parseSigners;
@@ -12,6 +12,8 @@ export default async function draftDocument(request, response) {
const send_email = request.body.send_email || true;
const fileData = request.files?.[0] ? request.files[0].buffer : null;
const SendinOrder = request.body.sendInOrder || false;
const isEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData);
const protocol = customAPIurl();
const baseUrl = new URL(process.env.PUBLIC_URL);
@@ -83,6 +85,7 @@ export default async function draftDocument(request, response) {
object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr);
object.set('IsSendMail', send_email);
object.set('IsEnableOTP', isEnableOTP);
if (signers && signers.length > 0) {
let parseSigners;
if (base64File) {
@@ -62,6 +62,7 @@ export default async function getDocument(request, response) {
document?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) ||
[],
sendInOrder: document?.SendinOrder || false,
enableOTP: document?.IsEnableOTP || false,
createdAt: document.createdAt,
updatedAt: document.updatedAt,
});
@@ -100,6 +100,7 @@ export default async function getDocumentList(request, response) {
x?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) ||
[],
sendInOrder: x?.SendinOrder || false,
enableOTP: x?.IsEnableOTP || false,
createdAt: x.createdAt,
updatedAt: x.updatedAt,
}));
@@ -61,6 +61,7 @@ export default async function getTemplate(request, response) {
),
})) || [],
sendInOrder: template?.SendinOrder || false,
enableOTP: template?.IsEnableOTP || false,
createdAt: template.createdAt,
updatedAt: template.updatedAt,
});
@@ -88,6 +88,7 @@ export default async function getTemplatetList(request, response) {
),
})) || [],
sendInOrder: template?.SendinOrder || false,
enableOTP: template?.IsEnableOTP || false,
createdAt: template.createdAt,
updatedAt: template.updatedAt,
}));
@@ -48,6 +48,10 @@ export default async function updateDocument(request, response) {
objectId: request?.body?.folderId,
});
}
if (request.body?.enableOTP) {
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
}
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
if (updatedRes) {
if (request.posthog) {
@@ -48,6 +48,9 @@ export default async function updateTemplate(request, response) {
objectId: request?.body?.folderId,
});
}
if (request.body?.enableOTP) {
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
}
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
if (updatedRes) {
if (request.posthog) {
@@ -10,9 +10,9 @@ export default async function callWebhook(request) {
try {
const docQuery = new Parse.Query('contracts_Document');
const docRes = await docQuery.get(docId, { useMasterKey: true });
const isDisableOTP = docRes?.get('IsDisableOTP') || false;
const isEnableOTP = docRes?.get('IsEnableOTP') || false;
let userId;
if (!isDisableOTP) {
if (!isEnableOTP) {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': appId,
@@ -21,7 +21,7 @@ export default async function callWebhook(request) {
});
userId = userRes.data && userRes.data.objectId;
}
if (isDisableOTP || userId) {
if (!isEnableOTP || userId) {
if (event === 'viewed' && contactId) {
if (docRes) {
const _docRes = docRes.toJSON();
@@ -199,7 +199,7 @@ export default async function createBatchDocs(request) {
TimeToCompleteDays: x.TimeToCompleteDays || 15,
OriginIp: Ip,
DocSentAt: { __type: 'Date', iso: isoDate },
IsDisableOTP: x?.IsDisableOTP || false,
IsEnableOTP: x?.IsEnableOTP || false,
},
};
});
@@ -19,8 +19,8 @@ export default async function getDocument(request) {
query.notEqualTo('IsArchive', true);
const res = await query.first({ useMasterKey: true });
if (res) {
const IsDisableOTP = res?.get('IsDisableOTP') || false;
if (IsDisableOTP) {
const IsEnableOTP = res?.get('IsEnableOTP') || false;
if (!IsEnableOTP) {
return res;
} else {
if (request?.headers?.['sessiontoken']) {
@@ -34,7 +34,7 @@ export async function getSignedUrl(request) {
try {
const query = new Parse.Query('contracts_Document');
query.equalTo('objectId', docId);
query.equalTo('IsDisableOTP', true);
query.notEqualTo('IsEnableOTP', true);
query.include('CreatedBy');
query.include('Signers');
query.include('AuditTrail.UserPtr');
@@ -32,7 +32,7 @@ export default async function GenerateCertificate(docDetails) {
const OriginIp = docDetails?.OriginIp || '';
const company = docDetails?.ExtUserPtr?.Company || '';
const createdAt = docDetails?.DocSentAt?.iso || docDetails.createdAt;
const isDisableOTP = docDetails?.IsDisableOTP || false;
const IsEnableOTP = docDetails?.IsEnableOTP || false;
const auditTrail =
docDetails?.Signers?.length > 0
? docDetails.AuditTrail.map(x => {
@@ -349,7 +349,7 @@ export default async function GenerateCertificate(docDetails) {
font: timesRomanFont,
color: textValueColor,
});
if (!isDisableOTP) {
if (IsEnableOTP) {
page.drawText('Security level :', {
x: half + 55,
y: yPosition4 + 10,
@@ -286,9 +286,9 @@ async function PDF(req) {
if (!resDoc) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
}
const IsDisableOTP = resDoc?.get('IsDisableOTP') || false;
// if `IsDisableOTP` is true then we don't have to check authentication
if (!IsDisableOTP) {
const IsEnableOTP = resDoc?.get('IsEnableOTP') || false;
// if `IsEnableOTP` is false then we don't have to check authentication
if (IsEnableOTP) {
if (!req?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
@@ -4,12 +4,12 @@
*/
exports.up = async Parse => {
const templateSchema = new Parse.Schema('contracts_Template');
templateSchema.addBoolean('IsDisableOTP');
templateSchema.addBoolean('IsEnableOTP');
await templateSchema.update();
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.addBoolean('IsDisableOTP');
schema.addBoolean('IsEnableOTP');
return schema.update();
};
@@ -19,11 +19,11 @@ exports.up = async Parse => {
*/
exports.down = async Parse => {
const templateSchema = new Parse.Schema('contracts_Template');
templateSchema.deleteField('IsDisableOTP');
templateSchema.deleteField('IsEnableOTP');
await templateSchema.update();
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.deleteField('IsDisableOTP');
schema.deleteField('IsEnableOTP');
return schema.update();
};