diff --git a/gui/.eslintrc.js b/gui/.eslintrc.js index 5d055773a0..d425103613 100644 --- a/gui/.eslintrc.js +++ b/gui/.eslintrc.js @@ -19,7 +19,8 @@ module.exports = { ], plugins: [ "@typescript-eslint", - "react-hooks" + "react-hooks", + "eslint-plugin-tsdoc" ], parserOptions: { ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features @@ -33,7 +34,8 @@ module.exports = { "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks - "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies + "react-hooks/exhaustive-deps": "error", // Checks effect dependencies + "tsdoc/syntax": "off", // "warn" to check tsdoc syntax }, settings: { react: { diff --git a/gui/.gitignore b/gui/.gitignore index 87fd607e72..7c95102fad 100644 --- a/gui/.gitignore +++ b/gui/.gitignore @@ -15,6 +15,7 @@ # docs /generateddoc +/docs # misc .DS_Store diff --git a/gui/package-lock.json b/gui/package-lock.json index 0b3280377f..2f14eca554 100644 --- a/gui/package-lock.json +++ b/gui/package-lock.json @@ -62,6 +62,7 @@ "eslint": "^8.3.0", "eslint-plugin-react": "^7.26.1", "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-tsdoc": "^0.2.16", "eslint-webpack-plugin": "^3.1.0", "generate-json-webpack-plugin": "^2.0.0", "html-webpack-plugin": "^5.5.0", @@ -73,6 +74,8 @@ "mock-socket": "^9.0.7", "ts-jest": "^28.0.5", "ts-loader": "^9.2.6", + "typedoc": "^0.23.11", + "typedoc-plugin-markdown": "^3.13.4", "typescript": "^4.4.4", "webpack": "^5.61.0", "webpack-cli": "^4.9.1" @@ -1783,6 +1786,37 @@ "node": ">=6.0.0" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.1.tgz", + "integrity": "sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.1.tgz", + "integrity": "sha512-2RqkwiD4uN6MLnHFljqBlZIXlt/SaUT6cuogU1w2ARw4nKuuppSmR0+s+NC+7kXBQykd9zzu0P4HtBpZT5zBpQ==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.1", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@mui/base": { "version": "5.0.0-alpha.94", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.94.tgz", @@ -5711,6 +5745,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.16.tgz", + "integrity": "sha512-F/RWMnyDQuGlg82vQEFHQtGyWi7++XJKdYNn0ulIbyMOFqYIjoJOUdE6olORxgwgLkpJxsCJpJbTHgxJ/ggfXw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.1", + "@microsoft/tsdoc-config": "0.16.1" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -6760,6 +6804,36 @@ "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -9471,6 +9545,12 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9581,6 +9661,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsx-ast-utils": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", @@ -10118,6 +10204,12 @@ "node": ">=10" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/lz-string": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", @@ -10206,6 +10298,18 @@ "node": ">=6.4.0" } }, + "node_modules/marked": { + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz", + "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/math-log2": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-log2/-/math-log2-1.0.1.tgz", @@ -12056,6 +12160,17 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", + "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "^6.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -13239,6 +13354,60 @@ "dup": "^1.0.0" } }, + "node_modules/typedoc": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.11.tgz", + "integrity": "sha512-FhZ2HfqlS++53UwHk4txCsTrTlpYR0So/0osMyBeP1E7llRNRqycJGfYK1qx9Wvvv5VO8tGdpwzOwDW5FrTi7A==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.0.19", + "minimatch": "^5.1.0", + "shiki": "^0.11.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.13.4.tgz", + "integrity": "sha512-E/EBBmu6ARtnbswZGtBVBB/BfukZiGMOlqPc0RXCI/NFitONBahFqbCAF5fKQlijlcfipJj5pw5AMFH3NytrAw==", + "dev": true, + "dependencies": { + "handlebars": "^4.7.7" + }, + "peerDependencies": { + "typedoc": ">=0.23.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typescript": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", @@ -13260,6 +13429,19 @@ "node": ">=8" } }, + "node_modules/uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -13488,6 +13670,18 @@ "resolved": "https://registry.npmjs.org/validate.io-string-primitive/-/validate.io-string-primitive-1.0.1.tgz", "integrity": "sha512-TORbkLMdOFkEbPtfdx76FSVQGSAzyUEMxI+pBq5pfFm1ZzIesP+XiGc6eIK75aKu7RA7a8EcqUv5OrY5wfog5w==" }, + "node_modules/vscode-oniguruma": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", + "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", + "dev": true + }, "node_modules/vt-pbf": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", @@ -13803,6 +13997,12 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", @@ -15354,6 +15554,36 @@ "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==" }, + "@microsoft/tsdoc": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.1.tgz", + "integrity": "sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.1.tgz", + "integrity": "sha512-2RqkwiD4uN6MLnHFljqBlZIXlt/SaUT6cuogU1w2ARw4nKuuppSmR0+s+NC+7kXBQykd9zzu0P4HtBpZT5zBpQ==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.1", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + }, + "dependencies": { + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, "@mui/base": { "version": "5.0.0-alpha.94", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.94.tgz", @@ -18422,6 +18652,16 @@ "dev": true, "requires": {} }, + "eslint-plugin-tsdoc": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.16.tgz", + "integrity": "sha512-F/RWMnyDQuGlg82vQEFHQtGyWi7++XJKdYNn0ulIbyMOFqYIjoJOUdE6olORxgwgLkpJxsCJpJbTHgxJ/ggfXw==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.14.1", + "@microsoft/tsdoc-config": "0.16.1" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -19179,6 +19419,27 @@ "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -21146,6 +21407,12 @@ } } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -21227,6 +21494,12 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "jsx-ast-utils": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", @@ -21612,6 +21885,12 @@ "yallist": "^4.0.0" } }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "lz-string": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", @@ -21690,6 +21969,12 @@ "vt-pbf": "^3.1.1" } }, + "marked": { + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz", + "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==", + "dev": true + }, "math-log2": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-log2/-/math-log2-1.0.1.tgz", @@ -23117,6 +23402,17 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shiki": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", + "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "^6.0.0" + } + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -24017,6 +24313,47 @@ "dup": "^1.0.0" } }, + "typedoc": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.11.tgz", + "integrity": "sha512-FhZ2HfqlS++53UwHk4txCsTrTlpYR0So/0osMyBeP1E7llRNRqycJGfYK1qx9Wvvv5VO8tGdpwzOwDW5FrTi7A==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.0.19", + "minimatch": "^5.1.0", + "shiki": "^0.11.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typedoc-plugin-markdown": { + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.13.4.tgz", + "integrity": "sha512-E/EBBmu6ARtnbswZGtBVBB/BfukZiGMOlqPc0RXCI/NFitONBahFqbCAF5fKQlijlcfipJj5pw5AMFH3NytrAw==", + "dev": true, + "requires": { + "handlebars": "^4.7.7" + } + }, "typescript": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", @@ -24028,6 +24365,13 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" }, + "uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==", + "dev": true, + "optional": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -24231,6 +24575,18 @@ "resolved": "https://registry.npmjs.org/validate.io-string-primitive/-/validate.io-string-primitive-1.0.1.tgz", "integrity": "sha512-TORbkLMdOFkEbPtfdx76FSVQGSAzyUEMxI+pBq5pfFm1ZzIesP+XiGc6eIK75aKu7RA7a8EcqUv5OrY5wfog5w==" }, + "vscode-oniguruma": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "dev": true + }, + "vscode-textmate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", + "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", + "dev": true + }, "vt-pbf": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", @@ -24461,6 +24817,12 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, "wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", diff --git a/gui/package.json b/gui/package.json index 40ab670c87..bc3a528ef5 100644 --- a/gui/package.json +++ b/gui/package.json @@ -41,7 +41,9 @@ "lint": "eslint --ext .ts,.tsx", "lint:fix": "npm run lint -- --fix", "coverage": "npm test -- --coverage", - "types": "dts-bundle-generator -o packaging/taipy-gui.gen.d.ts src/extensions/exports.ts" + "types": "dts-bundle-generator -o packaging/taipy-gui.gen.d.ts src/extensions/exports.ts", + "doc": "typedoc --plugin typedoc-plugin-markdown --excludeNotDocumented --disableSources src/extensions/exports.ts", + "doc.json": "typedoc --json docs/taipy-gui.json src/extensions/exports.ts" }, "husky": { "hooks": { @@ -93,6 +95,7 @@ "eslint": "^8.3.0", "eslint-plugin-react": "^7.26.1", "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-tsdoc": "^0.2.16", "eslint-webpack-plugin": "^3.1.0", "generate-json-webpack-plugin": "^2.0.0", "html-webpack-plugin": "^5.5.0", @@ -104,6 +107,8 @@ "mock-socket": "^9.0.7", "ts-jest": "^28.0.5", "ts-loader": "^9.2.6", + "typedoc": "^0.23.11", + "typedoc-plugin-markdown": "^3.13.4", "typescript": "^4.4.4", "webpack": "^5.61.0", "webpack-cli": "^4.9.1" diff --git a/gui/packaging/taipy-gui.d.ts b/gui/packaging/taipy-gui.d.ts index c10a5dbbcd..a6b2a7f96a 100644 --- a/gui/packaging/taipy-gui.d.ts +++ b/gui/packaging/taipy-gui.d.ts @@ -11,66 +11,172 @@ * specific language governing permissions and limitations under the License. */ -export interface TaipyState { -} -export interface TaipyBaseAction { -} -export interface TaipyStore { - state: TaipyState; - dispatch: import("react").Dispatch; -} -export declare const TaipyContext: import("react").Context; - -// utils -export declare const useDynamicProperty: (value: T, defaultValue: T, defaultStatic: T) => T; - -// Reducers -export declare const createSendActionNameAction: (name: string | undefined, value: unknown, ...args: unknown[]) => TaipyBaseAction; -export declare const createSendUpdateAction: (name: string | undefined, value: unknown, onChange?: string, propagate?: boolean, relName?: string) => TaipyBaseAction; -export declare const createRequestDataUpdateAction: (name: string | undefined, id: string | undefined, columns: string[], pageKey: string, payload: Record, allData?: boolean, library?: string) => TaipyBaseAction; - +/** + * This extracts the backend name of a given property identified by `name`. + * @param {string} updateVars - The value held by the property `updateVars`. + * @param {string} name - The name of a bound property. + * @returns {string | undefined} The backend generated variable name. + */ +export declare const getUpdateVar: (updateVars: string, name: string) => string | undefined; -//Comps export declare const Router: () => JSX.Element; -//lov -export declare type LoVElt = [ - string, - stringIcon, - LoVElt[]? -]; -export declare type LoV = LoVElt[]; +/** + * An Icon representation. + */ export interface Icon { + /** {string} The URL to the image. */ path: string; + /** {string} The text. */ text: string; } +/** + * A String or icon. + */ export declare type stringIcon = string | Icon; +/** + * An item of lov. + */ export interface LovItem { + /** {string} The unique identifier. */ id: string; + /** {StringIcon} The label (string and/or icon). */ item: stringIcon; + /** {LovItem[] | undefined} The optional array of children. */ children?: LovItem[]; } -export declare const getUpdateVar: (updateVars: string, name: string) => string | undefined; +/** + * A lov element. + */ +export declare type LoVElt = [ + /** {string} The identifier. */ + string, + /** {stringIcon} The label. */ + stringIcon, + /** {LoVElt[] | undefined} The optional list of children. */ + LoVElt[]? +]; +/** + * The list of lov elements. + */ +export declare type LoV = LoVElt[]; +/** + * This React hook returns a lov list from the lov default value and the lov bound value. + * @param {LoV | undefined} lov - The bound lov value. + * @param {string} defaultLov - The json stringify default lov value. + * @param {boolean | undefined} [tree] - This flag indicates if the LoV list is a tree or a flat list (default is false). + * @returns {LovItem[]} A list of items. + */ export declare const useLovListMemo: (lov: LoV | undefined, defaultLov: string, tree?: boolean) => LovItem[]; -export declare const useDispatchRequestUpdateOnFirstRender: (dispatch: import("react").Dispatch, id?: string, updateVars?: string, varName?: string) => void; - - -// tabular data -export interface ColumnDesc { - dfid: string; - type: string; - format: string; - title?: string; - index: number; - width?: number | string; - notEditable?: boolean; - style?: string; - nanValue?: string; - tz?: string; - filter?: boolean; - apply?: string; - groupBy?: boolean; - widthHint?: number; +/** + * TaipyState The State of the Taipy Application. + */ + export interface TaipyState {} + /** + * TaipyAction The object used by the reducer. + */ +export interface TaipyAction { } -export declare type RowValue = string | number | null; -export declare type RowType = Record; +/** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will update the variable `name` (if `propagate` === true) and provoke the invocation of the on_change python function on the backend. + * @param {string | undefined} [name] - The name of the variable holding the requested data as received as a property (default is ""). + * @param {unknown} value - The new value for the variable named `name`. + * @param {string | undefined} onChange - The name of the on_change python function to invoke on the backend (default to "on_change" on the backend). + * @param {boolean | undefined} [propagate] - A flag indicating that the variable should be automatically updated on the backend (default is true). + * @param {string | undefined} [relName] - The name of the optional related variable (for example the lov when a lov value is updated). + * @returns {TaipyAction} The action fed to the reducer. + */ + export declare const createSendUpdateAction: (name: string | undefined, value: unknown, onChange?: string, propagate?: boolean, relName?: string) => TaipyAction; + /** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will provoke the invocation of an on_action python function on the backend with all parameters as a payload. + * @param {string | undefined} name - The name of the backend action. + * @param {unknown} value - The value associated with the action, this can be an object or any type of value. + * @param {unknown[]} args - Additional informations associated to the action. + * @returns {TaipyAction} The action fed to the reducer. + */ + export declare const createSendActionNameAction: (name: string | undefined, value: unknown, ...args: unknown[]) => TaipyAction; + /** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will provoke the invocation of the get_data python function on the backend that will generate an update of the elements holding data named `name` on the frontend. + * @param {string} name - The name of the variable holding the requested data as received as a property. + * @param {string | undefined} id - The id of the visual element. + * @param {string[]} columns - The list of the columns needed by the element emitting this action. + * @param {string} pageKey - The unique identifier to the data that will be received from this action. + * @param {Record} payload - The payload (specific to the type of component ie table, chart ...). + * @param {boolean | undefined} [allData] - The flag indicating if all the data is requested (default is false). + * @param {string | undefined} library - The optional name of the library {@link extension}. + * @returns {TaipyAction} The action fed to the reducer. + */ + export declare const createRequestDataUpdateAction: (name: string | undefined, id: string | undefined, columns: string[], pageKey: string, payload: Record, allData?: boolean, library?: string) => TaipyAction; + /** + * The Column description as received by the backend. + */ + export interface ColumnDesc { + /** {string} The unique column identifier. */ + dfid: string; + /** {string} The column type. */ + type: string; + /** {string} The optional value format. */ + format?: string; + /** {string | undefined} The optional column title. */ + title?: string; + /** {number} The order of the column. */ + index: number; + /** {number | string | undefined} The optional width. */ + width?: number | string; + /** {boolean | undefined} If set to true, the column should not be editable. */ + notEditable?: boolean; + /** {string | undefined} The optional column name that would hold the css classname to apply to the cell. */ + style?: string; + /** {string | undefined} The optional value that would replace a NaN value. */ + nanValue?: string; + /** {string | undefined} The optional TimeZone identifier used if the type is Date. */ + tz?: string; + /** {boolean | undefined} The flag that allows filtering. */ + filter?: boolean; + /** {string | undefined} The optional identifier for the aggregation function. */ + apply?: string; + /** {boolean | undefined} The optional flag that would allow the user to aggregate the column. */ + groupBy?: boolean; + widthHint?: number; + } + /** + * A cell value type. + */ + export declare type RowValue = string | number | boolean | null; + /** + * The row definition composed of a key/value string/`RowValue`. + */ + export declare type RowType = Record; + /** + * The Taipy Store. + */ + export interface TaipyStore { + /** {TaipyState} The State of the Taipy Application. */ + state: TaipyState; + /** {React.Dispatch} The react dispatch function. */ + dispatch: import("react").Dispatch; + } + /** + * {React.Context} Taipy specific react context. + */ + export declare const TaipyContext: import("react").Context; + /** + * This react hook helps manage a dynamic scalar property (defined by a default property and a bound property). + * @typeparam T - The dynamic property type. + * @param {T} value - The bound value + * @param {T} defaultValue - The default value + * @param {T} defaultStatic - The default static value + * @returns {T} The latest updated value. + */ + export declare const useDynamicProperty: (value: T, defaultValue: T, defaultStatic: T) => T; + /** + * This React hook requests an update for every dynamic property of the element. + * @param {React.Dispatch} dispatch - The react dispatcher associated to `TaipyContext`. + * @param {string | undefined} id - The optional id of the element. + * @param {string} updateVars - The content of the property `updateVars`. + * @param {string | undefined} varName - The default property backend provided variable (through property `updateVarName`). + */ + export declare const useDispatchRequestUpdateOnFirstRender: (dispatch: import("react").Dispatch, id?: string, updateVars?: string, varName?: string) => void; diff --git a/gui/public/favicon.ico b/gui/public/favicon.ico index f9eaccfdbc..674f9745fd 100644 Binary files a/gui/public/favicon.ico and b/gui/public/favicon.ico differ diff --git a/gui/public/favicon.png b/gui/public/favicon.png index 7cc0f7b093..b094841eda 100644 Binary files a/gui/public/favicon.png and b/gui/public/favicon.png differ diff --git a/gui/src/components/Taipy/lovUtils.tsx b/gui/src/components/Taipy/lovUtils.tsx index 173c773855..e5772ce916 100644 --- a/gui/src/components/Taipy/lovUtils.tsx +++ b/gui/src/components/Taipy/lovUtils.tsx @@ -41,8 +41,21 @@ export interface LovProps extends TaipyActive valueById?: boolean; } -type LoVElt = [string, stringIcon, LoVElt[]?]; +/** + * A lov element. + */ +type LoVElt = [ + /** {string} The identifier. */ + string, + /** {stringIcon} The label. */ + stringIcon, + /** {LoVElt[] | undefined} The optional list of children. */ + LoVElt[]? +]; +/** + * The list of lov elements. + */ export type LoV = LoVElt[]; const getLovItem = (elt: LoVElt | string, tree = false): LovItem => { @@ -62,6 +75,13 @@ export const boxSx = { width: "100%" } as CSSProperties; export const paperBaseSx = { width: "100%", mb: 2, display: "grid", gridTemplateRows: "auto 1fr" } as CSSProperties; export const treeSelBaseSx = { width: "100%", bgcolor: "background.paper", overflowY: "auto" } as CSSProperties; +/** + * This React hook returns a lov list from the lov default value and the lov bound value. + * @param {LoV | undefined} lov - The bound lov value. + * @param {string} defaultLov - The json stringify default lov value. + * @param {boolean | undefined} [tree] - This flag indicates if the LoV list is a tree or a flat list (default is false). + * @returns {LovItem[]} A list of items. + */ export const useLovListMemo = (lov: LoV | undefined, defaultLov: string, tree = false): LovItem[] => useMemo(() => { if (lov) { diff --git a/gui/src/components/Taipy/tableUtils.tsx b/gui/src/components/Taipy/tableUtils.tsx index 7e0ee62b63..0be03503e1 100644 --- a/gui/src/components/Taipy/tableUtils.tsx +++ b/gui/src/components/Taipy/tableUtils.tsx @@ -26,19 +26,35 @@ import { FormatConfig } from "../../context/taipyReducers"; import { getDateTimeString, getNumberString } from "../../utils/index"; import { TaipyActiveProps, TaipyMultiSelectProps } from "./utils"; +/** + * The Column description as received by the backend. + */ export interface ColumnDesc { + /** {string} The unique column identifier. */ dfid: string; + /** {string} The column type. */ type: string; - format: string; + /** {string} The optional value format. */ + format?: string; + /** {string | undefined} The optional column title. */ title?: string; + /** {number} The order of the column. */ index: number; + /** {number | string | undefined} The optional width. */ width?: number | string; + /** {boolean | undefined} If set to true, the column should not be editable. */ notEditable?: boolean; + /** {string | undefined} The optional column name that would hold the css classname to apply to the cell. */ style?: string; + /** {string | undefined} The optional value that would replace a NaN value. */ nanValue?: string; + /** {string | undefined} The optional TimeZone identifier used if the type is Date. */ tz?: string; + /** {boolean | undefined} The flag that allows filtering. */ filter?: boolean; + /** {string | undefined} The optional identifier for the aggregation function. */ apply?: string; + /** {boolean | undefined} The optional flag that would allow the user to aggregate the column. */ groupBy?: boolean; widthHint?: number; } @@ -47,8 +63,14 @@ export const DEFAULT_SIZE = "small"; export type Order = "asc" | "desc"; +/** + * A cell value type. + */ export type RowValue = string | number | boolean | null; +/** + * The row definition composed of a key/value string/`RowValue`. + */ export type RowType = Record; export const EDIT_COL = "taipy_edit"; diff --git a/gui/src/components/Taipy/utils.ts b/gui/src/components/Taipy/utils.ts index 9a3a8d430a..9f255af5ab 100644 --- a/gui/src/components/Taipy/utils.ts +++ b/gui/src/components/Taipy/utils.ts @@ -67,6 +67,12 @@ export interface TaipyLabelProps { export const getArrayValue = (arr: T[], idx: number, defVal?: T): T | undefined => (arr && idx < arr.length && arr[idx]) || defVal; +/** + * This extracts the backend name of a given property identified by `name`. + * @param {string} updateVars - The value held by the property `updateVars`. + * @param {string} name - The name of a bound property. + * @returns {string | undefined} The backend generated variable name. + */ export const getUpdateVar = (updateVars: string, name: string) => { const sel = updateVars && updateVars.split(";").find((uv) => uv && uv.startsWith(name + "=")); if (sel) { diff --git a/gui/src/context/taipyContext.ts b/gui/src/context/taipyContext.ts index 7c73e56b2e..b9416de828 100644 --- a/gui/src/context/taipyContext.ts +++ b/gui/src/context/taipyContext.ts @@ -14,10 +14,18 @@ import { createContext, Dispatch } from "react"; import { TaipyBaseAction, TaipyState } from "./taipyReducers"; +/** + * The Taipy Store. + */ export interface TaipyStore { + /** {TaipyState} The State of the Taipy Application. */ state: TaipyState; + /** {React.Dispatch} The react dispatch function. */ dispatch: Dispatch; } +/** + * {React.Context} Taipy specific react context. + */ export const TaipyContext = createContext({state: {data: {}} as TaipyState, dispatch: () => null}); TaipyContext.displayName = 'Taipy Context'; diff --git a/gui/src/context/taipyReducers.ts b/gui/src/context/taipyReducers.ts index 05286ca0b2..350838e01a 100644 --- a/gui/src/context/taipyReducers.ts +++ b/gui/src/context/taipyReducers.ts @@ -44,6 +44,9 @@ enum Types { ModuleContext = "MODULE_CONTEXT", } +/** + * TaipyState The State of the Taipy Application. + */ export interface TaipyState { socket?: Socket; isSocketConnected?: boolean; @@ -62,7 +65,7 @@ export interface TaipyState { moduleContext: string; } -export interface TaipyBaseAction { + export interface TaipyBaseAction { type: Types; } @@ -78,7 +81,10 @@ export interface AlertMessage { duration: number; } -interface TaipyAction extends NamePayload, TaipyBaseAction { +/** + * TaipyAction The object used by the reducer. + */ + interface TaipyAction extends NamePayload, TaipyBaseAction { propagate?: boolean; } @@ -219,17 +225,19 @@ const getWsMessageListener = (dispatch: Dispatch) => { const dispatchWsMessage = (message: WsMessage) => { if (message.type === "MU" && Array.isArray(message.payload)) { const payloads = message.payload as NamePayload[]; - Promise.all(payloads.map((pl) => parseData(pl.payload.value as Record))).then(vals => { - vals.forEach((val, idx) => payloads[idx].payload.value = val); - dispatch(messageToAction(message)); - }).catch(console.warn); + Promise.all(payloads.map((pl) => parseData(pl.payload.value as Record))) + .then((vals) => { + vals.forEach((val, idx) => (payloads[idx].payload.value = val)); + dispatch(messageToAction(message)); + }) + .catch(console.warn); return; } else if (message.type === "MS" && Array.isArray(message.payload)) { - (message.payload as WsMessage[]).forEach(msg => dispatchWsMessage(msg)); + (message.payload as WsMessage[]).forEach((msg) => dispatchWsMessage(msg)); return; } dispatch(messageToAction(message)); - } + }; return dispatchWsMessage; }; @@ -435,6 +443,16 @@ const createMultipleUpdateAction = (payload: NamePayload[]): TaipyMultipleAction payload: payload, }); +/** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will update the variable `name` (if `propagate` === true) and provoke the invocation of the on_change python function on the backend. + * @param {string | undefined} [name] - The name of the variable holding the requested data as received as a property (default is ""). + * @param {unknown} value - The new value for the variable named `name`. + * @param {string | undefined} onChange - The name of the on_change python function to invoke on the backend (default to "on_change" on the backend). + * @param {boolean | undefined} [propagate] - A flag indicating that the variable should be automatically updated on the backend (default is true). + * @param {string | undefined} [relName] - The name of the optional related variable (for example the lov when a lov value is updated). + * @returns {TaipyAction} The action fed to the reducer. + */ export const createSendUpdateAction = ( name = "", value: unknown, @@ -459,6 +477,14 @@ const getPayload = (value: unknown, onChange?: string, relName?: string) => { return ret; }; +/** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will provoke the invocation of an on_action python function on the backend with all parameters as a payload. + * @param {string | undefined} name - The name of the backend action. + * @param {unknown} value - The value associated with the action, this can be an object or any type of value. + * @param {unknown[]} args - Additional informations associated to the action. + * @returns {TaipyAction} The action fed to the reducer. + */ export const createSendActionNameAction = ( name: string | undefined, value: unknown, @@ -547,7 +573,19 @@ export const createRequestInfiniteTableUpdateAction = ( filters: filters, }); -export const createRequestDataUpdateAction = ( +/** + * Creates a `TaipyAction` that will be used to update `TaipyContext`. + * This action will provoke the invocation of the get_data python function on the backend that will generate an update of the elements holding data named `name` on the frontend. + * @param {string} name - The name of the variable holding the requested data as received as a property. + * @param {string | undefined} id - The id of the visual element. + * @param {string[]} columns - The list of the columns needed by the element emitting this action. + * @param {string} pageKey - The unique identifier to the data that will be received from this action. + * @param {Record} payload - The payload (specific to the type of component ie table, chart ...). + * @param {boolean | undefined} [allData] - The flag indicating if all the data is requested (default is false). + * @param {string | undefined} library - The optional name of the library {@link extension}. + * @returns {TaipyAction} The action fed to the reducer. + */ + export const createRequestDataUpdateAction = ( name: string | undefined, id: string | undefined, columns: string[], @@ -555,7 +593,7 @@ export const createRequestDataUpdateAction = ( payload: Record, allData = false, library?: string -) => { +): TaipyAction => { payload = payload || {}; if (id !== undefined) { payload.id = id; diff --git a/gui/src/utils/hooks.ts b/gui/src/utils/hooks.ts index afdca0f85a..f24ebb7b9a 100644 --- a/gui/src/utils/hooks.ts +++ b/gui/src/utils/hooks.ts @@ -19,6 +19,14 @@ import { TaipyContext } from "../context/taipyContext"; import { createRequestUpdateAction, FormatConfig, TaipyBaseAction } from "../context/taipyReducers"; import { TIMEZONE_CLIENT } from "../utils"; +/** + * This react hook helps manage a dynamic scalar property (defined by a default property and a bound property). + * @typeparam T - The dynamic property type. + * @param {T} value - The bound value + * @param {T} defaultValue - The default value + * @param {T} defaultStatic - The default static value + * @returns {T} The latest updated value. + */ export const useDynamicProperty = (value: T, defaultValue: T, defaultStatic: T): T => { return useMemo(() => { if (value !== undefined) { @@ -31,6 +39,13 @@ export const useDynamicProperty = (value: T, defaultValue: T, defaultStatic: }, [value, defaultValue, defaultStatic]); }; +/** + * This React hook requests an update for every dynamic property of the element. + * @param {React.Dispatch} dispatch - The react dispatcher associated to `TaipyContext`. + * @param {string | undefined} id - The optional id of the element. + * @param {string} updateVars - The content of the property `updateVars`. + * @param {string | undefined} varName - The default property backend provided variable (through property `updateVarName`). + */ export const useDispatchRequestUpdateOnFirstRender = ( dispatch: Dispatch, id?: string, diff --git a/gui/src/utils/icon.tsx b/gui/src/utils/icon.tsx index 1bc80fd8ae..079b95af40 100644 --- a/gui/src/utils/icon.tsx +++ b/gui/src/utils/icon.tsx @@ -14,11 +14,19 @@ import React from "react"; import Avatar from "@mui/material/Avatar"; +/** + * An Icon representation. + */ export interface Icon { + /** {string} The URL to the image. */ path: string; + /** {string} The text. */ text: string; } +/** + * A String or icon. + */ export type stringIcon = string | Icon; interface IconProps { diff --git a/gui/src/utils/lov.ts b/gui/src/utils/lov.ts index a88de3b09c..b427ba825d 100644 --- a/gui/src/utils/lov.ts +++ b/gui/src/utils/lov.ts @@ -13,9 +13,15 @@ import { stringIcon } from "./icon"; +/** + * An item of lov. + */ export interface LovItem { + /** {string} The unique identifier. */ id: string; + /** {StringIcon} The label (string and/or icon). */ item: stringIcon; + /** {LovItem[] | undefined} The optional array of children. */ children?: LovItem[]; } diff --git a/src/taipy/gui/extension/user_element.py b/src/taipy/gui/extension/user_element.py index b065cc6a4c..de8ddb2fc6 100644 --- a/src/taipy/gui/extension/user_element.py +++ b/src/taipy/gui/extension/user_element.py @@ -25,6 +25,7 @@ class ElementAttribute: """ TODO + This is instantiated to describe an element attribute. """ def __init__( @@ -34,6 +35,16 @@ def __init__( default_value: t.Optional[t.Any] = None, js_name: t.Optional[str] = None, ) -> None: + """ + Arguments: + + name (str): The attribute name. + attribute_type (PropertyType): The attribute type. + default_value (optional Any): The attribute's default value (default is None). + js_name (optional str): The name of the attribute on the frontend (default to Camel Case of `name`). + Attribute starting with `on_` will be translated into `tp_on`. + + """ self.name = name self.attribute_type = attribute_type self.default_value = default_value @@ -56,11 +67,21 @@ def _get_tuple(self) -> tuple: class Element: """ TODO + This is instantiated to describe an element. + """ def __init__( self, name: str, default_attribute: str, attributes: t.List[ElementAttribute], js_name: t.Optional[str] = None ) -> None: + """ + Arguments: + + name (str): The element name. + default_attribute (str): the default attribute for the element. + attributes (List[ElementAttribute]): A list of attributes. + js_name (optional str): The name of the element on the frontend (default to Camel Case of `name`). + """ self.name = name self.default_attribute = default_attribute self.attributes = attributes @@ -137,9 +158,18 @@ def render( ) -> t.Union[None, t.Any, t.Tuple[str, str]]: """ TODO - returns a tuple of string with the full React component instanciation and the component name if is_html - else an xtree Element in markdown context - returns None to let taipy render the component + - returns a tuple of string with the full React component instanciation and the component name if is_html + else an xtree Element in markdown context + - returns None to let taipy render the component + + Arguments: + + gui (Gui): The current instance of Gui. + properties (t.Dict[str, t.Any]): The dict containing a value for each defined attribute. + hash_names (t.Dict[str, str]): The dict containing the internal variable name for each bound attribute. + is_html (t.Optional[bool]): The flag indicating if the method is called in the context of HTML or MarkDown rendering (default is False). + + Returns: (None | xtree.Element | t.Tuple[str, str]) """ return None @@ -147,13 +177,15 @@ def render( class ElementLibrary(ABC): """ TODO + This class needs to be inherited to define a new library. + """ @abstractmethod def get_elements(self) -> t.List[Element]: """ TODO - list of visual elements + Returns the list of visual elements. """ return NotImplemented @@ -161,7 +193,7 @@ def get_elements(self) -> t.List[Element]: def get_name(self) -> str: """ TODO - library name + Returns the library name. """ return NotImplemented @@ -169,7 +201,7 @@ def get_name(self) -> str: def get_scripts(self) -> t.List[str]: """ TODO - list of resources names for the scripts + Returns the list of resources names for the scripts. """ return NotImplemented @@ -177,7 +209,7 @@ def get_scripts(self) -> t.List[str]: def get_styles(self) -> t.List[str]: """ TODO - list of resources names for the css stylesheets + Returns the list of resources names for the css stylesheets. """ return NotImplemented @@ -186,7 +218,11 @@ def get_styles(self) -> t.List[str]: def get_resource(self, name: str) -> Path: """ TODO - returns a path for a resource name + Returns a path for a resource name. + + Arguments: + + name (str): The name of the resource for which a local Path should be returned. """ return NotImplemented @@ -194,14 +230,21 @@ def get_resource(self, name: str) -> Path: def get_register_js_function(self) -> str: """ TODO - returns the name of the function that will register new js components - signature (libName: string) => Record + Returns the name of the function that will register new js components. + signature (libName: string) => Record """ return NotImplemented def get_data(self, library_name: str, payload: t.Dict, var_name: str, value: t.Any) -> t.Optional[t.Dict]: """ TODO - called if implemented + Called if implemented (ie returns a dict). + + Arguments: + + library_name (str): The name of this library. + payload (t.Dict): The payload send by the `createRequestDataUpdateAction` frontend function. + var_name (str): The name of the variable holding the data. + value (t.Any): The current value of the variable identified by `var_name`. """ return None diff --git a/src/taipy/gui/renderers/builder.py b/src/taipy/gui/renderers/builder.py index 064810878f..d6f35c45e4 100644 --- a/src/taipy/gui/renderers/builder.py +++ b/src/taipy/gui/renderers/builder.py @@ -656,7 +656,7 @@ def set_file_content(self, var_name: str = "content"): if hash_name := self.__hashes.get(var_name): self.__set_update_var_name(hash_name) else: - warnings.warn("{self.element_name} {var_name} should be binded") + warnings.warn("{self.element_name} {var_name} should be bound") return self def set_content(self, var_name: str = "content", image=True): @@ -862,7 +862,7 @@ def __set_dynamic_bool_attribute(self, name: str, def_val: t.Any, with_update: b def __set_dynamic_property_without_default(self, name: str, property_type: PropertyType): hash_name = self.__hashes.get(name) if hash_name is None: - warnings.warn(f"{self.__element_name}.{name} should be binded.") + warnings.warn(f"{self.__element_name}.{name} should be bound.") else: hash_name = self.__get_typed_hash_name(hash_name, property_type) self.__update_vars.append(f"{_to_camel_case(name)}={hash_name}") diff --git a/src/taipy/gui/types.py b/src/taipy/gui/types.py index 6e3f48f628..d55d34d991 100644 --- a/src/taipy/gui/types.py +++ b/src/taipy/gui/types.py @@ -45,6 +45,11 @@ class _WsType(Enum): class PropertyType(Enum): + """ + TODO + The enumn describes the possible element attribute types. + """ + boolean = "boolean" content = _TaipyContent data = _TaipyData diff --git a/tests/taipy/gui/actions/test_invoke_state_callback.py b/tests/taipy/gui/actions/test_invoke_state_callback.py index 5308ee0aba..b636d44af1 100644 --- a/tests/taipy/gui/actions/test_invoke_state_callback.py +++ b/tests/taipy/gui/actions/test_invoke_state_callback.py @@ -20,7 +20,7 @@ def test_invoke_state_callback(gui: Gui, helpers): name = "World!" # noqa: F841 btn_id = "button1" # noqa: F841 - val = 1 + val = 1 # noqa: F841 def user_callback(state: State): state.val = 10 diff --git a/tests/taipy/gui/control/test_chart.py b/tests/taipy/gui/control/test_chart.py index b9f90cc9b2..09723ee61e 100644 --- a/tests/taipy/gui/control/test_chart.py +++ b/tests/taipy/gui/control/test_chart.py @@ -15,8 +15,10 @@ def test_chart_md_1(gui: Gui, helpers, csvdata): - selected_indices = [14258] - subplot_layout = {"grid": {"rows": 1, "columns": 2, "subplots": [["xy", "x2y"]], "roworder": "bottom to top"}} + selected_indices = [14258] # noqa: F841 + subplot_layout = { # noqa: F841 + "grid": {"rows": 1, "columns": 2, "subplots": [["xy", "x2y"]], "roworder": "bottom to top"} + } md_string = "<|{csvdata}|chart|x=Day|selected_color=green|y[1]=Daily hospital occupancy|label[1]=Entity|y[2]=Daily hospital occupancy|label[2]=Code|mode[2]=markers|color[2]=red|type[2]=scatter|xaxis[2]=x2|layout={subplot_layout}|on_range_change=range_change|width=100%|height=100%|selected={selected_indices}|>" expected_list = [ "" ) @@ -65,7 +65,7 @@ def test_dialog_labels_md(gui: Gui, helpers): def test_dialog_html_1(gui: Gui, helpers): gui._set_frame(inspect.currentframe()) - dialog_open = False + dialog_open = False # noqa: F841 html_string = ( '' ) @@ -82,8 +82,8 @@ def test_dialog_html_1(gui: Gui, helpers): def test_dialog_html_2(gui: Gui, helpers): gui._set_frame(inspect.currentframe()) - partial = gui.add_partial(Markdown("# A partial")) - dialog_open = False + partial = gui.add_partial(Markdown("# A partial")) # noqa: F841 + dialog_open = False # noqa: F841 html_string = ( '' ) @@ -100,7 +100,7 @@ def test_dialog_html_2(gui: Gui, helpers): def test_dialog_labels_html(gui: Gui, helpers): gui._set_frame(inspect.currentframe()) - dialog_open = False + dialog_open = False # noqa: F841 html_string = ( '' ) diff --git a/tests/taipy/gui/control/test_input.py b/tests/taipy/gui/control/test_input.py index 10d02f78a4..d630d3742a 100644 --- a/tests/taipy/gui/control/test_input.py +++ b/tests/taipy/gui/control/test_input.py @@ -15,7 +15,7 @@ def test_input_md(gui: Gui, helpers): - x = "Hello World!" + x = "Hello World!" # noqa: F841 gui._set_frame(inspect.currentframe()) md_string = "<|{x}|input|>" expected_list = [ @@ -29,7 +29,7 @@ def test_input_md(gui: Gui, helpers): def test_password_md(gui: Gui, helpers): - x = "Hello World!" + x = "Hello World!" # noqa: F841 gui._set_frame(inspect.currentframe()) md_string = "<|{x}|input|password|>" expected_list = [ @@ -43,7 +43,7 @@ def test_password_md(gui: Gui, helpers): def test_input_html_1(gui: Gui, helpers): - x = "Hello World!" + x = "Hello World!" # noqa: F841 gui._set_frame(inspect.currentframe()) html_string = '' expected_list = [ @@ -57,7 +57,7 @@ def test_input_html_1(gui: Gui, helpers): def test_password_html(gui: Gui, helpers): - x = "Hello World!" + x = "Hello World!" # noqa: F841 gui._set_frame(inspect.currentframe()) html_string = '' expected_list = [ @@ -71,7 +71,7 @@ def test_password_html(gui: Gui, helpers): def test_input_html_2(gui: Gui, helpers): - x = "Hello World!" + x = "Hello World!" # noqa: F841 gui._set_frame(inspect.currentframe()) html_string = "{x}" expected_list = [ diff --git a/tests/taipy/gui/control/test_slider.py b/tests/taipy/gui/control/test_slider.py index 55c1985ab9..645fe83379 100644 --- a/tests/taipy/gui/control/test_slider.py +++ b/tests/taipy/gui/control/test_slider.py @@ -34,8 +34,8 @@ def test_slider_with_min_max(gui: Gui, test_client, helpers): def test_slider_with_dict_labels_md(gui: Gui, helpers): - sel = "Item 1" - labels = {"Item 1": "Label Start", "Item 3": "Label End"} + sel = "Item 1" # noqa: F841 + labels = {"Item 1": "Label Start", "Item 3": "Label End"} # noqa: F841 gui._set_frame(inspect.currentframe()) md_string = "<|{sel}|slider|lov=Item 1;Item 2;Item 3|labels={labels}|>" expected_list = [ @@ -46,7 +46,7 @@ def test_slider_with_dict_labels_md(gui: Gui, helpers): def test_slider_with_boolean_labels_md(gui: Gui, helpers): - sel = "Item 1" + sel = "Item 1" # noqa: F841 gui._set_frame(inspect.currentframe()) md_string = "<|{sel}|slider|lov=Item 1;Item 2;Item 3|labels|>" expected_list = [" """ - t = _ISO_to_date("2022-03-03T00:00:00.000Z") + t = _ISO_to_date("2022-03-03T00:00:00.000Z") # noqa: F841 gui._set_frame(inspect.currentframe()) gui.add_page(name="test", page=page_md) helpers.run_e2e(gui, time_zone=time_zone) diff --git a/tests/taipy/gui/e2e/with_action/test_button_action.py b/tests/taipy/gui/e2e/with_action/test_button_action.py index 317ed7c27d..60412c605e 100644 --- a/tests/taipy/gui/e2e/with_action/test_button_action.py +++ b/tests/taipy/gui/e2e/with_action/test_button_action.py @@ -28,7 +28,7 @@ def test_button_action(page: "Page", gui: Gui, helpers): <|Action|button|on_action=do_something_fn|id=button1|> """ - x = 10 + x = 10 # noqa: F841 def do_something_fn(state): state.x = state.x * 2 diff --git a/tests/taipy/gui/e2e/with_action/test_dict.py b/tests/taipy/gui/e2e/with_action/test_dict.py index df50dbb993..630aa4a1e8 100644 --- a/tests/taipy/gui/e2e/with_action/test_dict.py +++ b/tests/taipy/gui/e2e/with_action/test_dict.py @@ -30,7 +30,7 @@ def test_dict(page: "Page", gui: Gui, helpers): <|test|button|on_action=on_action_2|id=btn2|> """ a_key = "key" - a_dict = {a_key: "Taipy"} + a_dict = {a_key: "Taipy"} # noqa: F841 def on_action_1(state): state.a_dict.key = "Hello" diff --git a/tests/taipy/gui/e2e/with_action/test_selector_action.py b/tests/taipy/gui/e2e/with_action/test_selector_action.py index c1665a5a17..88c4ab634f 100644 --- a/tests/taipy/gui/e2e/with_action/test_selector_action.py +++ b/tests/taipy/gui/e2e/with_action/test_selector_action.py @@ -26,7 +26,7 @@ def test_selector_action(page: "Page", gui: Gui, helpers): page_md = """ <|{x}|selector|lov=Item 1;Item 2;Item 3|id=selector1|> """ - x = "Item 1" + x = "Item 1" # noqa: F841 def on_init(state: State): assert state.x == "Item 1" diff --git a/tests/taipy/gui/e2e/with_action/test_slider_action.py b/tests/taipy/gui/e2e/with_action/test_slider_action.py index 858a9ae48d..46ddb99d08 100644 --- a/tests/taipy/gui/e2e/with_action/test_slider_action.py +++ b/tests/taipy/gui/e2e/with_action/test_slider_action.py @@ -28,7 +28,7 @@ def test_slider_action(page: "Page", gui: Gui, helpers): <|{x}|slider|id=slider1|> """ - x = 10 + x = 10 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.add_page(name="test", page=page_md) helpers.run_e2e(gui) @@ -52,7 +52,7 @@ def test_slider_action(page: "Page", gui: Gui, helpers): @pytest.mark.teste2e def test_slider_action_on_change(page: "Page", gui: Gui, helpers): - d = {"v1": 10, "v2": 10} + d = {"v1": 10, "v2": 10} # noqa: F841 def on_change(state, var, val): if var == "d.v2": diff --git a/tests/taipy/gui/e2e/with_action/test_slider_input_reload.py b/tests/taipy/gui/e2e/with_action/test_slider_input_reload.py index 023f6ddcf7..0739d9224f 100644 --- a/tests/taipy/gui/e2e/with_action/test_slider_input_reload.py +++ b/tests/taipy/gui/e2e/with_action/test_slider_input_reload.py @@ -73,7 +73,7 @@ def test_slider_input_reload(page: "Page", gui: Gui, helpers): <|{val}|slider|id=input2|> """ - val = 0 + val = 0 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.add_page(name="page1", page=page_md) helpers.run_e2e_multi_client(gui) diff --git a/tests/taipy/gui/e2e/with_action/test_text_edit.py b/tests/taipy/gui/e2e/with_action/test_text_edit.py index 3854ebccf4..8494f197e1 100644 --- a/tests/taipy/gui/e2e/with_action/test_text_edit.py +++ b/tests/taipy/gui/e2e/with_action/test_text_edit.py @@ -28,7 +28,7 @@ def test_text_edit(page: "Page", gui: Gui, helpers): <|{x}|input|id=input1|> """ - x = "Hey" + x = "Hey" # noqa: F841 gui._set_frame(inspect.currentframe()) gui.add_page(name="test", page=page_md) helpers.run_e2e(gui) @@ -58,7 +58,7 @@ def test_number_edit(page: "Page", gui: Gui, helpers): <|{x}|number|id=number1|> """ - x = 10 + x = 10 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.add_page(name="test", page=page_md) helpers.run_e2e(gui) diff --git a/tests/taipy/gui/extension/test_library.py b/tests/taipy/gui/extension/test_library.py index baf04a3677..d2711c51b1 100644 --- a/tests/taipy/gui/extension/test_library.py +++ b/tests/taipy/gui/extension/test_library.py @@ -40,10 +40,10 @@ def get_scripts(self) -> t.List[str]: return [] def get_styles(self) -> t.List[str]: - return None + return [] def get_resource(self, name: str) -> Path: - return None + return Path(name) def get_register_js_function(self) -> str: return "testRegister" @@ -67,7 +67,7 @@ def test_lib_input_md(gui: Gui, test_client, helpers): def test_lib_input_html_1(gui: Gui, test_client, helpers): - val = "" + val = "" # noqa: F841 gui._set_frame(inspect.currentframe()) html_string = '' expected_list = [" {ret.status_code} != 200" assert ret.mimetype == "application/json", f"mimetype => {ret.mimetype} != application/json" assert ret.json, "json is not defined" - assert "gui" in ret.json, f"json has no key gui" + assert "gui" in ret.json, "json has no key gui" gui = ret.json.get("gui") - assert isinstance(gui, dict), f"json.gui is not a dict" - assert "user_status" in gui, f"json.gui has no key user_status" - assert gui.get("user_status") == "", f"json.gui.user_status is not empty" + assert isinstance(gui, dict), "json.gui is not a dict" + assert "user_status" in gui, "json.gui has no key user_status" + assert gui.get("user_status") == "", "json.gui.user_status is not empty" def test_get_extended_status(gui: Gui): @@ -39,13 +39,13 @@ def test_get_extended_status(gui: Gui): assert ret.mimetype == "application/json", f"mimetype => {ret.mimetype} != application/json" assert ret.json, "json is not defined" gui = ret.json.get("gui") - assert "backend_version" in gui, f"json.gui has no key backend_version" - assert "flask_version" in gui, f"json.gui has no key flask_version" - assert "frontend_version" in gui, f"json.gui has no key frontend_version" - assert "host" in gui, f"json.gui has no key host" - assert "python_version" in gui, f"json.gui has no key python_version" - assert "user_status" in gui, f"json.gui has no key user_status" - assert gui.get("user_status") == "", f"json.gui.user_status is not empty" + assert "backend_version" in gui, "json.gui has no key backend_version" + assert "flask_version" in gui, "json.gui has no key flask_version" + assert "frontend_version" in gui, "json.gui has no key frontend_version" + assert "host" in gui, "json.gui has no key host" + assert "python_version" in gui, "json.gui has no key python_version" + assert "user_status" in gui, "json.gui has no key user_status" + assert gui.get("user_status") == "", "json.gui.user_status is not empty" def test_get_status_with_user_status(gui: Gui): @@ -62,5 +62,5 @@ def on_status(state): assert ret.status_code == 200, f"status_code => {ret.status_code} != 200" assert ret.json, "json is not defined" gui = ret.json.get("gui") - assert "user_status" in gui, f"json.gui has no key user_status" + assert "user_status" in gui, "json.gui has no key user_status" assert gui.get("user_status") == user_status, f'json.gui.user_status => {gui.get("user_status")} != {user_status}' diff --git a/tests/taipy/gui/server/ws/test_on_change.py b/tests/taipy/gui/server/ws/test_on_change.py index 5a5d13b5ba..bb2e6cef50 100644 --- a/tests/taipy/gui/server/ws/test_on_change.py +++ b/tests/taipy/gui/server/ws/test_on_change.py @@ -38,7 +38,7 @@ def on_change(state, var, value): # fake var update ws_client.emit("message", {"client_id": sid, "type": "U", "name": "x", "payload": {"value": "20"}}) assert ws_client.get_received() - assert st["d"] == True + assert st["d"] is True def test_specific_on_change(gui: Gui, helpers): @@ -69,5 +69,5 @@ def on_input_change(state, var, value): {"client_id": sid, "type": "U", "name": "x", "payload": {"value": "20", "on_change": "on_input_change"}}, ) assert ws_client.get_received() - assert st["s"] == True - assert st["d"] == False + assert st["s"] is True + assert st["d"] is False diff --git a/tests/taipy/gui/utils/test_evaluator.py b/tests/taipy/gui/utils/test_evaluator.py index 02edb98d53..725b82ee3c 100644 --- a/tests/taipy/gui/utils/test_evaluator.py +++ b/tests/taipy/gui/utils/test_evaluator.py @@ -28,7 +28,7 @@ def test_unbind_variable_in_expression(gui: Gui): def test_evaluate_same_expression_multiple_times(gui: Gui): - x = 10 + x = 10 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.run(run_server=False, single_client=True) with gui.get_flask_app().app_context(): @@ -38,7 +38,7 @@ def test_evaluate_same_expression_multiple_times(gui: Gui): def test_evaluate_expressions_same_variable(gui: Gui): - x = 10 + x = 10 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.run(run_server=False, single_client=True) with gui.get_flask_app().app_context(): @@ -48,10 +48,10 @@ def test_evaluate_expressions_same_variable(gui: Gui): def test_evaluate_holder(gui: Gui, test_client): - x = 10 + x = 10 # noqa: F841 gui._set_frame(inspect.currentframe()) gui.run(run_server=False, single_client=True) - with warnings.catch_warnings(record=True) as w: + with warnings.catch_warnings(record=True): with gui.get_flask_app().app_context(): gui._evaluate_expr("{x + 10}") hash = gui._evaluate_bind_holder(_TaipyNumber, "TpExPr_x + 10_TPMDL_0") diff --git a/tests/taipy/gui/utils/test_types.py b/tests/taipy/gui/utils/test_types.py index 3b2e26e7a6..6389be51d4 100644 --- a/tests/taipy/gui/utils/test_types.py +++ b/tests/taipy/gui/utils/test_types.py @@ -27,14 +27,14 @@ def test_taipy_base(): def test_taipy_bool(): - assert _TaipyBool(0, "v").get() == False - assert _TaipyBool(1, "v").get() == True - assert _TaipyBool(False, "v").get() == False - assert _TaipyBool(True, "v").get() == True - assert _TaipyBool("", "v").get() == False - assert _TaipyBool("hey", "v").get() == True - assert _TaipyBool([], "v").get() == False - assert _TaipyBool(["an item"], "v").get() == True + assert _TaipyBool(0, "v").get() is False + assert _TaipyBool(1, "v").get() is True + assert _TaipyBool(False, "v").get() is False + assert _TaipyBool(True, "v").get() is True + assert _TaipyBool("", "v").get() is False + assert _TaipyBool("hey", "v").get() is True + assert _TaipyBool([], "v").get() is False + assert _TaipyBool(["an item"], "v").get() is True def test_taipy_number():