diff --git a/package-lock.json b/package-lock.json index 6070611..351acef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "angular-expressions": "^1.4.3", "clsx": "^2.1.1", "core-js": "^3.42.0", + "dayjs": "^1.11.13", "docxtemplater": "^3.63.2", "file-saver": "^2.0.5", "moize": "^6.1.6", @@ -26,8 +27,8 @@ "@kintone/dts-gen": "^8.1.2", "@kintone/plugin-uploader": "^9.1.5", "@kintone/webpack-plugin-kintone-plugin": "^8.0.11", - "@rspack/cli": "^1.3.12", - "@rspack/core": "^1.3.12", + "@rspack/cli": "^1.3.13", + "@rspack/core": "^1.3.13", "@shin-chan/kypes": "^0.0.7", "@swc/helpers": "^0.5.17", "@types/file-saver": "^2.0.7", @@ -36,7 +37,7 @@ "cross-env": "^7.0.3", "css-loader": "^7.1.2", "env-cmd": "^10.1.0", - "eslint": "^9.27.0", + "eslint": "^9.28.0", "eslint-plugin-react": "^7.37.5", "npm-run-all": "^4.1.5", "prettier": "^3.5.3", @@ -363,9 +364,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", - "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "dev": true, "license": "MIT", "engines": { @@ -968,62 +969,62 @@ "license": "MIT" }, "node_modules/@module-federation/error-codes": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.14.0.tgz", - "integrity": "sha512-GGk+EoeSACJikZZyShnLshtq9E2eCrDWbRiB4QAFXCX4oYmGgFfzXlx59vMNwqTKPJWxkEGnPYacJMcr2YYjag==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.14.3.tgz", + "integrity": "sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw==", "dev": true, "license": "MIT" }, "node_modules/@module-federation/runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.14.0.tgz", - "integrity": "sha512-kR3cyHw/Y64SEa7mh4CHXOEQYY32LKLK75kJOmBroLNLO7/W01hMNAvGBYTedS7hWpVuefPk1aFZioy3q2VLdQ==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.14.3.tgz", + "integrity": "sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.14.0", - "@module-federation/runtime-core": "0.14.0", - "@module-federation/sdk": "0.14.0" + "@module-federation/error-codes": "0.14.3", + "@module-federation/runtime-core": "0.14.3", + "@module-federation/sdk": "0.14.3" } }, "node_modules/@module-federation/runtime-core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.14.0.tgz", - "integrity": "sha512-fGE1Ro55zIFDp/CxQuRhKQ1pJvG7P0qvRm2N+4i8z++2bgDjcxnCKUqDJ8lLD+JfJQvUJf0tuSsJPgevzueD4g==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.14.3.tgz", + "integrity": "sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.14.0", - "@module-federation/sdk": "0.14.0" + "@module-federation/error-codes": "0.14.3", + "@module-federation/sdk": "0.14.3" } }, "node_modules/@module-federation/runtime-tools": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.14.0.tgz", - "integrity": "sha512-y/YN0c2DKsLETE+4EEbmYWjqF9G6ZwgZoDIPkaQ9p0pQu0V4YxzWfQagFFxR0RigYGuhJKmSU/rtNoHq+qF8jg==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.14.3.tgz", + "integrity": "sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.14.0", - "@module-federation/webpack-bundler-runtime": "0.14.0" + "@module-federation/runtime": "0.14.3", + "@module-federation/webpack-bundler-runtime": "0.14.3" } }, "node_modules/@module-federation/sdk": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.14.0.tgz", - "integrity": "sha512-lg/OWRsh18hsyTCamOOhEX546vbDiA2O4OggTxxH2wTGr156N6DdELGQlYIKfRdU/0StgtQS81Goc0BgDZlx9A==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.14.3.tgz", + "integrity": "sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw==", "dev": true, "license": "MIT" }, "node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.14.0.tgz", - "integrity": "sha512-POWS6cKBicAAQ3DNY5X7XEUSfOfUsRaBNxbuwEfSGlrkTE9UcWheO06QP2ndHi8tHQuUKcIHi2navhPkJ+k5xg==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.14.3.tgz", + "integrity": "sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.14.0", - "@module-federation/sdk": "0.14.0" + "@module-federation/runtime": "0.14.3", + "@module-federation/sdk": "0.14.3" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -1134,27 +1135,27 @@ } }, "node_modules/@rspack/binding": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.3.12.tgz", - "integrity": "sha512-4Ic8lV0+LCBfTlH5aIOujIRWZOtgmG223zC4L3o8WY/+ESAgpdnK6lSSMfcYgRanYLAy3HOmFIp20jwskMpbAg==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.3.13.tgz", + "integrity": "sha512-BdM6tfLCP7/0H5uGc+okG6AYsU9JEnR5bRHq4YuGaS4tb+N5ct0czm0LprGMZ7zRAnIql/zoLn/bHlheNxZw3g==", "dev": true, "license": "MIT", "optionalDependencies": { - "@rspack/binding-darwin-arm64": "1.3.12", - "@rspack/binding-darwin-x64": "1.3.12", - "@rspack/binding-linux-arm64-gnu": "1.3.12", - "@rspack/binding-linux-arm64-musl": "1.3.12", - "@rspack/binding-linux-x64-gnu": "1.3.12", - "@rspack/binding-linux-x64-musl": "1.3.12", - "@rspack/binding-win32-arm64-msvc": "1.3.12", - "@rspack/binding-win32-ia32-msvc": "1.3.12", - "@rspack/binding-win32-x64-msvc": "1.3.12" + "@rspack/binding-darwin-arm64": "1.3.13", + "@rspack/binding-darwin-x64": "1.3.13", + "@rspack/binding-linux-arm64-gnu": "1.3.13", + "@rspack/binding-linux-arm64-musl": "1.3.13", + "@rspack/binding-linux-x64-gnu": "1.3.13", + "@rspack/binding-linux-x64-musl": "1.3.13", + "@rspack/binding-win32-arm64-msvc": "1.3.13", + "@rspack/binding-win32-ia32-msvc": "1.3.13", + "@rspack/binding-win32-x64-msvc": "1.3.13" } }, "node_modules/@rspack/binding-darwin-arm64": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.12.tgz", - "integrity": "sha512-8hKjVTBeWPqkMzFPNWIh72oU9O3vFy3e88wRjMPImDCXBiEYrKqGTTLd/J0SO+efdL3SBD1rX1IvdJpxCv6Yrw==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.13.tgz", + "integrity": "sha512-1c+KC+TFaKRWu+SO4cJZ5oHKOFuDhTIitbSIG9boJpDRoZmJxHDmFyTTxVI2r2QUjxJaDdUlSFepybhhJ3UiPg==", "cpu": [ "arm64" ], @@ -1166,9 +1167,9 @@ ] }, "node_modules/@rspack/binding-darwin-x64": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.12.tgz", - "integrity": "sha512-Sj4m+mCUxL7oCpdu7OmWT7fpBM7hywk5CM9RDc3D7StaBZbvNtNftafCrTZzTYKuZrKmemTh5SFzT5Tz7tf6GA==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.13.tgz", + "integrity": "sha512-YBF+XjoGSjhJ5o/xOaCBd39BntMudMeup11j2Dz+rrTH+wG6TvH017HYIgDMT3UBVv66eNsQpzA0ZW5raJ0lbA==", "cpu": [ "x64" ], @@ -1180,9 +1181,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-gnu": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.12.tgz", - "integrity": "sha512-7MuOxf3/Mhv4mgFdLTvgnt/J+VouNR65DEhorth+RZm3LEWojgoFEphSAMAvpvAOpYSS68Sw4SqsOZi719ia2w==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.13.tgz", + "integrity": "sha512-II71Ez7Z0/5ZpcK+kCgvXFKK0AysS9La8LNQbqf2wmzxDJi5H8eVUiwkM5BabICxzOWYtTGJLZ89QbCYaFbqCg==", "cpu": [ "arm64" ], @@ -1194,9 +1195,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-musl": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.12.tgz", - "integrity": "sha512-s6KKj20T9Z1bA8caIjU6EzJbwyDo1URNFgBAlafCT2UC6yX7flstDJJ38CxZacA9A2P24RuQK2/jPSZpWrTUFA==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.13.tgz", + "integrity": "sha512-JFFhqglKVjlWcmmVwdS80Kw6v35yY9xlQJup09mL8gMtiiFiT36wTyTujz15Iv+2+S/Dv0Z+UeUJ99KRbQxgcQ==", "cpu": [ "arm64" ], @@ -1208,9 +1209,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-gnu": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.12.tgz", - "integrity": "sha512-0w/sRREYbRgHgWvs2uMEJSLfvzbZkPHUg6CMcYQGNVK6axYRot6jPyKetyFYA9pR5fB5rsXegpnFaZaVrRIK2g==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.13.tgz", + "integrity": "sha512-ogm4rt+PMQHkMg/0mA9VTjfGE3c+YaHZQT8KrFgTsoj2YCW9WO2J/RjdMc6STG4Y10BWO9Ar2azLxxHrKb+8UQ==", "cpu": [ "x64" ], @@ -1222,9 +1223,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-musl": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.12.tgz", - "integrity": "sha512-jEdxkPymkRxbijDRsBGdhopcbGXiXDg59lXqIRkVklqbDmZ/O6DHm7gImmlx5q9FoWbz0gqJuOKBz4JqWxjWVA==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.13.tgz", + "integrity": "sha512-8icDyXhg1iMKhQ3X2FTgAGQTQqnli9FyqHCuRIBauxy1V4W478Mp9Y+V+ErVUY1YxbZEUrkt3a59hssjGeDEeg==", "cpu": [ "x64" ], @@ -1236,9 +1237,9 @@ ] }, "node_modules/@rspack/binding-win32-arm64-msvc": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.12.tgz", - "integrity": "sha512-ZRvUCb3TDLClAqcTsl/o9UdJf0B5CgzAxgdbnYJbldyuyMeTUB4jp20OfG55M3C2Nute2SNhu2bOOp9Se5Ongw==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.13.tgz", + "integrity": "sha512-y5XxwxDW4DrPKy+8P6t7I7IbA7B/iXjLoaS0jP/EwjSHWf/EnZzq9MgWqdop1km8Mwx6s1zcj+0qs73jL2N98w==", "cpu": [ "arm64" ], @@ -1250,9 +1251,9 @@ ] }, "node_modules/@rspack/binding-win32-ia32-msvc": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.12.tgz", - "integrity": "sha512-1TKPjuXStPJr14f3ZHuv40Xc/87jUXx10pzVtrPnw+f3hckECHrbYU/fvbVzZyuXbsXtkXpYca6ygCDRJAoNeQ==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.13.tgz", + "integrity": "sha512-n24sznsZe3lC8ok6MgsT1nG4lVx3SQ/lZ0g23i2BGMRN8/p+kaC2eoPaHe/4m9Liz/W4Z5LhZCCvg4DQMEzeLA==", "cpu": [ "ia32" ], @@ -1264,9 +1265,9 @@ ] }, "node_modules/@rspack/binding-win32-x64-msvc": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.12.tgz", - "integrity": "sha512-lCR0JfnYKpV+a6r2A2FdxyUKUS4tajePgpPJN5uXDgMGwrDtRqvx+d0BHhwjFudQVJq9VVbRaL89s2MQ6u+xYw==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.13.tgz", + "integrity": "sha512-CLyTNo0OrOD7xFKusFciKKG+8CXPowjPz+tcdkkrKYqGzAPzOcszblikITJhMbc7DLMzdTRSZUTkKLRydYH9sw==", "cpu": [ "x64" ], @@ -1278,9 +1279,9 @@ ] }, "node_modules/@rspack/cli": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/cli/-/cli-1.3.12.tgz", - "integrity": "sha512-LdajkH+YW2NaWvY0rHs+l6Ip4X1/eQ7J3qVGlV9H5TkXMp3+ldIIw/6W/2sjmf2l4GRobpVASm5U2e58bqiIpg==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/cli/-/cli-1.3.13.tgz", + "integrity": "sha512-a9zPvSB3OvER+87l6tg+gzh6yhlqz9eHaw4hcogbd14tTJJzBI7nQJDGCf/3J+TEvOxzvuNj2+OvdDD76UU5sw==", "dev": true, "license": "MIT", "dependencies": { @@ -1301,16 +1302,15 @@ } }, "node_modules/@rspack/core": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.3.12.tgz", - "integrity": "sha512-mAPmV4LPPRgxpouUrGmAE4kpF1NEWJGyM5coebsjK/zaCMSjw3mkdxiU2b5cO44oIi0Ifv5iGkvwbdrZOvMyFA==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.3.13.tgz", + "integrity": "sha512-j9jsNzKeEN14yraqX4jAFrM/nMfX5YEPgEMPlp4g5NAu3siaBa8gDF5brbdNq6TDXnTHK1MwwjaMdKA+3YeBKQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime-tools": "0.14.0", - "@rspack/binding": "1.3.12", - "@rspack/lite-tapable": "1.0.1", - "caniuse-lite": "^1.0.30001718" + "@module-federation/runtime-tools": "0.14.3", + "@rspack/binding": "1.3.13", + "@rspack/lite-tapable": "1.0.1" }, "engines": { "node": ">=16.0.0" @@ -3262,7 +3262,8 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "CC-BY-4.0" + "license": "CC-BY-4.0", + "peer": true }, "node_modules/chalk": { "version": "4.1.2", @@ -3774,6 +3775,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -4381,9 +4388,9 @@ } }, "node_modules/eslint": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", - "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4393,7 +4400,7 @@ "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.27.0", + "@eslint/js": "9.28.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", diff --git a/package.json b/package.json index d2dbfc0..1d441d1 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "angular-expressions": "^1.4.3", "clsx": "^2.1.1", "core-js": "^3.42.0", + "dayjs": "^1.11.13", "docxtemplater": "^3.63.2", "file-saver": "^2.0.5", "moize": "^6.1.6", @@ -30,8 +31,8 @@ "@kintone/dts-gen": "^8.1.2", "@kintone/plugin-uploader": "^9.1.5", "@kintone/webpack-plugin-kintone-plugin": "^8.0.11", - "@rspack/cli": "^1.3.12", - "@rspack/core": "^1.3.12", + "@rspack/cli": "^1.3.13", + "@rspack/core": "^1.3.13", "@shin-chan/kypes": "^0.0.7", "@swc/helpers": "^0.5.17", "@types/file-saver": "^2.0.7", @@ -40,7 +41,7 @@ "cross-env": "^7.0.3", "css-loader": "^7.1.2", "env-cmd": "^10.1.0", - "eslint": "^9.27.0", + "eslint": "^9.28.0", "eslint-plugin-react": "^7.37.5", "npm-run-all": "^4.1.5", "prettier": "^3.5.3", diff --git a/src/common/DynamicPortal.tsx b/src/common/DynamicPortal.tsx index ab1cffa..90c0c33 100644 --- a/src/common/DynamicPortal.tsx +++ b/src/common/DynamicPortal.tsx @@ -21,6 +21,7 @@ const DynamicPortal: React.FC = (props) => { el.parentNode.removeChild(el); } }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ReactDOM.createPortal(children, el); }; diff --git a/src/common/global.ts b/src/common/global.ts index 1ed240a..4fcb867 100644 --- a/src/common/global.ts +++ b/src/common/global.ts @@ -3,5 +3,13 @@ import invariant from 'tiny-invariant'; export const PLUGIN_ID = kintone.$PLUGIN_ID; invariant(PLUGIN_ID, 'The PLUGIN_ID is not available. Please ensure you are on a Kintone plugin page.'); -export const LANGUAGE = kintone.getLoginUser().language; -invariant(LANGUAGE, 'The LANGUAGE is not available. Please ensure you are on a Kintone plugin page.'); +const KintoneUserLanguages = ['en', 'ja', 'zh', 'zh-TW', 'es', 'pt-BR', 'th'] as const; +export type KintoneUserLanguages = (typeof KintoneUserLanguages)[number]; +export const LANGUAGE = kintone.getLoginUser().language as KintoneUserLanguages; +invariant( + KintoneUserLanguages.includes(LANGUAGE), + `Unsupported language: ${LANGUAGE}. Supported languages are: ${KintoneUserLanguages.join(', ')}`, +); + +export const DOCX_CONTENTTYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; +export const DOCX_EXTENSION = 'docx'; diff --git a/src/desktop/MenuPanel.tsx b/src/desktop/MenuPanel.tsx index ae507b1..778275e 100644 --- a/src/desktop/MenuPanel.tsx +++ b/src/desktop/MenuPanel.tsx @@ -1,15 +1,16 @@ import React from 'react'; -import { KintoneRestAPIClient } from '@kintone/rest-api-client'; +import { KintoneFormFieldProperty, KintoneRestAPIClient } from '@kintone/rest-api-client'; import { Properties as KintoneFormFieldProperties } from '@kintone/rest-api-client/lib/src/client/types'; import { KintoneRecord } from '@shin-chan/kypes/types/page'; +import dayjs from 'dayjs'; import Docxtemplater from 'docxtemplater'; import expressionParser from 'docxtemplater/expressions'; import { saveAs } from 'file-saver'; import moize from 'moize'; import PizZip from 'pizzip'; import invariant from 'tiny-invariant'; -import { LANGUAGE, PLUGIN_ID } from '../common/global'; +import { DOCX_CONTENTTYPE, LANGUAGE, PLUGIN_ID } from '../common/global'; import KintonePluginAlert from '../common/ui/KintonePluginAlert'; import KintonePluginButton from '../common/ui/KintonePluginButton'; @@ -19,8 +20,6 @@ interface TemplateData { [key: string]: TemplateData | TemplateData[] | string | string[]; } -const DOCX_CONTENTTYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; - interface MenuPanelProps { event: kintone.events.AppRecordDetailShowEvent | kintone.events.MobileAppRecordDetailShowEvent; } @@ -31,6 +30,105 @@ const cachedFormFieldsProperties = moize.promise(async (appId: number): Promise< return properties; }); +const formatNumberValue = (value: string, digit: boolean, scale?: number): string => { + if (value !== '' && !isNaN(Number(value))) { + const numberValue = Number(value); + const options: Intl.NumberFormatOptions = { + useGrouping: digit, + }; + if (scale != null && scale >= 0) { + options.minimumFractionDigits = scale; + options.maximumFractionDigits = scale; + } + return new Intl.NumberFormat('en-US', options).format(numberValue); + } + return value; +}; + +const formatValueWithUnit = ( + value: string, + property: KintoneFormFieldProperty.Number | KintoneFormFieldProperty.Calc, +): string => { + if (value !== '' && property.unit !== '') { + if (property.unitPosition === 'BEFORE') { + return `${property.unit} ${value}`; + } else if (property.unitPosition === 'AFTER') { + return `${value} ${property.unit}`; + } + } + return value; +}; + +const formatNumberRecordValue = ( + value: string, + property: KintoneFormFieldProperty.Number | KintoneFormFieldProperty.Lookup, +): string => { + if ('lookup' in property) { + return value; + } + const scale = property.displayScale !== '' ? Number(property.displayScale) : undefined; + const digit = property.digit ?? false; + const formattedValue = formatNumberValue(value, digit, scale); + return formatValueWithUnit(formattedValue, property); +}; + +const formatCalculatedRecordValue = (value: string, property: KintoneFormFieldProperty.Calc): string => { + const { format } = property; + if (value === '') { + return ''; + } + const scale = property.displayScale !== '' ? Number(property.displayScale) : undefined; + let formattedValue: string; + if (format === 'NUMBER') { + formattedValue = formatNumberValue(value, false, scale); + } else if (format === 'NUMBER_DIGIT') { + formattedValue = formatNumberValue(value, true, scale); + } else if (format === 'DATETIME') { + // "2025-05-30T00:00:00Z" -> "2025-05-30 9:00" (browser local timezone) + const date = new Date(value); + invariant(!isNaN(date.getTime()), `Expected value to be a valid date string, but got ${value}`); + formattedValue = dayjs(date).format('YYYY-MM-DD h:mm'); + } else if (format === 'DATE') { + // "2025-05-30T00:00:00Z" -> "2025-05-30" (browser local timezone) + const date = new Date(value); + invariant(!isNaN(date.getTime()), `Expected value to be a valid date string, but got ${value}`); + formattedValue = dayjs(date).format('YYYY-MM-DD'); + } else if (format === 'TIME') { + // "00:30" -> "0:30" + const [hours, minutes] = value.split(':').map((v) => Number(v)); + invariant( + !isNaN(hours) && !isNaN(minutes), + `Expected hours and minutes to be numbers, but got hours: ${hours}, minutes: ${minutes}`, + ); + formattedValue = `${hours}:${String(minutes).padStart(2, '0')}`; + } else if (format === 'HOUR_MINUTE') { + // "49:30" -> en:"49 hours 30 minutes", ja: "49時間30分" + const [hours, minutes] = value.split(':').map((v) => Number(v)); + invariant( + !isNaN(hours) && !isNaN(minutes), + `Expected hours and minutes to be numbers, but got hours: ${hours}, minutes: ${minutes}`, + ); + formattedValue = LANGUAGE === 'ja' ? `${hours}時間${minutes}分` : `${hours} hours ${minutes} minutes`; + } else if (format === 'DAY_HOUR_MINUTE') { + // "49:30" -> en: "2 days 1 hour 30 minutes", ja: "2日1時間30分 + const [hours, minutes] = value.split(':').map((v) => Number(v)); + invariant( + !isNaN(hours) && !isNaN(minutes), + `Expected hours and minutes to be numbers, but got hours: ${hours}, minutes: ${minutes}`, + ); + const days = Math.floor(Number(hours) / 24); + const remainingHours = Number(hours) % 24; + formattedValue = + LANGUAGE === 'ja' + ? `${days}日${remainingHours}時間${minutes}分` + : `${days} days ${remainingHours} hours ${minutes} minutes`; + } else { + // DATETIME, DATE, TIME + formattedValue = value; + } + return formatValueWithUnit(formattedValue, property); +}; + const record2data = (properties: KintoneFormFieldProperties, record: Partial): TemplateData => { const data: TemplateData = {}; for (const key in record) { @@ -46,13 +144,19 @@ const record2data = (properties: KintoneFormFieldProperties, record: Partial v); } else if ( - type === 'STATUS_ASSIGNEE' || type === 'USER_SELECT' || + type === 'ORGANIZATION_SELECT' || type === 'GROUP_SELECT' || - type === 'ORGANIZATION_SELECT' + type === 'STATUS_ASSIGNEE' ) { data[key] = value.map((v) => { return { name: v.name, code: v.code }; @@ -60,44 +164,17 @@ const record2data = (properties: KintoneFormFieldProperties, record: Partial record2data(property.fields, subRecord.value)); - } else if (type === 'CALC') { - invariant(property.type === 'CALC', `Expected property type to be CALC, but got ${property.type}`); - if (value === '') { - data[key] = ''; - } else if (property.format === 'NUMBER_DIGIT') { - // "1234567" -> "1,234,567" - data[key] = Number(value).toLocaleString('en-US'); - } else if (property.format === 'HOUR_MINUTE') { - // "49:30" -> en:"49 hours 30 minutes", ja: "49時間30分" - const [hours, minutes] = value.split(':').map((v) => Number(v)); - invariant( - !isNaN(hours) && !isNaN(minutes), - `Expected hours and minutes to be numbers, but got hours: ${hours}, minutes: ${minutes}`, - ); - if (LANGUAGE === 'ja') { - data[key] = `${hours}時間${minutes}分`; - } else { - data[key] = `${hours} hours ${minutes} minutes`; - } - } else if (property.format === 'DAY_HOUR_MINUTE') { - // "49:30" -> en: "2 days 1 hour 30 minutes", ja: "2日1時間30分 - const [hours, minutes] = value.split(':').map((v) => Number(v)); - invariant( - !isNaN(hours) && !isNaN(minutes), - `Expected hours and minutes to be numbers, but got hours: ${hours}, minutes: ${minutes}`, - ); - const days = Math.floor(Number(hours) / 24); - const remainingHours = Number(hours) % 24; - if (LANGUAGE === 'ja') { - data[key] = `${days}日${remainingHours}時間${minutes}分`; - } else { - data[key] = `${days} days ${remainingHours} hours ${minutes} minutes`; - } - } else { - // NUMBER, DATETIME, DATE, TIME - data[key] = value; - } + } else if (type === 'FILE') { + invariant(property.type === 'FILE', `Expected property type to be FILE, but got ${property.type}`); + data[key] = value.map((file) => ({ + name: file.name, + size: file.size, + contentType: file.contentType, + fileKey: file.fileKey, + })); } else { + // RECORD_NUMBER, __ID__, __REVISION__, CREATED_TIME, UPDATED_TIME + // SINGLE_LINE_TEXT, MULTI_LINE_TEXT, RICH_TEXT, RADIO_BUTTON, DROP_DOWN, DATE, TIME, DATETIME, LINK, STATUS data[key] = value; } } @@ -123,15 +200,15 @@ const MenuPanel: React.FC = (props) => { return WORD output plugin: Template field is not available in this app.; } if (record.type !== 'FILE') { - return WORD output plugin: The template field must be a file field.; + return WORD output plugin: Template field must be a file field.; } if (record.value.length === 0) { - return WORD output plugin: The template field does not contain any files.; + return WORD output plugin: Template field does not contain any files.; } if (record.value.length > 1) { return ( - WORD output plugin: The template field contains multiple files. Only the first file will be used. + WORD output plugin: Template field contains multiple files. Please ensure it contains only one file. ); }