diff --git a/.eslintrc.json b/.eslintrc.json
index dd7a6de13..392b5c2c3 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -21,6 +21,7 @@
"extends": [
"airbnb",
"eslint:recommended",
+ "@typescript-eslint/parser",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:react/recommended",
diff --git a/package-lock.json b/package-lock.json
index 4be1bb22f..b80ddb7e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -48,7 +48,7 @@
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"cypress": "^10.11.0",
- "eslint": "^8.13.0",
+ "eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^2.7.1",
@@ -67,6 +67,15 @@
"vite-plugin-pwa": "^0.12.0"
}
},
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/@adobe/css-tools": {
"version": "4.2.0",
"license": "MIT"
@@ -1860,21 +1869,23 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.5.1",
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/@eslint/eslintrc": {
- "version": "2.0.3",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.5.2",
+ "espree": "^9.6.0",
"globals": "^13.19.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
@@ -1890,9 +1901,10 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.20.0",
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -1905,8 +1917,9 @@
},
"node_modules/@eslint/eslintrc/node_modules/type-fest": {
"version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
- "license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
},
@@ -1915,20 +1928,22 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.41.0",
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
"dev": true,
- "license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@humanwhocodes/config-array": {
- "version": "0.11.8",
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
- "@humanwhocodes/object-schema": "^1.2.1",
- "debug": "^4.1.1",
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
"minimatch": "^3.0.5"
},
"engines": {
@@ -1948,9 +1963,10 @@
}
},
"node_modules/@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "dev": true,
- "license": "BSD-3-Clause"
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
+ "dev": true
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
@@ -4261,6 +4277,12 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
"node_modules/@zeit/schemas": {
"version": "2.29.0",
"dev": true,
@@ -4284,9 +4306,10 @@
}
},
"node_modules/acorn": {
- "version": "8.8.2",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
- "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -4316,8 +4339,9 @@
},
"node_modules/acorn-jsx": {
"version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
- "license": "MIT",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
@@ -4355,8 +4379,9 @@
},
"node_modules/ajv": {
"version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
- "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -4514,8 +4539,9 @@
},
"node_modules/argparse": {
"version": "2.0.1",
- "dev": true,
- "license": "Python-2.0"
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
},
"node_modules/aria-query": {
"version": "5.1.3",
@@ -6715,26 +6741,28 @@
}
},
"node_modules/eslint": {
- "version": "8.41.0",
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.0.3",
- "@eslint/js": "8.41.0",
- "@humanwhocodes/config-array": "^0.11.8",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.10.0",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.0",
- "eslint-visitor-keys": "^3.4.1",
- "espree": "^9.5.2",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -6744,7 +6772,6 @@
"globals": "^13.19.0",
"graphemer": "^1.4.0",
"ignore": "^5.2.0",
- "import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"is-path-inside": "^3.0.3",
@@ -6754,9 +6781,8 @@
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
+ "optionator": "^0.9.3",
"strip-ansi": "^6.0.1",
- "strip-json-comments": "^3.1.0",
"text-table": "^0.2.0"
},
"bin": {
@@ -7072,9 +7098,10 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "3.4.1",
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
- "license": "Apache-2.0",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -7139,9 +7166,10 @@
}
},
"node_modules/eslint/node_modules/eslint-scope": {
- "version": "7.2.0",
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
"dev": true,
- "license": "BSD-2-Clause",
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
@@ -7198,11 +7226,12 @@
}
},
"node_modules/espree": {
- "version": "9.5.2",
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
"dev": true,
- "license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.8.0",
+ "acorn": "^8.9.0",
"acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.4.1"
},
@@ -8058,8 +8087,9 @@
},
"node_modules/import-fresh": {
"version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@@ -12671,8 +12701,9 @@
},
"node_modules/js-yaml": {
"version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -12766,8 +12797,9 @@
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
- "dev": true,
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
@@ -12883,8 +12915,9 @@
},
"node_modules/levn": {
"version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
@@ -13767,16 +13800,17 @@
}
},
"node_modules/optionator": {
- "version": "0.9.1",
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
"dev": true,
- "license": "MIT",
"dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
+ "type-check": "^0.4.0"
},
"engines": {
"node": ">= 0.8.0"
@@ -13839,8 +13873,9 @@
},
"node_modules/parent-module": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
- "license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
@@ -14082,8 +14117,9 @@
},
"node_modules/prelude-ls": {
"version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 0.8.0"
}
@@ -15210,8 +15246,9 @@
},
"node_modules/resolve-from": {
"version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -16376,8 +16413,9 @@
},
"node_modules/type-check": {
"version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
- "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1"
},
diff --git a/package.json b/package.json
index 35d6c7167..8a374b1d2 100644
--- a/package.json
+++ b/package.json
@@ -9,13 +9,13 @@
},
"dependencies": {
"@jest/globals": "^28.1.0",
+ "@playwright/test": "^1.38.1",
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^11.2.7",
"@types/node": "^17.0.31",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"@types/uuid": "^8.3.4",
- "@playwright/test": "^1.38.1",
"antd": "^5.4.3",
"crypto-js": "^4.2.0",
"dexie": "^3.2.3",
@@ -85,7 +85,7 @@
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"cypress": "^10.11.0",
- "eslint": "^8.13.0",
+ "eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^2.7.1",
diff --git a/playwright/utils/collaboration-feature-utils.ts b/playwright/utils/collaboration-feature-utils.ts
index 2ea6e30b7..fb4440fc6 100644
--- a/playwright/utils/collaboration-feature-utils.ts
+++ b/playwright/utils/collaboration-feature-utils.ts
@@ -14,7 +14,7 @@ export async function goalActionFlow(page: Page, action: string) {
.locator("div")
.filter({ hasText: new RegExp(`^${action}$`) })
.first()
- .click();
+ .click({ force: true });
}
export async function goToShareGoalModalFlow(page: Page) {
diff --git a/src/Interfaces/IPopupModals.ts b/src/Interfaces/IPopupModals.ts
index d4d620e91..31223eb39 100644
--- a/src/Interfaces/IPopupModals.ts
+++ b/src/Interfaces/IPopupModals.ts
@@ -5,22 +5,24 @@ export interface confirmActionState {
delete: boolean;
shareAnonymously: boolean;
shareWithOne: boolean;
+ restore: boolean;
};
collaboration: {
colabRequest: boolean;
delete: boolean;
archive: boolean;
+ restore: boolean;
};
}
export interface confirmGoalAction {
actionCategory: "goal";
- actionName: "archive" | "delete" | "shareAnonymously" | "shareWithOne";
+ actionName: "archive" | "delete" | "shareAnonymously" | "shareWithOne" | "restore";
}
export interface confirmColabGoalAction {
actionCategory: "collaboration";
- actionName: "colabRequest" | "delete" | "archive";
+ actionName: "colabRequest" | "delete" | "archive" | "restore";
}
export interface ConfirmationModalProps {
diff --git a/src/Interfaces/index.ts b/src/Interfaces/index.ts
index 08b03190c..6ab837dc4 100644
--- a/src/Interfaces/index.ts
+++ b/src/Interfaces/index.ts
@@ -1,4 +1,4 @@
-import { ISubGoalHistory } from "@src/store/GoalsState";
+import { ISubGoalHistory, TDisplayGoalActions } from "@src/store/GoalsState";
import { GoalItem, IParticipant } from "@src/models/GoalItem";
import ContactItem from "@src/models/ContactItem";
import { ILanguage, ILanguageListProps } from "./ILanguage";
@@ -20,7 +20,7 @@ export interface ILocationState {
displayInputNoteModal?: number; // show input modal for adding note for id
changeTheme?: boolean; // theme changer mode
expandedGoalId?: string; // id of goal to be expanded
- displayGoalActions?: GoalItem; // id of goal whose actions have to be opened
+ displayGoalActions?: TDisplayGoalActions; // id of goal whose actions have to be opened
displayPartnerMode?: boolean; // whether or not to display the partner goals
displayAddContact?: boolean; // whether or not to display the add contact form
displayParticipants?: string; // id of goal whose participants have to be displayed
diff --git a/src/api/GoalsAPI/index.ts b/src/api/GoalsAPI/index.ts
old mode 100644
new mode 100755
index c9c26ad10..e23d557c4
--- a/src/api/GoalsAPI/index.ts
+++ b/src/api/GoalsAPI/index.ts
@@ -3,6 +3,7 @@ import { db } from "@models";
import { GoalItem, IParticipant } from "@src/models/GoalItem";
import { shareGoal } from "@src/services/goal.service";
import { sortGoalsByProps } from "../GCustomAPI";
+import { addDeletedGoal } from "../TrashAPI";
export const addIntoSublist = async (parentGoalId: string, goalIds: string[]) => {
db.transaction("rw", db.goalsCollection, async () => {
@@ -132,8 +133,11 @@ export const unarchiveUserGoal = async (goal: GoalItem) => {
await unarchiveGoal(goal);
};
-export const removeGoal = async (goalId: string) => {
- await db.goalsCollection.delete(goalId).catch((err) => console.log("failed to delete", err));
+export const removeGoal = async (goal: GoalItem) => {
+ await Promise.allSettled([
+ db.goalsCollection.delete(goal.id).catch((err) => console.log("failed to delete", err)),
+ addDeletedGoal(goal),
+ ]);
};
export const removeChildrenGoals = async (parentGoalId: string) => {
@@ -143,7 +147,7 @@ export const removeChildrenGoals = async (parentGoalId: string) => {
}
childrenGoals.forEach((goal) => {
removeChildrenGoals(goal.id);
- removeGoal(goal.id);
+ removeGoal(goal);
});
};
@@ -259,7 +263,7 @@ export const notifyNewColabRequest = async (id: string, relId: string) => {
export const removeGoalWithChildrens = async (goal: GoalItem) => {
await removeChildrenGoals(goal.id);
- await removeGoal(goal.id);
+ await removeGoal(goal);
if (goal.parentGoalId !== "root") {
getGoal(goal.parentGoalId).then(async (parentGoal: GoalItem) => {
const parentGoalSublist = parentGoal.sublist;
diff --git a/src/api/InboxAPI/index.ts b/src/api/InboxAPI/index.ts
index d27f9a677..5f8af9be6 100644
--- a/src/api/InboxAPI/index.ts
+++ b/src/api/InboxAPI/index.ts
@@ -30,7 +30,7 @@ export const addGoalChangesInID = async (id: string, relId: string, newChanges:
.where("id")
.equals(id)
.modify((obj: InboxItem) => {
- const currentState = obj.changes[relId] || getDefaultValueOfGoalChanges();
+ const currentState = { ...getDefaultValueOfGoalChanges(), ...obj.changes[relId] };
Object.keys(currentState).forEach((changeType: typeOfChange) => {
currentState[changeType] = [...currentState[changeType], ...newChanges[changeType]];
});
diff --git a/src/api/SharedWMAPI/index.ts b/src/api/SharedWMAPI/index.ts
index d968939f0..7c86c7ddf 100644
--- a/src/api/SharedWMAPI/index.ts
+++ b/src/api/SharedWMAPI/index.ts
@@ -3,6 +3,7 @@ import { db } from "@models";
import { GoalItem } from "@src/models/GoalItem";
import { createGoalObjectFromTags } from "@src/helpers/GoalProcessor";
import { addGoal } from "../GoalsAPI";
+import { addDeletedGoal } from "../TrashAPI";
export const addSharedWMSublist = async (parentGoalId: string, goalIds: string[]) => {
db.transaction("rw", db.sharedWMCollection, async () => {
@@ -74,7 +75,7 @@ export const getRootGoalsOfPartner = async (relId: string) => {
await db.sharedWMCollection
.where("parentGoalId")
.equals("root")
- .and((x) => x.participants[0].relId === relId)
+ .and((x) => x.participants.length > 0 && x.participants[0].relId === relId)
.sortBy("createdAt")
).reverse();
};
@@ -116,8 +117,11 @@ export const archiveSharedWMGoal = async (goal: GoalItem) => {
await archiveGoal(goal);
};
-export const removeSharedWMGoal = async (goalId: string) => {
- await db.sharedWMCollection.delete(goalId).catch((err) => console.log("failed to delete", err));
+export const removeSharedWMGoal = async (goal: GoalItem) => {
+ await Promise.allSettled([
+ addDeletedGoal(goal),
+ db.sharedWMCollection.delete(goal.id).catch((err) => console.log("failed to delete", err)),
+ ]);
};
export const removeSharedWMChildrenGoals = async (parentGoalId: string) => {
@@ -127,7 +131,7 @@ export const removeSharedWMChildrenGoals = async (parentGoalId: string) => {
}
childrenGoals.forEach((goal) => {
removeSharedWMChildrenGoals(goal.id);
- removeSharedWMGoal(goal.id);
+ removeSharedWMGoal(goal);
});
};
@@ -138,7 +142,7 @@ export const transferToMyGoals = async (id: string) => {
}
childrenGoals.forEach((goal) => {
transferToMyGoals(goal.id);
- addGoal(goal).then(async () => removeSharedWMGoal(goal.id));
+ addGoal(goal).then(async () => removeSharedWMGoal(goal));
});
};
@@ -147,7 +151,7 @@ export const convertSharedWMGoalToColab = async (goal: GoalItem) => {
.then(async () => {
addGoal({ ...goal, typeOfGoal: "shared" })
.then(async () => {
- removeSharedWMGoal(goal.id);
+ removeSharedWMGoal(goal);
})
.catch((err) => console.log(err));
})
diff --git a/src/api/TrashAPI/index.ts b/src/api/TrashAPI/index.ts
new file mode 100755
index 000000000..0ec5cbd50
--- /dev/null
+++ b/src/api/TrashAPI/index.ts
@@ -0,0 +1,98 @@
+/* eslint-disable no-param-reassign */
+import { db } from "@models";
+import { GoalItem } from "@src/models/GoalItem";
+import { TrashItem } from "@src/models/TrashItem";
+import { addGoal } from "../GoalsAPI";
+import { addSharedWMGoal } from "../SharedWMAPI";
+
+export const getDeletedGoals = async (parentGoalId: string) => {
+ const childrenGoals: TrashItem[] = await db.goalTrashCollection
+ .where("parentGoalId")
+ .equals(parentGoalId)
+ .sortBy("deletedAt");
+ childrenGoals.reverse();
+ return childrenGoals;
+};
+
+export const addDeletedGoal = async (goal: GoalItem) => {
+ await db
+ .transaction("rw", db.goalTrashCollection, async () => {
+ await db.goalTrashCollection.add({ ...goal, deletedAt: new Date().toISOString() });
+ })
+ .catch((e) => {
+ console.log(e.stack || e);
+ });
+};
+
+export const getDeletedGoal = async (goalId: string) => {
+ const delGoal: TrashItem[] = await db.goalTrashCollection.where("id").equals(goalId).toArray();
+ return delGoal.length > 0 ? delGoal[0] : null;
+};
+
+export const restoreGoal = async (goal: GoalItem, isShareWMType = false) => {
+ db.goalTrashCollection.delete(goal.id).catch((err) => console.log("failed to delete", err));
+ if (isShareWMType) {
+ await addSharedWMGoal(goal);
+ } else {
+ await addGoal(goal);
+ }
+};
+
+export const restoreChildrenGoals = async (id: string, isShareWMType = false) => {
+ const childrenGoals: TrashItem[] = await getDeletedGoals(id);
+ if (childrenGoals) {
+ childrenGoals.forEach(async ({ deletedAt, ...goal }) => {
+ await restoreChildrenGoals(goal.id, isShareWMType);
+ await restoreGoal(goal, isShareWMType);
+ });
+ }
+};
+
+export const restoreUserGoal = async (goal: GoalItem, isShareWMType = false) => {
+ await restoreChildrenGoals(goal.id, isShareWMType);
+ await restoreGoal(goal, isShareWMType);
+};
+
+export const removeDeletedGoal = async (goal: GoalItem) => {
+ await Promise.allSettled([
+ db.goalsCollection.delete(goal.id).catch((err) => console.log("failed to delete", err)),
+ addDeletedGoal(goal),
+ ]);
+};
+
+export const removeDeletedChildrenGoals = async (parentGoalId: string) => {
+ const childrenGoals = await getDeletedGoals(parentGoalId);
+ if (childrenGoals.length === 0) {
+ return;
+ }
+ childrenGoals.forEach((goal) => {
+ removeDeletedChildrenGoals(goal.id);
+ removeDeletedGoal(goal);
+ });
+};
+
+export const removeDeletedGoalWithChildrens = async (goal: GoalItem) => {
+ await removeDeletedChildrenGoals(goal.id);
+ await removeDeletedGoal(goal);
+ if (goal.parentGoalId !== "root") {
+ getDeletedGoal(goal.parentGoalId).then(async (deletedGoal) => {
+ if (!deletedGoal) {
+ return;
+ }
+ const parentGoalSublist = deletedGoal.sublist;
+ const childGoalIndex = parentGoalSublist.indexOf(goal.id);
+ if (childGoalIndex !== -1) {
+ parentGoalSublist.splice(childGoalIndex, 1);
+ }
+ await db.goalTrashCollection.update(deletedGoal.id, { sublist: parentGoalSublist }).then((updated) => updated);
+ });
+ }
+};
+
+export const getParticipantsOfDeletedGoal = async (id: string) => {
+ const goals = await db.goalTrashCollection
+ .where("id")
+ .anyOf(...[id])
+ .toArray();
+ return goals.flatMap((goal) => goal.participants.map((participant) => ({ sub: participant, rootGoalId: goal.id })));
+};
diff --git a/src/components/GoalsComponents/ArchivedAccordion.tsx b/src/components/GoalsComponents/ArchivedAccordion.tsx
deleted file mode 100644
index 4a147caf0..000000000
--- a/src/components/GoalsComponents/ArchivedAccordion.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from "react";
-import { useRecoilValue } from "recoil";
-import { darkModeState } from "@src/store";
-
-import { GoalItem } from "@src/models/GoalItem";
-import ZAccordion from "@src/common/Accordion";
-
-import MyGoal from "./MyGoal/MyGoal";
-
-interface IArchivedAccordionProps {
- archivedGoals: GoalItem[];
- showActions: {
- open: string;
- click: number;
- };
- setShowActions: React.Dispatch<
- React.SetStateAction<{
- open: string;
- click: number;
- }>
- >;
-}
-const ArchivedAccordion: React.FC = ({ archivedGoals, showActions, setShowActions }) => {
- const darkModeStatus = useRecoilValue(darkModeState);
- return (
-
- {archivedGoals.length > 0 && (
- (
-
- )),
- },
- ]}
- />
- )}
-
- );
-};
-
-export default ArchivedAccordion;
diff --git a/src/components/GoalsComponents/DisplayChangesModal/AcceptBtn.tsx b/src/components/GoalsComponents/DisplayChangesModal/AcceptBtn.tsx
index 3992d4896..0b2f87fa5 100644
--- a/src/components/GoalsComponents/DisplayChangesModal/AcceptBtn.tsx
+++ b/src/components/GoalsComponents/DisplayChangesModal/AcceptBtn.tsx
@@ -31,6 +31,7 @@ const AcceptBtn = ({ typeAtPriority, acceptChanges }: AcceptBtnProps) => {
/>
{typeAtPriority === "archived" && "Complete for me too"}
+ {typeAtPriority === "restored" && "Restore for me too"}
{typeAtPriority === "deleted" && "Delete for me too"}
{typeAtPriority === "subgoals" && "Add all checked"}
{typeAtPriority === "modifiedGoals" && "Make all checked changes"}
diff --git a/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx b/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx
index b2e9a2802..738c35596 100644
--- a/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx
+++ b/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx
@@ -15,6 +15,7 @@ import { archiveUserGoal, getGoal, removeGoalWithChildrens, updateGoal } from "@
import { deleteGoalChangesInID, getInboxItem, removeGoalInbox, removePPTFromInboxOfGoal } from "@src/api/InboxAPI";
import { findGoalTagChanges, jumpToLowestChanges } from "@src/helpers/GoalProcessor";
import { acceptSelectedSubgoals, acceptSelectedTags } from "@src/helpers/InboxProcessor";
+import { getDeletedGoal, restoreUserGoal } from "@src/api/TrashAPI";
import SubHeader from "@src/common/SubHeader";
import ContactItem from "@src/models/ContactItem";
import ZModal from "@src/common/ZModal";
@@ -163,6 +164,8 @@ const DisplayChangesModal = () => {
await removeGoalWithChildrens(activeGoal);
} else if (currentDisplay === "archived") {
await archiveUserGoal(activeGoal);
+ } else if (currentDisplay === "restored") {
+ await restoreUserGoal(activeGoal);
}
setCurrentDisplay("none");
};
@@ -185,21 +188,29 @@ const DisplayChangesModal = () => {
const currPPT = participants[activePPT].relId;
setActivePPT(0);
setParticipants([...participants.filter((ele) => ele.relId !== currPPT)]);
- }
- const changedGoal = await getGoal(parentId);
- if (changedGoal) {
- setActiveGoal({ ...changedGoal });
- if (typeAtPriority === "subgoals") {
- setNewGoals(goals || []);
- } else if (typeAtPriority === "modifiedGoals") {
- setUpdatesIntent(goals[0].intent);
- const incGoal: GoalItem = { ...goals[0].goal };
- setUpdateList({ ...findGoalTagChanges(changedGoal, incGoal) });
+ } else if (typeAtPriority === "restored") {
+ const goalToBeRestored = await getDeletedGoal(parentId);
+ console.log("🚀 ~ getChanges ~ goalToBeRestored:", goalToBeRestored);
+ if (goalToBeRestored) {
+ delete goalToBeRestored.deletedAt;
+ setActiveGoal(goalToBeRestored);
}
- if (currentDisplay !== typeAtPriority) {
- setCurrentDisplay(typeAtPriority);
+ } else {
+ const changedGoal = await getGoal(parentId);
+ if (changedGoal) {
+ setActiveGoal({ ...changedGoal });
+ if (typeAtPriority === "subgoals") {
+ setNewGoals(goals || []);
+ } else if (typeAtPriority === "modifiedGoals") {
+ setUpdatesIntent(goals[0].intent);
+ const incGoal: GoalItem = { ...goals[0].goal };
+ setUpdateList({ ...findGoalTagChanges(changedGoal, incGoal) });
+ }
}
}
+ if (currentDisplay !== typeAtPriority) {
+ setCurrentDisplay(typeAtPriority);
+ }
}
};
@@ -273,9 +284,10 @@ const DisplayChangesModal = () => {
/>
)}
- {(currentDisplay === "archived" || currentDisplay === "deleted") && }
+ {["deleted", "archived", "restored"].includes(currentDisplay) && }
{currentDisplay === "modifiedGoals" && getEditChangesList()}
{currentDisplay === "subgoals" && getSubgoalsList()}
+
{activeGoal && (
<>
diff --git a/src/components/GoalsComponents/DisplayChangesModal/Header.tsx b/src/components/GoalsComponents/DisplayChangesModal/Header.tsx
index e14fc414f..16f5cc644 100644
--- a/src/components/GoalsComponents/DisplayChangesModal/Header.tsx
+++ b/src/components/GoalsComponents/DisplayChangesModal/Header.tsx
@@ -36,6 +36,12 @@ const Header = ({
{contactName} completed {title}.
>
);
+ case "restored":
+ return (
+ <>
+ {contactName} restored {title}.
+ >
+ );
default:
return <> >;
}
diff --git a/src/components/GoalsComponents/GoalSublist/GoalSublist.tsx b/src/components/GoalsComponents/GoalSublist/GoalSublist.tsx
old mode 100644
new mode 100755
index f617ce98c..497bc9eb0
--- a/src/components/GoalsComponents/GoalSublist/GoalSublist.tsx
+++ b/src/components/GoalsComponents/GoalSublist/GoalSublist.tsx
@@ -2,11 +2,6 @@ import React, { useEffect, useState } from "react";
import { useRecoilValue } from "recoil";
import { useTranslation } from "react-i18next";
-import { GoalItem } from "@src/models/GoalItem";
-import { getChildrenGoals, getGoal } from "@src/api/GoalsAPI";
-import { createGoalObjectFromTags } from "@src/helpers/GoalProcessor";
-import { getSharedWMChildrenGoals, getSharedWMGoal } from "@src/api/SharedWMAPI";
-import { displayPartnerMode, lastAction } from "@src/store";
import {
displayAddGoal,
displayChangesModal,
@@ -14,13 +9,19 @@ import {
displaySuggestionsModal,
displayUpdateGoal,
} from "@src/store/GoalsState";
+import { GoalItem } from "@src/models/GoalItem";
+import { getDeletedGoals } from "@src/api/TrashAPI";
+import { createGoalObjectFromTags } from "@src/helpers/GoalProcessor";
+import { getChildrenGoals, getGoal } from "@src/api/GoalsAPI";
+import { displayPartnerMode, lastAction } from "@src/store";
+import { getSharedWMChildrenGoals, getSharedWMGoal } from "@src/api/SharedWMAPI";
import GoalsList from "../GoalsList";
import ConfigGoal from "../GoalConfigModal/ConfigGoal";
+import GoalHistory from "./GoalHistory";
+import GoalsAccordion from "../GoalsAccordion";
import "./GoalSublist.scss";
-import GoalHistory from "./GoalHistory";
-import ArchivedAccordion from "../ArchivedAccordion";
export const GoalSublist = () => {
const { t } = useTranslation();
@@ -33,6 +34,7 @@ export const GoalSublist = () => {
const showPartnerMode = useRecoilValue(displayPartnerMode);
const [parentGoal, setParentGoal] = useState
(null);
const [childrenGoals, setChildrenGoals] = useState([]);
+ const [deletedGoals, setDeletedGoals] = useState([]);
const [archivedChildren, setArchivedChildren] = useState([]);
const [showActions, setShowActions] = useState({ open: "root", click: 1 });
@@ -42,12 +44,20 @@ export const GoalSublist = () => {
};
useEffect(() => {
- (showPartnerMode ? getSharedWMGoal(goalID) : getGoal(goalID)).then((parent) => setParentGoal(parent));
+ (showPartnerMode ? getSharedWMGoal(goalID) : getGoal(goalID)).then((parent) => {
+ setParentGoal(parent);
+ getDeletedGoals(goalID).then((res) => {
+ setDeletedGoals([...res.map(({ deletedAt, ...goal }) => goal)]);
+ });
+ });
}, [goalID]);
useEffect(() => {
(showPartnerMode ? getSharedWMChildrenGoals(goalID) : getChildrenGoals(goalID)).then((fetchedGoals) => {
handleChildrenGoals(fetchedGoals);
+ getDeletedGoals(goalID).then((res) => {
+ setDeletedGoals([...res.map(({ deletedAt, ...goal }) => goal)]);
+ });
});
}, [action, parentGoal, showAddGoal, showSuggestionModal, showChangesModal, showUpdateGoal]);
@@ -65,8 +75,15 @@ export const GoalSublist = () => {
setGoals={setChildrenGoals}
setShowActions={setShowActions}
/>
-
+
diff --git a/src/components/GoalsComponents/GoalsAccordion.tsx b/src/components/GoalsComponents/GoalsAccordion.tsx
new file mode 100755
index 000000000..e74a8ef93
--- /dev/null
+++ b/src/components/GoalsComponents/GoalsAccordion.tsx
@@ -0,0 +1,71 @@
+import React from "react";
+import { useRecoilValue } from "recoil";
+import { darkModeState } from "@src/store";
+
+import { GoalItem } from "@src/models/GoalItem";
+import ZAccordion from "@src/common/Accordion";
+
+import MyGoal from "./MyGoal/MyGoal";
+import { TAction, displayGoalActions } from "@src/store/GoalsState";
+import AccordionActions from "./MyGoalActions/AccordionActions";
+
+interface IGoalsAccordionProps {
+ header: "Done" | "Trash";
+ goals: GoalItem[];
+ showActions: {
+ open: string;
+ click: number;
+ };
+ setShowActions: React.Dispatch<
+ React.SetStateAction<{
+ open: string;
+ click: number;
+ }>
+ >;
+}
+
+const actionsMap: {
+ [key: string]: TAction;
+} = {
+ Done: "archived",
+ Trash: "deleted",
+};
+
+const GoalsAccordion: React.FC = ({ header, goals, showActions, setShowActions }) => {
+ const darkModeStatus = useRecoilValue(darkModeState);
+ const actionType = actionsMap[header] || "regular";
+ const showGoalActions = useRecoilValue(displayGoalActions);
+
+ return (
+
+ {showGoalActions && ["archived", "deleted"].includes(showGoalActions.actionType) && (
+
+ )}
+ {goals.length > 0 && (
+
(
+
+ )),
+ },
+ ]}
+ />
+ )}
+
+ );
+};
+
+export default GoalsAccordion;
diff --git a/src/components/GoalsComponents/GoalsList.tsx b/src/components/GoalsComponents/GoalsList.tsx
index 58fe77fec..7588480d9 100644
--- a/src/components/GoalsComponents/GoalsList.tsx
+++ b/src/components/GoalsComponents/GoalsList.tsx
@@ -2,10 +2,12 @@ import { updatePositionIndex } from "@src/api/GCustomAPI";
import DragAndDrop from "@src/layouts/DragAndDrop";
import { GoalItem } from "@src/models/GoalItem";
import React, { useState } from "react";
-import { displayUpdateGoal } from "@src/store/GoalsState";
+import { displayGoalActions, displayUpdateGoal } from "@src/store/GoalsState";
import { useRecoilValue } from "recoil";
import ConfigGoal from "./GoalConfigModal/ConfigGoal";
import MyGoal from "./MyGoal/MyGoal";
+import MyGoalActions from "./MyGoalActions/MyGoalActions";
+import RegularGoalActions from "./MyGoalActions/RegularGoalActions";
interface GoalsListProps {
goals: GoalItem[];
@@ -22,12 +24,13 @@ interface GoalsListProps {
>;
}
-const GoalsList: React.FC = ({ goals, showActions, setGoals, setShowActions }) => {
+const GoalsList = ({ goals, showActions, setGoals, setShowActions }: GoalsListProps) => {
const showUpdateGoal = useRecoilValue(displayUpdateGoal);
+ const showGoalActions = useRecoilValue(displayGoalActions);
const [dragging, setDragging] = useState(false);
const [draggedItem, setDraggedItem] = useState(null);
- const handleDragStart = (e, index: number) => {
+ const handleDragStart = (e: any, index: number) => {
setDragging(true);
setDraggedItem(goals[index]);
e.dataTransfer.effectAllowed = "move";
@@ -48,22 +51,29 @@ const GoalsList: React.FC = ({ goals, showActions, setGoals, set
const posIndexPromises = goals.map(async (ele, index) => updatePositionIndex(ele.id, index));
Promise.all(posIndexPromises).catch((err) => console.log("error in sorting", err));
};
- return goals.map((goal: GoalItem, index: number) => (
- // eslint-disable-next-line react/no-array-index-key
-
- {showUpdateGoal?.goalId === goal.id && }
-
-
-
-
- ));
+ return (
+ <>
+ {showGoalActions && showGoalActions.actionType === "regular" && (
+
+ )}
+ {goals.map((goal: GoalItem, index: number) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ {showUpdateGoal?.goalId === goal.id && }
+
+
+
+
+ ))}
+ >
+ );
};
export default GoalsList;
diff --git a/src/components/GoalsComponents/MyGoal/MyGoal.tsx b/src/components/GoalsComponents/MyGoal/MyGoal.tsx
index 84aa73204..c6b439ec4 100644
--- a/src/components/GoalsComponents/MyGoal/MyGoal.tsx
+++ b/src/components/GoalsComponents/MyGoal/MyGoal.tsx
@@ -1,18 +1,23 @@
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
-import { useRecoilValue } from "recoil";
+import { useRecoilValue, useSetRecoilState } from "recoil";
+
+import { unarchiveIcon } from "@src/assets";
import { GoalItem } from "@src/models/GoalItem";
+import { unarchiveUserGoal } from "@src/api/GoalsAPI";
-import { darkModeState, displayPartnerMode, lastAction } from "@src/store";
-import { displayGoalId, displayUpdateGoal, goalsHistory, displayChangesModal } from "@src/store/GoalsState";
+import { darkModeState, displayPartnerMode } from "@src/store";
+import { displayGoalId, displayUpdateGoal, goalsHistory, displayChangesModal, TAction } from "@src/store/GoalsState";
import GoalAvatar from "../GoalAvatar";
import GoalSummary from "./GoalSummary/GoalSummary";
import GoalDropdown from "./GoalDropdown";
import GoalTitle from "./GoalTitle";
+import { ILocationState } from "@src/Interfaces";
interface MyGoalProps {
+ actionType: TAction;
goal: GoalItem;
showActions: {
open: string;
@@ -22,12 +27,11 @@ interface MyGoalProps {
React.SetStateAction<{
open: string;
click: number;
- // eslint-disable-next-line prettier/prettier
}>
>;
}
-const MyGoal: React.FC = ({ goal, showActions, setShowActions }) => {
+const MyGoal: React.FC = ({ goal, actionType, showActions, setShowActions }) => {
const archived = goal.archived === "true";
const defaultTap = { open: "root", click: 1 };
const isActionVisible = !archived && showActions.open === goal.id && showActions.click > 0;
@@ -73,12 +77,11 @@ const MyGoal: React.FC = ({ goal, showActions, setShowActions }) =>
};
async function handleDropDown(e: React.MouseEvent) {
e.stopPropagation();
- const navState = { ...location.state, from: "" };
+ const navState: ILocationState = { ...location.state, from: "" };
if (goal.newUpdates) {
navState.displayChanges = goal;
} else {
- navState.displayGoalActions = goal;
- console.log("in navstate, displayGoalActions: ", navState);
+ navState.displayGoalActions = { actionType, goal };
}
navigate("/MyGoals", { state: navState });
}
diff --git a/src/components/GoalsComponents/MyGoalActions/AccordionActions.tsx b/src/components/GoalsComponents/MyGoalActions/AccordionActions.tsx
new file mode 100644
index 000000000..45616b810
--- /dev/null
+++ b/src/components/GoalsComponents/MyGoalActions/AccordionActions.tsx
@@ -0,0 +1,122 @@
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useRecoilValue, useSetRecoilState } from "recoil";
+
+import ZModal from "@src/common/ZModal";
+import useGoalStore from "@src/hooks/useGoalStore";
+import ConfirmationModal from "@src/common/ConfirmationModal";
+
+import { GoalItem } from "@src/models/GoalItem";
+import { restoreGoal } from "@src/helpers/GoalController";
+import { confirmAction } from "@src/Interfaces/IPopupModals";
+import { unarchiveIcon } from "@src/assets";
+import { unarchiveUserGoal } from "@src/api/GoalsAPI";
+import { TAction, goalsHistory } from "@src/store/GoalsState";
+import { archiveThisGoal, removeThisGoal } from "@src/helpers/GoalActionHelper";
+import { lastAction, openDevMode, displayConfirmation, displayPartnerMode, darkModeState } from "@src/store";
+
+import ActionDiv from "./ActionDiv";
+import "./MyGoalActions.scss";
+
+const AccordionActions = ({ actionType, goal, open }: { actionType: TAction; open: boolean; goal: GoalItem }) => {
+ const { t } = useTranslation();
+ const { handleUpdateGoal, handleConfirmation } = useGoalStore();
+ const confirmActionCategory = goal.typeOfGoal === "shared" && goal.parentGoalId === "root" ? "collaboration" : "goal";
+
+ const subGoalsHistory = useRecoilValue(goalsHistory);
+ const showConfirmation = useRecoilValue(displayConfirmation);
+ const isPartnerGoal = useRecoilValue(displayPartnerMode);
+ const setDevMode = useSetRecoilState(openDevMode);
+ const darkModeStatus = useRecoilValue(darkModeState);
+ const setLastAction = useSetRecoilState(lastAction);
+ const ancestors = subGoalsHistory.map((ele) => ele.goalID);
+
+ const [confirmationAction, setConfirmationAction] = useState(null);
+
+ const handleActionClick = async (action: string) => {
+ if (action === "delete") {
+ if (goal.title === "magic") {
+ setDevMode(false);
+ }
+ await removeThisGoal(goal, ancestors, isPartnerGoal);
+ setLastAction("goalDeleted");
+ } else if (action === "archive") {
+ await archiveThisGoal(goal, ancestors);
+ setLastAction("goalArchived");
+ } else if (action === "restore") {
+ if (actionType === "archived") {
+ await unarchiveUserGoal(goal);
+ } else if (actionType === "deleted") {
+ await restoreGoal(goal, ancestors);
+ }
+ setLastAction("goalUnarchived");
+ } else {
+ return;
+ }
+ window.history.go(confirmationAction ? -2 : -1);
+ };
+
+ const openConfirmationPopUp = async (action: confirmAction) => {
+ const { actionCategory, actionName } = action;
+ if (actionCategory === "collaboration" && showConfirmation.collaboration[actionName]) {
+ handleConfirmation();
+ setConfirmationAction({ ...action });
+ } else if (actionCategory === "goal" && showConfirmation.goal[action.actionName]) {
+ handleConfirmation();
+ setConfirmationAction({ ...action });
+ } else {
+ await handleActionClick(actionName);
+ }
+ };
+
+ return (
+ window.history.back()} type="interactables-modal">
+ {
+ handleUpdateGoal(goal.id, !!goal.timeBudget?.perDay);
+ }}
+ >
+
+ {t(`${goal.title}`)}
+
+
+
+ {confirmationAction &&
}
+
+
{
+ e.stopPropagation();
+ await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "restore" });
+ }}
+ >
+
+ }
+ />
+
+ {!isPartnerGoal && (
+
{
+ e.stopPropagation();
+ await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "delete" });
+ }}
+ >
+
+
+ )}
+
+
+ );
+};
+
+export default AccordionActions;
diff --git a/src/components/GoalsComponents/MyGoalActions/MyGoalActions.tsx b/src/components/GoalsComponents/MyGoalActions/MyGoalActions.tsx
deleted file mode 100644
index 30b9b90ab..000000000
--- a/src/components/GoalsComponents/MyGoalActions/MyGoalActions.tsx
+++ /dev/null
@@ -1,184 +0,0 @@
-import React, { useState } from "react";
-import { useTranslation } from "react-i18next";
-import { useRecoilValue, useSetRecoilState } from "recoil";
-import { useLocation, useNavigate } from "react-router-dom";
-
-import useGoalStore from "@src/hooks/useGoalStore";
-import ConfirmationModal from "@src/common/ConfirmationModal";
-import { unarchiveUserGoal } from "@src/api/GoalsAPI";
-import { unarchiveIcon } from "@src/assets";
-import ZModal from "@src/common/ZModal";
-
-import {
- displayToast,
- lastAction,
- openDevMode,
- displayConfirmation,
- displayPartnerMode,
- darkModeState,
-} from "@src/store";
-import { GoalItem } from "@src/models/GoalItem";
-import { goalsHistory } from "@src/store/GoalsState";
-import { confirmAction } from "@src/Interfaces/IPopupModals";
-import { convertSharedWMGoalToColab } from "@src/api/SharedWMAPI";
-import { archiveThisGoal, removeThisGoal } from "@src/helpers/GoalActionHelper";
-
-import ActionDiv from "./ActionDiv";
-import "./MyGoalActions.scss";
-
-const MyGoalActions = ({ goal, open }: { open: boolean; goal: GoalItem }) => {
- const { t } = useTranslation();
- const { handleUpdateGoal, handleShareGoal, handleConfirmation } = useGoalStore();
- const confirmActionCategory = goal.typeOfGoal === "shared" && goal.parentGoalId === "root" ? "collaboration" : "goal";
-
- const subGoalsHistory = useRecoilValue(goalsHistory);
- const showConfirmation = useRecoilValue(displayConfirmation);
- const isPartnerGoal = useRecoilValue(displayPartnerMode);
- const setDevMode = useSetRecoilState(openDevMode);
- const setShowToast = useSetRecoilState(displayToast);
- const darkModeStatus = useRecoilValue(darkModeState);
- const setLastAction = useSetRecoilState(lastAction);
- const ancestors = subGoalsHistory.map((ele) => ele.goalID);
-
- const [confirmationAction, setConfirmationAction] = useState(null);
-
- const handleActionClick = async (action: string) => {
- if (action === "delete") {
- if (goal.title === "magic") {
- setDevMode(false);
- }
- await removeThisGoal(goal, ancestors, isPartnerGoal);
- setLastAction("goalDeleted");
- } else if (action === "archive") {
- await archiveThisGoal(goal, ancestors);
- setLastAction("goalArchived");
- } else if (action === "restore") {
- await unarchiveUserGoal(goal);
- setLastAction("goalUnarchived");
- } else if (action === "colabRequest") {
- await convertSharedWMGoalToColab(goal);
- window.history.back();
- } else {
- return;
- }
- window.history.go(confirmationAction ? -2 : -1);
- };
-
- const openConfirmationPopUp = async (action: confirmAction) => {
- const { actionCategory, actionName } = action;
- if (actionCategory === "collaboration" && showConfirmation.collaboration[actionName]) {
- handleConfirmation();
- setConfirmationAction({ ...action });
- } else if (actionCategory === "goal" && showConfirmation.goal[action.actionName]) {
- handleConfirmation();
- setConfirmationAction({ ...action });
- } else {
- await handleActionClick(actionName);
- }
- };
-
- const isGoalArchived = goal.archived;
-
- return (
- window.history.back()} type="interactables-modal">
- {
- handleUpdateGoal(goal.id, !!goal.timeBudget?.perDay);
- }}
- >
-
- {t(`${goal.title}`)}
-
-
-
- {confirmationAction &&
}
- {isGoalArchived === "true" ? (
- <>
-
{
- e.stopPropagation();
- await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "restore" });
- }}
- >
-
- }
- />
-
- {!isPartnerGoal && (
-
{
- e.stopPropagation();
- await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "delete" });
- }}
- >
-
-
- )}
- >
- ) : (
- <>
-
{
- e.stopPropagation();
- await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "delete" });
- }}
- >
-
-
- {!isPartnerGoal && (
-
{
- e.stopPropagation();
- await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "archive" });
- }}
- >
-
-
- )}
- {((isPartnerGoal && goal.parentGoalId === "root") || !isPartnerGoal) && (
-
{
- e.stopPropagation();
- if (!isPartnerGoal) {
- handleShareGoal(goal);
- } else {
- await openConfirmationPopUp({ actionCategory: "collaboration", actionName: "colabRequest" });
- }
- }}
- >
-
-
- )}
-
{
- handleUpdateGoal(goal.id, !!goal.timeBudget?.perDay);
- }}
- >
-
-
- >
- )}
-
-
- );
-};
-
-export default MyGoalActions;
diff --git a/src/components/GoalsComponents/MyGoalActions/RegularGoalActions.tsx b/src/components/GoalsComponents/MyGoalActions/RegularGoalActions.tsx
new file mode 100755
index 000000000..a195022b1
--- /dev/null
+++ b/src/components/GoalsComponents/MyGoalActions/RegularGoalActions.tsx
@@ -0,0 +1,131 @@
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useRecoilValue, useSetRecoilState } from "recoil";
+
+import useGoalStore from "@src/hooks/useGoalStore";
+import ConfirmationModal from "@src/common/ConfirmationModal";
+import ZModal from "@src/common/ZModal";
+
+import { lastAction, openDevMode, displayConfirmation, displayPartnerMode } from "@src/store";
+import { GoalItem } from "@src/models/GoalItem";
+import { goalsHistory } from "@src/store/GoalsState";
+import { confirmAction } from "@src/Interfaces/IPopupModals";
+import { convertSharedWMGoalToColab } from "@src/api/SharedWMAPI";
+import { archiveThisGoal, removeThisGoal } from "@src/helpers/GoalActionHelper";
+
+import ActionDiv from "./ActionDiv";
+import "./MyGoalActions.scss";
+
+const RegularGoalActions = ({ goal, open }: { open: boolean; goal: GoalItem }) => {
+ const { t } = useTranslation();
+ const { handleUpdateGoal, handleShareGoal, handleConfirmation } = useGoalStore();
+ const confirmActionCategory = goal.typeOfGoal === "shared" && goal.parentGoalId === "root" ? "collaboration" : "goal";
+
+ const subGoalsHistory = useRecoilValue(goalsHistory);
+ const showConfirmation = useRecoilValue(displayConfirmation);
+ const isPartnerGoal = useRecoilValue(displayPartnerMode);
+ const setDevMode = useSetRecoilState(openDevMode);
+ const setLastAction = useSetRecoilState(lastAction);
+ const ancestors = subGoalsHistory.map((ele) => ele.goalID);
+
+ const [confirmationAction, setConfirmationAction] = useState(null);
+
+ const handleActionClick = async (action: string) => {
+ if (action === "delete") {
+ if (goal.title === "magic") {
+ setDevMode(false);
+ }
+ await removeThisGoal(goal, ancestors, isPartnerGoal);
+ setLastAction("goalDeleted");
+ } else if (action === "archive") {
+ await archiveThisGoal(goal, ancestors);
+ setLastAction("goalArchived");
+ } else if (action === "colabRequest") {
+ await convertSharedWMGoalToColab(goal);
+ window.history.back();
+ } else {
+ return;
+ }
+ window.history.go(confirmationAction ? -2 : -1);
+ };
+
+ const openConfirmationPopUp = async (action: confirmAction) => {
+ const { actionCategory, actionName } = action;
+ if (actionCategory === "collaboration" && showConfirmation.collaboration[actionName]) {
+ handleConfirmation();
+ setConfirmationAction({ ...action });
+ } else if (actionCategory === "goal" && showConfirmation.goal[action.actionName]) {
+ handleConfirmation();
+ setConfirmationAction({ ...action });
+ } else {
+ await handleActionClick(actionName);
+ }
+ };
+
+ return (
+ window.history.back()} type="interactables-modal">
+ {
+ handleUpdateGoal(goal.id, !!goal.timeBudget?.perDay);
+ }}
+ >
+
+ {t(`${goal.title}`)}
+
+
+
+ {confirmationAction &&
}
+
{
+ e.stopPropagation();
+ await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "delete" });
+ }}
+ >
+
+
+ {!isPartnerGoal && (
+
{
+ e.stopPropagation();
+ await openConfirmationPopUp({ actionCategory: confirmActionCategory, actionName: "archive" });
+ }}
+ >
+
+
+ )}
+ {((isPartnerGoal && goal.parentGoalId === "root") || !isPartnerGoal) && (
+
{
+ e.stopPropagation();
+ if (!isPartnerGoal) {
+ handleShareGoal(goal);
+ } else {
+ await openConfirmationPopUp({ actionCategory: "collaboration", actionName: "colabRequest" });
+ }
+ }}
+ >
+
+
+ )}
+
{
+ handleUpdateGoal(goal.id, !!goal.timeBudget?.perDay);
+ }}
+ >
+
+
+
+
+ );
+};
+
+export default RegularGoalActions;
diff --git a/src/helpers/GoalController.ts b/src/helpers/GoalController.ts
index b9d5e5eaa..452a4c832 100644
--- a/src/helpers/GoalController.ts
+++ b/src/helpers/GoalController.ts
@@ -12,6 +12,7 @@ import {
} from "@src/api/GoalsAPI";
import { createGoalObjectFromTags } from "./GoalProcessor";
import { sendFinalUpdateOnGoal, sendUpdatedGoal } from "./PubSubController";
+import { restoreUserGoal } from "@src/api/TrashAPI";
export const createGoal = async (
parentGoalId: string,
@@ -82,12 +83,19 @@ export const archiveGoal = async (goal: GoalItem, ancestors: string[]) => {
};
export const deleteGoal = async (goal: GoalItem, ancestors: string[]) => {
- sendFinalUpdateOnGoal(goal.id, "deleted", ancestors, false).then(() => {
+ sendFinalUpdateOnGoal(goal.id, "deleted", [...ancestors, goal.id], false).then(() => {
console.log("Update Sent");
});
await removeGoalWithChildrens(goal);
};
+export const restoreGoal = async (goal: GoalItem, ancestors: string[]) => {
+ sendFinalUpdateOnGoal(goal.id, "restored", [...ancestors, goal.id], false).then(() => {
+ console.log("Update Sent");
+ });
+ await restoreUserGoal(goal);
+};
+
export const deleteSharedGoal = async (goal: GoalItem) => {
await removeSharedWMChildrenGoals(goal.id);
if (goal.parentGoalId !== "root") {
diff --git a/src/helpers/GoalProcessor.ts b/src/helpers/GoalProcessor.ts
index c5352ac56..658d0fec9 100644
--- a/src/helpers/GoalProcessor.ts
+++ b/src/helpers/GoalProcessor.ts
@@ -126,6 +126,8 @@ export const getTypeAtPriority = (goalChanges: IChangesInGoal) => {
typeAtPriority = "archived";
} else if (goalChanges.deleted.length > 0) {
typeAtPriority = "deleted";
+ } else if (goalChanges.restored.length > 0) {
+ typeAtPriority = "restored";
}
return { typeAtPriority };
};
diff --git a/src/helpers/InboxProcessor.ts b/src/helpers/InboxProcessor.ts
index ba2bbee68..5cbfff889 100644
--- a/src/helpers/InboxProcessor.ts
+++ b/src/helpers/InboxProcessor.ts
@@ -20,6 +20,7 @@ import {
} from "@src/api/SharedWMAPI";
import { ITagChangesSchemaVersion, ITagsChanges } from "@src/Interfaces/IDisplayChangesModal";
import { fixDateVlauesInGoalObject } from "@src/utils";
+import { getDeletedGoal, restoreUserGoal } from "@src/api/TrashAPI";
export const handleIncomingChanges = async (payload, relId) => {
if (payload.type === "sharer" && (await getSharedWMGoal(payload.rootGoalId))) {
@@ -39,24 +40,28 @@ export const handleIncomingChanges = async (payload, relId) => {
];
await updateSharedWMGoal(changes[0].goal.id, changes[0].goal);
} else if (payload.changeType === "deleted") {
- await removeSharedWMChildrenGoals(payload.changes[0].id);
- await removeSharedWMGoal(payload.changes[0].id);
- getSharedWMGoal(payload.changes[0].id).then((goal: GoalItem) => {
- if (goal.parentGoalId !== "root") {
- getSharedWMGoal(goal.parentGoalId).then(async (parentGoal: GoalItem) => {
- const parentGoalSublist = parentGoal.sublist;
- const childGoalIndex = parentGoalSublist.indexOf(goal.id);
- if (childGoalIndex !== -1) {
- parentGoalSublist.splice(childGoalIndex, 1);
- }
- await updateSharedWMGoal(parentGoal.id, { sublist: parentGoalSublist });
- });
- }
- });
+ const goalToBeDeleted = await getSharedWMGoal(payload.changes[0].id);
+ await removeSharedWMChildrenGoals(goalToBeDeleted.id);
+ await removeSharedWMGoal(goalToBeDeleted);
+ if (goalToBeDeleted.parentGoalId !== "root") {
+ getSharedWMGoal(goalToBeDeleted.parentGoalId).then(async (parentGoal: GoalItem) => {
+ const parentGoalSublist = parentGoal.sublist;
+ const childGoalIndex = parentGoalSublist.indexOf(goalToBeDeleted.id);
+ if (childGoalIndex !== -1) {
+ parentGoalSublist.splice(childGoalIndex, 1);
+ }
+ await updateSharedWMGoal(parentGoal.id, { sublist: parentGoalSublist });
+ });
+ }
} else if (payload.changeType === "archived") {
getSharedWMGoal(payload.changes[0].id).then(async (goal: GoalItem) =>
archiveSharedWMGoal(goal).catch((err) => console.log(err, "failed to archive")),
);
+ } else if (payload.changeType === "restored") {
+ const goalToBeRestored = await getDeletedGoal(payload.changes[0].id);
+ if (goalToBeRestored) {
+ await restoreUserGoal(goalToBeRestored, true);
+ }
}
} else if (["sharer", "suggestion"].includes(payload.type)) {
const { rootGoalId, changes, changeType } = payload;
diff --git a/src/helpers/PubSubController.ts b/src/helpers/PubSubController.ts
index a3b4d3d5a..cf63ee0d1 100644
--- a/src/helpers/PubSubController.ts
+++ b/src/helpers/PubSubController.ts
@@ -2,6 +2,7 @@
import { sendUpdatesToSubscriber } from "@src/services/contact.service";
import { getGoal, getParticipantsOfGoals } from "@src/api/GoalsAPI";
import { getHistoryUptoGoal } from "./GoalProcessor";
+import { getParticipantsOfDeletedGoal } from "@src/api/TrashAPI";
export const sendUpdatedGoal = async (
goalId: string,
@@ -29,13 +30,18 @@ export const sendUpdatedGoal = async (
export const sendFinalUpdateOnGoal = async (
goalId: string,
- action: "archived" | "deleted",
+ action: "archived" | "deleted" | "restored",
ancestors: string[] = [],
redefineAncestors = true,
excludeSubs: string[] = [],
) => {
const ancestorGoalIds = redefineAncestors ? (await getHistoryUptoGoal(goalId)).map((ele) => ele.goalID) : ancestors;
const subscribers = await getParticipantsOfGoals(ancestorGoalIds);
+ if (action === "restored") {
+ (await getParticipantsOfDeletedGoal(goalId)).forEach((doc) => {
+ subscribers.push(doc);
+ });
+ }
subscribers
.filter((ele) => !excludeSubs.includes(ele.sub.relId))
.forEach(async ({ sub, rootGoalId }) => {
diff --git a/src/models/InboxItem.ts b/src/models/InboxItem.ts
index 102e6a101..d8e1358be 100644
--- a/src/models/InboxItem.ts
+++ b/src/models/InboxItem.ts
@@ -1,6 +1,6 @@
import { GoalItem } from "./GoalItem";
-export type typeOfChange = "subgoals" | "modifiedGoals" | "archived" | "deleted";
+export type typeOfChange = "subgoals" | "modifiedGoals" | "archived" | "deleted" | "restored";
export type typeOfIntent = "suggestion" | "shared";
export type changesInId = { level: number; id: string; intent: typeOfIntent };
@@ -11,6 +11,7 @@ export interface IChangesInGoal {
modifiedGoals: changesInGoal[];
archived: changesInId[];
deleted: changesInId[];
+ restored: changesInId[];
}
export interface InboxItem {
diff --git a/src/models/TrashItem.ts b/src/models/TrashItem.ts
new file mode 100755
index 000000000..7547b7fb2
--- /dev/null
+++ b/src/models/TrashItem.ts
@@ -0,0 +1,5 @@
+import { GoalItem } from "./GoalItem";
+
+export interface TrashItem extends GoalItem {
+ deletedAt: String;
+}
diff --git a/src/models/db.ts b/src/models/db.ts
old mode 100644
new mode 100755
index b23abaeca..04426b2dd
--- a/src/models/db.ts
+++ b/src/models/db.ts
@@ -7,6 +7,7 @@ import { InboxItem } from "./InboxItem";
import { TaskItem } from "./TaskItem";
import { GCustomItem } from "./GCustomItem";
import { DumpboxItem } from "./DumpboxItem";
+import { TrashItem } from "./TrashItem";
export const dexieVersion = 17;
@@ -30,6 +31,8 @@ export class ZinZenDB extends Dexie {
dumpboxCollection!: Table;
+ goalTrashCollection!: Table;
+
constructor() {
super("ZinZenDB");
this.version(dexieVersion)
@@ -49,6 +52,8 @@ export class ZinZenDB extends Dexie {
customizationCollection: "++id, goalId, posIndex",
dumpboxCollection: "id, key, value",
partnersCollection: null,
+ goalTrashCollection:
+ "id, deletedAt, title, duration, sublist, habit, on, start, due, afterTime, beforeTime, createdAt, parentGoalId, archived, participants, goalColor, language, link, rootGoalId, timeBudget, typeOfGoal",
})
.upgrade((trans) => {
console.log("🚀 ~ file: db.ts:63 ~ ZinZenDB ~ .upgrade ~ this.verno:", currentVersion);
diff --git a/src/pages/GoalsPage/MyGoals.tsx b/src/pages/GoalsPage/MyGoals.tsx
old mode 100644
new mode 100755
index fc218d954..848fc0ac2
--- a/src/pages/GoalsPage/MyGoals.tsx
+++ b/src/pages/GoalsPage/MyGoals.tsx
@@ -9,7 +9,6 @@ import ZinZenTextDark from "@assets/images/LogoTextDark.svg";
import {
displayAddGoal,
displayChangesModal,
- displayGoalActions,
displayGoalId,
displayShareModal,
displaySuggestionsModal,
@@ -24,15 +23,17 @@ import { darkModeState, lastAction, searchActive } from "@src/store";
import AppLayout from "@src/layouts/AppLayout";
import GoalsList from "@components/GoalsComponents/GoalsList";
import ConfigGoal from "@components/GoalsComponents/GoalConfigModal/ConfigGoal";
-import MyGoalActions from "@components/GoalsComponents/MyGoalActions/MyGoalActions";
import ShareGoalModal from "@components/GoalsComponents/ShareGoalModal/ShareGoalModal";
-import ArchivedAccordion from "@components/GoalsComponents/ArchivedAccordion";
+import GoalsAccordion from "@components/GoalsComponents/GoalsAccordion";
import DisplayChangesModal from "@components/GoalsComponents/DisplayChangesModal/DisplayChangesModal";
+import { TrashItem } from "@src/models/TrashItem";
+import { getDeletedGoals } from "@src/api/TrashAPI";
export const MyGoals = () => {
let debounceTimeout: ReturnType;
const [activeGoals, setActiveGoals] = useState([]);
const [archivedGoals, setArchivedGoals] = useState([]);
+ const [deletedGoals, setDeletedGoals] = useState([]);
const [showActions, setShowActions] = useState({ open: "root", click: 1 });
const showAddGoal = useRecoilValue(displayAddGoal);
@@ -41,23 +42,31 @@ export const MyGoals = () => {
const darkModeStatus = useRecoilValue(darkModeState);
const showShareModal = useRecoilValue(displayShareModal);
const showUpdateGoal = useRecoilValue(displayUpdateGoal);
- const showGoalActions = useRecoilValue(displayGoalActions);
const showChangesModal = useRecoilValue(displayChangesModal);
const showSuggestionModal = useRecoilValue(displaySuggestionsModal);
const [action, setLastAction] = useRecoilState(lastAction);
- const handleUserGoals = (goals: GoalItem[]) => {
+ const getAllGoals = async () => {
+ const [goals, delGoals] = await Promise.all([getActiveGoals("true"), getDeletedGoals("root")]);
+ console.log("🚀 ~ getAllGoals ~ goals, delGoals:", goals, delGoals);
+ return { goals, delGoals };
+ };
+ const handleUserGoals = (goals: GoalItem[], delGoals: TrashItem[]) => {
+ setDeletedGoals([...delGoals.map(({ deletedAt, ...goal }) => goal)]);
setActiveGoals([...goals.filter((goal) => goal.archived === "false")]);
setArchivedGoals([...goals.filter((goal) => goal.archived === "true" && goal.typeOfGoal === "myGoal")]);
};
const refreshActiveGoals = async () => {
- const goals: GoalItem[] = await getActiveGoals("true");
- handleUserGoals(goals);
+ const { goals, delGoals } = await getAllGoals();
+ handleUserGoals(goals, delGoals);
};
const search = async (text: string) => {
- const goals: GoalItem[] = await getActiveGoals("true");
- handleUserGoals(goals.filter((goal) => goal.title.toUpperCase().includes(text.toUpperCase())));
+ const { goals, delGoals } = await getAllGoals();
+ handleUserGoals(
+ goals.filter((goal) => goal.title.toUpperCase().includes(text.toUpperCase())),
+ delGoals.filter(({ deletedAt, ...goal }) => goal.title.toUpperCase().includes(text.toUpperCase())),
+ );
};
const debounceSearch = (event: ChangeEvent) => {
if (debounceTimeout) {
@@ -88,7 +97,6 @@ export const MyGoals = () => {
return (
{showShareModal && }
- {showGoalActions && }
{showChangesModal && }
{selectedGoalId === "root" ? (
@@ -104,8 +112,17 @@ export const MyGoals = () => {
/>
{archivedGoals.length > 0 && (
-
+ )}
+ {deletedGoals.length > 0 && (
+
diff --git a/src/pages/GoalsPage/PartnerGoals.tsx b/src/pages/GoalsPage/PartnerGoals.tsx
old mode 100644
new mode 100755
index 213acaca6..14c3b386c
--- a/src/pages/GoalsPage/PartnerGoals.tsx
+++ b/src/pages/GoalsPage/PartnerGoals.tsx
@@ -11,13 +11,13 @@ import { GoalSublist } from "@components/GoalsComponents/GoalSublist/GoalSublist
import { displayGoalActions, displayGoalId } from "@src/store/GoalsState";
import { darkModeState, lastAction, searchActive } from "@src/store";
-import ArchivedAccordion from "@components/GoalsComponents/ArchivedAccordion";
-import GoalLocStateHandler from "@src/helpers/GoalLocStateHandler";
-import AppLayout from "@src/layouts/AppLayout";
import GoalsList from "@components/GoalsComponents/GoalsList";
-import MyGoalActions from "@components/GoalsComponents/MyGoalActions/MyGoalActions";
+import AppLayout from "@src/layouts/AppLayout";
import ContactItem from "@src/models/ContactItem";
+import GoalsAccordion from "@components/GoalsComponents/GoalsAccordion";
+import GoalLocStateHandler from "@src/helpers/GoalLocStateHandler";
import { getRootGoalsOfPartner } from "@src/api/SharedWMAPI";
+import RegularGoalActions from "@components/GoalsComponents/MyGoalActions/RegularGoalActions";
import InvitationStatus from "./InvitationStatus";
@@ -76,7 +76,7 @@ const PartnerGoals = ({ partner }: { partner: ContactItem }) => {
return (
- {showGoalActions && }
+ {showGoalActions && }
{selectedGoalId === "root" ? (
@@ -89,8 +89,9 @@ const PartnerGoals = ({ partner }: { partner: ContactItem }) => {
setGoals={setActiveGoals}
/>
-
diff --git a/src/store/GoalsState.ts b/src/store/GoalsState.ts
index b42e48ef9..998842067 100644
--- a/src/store/GoalsState.ts
+++ b/src/store/GoalsState.ts
@@ -9,9 +9,12 @@ export interface ISubGoalHistory {
goalTitle: string;
}
+export type TAction = "deleted" | "archived" | "regular";
+export type TDisplayGoalActions = { actionType: TAction; goal: GoalItem };
+
export const displayGoalActions = atom({
key: "displayGoalActions",
- default: null as GoalItem | null,
+ default: null as TDisplayGoalActions | null,
});
export const displayGoalConfigModal = atom({
diff --git a/src/store/index.ts b/src/store/index.ts
old mode 100644
new mode 100755
index 11c315373..360cc01c2
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -3,26 +3,38 @@ import { confirmActionState } from "@src/Interfaces/IPopupModals";
import ContactItem from "@src/models/ContactItem";
import { darkModeState } from "./DarkModeState";
import { languageSelectionState } from "./LanguageSelectionState";
+import { isJSONParsable } from "@src/utils/patterns";
+
+const defaultConfirmationObj: confirmActionState = {
+ open: false,
+ goal: {
+ archive: true,
+ delete: true,
+ shareAnonymously: true,
+ shareWithOne: true,
+ restore: true,
+ },
+ collaboration: {
+ colabRequest: true,
+ delete: true,
+ archive: true,
+ restore: true,
+ },
+};
+
+if (isJSONParsable(localStorage.getItem("confirmationState"))) {
+ //@ts-ignore
+ const savedConfirmationState = JSON.parse(localStorage.getItem("confirmationService"));
+ defaultConfirmationObj.goal = { ...defaultConfirmationObj.goal, ...(savedConfirmationState?.goal || {}) };
+ defaultConfirmationObj.collaboration = {
+ ...defaultConfirmationObj.collaboration,
+ ...(savedConfirmationState?.collaboration || {}),
+ };
+}
export const displayConfirmation = atom({
key: "displayConfirmation",
- default: JSON.parse(
- localStorage.getItem("confirmationState") ||
- JSON.stringify({
- open: false,
- goal: {
- archive: true,
- delete: true,
- shareAnonymously: true,
- shareWithOne: true,
- },
- collaboration: {
- colabRequest: true,
- delete: true,
- archive: true,
- },
- }),
- ) as confirmActionState,
+ default: defaultConfirmationObj,
});
export const lastAction = atom({
diff --git a/src/utils/defaultGenerators.ts b/src/utils/defaultGenerators.ts
index eb0f6b553..4d71305e7 100644
--- a/src/utils/defaultGenerators.ts
+++ b/src/utils/defaultGenerators.ts
@@ -27,5 +27,6 @@ export function getDefaultValueOfGoalChanges() {
modifiedGoals: [],
archived: [],
deleted: [],
+ restored: [],
};
}
diff --git a/src/utils/patterns.ts b/src/utils/patterns.ts
old mode 100644
new mode 100755
index 4d1ec9b1e..cd93fc016
--- a/src/utils/patterns.ts
+++ b/src/utils/patterns.ts
@@ -34,3 +34,13 @@ export function summarizeUrl(url: string) {
}
return "";
}
+
+export function isJSONParsable(str: string | null | undefined): boolean {
+ if (!str) return false;
+ try {
+ JSON.parse(str);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}