From 9efaa55235b85100eebf354fe052f7b455232d10 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 22 Jan 2025 15:52:41 -0800 Subject: [PATCH 01/45] IO-3092 basic URL signing and image/pdf/video thumb generation. --- package-lock.json | 560 ++++++++++++++++++++++++++++++++++ package.json | 1 + server/media/imgprox-media.js | 136 +++++++++ server/routes/mediaRoutes.js | 7 + 4 files changed, 704 insertions(+) create mode 100644 server/media/imgprox-media.js diff --git a/package-lock.json b/package-lock.json index 4705bef33..0ae94d2a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@aws-sdk/client-secrets-manager": "^3.693.0", "@aws-sdk/client-ses": "^3.693.0", "@aws-sdk/credential-provider-node": "^3.693.0", + "@aws-sdk/s3-request-presigner": "^3.731.1", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -1101,6 +1102,499 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.731.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.731.1.tgz", + "integrity": "sha512-GdG0pXkcTgBpenouB834FoCHyLaivV2rGQn7OEQBiT8SBaTxSackZ6tGlJQAlzZQkiQfE/NePUJU7DczJZZvrg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/signature-v4-multi-region": "3.731.0", + "@aws-sdk/types": "3.731.0", + "@aws-sdk/util-format-url": "3.731.0", + "@smithy/middleware-endpoint": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/core": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.731.0.tgz", + "integrity": "sha512-ithBN1VWASkvAIlozJmenqDvNnFddr/SZXAs58+jCnBHgy3tXLHABZGVNCjetZkHRqNdXEO1kirnoxaFeXMeDA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.731.0", + "@smithy/core": "^3.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/property-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.731.0.tgz", + "integrity": "sha512-J9aKyQaVoec5eWTSDfO4h2sKHNP0wTzN15LFcHnkD+e/d0rdmOi7BTkkbJrIaynma9WShIasmrtM3HNi9GiiTA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.731.0", + "@aws-sdk/types": "3.731.0", + "@aws-sdk/util-arn-parser": "3.723.0", + "@smithy/core": "^3.0.0", + "@smithy/node-config-provider": "^4.0.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/smithy-client": "^4.0.0", + "@smithy/types": "^4.0.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.0", + "@smithy/util-stream": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.731.0.tgz", + "integrity": "sha512-1r/b4Os15dR+BCVRRLVQJMF7Krq6xX6IKHxN43kuvODYWz8Nv3XDlaSpeRpAzyJuzW/fTp4JgE+z0+gmJfdEeA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.731.0", + "@aws-sdk/types": "3.731.0", + "@smithy/protocol-http": "^5.0.0", + "@smithy/signature-v4": "^5.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/types": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.731.0.tgz", + "integrity": "sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/util-arn-parser": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.723.0.tgz", + "integrity": "sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/core": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.1.tgz", + "integrity": "sha512-hhUZlBWYuh9t6ycAcN90XOyG76C1AzwxZZgaCVPMYpWqqk9uMFo7HGG5Zu2cEhCJn7DdOi5krBmlibWWWPgdsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-stream": "^4.0.2", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/fetch-http-handler": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz", + "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/is-array-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", + "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/middleware-endpoint": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.2.tgz", + "integrity": "sha512-Z9m67CXizGpj8CF/AW/7uHqYNh1VXXOn9Ap54fenWsCa0HnT4cJuE61zqG3cBkTZJDCy0wHJphilI41co/PE5g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.1.1", + "@smithy/middleware-serde": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/middleware-serde": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.1.tgz", + "integrity": "sha512-Fh0E2SOF+S+P1+CsgKyiBInAt3o2b6Qk7YOp2W0Qx2XnfTdfMuSDKUEcnrtpxCzgKJnqXeLUZYqtThaP0VGqtA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/middleware-stack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz", + "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/node-http-handler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", + "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/property-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz", + "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/querystring-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz", + "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/shared-ini-file-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz", + "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/signature-v4": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", + "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-uri-escape": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/smithy-client": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.2.tgz", + "integrity": "sha512-0yApeHWBqocelHGK22UivZyShNxFbDNrgREBllGh5Ws0D0rg/yId/CJfeoKKpjbfY2ju8j6WgDUGZHYQmINZ5w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.1.1", + "@smithy/middleware-endpoint": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.0.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/url-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", + "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-base64": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", + "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-body-length-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", + "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-buffer-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", + "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-config-provider": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", + "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-hex-encoding": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", + "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-middleware": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", + "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz", + "integrity": "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-utf8": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", + "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@aws-sdk/signature-v4-multi-region": { "version": "3.696.0", "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.696.0.tgz", @@ -1177,6 +1671,72 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.731.0.tgz", + "integrity": "sha512-wZHObjnYmiz8wFlUQ4/5dHsT7k0at+GvZM02LgvshcRJLnFjYdrzjelMKuNynd/NNK3gLgTsFTGuIgPpz9r4rA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.731.0", + "@smithy/querystring-builder": "^4.0.0", + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url/node_modules/@aws-sdk/types": { + "version": "3.731.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.731.0.tgz", + "integrity": "sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url/node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@aws-sdk/util-locate-window": { "version": "3.693.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz", diff --git a/package.json b/package.json index cd9ec1870..45028a531 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@aws-sdk/client-secrets-manager": "^3.693.0", "@aws-sdk/client-ses": "^3.693.0", "@aws-sdk/credential-provider-node": "^3.693.0", + "@aws-sdk/s3-request-presigner": "^3.731.1", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", diff --git a/server/media/imgprox-media.js b/server/media/imgprox-media.js new file mode 100644 index 000000000..6bb8e7a19 --- /dev/null +++ b/server/media/imgprox-media.js @@ -0,0 +1,136 @@ +const path = require("path"); +require("dotenv").config({ + path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) +}); +const logger = require("../utils/logger"); +const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3"); +const { getSignedUrl } = require("@aws-sdk/s3-request-presigner"); +const crypto = require("crypto"); +const { InstanceRegion } = require("../utils/instanceMgr"); + +//TODO: Remove hardcoded values. +const imgproxyBaseUrl = process.env.IMGPROXY_BASE_URL || `https://d3ictiiutovkvi.cloudfront.net`; +const imgproxyKey = process.env.IMGPROXY_KEY || `secret`; +const imgproxySalt = process.env.IMGPROXY_SALT || `salt`; +const imgproxyDestinationBucket = process.env.IMGPROXY_DESTINATION_BUCKET || `imex-shop-media`; + +//Generate a signed upload link for the S3 bucket. +//All uploads must be going to the same shop and jobid. +exports.generateSignedUploadUrls = async (req, res) => { + const { filenames, bodyshopid, jobid } = req.body; + try { + logger.log("imgproxy-upload-start", "DEBUG", req.user?.email, jobid, { filenames, bodyshopid, jobid }); + + //TODO: Ensure that the user has access to the given bodyshopid. + //This can be done by querying associations, or, maintaining a REDIS cache of user permissions. + const hasAccess = true; //TODO: Ensure this is not hardcoded. + if (!hasAccess) { + res.send(403); + return; + } + + const signedUrls = []; + for (const filename of filenames) { + // TODO: Implement a different, unique file naming convention. + const key = GenerateKey({ bodyshopid, jobid, filename }); + const client = new S3Client({ region: InstanceRegion() }); + const command = new PutObjectCommand({ Bucket: imgproxyDestinationBucket, Key: key }); + const presignedUrl = await getSignedUrl(client, command, { expiresIn: 360 }); + signedUrls.push({ filename, presignedUrl }); + } + + logger.log("imgproxy-upload-success", "DEBUG", req.user?.email, jobid, { signedUrls }); + res.json({ + success: true, + signedUrls + }); + } catch (error) { + res.status(400).json({ + success: false, + message: error.message, + stack: error.stack + }); + logger.log("imgproxy-upload-error", "ERROR", req.user?.email, jobid, { + message: error.message, + stack: error.stack + }); + } +}; + +exports.getThumbnailUrls = async (req, res) => { + const { jobid } = req.body; + try { + //TODO: Query for all documents related to the job. + //Delayed as the key structure may change slightly from what it is currently and will require evaluating mobile components. + // const { data } = await client.query({ + // query: queries.GET_DOCUMENTS_BY_JOBID, + // variables: { jobid } + // }); + + //Mocked Keys. + const keys = [ + "shopid/jobid/test2.jpg-1737502469411", + "shopid/jobid/test2.jpg-1737502469411", + "shopid/jobid/movie.mov-1737504997897", + "shopid/jobid/pdf.pdf-1737504944260" + ]; + + const thumbResizeParams = `rs:fill:250:250:1/g:ce`; + const proxiedUrls = keys.map((key) => { + //Format to follow: + /////< base 64 URL encoded to image path> + + // Build the S3 path to the object. + const fullS3Path = `s3://${imgproxyDestinationBucket}/${key}`; + const base64UrlEncodedKeyString = base64UrlEncode(fullS3Path); + //Thumbnail Generation Block + const thumbProxyPath = `${thumbResizeParams}/${base64UrlEncodedKeyString}`; + const thumbHmacSalt = createHmacSha256(`${imgproxySalt}/${thumbProxyPath}`); + + //Full Size URL block + + const fullSizeProxyPath = `${base64UrlEncodedKeyString}`; + const fullSizeHmacSalt = createHmacSha256(`${imgproxySalt}/${fullSizeProxyPath}`); + + //If not a picture, we need to get a signed download link to the file using S3 (or cloudfront preferably) + + return { + originalUrl: `${imgproxyBaseUrl}/${fullSizeHmacSalt}/${fullSizeProxyPath}`, + thumbnailUrl: `${imgproxyBaseUrl}/${thumbHmacSalt}/${thumbProxyPath}` + }; + }); + + res.json({ proxiedUrls }); + //Iterate over them, build the link based on the media type, and return the array. + } catch (error) { + logger.log("imgproxy-get-proxied-urls-error", "ERROR", req.user?.email, jobid, { + message: error.message, + stack: error.stack + }); + res.status(400).json({ message: error.message, stack: error.stack }); + } +}; + +exports.getBillFiles = async (req, res) => { + //Givena bill ID, get the documents associated to it. +}; + +exports.downloadFiles = async (req, res) => { + //Given a series of document IDs or keys, generate a file (or a link) to download all images in bulk +}; + +exports.deleteFiles = async (req, res) => { + //Mark a file for deletion in s3. Lifecycle deletion will actually delete the copy in the future. + //Mark as deleted from the documents section of the database. +}; + +function GenerateKey({ bodyshopid, jobid, filename }) { + return `${bodyshopid}/${jobid}/${filename}-${Date.now()}`; +} + +function base64UrlEncode(str) { + return Buffer.from(str).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); +} +function createHmacSha256(data) { + return crypto.createHmac("sha256", imgproxyKey).update(data).digest("base64url"); +} diff --git a/server/routes/mediaRoutes.js b/server/routes/mediaRoutes.js index 699579bb9..c93dbed8a 100644 --- a/server/routes/mediaRoutes.js +++ b/server/routes/mediaRoutes.js @@ -1,6 +1,10 @@ const express = require("express"); const router = express.Router(); const { createSignedUploadURL, downloadFiles, renameKeys, deleteFiles } = require("../media/media"); +const { + generateSignedUploadUrls, + getThumbnailUrls +} = require("../media/imgprox-media"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); router.use(validateFirebaseIdTokenMiddleware); @@ -10,4 +14,7 @@ router.post("/download", downloadFiles); router.post("/rename", renameKeys); router.post("/delete", deleteFiles); +router.post("/proxy/sign", generateSignedUploadUrls); +router.post("/proxy/get", getThumbnailUrls); + module.exports = router; From 47fe1959b1b0773ffb38acd1bb2b1e4c5a3abeb7 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 5 Feb 2025 11:03:29 -0800 Subject: [PATCH 02/45] IO-3092 WIP on img proxy thumbnail generation. --- .../documents-upload-imgproxy.component.jsx | 123 ++++++++++++ .../documents-upload-imgproxy.utility.js | 181 ++++++++++++++++++ .../jobs-documents-gallery.component.jsx | 112 ++++++++++- server/graphql-client/queries.js | 38 +++- server/media/imgprox-media.js | 67 ++++--- server/routes/mediaRoutes.js | 9 +- 6 files changed, 489 insertions(+), 41 deletions(-) create mode 100644 client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx create mode 100644 client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx new file mode 100644 index 000000000..259ca5831 --- /dev/null +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx @@ -0,0 +1,123 @@ +import { UploadOutlined } from "@ant-design/icons"; +import { Progress, Result, Space, Upload } from "antd"; +import { useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; +import formatBytes from "../../utils/formatbytes"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; +import LockWrapperComponent from "../lock-wrapper/lock-wrapper.component"; +import { handleUpload } from "./documents-upload-imgproxy.utility.js"; + +const mapStateToProps = createStructuredSelector({ + currentUser: selectCurrentUser, + bodyshop: selectBodyshop +}); + +export function DocumentsUploadImgproxyComponent({ + children, + currentUser, + bodyshop, + jobId, + tagsArray, + billId, + callbackAfterUpload, + totalSize, + ignoreSizeLimit = false +}) { + const { t } = useTranslation(); + const [fileList, setFileList] = useState([]); + const notification = useNotification(); + + const pct = useMemo(() => { + return parseInt((totalSize / ((bodyshop && bodyshop.jobsizelimit) || 1)) * 100); + }, [bodyshop, totalSize]); + + if (pct > 100 && !ignoreSizeLimit) + return ( + + ); + + const handleDone = (uid) => { + setTimeout(() => { + setFileList((fileList) => fileList.filter((x) => x.uid !== uid)); + }, 2000); + }; + const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); + + return ( + { + if (f.event && f.event.percent === 100) handleDone(f.file.uid); + setFileList(f.fileList); + }} + beforeUpload={(file, fileList) => { + if (ignoreSizeLimit) return true; + const newFiles = fileList.reduce((acc, val) => acc + val.size, 0); + const shouldStopUpload = (totalSize + newFiles) / ((bodyshop && bodyshop.jobsizelimit) || 1) >= 1; + + //Check to see if old files plus newly uploaded ones will be too much. + if (shouldStopUpload) { + notification.open({ + key: "cannotuploaddocuments", + type: "error", + message: t("documents.labels.upload_limitexceeded_title"), + description: t("documents.labels.upload_limitexceeded") + }); + return Upload.LIST_IGNORE; + } + return true; + }} + customRequest={(ev) => + handleUpload( + ev, + { + bodyshop: bodyshop, + uploaded_by: currentUser.email, + jobId: jobId, + billId: billId, + tagsArray: tagsArray, + callback: callbackAfterUpload + }, + notification + ) + } + accept="audio/*, video/*, image/*, .pdf, .doc, .docx, .xls, .xlsx" + // showUploadList={false} + > + {children || ( + <> +

+ +

+

+ {t("documents.labels.dragtoupload")} +

+ {!ignoreSizeLimit && ( + + + + {t("documents.labels.usage", { + percent: pct, + used: formatBytes(totalSize), + total: formatBytes(bodyshop && bodyshop.jobsizelimit) + })} + + + )} + + )} +
+ ); +} + +export default connect(mapStateToProps, null)(DocumentsUploadImgproxyComponent); diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js new file mode 100644 index 000000000..f9dd2a193 --- /dev/null +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -0,0 +1,181 @@ +import axios from "axios"; +import exifr from "exifr"; +import i18n from "i18next"; +import { logImEXEvent } from "../../firebase/firebase.utils"; +import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries"; +import { axiosAuthInterceptorId } from "../../utils/CleanAxios"; +import client from "../../utils/GraphQLClient"; + +//Context: currentUserEmail, bodyshop, jobid, invoiceid + +//Required to prevent headers from getting set and rejected from Cloudinary. +var cleanAxios = axios.create(); +cleanAxios.interceptors.request.eject(axiosAuthInterceptorId); + +export const handleUpload = (ev, context, notification) => { + logImEXEvent("document_upload", { filetype: ev.file.type }); + + const { onError, onSuccess, onProgress } = ev; + const { bodyshop, jobId } = context; + + const fileName = ev.file.name || ev.filename; + + let key = replaceAccents(fileName).replace(/[^A-Z0-9.]+/gi, "_"); + let extension = fileName.split(".").pop(); + uploadToS3(key, extension, ev.file.type, ev.file, onError, onSuccess, onProgress, context, notification); +}; + +//Handles only 1 file at a time. +export const uploadToS3 = async ( + key, + extension, + fileType, + file, + onError, + onSuccess, + onProgress, + context, + notification +) => { + const { bodyshop, jobId, billId, uploaded_by, callback, tagsArray } = context; + + //Set variables for getting the signed URL. + let timestamp = Math.floor(Date.now() / 1000); + //Get the signed url. + + const signedURLResponse = await axios.post("/media/proxy/sign", { + filenames: [key], + bodyshopid: bodyshop.id, + jobid: jobId + }); + + if (signedURLResponse.status !== 200) { + if (onError) onError(signedURLResponse.statusText); + notification["error"]({ + message: i18n.t("documents.errors.getpresignurl", { + message: signedURLResponse.statusText + }) + }); + return; + } + + const { presignedUrl: preSignedUploadUrlToS3, key: s3Key } = signedURLResponse.data.signedUrls[0]; + + //Build request to end to cloudinary. + var options = { + // headers: { "X-Requested-With": "XMLHttpRequest" }, + onUploadProgress: (e) => { + if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); + } + }; + + // const formData = new FormData(); + // formData.append("file", file); + + // formData.append("upload_preset", upload_preset); + + // formData.append("api_key", import.meta.env.VITE_APP_CLOUDINARY_API_KEY); + // formData.append("public_id", public_id); + // formData.append("tags", tags); + // formData.append("timestamp", timestamp); + // formData.append("signature", signature); + + const cloudinaryUploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); + + //Insert the document with the matching key. + let takenat; + if (fileType.includes("image")) { + try { + const exif = await exifr.parse(file); + takenat = exif && exif.DateTimeOriginal; + } catch (error) { + console.log("Unable to parse image file for EXIF Data"); + } + } + + const documentInsert = await client.mutate({ + mutation: INSERT_NEW_DOCUMENT, + variables: { + docInput: [ + { + ...(jobId ? { jobid: jobId } : {}), + ...(billId ? { billid: billId } : {}), + uploaded_by: uploaded_by, + key: s3Key, + type: fileType, + extension: cloudinaryUploadResponse.data.format || extension, + bodyshopid: bodyshop.id, + size: cloudinaryUploadResponse.data.bytes || file.size, + takenat + } + ] + } + }); + if (!documentInsert.errors) { + if (onSuccess) + onSuccess({ + //TODO: Since this may go server side, we can just manage the state locally. + uid: documentInsert.data.insert_documents.returning[0].id, + name: documentInsert.data.insert_documents.returning[0].name, + status: "done", + key: documentInsert.data.insert_documents.returning[0].key + }); + notification.open({ + type: "success", + key: "docuploadsuccess", + message: i18n.t("documents.successes.insert") + }); + if (callback) { + callback(); + } + } else { + if (onError) onError(JSON.stringify(documentInsert.errors)); + notification["error"]({ + message: i18n.t("documents.errors.insert", { + message: JSON.stringify(documentInsert.errors) + }) + }); + return; + } +}; + +//Also needs to be updated in media JS and mobile app. +export function DetermineFileType(filetype) { + if (!filetype) return "auto"; + else if (filetype.startsWith("image")) return "image"; + else if (filetype.startsWith("video")) return "video"; + else if (filetype.startsWith("application/pdf")) return "image"; + else if (filetype.startsWith("application")) return "raw"; + + return "auto"; +} + +function replaceAccents(str) { + // Verifies if the String has accents and replace them + if (str.search(/[\xC0-\xFF]/g) > -1) { + str = str + .replace(/[\xC0-\xC5]/g, "A") + .replace(/[\xC6]/g, "AE") + .replace(/[\xC7]/g, "C") + .replace(/[\xC8-\xCB]/g, "E") + .replace(/[\xCC-\xCF]/g, "I") + .replace(/[\xD0]/g, "D") + .replace(/[\xD1]/g, "N") + .replace(/[\xD2-\xD6\xD8]/g, "O") + .replace(/[\xD9-\xDC]/g, "U") + .replace(/[\xDD]/g, "Y") + .replace(/[\xDE]/g, "P") + .replace(/[\xE0-\xE5]/g, "a") + .replace(/[\xE6]/g, "ae") + .replace(/[\xE7]/g, "c") + .replace(/[\xE8-\xEB]/g, "e") + .replace(/[\xEC-\xEF]/g, "i") + .replace(/[\xF1]/g, "n") + .replace(/[\xF2-\xF6\xF8]/g, "o") + .replace(/[\xF9-\xFC]/g, "u") + .replace(/[\xFE]/g, "p") + .replace(/[\xFD\xFF]/g, "y"); + } + + return str; +} diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index 0dcc18855..27af3defe 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -1,24 +1,25 @@ import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Col, Row, Space } from "antd"; +import axios from "axios"; import React, { useEffect, useState } from "react"; import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; +import Lightbox from "react-image-lightbox"; +import "react-image-lightbox/style.css"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import DocumentsUploadImgproxyComponent from "../documents-upload-imgproxy/documents-upload-imgproxy.component"; import DocumentsUploadComponent from "../documents-upload/documents-upload.component"; import { DetermineFileType } from "../documents-upload/documents-upload.utility"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; +import UpsellComponent, { upsellEnum } from "../upsell/upsell.component"; import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility"; import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component"; import JobsDocumentsGalleryReassign from "./jobs-document-gallery.reassign.component"; import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component"; import JobsDocumentsGallerySelectAllComponent from "./jobs-documents-gallery.selectall.component"; -import Lightbox from "react-image-lightbox"; -import "react-image-lightbox/style.css"; -import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; - -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import UpsellComponent, { upsellEnum } from "../upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); @@ -114,6 +115,89 @@ function JobsDocumentsComponent({ ); setgalleryImages(documents); }, [data, setgalleryImages, t]); + + const getProxiedUrls = async () => { + const result = await axios.post("/media/proxy/thumbnails", { jobid: jobId }); + + result.data.forEach((r) => console.log(r.thumbnailUrl)); + + let documents = result.data.reduce( + (acc, value) => { + const fileType = DetermineFileType(value.type); + if (value.type.startsWith("image")) { + acc.images.push({ + src: value.thumbnailUrl, + fullsize: value.originalUrl, + height: 225, + width: 225, + isSelected: false, + key: value.key, + extension: value.extension, + id: value.id, + type: value.type, + size: value.size, + tags: [{ value: value.type, title: value.type }] + }); + } else { + let thumb; + switch (fileType) { + case "raw": + thumb = `${window.location.origin}/file.png`; + break; + default: + thumb = GenerateThumbUrl(value); + break; + } + + const fileName = value.key.split("/").pop(); + acc.other.push({ + source: value.originalUrlViaProxyPath, + src: value.thumbnailUrl, + fullsize: value.presignedGetUrl, + tags: [ + { + value: fileName, + title: fileName + }, + + { value: value.type, title: value.type }, + ...(value.bill + ? [ + { + value: value.bill.vendor.name, + title: t("vendors.fields.name") + }, + { value: value.bill.date, title: t("bills.fields.date") }, + { + value: value.bill.invoice_number, + title: t("bills.fields.invoice_number") + } + ] + : []) + ], + height: 225, + width: 225, + isSelected: false, + extension: value.extension, + key: value.key, + id: value.id, + type: value.type, + size: value.size + }); + } + + return acc; + }, + { images: [], other: [] } + ); + console.log("*** ~ file: jobs-documents-gallery.component.jsx:198 ~ getProxiedUrls ~ documents:", documents); + setgalleryImages(documents); + }; + + // useEffect(() => { + // getProxiedUrls(); + // }, [galleryImages]); + const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); return ( @@ -138,6 +222,18 @@ function JobsDocumentsComponent({ )} + + + + + + { const client = new S3Client({ region: InstanceRegion() }); const command = new PutObjectCommand({ Bucket: imgproxyDestinationBucket, Key: key }); const presignedUrl = await getSignedUrl(client, command, { expiresIn: 360 }); - signedUrls.push({ filename, presignedUrl }); + signedUrls.push({ filename, presignedUrl, key }); } logger.log("imgproxy-upload-success", "DEBUG", req.user?.email, jobid, { signedUrls }); @@ -58,30 +61,25 @@ exports.generateSignedUploadUrls = async (req, res) => { }; exports.getThumbnailUrls = async (req, res) => { - const { jobid } = req.body; + const { jobid, billid } = req.body; + try { //TODO: Query for all documents related to the job. //Delayed as the key structure may change slightly from what it is currently and will require evaluating mobile components. - // const { data } = await client.query({ - // query: queries.GET_DOCUMENTS_BY_JOBID, - // variables: { jobid } - // }); - //Mocked Keys. - const keys = [ - "shopid/jobid/test2.jpg-1737502469411", - "shopid/jobid/test2.jpg-1737502469411", - "shopid/jobid/movie.mov-1737504997897", - "shopid/jobid/pdf.pdf-1737504944260" - ]; + const client = req.userGraphQLClient; + const data = await client.request(GET_DOCUMENTS_BY_JOB, { jobId: jobid }); const thumbResizeParams = `rs:fill:250:250:1/g:ce`; - const proxiedUrls = keys.map((key) => { + const s3client = new S3Client({ region: InstanceRegion() }); + const proxiedUrls = []; + + for (const document of data.documents) { //Format to follow: /////< base 64 URL encoded to image path> // Build the S3 path to the object. - const fullS3Path = `s3://${imgproxyDestinationBucket}/${key}`; + const fullS3Path = `s3://${imgproxyDestinationBucket}/${document.key}`; const base64UrlEncodedKeyString = base64UrlEncode(fullS3Path); //Thumbnail Generation Block const thumbProxyPath = `${thumbResizeParams}/${base64UrlEncodedKeyString}`; @@ -92,15 +90,30 @@ exports.getThumbnailUrls = async (req, res) => { const fullSizeProxyPath = `${base64UrlEncodedKeyString}`; const fullSizeHmacSalt = createHmacSha256(`${imgproxySalt}/${fullSizeProxyPath}`); - //If not a picture, we need to get a signed download link to the file using S3 (or cloudfront preferably) + const s3Props = {}; + if (!document.type.startsWith("image")) { + //If not a picture, we need to get a signed download link to the file using S3 (or cloudfront preferably) + const command = new GetObjectCommand({ Bucket: imgproxyDestinationBucket, Key: document.key }); + const presignedGetUrl = await getSignedUrl(s3client, command, { expiresIn: 360 }); + s3Props.presignedGetUrl = presignedGetUrl; - return { + const originalProxyPath = `raw:1/${base64UrlEncodedKeyString}`; + const originalHmacSalt = createHmacSha256(`${imgproxySalt}/${originalProxyPath}`); + s3Props.originalUrlViaProxyPath = `${imgproxyBaseUrl}/${originalHmacSalt}/${originalProxyPath}`; + } + + proxiedUrls.push({ originalUrl: `${imgproxyBaseUrl}/${fullSizeHmacSalt}/${fullSizeProxyPath}`, - thumbnailUrl: `${imgproxyBaseUrl}/${thumbHmacSalt}/${thumbProxyPath}` - }; - }); + thumbnailUrl: `${imgproxyBaseUrl}/${thumbHmacSalt}/${thumbProxyPath}`, + fullS3Path, + base64UrlEncodedKeyString, + thumbProxyPath, + ...s3Props, + ...document + }); + } - res.json({ proxiedUrls }); + res.json(proxiedUrls); //Iterate over them, build the link based on the media type, and return the array. } catch (error) { logger.log("imgproxy-get-proxied-urls-error", "ERROR", req.user?.email, jobid, { @@ -124,8 +137,12 @@ exports.deleteFiles = async (req, res) => { //Mark as deleted from the documents section of the database. }; +//Gerneate a key for the s3 bucket by popping off the extension, add a timestamp, and add back the extension. +//This is to prevent any collisions/duplicates in the bucket. function GenerateKey({ bodyshopid, jobid, filename }) { - return `${bodyshopid}/${jobid}/${filename}-${Date.now()}`; + let nameArray = filename.split("."); + let extension = nameArray.pop(); + return `${bodyshopid}/${jobid}/${nameArray.join(".")}-${Date.now()}.${extension}`; } function base64UrlEncode(str) { diff --git a/server/routes/mediaRoutes.js b/server/routes/mediaRoutes.js index c93dbed8a..9718b85d1 100644 --- a/server/routes/mediaRoutes.js +++ b/server/routes/mediaRoutes.js @@ -1,13 +1,12 @@ const express = require("express"); const router = express.Router(); const { createSignedUploadURL, downloadFiles, renameKeys, deleteFiles } = require("../media/media"); -const { - generateSignedUploadUrls, - getThumbnailUrls -} = require("../media/imgprox-media"); +const { generateSignedUploadUrls, getThumbnailUrls } = require("../media/imgprox-media"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); +const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware"); router.use(validateFirebaseIdTokenMiddleware); +router.use(withUserGraphQLClientMiddleware); router.post("/sign", createSignedUploadURL); router.post("/download", downloadFiles); @@ -15,6 +14,6 @@ router.post("/rename", renameKeys); router.post("/delete", deleteFiles); router.post("/proxy/sign", generateSignedUploadUrls); -router.post("/proxy/get", getThumbnailUrls); +router.post("/proxy/thumbnails", getThumbnailUrls); module.exports = router; From fbb473941cfefd3d71c005be844c8f1de0863de6 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 6 Feb 2025 14:37:16 -0800 Subject: [PATCH 03/45] IO-3092 implement backwards compatibility for Cloudinary documents. --- .../documents-upload-imgproxy.utility.js | 13 ++------ .../jobs-documents-gallery.component.jsx | 7 ++--- server.js | 2 +- server/media/imgprox-media.js | 31 ++++++++++++------- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js index f9dd2a193..280469669 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -20,8 +20,9 @@ export const handleUpload = (ev, context, notification) => { const fileName = ev.file.name || ev.filename; - let key = replaceAccents(fileName).replace(/[^A-Z0-9.]+/gi, "_"); let extension = fileName.split(".").pop(); + let key = `${bodyshop.id}/${jobId}/${replaceAccents(fileName).replace(/[^A-Z0-9]+/gi, "_")}-${new Date().getTime()}.${extension}`; + uploadToS3(key, extension, ev.file.type, ev.file, onError, onSuccess, onProgress, context, notification); }; @@ -69,16 +70,6 @@ export const uploadToS3 = async ( } }; - // const formData = new FormData(); - // formData.append("file", file); - - // formData.append("upload_preset", upload_preset); - - // formData.append("api_key", import.meta.env.VITE_APP_CLOUDINARY_API_KEY); - // formData.append("public_id", public_id); - // formData.append("tags", tags); - // formData.append("timestamp", timestamp); - // formData.append("signature", signature); const cloudinaryUploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index 27af3defe..a3d667a35 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -118,9 +118,6 @@ function JobsDocumentsComponent({ const getProxiedUrls = async () => { const result = await axios.post("/media/proxy/thumbnails", { jobid: jobId }); - - result.data.forEach((r) => console.log(r.thumbnailUrl)); - let documents = result.data.reduce( (acc, value) => { const fileType = DetermineFileType(value.type); @@ -195,8 +192,8 @@ function JobsDocumentsComponent({ }; // useEffect(() => { - // getProxiedUrls(); - // }, [galleryImages]); + // if (data) getProxiedUrls(); + // }, [data]); const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); diff --git a/server.js b/server.js index ef480a7ea..b70b4e7cd 100644 --- a/server.js +++ b/server.js @@ -293,7 +293,7 @@ const applySocketIO = async ({ server, app }) => { */ const main = async () => { const app = express(); - const port = process.env.PORT || 5000; + const port = process.env.PORT || 4000; const server = http.createServer(app); diff --git a/server/media/imgprox-media.js b/server/media/imgprox-media.js index 065de42da..2ee4d5d5b 100644 --- a/server/media/imgprox-media.js +++ b/server/media/imgprox-media.js @@ -9,13 +9,10 @@ const crypto = require("crypto"); const { InstanceRegion } = require("../utils/instanceMgr"); const { GET_DOCUMENTS_BY_JOB } = require("../graphql-client/queries"); //TODO: Remove hardcoded values. -const imgproxyBaseUrl = - process.env.IMGPROXY_BASE_URL || - // `https://k2car6fha7w5cbgry3j2td56ra0kdmwn.lambda-url.ca-central-1.on.aws` || - `https://d3ictiiutovkvi.cloudfront.net`; -const imgproxyKey = process.env.IMGPROXY_KEY || `secret`; -const imgproxySalt = process.env.IMGPROXY_SALT || `salt`; -const imgproxyDestinationBucket = process.env.IMGPROXY_DESTINATION_BUCKET || `imex-shop-media`; +const imgproxyBaseUrl = process.env.IMGPROXY_BASE_URL; +const imgproxyKey = process.env.IMGPROXY_KEY; +const imgproxySalt = process.env.IMGPROXY_SALT; +const imgproxyDestinationBucket = process.env.IMGPROXY_DESTINATION_BUCKET; //Generate a signed upload link for the S3 bucket. //All uploads must be going to the same shop and jobid. @@ -35,7 +32,7 @@ exports.generateSignedUploadUrls = async (req, res) => { const signedUrls = []; for (const filename of filenames) { // TODO: Implement a different, unique file naming convention. - const key = GenerateKey({ bodyshopid, jobid, filename }); + const key = filename; //GenerateKey({ bodyshopid, jobid, filename }); const client = new S3Client({ region: InstanceRegion() }); const command = new PutObjectCommand({ Bucket: imgproxyDestinationBucket, Key: key }); const presignedUrl = await getSignedUrl(client, command, { expiresIn: 360 }); @@ -76,10 +73,17 @@ exports.getThumbnailUrls = async (req, res) => { for (const document of data.documents) { //Format to follow: - /////< base 64 URL encoded to image path> + /////< base 64 URL encoded to image path> + //When working with documents from Cloudinary, the URL does not include the extension. + let key; + if (/\.[^/.]+$/.test(document.key)) { + key = document.key; + } else { + key = `${document.key}.${document.extension.toLowerCase()}`; + } // Build the S3 path to the object. - const fullS3Path = `s3://${imgproxyDestinationBucket}/${document.key}`; + const fullS3Path = `s3://${imgproxyDestinationBucket}/${key}`; const base64UrlEncodedKeyString = base64UrlEncode(fullS3Path); //Thumbnail Generation Block const thumbProxyPath = `${thumbResizeParams}/${base64UrlEncodedKeyString}`; @@ -93,7 +97,10 @@ exports.getThumbnailUrls = async (req, res) => { const s3Props = {}; if (!document.type.startsWith("image")) { //If not a picture, we need to get a signed download link to the file using S3 (or cloudfront preferably) - const command = new GetObjectCommand({ Bucket: imgproxyDestinationBucket, Key: document.key }); + const command = new GetObjectCommand({ + Bucket: imgproxyDestinationBucket, + Key: key + }); const presignedGetUrl = await getSignedUrl(s3client, command, { expiresIn: 360 }); s3Props.presignedGetUrl = presignedGetUrl; @@ -142,7 +149,7 @@ exports.deleteFiles = async (req, res) => { function GenerateKey({ bodyshopid, jobid, filename }) { let nameArray = filename.split("."); let extension = nameArray.pop(); - return `${bodyshopid}/${jobid}/${nameArray.join(".")}-${Date.now()}.${extension}`; + return `${bodyshopid}/${jobid}/${nameArray.join(".")}-${Date.now()}`; } function base64UrlEncode(str) { From b069b6bc4cb5652064f69d8d1f7f3380f48c316e Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 7 Feb 2025 13:33:22 -0800 Subject: [PATCH 04/45] IO-3092 Implement delete, move and download on image proxy. Add imgproxy based components. --- .../documents-upload-imgproxy.utility.js | 34 +- .../jobs-documents-gallery.component.jsx | 96 +--- .../jobs-documents-gallery.container.jsx | 52 +- ...nt-imgproxy-gallery.download.component.jsx | 78 +++ ...nt-imgproxy-gallery.reassign.component.jsx | 129 +++++ ...s-documents-imgproxy-gallery.component.jsx | 247 +++++++++ ...s-documents-imgproxy-gallery.container.jsx | 29 + ...ents-imgproxy-gallery.delete.component.jsx | 68 +++ ...ts-imgproxy-gallery.external.component.jsx | 50 ++ ...s-imgproxy-gallery.selectall.component.jsx | 55 ++ ...obs-documents-imgproxy-gallery.styles.scss | 10 + .../temporary-docs.component.jsx | 19 +- package-lock.json | 511 +++++++++++++++++- package.json | 2 + server/graphql-client/queries.js | 27 + server/media/imgprox-media.js | 233 +++++++- server/routes/mediaRoutes.js | 15 +- 17 files changed, 1491 insertions(+), 164 deletions(-) create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx create mode 100644 client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.styles.scss diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js index 280469669..184cf86c6 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -38,13 +38,10 @@ export const uploadToS3 = async ( context, notification ) => { - const { bodyshop, jobId, billId, uploaded_by, callback, tagsArray } = context; + const { bodyshop, jobId, billId, uploaded_by, callback } = context; - //Set variables for getting the signed URL. - let timestamp = Math.floor(Date.now() / 1000); - //Get the signed url. - - const signedURLResponse = await axios.post("/media/proxy/sign", { + //Get the signed url allowing us to PUT to S3. + const signedURLResponse = await axios.post("/media/imgproxy/sign", { filenames: [key], bodyshopid: bodyshop.id, jobid: jobId @@ -60,19 +57,16 @@ export const uploadToS3 = async ( return; } + //Key should be same as we provided to maintain backwards compatibility. const { presignedUrl: preSignedUploadUrlToS3, key: s3Key } = signedURLResponse.data.signedUrls[0]; - //Build request to end to cloudinary. var options = { - // headers: { "X-Requested-With": "XMLHttpRequest" }, onUploadProgress: (e) => { if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); } }; - - const cloudinaryUploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); - + const s3UploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); //Insert the document with the matching key. let takenat; if (fileType.includes("image")) { @@ -94,18 +88,18 @@ export const uploadToS3 = async ( uploaded_by: uploaded_by, key: s3Key, type: fileType, - extension: cloudinaryUploadResponse.data.format || extension, + extension: s3UploadResponse.data.format || extension, bodyshopid: bodyshop.id, - size: cloudinaryUploadResponse.data.bytes || file.size, + size: s3UploadResponse.data.bytes || file.size, //Leftover from Cloudinary. We don't do any optimization on upload, so it will always be file.size. takenat } ] } }); + if (!documentInsert.errors) { if (onSuccess) onSuccess({ - //TODO: Since this may go server side, we can just manage the state locally. uid: documentInsert.data.insert_documents.returning[0].id, name: documentInsert.data.insert_documents.returning[0].name, status: "done", @@ -130,17 +124,6 @@ export const uploadToS3 = async ( } }; -//Also needs to be updated in media JS and mobile app. -export function DetermineFileType(filetype) { - if (!filetype) return "auto"; - else if (filetype.startsWith("image")) return "image"; - else if (filetype.startsWith("video")) return "video"; - else if (filetype.startsWith("application/pdf")) return "image"; - else if (filetype.startsWith("application")) return "raw"; - - return "auto"; -} - function replaceAccents(str) { // Verifies if the String has accents and replace them if (str.search(/[\xC0-\xFF]/g) > -1) { @@ -167,6 +150,5 @@ function replaceAccents(str) { .replace(/[\xFE]/g, "p") .replace(/[\xFD\xFF]/g, "y"); } - return str; } diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index a3d667a35..fdc919320 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -1,7 +1,6 @@ import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Col, Row, Space } from "antd"; -import axios from "axios"; -import React, { useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import Lightbox from "react-image-lightbox"; @@ -9,7 +8,6 @@ import "react-image-lightbox/style.css"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import DocumentsUploadImgproxyComponent from "../documents-upload-imgproxy/documents-upload-imgproxy.component"; import DocumentsUploadComponent from "../documents-upload/documents-upload.component"; import { DetermineFileType } from "../documents-upload/documents-upload.utility"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; @@ -116,85 +114,6 @@ function JobsDocumentsComponent({ setgalleryImages(documents); }, [data, setgalleryImages, t]); - const getProxiedUrls = async () => { - const result = await axios.post("/media/proxy/thumbnails", { jobid: jobId }); - let documents = result.data.reduce( - (acc, value) => { - const fileType = DetermineFileType(value.type); - if (value.type.startsWith("image")) { - acc.images.push({ - src: value.thumbnailUrl, - fullsize: value.originalUrl, - height: 225, - width: 225, - isSelected: false, - key: value.key, - extension: value.extension, - id: value.id, - type: value.type, - size: value.size, - tags: [{ value: value.type, title: value.type }] - }); - } else { - let thumb; - switch (fileType) { - case "raw": - thumb = `${window.location.origin}/file.png`; - break; - default: - thumb = GenerateThumbUrl(value); - break; - } - - const fileName = value.key.split("/").pop(); - acc.other.push({ - source: value.originalUrlViaProxyPath, - src: value.thumbnailUrl, - fullsize: value.presignedGetUrl, - tags: [ - { - value: fileName, - title: fileName - }, - - { value: value.type, title: value.type }, - ...(value.bill - ? [ - { - value: value.bill.vendor.name, - title: t("vendors.fields.name") - }, - { value: value.bill.date, title: t("bills.fields.date") }, - { - value: value.bill.invoice_number, - title: t("bills.fields.invoice_number") - } - ] - : []) - ], - height: 225, - width: 225, - isSelected: false, - extension: value.extension, - key: value.key, - id: value.id, - type: value.type, - size: value.size - }); - } - - return acc; - }, - { images: [], other: [] } - ); - console.log("*** ~ file: jobs-documents-gallery.component.jsx:198 ~ getProxiedUrls ~ documents:", documents); - setgalleryImages(documents); - }; - - // useEffect(() => { - // if (data) getProxiedUrls(); - // }, [data]); - const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); return ( @@ -218,19 +137,6 @@ function JobsDocumentsComponent({ )} - - - - - - - ; if (error) return ; - return ( - - ); + if (useImgProxy) { + return ( + + ); + } else { + return ( + + ); + } } diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx new file mode 100644 index 000000000..2d649bcc9 --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx @@ -0,0 +1,78 @@ +import { Button, Space } from "antd"; +import axios from "axios"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { logImEXEvent } from "../../firebase/firebase.utils"; +import cleanAxios from "../../utils/CleanAxios"; +import formatBytes from "../../utils/formatbytes"; +//import yauzl from "yauzl"; + +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyDownloadButton); + +export function JobsDocumentsImgproxyDownloadButton({ bodyshop, galleryImages, identifier }) { + const { t } = useTranslation(); + const [download, setDownload] = useState(null); + const [loading, setLoading] = useState(false); + + const imagesToDownload = [ + ...galleryImages.images.filter((image) => image.isSelected), + ...galleryImages.other.filter((image) => image.isSelected) + ]; + + function downloadProgress(progressEvent) { + setDownload((currentDownloadState) => { + return { + downloaded: progressEvent.loaded || 0, + speed: (progressEvent.loaded || 0) - ((currentDownloadState && currentDownloadState.downloaded) || 0) + }; + }); + } + function standardMediaDownload(bufferData) { + const a = document.createElement("a"); + const url = window.URL.createObjectURL(new Blob([bufferData])); + a.href = url; + a.download = `${identifier || "documents"}.zip`; + a.click(); + } + const handleDownload = async () => { + logImEXEvent("jobs_documents_download"); + setLoading(true); + const zipUrl = await axios({ + url: "/media/imgproxy/download", + method: "POST", + data: { documentids: imagesToDownload.map((_) => _.id) } + }); + + const theDownloadedZip = await cleanAxios({ + url: zipUrl.data.url, + method: "GET", + responseType: "arraybuffer", + onDownloadProgress: downloadProgress + }); + setLoading(false); + setDownload(null); + + standardMediaDownload(theDownloadedZip.data); + }; + + return ( + <> + + + ); +} diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx new file mode 100644 index 000000000..19b7d9352 --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx @@ -0,0 +1,129 @@ +import { useApolloClient } from "@apollo/client"; +import { Button, Form, Popover, Space } from "antd"; +import axios from "axios"; +import { useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import { GET_DOC_SIZE_BY_JOB } from "../../graphql/documents.queries.js"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import JobSearchSelect from "../job-search-select/job-search-select.component.jsx"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyGalleryReassign); + +export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages, callback }) { + const { t } = useTranslation(); + const [form] = Form.useForm(); + const notification = useNotification(); + + const selectedImages = useMemo(() => { + return [ + ...galleryImages.images.filter((image) => image.isSelected), + ...galleryImages.other.filter((image) => image.isSelected) + ]; + }, [galleryImages]); + const client = useApolloClient(); + const [open, setOpen] = useState(false); + const [loading, setLoading] = useState(false); + + const handleFinish = async ({ jobid }) => { + setLoading(true); + + //Check to see if the space remaining on the new job is sufficient. If it isn't cancel this. + const newJobData = await client.query({ + query: GET_DOC_SIZE_BY_JOB, + variables: { jobId: jobid } + }); + + const transferedDocSizeTotal = selectedImages.reduce((acc, val) => acc + val.size, 0); + + const shouldPreventTransfer = + bodyshop.jobsizelimit - newJobData.data.documents_aggregate.aggregate.sum.size < transferedDocSizeTotal; + + if (shouldPreventTransfer) { + notification.open({ + key: "cannotuploaddocuments", + type: "error", + message: t("documents.labels.reassign_limitexceeded_title"), + description: t("documents.labels.reassign_limitexceeded") + }); + setLoading(false); + return; + } + + const res = await axios.post("/media/imgproxy/rename", { + tojobid: jobid, + documents: selectedImages.map((i) => { + //Need to check if the current key folder is null, or another job. + const currentKeys = i.key.split("/"); + currentKeys[1] = jobid; + currentKeys.join("/"); + return { + id: i.id, + from: i.key, + to: currentKeys.join("/"), + extension: i.extension, + type: i.type + }; + }) + }); + //Add in confirmation & errors. + if (callback) callback(); + + if (res.errors) { + notification["error"]({ + message: t("documents.errors.updating", { + message: JSON.stringify(res.errors) + }) + }); + } + if (!res.mutationResult?.errors) { + notification["success"]({ + message: t("documents.successes.updated") + }); + } + setOpen(false); + setLoading(false); + }; + + const popContent = ( +
+
+ + + +
+ + + + +
+ ); + + return ( + + + + ); +} diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx new file mode 100644 index 000000000..0a9beacc1 --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx @@ -0,0 +1,247 @@ +import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; +import { Button, Card, Col, Row, Space, Typography } from "antd"; +import axios from "axios"; +import { useEffect, useState } from "react"; +import { Gallery } from "react-grid-gallery"; +import { useTranslation } from "react-i18next"; +import Lightbox from "react-image-lightbox"; +import "react-image-lightbox/style.css"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import DocumentsUploadImgproxyComponent from "../documents-upload-imgproxy/documents-upload-imgproxy.component"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; +import UpsellComponent, { upsellEnum } from "../upsell/upsell.component"; +import JobsDocumentsDownloadButton from "./jobs-document-imgproxy-gallery.download.component"; +import JobsDocumentsGalleryReassign from "./jobs-document-imgproxy-gallery.reassign.component"; +import JobsDocumentsDeleteButton from "./jobs-documents-imgproxy-gallery.delete.component"; +import JobsDocumentsGallerySelectAllComponent from "./jobs-documents-imgproxy-gallery.selectall.component"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({}); + +function JobsDocumentsImgproxyComponent({ + bodyshop, + data, + jobId, + refetch, + billId, + billsCallback, + totalSize, + downloadIdentifier, + ignoreSizeLimit +}) { + const [galleryImages, setgalleryImages] = useState({ images: [], other: [] }); + const { t } = useTranslation(); + const [modalState, setModalState] = useState({ open: false, index: 0 }); + + const fetchThumbnails = async () => { + const result = await axios.post("/media/imgproxy/thumbnails", { jobid: jobId }); + let documents = result.data.reduce( + (acc, value) => { + if (value.type.startsWith("image")) { + acc.images.push({ + src: value.thumbnailUrl, + fullsize: value.originalUrl, + height: 225, + width: 225, + isSelected: false, + key: value.key, + extension: value.extension, + id: value.id, + type: value.type, + size: value.size, + tags: [{ value: value.type, title: value.type }] + }); + } else { + const fileName = value.key.split("/").pop(); + acc.other.push({ + source: value.originalUrlViaProxyPath, + src: value.thumbnailUrl, + fullsize: value.presignedGetUrl, + tags: [ + { + value: fileName, + title: fileName + }, + + { value: value.type, title: value.type }, + ...(value.bill + ? [ + { + value: value.bill.vendor.name, + title: t("vendors.fields.name") + }, + { value: value.bill.date, title: t("bills.fields.date") }, + { + value: value.bill.invoice_number, + title: t("bills.fields.invoice_number") + } + ] + : []) + ], + height: 225, + width: 225, + isSelected: false, + extension: value.extension, + key: value.key, + id: value.id, + type: value.type, + size: value.size + }); + } + return acc; + }, + { images: [], other: [] } + ); + setgalleryImages(documents); + }; + useEffect(() => { + if (data) { + fetchThumbnails(); + } + }, [data, setgalleryImages, t]); + + const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); + const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); + return ( +
+ IMG PROXY COMPONENTS (DELETE ME) + + + + + + + + {!billId && } + + + {!hasMediaAccess && ( + + + + + + )} + + + + + + {hasMediaAccess && !hasMobileAccess && ( + + + + + + )} + + + { + setModalState({ open: true, index: index }); + // window.open( + // item.fullsize, + // "_blank", + // "toolbar=0,location=0,menubar=0" + // ); + }} + onSelect={(index, image) => { + setgalleryImages({ + ...galleryImages, + images: galleryImages.images.map((g, idx) => + index === idx ? { ...g, isSelected: !g.isSelected } : g + ) + }); + }} + /> + + + + + { + return { + backgroundImage: , + height: "100%", + width: "100%", + cursor: "pointer" + }; + }} + onClick={(index) => { + window.open(galleryImages.other[index].source, "_blank", "toolbar=0,location=0,menubar=0"); + }} + onSelect={(index) => { + setgalleryImages({ + ...galleryImages, + other: galleryImages.other.map((g, idx) => (index === idx ? { ...g, isSelected: !g.isSelected } : g)) + }); + }} + /> + + + {modalState.open && ( + { + const newWindow = window.open( + `${window.location.protocol}//${window.location.host}/edit?documentId=${ + galleryImages.images[modalState.index].id + }`, + "_blank", + "noopener,noreferrer" + ); + if (newWindow) newWindow.opener = null; + }} + /> + ]} + mainSrc={galleryImages.images[modalState.index].fullsize} + nextSrc={galleryImages.images[(modalState.index + 1) % galleryImages.images.length].fullsize} + prevSrc={ + galleryImages.images[(modalState.index + galleryImages.images.length - 1) % galleryImages.images.length] + .fullsize + } + onCloseRequest={() => setModalState({ open: false, index: 0 })} + onMovePrevRequest={() => + setModalState({ + ...modalState, + index: (modalState.index + galleryImages.images.length - 1) % galleryImages.images.length + }) + } + onMoveNextRequest={() => + setModalState({ + ...modalState, + index: (modalState.index + 1) % galleryImages.images.length + }) + } + /> + )} + +
+ ); +} + +export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyComponent); diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx new file mode 100644 index 000000000..50dd4bbe9 --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx @@ -0,0 +1,29 @@ +import { useQuery } from "@apollo/client"; +import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries"; +import AlertComponent from "../alert/alert.component"; +import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +import JobDocuments from "./jobs-documents-imgproxy-gallery.component"; + +export default function JobsDocumentsImgproxyContainer({ jobId, billId, documentsList, billsCallback }) { + const { loading, error, data, refetch } = useQuery(GET_DOCUMENTS_BY_JOB, { + variables: { jobId: jobId }, + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + skip: !!billId + }); + + if (loading) return ; + if (error) return ; + + return ( + + ); +} diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx new file mode 100644 index 000000000..51ebfbf2b --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx @@ -0,0 +1,68 @@ +import { QuestionCircleOutlined } from "@ant-design/icons"; +import { Button, Popconfirm } from "antd"; +import axios from "axios"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { logImEXEvent } from "../../firebase/firebase.utils.js"; +import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +//Context: currentUserEmail, bodyshop, jobid, invoiceid + +export default function JobsDocumentsImgproxyDeleteButton({ galleryImages, deletionCallback }) { + const { t } = useTranslation(); + const notification = useNotification(); + + const imagesToDelete = [ + ...galleryImages.images.filter((image) => image.isSelected), + ...galleryImages.other.filter((image) => image.isSelected) + ]; + const [loading, setLoading] = useState(false); + + const handleDelete = async () => { + logImEXEvent("job_documents_delete", { count: imagesToDelete.length }); + try { + setLoading(true); + const res = await axios.post("/media/imgproxy/delete", { + ids: imagesToDelete.map((d) => d.id) + }); + + if (res.data.error) { + notification["error"]({ + message: t("documents.errors.deleting", { + error: JSON.stringify(res.data.error.response.errors) + }) + }); + } else { + notification.open({ + key: "docdeletedsuccesfully", + type: "success", + message: t("documents.successes.delete") + }); + + if (deletionCallback) deletionCallback(); + } + } catch (error) { + notification["error"]({ + message: t("documents.errors.deleting", { + error: error.message + }) + }); + } + setLoading(false); + }; + + return ( + } + onConfirm={handleDelete} + title={t("documents.labels.confirmdelete")} + okText={t("general.actions.delete")} + okButtonProps={{ danger: true }} + cancelText={t("general.actions.cancel")} + > + + + ); +} diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx new file mode 100644 index 000000000..ed89cc1ca --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx @@ -0,0 +1,50 @@ +import { useEffect } from "react"; +import { Gallery } from "react-grid-gallery"; +import { useTranslation } from "react-i18next"; +import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents-imgproxy.utility"; + +function JobsDocumentImgproxyGalleryExternal({ + data, + + externalMediaState +}) { + const [galleryImages, setgalleryImages] = externalMediaState; + const { t } = useTranslation(); + + useEffect(() => { + let documents = data.reduce((acc, value) => { + if (value.type.startsWith("image")) { + acc.push({ + fullsize: GenerateSrcUrl(value), + src: GenerateThumbUrl(value), + thumbnailHeight: 225, + thumbnailWidth: 225, + isSelected: false, + key: value.key, + extension: value.extension, + id: value.id, + type: value.type, + tags: [{ value: value.type, title: value.type }], + size: value.size + }); + } + + return acc; + }, []); + setgalleryImages(documents); + }, [data, setgalleryImages, t]); + + return ( +
+ { + setgalleryImages(galleryImages.map((g, idx) => (index === idx ? { ...g, isSelected: !g.isSelected } : g))); + }} + /> +
+ ); +} + +export default JobsDocumentImgproxyGalleryExternal; diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx new file mode 100644 index 000000000..25162e7d0 --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx @@ -0,0 +1,55 @@ +import { Button, Space } from "antd"; +import { useTranslation } from "react-i18next"; + +export default function JobsDocumentsImgproxyGallerySelectAllComponent({ galleryImages, setGalleryImages }) { + const { t } = useTranslation(); + + const handleSelectAll = () => { + setGalleryImages({ + ...galleryImages, + other: galleryImages.other.map((i) => { + return { ...i, isSelected: true }; + }), + images: galleryImages.images.map((i) => { + return { ...i, isSelected: true }; + }) + }); + }; + const handleSelectAllImages = () => { + setGalleryImages({ + ...galleryImages, + + images: galleryImages.images.map((i) => { + return { ...i, isSelected: true }; + }) + }); + }; + const handleSelectAllDocuments = () => { + setGalleryImages({ + ...galleryImages, + other: galleryImages.other.map((i) => { + return { ...i, isSelected: true }; + }) + }); + }; + const handleDeselectAll = () => { + setGalleryImages({ + ...galleryImages, + other: galleryImages.other.map((i) => { + return { ...i, isSelected: false }; + }), + images: galleryImages.images.map((i) => { + return { ...i, isSelected: false }; + }) + }); + }; + + return ( + + + + + + + ); +} diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.styles.scss b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.styles.scss new file mode 100644 index 000000000..6df357ffc --- /dev/null +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.styles.scss @@ -0,0 +1,10 @@ +/* you can make up upload button and sample style by using stylesheets */ +.ant-upload-select-picture-card i { + font-size: 32px; + color: #999; +} + +.ant-upload-select-picture-card .ant-upload-text { + margin-top: 8px; + color: #666; +} diff --git a/client/src/pages/temporary-docs/temporary-docs.component.jsx b/client/src/pages/temporary-docs/temporary-docs.component.jsx index 092011e65..95ff5cabe 100644 --- a/client/src/pages/temporary-docs/temporary-docs.component.jsx +++ b/client/src/pages/temporary-docs/temporary-docs.component.jsx @@ -2,6 +2,7 @@ import { useQuery } from "@apollo/client"; import React from "react"; import AlertComponent from "../../components/alert/alert.component"; import JobsDocumentsComponent from "../../components/jobs-documents-gallery/jobs-documents-gallery.component"; +import JobsDocumentsContainer from "../../components/jobs-documents-gallery/jobs-documents-gallery.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import { QUERY_TEMPORARY_DOCS } from "../../graphql/documents.queries"; @@ -22,7 +23,7 @@ export function TemporaryDocsComponent({ bodyshop }) { const { loading, error, data, refetch } = useQuery(QUERY_TEMPORARY_DOCS, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", - skip: bodyshop.uselocalmediaserver + skip: bodyshop.uselocalmediaserver //TODO: Add skip if imgproxy is enabled. }); if (loading) return ; @@ -32,12 +33,14 @@ export function TemporaryDocsComponent({ bodyshop }) { return ; } return ( - + <> + + ); } diff --git a/package-lock.json b/package-lock.json index d0ea5ebcc..608a76ac4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,12 @@ "@aws-sdk/client-secrets-manager": "^3.738.0", "@aws-sdk/client-ses": "^3.738.0", "@aws-sdk/credential-provider-node": "^3.738.0", + "@aws-sdk/lib-storage": "^3.743.0", "@aws-sdk/s3-request-presigner": "^3.731.1", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", + "archiver": "^7.0.1", "aws4": "^1.13.2", "axios": "^1.7.7", "better-queue": "^3.8.12", @@ -794,6 +796,37 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.743.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.743.0.tgz", + "integrity": "sha512-Rf/5sljlEJRVtB5C4UjLCOIcK2ODZet9rQsRtsn0bIc2byURbpOdqIGvfEcKWPayoXCS4dC/5bdjhL1zhZ0TMg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.2", + "@smithy/smithy-client": "^4.1.2", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.743.0" + } + }, + "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.734.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.734.0.tgz", @@ -2488,6 +2521,16 @@ "node": ">=14" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -3678,7 +3721,6 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", - "optional": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -3813,6 +3855,155 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "license": "ISC" }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/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==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/archiver-utils/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", @@ -4090,12 +4281,25 @@ "js-md4": "^0.3.2" } }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "license": "Apache-2.0", + "optional": true + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -4259,6 +4463,39 @@ "node": ">= 0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -4612,6 +4849,38 @@ "node": ">=18" } }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -4831,6 +5100,47 @@ "node": ">=10.0.0" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/crisp-status-reporter": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crisp-status-reporter/-/crisp-status-reporter-1.2.2.tgz", @@ -5965,11 +6275,19 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "optional": true, "engines": { "node": ">=6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -6828,6 +7146,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/graphql": { "version": "16.10.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", @@ -7098,6 +7422,26 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -8007,6 +8351,48 @@ "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", "license": "MIT" }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -8608,6 +8994,15 @@ "node": ">=6" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/notepack.io": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-3.0.1.tgz", @@ -9096,6 +9491,15 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -9306,6 +9710,36 @@ "node": ">= 6" } }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/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==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/recursive-diff": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/recursive-diff/-/recursive-diff-1.0.9.tgz", @@ -10356,6 +10790,16 @@ "node": ">= 0.8" } }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, "node_modules/stream-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", @@ -10381,6 +10825,19 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -10652,6 +11109,17 @@ "node": ">=10" } }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -10754,6 +11222,15 @@ "rimraf": "bin.js" } }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -11766,6 +12243,36 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } } } } diff --git a/package.json b/package.json index c24e79f8e..91b4bc851 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,12 @@ "@aws-sdk/client-secrets-manager": "^3.738.0", "@aws-sdk/client-ses": "^3.738.0", "@aws-sdk/credential-provider-node": "^3.738.0", + "@aws-sdk/lib-storage": "^3.743.0", "@aws-sdk/s3-request-presigner": "^3.731.1", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", + "archiver": "^7.0.1", "aws4": "^1.13.2", "axios": "^1.7.7", "better-queue": "^3.8.12", diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index fa08614fb..a3bc38917 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2722,3 +2722,30 @@ exports.GET_DOCUMENTS_BY_JOB = ` } } }`; + +exports.QUERY_TEMPORARY_DOCS = ` query QUERY_TEMPORARY_DOCS { + documents(where: { jobid: { _is_null: true } }, order_by: { takenat: desc }) { + id + name + key + type + extension + size + takenat + } + }`; + +exports.GET_DOCUMENTS_BY_IDS = ` + query GET_DOCUMENTS_BY_IDS($documentIds: [uuid!]!) { + documents(where: {id: {_in: $documentIds}}, order_by: {takenat: desc}) { + id + name + key + type + extension + size + takenat + } +} + + `; diff --git a/server/media/imgprox-media.js b/server/media/imgprox-media.js index 2ee4d5d5b..4cb0b7d94 100644 --- a/server/media/imgprox-media.js +++ b/server/media/imgprox-media.js @@ -3,13 +3,30 @@ require("dotenv").config({ path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) }); const logger = require("../utils/logger"); -const { S3Client, PutObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3"); +const { + S3Client, + PutObjectCommand, + GetObjectCommand, + CopyObjectCommand, + DeleteObjectCommand +} = require("@aws-sdk/client-s3"); +const { Upload } = require("@aws-sdk/lib-storage"); + const { getSignedUrl } = require("@aws-sdk/s3-request-presigner"); const crypto = require("crypto"); const { InstanceRegion } = require("../utils/instanceMgr"); -const { GET_DOCUMENTS_BY_JOB } = require("../graphql-client/queries"); -//TODO: Remove hardcoded values. -const imgproxyBaseUrl = process.env.IMGPROXY_BASE_URL; +const { + GET_DOCUMENTS_BY_JOB, + QUERY_TEMPORARY_DOCS, + GET_DOCUMENTS_BY_IDS, + DELETE_MEDIA_DOCUMENTS +} = require("../graphql-client/queries"); +const archiver = require("archiver"); +const stream = require("node:stream"); + +const imgproxyBaseUrl = + // `https://u4gzpp5wm437dnm75qa42tvza40fguqr.lambda-url.ca-central-1.on.aws` || //Direct Lambda function access to bypass CDN. + process.env.IMGPROXY_BASE_URL; const imgproxyKey = process.env.IMGPROXY_KEY; const imgproxySalt = process.env.IMGPROXY_SALT; const imgproxyDestinationBucket = process.env.IMGPROXY_DESTINATION_BUCKET; @@ -31,10 +48,13 @@ exports.generateSignedUploadUrls = async (req, res) => { const signedUrls = []; for (const filename of filenames) { - // TODO: Implement a different, unique file naming convention. const key = filename; //GenerateKey({ bodyshopid, jobid, filename }); const client = new S3Client({ region: InstanceRegion() }); - const command = new PutObjectCommand({ Bucket: imgproxyDestinationBucket, Key: key }); + const command = new PutObjectCommand({ + Bucket: imgproxyDestinationBucket, + Key: key, + StorageClass: "INTELLIGENT_TIERING" + }); const presignedUrl = await getSignedUrl(client, command, { expiresIn: 360 }); signedUrls.push({ filename, presignedUrl, key }); } @@ -61,11 +81,14 @@ exports.getThumbnailUrls = async (req, res) => { const { jobid, billid } = req.body; try { - //TODO: Query for all documents related to the job. - //Delayed as the key structure may change slightly from what it is currently and will require evaluating mobile components. + logger.log("imgproxy-thumbnails", "DEBUG", req.user?.email, jobid, { billid, jobid }); + //Delayed as the key structure may change slightly from what it is currently and will require evaluating mobile components. const client = req.userGraphQLClient; - const data = await client.request(GET_DOCUMENTS_BY_JOB, { jobId: jobid }); + //If there's no jobid and no billid, we're in temporary documents. + const data = await (jobid + ? client.request(GET_DOCUMENTS_BY_JOB, { jobId: jobid }) + : client.request(QUERY_TEMPORARY_DOCS)); const thumbResizeParams = `rs:fill:250:250:1/g:ce`; const s3client = new S3Client({ region: InstanceRegion() }); @@ -123,7 +146,9 @@ exports.getThumbnailUrls = async (req, res) => { res.json(proxiedUrls); //Iterate over them, build the link based on the media type, and return the array. } catch (error) { - logger.log("imgproxy-get-proxied-urls-error", "ERROR", req.user?.email, jobid, { + logger.log("imgproxy-thumbnails-error", "ERROR", req.user?.email, jobid, { + jobid, + billid, message: error.message, stack: error.stack }); @@ -137,20 +162,194 @@ exports.getBillFiles = async (req, res) => { exports.downloadFiles = async (req, res) => { //Given a series of document IDs or keys, generate a file (or a link) to download all images in bulk + const { jobid, billid, documentids } = req.body; + try { + logger.log("imgproxy-download", "DEBUG", req.user?.email, jobid, { billid, jobid, documentids }); + + //Delayed as the key structure may change slightly from what it is currently and will require evaluating mobile components. + const client = req.userGraphQLClient; + //Query for the keys of the document IDs + const data = await client.request(GET_DOCUMENTS_BY_IDS, { documentIds: documentids }); + //Using the Keys, get all of the S3 links, zip them, and send back to the client. + const s3client = new S3Client({ region: InstanceRegion() }); + const archiveStream = archiver("zip"); + archiveStream.on("error", (error) => { + console.error("Archival encountered an error:", error); + throw new Error(error); + }); + const passthrough = new stream.PassThrough(); + + archiveStream.pipe(passthrough); + for (const key of data.documents.map((d) => d.key)) { + const response = await s3client.send(new GetObjectCommand({ Bucket: imgproxyDestinationBucket, Key: key })); + // :: `response.Body` is a Buffer + console.log(path.basename(key)); + archiveStream.append(response.Body, { name: path.basename(key) }); + } + + archiveStream.finalize(); + + const archiveKey = `archives/${jobid}/archive-${new Date().toISOString()}.zip`; + + const parallelUploads3 = new Upload({ + client: s3client, + queueSize: 4, // optional concurrency configuration + leavePartsOnError: false, // optional manually handle dropped parts + params: { Bucket: imgproxyDestinationBucket, Key: archiveKey, Body: passthrough } + }); + + parallelUploads3.on("httpUploadProgress", (progress) => { + console.log(progress); + }); + + const uploadResult = await parallelUploads3.done(); + //Generate the presigned URL to download it. + const presignedUrl = await getSignedUrl( + s3client, + new GetObjectCommand({ Bucket: imgproxyDestinationBucket, Key: archiveKey }), + { expiresIn: 360 } + ); + + res.json({ success: true, url: presignedUrl }); + //Iterate over them, build the link based on the media type, and return the array. + } catch (error) { + logger.log("imgproxy-thumbnails-error", "ERROR", req.user?.email, jobid, { + jobid, + billid, + message: error.message, + stack: error.stack + }); + res.status(400).json({ message: error.message, stack: error.stack }); + } }; exports.deleteFiles = async (req, res) => { //Mark a file for deletion in s3. Lifecycle deletion will actually delete the copy in the future. //Mark as deleted from the documents section of the database. + const { ids } = req.body; + try { + logger.log("imgproxy-delete-files", "DEBUG", req.user.email, null, { ids }); + const client = req.userGraphQLClient; + + //Do this to make sure that they are only deleting things that they have access to + const data = await client.request(GET_DOCUMENTS_BY_IDS, { documentIds: ids }); + + const s3client = new S3Client({ region: InstanceRegion() }); + + const deleteTransactions = []; + data.documents.forEach((document) => { + deleteTransactions.push( + (async () => { + try { + // Delete the original object + const deleteResult = await s3client.send( + new DeleteObjectCommand({ + Bucket: imgproxyDestinationBucket, + Key: document.key + }) + ); + + return document; + } catch (error) { + return { document, error: error, bucket: imgproxyDestinationBucket }; + } + })() + ); + }); + + const result = await Promise.all(deleteTransactions); + console.log("*** ~ file: imgprox-media.js:260 ~ exports.deleteFiles ~ result:", result); + const errors = result.filter((d) => d.error); + + //Delete only the succesful deletes. + const deleteMutationResult = await client.request(DELETE_MEDIA_DOCUMENTS, { + ids: result.filter((t) => !t.error).map((d) => d.id) + }); + + res.json({ errors, deleteMutationResult }); + } catch (error) { + logger.log("imgproxy-delete-files-error", "ERROR", req.user.email, null, { + ids, + message: error.message, + stack: error.stack + }); + res.status(400).json({ message: error.message, stack: error.stack }); + } }; -//Gerneate a key for the s3 bucket by popping off the extension, add a timestamp, and add back the extension. -//This is to prevent any collisions/duplicates in the bucket. -function GenerateKey({ bodyshopid, jobid, filename }) { - let nameArray = filename.split("."); - let extension = nameArray.pop(); - return `${bodyshopid}/${jobid}/${nameArray.join(".")}-${Date.now()}`; -} +exports.moveFiles = async (req, res) => { + const { documents, tojobid } = req.body; + try { + logger.log("imgproxy-move-files", "DEBUG", req.user.email, null, { documents, tojobid }); + const s3client = new S3Client({ region: InstanceRegion() }); + + const moveTransactions = []; + documents.forEach((document) => { + moveTransactions.push( + (async () => { + try { + // Copy the object to the new key + const copyresult = await s3client.send( + new CopyObjectCommand({ + Bucket: imgproxyDestinationBucket, + CopySource: `${imgproxyDestinationBucket}/${document.from}`, + Key: document.to, + StorageClass: "INTELLIGENT_TIERING" + }) + ); + + // Delete the original object + const deleteResult = await s3client.send( + new DeleteObjectCommand({ + Bucket: imgproxyDestinationBucket, + Key: document.from + }) + ); + + return document; + } catch (error) { + return { id: document.id, from: document.from, error: error, bucket: imgproxyDestinationBucket }; + } + })() + ); + }); + + const result = await Promise.all(moveTransactions); + const errors = result.filter((d) => d.error); + + let mutations = ""; + result + .filter((d) => !d.error) + .forEach((d, idx) => { + //Create mutation text + mutations = + mutations + + ` + update_doc${idx}:update_documents_by_pk(pk_columns: { id: "${d.id}" }, _set: {key: "${d.to}", jobid: "${tojobid}"}){ + id + } + `; + }); + + const client = req.userGraphQLClient; + if (mutations !== "") { + const mutationResult = await client.request(`mutation { + ${mutations} + }`); + res.json({ errors, mutationResult }); + } else { + res.json({ errors: "No images were succesfully moved on remote server. " }); + } + } catch (error) { + logger.log("imgproxy-move-files-error", "ERROR", req.user.email, null, { + documents, + tojobid, + message: error.message, + stack: error.stack + }); + res.status(400).json({ message: error.message, stack: error.stack }); + } +}; function base64UrlEncode(str) { return Buffer.from(str).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); diff --git a/server/routes/mediaRoutes.js b/server/routes/mediaRoutes.js index 9718b85d1..293ac51a0 100644 --- a/server/routes/mediaRoutes.js +++ b/server/routes/mediaRoutes.js @@ -1,7 +1,13 @@ const express = require("express"); const router = express.Router(); const { createSignedUploadURL, downloadFiles, renameKeys, deleteFiles } = require("../media/media"); -const { generateSignedUploadUrls, getThumbnailUrls } = require("../media/imgprox-media"); +const { + generateSignedUploadUrls, + getThumbnailUrls, + downloadFiles: downloadFilesImgproxy, + moveFiles, + deleteFiles: deleteFilesImgproxy +} = require("../media/imgprox-media"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware"); @@ -13,7 +19,10 @@ router.post("/download", downloadFiles); router.post("/rename", renameKeys); router.post("/delete", deleteFiles); -router.post("/proxy/sign", generateSignedUploadUrls); -router.post("/proxy/thumbnails", getThumbnailUrls); +router.post("/imgproxy/sign", generateSignedUploadUrls); +router.post("/imgproxy/thumbnails", getThumbnailUrls); +router.post("/imgproxy/download", downloadFilesImgproxy); +router.post("/imgproxy/rename", moveFiles); +router.post("/imgproxy/delete", deleteFilesImgproxy); module.exports = router; From 66671385d04e245876dfa9def726005d5252cc36 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Tue, 25 Feb 2025 11:15:29 -0800 Subject: [PATCH 05/45] IO-3092 resolve thumbnail fetching --- .../jobs-documents-imgproxy-gallery.component.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx index 0a9beacc1..d102e263f 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx @@ -108,7 +108,6 @@ function JobsDocumentsImgproxyComponent({ const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); return (
- IMG PROXY COMPONENTS (DELETE ME) @@ -126,8 +125,13 @@ function JobsDocumentsImgproxyComponent({ - - {!billId && } + + {!billId && ( + + )} {!hasMediaAccess && ( @@ -143,7 +147,7 @@ function JobsDocumentsImgproxyComponent({ jobId={jobId} totalSize={totalSize} billId={billId} - callbackAfterUpload={billsCallback || refetch} + callbackAfterUpload={billsCallback || fetchThumbnails || refetch} ignoreSizeLimit={ignoreSizeLimit} /> From 25b289b65de3be0a1cf8226787eadb21a5fe8f85 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 26 Feb 2025 20:56:13 -0800 Subject: [PATCH 06/45] IO-3092 add messaging support for imgproxy --- .../chat-media-selector.component.jsx | 24 +++- .../jobs-documents-gallery.container.jsx | 30 +++- ...s-documents-imgproxy-gallery.component.jsx | 134 ++++++++++-------- ...ts-imgproxy-gallery.external.component.jsx | 36 ++--- .../temporary-docs.component.jsx | 14 +- 5 files changed, 136 insertions(+), 102 deletions(-) diff --git a/client/src/components/chat-media-selector/chat-media-selector.component.jsx b/client/src/components/chat-media-selector/chat-media-selector.component.jsx index 0526fde43..cc7a56b73 100644 --- a/client/src/components/chat-media-selector/chat-media-selector.component.jsx +++ b/client/src/components/chat-media-selector/chat-media-selector.component.jsx @@ -1,7 +1,8 @@ import { PictureFilled } from "@ant-design/icons"; import { useQuery } from "@apollo/client"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { Badge, Popover } from "antd"; -import React, { useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -9,6 +10,7 @@ import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; import AlertComponent from "../alert/alert.component"; import JobDocumentsGalleryExternal from "../jobs-documents-gallery/jobs-documents-gallery.external.component"; +import JobsDocumentImgproxyGalleryExternal from "../jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component"; import JobDocumentsLocalGalleryExternal from "../jobs-documents-local-gallery/jobs-documents-local-gallery.external.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; @@ -23,6 +25,13 @@ export default connect(mapStateToProps, mapDispatchToProps)(ChatMediaSelector); export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, conversation }) { const { t } = useTranslation(); const [open, setOpen] = useState(false); + const { + treatments: { Imgproxy } + } = useSplitTreatments({ + attributes: {}, + names: ["Imgproxy"], + splitKey: bodyshop && bodyshop.imexshopid + }); const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, { fetchPolicy: "network-only", @@ -42,6 +51,9 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c setSelectedMedia([]); }, [setSelectedMedia, conversation]); + + //Knowingly taking on the technical debt of poor implementation below. + //Cloudinary will be removed once the migration is completed. const content = (
{loading && } @@ -49,13 +61,19 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c {selectedMedia.filter((s) => s.isSelected).length >= 10 ? (
{t("messaging.labels.maxtenimages")}
) : null} - {!bodyshop.uselocalmediaserver && data && ( + {Imgproxy.treatment === "on" && !bodyshop.uselocalmediaserver && data && ( + + )} + {Imgproxy.treatment !== "on" && !bodyshop.uselocalmediaserver && data && ( )} - {bodyshop.uselocalmediaserver && open && ( + {Imgproxy.treatment !== "on" && bodyshop.uselocalmediaserver && open && ( ({}); +export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsContainer); -export default function JobsDocumentsContainer({ +export function JobsDocumentsContainer({ jobId, billId, documentsList, billsCallback, refetchOverride, - ignoreSizeLimit + ignoreSizeLimit, + bodyshop }) { - //TODO Add a checker to see whether we should use the img proxy side, or this side. - const useImgProxy = true; + const { + treatments: { Imgproxy } + } = useSplitTreatments({ + attributes: {}, + names: ["Imgproxy"], + splitKey: bodyshop && bodyshop.imexshopid + }); + const { loading, error, data, refetch } = useQuery(GET_DOCUMENTS_BY_JOB, { variables: { jobId: jobId }, fetchPolicy: "network-only", nextFetchPolicy: "network-only", - skip: useImgProxy || !!billId + skip: Imgproxy.treatment === "on" || !!billId }); if (loading) return ; if (error) return ; - if (useImgProxy) { + if (Imgproxy.treatment === "on") { return ( { - const result = await axios.post("/media/imgproxy/thumbnails", { jobid: jobId }); - let documents = result.data.reduce( - (acc, value) => { - if (value.type.startsWith("image")) { - acc.images.push({ - src: value.thumbnailUrl, - fullsize: value.originalUrl, - height: 225, - width: 225, - isSelected: false, - key: value.key, - extension: value.extension, - id: value.id, - type: value.type, - size: value.size, - tags: [{ value: value.type, title: value.type }] - }); - } else { - const fileName = value.key.split("/").pop(); - acc.other.push({ - source: value.originalUrlViaProxyPath, - src: value.thumbnailUrl, - fullsize: value.presignedGetUrl, - tags: [ - { - value: fileName, - title: fileName - }, - - { value: value.type, title: value.type }, - ...(value.bill - ? [ - { - value: value.bill.vendor.name, - title: t("vendors.fields.name") - }, - { value: value.bill.date, title: t("bills.fields.date") }, - { - value: value.bill.invoice_number, - title: t("bills.fields.invoice_number") - } - ] - : []) - ], - height: 225, - width: 225, - isSelected: false, - extension: value.extension, - key: value.key, - id: value.id, - type: value.type, - size: value.size - }); - } - return acc; - }, - { images: [], other: [] } - ); - setgalleryImages(documents); + const fetchThumbnails = () => { + fetchImgproxyThumbnails({ setStateCallback: setgalleryImages, jobId }); }; + useEffect(() => { if (data) { fetchThumbnails(); } - }, [data, setgalleryImages, t]); + }, [data, setgalleryImages]); const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); @@ -249,3 +193,69 @@ function JobsDocumentsImgproxyComponent({ } export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyComponent); + +export const fetchImgproxyThumbnails = async ({ setStateCallback, jobId, imagesOnly }) => { + const result = await axios.post("/media/imgproxy/thumbnails", { jobid: jobId }); + let documents = result.data.reduce( + (acc, value) => { + if (value.type.startsWith("image")) { + acc.images.push({ + src: value.thumbnailUrl, + fullsize: value.originalUrl, + height: 225, + width: 225, + isSelected: false, + key: value.key, + extension: value.extension, + id: value.id, + type: value.type, + size: value.size, + tags: [{ value: value.type, title: value.type }] + }); + } else { + const fileName = value.key.split("/").pop(); + acc.other.push({ + source: value.originalUrlViaProxyPath, + src: value.thumbnailUrl, + fullsize: value.presignedGetUrl, + tags: [ + { + value: fileName, + title: fileName + }, + + { value: value.type, title: value.type }, + ...(value.bill + ? [ + { + value: value.bill.vendor.name, + title: i18n.t("vendors.fields.name") + }, + { value: value.bill.date, title: i18n.t("bills.fields.date") }, + { + value: value.bill.invoice_number, + title: i18n.t("bills.fields.invoice_number") + } + ] + : []) + ], + height: 225, + width: 225, + isSelected: false, + extension: value.extension, + key: value.key, + id: value.id, + type: value.type, + size: value.size + }); + } + return acc; + }, + { images: [], other: [] } + ); + if (imagesOnly) { + setStateCallback(documents.images); + } else { + setStateCallback(documents); + } +}; diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx index ed89cc1ca..21c8059f9 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx @@ -1,38 +1,20 @@ import { useEffect } from "react"; import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; -import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents-imgproxy.utility"; +import { fetchImgproxyThumbnails } from "./jobs-documents-imgproxy-gallery.component"; +//import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents-imgproxy.utility"; -function JobsDocumentImgproxyGalleryExternal({ - data, - - externalMediaState -}) { +function JobsDocumentImgproxyGalleryExternal({ jobId, externalMediaState }) { const [galleryImages, setgalleryImages] = externalMediaState; const { t } = useTranslation(); - useEffect(() => { - let documents = data.reduce((acc, value) => { - if (value.type.startsWith("image")) { - acc.push({ - fullsize: GenerateSrcUrl(value), - src: GenerateThumbUrl(value), - thumbnailHeight: 225, - thumbnailWidth: 225, - isSelected: false, - key: value.key, - extension: value.extension, - id: value.id, - type: value.type, - tags: [{ value: value.type, title: value.type }], - size: value.size - }); - } + const fetchThumbnails = () => { + fetchImgproxyThumbnails({ setStateCallback: setgalleryImages, jobId, imagesOnly: true }); + }; - return acc; - }, []); - setgalleryImages(documents); - }, [data, setgalleryImages, t]); + useEffect(() => { + fetchThumbnails(); + }, [jobId]); return (
diff --git a/client/src/pages/temporary-docs/temporary-docs.component.jsx b/client/src/pages/temporary-docs/temporary-docs.component.jsx index 95ff5cabe..26948d7a4 100644 --- a/client/src/pages/temporary-docs/temporary-docs.component.jsx +++ b/client/src/pages/temporary-docs/temporary-docs.component.jsx @@ -1,15 +1,15 @@ import { useQuery } from "@apollo/client"; import React from "react"; import AlertComponent from "../../components/alert/alert.component"; -import JobsDocumentsComponent from "../../components/jobs-documents-gallery/jobs-documents-gallery.component"; import JobsDocumentsContainer from "../../components/jobs-documents-gallery/jobs-documents-gallery.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import { QUERY_TEMPORARY_DOCS } from "../../graphql/documents.queries"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; import JobsDocumentsLocalGallery from "../../components/jobs-documents-local-gallery/jobs-documents-local-gallery.container"; +import { selectBodyshop } from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -20,10 +20,18 @@ const mapDispatchToProps = (dispatch) => ({ export default connect(mapStateToProps, mapDispatchToProps)(TemporaryDocsComponent); export function TemporaryDocsComponent({ bodyshop }) { + const { + treatments: { Imgproxy } + } = useSplitTreatments({ + attributes: {}, + names: ["Imgproxy"], + splitKey: bodyshop && bodyshop.imexshopid + }); + const { loading, error, data, refetch } = useQuery(QUERY_TEMPORARY_DOCS, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", - skip: bodyshop.uselocalmediaserver //TODO: Add skip if imgproxy is enabled. + skip: Imgproxy.treatment === "on" }); if (loading) return ; From fa29bd609f223dbd76bce6d41bf85bfc2d91d546 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 27 Feb 2025 12:15:36 -0800 Subject: [PATCH 07/45] IO-3092 Additional comments, email compatibility. --- .../chat-media-selector.component.jsx | 55 ++++++++++++------- .../documents-upload-imgproxy.utility.js | 2 +- .../email-documents.component.jsx | 51 +++++++++++++---- ...bs-document-gallery.download.component.jsx | 8 ++- ...bs-document-gallery.reassign.component.jsx | 8 ++- .../jobs-documents-gallery.component.jsx | 8 ++- .../jobs-documents-gallery.container.jsx | 8 ++- ...obs-documents-gallery.delete.component.jsx | 9 ++- ...s-documents-gallery.external.component.jsx | 7 +++ ...-documents-gallery.selectall.component.jsx | 8 +++ ...nt-imgproxy-gallery.download.component.jsx | 9 +++ ...nt-imgproxy-gallery.reassign.component.jsx | 8 ++- ...s-documents-imgproxy-gallery.component.jsx | 8 ++- ...s-documents-imgproxy-gallery.container.jsx | 8 +++ ...ents-imgproxy-gallery.delete.component.jsx | 10 +++- ...ts-imgproxy-gallery.external.component.jsx | 9 ++- ...s-imgproxy-gallery.selectall.component.jsx | 8 +++ .../{imgprox-media.js => imgproxy-media.js} | 15 +---- server/routes/mediaRoutes.js | 2 +- 19 files changed, 185 insertions(+), 56 deletions(-) rename server/media/{imgprox-media.js => imgproxy-media.js} (95%) diff --git a/client/src/components/chat-media-selector/chat-media-selector.component.jsx b/client/src/components/chat-media-selector/chat-media-selector.component.jsx index cc7a56b73..b7e7d64a3 100644 --- a/client/src/components/chat-media-selector/chat-media-selector.component.jsx +++ b/client/src/components/chat-media-selector/chat-media-selector.component.jsx @@ -51,9 +51,10 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c setSelectedMedia([]); }, [setSelectedMedia, conversation]); - - //Knowingly taking on the technical debt of poor implementation below. - //Cloudinary will be removed once the migration is completed. + //Knowingly taking on the technical debt of poor implementation below. Done this way to avoid an edge case where no component may be displayed. + //Cloudinary will be removed once the migration is completed. + //If Imageproxy is on, rely only on the LMS selector + //If not on, use the old methods. const content = (
{loading && } @@ -61,23 +62,37 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c {selectedMedia.filter((s) => s.isSelected).length >= 10 ? (
{t("messaging.labels.maxtenimages")}
) : null} - {Imgproxy.treatment === "on" && !bodyshop.uselocalmediaserver && data && ( - - )} - {Imgproxy.treatment !== "on" && !bodyshop.uselocalmediaserver && data && ( - - )} - {Imgproxy.treatment !== "on" && bodyshop.uselocalmediaserver && open && ( - + + {Imgproxy.treatment === "on" ? ( + <> + {!bodyshop.uselocalmediaserver && ( + + )} + {bodyshop.uselocalmediaserver && open && ( + + )} + + ) : ( + <> + {!bodyshop.uselocalmediaserver && data && ( + + )} + {bodyshop.uselocalmediaserver && open && ( + + )} + )}
); diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js index 184cf86c6..ed64f5efb 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -74,7 +74,7 @@ export const uploadToS3 = async ( const exif = await exifr.parse(file); takenat = exif && exif.DateTimeOriginal; } catch (error) { - console.log("Unable to parse image file for EXIF Data"); + console.log("Unable to parse image file for EXIF Data", error.message); } } diff --git a/client/src/components/email-documents/email-documents.component.jsx b/client/src/components/email-documents/email-documents.component.jsx index d3c6b20da..7e17d5565 100644 --- a/client/src/components/email-documents/email-documents.component.jsx +++ b/client/src/components/email-documents/email-documents.component.jsx @@ -10,6 +10,8 @@ import AlertComponent from "../alert/alert.component"; import JobDocumentsGalleryExternal from "../jobs-documents-gallery/jobs-documents-gallery.external.component"; import JobsDocumentsLocalGalleryExternalComponent from "../jobs-documents-local-gallery/jobs-documents-local-gallery.external.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; +import JobsDocumentImgproxyGalleryExternal from "../jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -23,6 +25,13 @@ export default connect(mapStateToProps, mapDispatchToProps)(EmailDocumentsCompon export function EmailDocumentsComponent({ emailConfig, form, selectedMediaState, bodyshop }) { const { t } = useTranslation(); + const { + treatments: { Imgproxy } + } = useSplitTreatments({ + attributes: {}, + names: ["Imgproxy"], + splitKey: bodyshop && bodyshop.imexshopid + }); const [selectedMedia, setSelectedMedia] = selectedMediaState; const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, { @@ -46,17 +55,37 @@ export function EmailDocumentsComponent({ emailConfig, form, selectedMediaState, 10485760 - new Blob([form.getFieldValue("html")]).size ? (
{t("general.errors.sizelimit")}
) : null} - {!bodyshop.uselocalmediaserver && data && ( - - )} - {bodyshop.uselocalmediaserver && ( - + + {Imgproxy.treatment === "on" ? ( + <> + {!bodyshop.uselocalmediaserver && data && ( + + )} + {bodyshop.uselocalmediaserver && ( + + )} + + ) : ( + <> + {!bodyshop.uselocalmediaserver && data && ( + + )} + {bodyshop.uselocalmediaserver && ( + + )} + )}
); diff --git a/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx b/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx index f85db7c8c..cbc89ab38 100644 --- a/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx @@ -19,7 +19,13 @@ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsDownloadButton); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ export function JobsDocumentsDownloadButton({ bodyshop, galleryImages, identifier }) { const { t } = useTranslation(); const [download, setDownload] = useState(null); diff --git a/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx b/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx index 33f2e964a..51c889729 100644 --- a/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx @@ -17,7 +17,13 @@ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsGalleryReassign); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages, callback }) { const { t } = useTranslation(); const [form] = Form.useForm(); diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index fdc919320..58adaccad 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -22,7 +22,13 @@ const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); const mapDispatchToProps = (dispatch) => ({}); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ function JobsDocumentsComponent({ bodyshop, data, diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.container.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.container.jsx index 3c2cf3843..5bbd95f94 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.container.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.container.jsx @@ -14,7 +14,13 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({}); export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsContainer); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ export function JobsDocumentsContainer({ jobId, billId, diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx index 5cd1fcb06..4b92e4c99 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx @@ -5,8 +5,13 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; -//Context: currentUserEmail, bodyshop, jobid, invoiceid - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ export default function JobsDocumentsDeleteButton({ galleryImages, deletionCallback }) { const { t } = useTranslation(); const notification = useNotification(); diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx index 940598052..d4340bb98 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx @@ -3,6 +3,13 @@ import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility"; +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ function JobsDocumentGalleryExternal({ data, diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.selectall.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.selectall.component.jsx index 122ce6236..157e04dca 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.selectall.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.selectall.component.jsx @@ -2,6 +2,14 @@ import { Button, Space } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Imgproxy code. This code will be removed once the imgproxy migration is completed. +################################################################################################ +*/ + export default function JobsDocumentsGallerySelectAllComponent({ galleryImages, setGalleryImages }) { const { t } = useTranslation(); diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx index 2d649bcc9..6c08936dc 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.download.component.jsx @@ -17,6 +17,15 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); + +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ + export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyDownloadButton); export function JobsDocumentsImgproxyDownloadButton({ bodyshop, galleryImages, identifier }) { diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx index 19b7d9352..4ce2d12a2 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx @@ -17,7 +17,13 @@ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgproxyGalleryReassign); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages, callback }) { const { t } = useTranslation(); const [form] = Form.useForm(); diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx index b28d3f1bd..156362ff1 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx @@ -22,7 +22,13 @@ const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); const mapDispatchToProps = (dispatch) => ({}); - +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ function JobsDocumentsImgproxyComponent({ bodyshop, data, diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx index 50dd4bbe9..9191b262c 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.container.jsx @@ -4,6 +4,14 @@ import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import JobDocuments from "./jobs-documents-imgproxy-gallery.component"; +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ + export default function JobsDocumentsImgproxyContainer({ jobId, billId, documentsList, billsCallback }) { const { loading, error, data, refetch } = useQuery(GET_DOCUMENTS_BY_JOB, { variables: { jobId: jobId }, diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx index 51ebfbf2b..72143531b 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx @@ -5,7 +5,15 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; -//Context: currentUserEmail, bodyshop, jobid, invoiceid + + +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ export default function JobsDocumentsImgproxyDeleteButton({ galleryImages, deletionCallback }) { const { t } = useTranslation(); diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx index 21c8059f9..75943dceb 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx @@ -2,7 +2,14 @@ import { useEffect } from "react"; import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import { fetchImgproxyThumbnails } from "./jobs-documents-imgproxy-gallery.component"; -//import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents-imgproxy.utility"; + +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ function JobsDocumentImgproxyGalleryExternal({ jobId, externalMediaState }) { const [galleryImages, setgalleryImages] = externalMediaState; diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx index 25162e7d0..4d4b0b32e 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.selectall.component.jsx @@ -1,6 +1,14 @@ import { Button, Space } from "antd"; import { useTranslation } from "react-i18next"; +/* +################################################################################################ + Developer Note: + Known Technical Debt Item + Modifications to this code requires complementary changes to the Cloudinary code. Cloudinary code will be removed upon completed migration. +################################################################################################ +*/ + export default function JobsDocumentsImgproxyGallerySelectAllComponent({ galleryImages, setGalleryImages }) { const { t } = useTranslation(); diff --git a/server/media/imgprox-media.js b/server/media/imgproxy-media.js similarity index 95% rename from server/media/imgprox-media.js rename to server/media/imgproxy-media.js index 4cb0b7d94..fdb313984 100644 --- a/server/media/imgprox-media.js +++ b/server/media/imgproxy-media.js @@ -24,9 +24,7 @@ const { const archiver = require("archiver"); const stream = require("node:stream"); -const imgproxyBaseUrl = - // `https://u4gzpp5wm437dnm75qa42tvza40fguqr.lambda-url.ca-central-1.on.aws` || //Direct Lambda function access to bypass CDN. - process.env.IMGPROXY_BASE_URL; +const imgproxyBaseUrl = process.env.IMGPROXY_BASE_URL; // `https://u4gzpp5wm437dnm75qa42tvza40fguqr.lambda-url.ca-central-1.on.aws` //Direct Lambda function access to bypass CDN. const imgproxyKey = process.env.IMGPROXY_KEY; const imgproxySalt = process.env.IMGPROXY_SALT; const imgproxyDestinationBucket = process.env.IMGPROXY_DESTINATION_BUCKET; @@ -38,17 +36,9 @@ exports.generateSignedUploadUrls = async (req, res) => { try { logger.log("imgproxy-upload-start", "DEBUG", req.user?.email, jobid, { filenames, bodyshopid, jobid }); - //TODO: Ensure that the user has access to the given bodyshopid. - //This can be done by querying associations, or, maintaining a REDIS cache of user permissions. - const hasAccess = true; //TODO: Ensure this is not hardcoded. - if (!hasAccess) { - res.send(403); - return; - } - const signedUrls = []; for (const filename of filenames) { - const key = filename; //GenerateKey({ bodyshopid, jobid, filename }); + const key = filename; const client = new S3Client({ region: InstanceRegion() }); const command = new PutObjectCommand({ Bucket: imgproxyDestinationBucket, @@ -258,7 +248,6 @@ exports.deleteFiles = async (req, res) => { }); const result = await Promise.all(deleteTransactions); - console.log("*** ~ file: imgprox-media.js:260 ~ exports.deleteFiles ~ result:", result); const errors = result.filter((d) => d.error); //Delete only the succesful deletes. diff --git a/server/routes/mediaRoutes.js b/server/routes/mediaRoutes.js index 293ac51a0..0fcfdd3c5 100644 --- a/server/routes/mediaRoutes.js +++ b/server/routes/mediaRoutes.js @@ -7,7 +7,7 @@ const { downloadFiles: downloadFilesImgproxy, moveFiles, deleteFiles: deleteFilesImgproxy -} = require("../media/imgprox-media"); +} = require("../media/imgproxy-media"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware"); From f13a70a22f020f0f32a97babf0aec6b568ed2f16 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 27 Feb 2025 12:17:26 -0800 Subject: [PATCH 08/45] IO-3092 Improve import name in routes. --- server/routes/mediaRoutes.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/routes/mediaRoutes.js b/server/routes/mediaRoutes.js index 0fcfdd3c5..59ee836ec 100644 --- a/server/routes/mediaRoutes.js +++ b/server/routes/mediaRoutes.js @@ -2,10 +2,10 @@ const express = require("express"); const router = express.Router(); const { createSignedUploadURL, downloadFiles, renameKeys, deleteFiles } = require("../media/media"); const { - generateSignedUploadUrls, - getThumbnailUrls, + generateSignedUploadUrls: createSignedUploadURLImgproxy, + getThumbnailUrls: getThumbnailUrlsImgproxy, downloadFiles: downloadFilesImgproxy, - moveFiles, + moveFiles: moveFilesImgproxy, deleteFiles: deleteFilesImgproxy } = require("../media/imgproxy-media"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); @@ -19,10 +19,10 @@ router.post("/download", downloadFiles); router.post("/rename", renameKeys); router.post("/delete", deleteFiles); -router.post("/imgproxy/sign", generateSignedUploadUrls); -router.post("/imgproxy/thumbnails", getThumbnailUrls); +router.post("/imgproxy/sign", createSignedUploadURLImgproxy); +router.post("/imgproxy/thumbnails", getThumbnailUrlsImgproxy); router.post("/imgproxy/download", downloadFilesImgproxy); -router.post("/imgproxy/rename", moveFiles); +router.post("/imgproxy/rename", moveFilesImgproxy); router.post("/imgproxy/delete", deleteFilesImgproxy); module.exports = router; From ace0039429e7bb8c7001e070b775cbfaf5a0238c Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 27 Feb 2025 13:54:16 -0800 Subject: [PATCH 09/45] IO-3092 Address PR concerns. --- .../documents-upload-imgproxy.component.jsx | 3 +- .../documents-upload-imgproxy.utility.js | 125 ++++++++++-------- ...nt-imgproxy-gallery.reassign.component.jsx | 11 +- ...s-documents-imgproxy-gallery.component.jsx | 25 ++-- ...ents-imgproxy-gallery.delete.component.jsx | 11 +- server/graphql-client/queries.js | 4 +- 6 files changed, 96 insertions(+), 83 deletions(-) diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx index 259ca5831..f71760e3b 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.component.jsx @@ -67,9 +67,8 @@ export function DocumentsUploadImgproxyComponent({ //Check to see if old files plus newly uploaded ones will be too much. if (shouldStopUpload) { - notification.open({ + notification.error({ key: "cannotuploaddocuments", - type: "error", message: t("documents.labels.upload_limitexceeded_title"), description: t("documents.labels.upload_limitexceeded") }); diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js index ed64f5efb..8fa7cb001 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -5,6 +5,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries"; import { axiosAuthInterceptorId } from "../../utils/CleanAxios"; import client from "../../utils/GraphQLClient"; +import { error } from "logrocket"; //Context: currentUserEmail, bodyshop, jobid, invoiceid @@ -13,17 +14,26 @@ var cleanAxios = axios.create(); cleanAxios.interceptors.request.eject(axiosAuthInterceptorId); export const handleUpload = (ev, context, notification) => { - logImEXEvent("document_upload", { filetype: ev.file.type }); + logImEXEvent("document_upload", { filetype: ev.file?.type }); const { onError, onSuccess, onProgress } = ev; const { bodyshop, jobId } = context; - const fileName = ev.file.name || ev.filename; + const fileName = ev.file?.name || ev.filename; let extension = fileName.split(".").pop(); let key = `${bodyshop.id}/${jobId}/${replaceAccents(fileName).replace(/[^A-Z0-9]+/gi, "_")}-${new Date().getTime()}.${extension}`; - uploadToS3(key, extension, ev.file.type, ev.file, onError, onSuccess, onProgress, context, notification); + uploadToS3(key, extension, ev.file.type, ev.file, onError, onSuccess, onProgress, context, notification).catch( + (error) => { + console.error("Error uploading file to S3", error); + notification.error({ + message: i18n.t("documents.errors.insert", { + message: error.message + }) + }); + } + ); }; //Handles only 1 file at a time. @@ -49,7 +59,7 @@ export const uploadToS3 = async ( if (signedURLResponse.status !== 200) { if (onError) onError(signedURLResponse.statusText); - notification["error"]({ + notification.error({ message: i18n.t("documents.errors.getpresignurl", { message: signedURLResponse.statusText }) @@ -60,67 +70,76 @@ export const uploadToS3 = async ( //Key should be same as we provided to maintain backwards compatibility. const { presignedUrl: preSignedUploadUrlToS3, key: s3Key } = signedURLResponse.data.signedUrls[0]; - var options = { + const options = { onUploadProgress: (e) => { if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); } }; - const s3UploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); - //Insert the document with the matching key. - let takenat; - if (fileType.includes("image")) { - try { - const exif = await exifr.parse(file); - takenat = exif && exif.DateTimeOriginal; - } catch (error) { - console.log("Unable to parse image file for EXIF Data", error.message); + try { + const s3UploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options); + //Insert the document with the matching key. + let takenat; + if (fileType.includes("image")) { + try { + const exif = await exifr.parse(file); + takenat = exif && exif.DateTimeOriginal; + } catch (error) { + console.log("Unable to parse image file for EXIF Data", error.message); + } } - } - const documentInsert = await client.mutate({ - mutation: INSERT_NEW_DOCUMENT, - variables: { - docInput: [ - { - ...(jobId ? { jobid: jobId } : {}), - ...(billId ? { billid: billId } : {}), - uploaded_by: uploaded_by, - key: s3Key, - type: fileType, - extension: s3UploadResponse.data.format || extension, - bodyshopid: bodyshop.id, - size: s3UploadResponse.data.bytes || file.size, //Leftover from Cloudinary. We don't do any optimization on upload, so it will always be file.size. - takenat - } - ] - } - }); - - if (!documentInsert.errors) { - if (onSuccess) - onSuccess({ - uid: documentInsert.data.insert_documents.returning[0].id, - name: documentInsert.data.insert_documents.returning[0].name, - status: "done", - key: documentInsert.data.insert_documents.returning[0].key - }); - notification.open({ - type: "success", - key: "docuploadsuccess", - message: i18n.t("documents.successes.insert") + const documentInsert = await client.mutate({ + mutation: INSERT_NEW_DOCUMENT, + variables: { + docInput: [ + { + ...(jobId ? { jobid: jobId } : {}), + ...(billId ? { billid: billId } : {}), + uploaded_by: uploaded_by, + key: s3Key, + type: fileType, + extension: s3UploadResponse.data.format || extension, + bodyshopid: bodyshop.id, + size: s3UploadResponse.data.bytes || file.size, //Leftover from Cloudinary. We don't do any optimization on upload, so it will always be file.size. + takenat + } + ] + } }); - if (callback) { - callback(); + + if (!documentInsert.errors) { + if (onSuccess) + onSuccess({ + uid: documentInsert.data.insert_documents.returning[0].id, + name: documentInsert.data.insert_documents.returning[0].name, + status: "done", + key: documentInsert.data.insert_documents.returning[0].key + }); + notification.success({ + key: "docuploadsuccess", + message: i18n.t("documents.successes.insert") + }); + if (callback) { + callback(); + } + } else { + if (onError) onError(JSON.stringify(documentInsert.errors)); + notification.error({ + message: i18n.t("documents.errors.insert", { + message: JSON.stringify(documentInsert.errors) + }) + }); + return; } - } else { - if (onError) onError(JSON.stringify(documentInsert.errors)); - notification["error"]({ + } catch (error) { + console.log("Error uploading file to S3", error.message, error.stack); + notification.error({ message: i18n.t("documents.errors.insert", { - message: JSON.stringify(documentInsert.errors) + message: error.message }) }); - return; + if (onError) onError(JSON.stringify(error.message)); } }; diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx index 4ce2d12a2..2fcd55a9f 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-document-imgproxy-gallery.reassign.component.jsx @@ -9,7 +9,7 @@ import { useNotification } from "../../contexts/Notifications/notificationContex import { GET_DOC_SIZE_BY_JOB } from "../../graphql/documents.queries.js"; import { selectBodyshop } from "../../redux/user/user.selectors.js"; import JobSearchSelect from "../job-search-select/job-search-select.component.jsx"; - +import { isFunction } from "lodash"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); @@ -54,9 +54,8 @@ export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages, bodyshop.jobsizelimit - newJobData.data.documents_aggregate.aggregate.sum.size < transferedDocSizeTotal; if (shouldPreventTransfer) { - notification.open({ + notification.error({ key: "cannotuploaddocuments", - type: "error", message: t("documents.labels.reassign_limitexceeded_title"), description: t("documents.labels.reassign_limitexceeded") }); @@ -81,17 +80,17 @@ export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages, }) }); //Add in confirmation & errors. - if (callback) callback(); + if (isFunction(callback)) callback(); if (res.errors) { - notification["error"]({ + notification.error({ message: t("documents.errors.updating", { message: JSON.stringify(res.errors) }) }); } if (!res.mutationResult?.errors) { - notification["success"]({ + notification.success({ message: t("documents.successes.updated") }); } diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx index 156362ff1..61b009f13 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx @@ -17,6 +17,7 @@ import JobsDocumentsGalleryReassign from "./jobs-document-imgproxy-gallery.reass import JobsDocumentsDeleteButton from "./jobs-documents-imgproxy-gallery.delete.component"; import JobsDocumentsGallerySelectAllComponent from "./jobs-documents-imgproxy-gallery.selectall.component"; import i18n from "i18next"; +import { isFunction } from "lodash"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -40,19 +41,19 @@ function JobsDocumentsImgproxyComponent({ downloadIdentifier, ignoreSizeLimit }) { - const [galleryImages, setgalleryImages] = useState({ images: [], other: [] }); + const [galleryImages, setGalleryImages] = useState({ images: [], other: [] }); const { t } = useTranslation(); const [modalState, setModalState] = useState({ open: false, index: 0 }); const fetchThumbnails = () => { - fetchImgproxyThumbnails({ setStateCallback: setgalleryImages, jobId }); + fetchImgproxyThumbnails({ setStateCallback: setGalleryImages, jobId }); }; useEffect(() => { if (data) { fetchThumbnails(); } - }, [data, setgalleryImages]); + }, [data]); const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); @@ -65,7 +66,7 @@ function JobsDocumentsImgproxyComponent({ onClick={() => { //Handle any doc refresh. - refetch && refetch(); + isFunction(refetch) && refetch(); //Do the imgproxy refresh too fetchThumbnails(); @@ -73,7 +74,7 @@ function JobsDocumentsImgproxyComponent({ > - + { - setgalleryImages({ + setGalleryImages({ ...galleryImages, images: galleryImages.images.map((g, idx) => index === idx ? { ...g, isSelected: !g.isSelected } : g @@ -148,7 +149,7 @@ function JobsDocumentsImgproxyComponent({ window.open(galleryImages.other[index].source, "_blank", "toolbar=0,location=0,menubar=0"); }} onSelect={(index) => { - setgalleryImages({ + setGalleryImages({ ...galleryImages, other: galleryImages.other.map((g, idx) => (index === idx ? { ...g, isSelected: !g.isSelected } : g)) }); @@ -160,6 +161,7 @@ function JobsDocumentsImgproxyComponent({ { const newWindow = window.open( `${window.location.protocol}//${window.location.host}/edit?documentId=${ @@ -202,7 +204,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsImgprox export const fetchImgproxyThumbnails = async ({ setStateCallback, jobId, imagesOnly }) => { const result = await axios.post("/media/imgproxy/thumbnails", { jobid: jobId }); - let documents = result.data.reduce( + const documents = result.data.reduce( (acc, value) => { if (value.type.startsWith("image")) { acc.images.push({ @@ -259,9 +261,6 @@ export const fetchImgproxyThumbnails = async ({ setStateCallback, jobId, imagesO }, { images: [], other: [] } ); - if (imagesOnly) { - setStateCallback(documents.images); - } else { - setStateCallback(documents); - } + + setStateCallback(imagesOnly ? documents.images : documents); }; diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx index 72143531b..4701bca67 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.delete.component.jsx @@ -5,7 +5,7 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; - +import { isFunction } from "lodash"; /* ################################################################################################ @@ -34,22 +34,21 @@ export default function JobsDocumentsImgproxyDeleteButton({ galleryImages, delet }); if (res.data.error) { - notification["error"]({ + notification.error({ message: t("documents.errors.deleting", { error: JSON.stringify(res.data.error.response.errors) }) }); } else { - notification.open({ + notification.success({ key: "docdeletedsuccesfully", - type: "success", message: t("documents.successes.delete") }); - if (deletionCallback) deletionCallback(); + if (isFunction(deletionCallback)) deletionCallback(); } } catch (error) { - notification["error"]({ + notification.error({ message: t("documents.errors.deleting", { error: error.message }) diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 633a8a3c6..7d52542e5 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2253,7 +2253,7 @@ exports.UPDATE_PARTS_CRITICAL = `mutation UPDATE_PARTS_CRITICAL ($IdsToMarkCriti notcritical: update_joblines(where: {id: {_nin: $IdsToMarkCritical}, jobid: {_eq: $jobid}}, _set: {critical: false}) { affected_rows } -}`;; +}`; exports.ACTIVE_SHOP_BY_USER = `query ACTIVE_SHOP_BY_USER($user: String) { associations(where: {active: {_eq: true}, useremail: {_eq: $user}}) { @@ -2706,8 +2706,6 @@ exports.INSERT_AUDIT_TRAIL = ` } `; - - exports.GET_DOCUMENTS_BY_JOB = ` query GET_DOCUMENTS_BY_JOB($jobId: uuid!) { jobs_by_pk(id: $jobId) { From 787366b23114054e64a5e00c01ec3c6172a8b6b9 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 28 Feb 2025 09:32:16 -0800 Subject: [PATCH 10/45] IO-3092 Refactor exports. --- server/media/media.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/server/media/media.js b/server/media/media.js index 6706d3392..06b1c9bb8 100644 --- a/server/media/media.js +++ b/server/media/media.js @@ -11,12 +11,14 @@ require("dotenv").config({ var cloudinary = require("cloudinary").v2; cloudinary.config(process.env.CLOUDINARY_URL); -exports.createSignedUploadURL = (req, res) => { +const createSignedUploadURL = (req, res) => { logger.log("media-signed-upload", "DEBUG", req.user.email, null, null); res.send(cloudinary.utils.api_sign_request(req.body, process.env.CLOUDINARY_API_SECRET)); }; -exports.downloadFiles = (req, res) => { +exports.createSignedUploadURL = createSignedUploadURL; + +const downloadFiles = (req, res) => { const { ids } = req.body; logger.log("media-bulk-download", "DEBUG", req.user.email, ids, null); @@ -26,8 +28,9 @@ exports.downloadFiles = (req, res) => { }); res.send(url); }; +exports.downloadFiles = downloadFiles; -exports.deleteFiles = async (req, res) => { +const deleteFiles = async (req, res) => { const { ids } = req.body; const types = _.groupBy(ids, (x) => DetermineFileType(x.type)); @@ -88,7 +91,9 @@ exports.deleteFiles = async (req, res) => { } }; -exports.renameKeys = async (req, res) => { +exports.deleteFiles = deleteFiles; + +const renameKeys = async (req, res) => { const { documents, tojobid } = req.body; logger.log("media-bulk-rename", "DEBUG", req.user.email, null, documents); @@ -146,6 +151,7 @@ exports.renameKeys = async (req, res) => { res.json({ errors: "No images were succesfully moved on remote server. " }); } }; +exports.renameKeys = renameKeys; //Also needs to be updated in upload utility and mobile app. function DetermineFileType(filetype) { From 0810798d3019afba5591d334c8d685d494c4495c Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Tue, 4 Mar 2025 11:14:43 -0800 Subject: [PATCH 11/45] IO-3092 Remove compiler warnings. --- .../documents-upload-imgproxy.utility.js | 1 - .../jobs-documents-imgproxy-gallery.component.jsx | 12 ++++++------ ...documents-imgproxy-gallery.external.component.jsx | 10 ++-------- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js index 8fa7cb001..7ecbd50bb 100644 --- a/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js +++ b/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js @@ -5,7 +5,6 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries"; import { axiosAuthInterceptorId } from "../../utils/CleanAxios"; import client from "../../utils/GraphQLClient"; -import { error } from "logrocket"; //Context: currentUserEmail, bodyshop, jobid, invoiceid diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx index 61b009f13..a07ed0bf1 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.component.jsx @@ -1,7 +1,9 @@ import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Col, Row, Space } from "antd"; import axios from "axios"; -import { useEffect, useState } from "react"; +import i18n from "i18next"; +import { isFunction } from "lodash"; +import { useCallback, useEffect, useState } from "react"; import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import Lightbox from "react-image-lightbox"; @@ -16,8 +18,6 @@ import JobsDocumentsDownloadButton from "./jobs-document-imgproxy-gallery.downlo import JobsDocumentsGalleryReassign from "./jobs-document-imgproxy-gallery.reassign.component"; import JobsDocumentsDeleteButton from "./jobs-documents-imgproxy-gallery.delete.component"; import JobsDocumentsGallerySelectAllComponent from "./jobs-documents-imgproxy-gallery.selectall.component"; -import i18n from "i18next"; -import { isFunction } from "lodash"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -45,15 +45,15 @@ function JobsDocumentsImgproxyComponent({ const { t } = useTranslation(); const [modalState, setModalState] = useState({ open: false, index: 0 }); - const fetchThumbnails = () => { + const fetchThumbnails = useCallback(() => { fetchImgproxyThumbnails({ setStateCallback: setGalleryImages, jobId }); - }; + }, [jobId, setGalleryImages]); useEffect(() => { if (data) { fetchThumbnails(); } - }, [data]); + }, [data, fetchThumbnails]); const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" }); const hasMobileAccess = HasFeatureAccess({ bodyshop, featureName: "mobile" }); diff --git a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx index 75943dceb..a970b01b7 100644 --- a/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-imgproxy-gallery/jobs-documents-imgproxy-gallery.external.component.jsx @@ -1,6 +1,5 @@ import { useEffect } from "react"; import { Gallery } from "react-grid-gallery"; -import { useTranslation } from "react-i18next"; import { fetchImgproxyThumbnails } from "./jobs-documents-imgproxy-gallery.component"; /* @@ -13,15 +12,10 @@ import { fetchImgproxyThumbnails } from "./jobs-documents-imgproxy-gallery.compo function JobsDocumentImgproxyGalleryExternal({ jobId, externalMediaState }) { const [galleryImages, setgalleryImages] = externalMediaState; - const { t } = useTranslation(); - - const fetchThumbnails = () => { - fetchImgproxyThumbnails({ setStateCallback: setgalleryImages, jobId, imagesOnly: true }); - }; useEffect(() => { - fetchThumbnails(); - }, [jobId]); + if (jobId) fetchImgproxyThumbnails({ setStateCallback: setgalleryImages, jobId, imagesOnly: true }); + }, [jobId, setgalleryImages]); return (
From 4a9b0cae698c4d8f3fa3545463676107b08bc0e1 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 14 Mar 2025 21:47:03 -0700 Subject: [PATCH 12/45] IO-2999 IO Test Report Server Migration Signed-off-by: Allan Carr --- client/.env.development.imex | 2 +- client/.env.development.rome | 2 +- client/.env.test.imex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/.env.development.imex b/client/.env.development.imex index 968dbab37..ef94b0621 100644 --- a/client/.env.development.imex +++ b/client/.env.development.imex @@ -9,6 +9,6 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250 VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4' VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_AXIOS_BASE_API_URL=/api/ -VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online +VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_INSTANCE=IMEX diff --git a/client/.env.development.rome b/client/.env.development.rome index e0805f439..5d0c366fa 100644 --- a/client/.env.development.rome +++ b/client/.env.development.rome @@ -10,7 +10,7 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250 VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo' VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_AXIOS_BASE_API_URL=/api/ -VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online +VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_COUNTRY=USA VITE_APP_INSTANCE=ROME diff --git a/client/.env.test.imex b/client/.env.test.imex index a8a359f46..84167c4cb 100644 --- a/client/.env.test.imex +++ b/client/.env.test.imex @@ -9,7 +9,7 @@ VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250 VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo' VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g VITE_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/ -VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online +VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online VITE_APP_IS_TEST=true VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_INSTANCE=IMEX From 38119f7f1fb7856cbc1daaa64488e68f808f3d3b Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 19 Mar 2025 09:10:20 -0700 Subject: [PATCH 13/45] IO-3176 IntelliPay Payment Method Mapping Signed-off-by: Allan Carr --- .../shop-intellipay-config.component.jsx | 105 +- client/src/translations/en_us/common.json | 7546 +++++++++-------- client/src/translations/es/common.json | 7546 +++++++++-------- client/src/translations/fr/common.json | 7546 +++++++++-------- server/intellipay/intellipay.js | 5 +- 5 files changed, 11432 insertions(+), 11316 deletions(-) diff --git a/client/src/components/shop-info/shop-intellipay-config.component.jsx b/client/src/components/shop-info/shop-intellipay-config.component.jsx index 5c8ec7ee9..61529969d 100644 --- a/client/src/components/shop-info/shop-intellipay-config.component.jsx +++ b/client/src/components/shop-info/shop-intellipay-config.component.jsx @@ -1,11 +1,10 @@ -import { Alert, Form, Switch } from "antd"; -import React from "react"; +import { Alert, Form, Select, Switch } from "antd"; import { useTranslation } from "react-i18next"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {selectBodyshop} from "../../redux/user/user.selectors"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -16,17 +15,17 @@ const mapDispatchToProps = () => ({ export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoIntellipay); // noinspection JSUnusedLocalSymbols -export function ShopInfoIntellipay({bodyshop, form}) { - const {t} = useTranslation(); +export function ShopInfoIntellipay({ bodyshop, form }) { + const { t } = useTranslation(); return ( <> {() => { - const {intellipay_config} = form.getFieldsValue(); + const { intellipay_config } = form.getFieldsValue(); if (intellipay_config?.enable_cash_discount) - return ; + return ; }} @@ -36,7 +35,93 @@ export function ShopInfoIntellipay({bodyshop, form}) { valuePropName="checked" name={["intellipay_config", "enable_cash_discount"]} > - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 79c558d2f..5e062169a 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1,3772 +1,3782 @@ { - "translation": { - "allocations": { - "actions": { - "assign": "Assign" - }, - "errors": { - "deleting": "Error encountered while deleting allocation. {{message}}", - "saving": "Error while allocating. {{message}}", - "validation": "Please ensure all fields are entered correctly. " - }, - "fields": { - "employee": "Allocated To" - }, - "successes": { - "deleted": "Allocation deleted successfully.", - "save": "Allocated successfully. " - } - }, - "appointments": { - "actions": { - "block": "Block Day", - "calculate": "Calculate SMART Dates", - "cancel": "Cancel Appointment", - "intake": "Intake", - "new": "New Appointment", - "preview": "Preview", - "reschedule": "Reschedule", - "sendreminder": "Send Reminder", - "unblock": "Unblock", - "viewjob": "View Job" - }, - "errors": { - "blocking": "Error creating block {{message}}.", - "canceling": "Error canceling appointment. {{message}}", - "saving": "Error scheduling appointment. {{message}}" - }, - "fields": { - "alt_transport": "Alt. Trans.", - "color": "Appointment Color", - "end": "End", - "note": "Note", - "start": "Start", - "time": "Appointment Time", - "title": "Title" - }, - "labels": { - "arrivedon": "Arrived on: ", - "arrivingjobs": "Arriving Jobs", - "blocked": "Blocked", - "cancelledappointment": "Canceled appointment for: ", - "completingjobs": "Completing Jobs", - "dataconsistency": "<0>{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.", - "expectedjobs": "Expected Jobs in Production: ", - "expectedprodhrs": "Expected Production Hours:", - "history": "History", - "inproduction": "Jobs In Production", - "manualevent": "Add Manual Appointment", - "noarrivingjobs": "No Jobs are arriving.", - "nocompletingjobs": "No Jobs scheduled for completion.", - "nodateselected": "No date has been selected.", - "priorappointments": "Previous Appointments", - "reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ", - "scheduledfor": "Scheduled appointment for: ", - "severalerrorsfound": "Several Jobs have issues which may prevent accurate smart scheduling. Click to expand.", - "smartscheduling": "Smart Scheduling", - "smspaymentreminder": "This is {{shopname}} reminding you about your remaining balance of {{amount}}. To pay for the said balance click the link {{payment_link}}.", - "suggesteddates": "Suggested Dates" - }, - "successes": { - "canceled": "Appointment canceled successfully.", - "created": "Appointment scheduled successfully.", - "saved": "Appointment saved successfully." - } - }, - "associations": { - "actions": { - "activate": "Activate" - }, - "fields": { - "active": "Active?", - "shopname": "Shop Name" - }, - "labels": { - "actions": "Actions" - } - }, - "audit": { - "fields": { - "cc": "CC", - "contents": "Contents", - "created": "Time", - "operation": "Operation", - "status": "Status", - "subject": "Subject", - "to": "To", - "useremail": "User", - "values": "Values" - } - }, - "audit_trail": { - "messages": { - "admin_job_remove_from_ar": "ADMIN: Remove from AR updated to: {{status}}", - "admin_jobmarkexported": "ADMIN: Job marked as exported.", - "admin_jobmarkforreexport": "ADMIN: Job marked for re-export.", - "admin_jobuninvoice": "ADMIN: Job has been uninvoiced.", - "admin_jobunvoid": "ADMIN: Job has been unvoided.", - "alerttoggle": "Alert Toggle set to {{status}}", - "appointmentcancel": "Appointment canceled. Lost Reason: {{lost_sale_reason}}.", - "appointmentinsert": "Appointment created. Appointment Date: {{start}}.", - "assignedlinehours": "Assigned job lines totaling {{hours}} units to {{team}}.", - "billdeleted": "Bill with invoice number {{invoice_number}} deleted.", - "billposted": "Bill with invoice number {{invoice_number}} posted.", - "billupdated": "Bill with invoice number {{invoice_number}} updated.", - "failedpayment": "Failed payment attempt.", - "jobassignmentchange": "Employee {{name}} assigned to {{operation}}", - "jobassignmentremoved": "Employee assignment removed for {{operation}}", - "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.", - "jobclosedwithbypass": "Job was invoiced using the master bypass password. ", - "jobconverted": "Job converted and assigned number {{ro_number}}.", - "jobdelivery": "Job intake completed. Status set to {{status}}. Actual completion is {{actual_completion}}.", - "jobexported": "Job has been exported", - "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.", - "jobimported": "Job imported.", - "jobinproductionchange": "Job production status set to {{inproduction}}", - "jobintake": "Job intake completed. Status set to {{status}}. Scheduled completion is {{scheduled_completion}}.", - "jobinvoiced": "Job has been invoiced.", - "jobioucreated": "IOU Created.", - "jobmodifylbradj": "Labor adjustments modified {{mod_lbr_ty}} / {{hours}}.", - "jobnoteadded": "Note added to Job.", - "jobnotedeleted": "Note deleted from Job.", - "jobnoteupdated": "Note updated on Job.", - "jobspartsorder": "Parts order {{order_number}} added to Job.", - "jobspartsreturn": "Parts return {{order_number}} added to Job.", - "jobstatuschange": "Job status changed to {{status}}.", - "jobsupplement": "Job supplement imported.", - "jobsuspend": "Suspend Toggle set to {{status}}", - "jobvoid": "Job has been voided.", - "tasks_completed": "Task '{{title}}' completed by {{completedBy}}", - "tasks_created": "Task '{{title}}' created by {{createdBy}}", - "tasks_deleted": "Task '{{title}}' deleted by {{deletedBy}}", - "tasks_uncompleted": "Task '{{title}}' uncompleted by {{uncompletedBy}}", - "tasks_undeleted": "Task '{{title}}' undeleted by {{undeletedBy}}", - "tasks_updated": "Task '{{title}}' updated by {{updatedBy}}" - } - }, - "billlines": { - "actions": { - "newline": "New Line" - }, - "fields": { - "actual_cost": "Actual Cost", - "actual_price": "Retail", - "cost_center": "Cost Center", - "federal_tax_applicable": "Fed. Tax?", - "jobline": "Job Line", - "line_desc": "Line Description", - "local_tax_applicable": "Loc. Tax?", - "location": "Location", - "quantity": "Quantity", - "state_tax_applicable": "St. Tax?" - }, - "labels": { - "deductedfromlbr": "Deduct from Labor?", - "entered": "Entered", - "from": "From", - "mod_lbr_adjustment": "Adjustment Units", - "other": "-- Not On Estimate --", - "reconciled": "Reconciled!", - "unreconciled": "Unreconciled" - }, - "validation": { - "atleastone": "At least one bill line must be entered." - } - }, - "bills": { - "actions": { - "deductallhours": "Deduct all", - "edit": "Edit", - "receive": "Receive Part", - "return": "Return Items" - }, - "errors": { - "creating": "Error adding bill. {{error}}", - "deleting": "Error deleting bill. {{error}}", - "existinginventoryline": "This bill cannot be deleted as it is tied to items in inventory.", - "exporting": "Error exporting payable(s). {{error}}", - "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.", - "invalidro": "Not a valid RO.", - "invalidvendor": "Not a valid vendor.", - "validation": "Please ensure all fields are entered correctly. " - }, - "fields": { - "allpartslocation": "Parts Bin", - "date": "Bill Date", - "exported": "Exported", - "federal_tax_rate": "Federal Tax Rate", - "invoice_number": "Invoice Number", - "is_credit_memo": "Credit Memo?", - "is_credit_memo_short": "CM", - "local_tax_rate": "Local Tax Rate", - "ro_number": "RO Number", - "state_tax_rate": "State Tax Rate", - "total": "Bill Total", - "vendor": "Vendor", - "vendorname": "Vendor Name" - }, - "labels": { - "actions": "Actions", - "bill_lines": "Bill Lines", - "bill_total": "Bill Total Amount", - "billcmtotal": "Credit Memos", - "bills": "Bills", - "calculatedcreditsnotreceived": "Calculated CNR", - "creditsnotreceived": "Credits Not Marked Received", - "creditsreceived": "Credits Received", - "dedfromlbr": "Labor Adjustments", - "deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.", - "discrepancy": "Discrepancy", - "discrepwithcms": "Discrepancy including Credit Memos", - "discrepwithlbradj": "Discrepancy including Lbr. Adj.", - "editadjwarning": "This bill had lines which resulted in labor adjustments. Manual correction to adjustments may be required.", - "entered_total": "Total of Entered Lines", - "enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.", - "federal_tax": "Federal Tax", - "federal_tax_exempt": "Federal Tax Exempt?", - "generatepartslabel": "Generate Parts Labels after Saving?", - "iouexists": "An IOU exists that is associated to this RO.", - "local_tax": "Local Tax", - "markexported": "Mark Exported", - "markforreexport": "Mark for Re-export", - "new": "New Bill", - "nobilllines": "No bills have been posted yet.", - "noneselected": "No bill selected.", - "onlycmforinvoiced": "Only credit memos can be entered for any Job that has been invoiced, exported, or voided.", - "printlabels": "Print Labels", - "retailtotal": "Bills Retail Total", - "returnfrombill": "Return From Bill", - "savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.", - "state_tax": "State Tax", - "subtotal": "Subtotal", - "totalreturns": "Total Returns" - }, - "successes": { - "created": "Invoice added successfully.", - "deleted": "Bill deleted successfully.", - "exported": "Bill(s) exported successfully.", - "markexported": "Bill marked as exported.", - "reexport": "Bill marked for re-export." - }, - "validation": { - "closingperiod": "This Bill Date is outside of the Closing Period.", - "inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).", - "manualinhouse": "Manual posting to the in house vendor is restricted. ", - "unique_invoice_number": "This invoice number has already been entered for this vendor." - } - }, - "bodyshop": { - "actions": { - "add_task_preset": "Add Task Preset", - "addapptcolor": "Add Appointment Color", - "addbucket": "Add Definition", - "addpartslocation": "Add Parts Location", - "addpartsrule": "Add Parts Scan Rule", - "addspeedprint": "Add Speed Print", - "addtemplate": "Add Template", - "newlaborrate": "New Labor Rate", - "newsalestaxcode": "New Sales Tax Code", - "newstatus": "Add Status", - "testrender": "Test Render" - }, - "errors": { - "creatingdefaultview": "Error creating default view.", - "loading": "Unable to load shop details. Please call technical support.", - "saving": "Error encountered while saving. {{message}}" - }, - "fields": { - "ReceivableCustomField": "QBO Receivable Custom Field {{number}}", - "address1": "Address 1", - "address2": "Address 2", - "appt_alt_transport": "Appointment Alternative Transportation Options", - "appt_colors": { - "color": "Color", - "label": "Label" - }, - "appt_length": "Default Appointment Length", - "attach_pdf_to_email": "Attach PDF copy to sent emails?", - "batchid": "ADP Batch ID", - "bill_allow_post_to_closed": "Allow Bills to be posted to Closed Jobs", - "bill_federal_tax_rate": "Bills - Federal Tax Rate %", - "bill_local_tax_rate": "Bill - Local Tax Rate %", - "bill_state_tax_rate": "Bill - Provincial/State Tax Rate %", - "city": "City", - "closingperiod": "Closing Period", - "companycode": "ADP Company Code", - "country": "Country", - "dailybodytarget": "Scoreboard - Daily Body Target", - "dailypainttarget": "Scoreboard - Daily Paint Target", - "default_adjustment_rate": "Default Labor Deduction Adjustment Rate", - "deliver": { - "require_actual_delivery_date": "Require Actual Delivery", - "templates": "Delivery Templates" - }, - "dms": { - "apcontrol": "AP Control Number", - "appostingaccount": "AP Posting Account", - "cashierid": "Cashier ID", - "default_journal": "Default Journal", - "disablebillwip": "Disable bill WIP for A/P Posting", - "disablecontactvehiclecreation": "Disable Contact & Vehicle Updates/Creation", - "dms_acctnumber": "DMS Account #", - "dms_control_override": "Static Control # Override", - "dms_wip_acctnumber": "DMS W.I.P. Account #", - "generic_customer_number": "Generic Customer Number", - "itc_federal": "Federal Tax is ITC?", - "itc_local": "Local Tax is ITC?", - "itc_state": "State Tax is ITC?", - "mappingname": "DMS Mapping Name", - "sendmaterialscosting": "Materials Cost as % of Sale", - "srcco": "Source Company #/Dealer #" - }, - "email": "General Shop Email", - "enforce_class": "Enforce Class on Conversion?", - "enforce_conversion_category": "Enforce Category on Conversion?", - "enforce_conversion_csr": "Enforce CSR on Conversion?", - "enforce_referral": "Enforce Referrals", - "federal_tax_id": "Federal Tax ID (GST/HST)", - "ignoreblockeddays": "Scoreboard - Ignore Blocked Days", - "inhousevendorid": "In House Vendor ID", - "insurance_vendor_id": "Insurance Vendor ID", - "intake": { - "next_contact_hours": "Automatic Next Contact Date - Hours from Intake", - "templates": "Intake Templates" - }, - "intellipay_config": { - "cash_discount_percentage": "Cash Discount %", - "enable_cash_discount": "Enable Cash Discounting" - }, - "invoice_federal_tax_rate": "Invoices - Federal Tax Rate", - "invoice_local_tax_rate": "Invoices - Local Tax Rate", - "invoice_state_tax_rate": "Invoices - State Tax Rate", - "jc_hourly_rates": { - "mapa": "Job Costing - Paint Materials Hourly Cost Rate", - "mash": "Job Costing - Shop Materials Hourly Cost Rate" - }, - "last_name_first": "Display Owner Info as , ", - "lastnumberworkingdays": "Scoreboard - Last Number of Working Days", - "localmediaserverhttp": "Local Media Server - HTTP Path", - "localmediaservernetwork": "Local Media Server - Network Path", - "localmediatoken": "Local Media Server - Token", - "logo_img_footer_margin": "Footer Margin (px)", - "logo_img_header_margin": "Header Margin (px)", - "logo_img_path": "Shop Logo", - "logo_img_path_height": "Logo Image Height", - "logo_img_path_width": "Logo Image Width", - "md_categories": "Categories", - "md_ccc_rates": "Courtesy Car Contract Rate Presets", - "md_classes": "Classes", - "md_ded_notes": "Deductible Notes", - "md_email_cc": "Auto Email CC: $t(parts_orders.labels.{{template}})", - "md_from_emails": "Additional From Emails", - "md_functionality_toggles": { - "parts_queue_toggle": "Auto Add Imported/Supplemented Jobs to Parts Queue" - }, - "md_hour_split": { - "paint": "Paint Hour Split", - "prep": "Prep Hour Split" - }, - "md_ins_co": { - "city": "City", - "name": "Insurance Company Name", - "private": "Private", - "state": "Province/State", - "street1": "Street 1", - "street2": "Street 2", - "zip": "Zip/Postal Code" - }, - "md_jobline_presets": "Jobline Presets", - "md_lost_sale_reasons": "Lost Sale Reasons", - "md_parts_order_comment": "Parts Orders Comments", - "md_parts_scan": { - "caseInsensitive": "Case Insensitive", - "expression": "", - "field": "Field", - "flags": "", - "mark_critical": "Mark Line as Critical?", - "operation": "Operation", - "update_field": "Field to Update", - "update_value": "Update Value", - "value": "Value" - }, - "md_payment_types": "Payment Types", - "md_referral_sources": "Referral Sources", - "md_ro_guard": { - "enabled": "RO Guard Enabled?", - "enforce_ar": "Enforce AR Balance", - "enforce_bills": "Enforce Bill Discrepancy", - "enforce_cm": "Enforce Credit Memo Entry", - "enforce_labor": "Enforce Labor Allocation", - "enforce_ppd": "Enforce PPD Sync", - "enforce_profit": "Enforce Profit Requirement", - "enforce_sublet": "Enforce Sublet Completion", - "masterbypass": "Master Bypass Password (not encrypted)", - "totalgppercent_minimum": "Minimum Total Gross Profit %" - }, - "md_tasks_presets": { - "enable_tasks": "Enable Hour Flagging", - "hourstype": "Hour Types", - "memo": "Time Ticket Memo", - "name": "Preset Name", - "nextstatus": "Next Status", - "percent": "Percent", - "use_approvals": "Use Time Ticket Approval Queue" - }, - "messaginglabel": "Messaging Preset Label", - "messagingtext": "Messaging Preset Text", - "noteslabel": "Note Label", - "notestext": "Note Text", - "partslocation": "Parts Location", - "phone": "Phone", - "prodtargethrs": "Production Target Hours", - "rbac": { - "accounting": { - "exportlog": "Accounting -> Export Log", - "payables": "Accounting -> Payables", - "payments": "Accounting -> Payments", - "receivables": "Accounting -> Receivables" - }, - "bills": { - "delete": "Bills -> Delete", - "enter": "Bills -> Enter", - "list": "Bills -> List", - "reexport": "Bills -> Re-export", - "view": "Bills -> View" - }, - "contracts": { - "create": "Contracts -> Create", - "detail": "Contracts -> Detail", - "list": "Contracts -> List" - }, - "courtesycar": { - "create": "Courtesy Car -> Create", - "detail": "Courtesy Car -> Detail", - "list": "Courtesy Car -> List" - }, - "csi": { - "export": "CSI -> Export", - "page": "CSI -> Page" - }, - "employee_teams": { - "page": "Employee Teams -> List" - }, - "employees": { - "page": "Employees -> List" - }, - "inventory": { - "delete": "Inventory -> Delete", - "list": "Inventory -> List" - }, - "jobs": { - "admin": "Jobs -> Admin", - "available-list": "Jobs -> Available List", - "checklist-view": "Jobs -> Checklist View", - "close": "Jobs -> Close", - "create": "Jobs -> Create", - "deliver": "Jobs -> Deliver", - "detail": "Jobs -> Detail", - "intake": "Jobs -> Intake", - "list-active": "Jobs -> List Active", - "list-all": "Jobs -> List All", - "list-ready": "Jobs -> List Ready", - "partsqueue": "Jobs -> Parts Queue", - "void": "Jobs -> Void" - }, - "owners": { - "detail": "Owners -> Detail", - "list": "Owners -> List" - }, - "payments": { - "enter": "Payments -> Enter", - "list": "Payments -> List" - }, - "phonebook": { - "edit": "Phonebook -> Edit", - "view": "Phonebook -> View" - }, - "production": { - "board": "Production -> Board", - "list": "Production -> List" - }, - "schedule": { - "view": "Schedule -> View" - }, - "scoreboard": { - "view": "Scoreboard -> View" - }, - "shiftclock": { - "view": "Shift Clock -> View" - }, - "shop": { - "config": "Shop -> Config", - "dashboard": "Shop -> Dashboard", - "rbac": "Shop -> RBAC", - "reportcenter": "Shop -> Report Center", - "templates": "Shop -> Templates", - "vendors": "Shop -> Vendors" - }, - "temporarydocs": { - "view": "Temporary Docs -> View" - }, - "timetickets": { - "edit": "Time Tickets -> Edit", - "editcommitted": "Time Tickets -> Edit Committed", - "enter": "Time Tickets -> Enter", - "list": "Time Tickets -> List", - "shiftedit": "Time Tickets -> Shift Edit" - }, - "ttapprovals": { - "approve": "Time Ticket Approval -> Approve", - "view": "Time Ticket Approval -> View" - }, - "users": { - "editaccess": "Users -> Edit access" - } - }, - "responsibilitycenter": "Responsibility Center", - "responsibilitycenter_accountdesc": "Account Description", - "responsibilitycenter_accountitem": "Item", - "responsibilitycenter_accountname": "Account Name", - "responsibilitycenter_accountnumber": "Account Number", - "responsibilitycenter_rate": "Rate", - "responsibilitycenter_tax_rate": "Tax {{typeNum}} Tier {{typeNumIterator}} Rate", - "responsibilitycenter_tax_sur": "Tax {{typeNum}} Tier {{typeNumIterator}} Surcharge", - "responsibilitycenter_tax_thres": "Tax {{typeNum}} Tier {{typeNumIterator}} Threshold", - "responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}", - "responsibilitycenter_tax_type": "Tax {{typeNum}} Type", - "responsibilitycenters": { - "ap": "Accounts Payable", - "ar": "Accounts Receivable", - "ats": "ATS", - "federal_tax": "Federal Tax", - "federal_tax_itc": "Federal Tax Credit", - "gst_override": "GST Override Account #", - "invoiceexemptcode": "QuickBooks US - Invoice Tax Exempt Code", - "itemexemptcode": "QuickBooks US - Line Item Tax Exempt Code", - "la1": "LA1", - "la2": "LA2", - "la3": "LA3", - "la4": "LA4", - "laa": "Aluminum", - "lab": "Body", - "lad": "Diagnostic", - "lae": "Electrical", - "laf": "Frame", - "lag": "Glass", - "lam": "Mechanical", - "lar": "Refinish", - "las": "Structural", - "lau": "User Defined", - "local_tax": "Local Tax", - "mapa": "Paint Materials", - "mash": "Shop Materials", - "paa": "Aftermarket", - "pac": "Chrome", - "pag": "Glass", - "pal": "LKQ", - "pam": "Remanufactured", - "pan": "OEM", - "pao": "Other", - "pap": "OEM Partial", - "par": "Recored", - "pas": "Sublet", - "pasl": "Sublet (L)", - "refund": "Refund", - "sales_tax_codes": { - "code": "Code", - "description": "Description", - "federal": "Federal Tax Applies", - "local": "Local Tax Applies", - "state": "State Tax Applies" - }, - "state_tax": "State Tax", - "tow": "Towing" - }, - "schedule_end_time": "Schedule Ending Time", - "schedule_start_time": "Schedule Starting Time", - "shopname": "Shop Name", - "speedprint": { - "id": "Id", - "label": "Label", - "templates": "Templates" - }, - "ss_configuration": { - "dailyhrslimit": "Daily Incoming Hours Limit" - }, - "ssbuckets": { - "color": "Job Color", - "gte": "Greater Than/Equal to (hrs)", - "id": "ID", - "label": "Label", - "lt": "Less than (hrs)", - "target": "Target (count)" - }, - "state": "Province/State", - "state_tax_id": "State Tax ID", - "status": "Status Label", - "statuses": { - "active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)", - "additional_board_statuses": "Additional Status to Display on Production Board", - "color": "Color", - "default_arrived": "Default Arrived Status (Transition to Production)", - "default_bo": "Default Backordered Status", - "default_canceled": "Default Canceled Status", - "default_completed": "Default Completed Status", - "default_delivered": "Default Delivered Status (Transition to Post-Production)", - "default_exported": "Default Exported Status", - "default_imported": "Default Imported Status", - "default_invoiced": "Default Invoiced Status", - "default_ordered": "Default Ordered Status", - "default_quote": "Default Quote Status", - "default_received": "Default Received Status", - "default_returned": "Default Returned", - "default_scheduled": "Default Scheduled Status", - "default_void": "Default Void", - "open_statuses": "Open Statuses", - "post_production_statuses": "Post-Production Statuses", - "pre_production_statuses": "Pre-Production Statuses", - "production_colors": "Production Status Colors", - "production_statuses": "Production Statuses", - "ready_statuses": "Ready Statuses" - }, - "target_touchtime": "Target Touch Time", - "timezone": "Timezone", - "tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs", - "tt_enforce_hours_for_tech_console": "Restrict Claimable Hours", - "use_fippa": "Conceal Customer Information on Generated Documents?", - "use_paint_scale_data": "Use Paint Scale Data for Job Costing?", - "uselocalmediaserver": "Use Local Media Server?", - "website": "Website", - "zip_post": "Zip/Postal Code" - }, - "labels": { - "2tiername": "Name => RO", - "2tiersetup": "2 Tier Setup", - "2tiersource": "Source => RO", - "accountingsetup": "Accounting Setup", - "accountingtiers": "Number of Tiers to Use for Export", - "alljobstatuses": "All Job Statuses", - "allopenjobstatuses": "All Open Job Statuses", - "apptcolors": "Appointment Colors", - "businessinformation": "Business Information", - "checklists": "Checklists", - "csiq": "CSI Questions", - "customtemplates": "Custom Templates", - "defaultcostsmapping": "Default Costs Mapping", - "defaultprofitsmapping": "Default Profits Mapping", - "deliverchecklist": "Delivery Checklist", - "dms": { - "cdk": { - "controllist": "Control Number List", - "payers": "Payers" - }, - "cdk_dealerid": "CDK Dealer ID", - "costsmapping": "Costs Mapping", - "dms_allocations": "DMS Allocations", - "pbs_serialnumber": "PBS Serial Number", - "profitsmapping": "Profits Mapping", - "title": "DMS" - }, - "emaillater": "Email Later", - "employee_teams": "Employee Teams", - "employees": "Employees", - "estimators": "Estimators", - "filehandlers": "Adjusters", - "imexpay": "ImEX Pay", - "insurancecos": "Insurance Companies", - "intakechecklist": "Intake Checklist", - "intellipay_cash_discount": "Please ensure that cash discounting has been enabled on your merchant account. Reach out to IntelliPay Support if you need assistance. ", - "jobstatuses": "Job Statuses", - "laborrates": "Labor Rates", - "licensing": "Licensing", - "md_parts_scan": "Parts Scan Rules", - "md_ro_guard": "RO Guard", - "md_tasks_presets": "Tasks Presets", - "md_to_emails": "Preset To Emails", - "md_to_emails_emails": "Emails", - "messagingpresets": "Messaging Presets", - "notemplatesavailable": "No templates available to add.", - "notespresets": "Notes Presets", - "orderstatuses": "Order Statuses", - "partslocations": "Parts Locations", - "partsscan": "Parts Scanning", - "printlater": "Print Later", - "qbo": "Use QuickBooks Online?", - "qbo_departmentid": "QBO Department ID", - "qbo_usa": "QBO USA Compatibility", - "rbac": "Role Based Access Control", - "responsibilitycenters": { - "costs": "Cost Centers", - "profits": "Profit Centers", - "sales_tax_codes": "Sales Tax Codes", - "tax_accounts": "Tax Accounts", - "title": "Responsibility Centers", - "ttl_adjustment": "Subtotal Adjustment Account", - "ttl_tax_adjustment": "Tax Adjustment Account" - }, - "roguard": { - "title": "RO Guard" - }, - "romepay": "Rome Pay", - "scheduling": "SMART Scheduling", - "scoreboardsetup": "Scoreboard Setup", - "shop_enabled_features": "Shop Enabled Features", - "shopinfo": "Shop Information", - "speedprint": "Speed Print Configuration", - "ssbuckets": "Job Size Definitions", - "systemsettings": "System Settings", - "task-presets": "Task Presets", - "workingdays": "Working Days" - }, - "operations": { - "contains": "Contains", - "ends_with": "Ends With", - "equals": "Equals", - "greater_than": "Greater Than", - "less_than": "Less Than", - "not_equals": "Not Equals", - "starts_with": "Starts With" - }, - "successes": { - "areyousure": "Are you sure you want to continue?", - "defaultviewcreated": "Default view created successfully.", - "save": "Shop configuration saved successfully. ", - "unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?" - }, - "tooltips": { - "md_parts_scan": { - "update_value_tooltip": "Some fields require coded values in order to function properly (e.g. labor and part types). Please reach out to support if you have any questions." - } - }, - "validation": { - "centermustexist": "The chosen responsibility center does not exist.", - "larsplit": "Refinish hour split must add up to 1.", - "useremailmustexist": "This email is not a valid user." - } - }, - "checklist": { - "actions": { - "printall": "Print All Documents" - }, - "errors": { - "complete": "Error during Job checklist completion. {{error}}", - "nochecklist": "No checklist has been configured for your shop. " - }, - "labels": { - "addtoproduction": "Add Job to Production?", - "allow_text_message": "Permission to Text?", - "checklist": "Checklist", - "printpack": "Job Intake Print Pack", - "removefromproduction": "Remove Job from Production?" - }, - "successes": { - "completed": "Job checklist completed." - } - }, - "contracts": { - "actions": { - "changerate": "Change Contract Rates", - "convertoro": "Convert to RO", - "decodelicense": "Decode License", - "find": "Find Contract", - "printcontract": "Print Contract", - "senddltoform": "Insert Driver's License Information" - }, - "errors": { - "fetchingjobinfo": "Error fetching Job Info. {{error}}.", - "returning": "Error returning Courtesy Car. {{error}}", - "saving": "Error saving Contract. {{error}}", - "selectjobandcar": "Please ensure both a car and job are selected." - }, - "fields": { - "actax": "A/C Tax", - "actualreturn": "Actual Return Date", - "agreementnumber": "Agreement Number", - "cc_cardholder": "Cardholder Name", - "cc_expiry": "Credit Card Expiry Date", - "cc_num": "Credit Card Number", - "cleanupcharge": "Clean Up Charge", - "coverage": "Coverage", - "dailyfreekm": "Daily Free Mileage", - "dailyrate": "Daily Rate", - "damage": "Existing Damage", - "damagewaiver": "Damage Waiver", - "driver": "Driver", - "driver_addr1": "Driver Address 1", - "driver_addr2": "Driver Address 2", - "driver_city": "Driver City", - "driver_dlexpiry": "Driver's License Expiration Date", - "driver_dlnumber": "Driver's License Number", - "driver_dlst": "Driver's License Province/State", - "driver_dob": "Driver's DOB", - "driver_fn": "Driver's First Name", - "driver_ln": "Driver's Last Name", - "driver_ph1": "Driver's Phone", - "driver_state": "Driver's Province/State ", - "driver_zip": "Driver's Postal/ZIP Code", - "excesskmrate": "Excess Mileage", - "federaltax": "Federal Taxes", - "fuelin": "Fuel In", - "fuelout": "Fuel Out", - "kmend": "Mileage End", - "kmstart": "Mileage Start", - "length": "Length", - "localtax": "Local Taxes", - "refuelcharge": "Refuel Charge (per liter/gallon)", - "scheduledreturn": "Scheduled Return", - "start": "Contract Start", - "statetax": "Provincial/State Taxes", - "status": "Status" - }, - "labels": { - "agreement": "Agreement {{agreement_num}} - {{status}}", - "availablecars": "Available Cars", - "cardueforservice": "The courtesy car is due for servicing.", - "convertform": { - "applycleanupcharge": "Apply cleanup charge?", - "refuelqty": "Refuel qty.?" - }, - "correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.", - "dateinpast": "Date is in the past.", - "dlexpirebeforereturn": "The driver's license expires before the car is expected to return. ", - "driverinformation": "Driver's Information", - "findcontract": "Find Contract", - "findermodal": "Contract Finder", - "insuranceexpired": "The courtesy car insurance expires before the car is expected to return.", - "noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.", - "populatefromjob": "Populate from Job", - "rates": "Contract Rates", - "time": "Time", - "vehicle": "Vehicle", - "waitingforscan": "Please scan driver's license barcode..." - }, - "status": { - "new": "New Contract", - "out": "Out", - "returned": "Returned" - }, - "successes": { - "saved": "Contract saved successfully. " - } - }, - "courtesycars": { - "actions": { - "new": "New Courtesy Car", - "return": "Return Car" - }, - "errors": { - "saving": "Error saving Courtesy Car. {{error}}" - }, - "fields": { - "color": "Color", - "dailycost": "Daily Cost to Rent", - "damage": "Damage", - "fleetnumber": "Fleet Number", - "fuel": "Fuel Level", - "insuranceexpires": "Insurance Expires On", - "leaseenddate": "Lease Ends On", - "make": "Make", - "mileage": "Mileage", - "model": "Model", - "nextservicedate": "Next Service Date", - "nextservicekm": "Next Service KMs", - "notes": "Notes", - "plate": "Plate Number", - "purchasedate": "Purchase Date", - "readiness": "Readiness", - "registrationexpires": "Registration Expires On", - "serviceenddate": "Usage End Date", - "servicestartdate": "Usage Start Date", - "status": "Status", - "vin": "VIN", - "year": "Year" - }, - "labels": { - "courtesycar": "Courtesy Car", - "fuel": { - "12": "1/2", - "14": "1/4", - "18": "1/8", - "34": "3/4", - "38": "3/8", - "58": "5/8", - "78": "7/8", - "empty": "Empty", - "full": "Full" - }, - "outwith": "Out With", - "return": "Return Courtesy Car", - "status": "Status", - "uniquefleet": "Enter a unique fleet number.", - "usage": "Usage", - "vehicle": "Vehicle Description" - }, - "readiness": { - "notready": "Not Ready", - "ready": "Ready" - }, - "status": { - "in": "Available", - "inservice": "Service/Maintenance", - "leasereturn": "Lease Returned", - "out": "Rented", - "sold": "Sold", - "unavailable": "Unavailable" - }, - "successes": { - "saved": "Courtesy Car saved successfully." - } - }, - "csi": { - "actions": { - "activate": "Activate" - }, - "errors": { - "creating": "Error creating survey {{message}}", - "notconfigured": "You do not have any current CSI Question Sets configured.", - "notfoundsubtitle": "We were unable to find a survey using the link you provided. Please ensure the URL is correct or reach out to your shop for more help.", - "notfoundtitle": "No survey found.", - "surveycompletesubtitle": "", - "surveycompletetitle": "" - }, - "fields": { - "completedon": "Completed On", - "created_at": "Created At", - "surveyid": "", - "validuntil": "" - }, - "labels": { - "copyright": "", - "greeting": "", - "intro": "", - "nologgedinuser": "Please log out of {{app}}", - "nologgedinuser_sub": "Users of {{app}} cannot complete CSI surveys while logged in. Please log out and try again.", - "noneselected": "No response selected.", - "title": "Customer Satisfaction Survey" - }, - "successes": { - "created": "CSI created successfully. ", - "submitted": "Your responses have been submitted successfully.", - "submittedsub": "Your input is highly appreciated." - } - }, - "dashboard": { - "actions": { - "addcomponent": "Add Component" - }, - "errors": { - "refreshrequired": "You must refresh the dashboard data to see this component.", - "updatinglayout": "Error saving updated layout {{message}}" - }, - "labels": { - "bodyhrs": "Body Hrs", - "dollarsinproduction": "Dollars in Production", - "phone": "Phone", - "prodhrs": "Production Hrs", - "refhrs": "Refinish Hrs" - }, - "titles": { - "joblifecycle": "Job Life Cycles", - "labhours": "Total Body Hours", - "larhours": "Total Refinish Hours", - "monthlyemployeeefficiency": "Monthly Employee Efficiency", - "monthlyjobcosting": "Monthly Job Costing ", - "monthlylaborsales": "Monthly Labor Sales", - "monthlypartssales": "Monthly Parts Sales", - "monthlyrevenuegraph": "Monthly Revenue Graph", - "prodhrssummary": "Production Hours Summary", - "productiondollars": "Total Dollars in Production", - "productionhours": "Total Hours in Production", - "projectedmonthlysales": "Projected Monthly Sales", - "scheduledindate": "Scheduled In Today: {{date}}", - "scheduledintoday": "Scheduled In Today", - "scheduledoutdate": "Scheduled Out Today: {{date}}", - "scheduledouttoday": "Scheduled Out Today", - "tasks": "Tasks" - } - }, - "dms": { - "errors": { - "alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export." - }, - "labels": { - "refreshallocations": "Refresh to see DMS Allocataions." - } - }, - "documents": { - "actions": { - "delete": "Delete Selected Documents", - "download": "Download Selected Images", - "reassign": "Reassign to another Job", - "selectallimages": "Select All Images", - "selectallotherdocuments": "Select All Other Documents" - }, - "errors": { - "deletes3": "Error deleting document from storage. ", - "deleting": "Error deleting documents {{error}}", - "deleting_cloudinary": "Error deleting document from storage. {{message}}", - "getpresignurl": "Error obtaining presigned URL for document. {{message}}", - "insert": "Unable to upload file. {{message}}", - "nodocuments": "There are no documents.", - "updating": "Error updating document. {{error}}" - }, - "labels": { - "confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.", - "doctype": "Document Type", - "dragtoupload": "Click or drag files to this area to upload", - "newjobid": "Assign to Job", - "openinexplorer": "Open in Explorer", - "optimizedimage": "The below image is optimized. Click on the picture below to open in a new window and view it full size, or open it in explorer.", - "reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ", - "reassign_limitexceeded_title": "Unable to reassign document(s)", - "storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.", - "storageexceeded_title": "Storage Limit Exceeded", - "upload": "Upload", - "upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ", - "upload_limitexceeded_title": "Unable to upload document(s)", - "uploading": "Uploading...", - "usage": "of Job storage used. ({{used}} / {{total}})" - }, - "successes": { - "delete": "Document(s) deleted successfully.", - "edituploaded": "Edited document uploaded successfully. Please close this window and refresh the documents list.", - "insert": "Uploaded document successfully. ", - "updated": "Document updated successfully. " - } - }, - "emails": { - "errors": { - "notsent": "Email not sent. Error encountered while sending {{message}}" - }, - "fields": { - "cc": "CC", - "from": "From", - "subject": "Subject", - "to": "To" - }, - "labels": { - "attachments": "Attachments", - "documents": "Documents", - "emailpreview": "Email Preview", - "generatingemail": "Generating email...", - "pdfcopywillbeattached": "A PDF copy of this email will be attached when it is sent.", - "preview": "Email Preview" - }, - "successes": { - "sent": "Email sent successfully." - } - }, - "employee_teams": { - "actions": { - "new": "New Team", - "newmember": "New Team Member" - }, - "fields": { - "active": "Active", - "employeeid": "Employee", - "max_load": "Max Load", - "name": "Team Name", - "percentage": "Percent" - } - }, - "employees": { - "actions": { - "addvacation": "Add Vacation", - "new": "New Employee", - "newrate": "New Rate" - }, - "errors": { - "delete": "Error encountered while deleting employee. {{message}}", - "save": "Error encountered saving employee. {{message}}", - "validation": "Please check all fields.", - "validationtitle": "Unable to save employee." - }, - "fields": { - "active": "Active?", - "base_rate": "Base Rate", - "cost_center": "Cost Center", - "employee_number": "Employee Number", - "external_id": "External Employee ID", - "first_name": "First Name", - "flat_rate": "Flat Rate (Disabled is Straight Time)", - "hire_date": "Hire Date", - "last_name": "Last Name", - "pin": "Tech Console PIN", - "rate": "Rate", - "termination_date": "Termination Date", - "user_email": "User Email", - "vacation": { - "end": "Vacation End", - "length": "Vacation Length", - "start": "Vacation Start" - } - }, - "labels": { - "actions": "Actions", - "active": "Active", - "endmustbeafterstart": "End date must be after start date.", - "flat_rate": "Flat Rate", - "inactive": "Inactive", - "name": "Name", - "rate_type": "Rate Type", - "status": "Status", - "straight_time": "Straight Time" - }, - "successes": { - "delete": "Employee deleted successfully.", - "save": "Employee saved successfully.", - "vacationadded": "Employee vacation added." - }, - "validation": { - "unique_employee_number": "You must enter a unique employee number." - } - }, - "eula": { - "buttons": { - "accept": "Accept EULA" - }, - "content": { - "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." - }, - "errors": { - "acceptance": { - "description": "Something went wrong while accepting the EULA. Please try again.", - "message": "Eula Acceptance Error" - } - }, - "labels": { - "accepted_terms": "I accept the terms and conditions of this agreement.", - "address": "Address", - "business_name": "Legal Business Name", - "date_accepted": "Date Accepted", - "first_name": "First Name", - "last_name": "Last Name", - "phone_number": "Phone Number" - }, - "messages": { - "accepted_terms": "Please accept the terms and conditions of this agreement.", - "business_name": "Please enter your legal business name.", - "date_accepted": "Please enter Today's Date.", - "first_name": "Please enter your first name.", - "last_name": "Please enter your last name.", - "phone_number": "Please enter your phone number." - }, - "titles": { - "modal": "Terms and Conditions", - "upper_card": "Acknowledgement" - } - }, - "exportlogs": { - "fields": { - "createdat": "Created At" - }, - "labels": { - "attempts": "Export Attempts", - "priorsuccesfulexport": "This record has previously been exported successfully. Please make sure it has already been deleted in the target system." - } - }, - "general": { - "actions": { - "add": "Add", - "autoupdate": "{{app}} will automatically update in {{time}} seconds. Please save all changes.", - "calculate": "Calculate", - "cancel": "Cancel", - "clear": "Clear", - "close": "Close", - "copied": "Copied!", - "copylink": "Copy Link", - "create": "Create", - "defaults": "Defaults", - "delay": "Delay Update (5 mins)", - "delete": "Delete", - "deleteall": "Delete All", - "deselectall": "Deselect All", - "download": "Download", - "edit": "Edit", - "login": "Login", - "next": "Next", - "ok": "Ok", - "previous": "Previous", - "print": "Print", - "refresh": "Refresh", - "remove": "Remove", - "remove_alert": "Are you sure you want to dismiss the alert?", - "reset": "Reset your changes.", - "resetpassword": "Reset Password", - "save": "Save", - "saveandnew": "Save and New", - "saveas": "Save As", - "selectall": "Select All", - "send": "Send", - "sendbysms": "Send by SMS", - "senderrortosupport": "Send Error to Support", - "sharetoteams": "Share to Teams", - "submit": "Submit", - "tryagain": "Try Again", - "view": "View", - "viewreleasenotes": "See What's Changed" - }, - "errors": { - "fcm": "You must allow notification permissions to have real time messaging. Click to try again.", - "notfound": "No record was found.", - "sizelimit": "The selected items exceed the size limit." - }, - "itemtypes": { - "contract": "CC Contract", - "courtesycar": "Courtesy Car", - "job": "Job", - "owner": "Owner", - "vehicle": "Vehicle" - }, - "labels": { - "actions": "Actions", - "areyousure": "Are you sure?", - "barcode": "Barcode", - "cancel": "Are you sure you want to cancel? Your changes will not be saved.", - "clear": "Clear", - "confirmpassword": "Confirm Password", - "created_at": "Created At", - "date": "Select Date", - "datetime": "Select Date & Time", - "email": "Email", - "errors": "Errors", - "excel": "Excel", - "exceptiontitle": "An error has occurred.", - "friday": "Friday", - "globalsearch": "Global Search", - "help": "Help", - "hours": "hrs", - "in": "In", - "instanceconflictext": "Your {{app}} account can only be used on one device at any given time. Refresh your session to take control.", - "instanceconflictitle": "Your account is being used elsewhere.", - "item": "Item", - "label": "Label", - "loading": "Loading...", - "loadingapp": "Loading {{app}}", - "loadingshop": "Loading shop data...", - "loggingin": "Authorizing...", - "markedexported": "Manually marked as exported.", - "media": "Media", - "message": "Message", - "monday": "Monday", - "na": "N/A", - "newpassword": "New Password", - "no": "No", - "nointernet": "It looks like you're not connected to the internet.", - "nointernet_sub": "Please check your connection and try again. ", - "none": "None", - "out": "Out", - "password": "Password", - "passwordresetsuccess": "A password reset link has been sent to you.", - "passwordresetsuccess_sub": "You should receive this email in the next few minutes. Please check your email including any junk or spam folders. ", - "passwordresetvalidatesuccess": "Password successfully reset. ", - "passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ", - "passwordsdonotmatch": "The passwords you have entered do not match.", - "print": "Print", - "refresh": "Refresh", - "reports": "Reports", - "required": "Required", - "saturday": "Saturday", - "search": "Search...", - "searchresults": "Results for {{search}}", - "selectdate": "Select date...", - "sendagain": "Send Again", - "sendby": "Send By", - "signin": "Sign In", - "sms": "SMS", - "status": "Status", - "sub_status": { - "expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. " - }, - "successful": "Successful", - "sunday": "Sunday", - "text": "Text", - "thursday": "Thursday", - "time": "Select Time", - "total": "Total", - "totals": "Totals", - "tuesday": "Tuesday", - "tvmode": "TV Mode", - "unknown": "Unknown", - "unsavedchanges": "Unsaved changes.", - "username": "Username", - "view": "View", - "wednesday": "Wednesday", - "yes": "Yes" - }, - "languages": { - "english": "English", - "french": "French", - "spanish": "Spanish" - }, - "messages": { - "exception": "{{app}} has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.", - "newversionmessage": "Click refresh below to update to the latest available version of {{app}}. Please make sure all other tabs and windows are closed.", - "newversiontitle": "New version of {{app}} Available", - "noacctfilepath": "There is no accounting file path set. You will not be able to export any items.", - "nofeatureaccess": "You do not have access to this feature of {{app}}. Please contact support to request a license for this feature.", - "noshop": "You do not have access to any shops. Please reach out to your shop manager or technical support. ", - "notfoundsub": "Please make sure that you have access to the data or that the link is correct.", - "notfoundtitle": "We couldn't find what you're looking for...", - "partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.", - "rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.", - "unsavedchanges": "You have unsaved changes.", - "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?" - }, - "validation": { - "dateRangeExceeded": "The date range has been exceeded.", - "invalidemail": "Please enter a valid email.", - "invalidphone": "Please enter a valid phone number.", - "required": "{{label}} is required." - } - }, - "help": { - "actions": { - "connect": "Connect" - }, - "labels": { - "codeplacholder": "6 digit PIN code", - "rescuedesc": "Enter the 6 digit code provided by {{app}} Support below and click connect.", - "rescuetitle": "Rescue Me!" - } - }, - "intake": { - "labels": { - "printpack": "Intake Print Pack" - } - }, - "inventory": { - "actions": { - "addtoinventory": "Add to Inventory", - "addtoro": "Add to RO", - "consumefrominventory": "Consume from Inventory?", - "edit": "Edit Inventory LIne", - "new": "New Inventory Line" - }, - "errors": { - "inserting": "Error inserting inventory item. {{error}}" - }, - "fields": { - "comment": "Comment", - "manualinvoicenumber": "Invoice Number", - "manualvendor": "Vendor" - }, - "labels": { - "consumedbyjob": "Consumed by Job", - "deleteconfirm": "Are you sure you want to delete this from inventory? The associated bill will not be modified or deleted. ", - "frombillinvoicenumber": "Original Bill Invoice Number", - "fromvendor": "Original Bill Vendor", - "inventory": "Inventory", - "showall": "Show All Inventory", - "showavailable": "Show Only Available Inventory" - }, - "successes": { - "deleted": "Inventory lined deleted.", - "inserted": "Added line to inventory.", - "updated": "Inventory line updated." - } - }, - "job_lifecycle": { - "columns": { - "average_human_readable": "Average Human Readable", - "average_value": "Average Value", - "duration": "Duration", - "end": "End", - "human_readable": "Human Readable", - "percentage": "Percentage", - "relative_end": "Relative End", - "relative_start": "Relative Start", - "start": "Start", - "status": "Status", - "status_count": "In Status", - "value": "Value" - }, - "content": { - "calculated_based_on": "Calculated based on", - "current_status_accumulated_time": "Current Status Accumulated Time", - "data_unavailable": " There is currently no Lifecycle data for this Job.", - "jobs_in_since": "Jobs in since", - "legend_title": "Legend", - "loading": "Loading Job Timelines....", - "not_available": "N/A", - "previous_status_accumulated_time": "Previous Status Accumulated Time", - "title": "Job Lifecycle Component", - "title_durations": "Historical Status Durations", - "title_loading": "Loading", - "title_transitions": "Transitions" - }, - "errors": { - "fetch": "Error getting Job Lifecycle Data" - }, - "titles": { - "dashboard": "Job Lifecycle", - "top_durations": "Top Durations" - } - }, - "job_payments": { - "buttons": { - "create_short_link": "Generate Short Link", - "goback": "Go Back", - "proceedtopayment": "Proceed to Payment", - "refundpayment": "Refund Payment" - }, - "notifications": { - "error": { - "description": "Please try again. Make sure the refund amount does not exceeds the payment amount.", - "openingip": "Error connecting to IntelliPay service.", - "title": "Error placing refund" - } - }, - "titles": { - "amount": "Amount", - "dateOfPayment": "Date of Payment", - "descriptions": "Payment Details", - "hint": "Hint", - "payer": "Payer", - "payername": "Payer Name", - "paymentid": "Payment Reference ID", - "paymentnum": "Payment Number", - "paymenttype": "Payment Type", - "refundamount": "Refund Amount", - "transactionid": "Transaction ID" - } - }, - "joblines": { - "actions": { - "assign_team": "Assign Team", - "converttolabor": "Convert amount to Labor.", - "dispatchparts": "Dispatch Parts ({{count}})", - "new": "New Line" - }, - "errors": { - "creating": "Error encountered while creating job line. {{message}}", - "updating": "Error encountered updating job line. {{message}}" - }, - "fields": { - "act_price": "Retail Price", - "act_price_before_ppc": "Original Part Price", - "adjustment": "Adjustment", - "ah_detail_line": "Mark as Detail Labor Line (Autohouse Only)", - "alt_partno": "Alt Part #", - "amount": "Amount", - "assigned_team": "Team", - "assigned_team_name": "Team {{name}}", - "create_ppc": "Create PPC?", - "db_price": "List Price", - "include_in_part_cnt": "Include in Parts Status Count", - "lbr_types": { - "LA1": "LA1", - "LA2": "LA2", - "LA3": "LA3", - "LA4": "LA4", - "LAA": "Aluminum", - "LAB": "Body", - "LAD": "Diagnostic", - "LAE": "Electrical", - "LAF": "Frame", - "LAG": "Glass", - "LAM": "Mechanical", - "LAR": "Refinish", - "LAS": "Structural", - "LAU": "User Defined" - }, - "line_desc": "Line Desc.", - "line_ind": "S#", - "line_no": "Line #", - "location": "Location", - "mod_lb_hrs": "Hrs", - "mod_lbr_ty": "Labor Type", - "notes": "Notes", - "oem_partno": "OEM Part #", - "op_code_desc": "Op Code Description", - "part_qty": "Qty.", - "part_type": "Part Type", - "part_types": { - "CCC": "CC Cleaning", - "CCD": "CC Damage Waiver", - "CCDR": "CC Daily Rate", - "CCF": "CC Refuel", - "CCM": "CC Mileage", - "PAA": "Aftermarket", - "PAC": "Rechromed", - "PAE": "Existing", - "PAG": "Glass", - "PAL": "LKQ", - "PAM": "Remanufactured", - "PAN": "New/OEM", - "PAO": "Other", - "PAP": "OEM Partial", - "PAR": "Recored", - "PAS": "Sublet", - "PASL": "Sublet (L)" - }, - "profitcenter_labor": "Profit Center: Labor", - "profitcenter_part": "Profit Center: Part", - "prt_dsmk_m": "Line Discount/Markup $", - "prt_dsmk_p": "Line Discount/Markup %", - "status": "Status", - "tax_part": "Tax Part", - "total": "Total", - "unq_seq": "Seq #" - }, - "labels": { - "adjustmenttobeadded": "Adjustment to be added: {{adjustment}}", - "billref": "Latest Bill", - "convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.", - "edit": "Edit Line", - "ioucreated": "IOU", - "new": "New Line", - "nostatus": "No Status", - "presets": "Jobline Presets" - }, - "successes": { - "created": "Job line created successfully.", - "saved": "Job line saved.", - "updated": "Job line updated successfully." - }, - "validations": { - "ahdetailonlyonuserdefinedtypes": "Detail line indicator can only be set for LA1, LA2, LA3, LA4, and LAU labor types.", - "hrsrequirediflbrtyp": "Labor hours are required if a labor type is selected. Clear the labor type if there are no labor hours.", - "requiredifparttype": "Required if a part type has been specified.", - "zeropriceexistingpart": "This line cannot have any price since it uses an existing part." - } - }, - "jobs": { - "actions": { - "addDocuments": "Add Job Documents", - "addNote": "Add Note", - "addtopartsqueue": "Add to Parts Queue", - "addtoproduction": "Add to Production", - "addtoscoreboard": "Add to Scoreboard", - "allocate": "Allocate", - "autoallocate": "Auto Allocate", - "changefilehandler": "Change Adjuster", - "changelaborrate": "Change Labor Rate", - "changestatus": "Change Status", - "changestimator": "Change Estimator", - "convert": "Convert", - "createiou": "Create IOU", - "deliver": "Deliver", - "deliver_quick": "Quick Deliver", - "dms": { - "addpayer": "Add Payer", - "createnewcustomer": "Create New Customer", - "findmakemodelcode": "Find Make/Model Code", - "getmakes": "Get Makes", - "labels": { - "refreshallocations": "Refresh this component to see the DMS allocations." - }, - "post": "Post", - "refetchmakesmodels": "Refetch Make and Model Codes", - "usegeneric": "Use Generic Customer", - "useselected": "Use Selected Customer" - }, - "dmsautoallocate": "DMS Auto Allocate", - "export": "Export", - "exportcustdata": "Export Customer Data", - "exportselected": "Export Selected", - "filterpartsonly": "Filter Parts Only", - "generatecsi": "Generate CSI & Copy Link", - "gotojob": "Go to Job", - "intake": "Intake", - "intake_quick": "Quick Intake", - "manualnew": "Create New Job Manually", - "mark": "Mark", - "markasexported": "Mark as Exported", - "markpstexempt": "Mark Job PST Exempt", - "markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.", - "postbills": "Post Bills", - "printCenter": "Print Center", - "recalculate": "Recalculate", - "reconcile": "Reconcile", - "removefromproduction": "Remove from Production", - "schedule": "Schedule", - "sendcsi": "Send CSI", - "sendpartspricechange": "Send Parts Price Change", - "sendtodms": "Send to DMS", - "sync": "Sync", - "taxprofileoverride": "Override Tax Profile with Shop Configuration", - "taxprofileoverride_confirm": "Are you sure you want to override the tax profile information? This cannot be undone without re-importing the job. ", - "uninvoice": "Uninvoice", - "unvoid": "Unvoid Job", - "viewchecklist": "View Checklists", - "viewdetail": "View Details" - }, - "errors": { - "addingtoproduction": "Error adding to production. {{error}}", - "cannotintake": "Intake cannot be completed for this Job. It has either already been completed or the job is already here.", - "closing": "Error closing Job. {{error}}", - "creating": "Error encountered while creating job. {{error}}", - "deleted": "Error deleting Job. {{error}}", - "exporting": "Error exporting Job. {{error}}", - "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.", - "invoicing": "Error invoicing Job. {{error}}", - "noaccess": "This Job does not exist or you do not have access to it.", - "nodamage": "No damage points on estimate.", - "nodates": "No dates specified for this Job.", - "nofinancial": "No financial data has been calculated yet for this job. Please save it again.", - "nojobselected": "No Job is selected.", - "noowner": "No owner associated.", - "novehicle": "No vehicle associated.", - "partspricechange": "Error sending parts price change. {{error}}.", - "saving": "Error encountered while saving record.", - "scanimport": "Error importing Job. {{message}}", - "totalscalc": "Error while calculating new Job totals.", - "updating": "Error while updating Job(s). {{error}}", - "validation": "Please ensure all fields are entered correctly.", - "validationtitle": "Validation Error", - "voiding": "Error voiding Job. {{error}}" - }, - "fields": { - "active_tasks": "Active Tasks", - "actual_completion": "Actual Completion", - "actual_delivery": "Actual Delivery", - "actual_in": "Actual In", - "adjustment_bottom_line": "Adjustments", - "adjustmenthours": "Adjustment Hours", - "alt_transport": "Alt. Trans.", - "area_of_damage_impact": { - "10": "Left Front Side", - "11": "Left Front Corner", - "12": "Front", - "13": "Rollover", - "14": "Unknown", - "15": "Total Loss", - "16": "Non-collision", - "25": "Hood", - "26": "Deck-lid", - "27": "Roof", - "28": "Undercarriage", - "34": "All Over", - "01": "Right Front Corner", - "02": "Right Front Side", - "03": "Right Side", - "04": "Right Rear Side", - "05": "Right Rear Corner", - "06": "Rear", - "07": "Left Rear Corner", - "08": "Left Rear Side", - "09": "Left Side" - }, - "auto_add_ats": "Automatically Add/Update ATS", - "ca_bc_pvrt": "PVRT", - "ca_customer_gst": "Customer Portion of GST", - "ca_gst_registrant": "GST Registrant", - "category": "Category", - "ccc": "CC Cleaning", - "ccd": "CC Damage Waiver", - "ccdr": "CC Daily Rate", - "ccf": "CC Refuel", - "ccm": "CC Mileage", - "cieca_id": "CIECA ID", - "cieca_pfl": { - "lbr_adjp": "Labor Adjustment", - "lbr_tax_in": "Tax Labor Indicator", - "lbr_taxp": "Labor Tax Rate", - "lbr_tx_in1": "Tax 1 Indicator", - "lbr_tx_in2": "Tax 2 Indicator", - "lbr_tx_in3": "Tax 3 Indicator", - "lbr_tx_in4": "Tax 4 Indicator", - "lbr_tx_in5": "Tax 5 Indicator" - }, - "cieca_pfo": { - "stor_t_in1": "Storage Tax 1 Indicator", - "stor_t_in2": "Storage Tax 2 Indicator", - "stor_t_in3": "Storage Tax 3 Indicator", - "stor_t_in4": "Storage Tax 4 Indicator", - "stor_t_in5": "Storage Tax 5 Indicator", - "tow_t_in1": "Tow Tax 1 Indicator", - "tow_t_in2": "Tow Tax 2 Indicator", - "tow_t_in3": "Tow Tax 3 Indicator", - "tow_t_in4": "Tow Tax 4 Indicator", - "tow_t_in5": "Tow Tax 5 Indicator" - }, - "claim_total": "Claim Total", - "class": "Class", - "clm_no": "Claim #", - "clm_total": "Claim Total", - "comment": "Comment", - "customerowing": "Customer Owing", - "date_estimated": "Date Estimated", - "date_exported": "Exported", - "date_invoiced": "Invoiced", - "date_last_contacted": "Last Contacted Date", - "date_lost_sale": "Lost Sale", - "date_next_contact": "Next Contact Date", - "date_open": "Open", - "date_rentalresp": "Shop Rental Responsibility Start", - "date_repairstarted": "Repairs Started", - "date_scheduled": "Scheduled", - "date_towin": "Towed In", - "date_void": "Void", - "ded_amt": "Deductible", - "ded_note": "Deductible Note", - "ded_status": "Deductible Status", - "depreciation_taxes": "Betterment/Depreciation/Taxes", - "dms": { - "address": "Customer Address", - "amount": "Amount", - "center": "Center", - "control_type": { - "account_number": "Account Number" - }, - "cost": "Cost", - "cost_dms_acctnumber": "Cost DMS Acct #", - "dms_make": "DMS Make", - "dms_model": "DMS Model", - "dms_model_override": "Override DMS Make/Model", - "dms_unsold": "New, Unsold Vehicle", - "dms_wip_acctnumber": "Cost WIP DMS Acct #", - "id": "DMS ID", - "inservicedate": "In Service Date", - "journal": "Journal #", - "lines": "Posting Lines", - "name1": "Customer Name", - "payer": { - "amount": "Amount", - "control_type": "Control Type", - "controlnumber": "Control Number", - "dms_acctnumber": "DMS Account #", - "name": "Payer Name" - }, - "sale": "Sale", - "sale_dms_acctnumber": "Sale DMS Acct #", - "story": "Story", - "vinowner": "VIN Owner" - }, - "dms_allocation": "DMS Allocation", - "driveable": "Driveable", - "employee_body": "Body", - "employee_csr": "Customer Service Rep.", - "employee_csr_writer": "Writer", - "employee_prep": "Prep", - "employee_refinish": "Refinish", - "est_addr1": "Estimator Address", - "est_co_nm": "Estimator Company", - "est_ct_fn": "Estimator First Name", - "est_ct_ln": "Estimator Last Name", - "est_ea": "Estimator Email", - "est_ph1": "Estimator Phone #", - "federal_tax_payable": "Federal Tax Payable", - "federal_tax_rate": "Federal Tax Rate", - "ins_addr1": "Insurance Co. Address", - "ins_city": "Insurance Co. City", - "ins_co_id": "Insurance Co. ID", - "ins_co_nm": "Insurance Company Name", - "ins_co_nm_short": "Ins. Co.", - "ins_ct_fn": "Adjuster First Name", - "ins_ct_ln": "Adjuster Last Name", - "ins_ea": "Adjuster Email", - "ins_ph1": "Adjuster Phone #", - "intake": { - "label": "Label", - "max": "Maximum", - "min": "Minimum", - "name": "Name", - "required": "Required?", - "type": "Type" - }, - "invoice_final_note": "Note to Display on Final Invoice", - "kmin": "Mileage In", - "kmout": "Mileage Out", - "la1": "LA1", - "la2": "LA2", - "la3": "LA3", - "la4": "LA4", - "laa": "Aluminum ", - "lab": "Body", - "labor_rate_desc": "Labor Rate Name", - "lad": "Diagnostic", - "lae": "Electrical", - "laf": "Frame", - "lag": "Glass", - "lam": "Mechanical", - "lar": "Refinish", - "las": "Structural", - "lau": "User Defined", - "local_tax_rate": "Local Tax Rate", - "loss_date": "Loss Date", - "loss_desc": "Loss Description", - "loss_of_use": "Loss of Use", - "lost_sale_reason": "Lost Sale Reason", - "ma2s": "2 Stage Paint", - "ma3s": "3 Stage Pain", - "mabl": "MABL?", - "macs": "MACS?", - "mahw": "Hazardous Waste", - "mapa": "Paint Materials", - "mash": "Shop Materials", - "matd": "Tire Disposal", - "materials": { - "MAPA": "Paint Materials", - "MASH": "Shop Materials", - "cal_maxdlr": "Threshhold", - "cal_opcode": "OP Codes", - "mat_adjp": "Material Adjustment", - "mat_taxp": "Material Tax Rate", - "mat_tx_in1": "Tax 1 Indicator", - "mat_tx_in2": "Tax 2 Indicator", - "mat_tx_in3": "Tax 3 Indicator", - "mat_tx_in4": "Tax 4 Indicator", - "mat_tx_in5": "Tax 5 Indicator", - "materials": "Profile - Materials", - "tax_ind": "Tax Indicator" - }, - "other_amount_payable": "Other Amount Payable", - "owner": "Owner", - "owner_owing": "Cust. Owes", - "ownr_ea": "Email", - "ownr_ph1": "Phone 1", - "ownr_ph2": "Phone 2", - "paa": "Aftermarket", - "pac": "Rechromed", - "pae": "Existing", - "pag": "Glass", - "pal": "LKQ", - "pam": "Remanufactured", - "pan": "OEM/New", - "pao": "Other", - "pap": "OEM Partial", - "par": "Re-cored", - "parts_tax_rates": { - "prt_discp": "Discount %", - "prt_mktyp": "Markup Type", - "prt_mkupp": "Markup %", - "prt_tax_in": "Tax Indicator", - "prt_tax_rt": "Part Tax Rate", - "prt_tx_in1": "Tax 1 Indicator", - "prt_tx_in2": "Tax 2 Indicator", - "prt_tx_in3": "Tax 3 Indicator", - "prt_tx_in4": "Tax 4 Indicator", - "prt_tx_in5": "Tax 5 Indicator", - "prt_tx_ty1": "Parts Tax Type 1", - "prt_type": "Part Type" - }, - "partsstatus": "Parts Status", - "pas": "Sublet", - "pay_date": "Pay Date", - "phoneshort": "PH", - "po_number": "PO Number", - "policy_no": "Policy #", - "ponumber": "PO Number", - "production_vars": { - "note": "Production Note" - }, - "qb_multiple_payers": { - "amount": "Amount", - "name": "Name" - }, - "queued_for_parts": "Queued for Parts", - "rate_ats": "ATS Rate", - "rate_la1": "LA1", - "rate_la2": "LA2", - "rate_la3": "LA3", - "rate_la4": "LA4", - "rate_laa": "Aluminum", - "rate_lab": "Body", - "rate_lad": "Diagnostic", - "rate_lae": "Electrical", - "rate_laf": "Frame", - "rate_lag": "Glass", - "rate_lam": "Mechanical", - "rate_lar": "Refinish", - "rate_las": "Structural", - "rate_lau": "User Defined", - "rate_ma2s": "2 Stage Paint", - "rate_ma3s": "3 Stage Paint", - "rate_mabl": "MABL??", - "rate_macs": "MACS??", - "rate_mahw": "Hazardous Waste", - "rate_mapa": "Paint Materials", - "rate_mash": "Shop Material", - "rate_matd": "Tire Disposal", - "referral_source_extra": "Other Referral Source", - "referral_source_other": "", - "referralsource": "Referral Source", - "regie_number": "Registration #", - "repairtotal": "Repair Total", - "ro_number": "RO #", - "scheduled_completion": "Scheduled Completion", - "scheduled_delivery": "Scheduled Delivery", - "scheduled_in": "Scheduled In", - "selling_dealer": "Selling Dealer", - "selling_dealer_contact": "Selling Dealer Contact", - "servicecar": "Service Car", - "servicing_dealer": "Servicing Dealer", - "servicing_dealer_contact": "Servicing Dealer Contact", - "special_coverage_policy": "Special Coverage Policy", - "specialcoveragepolicy": "Special Coverage Policy", - "state_tax_rate": "State Tax Rate", - "status": "Job Status", - "storage_payable": "Storage", - "tax_lbr_rt": "Labor Tax Rate", - "tax_levies_rt": "Levies Tax Rate", - "tax_paint_mat_rt": "Paint Material Tax Rate", - "tax_registration_number": "Tax Registration Number", - "tax_shop_mat_rt": "Shop Material Tax Rate", - "tax_str_rt": "Storage Tax Rate", - "tax_sub_rt": "Sublet Tax Rate", - "tax_tow_rt": "Towing Tax Rate", - "tlos_ind": "Total Loss Indicator", - "towin": "Tow In", - "towing_payable": "Towing Payable", - "unitnumber": "Unit #", - "updated_at": "Updated At", - "uploaded_by": "Uploaded By", - "vehicle": "Vehicle" - }, - "forms": { - "admindates": "Administrative Dates", - "appraiserinfo": "Estimator Info", - "claiminfo": "Claim Information", - "estdates": "Estimate Dates", - "laborrates": "Labor Rates", - "lossinfo": "Loss Information", - "other": "Other", - "repairdates": "Repair Dates", - "scheddates": "Schedule Dates" - }, - "labels": { - "accountsreceivable": "Accounts Receivable", - "act_price_ppc": "New Part Price", - "actual_completion_inferred": "$t(jobs.fields.actual_completion) inferred using $t(jobs.fields.scheduled_completion).", - "actual_delivery_inferred": "$t(jobs.fields.actual_delivery) inferred using $t(jobs.fields.scheduled_delivery).", - "actual_in_inferred": "$t(jobs.fields.actual_in) inferred using $t(jobs.fields.scheduled_in).", - "additionalpayeroverallocation": "You have allocated more than the sale of the Job to additional payers.", - "additionaltotal": "Additional Total", - "adjustmentrate": "Adjustment Rate", - "adjustments": "Adjustments", - "adminwarning": "Use the functionality on this page at your own risk. You are responsible for any and all changes to your data.", - "allocations": "Allocations", - "alreadyaddedtoscoreboard": "Job has already been added to scoreboard. Saving will update the previous entry.", - "alreadyclosed": "This Job has already been closed.", - "appointmentconfirmation": "Send confirmation to customer?", - "associationwarning": "Any changes to associations will require updating the data from the new parent record to the Job.", - "audit": "Audit Trail", - "available": "Available", - "availablejobs": "Available Jobs", - "ca_bc_pvrt": { - "days": "Days", - "rate": "PVRT Rate" - }, - "ca_gst_all_if_null": "If the Job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ", - "calc_repair_days": "Calculated Repair Days", - "calc_repair_days_tt": "This is the approximate number of days required to complete the repair according to the target touch time in your shop configuration (current set to {{target_touchtime}}).", - "calc_scheuled_completion": "Calculate Scheduled Completion", - "cards": { - "customer": "Customer Information", - "damage": "Area of Damage", - "dates": "Dates", - "documents": "Recent Documents", - "estimator": "Estimator", - "filehandler": "Adjuster", - "insurance": "Insurance Details", - "more": "More", - "notes": "Notes", - "parts": "Parts", - "totals": "Totals", - "vehicle": "Vehicle" - }, - "changeclass": "Changing the Job's class can have fundamental impacts to already exported accounting items. Are you sure you want to do this?", - "checklistcompletedby": "Checklist completed by {{by}} at {{at}}", - "checklistdocuments": "Checklist Documents", - "checklists": "Checklists", - "cieca_pfl": "Profile - Labor", - "cieca_pfo": "Profile - Other", - "cieca_pft": "Profile - Taxes", - "closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.", - "closejob": "Close Job {{ro_number}}", - "closingperiod": "This Invoice Date is outside of the Closing Period.", - "contracts": "CC Contracts", - "convertedtolabor": "Labor Line Adjustments", - "cost": "Cost", - "cost_Additional": "Cost - Additional", - "cost_labor": "Cost - Labor", - "cost_parts": "Cost - Parts", - "cost_sublet": "Cost - Sublet", - "costs": "Costs", - "create": { - "jobinfo": "Job Info", - "newowner": "Create a new Owner instead. ", - "newvehicle": "Create a new Vehicle Instead", - "novehicle": "No vehicle (only for ROs to track parts/labor only work).", - "ownerinfo": "Owner Info", - "vehicleinfo": "Vehicle Info" - }, - "createiouwarning": "Are you sure you want to create an IOU for these lines? A new RO will be created based on those lines for this customer.", - "creating_new_job": "Creating new Job...", - "deductible": { - "stands": "Stands", - "waived": "Waived" - }, - "deleteconfirm": "Are you sure you want to delete this Job? This cannot be undone. ", - "deletedelivery": "Delete Delivery Checklist", - "deleteintake": "Delete Intake Checklist", - "deliverchecklist": "Deliver Checklist", - "difference": "Difference", - "diskscan": "Scan Disk for Estimates", - "dms": { - "apexported": "AP export completed. See logs for details.", - "damageto": "Damage to $t(jobs.fields.area_of_damage_impact.{{area_of_damage}}).", - "defaultstory": "B/S RO: {{ro_number}}. Owner: {{ownr_nm}}. Insurance Co: {{ins_co_nm}}. Claim/PO #: {{clm_po}}", - "disablebillwip": "Cost and WIP for bills has been ignored per shop configuration.", - "invoicedatefuture": "Invoice date must be today or in the future for CDK posting.", - "kmoutnotgreaterthankmin": "Mileage out must be greater than mileage in.", - "logs": "Logs", - "notallocated": "Not Allocated", - "postingform": "Posting Form", - "totalallocated": "Total Amount Allocated" - }, - "documents": "Documents", - "documents-images": "Images", - "documents-other": "Other Documents", - "duplicateconfirm": "Are you sure you want to duplicate this Job? Some elements of this Job will not be duplicated.", - "emailaudit": "Email Audit Trail", - "employeeassignments": "Employee Assignments", - "estimatelines": "Estimate Lines", - "estimator": "Estimator", - "existing_jobs": "Existing Jobs", - "federal_tax_amt": "Federal Taxes", - "gpdollars": "$ G.P.", - "gppercent": "% G.P.", - "hrs_claimed": "Hours Flagged", - "hrs_total": "Hours Total", - "importnote": "The Job was initially imported.", - "inproduction": "In Production", - "intakechecklist": "Intake Checklist", - "iou": "IOU", - "job": "Job Details", - "jobcosting": "Job Costing", - "jobtotals": "Job Totals", - "labor_hrs": "B/P/T Hrs", - "labor_rates_subtotal": "Labor Rates Subtotal", - "laborallocations": "Labor Allocations", - "labortotals": "Labor Totals", - "lines": "Estimate Lines", - "local_tax_amt": "Local Taxes", - "mapa": "Paint Materials", - "markforreexport": "Mark for Re-export", - "mash": "Shop Materials", - "masterbypass": "Master Bypass Password", - "materials": { - "mapa": "" - }, - "missingprofileinfo": "This job has missing tax profile info. To ensure correct totals calculations, re-import the job.", - "multipayers": "Additional Payers", - "net_repairs": "Net Repairs", - "notes": "Notes", - "othertotal": "Other Totals", - "outstanding_ar": "A balance is outstanding on this RO. Payments can still be entered when the job is closed. ", - "outstanding_credit_memos": "Outstanding credit memos have not been entered against this job. Credit Memos may still be posted once the job is closed.", - "outstanding_ppd": "There are outstanding PPDs that may not have been synced back to the estimate.", - "outstanding_reconciliation_discrep": "At least one discrepancy is not $0. This may indicate that this job is not properly reconciled and should not be closed.", - "outstanding_sublets": "There are sublet lines on the job which have not been marked as completed. ", - "outstandinghours": "There are outstanding hours on the job that have not been paid or have been overpaid.", - "override_header": "Override estimate header on import?", - "ownerassociation": "Owner Association", - "parts": "Parts", - "parts_lines": "Parts Lines", - "parts_received": "Parts Rec.", - "parts_tax_rates": "Profile - Parts", - "partsfilter": "Parts Only", - "partssubletstotal": "Parts & Sublets Total", - "partstotal": "Parts Total (ex. Taxes)", - "performance": "Performance", - "pimraryamountpayable": "Total Primary Payable", - "plitooltips": { - "billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).", - "calculatedcreditsnotreceived": "The calculated credits not received is derived by subtracting the amount of credit memos entered from the retail total of returns created. This does not take into account whether the credit was marked as received. You can find more information here.", - "creditmemos": "The total retail amount of all returns created. This amount does not reflect credit memos that have been posted.", - "creditsnotreceived": "This total reflects the total retail of parts returns lines that have not been explicitly marked as returned when posting a credit memo. You can learn more about this here here. ", - "discrep1": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.
  • \n
  • You do not have the latest supplement imported, or, a supplement must be submitted and then imported.
  • \n
  • You have posted a bill line to labor.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", - "discrep2": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • Used an incorrect rate when deducting from labor.
  • \n
  • An outstanding imbalance higher in the reconciliation process.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", - "discrep3": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • A parts order return has not been created.
  • \n
  • An outstanding imbalance higher in the reconciliation process.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", - "laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.", - "partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).
\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.", - "totalreturns": "The total retail amount of returns created for this job." - }, - "ppc": "This line contains a part price change.", - "ppdnotexported": "PPDs not Exported", - "profileadjustments": "Profile Disc./Mkup", - "profitbypassrequired": "Minimum gross profit requirements have not been met.", - "profits": "Job Profits", - "prt_dsmk_total": "Line Item Adjustment", - "rates": "Rates", - "rates_subtotal": "All Rates Subtotal", - "reconciliation": { - "billlinestotal": "Bill Lines Total", - "byassoc": "By Line Association", - "byprice": "By Price", - "clear": "Clear All", - "discrepancy": "Discrepancy", - "joblinestotal": "Job Lines Total", - "multipleactprices": "${{act_price}} is the price for multiple job lines.", - "multiplebilllines": "{{line_desc}} has 2 or more bill lines associated to it.", - "multiplebillsforactprice": "Found more than 1 bill matching ${{act_price}} retail price.", - "removedpartsstrikethrough": "Strike through lines represent parts that have been removed from the estimate. They are included for completeness of reconciliation." - }, - "reconciliationheader": "Parts & Sublet Reconciliation", - "relatedros": "Related ROs", - "remove_from_ar": "Remove from AR", - "returntotals": "Return Totals", - "ro_guard": { - "enforce_ar": "AR collection enforced.", - "enforce_bills": "Bill discrepancy enforced.", - "enforce_cm": "Credit memo entry enforced.", - "enforce_labor": "Labor allocations enforced.", - "enforce_ppd": "PPD sync enforced.", - "enforce_profit": "Profit marginsenforced.", - "enforce_sublet": "Sublet completion enforced.", - "enforce_validation": "Master Bypass Required: {{message}}", - "enforced": "This check has been enforced by your shop manager. Enter the master bypass password to close the Job." - }, - "roguard": "RO Guard", - "roguardwarnings": "RO Guard Warnings", - "rosaletotal": "RO Parts Total", - "sale_additional": "Sales - Additional", - "sale_labor": "Sales - Labor", - "sale_parts": "Sales - Parts", - "sale_sublet": "Sales - Sublet", - "sales": "Sales", - "savebeforeconversion": "You have unsaved changes on the Job. Please save them before converting it. ", - "scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the Job. ", - "specialcoveragepolicy": "Special Coverage Policy Applies", - "state_tax_amt": "Provincial/State Taxes", - "subletsnotcompleted": "Outstanding Sublets", - "subletstotal": "Sublets Total", - "subtotal": "Subtotal", - "supplementnote": "The Job had a supplement imported.", - "suspended": "SUSPENDED", - "suspense": "Suspense", - "tasks": "Tasks", - "threshhold": "Max Threshold: ${{amount}}", - "total_cost": "Total Cost", - "total_cust_payable": "Total Customer Amount Payable", - "total_cust_payable_cash_discount": "$t(jobs.labels.total_cust_payable) (Cash Discounted)", - "total_repairs": "Total Repairs", - "total_repairs_cash_discount": "Total Repairs (Cash Discounted)", - "total_sales": "Total Sales", - "total_sales_tax": "Total Sales Tax", - "totals": "Totals", - "unvoidnote": "This Job was unvoided.", - "update_scheduled_completion": "Update Scheduled Completion?", - "vehicle_info": "Vehicle", - "vehicleassociation": "Vehicle Association", - "viewallocations": "View Allocations", - "voidjob": "Are you sure you want to void this Job? This cannot be easily undone. ", - "voidnote": "This Job was voided." - }, - "successes": { - "addedtoproduction": "Job added to production board.", - "all_deleted": "{{count}} Jobs deleted successfully.", - "closed": "Job closed successfully.", - "converted": "Job converted successfully.", - "created": "Job created successfully. Click to view.", - "creatednoclick": "Job created successfully. ", - "delete": "Job deleted successfully.", - "deleted": "Job deleted successfully.", - "duplicated": "Job duplicated successfully. ", - "exported": "Job(s) exported successfully. ", - "invoiced": "Job closed and invoiced successfully.", - "ioucreated": "IOU created successfully. Click to see.", - "partsqueue": "Job added to parts queue.", - "save": "Job saved successfully.", - "savetitle": "Record saved successfully.", - "supplemented": "Job supplemented successfully. ", - "updated": "Job(s) updated successfully.", - "voided": "Job voided successfully." - } - }, - "landing": { - "bigfeature": { - "subtitle": "Rome Online is built using world class technology by experts in the collision repair industry. This translates to software that is tailor made for the unique challenges faced by repair facilities with no compromises. ", - "title": "Bringing the latest technology to the automotive repair industry. " - }, - "footer": { - "company": { - "about": "About Us", - "contact": "Contact", - "disclaimers": "Disclaimers", - "name": "Company", - "privacypolicy": "Privacy Policy" - }, - "io": { - "help": "Help", - "name": "Rome Online", - "status": "System Status" - }, - "slogan": "Rome Technologies. is a technology leader in the collision repair industry. We specialize in creating collision repair management systems and bodyshop management systems that lower cycle times and promote efficiency." - }, - "hero": { - "button": "Learn More", - "title": "Shop management reimagined." - }, - "labels": { - "features": "Features", - "managemyshop": "Sign In", - "pricing": "Pricing" - }, - "pricing": { - "basic": { - "name": "Basic", - "sub": "Best suited for shops looking to increase their volume." - }, - "essentials": { - "name": "Essentials", - "sub": "Best suited for small and low volume shops." - }, - "pricingtitle": "Features", - "pro": { - "name": "Pro", - "sub": "Empower your shop with the tools to operate at peak capacity." - }, - "title": "Features", - "unlimited": { - "name": "Unlimited", - "sub": "Everything you need and more for the high volume shop." - } - } - }, - "menus": { - "currentuser": { - "languageselector": "Language", - "profile": "Profile" - }, - "header": { - "accounting": "Accounting", - "accounting-payables": "Payables", - "accounting-payments": "Payments", - "accounting-receivables": "Receivables", - "activejobs": "Active Jobs", - "all_tasks": "All Tasks", - "alljobs": "All Jobs", - "allpayments": "All Payments", - "availablejobs": "Available Jobs", - "bills": "Bills", - "courtesycars": "Courtesy Cars", - "courtesycars-all": "All Courtesy Cars", - "courtesycars-contracts": "Contracts", - "courtesycars-newcontract": "New Contract", - "create_task": "Create Task", - "customers": "Customers", - "dashboard": "Dashboard", - "enterbills": "Enter Bills", - "entercardpayment": "New Card Charge", - "enterpayment": "Enter Payments", - "entertimeticket": "Enter Time Tickets", - "export": "Export", - "export-logs": "Export Logs", - "help": "Help", - "home": "Home", - "inventory": "Inventory", - "jobs": "Jobs", - "my_tasks": "My Tasks", - "newjob": "Create New Job", - "owners": "Owners", - "parts-queue": "Parts Queue", - "phonebook": "Phonebook", - "productionboard": "Production Board - Visual", - "productionlist": "Production Board - List", - "readyjobs": "Ready Jobs", - "recent": "Recent Items", - "reportcenter": "Report Center", - "rescueme": "Rescue me!", - "schedule": "Schedule", - "scoreboard": "Scoreboard", - "search": { - "bills": "Bills", - "jobs": "Jobs", - "owners": "Owners", - "payments": "Payments", - "phonebook": "Phonebook", - "vehicles": "Vehicles" - }, - "shiftclock": "Shift Clock", - "shop": "My Shop", - "shop_config": "Configuration", - "shop_csi": "CSI", - "shop_templates": "Templates", - "shop_vendors": "Vendors", - "tasks": "Tasks", - "temporarydocs": "Temporary Documents", - "timetickets": "Time Tickets", - "ttapprovals": "Time Ticket Approvals", - "vehicles": "Vehicles" - }, - "jobsactions": { - "admin": "Admin", - "cancelallappointments": "Cancel all appointments", - "closejob": "Close Job", - "deletejob": "Delete Job", - "duplicate": "Duplicate this Job", - "duplicatenolines": "Duplicate this Job without Repair Data", - "newcccontract": "Create Courtesy Car Contract", - "void": "Void Job" - }, - "jobsdetail": { - "claimdetail": "Claim Details", - "dates": "Dates", - "financials": "Financial Information", - "general": "General", - "insurance": "Insurance Information", - "labor": "Labor", - "lifecycle": "Lifecycle", - "parts": "Parts", - "partssublet": "Parts & Bills", - "rates": "Rates", - "repairdata": "Repair Data", - "totals": "Totals" - }, - "profilesidebar": { - "profile": "My Profile", - "shops": "My Shops" - }, - "tech": { - "assignedjobs": "Assigned Jobs", - "claimtask": "Flag Hours", - "dispatchedparts": "Dispatched Parts", - "home": "Home", - "jobclockin": "Job Clock In", - "jobclockout": "Job Clock Out", - "joblookup": "Job Lookup", - "login": "Login", - "logout": "Logout", - "productionboard": "Production Visual", - "productionlist": "Production List", - "shiftclockin": "Shift Clock" - } - }, - "messaging": { - "actions": { - "link": "Link to Job", - "new": "New Conversation" - }, - "errors": { - "invalidphone": "The phone number is invalid. Unable to open conversation. ", - "noattachedjobs": "No Jobs have been associated to this conversation. ", - "updatinglabel": "Error updating label. {{error}}" - }, - "labels": { - "addlabel": "Add a label to this conversation.", - "archive": "Archive", - "maxtenimages": "You can only select up to a maximum of 10 images at a time.", - "messaging": "Messaging", - "noallowtxt": "This customer has not indicated their permission to be messaged.", - "nojobs": "Not associated to any Job.", - "nopush": "Polling Mode Enabled", - "phonenumber": "Phone #", - "presets": "Presets", - "recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.", - "selectmedia": "Select Media", - "sentby": "Sent by {{by}} at {{time}}", - "typeamessage": "Send a message...", - "unarchive": "Unarchive" - }, - "render": { - "conversation_list": "Conversation List" - } - }, - "notes": { - "actions": { - "actions": "Actions", - "deletenote": "Delete Note", - "edit": "Edit Note", - "new": "New Note", - "savetojobnotes": "Save to Job Notes" - }, - "errors": { - "inserting": "Error inserting note. {{error}}" - }, - "fields": { - "createdby": "Created By", - "critical": "Critical", - "private": "Private", - "text": "Contents", - "type": "Type", - "types": { - "customer": "Customer", - "general": "General", - "office": "Office", - "paint": "Paint", - "parts": "Parts", - "shop": "Shop", - "supplement": "Supplement" - }, - "updatedat": "Updated At" - }, - "labels": { - "addtorelatedro": "Add to Related ROs", - "newnoteplaceholder": "Add a note...", - "notetoadd": "Note to Add", - "systemnotes": "System Notes", - "usernotes": "User Notes" - }, - "successes": { - "create": "Note created successfully.", - "deleted": "Note deleted successfully.", - "updated": "Note updated successfully." - } - }, - "owner": { - "labels": { - "noownerinfo": "No owner information." - } - }, - "owners": { - "actions": { - "update": "Update Selected Records" - }, - "errors": { - "deleting": "Error deleting owner. {{error}}.", - "noaccess": "The record does not exist or you do not have access to it. ", - "saving": "Error saving owner. {{error}}.", - "selectexistingornew": "Select an existing owner record or create a new one. " - }, - "fields": { - "accountingid": "Accounting ID", - "address": "Address", - "allow_text_message": "Permission to Text?", - "name": "Name", - "note": "Owner Note", - "ownr_addr1": "Address", - "ownr_addr2": "Address 2", - "ownr_city": "City", - "ownr_co_nm": "Owner Co. Name", - "ownr_ctry": "Country", - "ownr_ea": "Email", - "ownr_fn": "First Name", - "ownr_ln": "Last Name", - "ownr_ph1": "Phone 1", - "ownr_ph2": "Phone 2", - "ownr_st": "Province/State", - "ownr_title": "Title", - "ownr_zip": "Zip/Postal Code", - "preferred_contact": "Preferred Contact Method", - "tax_number": "Tax Number" - }, - "forms": { - "address": "Address", - "contact": "Contact Information", - "name": "Owner Details" - }, - "labels": { - "create_new": "Create a new owner record.", - "deleteconfirm": "Are you sure you want to delete this owner? This cannot be undone.", - "existing_owners": "Existing Owners", - "fromclaim": "Current Claim", - "fromowner": "Historical Owner Record", - "relatedjobs": "Related Jobs", - "updateowner": "Update Owner" - }, - "successes": { - "delete": "Owner deleted successfully.", - "save": "Owner saved successfully." - } - }, - "parts": { - "actions": { - "order": "Order Parts", - "orderinhouse": "Order as In House" - } - }, - "parts_dispatch": { - "actions": { - "accept": "Accept" - }, - "errors": { - "accepting": "Error accepting parts dispatch. {{error}}", - "creating": "Error dispatching parts. {{error}}" - }, - "fields": { - "number": "Number", - "percent_accepted": "% Accepted" - }, - "labels": { - "notyetdispatched": "This part has not been dispatched.", - "parts_dispatch": "Parts Dispatch" - } - }, - "parts_dispatch_lines": { - "fields": { - "accepted_at": "Accepted At" - } - }, - "parts_orders": { - "actions": { - "backordered": "Mark Backordered", - "receive": "Receive", - "receivebill": "Receive Bill" - }, - "errors": { - "associatedbills": "This parts order cannot", - "backordering": "Error backordering part {{message}}.", - "creating": "Error encountered when creating parts order. ", - "oec": "Error creating EMS files for parts order. {{error}}", - "saving": "Error saving parts order. {{error}}.", - "updating": "Error updating parts order/parts order line. {{error}}." - }, - "fields": { - "act_price": "Price", - "backordered_eta": "B.O. ETA", - "backordered_on": "B.O. On", - "cm_received": "CM Received?", - "comments": "Comments", - "cost": "Cost", - "db_price": "List Price", - "deliver_by": "Deliver By", - "job_line_id": "Job Line Id", - "line_desc": "Line Description", - "line_remarks": "Remarks", - "lineremarks": "Line Remarks", - "oem_partno": "Part #", - "order_date": "Order Date", - "order_number": "Order Number", - "orderedby": "Ordered By", - "part_type": "Type", - "quantity": "Qty.", - "return": "Return", - "status": "Status" - }, - "labels": { - "allpartsto": "All Parts Location", - "confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ", - "custompercent": "Custom %", - "discount": "Discount {{percent}}", - "email": "Send by Email", - "inthisorder": "Parts in this Order", - "is_quote": "Parts Quote?", - "mark_as_received": "Mark as Received?", - "newpartsorder": "New Parts Order", - "notyetordered": "This part has not yet been ordered.", - "oec": "Order via EMS", - "order_type": "Order Type", - "orderhistory": "Order History", - "parts_order": "Parts Order", - "parts_orders": "Parts Orders", - "parts_returns": "Parts Returns", - "print": "Show Printed Form", - "receive": "Receive Parts Order", - "removefrompartsqueue": "Unqueue from Parts Queue?", - "returnpartsorder": "Return Parts Order", - "sublet_order": "Sublet Order" - }, - "successes": { - "created": "Parts order created successfully. ", - "line_updated": "Parts return line updated.", - "received": "Parts order received.", - "return_created": "Parts return created successfully." - } - }, - "payments": { - "actions": { - "generatepaymentlink": "Generate Payment Link" - }, - "errors": { - "exporting": "Error exporting payment(s). {{error}}", - "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors.", - "inserting": "Error inserting payment. {{error}}" - }, - "fields": { - "amount": "Amount", - "created_at": "Created At", - "date": "Payment Date", - "exportedat": "Exported At", - "memo": "Memo", - "payer": "Payer", - "paymentnum": "Payment Number", - "stripeid": "Stripe ID", - "transactionid": "Transaction ID", - "type": "Type" - }, - "labels": { - "balance": "Balance", - "ca_bc_etf_table": "ICBC EFT Table Converter", - "customer": "Customer", - "edit": "Edit Payment", - "electronicpayment": "Use Electronic Payment Processing?", - "external": "External", - "findermodal": "ICBC Payment Finder", - "insurance": "Insurance", - "markexported": "Mark Exported", - "markforreexport": "Mark for Re-export", - "new": "New Payment", - "signup": "Please contact support to sign up for electronic payments.", - "smspaymentreminder": "This is {{shopname}} reminding you about your balance of {{amount}}. To pay, click the following link {{payment_link}}.", - "title": "Payments", - "totalpayments": "Total Payments" - }, - "successes": { - "exported": "Payment(s) exported successfully.", - "markexported": "Payment(s) marked exported.", - "markreexported": "Payment marked for re-export successfully", - "payment": "Payment created successfully. ", - "paymentupdate": "Payment updated successfully. ", - "stripe": "Credit card transaction charged successfully." - } - }, - "phonebook": { - "actions": { - "new": "New Phonebook Entry" - }, - "errors": { - "adding": "Error adding phonebook entry. {{error}}", - "saving": "Error saving phonebook entry. {{error}}" - }, - "fields": { - "address1": "Street 1", - "address2": "Street 2", - "category": "Category", - "city": "City", - "company": "Company", - "country": "Country", - "email": "Email", - "fax": "Fax", - "firstname": "First Name", - "lastname": "Last Name", - "phone1": "Phone 1", - "phone2": "Phone 2", - "state": "Province/State" - }, - "labels": { - "noneselected": "No phone book entry selected. ", - "onenamerequired": "At least one name related field is required.", - "vendorcategory": "Vendor" - }, - "successes": { - "added": "Phonebook entry added successfully. ", - "deleted": "Phonebook entry deleted successfully. ", - "saved": "Phonebook entry saved successfully. " - } - }, - "printcenter": { - "appointments": { - "appointment_confirmation": "Appointment Confirmation" - }, - "bills": { - "inhouse_invoice": "In House Invoice" - }, - "courtesycarcontract": { - "courtesy_car_contract": "Courtesy Car Contract", - "courtesy_car_impound": "Impound Charges", - "courtesy_car_inventory": "Courtesy Car Inventory", - "courtesy_car_terms": "Courtesy Car Terms" - }, - "errors": { - "nocontexttype": "No context type set." - }, - "jobs": { - "3rdpartyfields": { - "addr1": "Address 1", - "addr2": "Address 2", - "addr3": "Address 3", - "attn": "Attention", - "city": "City", - "custgst": "Customer Portion of GST", - "ded_amt": "Deductible", - "depreciation": "Depreciation", - "other": "Other", - "ponumber": "PO Number", - "refnumber": "Reference Number", - "sendtype": "Send by", - "state": "Province/State", - "zip": "Postal Code/Zip" - }, - "3rdpartypayer": "Invoice to Third Party Payer", - "ab_proof_of_loss": "AB - Proof of Loss", - "appointment_confirmation": "Appointment Confirmation", - "appointment_reminder": "Appointment Reminder", - "casl_authorization": "CASL Authorization", - "committed_timetickets_ro": "Committed Time Tickets", - "coversheet_landscape": "Coversheet (Landscape)", - "coversheet_portrait": "Coversheet Portrait", - "csi_invitation": "CSI Invitation", - "csi_invitation_action": "CSI Invite", - "diagnostic_authorization": "Diagnostic Authorization", - "dms_posting_sheet": "DMS Posting Sheet", - "envelope_return_address": "#10 Envelope Return Address Label", - "estimate": "Estimate Only", - "estimate_detail": "Estimate Details", - "estimate_followup": "Estimate Followup", - "express_repair_checklist": "Express Repair Checklist", - "filing_coversheet_landscape": "Filing Coversheet (Landscape)", - "filing_coversheet_portrait": "Filing Coversheet (Portrait)", - "final_invoice": "Final Invoice", - "fippa_authorization": "FIPPA Authorization", - "folder_label_multiple": "Folder Label - Multi", - "glass_express_checklist": "Glass Express Checklist", - "guarantee": "Repair Guarantee", - "individual_job_note": "RO Job Note", - "invoice_customer_payable": "Invoice (Customer Payable)", - "invoice_total_payable": "Invoice (Total Payable)", - "iou_form": "IOU Form", - "job_costing_ro": "Job Costing", - "job_lifecycle_ro": "Job Lifecycle", - "job_notes": "Job Notes", - "job_tasks": "Job Tasks", - "key_tag": "Key Tag", - "labels": { - "count": "Count", - "labels": "Labels", - "position": "Starting Position" - }, - "lag_time_ro": "Lag Time", - "mechanical_authorization": "Mechanical Authorization", - "mpi_animal_checklist": "MPI - Animal Checklist", - "mpi_eglass_auth": "MPI - eGlass Auth", - "mpi_final_acct_sheet": "MPI - Final Accounting Sheet (Direct Repair)", - "mpi_final_repair_acct_sheet": "MPI - Final Accounting Sheet", - "paint_grid": "Paint Grid", - "parts_dispatch": "Parts Dispatch", - "parts_invoice_label_single": "Parts Label Single", - "parts_label_multiple": "Parts Label - Multi", - "parts_label_single": "Parts Label - Single", - "parts_list": "Parts List", - "parts_order": "Parts Order Confirmation", - "parts_order_confirmation": "", - "parts_order_history": "Parts Order History", - "parts_return_slip": "Parts Return Slip", - "payment_receipt": "Payment Receipt", - "payment_request": "Payment Request", - "payments_by_job": "Job Payments", - "purchases_by_ro_detail": "Purchases - Detail", - "purchases_by_ro_summary": "Purchases - Summary", - "qc_sheet": "Quality Control Sheet", - "rental_reservation": "Rental Reservation", - "ro_totals": "RO Totals", - "ro_with_description": "RO Summary with Descriptions", - "sgi_certificate_of_repairs": "SGI - Certificate of Repairs", - "sgi_windshield_auth": "SGI - Windshield Authorization", - "stolen_recovery_checklist": "Stolen Recovery Checklist", - "sublet_order": "Sublet Order", - "supplement_request": "Supplement Request", - "thank_you_ro": "Thank You Letter", - "thirdpartypayer": "Third Party Payer", - "timetickets_ro": "Time Tickets", - "vehicle_check_in": "Vehicle Intake", - "vehicle_delivery_check": "Vehicle Delivery Checklist", - "window_tag": "Window Tag", - "window_tag_sublet": "Window Tag - Sublet", - "work_authorization": "Work Authorization", - "worksheet_by_line_number": "Worksheet by Line Number", - "worksheet_sorted_by_operation": "Worksheet by Operation", - "worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)", - "worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type", - "worksheet_sorted_by_operation_type": "Worksheet by Operation Type", - "worksheet_sorted_by_team": "Worksheet by Team" - }, - "labels": { - "groups": { - "authorization": "Authorization", - "financial": "Financial", - "post": "Post-Production", - "pre": "Pre-Production", - "ro": "Repair Order", - "worksheet": "Worksheets" - }, - "misc": "Miscellaneous Documents", - "repairorder": "Repair Order Related", - "reportcentermodal": "Report Center", - "speedprint": "Speed Print", - "title": "Print Center" - }, - "payments": { - "ca_bc_etf_table": "ICBC EFT Table", - "exported_payroll": "Payroll Table" - }, - "special": { - "attendance_detail_csv": "Attendance Table" - }, - "subjects": { - "jobs": { - "individual_job_note": "Job Note RO: {{ro_number}}", - "parts_dispatch": "Parts Dispatch RO: {{ro_number}}", - "parts_order": "Parts Order PO: {{ro_number}} - {{name}}", - "parts_return_slip": "Parts Return PO: {{ro_number}} - {{name}}", - "sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}" - } - }, - "vendors": { - "purchases_by_vendor_detailed": "Purchases by Vendor - Detailed", - "purchases_by_vendor_summary": "Purchases by Vendor - Summary" - } - }, - "production": { - "actions": { - "addcolumns": "Add Columns", - "bodypriority-clear": "Clear Body Priority", - "bodypriority-set": "Set Body Priority", - "detailpriority-clear": "Clear Detail Priority", - "detailpriority-set": "Set Detail Priority", - "paintpriority-clear": "Clear Paint Priority", - "paintpriority-set": "Set Paint Priority", - "remove": "Remove from Production", - "removecolumn": "Remove Column", - "saveconfig": "Save Configuration", - "suspend": "Suspend", - "unsuspend": "Unsuspend" - }, - "constants": { - "main_profile": "Default" - }, - "errors": { - "boardupdate": "Error encountered updating Job. {{message}}", - "name_exists": "A Profile with this name already exists. Please choose a different name.", - "name_required": "Profile name is required.", - "removing": "Error removing from production board. {{error}}", - "settings": "Error saving board settings: {{error}}" - }, - "labels": { - "actual_in": "Actual In", - "addnewprofile": "Add New Profile", - "alert": "Alert", - "alertoff": "Remove alert from Job", - "alerton": "Add alert to Job", - "alerts": "Alerts", - "ats": "Alternative Transportation", - "bodyhours": "B", - "bodypriority": "B/P", - "bodyshop": { - "labels": { - "qbo_departmentid": "QBO Department ID", - "qbo_usa": "QBO USA" - } - }, - "card_size": "Card Size", - "cardcolor": "Colored Cards", - "cardsettings": "Card Settings", - "clm_no": "Claim Number", - "comment": "Comment", - "compact": "Compact Cards", - "detailpriority": "D/P", - "employeeassignments": "Employee Assignments", - "employeesearch": "Employee Search", - "estimator": "Estimator", - "horizontal": "Horizontal", - "ins_co_nm": "Insurance Company Name", - "jobdetail": "Job Details", - "kiosk_mode": "Kiosk Mode", - "laborhrs": "Labor Hours", - "legend": "Legend:", - "model_info": "Vehicle Info", - "note": "Production Note", - "off": "Off", - "on": "On", - "orientation": "Board Orientation", - "ownr_nm": "Customer Name", - "paintpriority": "P/P", - "partsstatus": "Parts Status", - "production_note": "Production Note", - "refinishhours": "R", - "scheduled_completion": "Scheduled Completion", - "selectview": "Select a View", - "stickyheader": "Sticky Header (BETA)", - "sublets": "Sublets", - "subtotal": "Subtotal", - "tall": "Tall", - "tasks": "Tasks", - "totalhours": "Total Hrs ", - "touchtime": "T/T", - "unassigned": "Unassigned", - "vertical": "Vertical", - "viewname": "View Name", - "wide": "Wide" - }, - "options": { - "horizontal": "Horizontal", - "large": "Large", - "medium": "Medium", - "small": "Small", - "vertical": "Vertical" - }, - "settings": { - "board_settings": "Board Settings", - "filters": { - "md_estimators": "Estimators", - "md_ins_cos": "Insurance Companies" - }, - "filters_title": "Filters", - "information": "Information", - "layout": "Layout", - "statistics": { - "jobs_in_production": "Jobs in Production", - "tasks_in_production": "Tasks in Production", - "tasks_in_view": "Tasks in View", - "tasks_on_board": "Tasks on Board", - "total_amount_in_production": "Dollars in Production", - "total_amount_in_view": "Dollars in View", - "total_amount_on_board": "Dollars on Board", - "total_hours_in_production": "Hours in Production", - "total_hours_in_view": "Hours in View", - "total_hours_on_board": "Hours on Board", - "total_jobs_in_view": "Jobs in View", - "total_jobs_on_board": "Jobs on Board", - "total_lab_in_production": "Body Hours in Production", - "total_lab_in_view": "Body Hours in View", - "total_lab_on_board": "Body Hours on Board", - "total_lar_in_production": "Refinish Hours in Production", - "total_lar_in_view": "Refinish Hours in View", - "total_lar_on_board": "Refinish Hours on Board" - }, - "statistics_title": "Statistics" - }, - "statistics": { - "currency_symbol": "$", - "hours": "Hours", - "jobs": "Jobs", - "jobs_in_production": "Jobs in Production", - "tasks": "Tasks", - "tasks_in_production": "Tasks in Production", - "tasks_in_view": "Tasks in View", - "tasks_on_board": "Tasks on Board", - "total_amount_in_production": "Dollars in Production", - "total_amount_in_view": "Dollars in View", - "total_amount_on_board": "Dollars on Board", - "total_hours_in_production": "Hours in Production", - "total_hours_in_view": "Hours in View", - "total_hours_on_board": "Hours on Board", - "total_jobs_in_view": "Jobs in View", - "total_jobs_on_board": "Jobs on Board", - "total_lab_in_production": "Body Hours in Production", - "total_lab_in_view": "Body Hours in View", - "total_lab_on_board": "Body Hours on Board", - "total_lar_in_production": "Refinish Hours in Production", - "total_lar_in_view": "Refinish Hours in View", - "total_lar_on_board": "Refinish Hours on Board" - }, - "successes": { - "removed": "Job removed from production." - } - }, - "profile": { - "errors": { - "state": "Error reading page state. Please refresh." - }, - "labels": { - "activeshop": "Active Shop" - }, - "successes": { - "updated": "Profile updated successfully." - } - }, - "reportcenter": { - "actions": { - "generate": "Generate" - }, - "labels": { - "advanced_filters": "Advanced Filters and Sorters", - "advanced_filters_false": "False", - "advanced_filters_filter_field": "Field", - "advanced_filters_filter_operator": "Operator", - "advanced_filters_filter_value": "Value", - "advanced_filters_filters": "Filters", - "advanced_filters_hide": "Hide", - "advanced_filters_show": "Show", - "advanced_filters_sorter_direction": "Direction", - "advanced_filters_sorter_field": "Field", - "advanced_filters_sorters": "Sorters", - "advanced_filters_true": "True", - "dates": "Dates", - "employee": "Employee", - "filterson": "Filters on {{object}}: {{field}}", - "generateasemail": "Generate as Email?", - "groups": { - "customers": "Customers", - "jobs": "Jobs & Costing", - "payroll": "Payroll", - "purchases": "Purchases", - "sales": "Sales" - }, - "key": "Report", - "objects": { - "appointments": "Appointments", - "bills": "Bills", - "csi": "CSI", - "exportlogs": "Export Logs", - "jobs": "Jobs", - "parts_orders": "Parts Orders", - "payments": "Payments", - "scoreboard": "Scoreboard", - "tasks": "Tasks", - "timetickets": "Timetickets" - }, - "vendor": "Vendor" - }, - "templates": { - "adp_payroll_flat": "ADP Payroll - Flat Rate", - "adp_payroll_straight": "ADP Payroll - Straight Time", - "anticipated_revenue": "Anticipated Revenue", - "ar_aging": "AR Aging", - "attendance_detail": "Attendance (All Employees)", - "attendance_employee": "Employee Attendance", - "attendance_summary": "Attendance Summary (All Employees)", - "committed_timetickets": "Committed Time Tickets", - "committed_timetickets_employee": "Committed Employee Time Tickets", - "committed_timetickets_summary": "Committed Time Tickets Summary", - "credits_not_received_date": "Credits not Received by Date", - "credits_not_received_date_vendorid": "Credits not Received by Vendor", - "csi": "CSI Responses", - "customer_list": "Customer List", - "cycle_time_analysis": "Cycle Time Analysis", - "estimates_written_converted": "Estimates Written/Converted", - "estimator_detail": "Jobs by Estimator (Detail)", - "estimator_summary": "Jobs by Estimator (Summary)", - "export_payables": "Export Log - Payables", - "export_payments": "Export Log - Payments", - "export_receivables": "Export Log - Receivables", - "exported_gsr_by_ro": "Exported Gross Sales - Excel", - "exported_gsr_by_ro_labor": "Exported Gross Sales (Labor) - Excel", - "gsr_by_atp": "", - "gsr_by_ats": "Gross Sales by ATS", - "gsr_by_category": "Gross Sales by Category", - "gsr_by_csr": "Gross Sales by CSR", - "gsr_by_delivery_date": "Gross Sales by Delivery Date", - "gsr_by_estimator": "Gross Sales by Estimator", - "gsr_by_exported_date": "Exported Gross Sales", - "gsr_by_ins_co": "Gross Sales by Insurance Company", - "gsr_by_make": "Gross Sales by Vehicle Make", - "gsr_by_referral": "Gross Sales by Referral Source", - "gsr_by_ro": "Gross Sales by RO", - "gsr_labor_only": "Gross Sales - Labor Only", - "hours_sold_detail_closed": "Hours Sold Detail - Closed", - "hours_sold_detail_closed_csr": "Hours Sold Detail - Closed by CSR", - "hours_sold_detail_closed_estimator": "Hours Sold Detail - Closed by Estimator", - "hours_sold_detail_closed_ins_co": "Hours Sold Detail - Closed by Source", - "hours_sold_detail_closed_status": "Hours Sold Detail - Closed by Status", - "hours_sold_detail_open": "Hours Sold Detail - Open", - "hours_sold_detail_open_csr": "Hours Sold Detail - Open by CSR", - "hours_sold_detail_open_estimator": "Hours Sold Detail - Open by Estimator", - "hours_sold_detail_open_ins_co": "Hours Sold Detail - Open by Source", - "hours_sold_detail_open_status": "Hours Sold Detail - Open by Status", - "hours_sold_summary_closed": "Hours Sold Summary - Closed", - "hours_sold_summary_closed_csr": "Hours Sold Summary - Closed by CSR", - "hours_sold_summary_closed_estimator": "Hours Sold Summary - Closed by Estimator", - "hours_sold_summary_closed_ins_co": "Hours Sold Summary - Closed by Source", - "hours_sold_summary_closed_status": "Hours Sold Summary - Closed by Status", - "hours_sold_summary_open": "Hours Sold Summary - Open", - "hours_sold_summary_open_csr": "Hours Sold Summary - Open CSR", - "hours_sold_summary_open_estimator": "Hours Sold Summary - Open Estimator", - "hours_sold_summary_open_ins_co": "Hours Sold Summary - Open by Source", - "hours_sold_summary_open_status": "Hours Sold Summary - Open by Status", - "job_costing_ro_csr": "Job Costing by CSR", - "job_costing_ro_date_detail": "Job Costing by RO - Detail", - "job_costing_ro_date_summary": "Job Costing by RO - Summary", - "job_costing_ro_estimator": "Job Costing by Estimator", - "job_costing_ro_ins_co": "Job Costing by RO Source", - "job_lifecycle_date_detail": "Job Lifecycle by Date - Detail", - "job_lifecycle_date_summary": "Job Lifecycle by Date - Summary", - "jobs_completed_not_invoiced": "Jobs Completed not Invoiced", - "jobs_invoiced_not_exported": "Jobs Invoiced not Exported", - "jobs_reconcile": "Parts/Sublet/Labor Reconciliation", - "jobs_scheduled_completion": "Jobs Scheduled Completion", - "lag_time": "Lag Time", - "load_level": "Load Level", - "lost_sales": "Lost Sales", - "open_orders": "Open Orders by Date", - "open_orders_csr": "Open Orders by CSR", - "open_orders_estimator": "Open Orders by Estimator", - "open_orders_excel": "Open Orders - Excel", - "open_orders_ins_co": "Open Orders by Insurance Company", - "open_orders_referral": "Open Orders by Referral Source", - "open_orders_specific_csr": "Open Orders filtered by CSR", - "open_orders_status": "Open Orders by Status", - "parts_backorder": "IOU Parts List", - "parts_not_recieved": "Parts Not Received", - "parts_not_recieved_vendor": "Parts Not Received by Vendor", - "parts_received_not_scheduled": "Parts Received for Jobs Not Scheduled", - "payments_by_date": "Payments by Date", - "payments_by_date_payment": "Payments by Date and Payment Type", - "payments_by_date_type": "Payments by Date and Customer Type", - "production_by_category": "Production by Category", - "production_by_category_one": "Production filtered by Category", - "production_by_csr": "Production by CSR", - "production_by_last_name": "Production by Last Name", - "production_by_repair_status": "Production by Status", - "production_by_repair_status_one": "Production filtered by Status", - "production_by_ro": "Production by RO", - "production_by_target_date": "Production by Scheduled Completion", - "production_by_technician": "Production by Technician", - "production_by_technician_one": "Production filtered by Technician", - "production_not_production_status": "Production not in Production Status", - "production_over_time": "Production Level over Time", - "psr_by_make": "Percent of Sales by Vehicle Make", - "purchase_return_ratio_excel": "Purchase & Return Ratio - Excel", - "purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)", - "purchase_return_ratio_grouped_by_vendor_summary": "Purchase & Return Ratio by Vendor (Summary)", - "purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)", - "purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)", - "purchases_by_date_excel": "Purchases by Date - Excel", - "purchases_by_date_range_detail": "Purchases by Date - Detail", - "purchases_by_date_range_summary": "Purchases by Date - Summary", - "purchases_by_ro_detail_date": "Purchases by RO - Detail", - "purchases_by_ro_summary_date": "Purchases by RO - Summary", - "purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed", - "purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary", - "purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed", - "purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary", - "returns_grouped_by_vendor_detailed": "Returns Grouped by Vendor - Detailed", - "returns_grouped_by_vendor_summary": "Returns Grouped by Vendor - Summary", - "schedule": "Appointment Schedule", - "scheduled_parts_list": "Parts for Jobs Scheduled In", - "scoreboard_detail": "Scoreboard Detail", - "scoreboard_summary": "Scoreboard Summary", - "supplement_ratio_ins_co": "Supplement Ratio by Source", - "tasks_date": "Tasks by Date", - "tasks_date_employee": "Employee Tasks by Date", - "thank_you_date": "Thank You Letters", - "timetickets": "Time Tickets", - "timetickets_employee": "Employee Time Tickets", - "timetickets_summary": "Time Tickets Summary", - "total_loss_jobs": "Jobs Marked as Total Loss", - "unclaimed_hrs": "Unflagged Hours", - "void_ros": "Void ROs", - "work_in_progress_committed_labour": "Work in Progress - Committed Labor", - "work_in_progress_jobs": "Work in Progress - Jobs", - "work_in_progress_labour": "Work in Progress - Labor", - "work_in_progress_payables": "Work in Progress - Payables" - } - }, - "schedule": { - "labels": { - "atssummary": "ATS Summary", - "employeevacation": "Employee Vacations", - "estimators": "Filter by Writer/Customer Rep.", - "ins_co_nm_filter": "Filter by Insurance Company", - "intake": "Intake Events", - "manual": "Manual Events", - "manualevent": "Add Manual Event" - } - }, - "scoreboard": { - "actions": { - "edit": "Edit" - }, - "errors": { - "adding": "Error adding Job to Scoreboard. {{message}}", - "removing": "Error removing Job from Scoreboard. {{message}}", - "updating": "Error updating Scoreboard. {{message}}" - }, - "fields": { - "bodyhrs": "Body Hours", - "date": "Date", - "painthrs": "Paint Hours" - }, - "labels": { - "allemployeetimetickets": "All Employee Time Tickets", - "asoftodaytarget": "As of Today", - "body": "Body", - "bodyabbrev": "B", - "bodycharttitle": "Body Targets vs Actual", - "calendarperiod": "Periods based on calendar weeks/months.", - "combinedcharttitle": "Combined Targets vs Actual", - "dailyactual": "Actual (D)", - "dailytarget": "Daily", - "efficiencyoverperiod": "Efficiency over Selected Dates", - "entries": "Scoreboard Entries", - "jobs": "Jobs", - "jobscompletednotinvoiced": "Completed Not Invoiced", - "lastmonth": "Last Month", - "lastweek": "Last Week", - "monthlytarget": "Monthly", - "priorweek": "Prior Week", - "productivestatistics": "Productive Hours Statistics", - "productivetimeticketsoverdate": "Productive Hours over Selected Dates", - "refinish": "Refinish", - "refinishabbrev": "R", - "refinishcharttitle": "Refinish Targets vs Actual", - "targets": "Targets", - "thismonth": "This Month", - "thisweek": "This Week", - "timetickets": "Time Tickets", - "timeticketsemployee": "Time Tickets by Employee", - "todateactual": "Actual (MTD)", - "total": "Total", - "totalhrs": "Total Hours", - "totaloverperiod": "Total over Selected Dates", - "weeklyactual": "Actual (W)", - "weeklytarget": "Weekly", - "workingdays": "Working Days / Month" - }, - "successes": { - "added": "Job added to scoreboard.", - "removed": "Job removed from scoreboard.", - "updated": "Scoreboard updated." - } - }, - "tasks": { - "actions": { - "edit": "Edit Task", - "new": "New Task", - "view": "View Task" - }, - "buttons": { - "allTasks": "All", - "complete": "Toggle Complete", - "create": "Create Task", - "delete": "Toggle Delete", - "edit": "Edit", - "myTasks": "Mine", - "refresh": "Refresh" - }, - "date_presets": { - "completion": "Completion", - "day": "Day", - "days": "Days", - "delivery": "Delivery", - "next_week": "Next Week", - "one_month": "One Month", - "three_months": "Three Months", - "three_weeks": "Three Weeks", - "today": "Today", - "tomorrow": "Tomorrow", - "two_weeks": "Two Weeks" - }, - "failures": { - "completed": "Failed to toggle Task completion.", - "created": "Failed to create Task.", - "deleted": "Failed to toggle Task deletion.", - "updated": "Failed to update Task." - }, - "fields": { - "actions": "Actions", - "assigned_to": "Assigned To", - "bill": "Bill", - "billid": "Bill", - "completed": "Completed", - "created_at": "Created At", - "created_by": "Created By", - "description": "Description", - "due_date": "Due Date", - "job": { - "ro_number": "RO #" - }, - "jobid": "Job", - "jobline": "Job Line", - "joblineid": "Job Line", - "parts_order": "Parts Order", - "partsorderid": "Parts Order", - "priorities": { - "high": "High", - "low": "Low", - "medium": "Medium" - }, - "priority": "Priority", - "related_items": "Related Items", - "remind_at": "Remind At", - "title": "Title" - }, - "placeholders": { - "assigned_to": "Select an Employee", - "billid": "Select a Bill", - "description": "Enter a description", - "jobid": "Select a Job", - "joblineid": "Select a Job Line", - "partsorderid": "Select a Parts Order" - }, - "successes": { - "completed": "Toggled Task completion successfully.", - "created": "Task created successfully.", - "deleted": "Toggled Task deletion successfully.", - "updated": "Task updated successfully." - }, - "titles": { - "all_tasks": "All Tasks", - "completed": "Completed Tasks", - "deleted": "Deleted Tasks", - "job_tasks": "Job Tasks", - "mine": "My Tasks", - "my_tasks": "My Tasks" - }, - "validation": { - "due_at_error_message": "The due date must be in the future!", - "remind_at_error_message": "The reminder date and time must be at least 30 minutes in the future!" - } - }, - "tech": { - "fields": { - "employeeid": "Employee ID", - "pin": "PIN" - }, - "labels": { - "loggedin": "Logged in as {{name}}", - "notloggedin": "Not logged in." - } - }, - "templates": { - "errors": { - "updating": "Error updating template {{error}}." - }, - "successes": { - "updated": "Template updated successfully." - } - }, - "timetickets": { - "actions": { - "claimtasks": "Flag Hours", - "clockin": "Clock In", - "clockout": "Clock Out", - "commit": "Commit Tickets ({{count}})", - "commitone": "Commit", - "enter": "Enter New Time Ticket", - "payall": "Pay All", - "printemployee": "Print Time Tickets", - "uncommit": "Uncommit" - }, - "errors": { - "clockingin": "Error while clocking in. {{message}}", - "clockingout": "Error while clocking out. {{message}}", - "creating": "Error creating time ticket. {{message}}", - "deleting": "Error deleting time ticket. {{message}}", - "noemployeeforuser": "Unable to use Shift Clock", - "noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. ", - "payall": "Error flagging hours. {{error}}", - "shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry." - }, - "fields": { - "actualhrs": "Actual Hours", - "ciecacode": "CIECA Code", - "clockhours": "Clock Hours", - "clockoff": "Clock Off", - "clockon": "Clocked In", - "committed": "Committed", - "committed_at": "Committed At", - "cost_center": "Cost Center", - "created_by": "Created By", - "date": "Ticket Date", - "efficiency": "Efficiency", - "employee": "Employee", - "employee_team": "Employee Team", - "flat_rate": "Flat Rate?", - "memo": "Memo", - "productivehrs": "Productive Hours", - "ro_number": "Job to Post Against", - "task_name": "Task" - }, - "labels": { - "alreadyclockedon": "You are already clocked in to the following Job(s):", - "ambreak": "AM Break", - "amshift": "AM Shift", - "claimtaskpreview": "Flagged Hours Preview", - "clockhours": "Shift Clock Hours Summary", - "clockintojob": "Clock In to Job", - "deleteconfirm": "Are you sure you want to delete this time ticket? This cannot be undone.", - "edit": "Edit Time Ticket", - "efficiency": "Efficiency", - "flat_rate": "Flat Rate", - "jobhours": "Job Related Time Tickets Summary", - "lunch": "Lunch", - "new": "New Time Ticket", - "payrollclaimedtasks": "These time tickets will be automatically entered to the system as a part of claiming this task. These numbers are calculated using the jobs assigned lines. If lines are unassigned, they will be excluded from created tickets.", - "pmbreak": "PM Break", - "pmshift": "PM Shift", - "shift": "Shift", - "shiftalreadyclockedon": "Active Shift Time Tickets", - "straight_time": "Straight Time", - "task": "Task", - "timetickets": "Time Tickets", - "unassigned": "Unassigned", - "zeroactualnegativeprod": "Actual hours must be 0 if entering negative productive hours." - }, - "successes": { - "clockedin": "Clocked in successfully.", - "clockedout": "Clocked out successfully.", - "committed": "Time Tickets Committed Successfully", - "created": "Time ticket entered successfully.", - "deleted": "Time ticket deleted successfully.", - "payall": "All hours paid out successfully." - }, - "validation": { - "clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.", - "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time.", - "hoursenteredmorethanavailable": "The number of hours entered is more than what is available for this cost center.", - "unassignedlines": "There are currently {{unassignedHours}} hours of repair lines that are unassigned. These hours are not including in the above calculations and must be paid manually." - } - }, - "titles": { - "accounting-payables": "Payables | {{app}}", - "accounting-payments": "Payments | {{app}}", - "accounting-receivables": "Receivables | {{app}}", - "all_tasks": "All Tasks", - "app": "", - "bc": { - "accounting-payables": "Payables", - "accounting-payments": "Payments", - "accounting-receivables": "Receivables", - "all_tasks": "All Tasks", - "availablejobs": "Available Jobs", - "bills-list": "Bills", - "contracts": "Contracts", - "contracts-create": "New Contract", - "contracts-detail": "Contract #{{number}}", - "courtesycars": "Courtesy Cars", - "courtesycars-detail": "Courtesy Car {{number}}", - "courtesycars-new": "New Courtesy Car", - "dashboard": "Dashboard", - "dms": "DMS Export", - "export-logs": "Export Logs", - "inventory": "Inventory", - "jobs": "Jobs", - "jobs-active": "Active Jobs", - "jobs-admin": "Admin", - "jobs-all": "All Jobs", - "jobs-checklist": "Checklist", - "jobs-close": "Close Job", - "jobs-deliver": "Deliver Job", - "jobs-detail": "Job {{number}}", - "jobs-intake": "Intake", - "jobs-new": "Create a New Job", - "jobs-ready": "Ready Jobs", - "my_tasks": "My Tasks", - "owner-detail": "{{name}}", - "owners": "Owners", - "parts-queue": "Parts Queue", - "payments-all": "All Payments", - "phonebook": "Phonebook", - "productionboard": "Production Board - Visual", - "productionlist": "Production Board - List", - "profile": "My Profile", - "schedule": "Schedule", - "scoreboard": "Scoreboard", - "shop": "Manage my Shop ({{shopname}})", - "shop-csi": "CSI Responses", - "shop-templates": "Shop Templates", - "shop-vendors": "Vendors", - "tasks": "Tasks", - "temporarydocs": "Temporary Documents", - "timetickets": "Time Tickets", - "ttapprovals": "Time Ticket Approvals", - "vehicle-details": "Vehicle: {{vehicle}}", - "vehicles": "Vehicles" - }, - "bills-list": "Bills | {{app}}", - "contracts": "Courtesy Car Contracts | {{app}}", - "contracts-create": "New Contract | {{app}}", - "contracts-detail": "Contract {{id}} | {{app}}", - "courtesycars": "Courtesy Cars | {{app}}", - "courtesycars-create": "New Courtesy Car | {{app}}", - "courtesycars-detail": "Courtesy Car {{id}} | {{app}}", - "dashboard": "Dashboard | {{app}}", - "dms": "DMS Export | {{app}}", - "export-logs": "Export Logs | {{app}}", - "imexonline": "ImEX Online", - "inventory": "Inventory | {{app}}", - "jobs": "Active Jobs | {{app}}", - "jobs-admin": "Job {{ro_number}} - Admin | {{app}}", - "jobs-all": "All Jobs | {{app}}", - "jobs-checklist": "Job Checklist | {{app}}", - "jobs-close": "Close Job {{number}} | {{app}}", - "jobs-create": "Create a New Job | {{app}}", - "jobs-deliver": "Deliver Job | {{app}}", - "jobs-intake": "Intake | {{app}}", - "jobsavailable": "Available Jobs | {{app}}", - "jobsdetail": "Job {{ro_number}} | {{app}}", - "jobsdocuments": "Job Documents {{ro_number}} | {{app}}", - "manageroot": "Home | {{app}}", - "my_tasks": "My Tasks", - "owners": "All Owners | {{app}}", - "owners-detail": "{{name}} | {{app}}", - "parts-queue": "Parts Queue | {{app}}", - "payments-all": "Payments | {{app}}", - "phonebook": "Phonebook | {{app}}", - "productionboard": "Production Board - Visual | {{app}}", - "productionlist": "Production Board - List | {{app}}", - "profile": "My Profile | {{app}}", - "readyjobs": "Ready Jobs | {{app}}", - "resetpassword": "Reset Password", - "resetpasswordvalidate": "Enter New Password", - "romeonline": "Rome Online", - "schedule": "Schedule | {{app}}", - "scoreboard": "Scoreboard | {{app}}", - "shop": "My Shop | {{app}}", - "shop-csi": "CSI Responses | {{app}}", - "shop-templates": "Shop Templates | {{app}}", - "shop_vendors": "Vendors | {{app}}", - "tasks": "Tasks", - "techconsole": "Technician Console | {{app}}", - "techjobclock": "Technician Job Clock | {{app}}", - "techjoblookup": "Technician Job Lookup | {{app}}", - "techshiftclock": "Technician Shift Clock | {{app}}", - "temporarydocs": "Temporary Documents | {{app}}", - "timetickets": "Time Tickets | {{app}}", - "ttapprovals": "Time Ticket Approvals | {{app}}", - "vehicledetail": "Vehicle Details {{vehicle}} | {{app}}", - "vehicles": "All Vehicles | {{app}}" - }, - "trello": { - "labels": { - "add_card": "Add Card", - "add_lane": "Add Lane", - "cancel": "Cancel", - "delete_lane": "Delete Lane", - "description": "Description", - "label": "Label", - "lane_actions": "Lane Actions", - "title": "Title" - } - }, - "tt_approvals": { - "actions": { - "approveselected": "Approve Selected" - }, - "labels": { - "approval_queue_in_use": "Time tickets will be added to the approval queue.", - "calculate": "Calculate" - } - }, - "upsell": { - "cta": { - "learnmore": "Learn More" - }, - "messages": { - "accounting": { - "payables": { - "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", - "title": "Eliminate double data entry" - }, - "payments": { - "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", - "title": "Eliminate double data entry" - }, - "receivables": { - "subtitle": "Effortlessly send your invoices to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", - "title": "Eliminate double data entry" - } - }, - "audit": { - "general": { - "subtitle": "Know exactly what happened and when through the entire repair process.", - "title": "Comprehensive Audit Trails" - } - }, - "bills": { - "autoreconcile": { - "subtitle": "Let your management system do the tedious work - take advantage of automatic job reconciliation today.", - "title": "Did you account for every invoice?" - }, - "general": { - "subtitle": "Our Bills module allows you to precisely account for every penny on the repair order to ensure you maximize your bottom line.", - "title": "Boost your profits by taking control of costs!" - } - }, - "checklist": { - "general": { - "subtitle": "Standardize your intake and delivery with digitized checklists and SOPs.", - "title": "Done right, the first time." - } - }, - "courtesycars": { - "general": { - "subtitle": "Keep track of vehicles and contracts for your courtesy cars, all seamlessly synchronized with your Jobs.", - "title": "Manage your fleet with ease" - } - }, - "csi": { - "general": { - "subtitle": "With our integrated CSI module, send follow up surveys to your customers to see how well you did.", - "title": "See what your customers have to say" - } - }, - "dashboard": { - "general": { - "subtitle": "Make data based decisions and take control of your business using our real-time dashboard.", - "title": "Realtime Insight & Analytics" - } - }, - "lifecycle": { - "general": { - "subtitle": "Job life cycles tell you exactly how long the job stayed in each stage of the repair process to identify bottle necks and inefficiencies.", - "title": "Are your repair KPIs suffering?" - } - }, - "media": { - "general": { - "subtitle": "Store your vehicle repair documentation, invoices, and related documents digitally to access them anywhere, any time.", - "title": "Go paperless." - }, - "mobile": { - "subtitle": "Use our mobile app to attach images from your device to the job, increasing your efficiency.", - "title": "Accelerate repair documentation with Mobile" - } - }, - "payments": { - "general": { - "subtitle": "Manage outstanding balances and collect payments by credit card from your customers.", - "title": "Integrated Accounts Receivable & Payments" - } - }, - "scoreboard": { - "general": { - "subtitle": "Understand hours produced and sold to facilitate employee incentive programs.", - "title": "Give credit where credit is due" - } - }, - "smartscheduling": { - "datepicker": { - "subtitle": "Smart Scsheduling gives you the best dates for a vehicle to come in based on your current and predicted production load.", - "title": "When's the best time for this job to arrive?" - }, - "general": { - "subtitle": "Know exactly how busy you will be tomorrow, the day after, or next week to know exactly when to schedule your next repair.", - "title": "Forecast your production with Smart Scheduling" - }, - "hrsdelta": { - "subtitle": "Understand changes to your Work in Progress and production load instantly.", - "title": "Cars come and cars go." - } - }, - "techconsole": { - "general": { - "subtitle": "The technician's console allows technicians to see job information, media, documents and keep track of their time.", - "title": "Empower your Technicians" - } - }, - "timetickets": { - "allocations": { - "subtitle": "Ensure your technicians are paid out exactly what they are owed - not a penny less, not a penny more.", - "title": "Technician Payments Done Just Right" - }, - "general": { - "subtitle": "Track your technicians time with precision, giving you insight to repair progress and labor efficiency.", - "title": "Who did what and for how long?" - } - }, - "visualboard": { - "general": { - "subtitle": "The Visual Production Board makes it easier than ever before to manage your work in progress.", - "title": "A whole new kind of production board" - } - } - } - }, - "user": { - "actions": { - "changepassword": "Change Password", - "signout": "Sign Out", - "updateprofile": "Update Profile" - }, - "errors": { - "updating": "Error updating user or association {{message}}" - }, - "fields": { - "authlevel": "Authorization Level", - "displayname": "Display Name", - "email": "Email", - "photourl": "Avatar URL" - }, - "labels": { - "actions": "Actions", - "changepassword": "Change Password", - "profileinfo": "Profile Info" - }, - "successess": { - "passwordchanged": "Password changed successfully. " - } - }, - "users": { - "errors": { - "signinerror": { - "auth/user-disabled": "User account disabled. ", - "auth/user-not-found": "A user with this email does not exist.", - "auth/wrong-password": "The email and password combination you provided is incorrect." - } - } - }, - "vehicles": { - "errors": { - "deleting": "Error deleting vehicle. {{error}}.", - "noaccess": "The vehicle does not exist or you do not have access to it.", - "selectexistingornew": "Select an existing vehicle record or create a new one. ", - "validation": "Please ensure all fields are entered correctly.", - "validationtitle": "Validation Error" - }, - "fields": { - "description": "Vehicle Description", - "notes": "Vehicle Notes", - "plate_no": "License Plate", - "plate_st": "Plate Jurisdiction", - "trim_color": "Trim Color", - "v_bstyle": "Body Style", - "v_color": "Color", - "v_cond": "Condition", - "v_engine": "Engine", - "v_make_desc": "Make", - "v_makecode": "Make Code", - "v_mldgcode": "Molding Code", - "v_model_desc": "Model", - "v_model_yr": "Year", - "v_options": "Options", - "v_paint_codes": "Paint Codes {{number}}", - "v_prod_dt": "Production Date", - "v_stage": "Stage", - "v_tone": "Tone", - "v_trimcode": "Trim Code", - "v_type": "Type", - "v_vin": "V.I.N." - }, - "forms": { - "detail": "Vehicle Details", - "misc": "Miscellaneous", - "registration": "Registration" - }, - "labels": { - "deleteconfirm": "Are you sure you want to delete this vehicle? This cannot be undone.", - "fromvehicle": "Historical Vehicle Record", - "novehinfo": "No Vehicle Information", - "relatedjobs": "Related Jobs", - "updatevehicle": "Update Vehicle Information" - }, - "successes": { - "delete": "Vehicle deleted successfully.", - "save": "Vehicle saved successfully." - } - }, - "vendors": { - "actions": { - "addtophonebook": "Add to Phonebook", - "new": "New Vendor", - "newpreferredmake": "New Preferred Make" - }, - "errors": { - "deleting": "Error encountered while deleting vendor. ", - "saving": "Error encountered while saving vendor. " - }, - "fields": { - "active": "Active", - "am": "Aftermarket", - "city": "City", - "cost_center": "Cost Center", - "country": "Country", - "discount": "Discount % (as decimal)", - "display_name": "Display Name", - "dmsid": "DMS ID", - "due_date": "Payment Due Date (# of days)", - "email": "Contact Email", - "favorite": "Favorite?", - "lkq": "LKQ", - "make": "Make", - "name": "Vendor Name", - "oem": "OEM", - "phone": "Phone", - "prompt_discount": "Prompt Discount %", - "state": "Province/State", - "street1": "Street", - "street2": "Address 2", - "taxid": "Tax ID", - "terms": "Payment Terms", - "zip": "Zip/Postal Code" - }, - "labels": { - "noneselected": "No vendor is selected.", - "preferredmakes": "Preferred Makes for Vendor", - "search": "Type a Vendor's Name" - }, - "successes": { - "deleted": "Vendor deleted successfully. ", - "saved": "Vendor saved successfully." - }, - "validation": { - "unique_vendor_name": "You must enter a unique vendor name." - } - }, + "translation": { + "allocations": { + "actions": { + "assign": "Assign" + }, + "errors": { + "deleting": "Error encountered while deleting allocation. {{message}}", + "saving": "Error while allocating. {{message}}", + "validation": "Please ensure all fields are entered correctly. " + }, + "fields": { + "employee": "Allocated To" + }, + "successes": { + "deleted": "Allocation deleted successfully.", + "save": "Allocated successfully. " + } + }, + "appointments": { + "actions": { + "block": "Block Day", + "calculate": "Calculate SMART Dates", + "cancel": "Cancel Appointment", + "intake": "Intake", + "new": "New Appointment", + "preview": "Preview", + "reschedule": "Reschedule", + "sendreminder": "Send Reminder", + "unblock": "Unblock", + "viewjob": "View Job" + }, + "errors": { + "blocking": "Error creating block {{message}}.", + "canceling": "Error canceling appointment. {{message}}", + "saving": "Error scheduling appointment. {{message}}" + }, + "fields": { + "alt_transport": "Alt. Trans.", + "color": "Appointment Color", + "end": "End", + "note": "Note", + "start": "Start", + "time": "Appointment Time", + "title": "Title" + }, + "labels": { + "arrivedon": "Arrived on: ", + "arrivingjobs": "Arriving Jobs", + "blocked": "Blocked", + "cancelledappointment": "Canceled appointment for: ", + "completingjobs": "Completing Jobs", + "dataconsistency": "<0>{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.", + "expectedjobs": "Expected Jobs in Production: ", + "expectedprodhrs": "Expected Production Hours:", + "history": "History", + "inproduction": "Jobs In Production", + "manualevent": "Add Manual Appointment", + "noarrivingjobs": "No Jobs are arriving.", + "nocompletingjobs": "No Jobs scheduled for completion.", + "nodateselected": "No date has been selected.", + "priorappointments": "Previous Appointments", + "reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ", + "scheduledfor": "Scheduled appointment for: ", + "severalerrorsfound": "Several Jobs have issues which may prevent accurate smart scheduling. Click to expand.", + "smartscheduling": "Smart Scheduling", + "smspaymentreminder": "This is {{shopname}} reminding you about your remaining balance of {{amount}}. To pay for the said balance click the link {{payment_link}}.", + "suggesteddates": "Suggested Dates" + }, + "successes": { + "canceled": "Appointment canceled successfully.", + "created": "Appointment scheduled successfully.", + "saved": "Appointment saved successfully." + } + }, + "associations": { + "actions": { + "activate": "Activate" + }, + "fields": { + "active": "Active?", + "shopname": "Shop Name" + }, + "labels": { + "actions": "Actions" + } + }, + "audit": { + "fields": { + "cc": "CC", + "contents": "Contents", + "created": "Time", + "operation": "Operation", + "status": "Status", + "subject": "Subject", + "to": "To", + "useremail": "User", + "values": "Values" + } + }, + "audit_trail": { + "messages": { + "admin_job_remove_from_ar": "ADMIN: Remove from AR updated to: {{status}}", + "admin_jobmarkexported": "ADMIN: Job marked as exported.", + "admin_jobmarkforreexport": "ADMIN: Job marked for re-export.", + "admin_jobuninvoice": "ADMIN: Job has been uninvoiced.", + "admin_jobunvoid": "ADMIN: Job has been unvoided.", + "alerttoggle": "Alert Toggle set to {{status}}", + "appointmentcancel": "Appointment canceled. Lost Reason: {{lost_sale_reason}}.", + "appointmentinsert": "Appointment created. Appointment Date: {{start}}.", + "assignedlinehours": "Assigned job lines totaling {{hours}} units to {{team}}.", + "billdeleted": "Bill with invoice number {{invoice_number}} deleted.", + "billposted": "Bill with invoice number {{invoice_number}} posted.", + "billupdated": "Bill with invoice number {{invoice_number}} updated.", + "failedpayment": "Failed payment attempt.", + "jobassignmentchange": "Employee {{name}} assigned to {{operation}}", + "jobassignmentremoved": "Employee assignment removed for {{operation}}", + "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.", + "jobclosedwithbypass": "Job was invoiced using the master bypass password. ", + "jobconverted": "Job converted and assigned number {{ro_number}}.", + "jobdelivery": "Job intake completed. Status set to {{status}}. Actual completion is {{actual_completion}}.", + "jobexported": "Job has been exported", + "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.", + "jobimported": "Job imported.", + "jobinproductionchange": "Job production status set to {{inproduction}}", + "jobintake": "Job intake completed. Status set to {{status}}. Scheduled completion is {{scheduled_completion}}.", + "jobinvoiced": "Job has been invoiced.", + "jobioucreated": "IOU Created.", + "jobmodifylbradj": "Labor adjustments modified {{mod_lbr_ty}} / {{hours}}.", + "jobnoteadded": "Note added to Job.", + "jobnotedeleted": "Note deleted from Job.", + "jobnoteupdated": "Note updated on Job.", + "jobspartsorder": "Parts order {{order_number}} added to Job.", + "jobspartsreturn": "Parts return {{order_number}} added to Job.", + "jobstatuschange": "Job status changed to {{status}}.", + "jobsupplement": "Job supplement imported.", + "jobsuspend": "Suspend Toggle set to {{status}}", + "jobvoid": "Job has been voided.", + "tasks_completed": "Task '{{title}}' completed by {{completedBy}}", + "tasks_created": "Task '{{title}}' created by {{createdBy}}", + "tasks_deleted": "Task '{{title}}' deleted by {{deletedBy}}", + "tasks_uncompleted": "Task '{{title}}' uncompleted by {{uncompletedBy}}", + "tasks_undeleted": "Task '{{title}}' undeleted by {{undeletedBy}}", + "tasks_updated": "Task '{{title}}' updated by {{updatedBy}}" + } + }, + "billlines": { + "actions": { + "newline": "New Line" + }, + "fields": { + "actual_cost": "Actual Cost", + "actual_price": "Retail", + "cost_center": "Cost Center", + "federal_tax_applicable": "Fed. Tax?", + "jobline": "Job Line", + "line_desc": "Line Description", + "local_tax_applicable": "Loc. Tax?", + "location": "Location", + "quantity": "Quantity", + "state_tax_applicable": "St. Tax?" + }, + "labels": { + "deductedfromlbr": "Deduct from Labor?", + "entered": "Entered", + "from": "From", + "mod_lbr_adjustment": "Adjustment Units", + "other": "-- Not On Estimate --", + "reconciled": "Reconciled!", + "unreconciled": "Unreconciled" + }, + "validation": { + "atleastone": "At least one bill line must be entered." + } + }, + "bills": { + "actions": { + "deductallhours": "Deduct all", + "edit": "Edit", + "receive": "Receive Part", + "return": "Return Items" + }, + "errors": { + "creating": "Error adding bill. {{error}}", + "deleting": "Error deleting bill. {{error}}", + "existinginventoryline": "This bill cannot be deleted as it is tied to items in inventory.", + "exporting": "Error exporting payable(s). {{error}}", + "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.", + "invalidro": "Not a valid RO.", + "invalidvendor": "Not a valid vendor.", + "validation": "Please ensure all fields are entered correctly. " + }, + "fields": { + "allpartslocation": "Parts Bin", + "date": "Bill Date", + "exported": "Exported", + "federal_tax_rate": "Federal Tax Rate", + "invoice_number": "Invoice Number", + "is_credit_memo": "Credit Memo?", + "is_credit_memo_short": "CM", + "local_tax_rate": "Local Tax Rate", + "ro_number": "RO Number", + "state_tax_rate": "State Tax Rate", + "total": "Bill Total", + "vendor": "Vendor", + "vendorname": "Vendor Name" + }, + "labels": { + "actions": "Actions", + "bill_lines": "Bill Lines", + "bill_total": "Bill Total Amount", + "billcmtotal": "Credit Memos", + "bills": "Bills", + "calculatedcreditsnotreceived": "Calculated CNR", + "creditsnotreceived": "Credits Not Marked Received", + "creditsreceived": "Credits Received", + "dedfromlbr": "Labor Adjustments", + "deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.", + "discrepancy": "Discrepancy", + "discrepwithcms": "Discrepancy including Credit Memos", + "discrepwithlbradj": "Discrepancy including Lbr. Adj.", + "editadjwarning": "This bill had lines which resulted in labor adjustments. Manual correction to adjustments may be required.", + "entered_total": "Total of Entered Lines", + "enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.", + "federal_tax": "Federal Tax", + "federal_tax_exempt": "Federal Tax Exempt?", + "generatepartslabel": "Generate Parts Labels after Saving?", + "iouexists": "An IOU exists that is associated to this RO.", + "local_tax": "Local Tax", + "markexported": "Mark Exported", + "markforreexport": "Mark for Re-export", + "new": "New Bill", + "nobilllines": "No bills have been posted yet.", + "noneselected": "No bill selected.", + "onlycmforinvoiced": "Only credit memos can be entered for any Job that has been invoiced, exported, or voided.", + "printlabels": "Print Labels", + "retailtotal": "Bills Retail Total", + "returnfrombill": "Return From Bill", + "savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.", + "state_tax": "State Tax", + "subtotal": "Subtotal", + "totalreturns": "Total Returns" + }, + "successes": { + "created": "Invoice added successfully.", + "deleted": "Bill deleted successfully.", + "exported": "Bill(s) exported successfully.", + "markexported": "Bill marked as exported.", + "reexport": "Bill marked for re-export." + }, + "validation": { + "closingperiod": "This Bill Date is outside of the Closing Period.", + "inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).", + "manualinhouse": "Manual posting to the in house vendor is restricted. ", + "unique_invoice_number": "This invoice number has already been entered for this vendor." + } + }, + "bodyshop": { + "actions": { + "add_task_preset": "Add Task Preset", + "addapptcolor": "Add Appointment Color", + "addbucket": "Add Definition", + "addpartslocation": "Add Parts Location", + "addpartsrule": "Add Parts Scan Rule", + "addspeedprint": "Add Speed Print", + "addtemplate": "Add Template", + "newlaborrate": "New Labor Rate", + "newsalestaxcode": "New Sales Tax Code", + "newstatus": "Add Status", + "testrender": "Test Render" + }, + "errors": { + "creatingdefaultview": "Error creating default view.", + "loading": "Unable to load shop details. Please call technical support.", + "saving": "Error encountered while saving. {{message}}" + }, + "fields": { + "ReceivableCustomField": "QBO Receivable Custom Field {{number}}", + "address1": "Address 1", + "address2": "Address 2", + "appt_alt_transport": "Appointment Alternative Transportation Options", + "appt_colors": { + "color": "Color", + "label": "Label" + }, + "appt_length": "Default Appointment Length", + "attach_pdf_to_email": "Attach PDF copy to sent emails?", + "batchid": "ADP Batch ID", + "bill_allow_post_to_closed": "Allow Bills to be posted to Closed Jobs", + "bill_federal_tax_rate": "Bills - Federal Tax Rate %", + "bill_local_tax_rate": "Bill - Local Tax Rate %", + "bill_state_tax_rate": "Bill - Provincial/State Tax Rate %", + "city": "City", + "closingperiod": "Closing Period", + "companycode": "ADP Company Code", + "country": "Country", + "dailybodytarget": "Scoreboard - Daily Body Target", + "dailypainttarget": "Scoreboard - Daily Paint Target", + "default_adjustment_rate": "Default Labor Deduction Adjustment Rate", + "deliver": { + "require_actual_delivery_date": "Require Actual Delivery", + "templates": "Delivery Templates" + }, + "dms": { + "apcontrol": "AP Control Number", + "appostingaccount": "AP Posting Account", + "cashierid": "Cashier ID", + "default_journal": "Default Journal", + "disablebillwip": "Disable bill WIP for A/P Posting", + "disablecontactvehiclecreation": "Disable Contact & Vehicle Updates/Creation", + "dms_acctnumber": "DMS Account #", + "dms_control_override": "Static Control # Override", + "dms_wip_acctnumber": "DMS W.I.P. Account #", + "generic_customer_number": "Generic Customer Number", + "itc_federal": "Federal Tax is ITC?", + "itc_local": "Local Tax is ITC?", + "itc_state": "State Tax is ITC?", + "mappingname": "DMS Mapping Name", + "sendmaterialscosting": "Materials Cost as % of Sale", + "srcco": "Source Company #/Dealer #" + }, + "email": "General Shop Email", + "enforce_class": "Enforce Class on Conversion?", + "enforce_conversion_category": "Enforce Category on Conversion?", + "enforce_conversion_csr": "Enforce CSR on Conversion?", + "enforce_referral": "Enforce Referrals", + "federal_tax_id": "Federal Tax ID (GST/HST)", + "ignoreblockeddays": "Scoreboard - Ignore Blocked Days", + "inhousevendorid": "In House Vendor ID", + "insurance_vendor_id": "Insurance Vendor ID", + "intake": { + "next_contact_hours": "Automatic Next Contact Date - Hours from Intake", + "templates": "Intake Templates" + }, + "intellipay_config": { + "cash_discount_percentage": "Cash Discount %", + "enable_cash_discount": "Enable Cash Discounting", + "payment_type": "Payment Type Map", + "payment_map": { + "amex": "American Express", + "disc": "Discover", + "dnrs": "Diners", + "intr": "Interac", + "jcb": "JCB", + "mast": "MasterCard", + "visa": "Visa" + } + }, + "invoice_federal_tax_rate": "Invoices - Federal Tax Rate", + "invoice_local_tax_rate": "Invoices - Local Tax Rate", + "invoice_state_tax_rate": "Invoices - State Tax Rate", + "jc_hourly_rates": { + "mapa": "Job Costing - Paint Materials Hourly Cost Rate", + "mash": "Job Costing - Shop Materials Hourly Cost Rate" + }, + "last_name_first": "Display Owner Info as , ", + "lastnumberworkingdays": "Scoreboard - Last Number of Working Days", + "localmediaserverhttp": "Local Media Server - HTTP Path", + "localmediaservernetwork": "Local Media Server - Network Path", + "localmediatoken": "Local Media Server - Token", + "logo_img_footer_margin": "Footer Margin (px)", + "logo_img_header_margin": "Header Margin (px)", + "logo_img_path": "Shop Logo", + "logo_img_path_height": "Logo Image Height", + "logo_img_path_width": "Logo Image Width", + "md_categories": "Categories", + "md_ccc_rates": "Courtesy Car Contract Rate Presets", + "md_classes": "Classes", + "md_ded_notes": "Deductible Notes", + "md_email_cc": "Auto Email CC: $t(parts_orders.labels.{{template}})", + "md_from_emails": "Additional From Emails", + "md_functionality_toggles": { + "parts_queue_toggle": "Auto Add Imported/Supplemented Jobs to Parts Queue" + }, + "md_hour_split": { + "paint": "Paint Hour Split", + "prep": "Prep Hour Split" + }, + "md_ins_co": { + "city": "City", + "name": "Insurance Company Name", + "private": "Private", + "state": "Province/State", + "street1": "Street 1", + "street2": "Street 2", + "zip": "Zip/Postal Code" + }, + "md_jobline_presets": "Jobline Presets", + "md_lost_sale_reasons": "Lost Sale Reasons", + "md_parts_order_comment": "Parts Orders Comments", + "md_parts_scan": { + "caseInsensitive": "Case Insensitive", + "expression": "", + "field": "Field", + "flags": "", + "mark_critical": "Mark Line as Critical?", + "operation": "Operation", + "update_field": "Field to Update", + "update_value": "Update Value", + "value": "Value" + }, + "md_payment_types": "Payment Types", + "md_referral_sources": "Referral Sources", + "md_ro_guard": { + "enabled": "RO Guard Enabled?", + "enforce_ar": "Enforce AR Balance", + "enforce_bills": "Enforce Bill Discrepancy", + "enforce_cm": "Enforce Credit Memo Entry", + "enforce_labor": "Enforce Labor Allocation", + "enforce_ppd": "Enforce PPD Sync", + "enforce_profit": "Enforce Profit Requirement", + "enforce_sublet": "Enforce Sublet Completion", + "masterbypass": "Master Bypass Password (not encrypted)", + "totalgppercent_minimum": "Minimum Total Gross Profit %" + }, + "md_tasks_presets": { + "enable_tasks": "Enable Hour Flagging", + "hourstype": "Hour Types", + "memo": "Time Ticket Memo", + "name": "Preset Name", + "nextstatus": "Next Status", + "percent": "Percent", + "use_approvals": "Use Time Ticket Approval Queue" + }, + "messaginglabel": "Messaging Preset Label", + "messagingtext": "Messaging Preset Text", + "noteslabel": "Note Label", + "notestext": "Note Text", + "partslocation": "Parts Location", + "phone": "Phone", + "prodtargethrs": "Production Target Hours", + "rbac": { + "accounting": { + "exportlog": "Accounting -> Export Log", + "payables": "Accounting -> Payables", + "payments": "Accounting -> Payments", + "receivables": "Accounting -> Receivables" + }, + "bills": { + "delete": "Bills -> Delete", + "enter": "Bills -> Enter", + "list": "Bills -> List", + "reexport": "Bills -> Re-export", + "view": "Bills -> View" + }, + "contracts": { + "create": "Contracts -> Create", + "detail": "Contracts -> Detail", + "list": "Contracts -> List" + }, + "courtesycar": { + "create": "Courtesy Car -> Create", + "detail": "Courtesy Car -> Detail", + "list": "Courtesy Car -> List" + }, + "csi": { + "export": "CSI -> Export", + "page": "CSI -> Page" + }, + "employee_teams": { + "page": "Employee Teams -> List" + }, + "employees": { + "page": "Employees -> List" + }, + "inventory": { + "delete": "Inventory -> Delete", + "list": "Inventory -> List" + }, + "jobs": { + "admin": "Jobs -> Admin", + "available-list": "Jobs -> Available List", + "checklist-view": "Jobs -> Checklist View", + "close": "Jobs -> Close", + "create": "Jobs -> Create", + "deliver": "Jobs -> Deliver", + "detail": "Jobs -> Detail", + "intake": "Jobs -> Intake", + "list-active": "Jobs -> List Active", + "list-all": "Jobs -> List All", + "list-ready": "Jobs -> List Ready", + "partsqueue": "Jobs -> Parts Queue", + "void": "Jobs -> Void" + }, + "owners": { + "detail": "Owners -> Detail", + "list": "Owners -> List" + }, + "payments": { + "enter": "Payments -> Enter", + "list": "Payments -> List" + }, + "phonebook": { + "edit": "Phonebook -> Edit", + "view": "Phonebook -> View" + }, + "production": { + "board": "Production -> Board", + "list": "Production -> List" + }, + "schedule": { + "view": "Schedule -> View" + }, + "scoreboard": { + "view": "Scoreboard -> View" + }, + "shiftclock": { + "view": "Shift Clock -> View" + }, + "shop": { + "config": "Shop -> Config", + "dashboard": "Shop -> Dashboard", + "rbac": "Shop -> RBAC", + "reportcenter": "Shop -> Report Center", + "templates": "Shop -> Templates", + "vendors": "Shop -> Vendors" + }, + "temporarydocs": { + "view": "Temporary Docs -> View" + }, + "timetickets": { + "edit": "Time Tickets -> Edit", + "editcommitted": "Time Tickets -> Edit Committed", + "enter": "Time Tickets -> Enter", + "list": "Time Tickets -> List", + "shiftedit": "Time Tickets -> Shift Edit" + }, + "ttapprovals": { + "approve": "Time Ticket Approval -> Approve", + "view": "Time Ticket Approval -> View" + }, + "users": { + "editaccess": "Users -> Edit access" + } + }, + "responsibilitycenter": "Responsibility Center", + "responsibilitycenter_accountdesc": "Account Description", + "responsibilitycenter_accountitem": "Item", + "responsibilitycenter_accountname": "Account Name", + "responsibilitycenter_accountnumber": "Account Number", + "responsibilitycenter_rate": "Rate", + "responsibilitycenter_tax_rate": "Tax {{typeNum}} Tier {{typeNumIterator}} Rate", + "responsibilitycenter_tax_sur": "Tax {{typeNum}} Tier {{typeNumIterator}} Surcharge", + "responsibilitycenter_tax_thres": "Tax {{typeNum}} Tier {{typeNumIterator}} Threshold", + "responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}", + "responsibilitycenter_tax_type": "Tax {{typeNum}} Type", + "responsibilitycenters": { + "ap": "Accounts Payable", + "ar": "Accounts Receivable", + "ats": "ATS", + "federal_tax": "Federal Tax", + "federal_tax_itc": "Federal Tax Credit", + "gst_override": "GST Override Account #", + "invoiceexemptcode": "QuickBooks US - Invoice Tax Exempt Code", + "itemexemptcode": "QuickBooks US - Line Item Tax Exempt Code", + "la1": "LA1", + "la2": "LA2", + "la3": "LA3", + "la4": "LA4", + "laa": "Aluminum", + "lab": "Body", + "lad": "Diagnostic", + "lae": "Electrical", + "laf": "Frame", + "lag": "Glass", + "lam": "Mechanical", + "lar": "Refinish", + "las": "Structural", + "lau": "User Defined", + "local_tax": "Local Tax", + "mapa": "Paint Materials", + "mash": "Shop Materials", + "paa": "Aftermarket", + "pac": "Chrome", + "pag": "Glass", + "pal": "LKQ", + "pam": "Remanufactured", + "pan": "OEM", + "pao": "Other", + "pap": "OEM Partial", + "par": "Recored", + "pas": "Sublet", + "pasl": "Sublet (L)", + "refund": "Refund", + "sales_tax_codes": { + "code": "Code", + "description": "Description", + "federal": "Federal Tax Applies", + "local": "Local Tax Applies", + "state": "State Tax Applies" + }, + "state_tax": "State Tax", + "tow": "Towing" + }, + "schedule_end_time": "Schedule Ending Time", + "schedule_start_time": "Schedule Starting Time", + "shopname": "Shop Name", + "speedprint": { + "id": "Id", + "label": "Label", + "templates": "Templates" + }, + "ss_configuration": { + "dailyhrslimit": "Daily Incoming Hours Limit" + }, + "ssbuckets": { + "color": "Job Color", + "gte": "Greater Than/Equal to (hrs)", + "id": "ID", + "label": "Label", + "lt": "Less than (hrs)", + "target": "Target (count)" + }, + "state": "Province/State", + "state_tax_id": "State Tax ID", + "status": "Status Label", + "statuses": { + "active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)", + "additional_board_statuses": "Additional Status to Display on Production Board", + "color": "Color", + "default_arrived": "Default Arrived Status (Transition to Production)", + "default_bo": "Default Backordered Status", + "default_canceled": "Default Canceled Status", + "default_completed": "Default Completed Status", + "default_delivered": "Default Delivered Status (Transition to Post-Production)", + "default_exported": "Default Exported Status", + "default_imported": "Default Imported Status", + "default_invoiced": "Default Invoiced Status", + "default_ordered": "Default Ordered Status", + "default_quote": "Default Quote Status", + "default_received": "Default Received Status", + "default_returned": "Default Returned", + "default_scheduled": "Default Scheduled Status", + "default_void": "Default Void", + "open_statuses": "Open Statuses", + "post_production_statuses": "Post-Production Statuses", + "pre_production_statuses": "Pre-Production Statuses", + "production_colors": "Production Status Colors", + "production_statuses": "Production Statuses", + "ready_statuses": "Ready Statuses" + }, + "target_touchtime": "Target Touch Time", + "timezone": "Timezone", + "tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs", + "tt_enforce_hours_for_tech_console": "Restrict Claimable Hours", + "use_fippa": "Conceal Customer Information on Generated Documents?", + "use_paint_scale_data": "Use Paint Scale Data for Job Costing?", + "uselocalmediaserver": "Use Local Media Server?", + "website": "Website", + "zip_post": "Zip/Postal Code" + }, + "labels": { + "2tiername": "Name => RO", + "2tiersetup": "2 Tier Setup", + "2tiersource": "Source => RO", + "accountingsetup": "Accounting Setup", + "accountingtiers": "Number of Tiers to Use for Export", + "alljobstatuses": "All Job Statuses", + "allopenjobstatuses": "All Open Job Statuses", + "apptcolors": "Appointment Colors", + "businessinformation": "Business Information", + "checklists": "Checklists", + "csiq": "CSI Questions", + "customtemplates": "Custom Templates", + "defaultcostsmapping": "Default Costs Mapping", + "defaultprofitsmapping": "Default Profits Mapping", + "deliverchecklist": "Delivery Checklist", + "dms": { + "cdk": { + "controllist": "Control Number List", + "payers": "Payers" + }, + "cdk_dealerid": "CDK Dealer ID", + "costsmapping": "Costs Mapping", + "dms_allocations": "DMS Allocations", + "pbs_serialnumber": "PBS Serial Number", + "profitsmapping": "Profits Mapping", + "title": "DMS" + }, + "emaillater": "Email Later", + "employee_teams": "Employee Teams", + "employees": "Employees", + "estimators": "Estimators", + "filehandlers": "Adjusters", + "imexpay": "ImEX Pay", + "insurancecos": "Insurance Companies", + "intakechecklist": "Intake Checklist", + "intellipay_cash_discount": "Please ensure that cash discounting has been enabled on your merchant account. Reach out to IntelliPay Support if you need assistance. ", + "jobstatuses": "Job Statuses", + "laborrates": "Labor Rates", + "licensing": "Licensing", + "md_parts_scan": "Parts Scan Rules", + "md_ro_guard": "RO Guard", + "md_tasks_presets": "Tasks Presets", + "md_to_emails": "Preset To Emails", + "md_to_emails_emails": "Emails", + "messagingpresets": "Messaging Presets", + "notemplatesavailable": "No templates available to add.", + "notespresets": "Notes Presets", + "orderstatuses": "Order Statuses", + "partslocations": "Parts Locations", + "partsscan": "Parts Scanning", + "printlater": "Print Later", + "qbo": "Use QuickBooks Online?", + "qbo_departmentid": "QBO Department ID", + "qbo_usa": "QBO USA Compatibility", + "rbac": "Role Based Access Control", + "responsibilitycenters": { + "costs": "Cost Centers", + "profits": "Profit Centers", + "sales_tax_codes": "Sales Tax Codes", + "tax_accounts": "Tax Accounts", + "title": "Responsibility Centers", + "ttl_adjustment": "Subtotal Adjustment Account", + "ttl_tax_adjustment": "Tax Adjustment Account" + }, + "roguard": { + "title": "RO Guard" + }, + "romepay": "Rome Pay", + "scheduling": "SMART Scheduling", + "scoreboardsetup": "Scoreboard Setup", + "shop_enabled_features": "Shop Enabled Features", + "shopinfo": "Shop Information", + "speedprint": "Speed Print Configuration", + "ssbuckets": "Job Size Definitions", + "systemsettings": "System Settings", + "task-presets": "Task Presets", + "workingdays": "Working Days" + }, + "operations": { + "contains": "Contains", + "ends_with": "Ends With", + "equals": "Equals", + "greater_than": "Greater Than", + "less_than": "Less Than", + "not_equals": "Not Equals", + "starts_with": "Starts With" + }, + "successes": { + "areyousure": "Are you sure you want to continue?", + "defaultviewcreated": "Default view created successfully.", + "save": "Shop configuration saved successfully. ", + "unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?" + }, + "tooltips": { + "md_parts_scan": { + "update_value_tooltip": "Some fields require coded values in order to function properly (e.g. labor and part types). Please reach out to support if you have any questions." + } + }, + "validation": { + "centermustexist": "The chosen responsibility center does not exist.", + "larsplit": "Refinish hour split must add up to 1.", + "useremailmustexist": "This email is not a valid user." + } + }, + "checklist": { + "actions": { + "printall": "Print All Documents" + }, + "errors": { + "complete": "Error during Job checklist completion. {{error}}", + "nochecklist": "No checklist has been configured for your shop. " + }, + "labels": { + "addtoproduction": "Add Job to Production?", + "allow_text_message": "Permission to Text?", + "checklist": "Checklist", + "printpack": "Job Intake Print Pack", + "removefromproduction": "Remove Job from Production?" + }, + "successes": { + "completed": "Job checklist completed." + } + }, + "contracts": { + "actions": { + "changerate": "Change Contract Rates", + "convertoro": "Convert to RO", + "decodelicense": "Decode License", + "find": "Find Contract", + "printcontract": "Print Contract", + "senddltoform": "Insert Driver's License Information" + }, + "errors": { + "fetchingjobinfo": "Error fetching Job Info. {{error}}.", + "returning": "Error returning Courtesy Car. {{error}}", + "saving": "Error saving Contract. {{error}}", + "selectjobandcar": "Please ensure both a car and job are selected." + }, + "fields": { + "actax": "A/C Tax", + "actualreturn": "Actual Return Date", + "agreementnumber": "Agreement Number", + "cc_cardholder": "Cardholder Name", + "cc_expiry": "Credit Card Expiry Date", + "cc_num": "Credit Card Number", + "cleanupcharge": "Clean Up Charge", + "coverage": "Coverage", + "dailyfreekm": "Daily Free Mileage", + "dailyrate": "Daily Rate", + "damage": "Existing Damage", + "damagewaiver": "Damage Waiver", + "driver": "Driver", + "driver_addr1": "Driver Address 1", + "driver_addr2": "Driver Address 2", + "driver_city": "Driver City", + "driver_dlexpiry": "Driver's License Expiration Date", + "driver_dlnumber": "Driver's License Number", + "driver_dlst": "Driver's License Province/State", + "driver_dob": "Driver's DOB", + "driver_fn": "Driver's First Name", + "driver_ln": "Driver's Last Name", + "driver_ph1": "Driver's Phone", + "driver_state": "Driver's Province/State ", + "driver_zip": "Driver's Postal/ZIP Code", + "excesskmrate": "Excess Mileage", + "federaltax": "Federal Taxes", + "fuelin": "Fuel In", + "fuelout": "Fuel Out", + "kmend": "Mileage End", + "kmstart": "Mileage Start", + "length": "Length", + "localtax": "Local Taxes", + "refuelcharge": "Refuel Charge (per liter/gallon)", + "scheduledreturn": "Scheduled Return", + "start": "Contract Start", + "statetax": "Provincial/State Taxes", + "status": "Status" + }, + "labels": { + "agreement": "Agreement {{agreement_num}} - {{status}}", + "availablecars": "Available Cars", + "cardueforservice": "The courtesy car is due for servicing.", + "convertform": { + "applycleanupcharge": "Apply cleanup charge?", + "refuelqty": "Refuel qty.?" + }, + "correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.", + "dateinpast": "Date is in the past.", + "dlexpirebeforereturn": "The driver's license expires before the car is expected to return. ", + "driverinformation": "Driver's Information", + "findcontract": "Find Contract", + "findermodal": "Contract Finder", + "insuranceexpired": "The courtesy car insurance expires before the car is expected to return.", + "noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.", + "populatefromjob": "Populate from Job", + "rates": "Contract Rates", + "time": "Time", + "vehicle": "Vehicle", + "waitingforscan": "Please scan driver's license barcode..." + }, + "status": { + "new": "New Contract", + "out": "Out", + "returned": "Returned" + }, + "successes": { + "saved": "Contract saved successfully. " + } + }, + "courtesycars": { + "actions": { + "new": "New Courtesy Car", + "return": "Return Car" + }, + "errors": { + "saving": "Error saving Courtesy Car. {{error}}" + }, + "fields": { + "color": "Color", + "dailycost": "Daily Cost to Rent", + "damage": "Damage", + "fleetnumber": "Fleet Number", + "fuel": "Fuel Level", + "insuranceexpires": "Insurance Expires On", + "leaseenddate": "Lease Ends On", + "make": "Make", + "mileage": "Mileage", + "model": "Model", + "nextservicedate": "Next Service Date", + "nextservicekm": "Next Service KMs", + "notes": "Notes", + "plate": "Plate Number", + "purchasedate": "Purchase Date", + "readiness": "Readiness", + "registrationexpires": "Registration Expires On", + "serviceenddate": "Usage End Date", + "servicestartdate": "Usage Start Date", + "status": "Status", + "vin": "VIN", + "year": "Year" + }, + "labels": { + "courtesycar": "Courtesy Car", + "fuel": { + "12": "1/2", + "14": "1/4", + "18": "1/8", + "34": "3/4", + "38": "3/8", + "58": "5/8", + "78": "7/8", + "empty": "Empty", + "full": "Full" + }, + "outwith": "Out With", + "return": "Return Courtesy Car", + "status": "Status", + "uniquefleet": "Enter a unique fleet number.", + "usage": "Usage", + "vehicle": "Vehicle Description" + }, + "readiness": { + "notready": "Not Ready", + "ready": "Ready" + }, + "status": { + "in": "Available", + "inservice": "Service/Maintenance", + "leasereturn": "Lease Returned", + "out": "Rented", + "sold": "Sold", + "unavailable": "Unavailable" + }, + "successes": { + "saved": "Courtesy Car saved successfully." + } + }, + "csi": { + "actions": { + "activate": "Activate" + }, + "errors": { + "creating": "Error creating survey {{message}}", + "notconfigured": "You do not have any current CSI Question Sets configured.", + "notfoundsubtitle": "We were unable to find a survey using the link you provided. Please ensure the URL is correct or reach out to your shop for more help.", + "notfoundtitle": "No survey found.", + "surveycompletesubtitle": "", + "surveycompletetitle": "" + }, + "fields": { + "completedon": "Completed On", + "created_at": "Created At", + "surveyid": "", + "validuntil": "" + }, + "labels": { + "copyright": "", + "greeting": "", + "intro": "", + "nologgedinuser": "Please log out of {{app}}", + "nologgedinuser_sub": "Users of {{app}} cannot complete CSI surveys while logged in. Please log out and try again.", + "noneselected": "No response selected.", + "title": "Customer Satisfaction Survey" + }, + "successes": { + "created": "CSI created successfully. ", + "submitted": "Your responses have been submitted successfully.", + "submittedsub": "Your input is highly appreciated." + } + }, + "dashboard": { + "actions": { + "addcomponent": "Add Component" + }, + "errors": { + "refreshrequired": "You must refresh the dashboard data to see this component.", + "updatinglayout": "Error saving updated layout {{message}}" + }, + "labels": { + "bodyhrs": "Body Hrs", + "dollarsinproduction": "Dollars in Production", + "phone": "Phone", + "prodhrs": "Production Hrs", + "refhrs": "Refinish Hrs" + }, + "titles": { + "joblifecycle": "Job Life Cycles", + "labhours": "Total Body Hours", + "larhours": "Total Refinish Hours", + "monthlyemployeeefficiency": "Monthly Employee Efficiency", + "monthlyjobcosting": "Monthly Job Costing ", + "monthlylaborsales": "Monthly Labor Sales", + "monthlypartssales": "Monthly Parts Sales", + "monthlyrevenuegraph": "Monthly Revenue Graph", + "prodhrssummary": "Production Hours Summary", + "productiondollars": "Total Dollars in Production", + "productionhours": "Total Hours in Production", + "projectedmonthlysales": "Projected Monthly Sales", + "scheduledindate": "Scheduled In Today: {{date}}", + "scheduledintoday": "Scheduled In Today", + "scheduledoutdate": "Scheduled Out Today: {{date}}", + "scheduledouttoday": "Scheduled Out Today", + "tasks": "Tasks" + } + }, + "dms": { + "errors": { + "alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export." + }, + "labels": { + "refreshallocations": "Refresh to see DMS Allocataions." + } + }, + "documents": { + "actions": { + "delete": "Delete Selected Documents", + "download": "Download Selected Images", + "reassign": "Reassign to another Job", + "selectallimages": "Select All Images", + "selectallotherdocuments": "Select All Other Documents" + }, + "errors": { + "deletes3": "Error deleting document from storage. ", + "deleting": "Error deleting documents {{error}}", + "deleting_cloudinary": "Error deleting document from storage. {{message}}", + "getpresignurl": "Error obtaining presigned URL for document. {{message}}", + "insert": "Unable to upload file. {{message}}", + "nodocuments": "There are no documents.", + "updating": "Error updating document. {{error}}" + }, + "labels": { + "confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.", + "doctype": "Document Type", + "dragtoupload": "Click or drag files to this area to upload", + "newjobid": "Assign to Job", + "openinexplorer": "Open in Explorer", + "optimizedimage": "The below image is optimized. Click on the picture below to open in a new window and view it full size, or open it in explorer.", + "reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ", + "reassign_limitexceeded_title": "Unable to reassign document(s)", + "storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.", + "storageexceeded_title": "Storage Limit Exceeded", + "upload": "Upload", + "upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ", + "upload_limitexceeded_title": "Unable to upload document(s)", + "uploading": "Uploading...", + "usage": "of Job storage used. ({{used}} / {{total}})" + }, + "successes": { + "delete": "Document(s) deleted successfully.", + "edituploaded": "Edited document uploaded successfully. Please close this window and refresh the documents list.", + "insert": "Uploaded document successfully. ", + "updated": "Document updated successfully. " + } + }, + "emails": { + "errors": { + "notsent": "Email not sent. Error encountered while sending {{message}}" + }, + "fields": { + "cc": "CC", + "from": "From", + "subject": "Subject", + "to": "To" + }, + "labels": { + "attachments": "Attachments", + "documents": "Documents", + "emailpreview": "Email Preview", + "generatingemail": "Generating email...", + "pdfcopywillbeattached": "A PDF copy of this email will be attached when it is sent.", + "preview": "Email Preview" + }, + "successes": { + "sent": "Email sent successfully." + } + }, + "employee_teams": { + "actions": { + "new": "New Team", + "newmember": "New Team Member" + }, + "fields": { + "active": "Active", + "employeeid": "Employee", + "max_load": "Max Load", + "name": "Team Name", + "percentage": "Percent" + } + }, + "employees": { + "actions": { + "addvacation": "Add Vacation", + "new": "New Employee", + "newrate": "New Rate" + }, + "errors": { + "delete": "Error encountered while deleting employee. {{message}}", + "save": "Error encountered saving employee. {{message}}", + "validation": "Please check all fields.", + "validationtitle": "Unable to save employee." + }, + "fields": { + "active": "Active?", + "base_rate": "Base Rate", + "cost_center": "Cost Center", + "employee_number": "Employee Number", + "external_id": "External Employee ID", + "first_name": "First Name", + "flat_rate": "Flat Rate (Disabled is Straight Time)", + "hire_date": "Hire Date", + "last_name": "Last Name", + "pin": "Tech Console PIN", + "rate": "Rate", + "termination_date": "Termination Date", + "user_email": "User Email", + "vacation": { + "end": "Vacation End", + "length": "Vacation Length", + "start": "Vacation Start" + } + }, + "labels": { + "actions": "Actions", + "active": "Active", + "endmustbeafterstart": "End date must be after start date.", + "flat_rate": "Flat Rate", + "inactive": "Inactive", + "name": "Name", + "rate_type": "Rate Type", + "status": "Status", + "straight_time": "Straight Time" + }, + "successes": { + "delete": "Employee deleted successfully.", + "save": "Employee saved successfully.", + "vacationadded": "Employee vacation added." + }, + "validation": { + "unique_employee_number": "You must enter a unique employee number." + } + }, + "eula": { + "buttons": { + "accept": "Accept EULA" + }, + "content": { + "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." + }, + "errors": { + "acceptance": { + "description": "Something went wrong while accepting the EULA. Please try again.", + "message": "Eula Acceptance Error" + } + }, + "labels": { + "accepted_terms": "I accept the terms and conditions of this agreement.", + "address": "Address", + "business_name": "Legal Business Name", + "date_accepted": "Date Accepted", + "first_name": "First Name", + "last_name": "Last Name", + "phone_number": "Phone Number" + }, + "messages": { + "accepted_terms": "Please accept the terms and conditions of this agreement.", + "business_name": "Please enter your legal business name.", + "date_accepted": "Please enter Today's Date.", + "first_name": "Please enter your first name.", + "last_name": "Please enter your last name.", + "phone_number": "Please enter your phone number." + }, + "titles": { + "modal": "Terms and Conditions", + "upper_card": "Acknowledgement" + } + }, + "exportlogs": { + "fields": { + "createdat": "Created At" + }, + "labels": { + "attempts": "Export Attempts", + "priorsuccesfulexport": "This record has previously been exported successfully. Please make sure it has already been deleted in the target system." + } + }, + "general": { + "actions": { + "add": "Add", + "autoupdate": "{{app}} will automatically update in {{time}} seconds. Please save all changes.", + "calculate": "Calculate", + "cancel": "Cancel", + "clear": "Clear", + "close": "Close", + "copied": "Copied!", + "copylink": "Copy Link", + "create": "Create", + "defaults": "Defaults", + "delay": "Delay Update (5 mins)", + "delete": "Delete", + "deleteall": "Delete All", + "deselectall": "Deselect All", + "download": "Download", + "edit": "Edit", + "login": "Login", + "next": "Next", + "ok": "Ok", + "previous": "Previous", + "print": "Print", + "refresh": "Refresh", + "remove": "Remove", + "remove_alert": "Are you sure you want to dismiss the alert?", + "reset": "Reset your changes.", + "resetpassword": "Reset Password", + "save": "Save", + "saveandnew": "Save and New", + "saveas": "Save As", + "selectall": "Select All", + "send": "Send", + "sendbysms": "Send by SMS", + "senderrortosupport": "Send Error to Support", + "sharetoteams": "Share to Teams", + "submit": "Submit", + "tryagain": "Try Again", + "view": "View", + "viewreleasenotes": "See What's Changed" + }, + "errors": { + "fcm": "You must allow notification permissions to have real time messaging. Click to try again.", + "notfound": "No record was found.", + "sizelimit": "The selected items exceed the size limit." + }, + "itemtypes": { + "contract": "CC Contract", + "courtesycar": "Courtesy Car", + "job": "Job", + "owner": "Owner", + "vehicle": "Vehicle" + }, + "labels": { + "actions": "Actions", + "areyousure": "Are you sure?", + "barcode": "Barcode", + "cancel": "Are you sure you want to cancel? Your changes will not be saved.", + "clear": "Clear", + "confirmpassword": "Confirm Password", + "created_at": "Created At", + "date": "Select Date", + "datetime": "Select Date & Time", + "email": "Email", + "errors": "Errors", + "excel": "Excel", + "exceptiontitle": "An error has occurred.", + "friday": "Friday", + "globalsearch": "Global Search", + "help": "Help", + "hours": "hrs", + "in": "In", + "instanceconflictext": "Your {{app}} account can only be used on one device at any given time. Refresh your session to take control.", + "instanceconflictitle": "Your account is being used elsewhere.", + "item": "Item", + "label": "Label", + "loading": "Loading...", + "loadingapp": "Loading {{app}}", + "loadingshop": "Loading shop data...", + "loggingin": "Authorizing...", + "markedexported": "Manually marked as exported.", + "media": "Media", + "message": "Message", + "monday": "Monday", + "na": "N/A", + "newpassword": "New Password", + "no": "No", + "nointernet": "It looks like you're not connected to the internet.", + "nointernet_sub": "Please check your connection and try again. ", + "none": "None", + "out": "Out", + "password": "Password", + "passwordresetsuccess": "A password reset link has been sent to you.", + "passwordresetsuccess_sub": "You should receive this email in the next few minutes. Please check your email including any junk or spam folders. ", + "passwordresetvalidatesuccess": "Password successfully reset. ", + "passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ", + "passwordsdonotmatch": "The passwords you have entered do not match.", + "print": "Print", + "refresh": "Refresh", + "reports": "Reports", + "required": "Required", + "saturday": "Saturday", + "search": "Search...", + "searchresults": "Results for {{search}}", + "selectdate": "Select date...", + "sendagain": "Send Again", + "sendby": "Send By", + "signin": "Sign In", + "sms": "SMS", + "status": "Status", + "sub_status": { + "expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. " + }, + "successful": "Successful", + "sunday": "Sunday", + "text": "Text", + "thursday": "Thursday", + "time": "Select Time", + "total": "Total", + "totals": "Totals", + "tuesday": "Tuesday", + "tvmode": "TV Mode", + "unknown": "Unknown", + "unsavedchanges": "Unsaved changes.", + "username": "Username", + "view": "View", + "wednesday": "Wednesday", + "yes": "Yes" + }, + "languages": { + "english": "English", + "french": "French", + "spanish": "Spanish" + }, + "messages": { + "exception": "{{app}} has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.", + "newversionmessage": "Click refresh below to update to the latest available version of {{app}}. Please make sure all other tabs and windows are closed.", + "newversiontitle": "New version of {{app}} Available", + "noacctfilepath": "There is no accounting file path set. You will not be able to export any items.", + "nofeatureaccess": "You do not have access to this feature of {{app}}. Please contact support to request a license for this feature.", + "noshop": "You do not have access to any shops. Please reach out to your shop manager or technical support. ", + "notfoundsub": "Please make sure that you have access to the data or that the link is correct.", + "notfoundtitle": "We couldn't find what you're looking for...", + "partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.", + "rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.", + "unsavedchanges": "You have unsaved changes.", + "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?" + }, + "validation": { + "dateRangeExceeded": "The date range has been exceeded.", + "invalidemail": "Please enter a valid email.", + "invalidphone": "Please enter a valid phone number.", + "required": "{{label}} is required." + } + }, + "help": { + "actions": { + "connect": "Connect" + }, + "labels": { + "codeplacholder": "6 digit PIN code", + "rescuedesc": "Enter the 6 digit code provided by {{app}} Support below and click connect.", + "rescuetitle": "Rescue Me!" + } + }, + "intake": { + "labels": { + "printpack": "Intake Print Pack" + } + }, + "inventory": { + "actions": { + "addtoinventory": "Add to Inventory", + "addtoro": "Add to RO", + "consumefrominventory": "Consume from Inventory?", + "edit": "Edit Inventory LIne", + "new": "New Inventory Line" + }, + "errors": { + "inserting": "Error inserting inventory item. {{error}}" + }, + "fields": { + "comment": "Comment", + "manualinvoicenumber": "Invoice Number", + "manualvendor": "Vendor" + }, + "labels": { + "consumedbyjob": "Consumed by Job", + "deleteconfirm": "Are you sure you want to delete this from inventory? The associated bill will not be modified or deleted. ", + "frombillinvoicenumber": "Original Bill Invoice Number", + "fromvendor": "Original Bill Vendor", + "inventory": "Inventory", + "showall": "Show All Inventory", + "showavailable": "Show Only Available Inventory" + }, + "successes": { + "deleted": "Inventory lined deleted.", + "inserted": "Added line to inventory.", + "updated": "Inventory line updated." + } + }, + "job_lifecycle": { + "columns": { + "average_human_readable": "Average Human Readable", + "average_value": "Average Value", + "duration": "Duration", + "end": "End", + "human_readable": "Human Readable", + "percentage": "Percentage", + "relative_end": "Relative End", + "relative_start": "Relative Start", + "start": "Start", + "status": "Status", + "status_count": "In Status", + "value": "Value" + }, + "content": { + "calculated_based_on": "Calculated based on", + "current_status_accumulated_time": "Current Status Accumulated Time", + "data_unavailable": " There is currently no Lifecycle data for this Job.", + "jobs_in_since": "Jobs in since", + "legend_title": "Legend", + "loading": "Loading Job Timelines....", + "not_available": "N/A", + "previous_status_accumulated_time": "Previous Status Accumulated Time", + "title": "Job Lifecycle Component", + "title_durations": "Historical Status Durations", + "title_loading": "Loading", + "title_transitions": "Transitions" + }, + "errors": { + "fetch": "Error getting Job Lifecycle Data" + }, + "titles": { + "dashboard": "Job Lifecycle", + "top_durations": "Top Durations" + } + }, + "job_payments": { + "buttons": { + "create_short_link": "Generate Short Link", + "goback": "Go Back", + "proceedtopayment": "Proceed to Payment", + "refundpayment": "Refund Payment" + }, + "notifications": { + "error": { + "description": "Please try again. Make sure the refund amount does not exceeds the payment amount.", + "openingip": "Error connecting to IntelliPay service.", + "title": "Error placing refund" + } + }, + "titles": { + "amount": "Amount", + "dateOfPayment": "Date of Payment", + "descriptions": "Payment Details", + "hint": "Hint", + "payer": "Payer", + "payername": "Payer Name", + "paymentid": "Payment Reference ID", + "paymentnum": "Payment Number", + "paymenttype": "Payment Type", + "refundamount": "Refund Amount", + "transactionid": "Transaction ID" + } + }, + "joblines": { + "actions": { + "assign_team": "Assign Team", + "converttolabor": "Convert amount to Labor.", + "dispatchparts": "Dispatch Parts ({{count}})", + "new": "New Line" + }, + "errors": { + "creating": "Error encountered while creating job line. {{message}}", + "updating": "Error encountered updating job line. {{message}}" + }, + "fields": { + "act_price": "Retail Price", + "act_price_before_ppc": "Original Part Price", + "adjustment": "Adjustment", + "ah_detail_line": "Mark as Detail Labor Line (Autohouse Only)", + "alt_partno": "Alt Part #", + "amount": "Amount", + "assigned_team": "Team", + "assigned_team_name": "Team {{name}}", + "create_ppc": "Create PPC?", + "db_price": "List Price", + "include_in_part_cnt": "Include in Parts Status Count", + "lbr_types": { + "LA1": "LA1", + "LA2": "LA2", + "LA3": "LA3", + "LA4": "LA4", + "LAA": "Aluminum", + "LAB": "Body", + "LAD": "Diagnostic", + "LAE": "Electrical", + "LAF": "Frame", + "LAG": "Glass", + "LAM": "Mechanical", + "LAR": "Refinish", + "LAS": "Structural", + "LAU": "User Defined" + }, + "line_desc": "Line Desc.", + "line_ind": "S#", + "line_no": "Line #", + "location": "Location", + "mod_lb_hrs": "Hrs", + "mod_lbr_ty": "Labor Type", + "notes": "Notes", + "oem_partno": "OEM Part #", + "op_code_desc": "Op Code Description", + "part_qty": "Qty.", + "part_type": "Part Type", + "part_types": { + "CCC": "CC Cleaning", + "CCD": "CC Damage Waiver", + "CCDR": "CC Daily Rate", + "CCF": "CC Refuel", + "CCM": "CC Mileage", + "PAA": "Aftermarket", + "PAC": "Rechromed", + "PAE": "Existing", + "PAG": "Glass", + "PAL": "LKQ", + "PAM": "Remanufactured", + "PAN": "New/OEM", + "PAO": "Other", + "PAP": "OEM Partial", + "PAR": "Recored", + "PAS": "Sublet", + "PASL": "Sublet (L)" + }, + "profitcenter_labor": "Profit Center: Labor", + "profitcenter_part": "Profit Center: Part", + "prt_dsmk_m": "Line Discount/Markup $", + "prt_dsmk_p": "Line Discount/Markup %", + "status": "Status", + "tax_part": "Tax Part", + "total": "Total", + "unq_seq": "Seq #" + }, + "labels": { + "adjustmenttobeadded": "Adjustment to be added: {{adjustment}}", + "billref": "Latest Bill", + "convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.", + "edit": "Edit Line", + "ioucreated": "IOU", + "new": "New Line", + "nostatus": "No Status", + "presets": "Jobline Presets" + }, + "successes": { + "created": "Job line created successfully.", + "saved": "Job line saved.", + "updated": "Job line updated successfully." + }, + "validations": { + "ahdetailonlyonuserdefinedtypes": "Detail line indicator can only be set for LA1, LA2, LA3, LA4, and LAU labor types.", + "hrsrequirediflbrtyp": "Labor hours are required if a labor type is selected. Clear the labor type if there are no labor hours.", + "requiredifparttype": "Required if a part type has been specified.", + "zeropriceexistingpart": "This line cannot have any price since it uses an existing part." + } + }, + "jobs": { + "actions": { + "addDocuments": "Add Job Documents", + "addNote": "Add Note", + "addtopartsqueue": "Add to Parts Queue", + "addtoproduction": "Add to Production", + "addtoscoreboard": "Add to Scoreboard", + "allocate": "Allocate", + "autoallocate": "Auto Allocate", + "changefilehandler": "Change Adjuster", + "changelaborrate": "Change Labor Rate", + "changestatus": "Change Status", + "changestimator": "Change Estimator", + "convert": "Convert", + "createiou": "Create IOU", + "deliver": "Deliver", + "deliver_quick": "Quick Deliver", + "dms": { + "addpayer": "Add Payer", + "createnewcustomer": "Create New Customer", + "findmakemodelcode": "Find Make/Model Code", + "getmakes": "Get Makes", + "labels": { + "refreshallocations": "Refresh this component to see the DMS allocations." + }, + "post": "Post", + "refetchmakesmodels": "Refetch Make and Model Codes", + "usegeneric": "Use Generic Customer", + "useselected": "Use Selected Customer" + }, + "dmsautoallocate": "DMS Auto Allocate", + "export": "Export", + "exportcustdata": "Export Customer Data", + "exportselected": "Export Selected", + "filterpartsonly": "Filter Parts Only", + "generatecsi": "Generate CSI & Copy Link", + "gotojob": "Go to Job", + "intake": "Intake", + "intake_quick": "Quick Intake", + "manualnew": "Create New Job Manually", + "mark": "Mark", + "markasexported": "Mark as Exported", + "markpstexempt": "Mark Job PST Exempt", + "markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.", + "postbills": "Post Bills", + "printCenter": "Print Center", + "recalculate": "Recalculate", + "reconcile": "Reconcile", + "removefromproduction": "Remove from Production", + "schedule": "Schedule", + "sendcsi": "Send CSI", + "sendpartspricechange": "Send Parts Price Change", + "sendtodms": "Send to DMS", + "sync": "Sync", + "taxprofileoverride": "Override Tax Profile with Shop Configuration", + "taxprofileoverride_confirm": "Are you sure you want to override the tax profile information? This cannot be undone without re-importing the job. ", + "uninvoice": "Uninvoice", + "unvoid": "Unvoid Job", + "viewchecklist": "View Checklists", + "viewdetail": "View Details" + }, + "errors": { + "addingtoproduction": "Error adding to production. {{error}}", + "cannotintake": "Intake cannot be completed for this Job. It has either already been completed or the job is already here.", + "closing": "Error closing Job. {{error}}", + "creating": "Error encountered while creating job. {{error}}", + "deleted": "Error deleting Job. {{error}}", + "exporting": "Error exporting Job. {{error}}", + "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.", + "invoicing": "Error invoicing Job. {{error}}", + "noaccess": "This Job does not exist or you do not have access to it.", + "nodamage": "No damage points on estimate.", + "nodates": "No dates specified for this Job.", + "nofinancial": "No financial data has been calculated yet for this job. Please save it again.", + "nojobselected": "No Job is selected.", + "noowner": "No owner associated.", + "novehicle": "No vehicle associated.", + "partspricechange": "Error sending parts price change. {{error}}.", + "saving": "Error encountered while saving record.", + "scanimport": "Error importing Job. {{message}}", + "totalscalc": "Error while calculating new Job totals.", + "updating": "Error while updating Job(s). {{error}}", + "validation": "Please ensure all fields are entered correctly.", + "validationtitle": "Validation Error", + "voiding": "Error voiding Job. {{error}}" + }, + "fields": { + "active_tasks": "Active Tasks", + "actual_completion": "Actual Completion", + "actual_delivery": "Actual Delivery", + "actual_in": "Actual In", + "adjustment_bottom_line": "Adjustments", + "adjustmenthours": "Adjustment Hours", + "alt_transport": "Alt. Trans.", + "area_of_damage_impact": { + "10": "Left Front Side", + "11": "Left Front Corner", + "12": "Front", + "13": "Rollover", + "14": "Unknown", + "15": "Total Loss", + "16": "Non-collision", + "25": "Hood", + "26": "Deck-lid", + "27": "Roof", + "28": "Undercarriage", + "34": "All Over", + "01": "Right Front Corner", + "02": "Right Front Side", + "03": "Right Side", + "04": "Right Rear Side", + "05": "Right Rear Corner", + "06": "Rear", + "07": "Left Rear Corner", + "08": "Left Rear Side", + "09": "Left Side" + }, + "auto_add_ats": "Automatically Add/Update ATS", + "ca_bc_pvrt": "PVRT", + "ca_customer_gst": "Customer Portion of GST", + "ca_gst_registrant": "GST Registrant", + "category": "Category", + "ccc": "CC Cleaning", + "ccd": "CC Damage Waiver", + "ccdr": "CC Daily Rate", + "ccf": "CC Refuel", + "ccm": "CC Mileage", + "cieca_id": "CIECA ID", + "cieca_pfl": { + "lbr_adjp": "Labor Adjustment", + "lbr_tax_in": "Tax Labor Indicator", + "lbr_taxp": "Labor Tax Rate", + "lbr_tx_in1": "Tax 1 Indicator", + "lbr_tx_in2": "Tax 2 Indicator", + "lbr_tx_in3": "Tax 3 Indicator", + "lbr_tx_in4": "Tax 4 Indicator", + "lbr_tx_in5": "Tax 5 Indicator" + }, + "cieca_pfo": { + "stor_t_in1": "Storage Tax 1 Indicator", + "stor_t_in2": "Storage Tax 2 Indicator", + "stor_t_in3": "Storage Tax 3 Indicator", + "stor_t_in4": "Storage Tax 4 Indicator", + "stor_t_in5": "Storage Tax 5 Indicator", + "tow_t_in1": "Tow Tax 1 Indicator", + "tow_t_in2": "Tow Tax 2 Indicator", + "tow_t_in3": "Tow Tax 3 Indicator", + "tow_t_in4": "Tow Tax 4 Indicator", + "tow_t_in5": "Tow Tax 5 Indicator" + }, + "claim_total": "Claim Total", + "class": "Class", + "clm_no": "Claim #", + "clm_total": "Claim Total", + "comment": "Comment", + "customerowing": "Customer Owing", + "date_estimated": "Date Estimated", + "date_exported": "Exported", + "date_invoiced": "Invoiced", + "date_last_contacted": "Last Contacted Date", + "date_lost_sale": "Lost Sale", + "date_next_contact": "Next Contact Date", + "date_open": "Open", + "date_rentalresp": "Shop Rental Responsibility Start", + "date_repairstarted": "Repairs Started", + "date_scheduled": "Scheduled", + "date_towin": "Towed In", + "date_void": "Void", + "ded_amt": "Deductible", + "ded_note": "Deductible Note", + "ded_status": "Deductible Status", + "depreciation_taxes": "Betterment/Depreciation/Taxes", + "dms": { + "address": "Customer Address", + "amount": "Amount", + "center": "Center", + "control_type": { + "account_number": "Account Number" + }, + "cost": "Cost", + "cost_dms_acctnumber": "Cost DMS Acct #", + "dms_make": "DMS Make", + "dms_model": "DMS Model", + "dms_model_override": "Override DMS Make/Model", + "dms_unsold": "New, Unsold Vehicle", + "dms_wip_acctnumber": "Cost WIP DMS Acct #", + "id": "DMS ID", + "inservicedate": "In Service Date", + "journal": "Journal #", + "lines": "Posting Lines", + "name1": "Customer Name", + "payer": { + "amount": "Amount", + "control_type": "Control Type", + "controlnumber": "Control Number", + "dms_acctnumber": "DMS Account #", + "name": "Payer Name" + }, + "sale": "Sale", + "sale_dms_acctnumber": "Sale DMS Acct #", + "story": "Story", + "vinowner": "VIN Owner" + }, + "dms_allocation": "DMS Allocation", + "driveable": "Driveable", + "employee_body": "Body", + "employee_csr": "Customer Service Rep.", + "employee_csr_writer": "Writer", + "employee_prep": "Prep", + "employee_refinish": "Refinish", + "est_addr1": "Estimator Address", + "est_co_nm": "Estimator Company", + "est_ct_fn": "Estimator First Name", + "est_ct_ln": "Estimator Last Name", + "est_ea": "Estimator Email", + "est_ph1": "Estimator Phone #", + "federal_tax_payable": "Federal Tax Payable", + "federal_tax_rate": "Federal Tax Rate", + "ins_addr1": "Insurance Co. Address", + "ins_city": "Insurance Co. City", + "ins_co_id": "Insurance Co. ID", + "ins_co_nm": "Insurance Company Name", + "ins_co_nm_short": "Ins. Co.", + "ins_ct_fn": "Adjuster First Name", + "ins_ct_ln": "Adjuster Last Name", + "ins_ea": "Adjuster Email", + "ins_ph1": "Adjuster Phone #", + "intake": { + "label": "Label", + "max": "Maximum", + "min": "Minimum", + "name": "Name", + "required": "Required?", + "type": "Type" + }, + "invoice_final_note": "Note to Display on Final Invoice", + "kmin": "Mileage In", + "kmout": "Mileage Out", + "la1": "LA1", + "la2": "LA2", + "la3": "LA3", + "la4": "LA4", + "laa": "Aluminum ", + "lab": "Body", + "labor_rate_desc": "Labor Rate Name", + "lad": "Diagnostic", + "lae": "Electrical", + "laf": "Frame", + "lag": "Glass", + "lam": "Mechanical", + "lar": "Refinish", + "las": "Structural", + "lau": "User Defined", + "local_tax_rate": "Local Tax Rate", + "loss_date": "Loss Date", + "loss_desc": "Loss Description", + "loss_of_use": "Loss of Use", + "lost_sale_reason": "Lost Sale Reason", + "ma2s": "2 Stage Paint", + "ma3s": "3 Stage Pain", + "mabl": "MABL?", + "macs": "MACS?", + "mahw": "Hazardous Waste", + "mapa": "Paint Materials", + "mash": "Shop Materials", + "matd": "Tire Disposal", + "materials": { + "MAPA": "Paint Materials", + "MASH": "Shop Materials", + "cal_maxdlr": "Threshhold", + "cal_opcode": "OP Codes", + "mat_adjp": "Material Adjustment", + "mat_taxp": "Material Tax Rate", + "mat_tx_in1": "Tax 1 Indicator", + "mat_tx_in2": "Tax 2 Indicator", + "mat_tx_in3": "Tax 3 Indicator", + "mat_tx_in4": "Tax 4 Indicator", + "mat_tx_in5": "Tax 5 Indicator", + "materials": "Profile - Materials", + "tax_ind": "Tax Indicator" + }, + "other_amount_payable": "Other Amount Payable", + "owner": "Owner", + "owner_owing": "Cust. Owes", + "ownr_ea": "Email", + "ownr_ph1": "Phone 1", + "ownr_ph2": "Phone 2", + "paa": "Aftermarket", + "pac": "Rechromed", + "pae": "Existing", + "pag": "Glass", + "pal": "LKQ", + "pam": "Remanufactured", + "pan": "OEM/New", + "pao": "Other", + "pap": "OEM Partial", + "par": "Re-cored", + "parts_tax_rates": { + "prt_discp": "Discount %", + "prt_mktyp": "Markup Type", + "prt_mkupp": "Markup %", + "prt_tax_in": "Tax Indicator", + "prt_tax_rt": "Part Tax Rate", + "prt_tx_in1": "Tax 1 Indicator", + "prt_tx_in2": "Tax 2 Indicator", + "prt_tx_in3": "Tax 3 Indicator", + "prt_tx_in4": "Tax 4 Indicator", + "prt_tx_in5": "Tax 5 Indicator", + "prt_tx_ty1": "Parts Tax Type 1", + "prt_type": "Part Type" + }, + "partsstatus": "Parts Status", + "pas": "Sublet", + "pay_date": "Pay Date", + "phoneshort": "PH", + "po_number": "PO Number", + "policy_no": "Policy #", + "ponumber": "PO Number", + "production_vars": { + "note": "Production Note" + }, + "qb_multiple_payers": { + "amount": "Amount", + "name": "Name" + }, + "queued_for_parts": "Queued for Parts", + "rate_ats": "ATS Rate", + "rate_la1": "LA1", + "rate_la2": "LA2", + "rate_la3": "LA3", + "rate_la4": "LA4", + "rate_laa": "Aluminum", + "rate_lab": "Body", + "rate_lad": "Diagnostic", + "rate_lae": "Electrical", + "rate_laf": "Frame", + "rate_lag": "Glass", + "rate_lam": "Mechanical", + "rate_lar": "Refinish", + "rate_las": "Structural", + "rate_lau": "User Defined", + "rate_ma2s": "2 Stage Paint", + "rate_ma3s": "3 Stage Paint", + "rate_mabl": "MABL??", + "rate_macs": "MACS??", + "rate_mahw": "Hazardous Waste", + "rate_mapa": "Paint Materials", + "rate_mash": "Shop Material", + "rate_matd": "Tire Disposal", + "referral_source_extra": "Other Referral Source", + "referral_source_other": "", + "referralsource": "Referral Source", + "regie_number": "Registration #", + "repairtotal": "Repair Total", + "ro_number": "RO #", + "scheduled_completion": "Scheduled Completion", + "scheduled_delivery": "Scheduled Delivery", + "scheduled_in": "Scheduled In", + "selling_dealer": "Selling Dealer", + "selling_dealer_contact": "Selling Dealer Contact", + "servicecar": "Service Car", + "servicing_dealer": "Servicing Dealer", + "servicing_dealer_contact": "Servicing Dealer Contact", + "special_coverage_policy": "Special Coverage Policy", + "specialcoveragepolicy": "Special Coverage Policy", + "state_tax_rate": "State Tax Rate", + "status": "Job Status", + "storage_payable": "Storage", + "tax_lbr_rt": "Labor Tax Rate", + "tax_levies_rt": "Levies Tax Rate", + "tax_paint_mat_rt": "Paint Material Tax Rate", + "tax_registration_number": "Tax Registration Number", + "tax_shop_mat_rt": "Shop Material Tax Rate", + "tax_str_rt": "Storage Tax Rate", + "tax_sub_rt": "Sublet Tax Rate", + "tax_tow_rt": "Towing Tax Rate", + "tlos_ind": "Total Loss Indicator", + "towin": "Tow In", + "towing_payable": "Towing Payable", + "unitnumber": "Unit #", + "updated_at": "Updated At", + "uploaded_by": "Uploaded By", + "vehicle": "Vehicle" + }, + "forms": { + "admindates": "Administrative Dates", + "appraiserinfo": "Estimator Info", + "claiminfo": "Claim Information", + "estdates": "Estimate Dates", + "laborrates": "Labor Rates", + "lossinfo": "Loss Information", + "other": "Other", + "repairdates": "Repair Dates", + "scheddates": "Schedule Dates" + }, + "labels": { + "accountsreceivable": "Accounts Receivable", + "act_price_ppc": "New Part Price", + "actual_completion_inferred": "$t(jobs.fields.actual_completion) inferred using $t(jobs.fields.scheduled_completion).", + "actual_delivery_inferred": "$t(jobs.fields.actual_delivery) inferred using $t(jobs.fields.scheduled_delivery).", + "actual_in_inferred": "$t(jobs.fields.actual_in) inferred using $t(jobs.fields.scheduled_in).", + "additionalpayeroverallocation": "You have allocated more than the sale of the Job to additional payers.", + "additionaltotal": "Additional Total", + "adjustmentrate": "Adjustment Rate", + "adjustments": "Adjustments", + "adminwarning": "Use the functionality on this page at your own risk. You are responsible for any and all changes to your data.", + "allocations": "Allocations", + "alreadyaddedtoscoreboard": "Job has already been added to scoreboard. Saving will update the previous entry.", + "alreadyclosed": "This Job has already been closed.", + "appointmentconfirmation": "Send confirmation to customer?", + "associationwarning": "Any changes to associations will require updating the data from the new parent record to the Job.", + "audit": "Audit Trail", + "available": "Available", + "availablejobs": "Available Jobs", + "ca_bc_pvrt": { + "days": "Days", + "rate": "PVRT Rate" + }, + "ca_gst_all_if_null": "If the Job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ", + "calc_repair_days": "Calculated Repair Days", + "calc_repair_days_tt": "This is the approximate number of days required to complete the repair according to the target touch time in your shop configuration (current set to {{target_touchtime}}).", + "calc_scheuled_completion": "Calculate Scheduled Completion", + "cards": { + "customer": "Customer Information", + "damage": "Area of Damage", + "dates": "Dates", + "documents": "Recent Documents", + "estimator": "Estimator", + "filehandler": "Adjuster", + "insurance": "Insurance Details", + "more": "More", + "notes": "Notes", + "parts": "Parts", + "totals": "Totals", + "vehicle": "Vehicle" + }, + "changeclass": "Changing the Job's class can have fundamental impacts to already exported accounting items. Are you sure you want to do this?", + "checklistcompletedby": "Checklist completed by {{by}} at {{at}}", + "checklistdocuments": "Checklist Documents", + "checklists": "Checklists", + "cieca_pfl": "Profile - Labor", + "cieca_pfo": "Profile - Other", + "cieca_pft": "Profile - Taxes", + "closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.", + "closejob": "Close Job {{ro_number}}", + "closingperiod": "This Invoice Date is outside of the Closing Period.", + "contracts": "CC Contracts", + "convertedtolabor": "Labor Line Adjustments", + "cost": "Cost", + "cost_Additional": "Cost - Additional", + "cost_labor": "Cost - Labor", + "cost_parts": "Cost - Parts", + "cost_sublet": "Cost - Sublet", + "costs": "Costs", + "create": { + "jobinfo": "Job Info", + "newowner": "Create a new Owner instead. ", + "newvehicle": "Create a new Vehicle Instead", + "novehicle": "No vehicle (only for ROs to track parts/labor only work).", + "ownerinfo": "Owner Info", + "vehicleinfo": "Vehicle Info" + }, + "createiouwarning": "Are you sure you want to create an IOU for these lines? A new RO will be created based on those lines for this customer.", + "creating_new_job": "Creating new Job...", + "deductible": { + "stands": "Stands", + "waived": "Waived" + }, + "deleteconfirm": "Are you sure you want to delete this Job? This cannot be undone. ", + "deletedelivery": "Delete Delivery Checklist", + "deleteintake": "Delete Intake Checklist", + "deliverchecklist": "Deliver Checklist", + "difference": "Difference", + "diskscan": "Scan Disk for Estimates", + "dms": { + "apexported": "AP export completed. See logs for details.", + "damageto": "Damage to $t(jobs.fields.area_of_damage_impact.{{area_of_damage}}).", + "defaultstory": "B/S RO: {{ro_number}}. Owner: {{ownr_nm}}. Insurance Co: {{ins_co_nm}}. Claim/PO #: {{clm_po}}", + "disablebillwip": "Cost and WIP for bills has been ignored per shop configuration.", + "invoicedatefuture": "Invoice date must be today or in the future for CDK posting.", + "kmoutnotgreaterthankmin": "Mileage out must be greater than mileage in.", + "logs": "Logs", + "notallocated": "Not Allocated", + "postingform": "Posting Form", + "totalallocated": "Total Amount Allocated" + }, + "documents": "Documents", + "documents-images": "Images", + "documents-other": "Other Documents", + "duplicateconfirm": "Are you sure you want to duplicate this Job? Some elements of this Job will not be duplicated.", + "emailaudit": "Email Audit Trail", + "employeeassignments": "Employee Assignments", + "estimatelines": "Estimate Lines", + "estimator": "Estimator", + "existing_jobs": "Existing Jobs", + "federal_tax_amt": "Federal Taxes", + "gpdollars": "$ G.P.", + "gppercent": "% G.P.", + "hrs_claimed": "Hours Flagged", + "hrs_total": "Hours Total", + "importnote": "The Job was initially imported.", + "inproduction": "In Production", + "intakechecklist": "Intake Checklist", + "iou": "IOU", + "job": "Job Details", + "jobcosting": "Job Costing", + "jobtotals": "Job Totals", + "labor_hrs": "B/P/T Hrs", + "labor_rates_subtotal": "Labor Rates Subtotal", + "laborallocations": "Labor Allocations", + "labortotals": "Labor Totals", + "lines": "Estimate Lines", + "local_tax_amt": "Local Taxes", + "mapa": "Paint Materials", + "markforreexport": "Mark for Re-export", + "mash": "Shop Materials", + "masterbypass": "Master Bypass Password", + "materials": { + "mapa": "" + }, + "missingprofileinfo": "This job has missing tax profile info. To ensure correct totals calculations, re-import the job.", + "multipayers": "Additional Payers", + "net_repairs": "Net Repairs", + "notes": "Notes", + "othertotal": "Other Totals", + "outstanding_ar": "A balance is outstanding on this RO. Payments can still be entered when the job is closed. ", + "outstanding_credit_memos": "Outstanding credit memos have not been entered against this job. Credit Memos may still be posted once the job is closed.", + "outstanding_ppd": "There are outstanding PPDs that may not have been synced back to the estimate.", + "outstanding_reconciliation_discrep": "At least one discrepancy is not $0. This may indicate that this job is not properly reconciled and should not be closed.", + "outstanding_sublets": "There are sublet lines on the job which have not been marked as completed. ", + "outstandinghours": "There are outstanding hours on the job that have not been paid or have been overpaid.", + "override_header": "Override estimate header on import?", + "ownerassociation": "Owner Association", + "parts": "Parts", + "parts_lines": "Parts Lines", + "parts_received": "Parts Rec.", + "parts_tax_rates": "Profile - Parts", + "partsfilter": "Parts Only", + "partssubletstotal": "Parts & Sublets Total", + "partstotal": "Parts Total (ex. Taxes)", + "performance": "Performance", + "pimraryamountpayable": "Total Primary Payable", + "plitooltips": { + "billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).", + "calculatedcreditsnotreceived": "The calculated credits not received is derived by subtracting the amount of credit memos entered from the retail total of returns created. This does not take into account whether the credit was marked as received. You can find more information here.", + "creditmemos": "The total retail amount of all returns created. This amount does not reflect credit memos that have been posted.", + "creditsnotreceived": "This total reflects the total retail of parts returns lines that have not been explicitly marked as returned when posting a credit memo. You can learn more about this here here. ", + "discrep1": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.
  • \n
  • You do not have the latest supplement imported, or, a supplement must be submitted and then imported.
  • \n
  • You have posted a bill line to labor.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", + "discrep2": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • Used an incorrect rate when deducting from labor.
  • \n
  • An outstanding imbalance higher in the reconciliation process.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", + "discrep3": "If the discrepancy is not $0, you may have one of the following:

\n\n
    \n
  • A parts order return has not been created.
  • \n
  • An outstanding imbalance higher in the reconciliation process.
  • \n
\n
\nThere may be additional issues not listed above that prevent this Job from reconciling.", + "laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.", + "partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).
\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.", + "totalreturns": "The total retail amount of returns created for this job." + }, + "ppc": "This line contains a part price change.", + "ppdnotexported": "PPDs not Exported", + "profileadjustments": "Profile Disc./Mkup", + "profitbypassrequired": "Minimum gross profit requirements have not been met.", + "profits": "Job Profits", + "prt_dsmk_total": "Line Item Adjustment", + "rates": "Rates", + "rates_subtotal": "All Rates Subtotal", + "reconciliation": { + "billlinestotal": "Bill Lines Total", + "byassoc": "By Line Association", + "byprice": "By Price", + "clear": "Clear All", + "discrepancy": "Discrepancy", + "joblinestotal": "Job Lines Total", + "multipleactprices": "${{act_price}} is the price for multiple job lines.", + "multiplebilllines": "{{line_desc}} has 2 or more bill lines associated to it.", + "multiplebillsforactprice": "Found more than 1 bill matching ${{act_price}} retail price.", + "removedpartsstrikethrough": "Strike through lines represent parts that have been removed from the estimate. They are included for completeness of reconciliation." + }, + "reconciliationheader": "Parts & Sublet Reconciliation", + "relatedros": "Related ROs", + "remove_from_ar": "Remove from AR", + "returntotals": "Return Totals", + "ro_guard": { + "enforce_ar": "AR collection enforced.", + "enforce_bills": "Bill discrepancy enforced.", + "enforce_cm": "Credit memo entry enforced.", + "enforce_labor": "Labor allocations enforced.", + "enforce_ppd": "PPD sync enforced.", + "enforce_profit": "Profit marginsenforced.", + "enforce_sublet": "Sublet completion enforced.", + "enforce_validation": "Master Bypass Required: {{message}}", + "enforced": "This check has been enforced by your shop manager. Enter the master bypass password to close the Job." + }, + "roguard": "RO Guard", + "roguardwarnings": "RO Guard Warnings", + "rosaletotal": "RO Parts Total", + "sale_additional": "Sales - Additional", + "sale_labor": "Sales - Labor", + "sale_parts": "Sales - Parts", + "sale_sublet": "Sales - Sublet", + "sales": "Sales", + "savebeforeconversion": "You have unsaved changes on the Job. Please save them before converting it. ", + "scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the Job. ", + "specialcoveragepolicy": "Special Coverage Policy Applies", + "state_tax_amt": "Provincial/State Taxes", + "subletsnotcompleted": "Outstanding Sublets", + "subletstotal": "Sublets Total", + "subtotal": "Subtotal", + "supplementnote": "The Job had a supplement imported.", + "suspended": "SUSPENDED", + "suspense": "Suspense", + "tasks": "Tasks", + "threshhold": "Max Threshold: ${{amount}}", + "total_cost": "Total Cost", + "total_cust_payable": "Total Customer Amount Payable", + "total_cust_payable_cash_discount": "$t(jobs.labels.total_cust_payable) (Cash Discounted)", + "total_repairs": "Total Repairs", + "total_repairs_cash_discount": "Total Repairs (Cash Discounted)", + "total_sales": "Total Sales", + "total_sales_tax": "Total Sales Tax", + "totals": "Totals", + "unvoidnote": "This Job was unvoided.", + "update_scheduled_completion": "Update Scheduled Completion?", + "vehicle_info": "Vehicle", + "vehicleassociation": "Vehicle Association", + "viewallocations": "View Allocations", + "voidjob": "Are you sure you want to void this Job? This cannot be easily undone. ", + "voidnote": "This Job was voided." + }, + "successes": { + "addedtoproduction": "Job added to production board.", + "all_deleted": "{{count}} Jobs deleted successfully.", + "closed": "Job closed successfully.", + "converted": "Job converted successfully.", + "created": "Job created successfully. Click to view.", + "creatednoclick": "Job created successfully. ", + "delete": "Job deleted successfully.", + "deleted": "Job deleted successfully.", + "duplicated": "Job duplicated successfully. ", + "exported": "Job(s) exported successfully. ", + "invoiced": "Job closed and invoiced successfully.", + "ioucreated": "IOU created successfully. Click to see.", + "partsqueue": "Job added to parts queue.", + "save": "Job saved successfully.", + "savetitle": "Record saved successfully.", + "supplemented": "Job supplemented successfully. ", + "updated": "Job(s) updated successfully.", + "voided": "Job voided successfully." + } + }, + "landing": { + "bigfeature": { + "subtitle": "Rome Online is built using world class technology by experts in the collision repair industry. This translates to software that is tailor made for the unique challenges faced by repair facilities with no compromises. ", + "title": "Bringing the latest technology to the automotive repair industry. " + }, + "footer": { + "company": { + "about": "About Us", + "contact": "Contact", + "disclaimers": "Disclaimers", + "name": "Company", + "privacypolicy": "Privacy Policy" + }, + "io": { + "help": "Help", + "name": "Rome Online", + "status": "System Status" + }, + "slogan": "Rome Technologies. is a technology leader in the collision repair industry. We specialize in creating collision repair management systems and bodyshop management systems that lower cycle times and promote efficiency." + }, + "hero": { + "button": "Learn More", + "title": "Shop management reimagined." + }, + "labels": { + "features": "Features", + "managemyshop": "Sign In", + "pricing": "Pricing" + }, + "pricing": { + "basic": { + "name": "Basic", + "sub": "Best suited for shops looking to increase their volume." + }, + "essentials": { + "name": "Essentials", + "sub": "Best suited for small and low volume shops." + }, + "pricingtitle": "Features", + "pro": { + "name": "Pro", + "sub": "Empower your shop with the tools to operate at peak capacity." + }, + "title": "Features", + "unlimited": { + "name": "Unlimited", + "sub": "Everything you need and more for the high volume shop." + } + } + }, + "menus": { + "currentuser": { + "languageselector": "Language", + "profile": "Profile" + }, + "header": { + "accounting": "Accounting", + "accounting-payables": "Payables", + "accounting-payments": "Payments", + "accounting-receivables": "Receivables", + "activejobs": "Active Jobs", + "all_tasks": "All Tasks", + "alljobs": "All Jobs", + "allpayments": "All Payments", + "availablejobs": "Available Jobs", + "bills": "Bills", + "courtesycars": "Courtesy Cars", + "courtesycars-all": "All Courtesy Cars", + "courtesycars-contracts": "Contracts", + "courtesycars-newcontract": "New Contract", + "create_task": "Create Task", + "customers": "Customers", + "dashboard": "Dashboard", + "enterbills": "Enter Bills", + "entercardpayment": "New Card Charge", + "enterpayment": "Enter Payments", + "entertimeticket": "Enter Time Tickets", + "export": "Export", + "export-logs": "Export Logs", + "help": "Help", + "home": "Home", + "inventory": "Inventory", + "jobs": "Jobs", + "my_tasks": "My Tasks", + "newjob": "Create New Job", + "owners": "Owners", + "parts-queue": "Parts Queue", + "phonebook": "Phonebook", + "productionboard": "Production Board - Visual", + "productionlist": "Production Board - List", + "readyjobs": "Ready Jobs", + "recent": "Recent Items", + "reportcenter": "Report Center", + "rescueme": "Rescue me!", + "schedule": "Schedule", + "scoreboard": "Scoreboard", + "search": { + "bills": "Bills", + "jobs": "Jobs", + "owners": "Owners", + "payments": "Payments", + "phonebook": "Phonebook", + "vehicles": "Vehicles" + }, + "shiftclock": "Shift Clock", + "shop": "My Shop", + "shop_config": "Configuration", + "shop_csi": "CSI", + "shop_templates": "Templates", + "shop_vendors": "Vendors", + "tasks": "Tasks", + "temporarydocs": "Temporary Documents", + "timetickets": "Time Tickets", + "ttapprovals": "Time Ticket Approvals", + "vehicles": "Vehicles" + }, + "jobsactions": { + "admin": "Admin", + "cancelallappointments": "Cancel all appointments", + "closejob": "Close Job", + "deletejob": "Delete Job", + "duplicate": "Duplicate this Job", + "duplicatenolines": "Duplicate this Job without Repair Data", + "newcccontract": "Create Courtesy Car Contract", + "void": "Void Job" + }, + "jobsdetail": { + "claimdetail": "Claim Details", + "dates": "Dates", + "financials": "Financial Information", + "general": "General", + "insurance": "Insurance Information", + "labor": "Labor", + "lifecycle": "Lifecycle", + "parts": "Parts", + "partssublet": "Parts & Bills", + "rates": "Rates", + "repairdata": "Repair Data", + "totals": "Totals" + }, + "profilesidebar": { + "profile": "My Profile", + "shops": "My Shops" + }, + "tech": { + "assignedjobs": "Assigned Jobs", + "claimtask": "Flag Hours", + "dispatchedparts": "Dispatched Parts", + "home": "Home", + "jobclockin": "Job Clock In", + "jobclockout": "Job Clock Out", + "joblookup": "Job Lookup", + "login": "Login", + "logout": "Logout", + "productionboard": "Production Visual", + "productionlist": "Production List", + "shiftclockin": "Shift Clock" + } + }, + "messaging": { + "actions": { + "link": "Link to Job", + "new": "New Conversation" + }, + "errors": { + "invalidphone": "The phone number is invalid. Unable to open conversation. ", + "noattachedjobs": "No Jobs have been associated to this conversation. ", + "updatinglabel": "Error updating label. {{error}}" + }, + "labels": { + "addlabel": "Add a label to this conversation.", + "archive": "Archive", + "maxtenimages": "You can only select up to a maximum of 10 images at a time.", + "messaging": "Messaging", + "noallowtxt": "This customer has not indicated their permission to be messaged.", + "nojobs": "Not associated to any Job.", + "nopush": "Polling Mode Enabled", + "phonenumber": "Phone #", + "presets": "Presets", + "recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.", + "selectmedia": "Select Media", + "sentby": "Sent by {{by}} at {{time}}", + "typeamessage": "Send a message...", + "unarchive": "Unarchive" + }, + "render": { + "conversation_list": "Conversation List" + } + }, + "notes": { + "actions": { + "actions": "Actions", + "deletenote": "Delete Note", + "edit": "Edit Note", + "new": "New Note", + "savetojobnotes": "Save to Job Notes" + }, + "errors": { + "inserting": "Error inserting note. {{error}}" + }, + "fields": { + "createdby": "Created By", + "critical": "Critical", + "private": "Private", + "text": "Contents", + "type": "Type", + "types": { + "customer": "Customer", + "general": "General", + "office": "Office", + "paint": "Paint", + "parts": "Parts", + "shop": "Shop", + "supplement": "Supplement" + }, + "updatedat": "Updated At" + }, + "labels": { + "addtorelatedro": "Add to Related ROs", + "newnoteplaceholder": "Add a note...", + "notetoadd": "Note to Add", + "systemnotes": "System Notes", + "usernotes": "User Notes" + }, + "successes": { + "create": "Note created successfully.", + "deleted": "Note deleted successfully.", + "updated": "Note updated successfully." + } + }, + "owner": { + "labels": { + "noownerinfo": "No owner information." + } + }, + "owners": { + "actions": { + "update": "Update Selected Records" + }, + "errors": { + "deleting": "Error deleting owner. {{error}}.", + "noaccess": "The record does not exist or you do not have access to it. ", + "saving": "Error saving owner. {{error}}.", + "selectexistingornew": "Select an existing owner record or create a new one. " + }, + "fields": { + "accountingid": "Accounting ID", + "address": "Address", + "allow_text_message": "Permission to Text?", + "name": "Name", + "note": "Owner Note", + "ownr_addr1": "Address", + "ownr_addr2": "Address 2", + "ownr_city": "City", + "ownr_co_nm": "Owner Co. Name", + "ownr_ctry": "Country", + "ownr_ea": "Email", + "ownr_fn": "First Name", + "ownr_ln": "Last Name", + "ownr_ph1": "Phone 1", + "ownr_ph2": "Phone 2", + "ownr_st": "Province/State", + "ownr_title": "Title", + "ownr_zip": "Zip/Postal Code", + "preferred_contact": "Preferred Contact Method", + "tax_number": "Tax Number" + }, + "forms": { + "address": "Address", + "contact": "Contact Information", + "name": "Owner Details" + }, + "labels": { + "create_new": "Create a new owner record.", + "deleteconfirm": "Are you sure you want to delete this owner? This cannot be undone.", + "existing_owners": "Existing Owners", + "fromclaim": "Current Claim", + "fromowner": "Historical Owner Record", + "relatedjobs": "Related Jobs", + "updateowner": "Update Owner" + }, + "successes": { + "delete": "Owner deleted successfully.", + "save": "Owner saved successfully." + } + }, + "parts": { + "actions": { + "order": "Order Parts", + "orderinhouse": "Order as In House" + } + }, + "parts_dispatch": { + "actions": { + "accept": "Accept" + }, + "errors": { + "accepting": "Error accepting parts dispatch. {{error}}", + "creating": "Error dispatching parts. {{error}}" + }, + "fields": { + "number": "Number", + "percent_accepted": "% Accepted" + }, + "labels": { + "notyetdispatched": "This part has not been dispatched.", + "parts_dispatch": "Parts Dispatch" + } + }, + "parts_dispatch_lines": { + "fields": { + "accepted_at": "Accepted At" + } + }, + "parts_orders": { + "actions": { + "backordered": "Mark Backordered", + "receive": "Receive", + "receivebill": "Receive Bill" + }, + "errors": { + "associatedbills": "This parts order cannot", + "backordering": "Error backordering part {{message}}.", + "creating": "Error encountered when creating parts order. ", + "oec": "Error creating EMS files for parts order. {{error}}", + "saving": "Error saving parts order. {{error}}.", + "updating": "Error updating parts order/parts order line. {{error}}." + }, + "fields": { + "act_price": "Price", + "backordered_eta": "B.O. ETA", + "backordered_on": "B.O. On", + "cm_received": "CM Received?", + "comments": "Comments", + "cost": "Cost", + "db_price": "List Price", + "deliver_by": "Deliver By", + "job_line_id": "Job Line Id", + "line_desc": "Line Description", + "line_remarks": "Remarks", + "lineremarks": "Line Remarks", + "oem_partno": "Part #", + "order_date": "Order Date", + "order_number": "Order Number", + "orderedby": "Ordered By", + "part_type": "Type", + "quantity": "Qty.", + "return": "Return", + "status": "Status" + }, + "labels": { + "allpartsto": "All Parts Location", + "confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ", + "custompercent": "Custom %", + "discount": "Discount {{percent}}", + "email": "Send by Email", + "inthisorder": "Parts in this Order", + "is_quote": "Parts Quote?", + "mark_as_received": "Mark as Received?", + "newpartsorder": "New Parts Order", + "notyetordered": "This part has not yet been ordered.", + "oec": "Order via EMS", + "order_type": "Order Type", + "orderhistory": "Order History", + "parts_order": "Parts Order", + "parts_orders": "Parts Orders", + "parts_returns": "Parts Returns", + "print": "Show Printed Form", + "receive": "Receive Parts Order", + "removefrompartsqueue": "Unqueue from Parts Queue?", + "returnpartsorder": "Return Parts Order", + "sublet_order": "Sublet Order" + }, + "successes": { + "created": "Parts order created successfully. ", + "line_updated": "Parts return line updated.", + "received": "Parts order received.", + "return_created": "Parts return created successfully." + } + }, + "payments": { + "actions": { + "generatepaymentlink": "Generate Payment Link" + }, + "errors": { + "exporting": "Error exporting payment(s). {{error}}", + "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors.", + "inserting": "Error inserting payment. {{error}}" + }, + "fields": { + "amount": "Amount", + "created_at": "Created At", + "date": "Payment Date", + "exportedat": "Exported At", + "memo": "Memo", + "payer": "Payer", + "paymentnum": "Payment Number", + "stripeid": "Stripe ID", + "transactionid": "Transaction ID", + "type": "Type" + }, + "labels": { + "balance": "Balance", + "ca_bc_etf_table": "ICBC EFT Table Converter", + "customer": "Customer", + "edit": "Edit Payment", + "electronicpayment": "Use Electronic Payment Processing?", + "external": "External", + "findermodal": "ICBC Payment Finder", + "insurance": "Insurance", + "markexported": "Mark Exported", + "markforreexport": "Mark for Re-export", + "new": "New Payment", + "signup": "Please contact support to sign up for electronic payments.", + "smspaymentreminder": "This is {{shopname}} reminding you about your balance of {{amount}}. To pay, click the following link {{payment_link}}.", + "title": "Payments", + "totalpayments": "Total Payments" + }, + "successes": { + "exported": "Payment(s) exported successfully.", + "markexported": "Payment(s) marked exported.", + "markreexported": "Payment marked for re-export successfully", + "payment": "Payment created successfully. ", + "paymentupdate": "Payment updated successfully. ", + "stripe": "Credit card transaction charged successfully." + } + }, + "phonebook": { + "actions": { + "new": "New Phonebook Entry" + }, + "errors": { + "adding": "Error adding phonebook entry. {{error}}", + "saving": "Error saving phonebook entry. {{error}}" + }, + "fields": { + "address1": "Street 1", + "address2": "Street 2", + "category": "Category", + "city": "City", + "company": "Company", + "country": "Country", + "email": "Email", + "fax": "Fax", + "firstname": "First Name", + "lastname": "Last Name", + "phone1": "Phone 1", + "phone2": "Phone 2", + "state": "Province/State" + }, + "labels": { + "noneselected": "No phone book entry selected. ", + "onenamerequired": "At least one name related field is required.", + "vendorcategory": "Vendor" + }, + "successes": { + "added": "Phonebook entry added successfully. ", + "deleted": "Phonebook entry deleted successfully. ", + "saved": "Phonebook entry saved successfully. " + } + }, + "printcenter": { + "appointments": { + "appointment_confirmation": "Appointment Confirmation" + }, + "bills": { + "inhouse_invoice": "In House Invoice" + }, + "courtesycarcontract": { + "courtesy_car_contract": "Courtesy Car Contract", + "courtesy_car_impound": "Impound Charges", + "courtesy_car_inventory": "Courtesy Car Inventory", + "courtesy_car_terms": "Courtesy Car Terms" + }, + "errors": { + "nocontexttype": "No context type set." + }, + "jobs": { + "3rdpartyfields": { + "addr1": "Address 1", + "addr2": "Address 2", + "addr3": "Address 3", + "attn": "Attention", + "city": "City", + "custgst": "Customer Portion of GST", + "ded_amt": "Deductible", + "depreciation": "Depreciation", + "other": "Other", + "ponumber": "PO Number", + "refnumber": "Reference Number", + "sendtype": "Send by", + "state": "Province/State", + "zip": "Postal Code/Zip" + }, + "3rdpartypayer": "Invoice to Third Party Payer", + "ab_proof_of_loss": "AB - Proof of Loss", + "appointment_confirmation": "Appointment Confirmation", + "appointment_reminder": "Appointment Reminder", + "casl_authorization": "CASL Authorization", + "committed_timetickets_ro": "Committed Time Tickets", + "coversheet_landscape": "Coversheet (Landscape)", + "coversheet_portrait": "Coversheet Portrait", + "csi_invitation": "CSI Invitation", + "csi_invitation_action": "CSI Invite", + "diagnostic_authorization": "Diagnostic Authorization", + "dms_posting_sheet": "DMS Posting Sheet", + "envelope_return_address": "#10 Envelope Return Address Label", + "estimate": "Estimate Only", + "estimate_detail": "Estimate Details", + "estimate_followup": "Estimate Followup", + "express_repair_checklist": "Express Repair Checklist", + "filing_coversheet_landscape": "Filing Coversheet (Landscape)", + "filing_coversheet_portrait": "Filing Coversheet (Portrait)", + "final_invoice": "Final Invoice", + "fippa_authorization": "FIPPA Authorization", + "folder_label_multiple": "Folder Label - Multi", + "glass_express_checklist": "Glass Express Checklist", + "guarantee": "Repair Guarantee", + "individual_job_note": "RO Job Note", + "invoice_customer_payable": "Invoice (Customer Payable)", + "invoice_total_payable": "Invoice (Total Payable)", + "iou_form": "IOU Form", + "job_costing_ro": "Job Costing", + "job_lifecycle_ro": "Job Lifecycle", + "job_notes": "Job Notes", + "job_tasks": "Job Tasks", + "key_tag": "Key Tag", + "labels": { + "count": "Count", + "labels": "Labels", + "position": "Starting Position" + }, + "lag_time_ro": "Lag Time", + "mechanical_authorization": "Mechanical Authorization", + "mpi_animal_checklist": "MPI - Animal Checklist", + "mpi_eglass_auth": "MPI - eGlass Auth", + "mpi_final_acct_sheet": "MPI - Final Accounting Sheet (Direct Repair)", + "mpi_final_repair_acct_sheet": "MPI - Final Accounting Sheet", + "paint_grid": "Paint Grid", + "parts_dispatch": "Parts Dispatch", + "parts_invoice_label_single": "Parts Label Single", + "parts_label_multiple": "Parts Label - Multi", + "parts_label_single": "Parts Label - Single", + "parts_list": "Parts List", + "parts_order": "Parts Order Confirmation", + "parts_order_confirmation": "", + "parts_order_history": "Parts Order History", + "parts_return_slip": "Parts Return Slip", + "payment_receipt": "Payment Receipt", + "payment_request": "Payment Request", + "payments_by_job": "Job Payments", + "purchases_by_ro_detail": "Purchases - Detail", + "purchases_by_ro_summary": "Purchases - Summary", + "qc_sheet": "Quality Control Sheet", + "rental_reservation": "Rental Reservation", + "ro_totals": "RO Totals", + "ro_with_description": "RO Summary with Descriptions", + "sgi_certificate_of_repairs": "SGI - Certificate of Repairs", + "sgi_windshield_auth": "SGI - Windshield Authorization", + "stolen_recovery_checklist": "Stolen Recovery Checklist", + "sublet_order": "Sublet Order", + "supplement_request": "Supplement Request", + "thank_you_ro": "Thank You Letter", + "thirdpartypayer": "Third Party Payer", + "timetickets_ro": "Time Tickets", + "vehicle_check_in": "Vehicle Intake", + "vehicle_delivery_check": "Vehicle Delivery Checklist", + "window_tag": "Window Tag", + "window_tag_sublet": "Window Tag - Sublet", + "work_authorization": "Work Authorization", + "worksheet_by_line_number": "Worksheet by Line Number", + "worksheet_sorted_by_operation": "Worksheet by Operation", + "worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)", + "worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type", + "worksheet_sorted_by_operation_type": "Worksheet by Operation Type", + "worksheet_sorted_by_team": "Worksheet by Team" + }, + "labels": { + "groups": { + "authorization": "Authorization", + "financial": "Financial", + "post": "Post-Production", + "pre": "Pre-Production", + "ro": "Repair Order", + "worksheet": "Worksheets" + }, + "misc": "Miscellaneous Documents", + "repairorder": "Repair Order Related", + "reportcentermodal": "Report Center", + "speedprint": "Speed Print", + "title": "Print Center" + }, + "payments": { + "ca_bc_etf_table": "ICBC EFT Table", + "exported_payroll": "Payroll Table" + }, + "special": { + "attendance_detail_csv": "Attendance Table" + }, + "subjects": { + "jobs": { + "individual_job_note": "Job Note RO: {{ro_number}}", + "parts_dispatch": "Parts Dispatch RO: {{ro_number}}", + "parts_order": "Parts Order PO: {{ro_number}} - {{name}}", + "parts_return_slip": "Parts Return PO: {{ro_number}} - {{name}}", + "sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}" + } + }, + "vendors": { + "purchases_by_vendor_detailed": "Purchases by Vendor - Detailed", + "purchases_by_vendor_summary": "Purchases by Vendor - Summary" + } + }, + "production": { + "actions": { + "addcolumns": "Add Columns", + "bodypriority-clear": "Clear Body Priority", + "bodypriority-set": "Set Body Priority", + "detailpriority-clear": "Clear Detail Priority", + "detailpriority-set": "Set Detail Priority", + "paintpriority-clear": "Clear Paint Priority", + "paintpriority-set": "Set Paint Priority", + "remove": "Remove from Production", + "removecolumn": "Remove Column", + "saveconfig": "Save Configuration", + "suspend": "Suspend", + "unsuspend": "Unsuspend" + }, + "constants": { + "main_profile": "Default" + }, + "errors": { + "boardupdate": "Error encountered updating Job. {{message}}", + "name_exists": "A Profile with this name already exists. Please choose a different name.", + "name_required": "Profile name is required.", + "removing": "Error removing from production board. {{error}}", + "settings": "Error saving board settings: {{error}}" + }, + "labels": { + "actual_in": "Actual In", + "addnewprofile": "Add New Profile", + "alert": "Alert", + "alertoff": "Remove alert from Job", + "alerton": "Add alert to Job", + "alerts": "Alerts", + "ats": "Alternative Transportation", + "bodyhours": "B", + "bodypriority": "B/P", + "bodyshop": { + "labels": { + "qbo_departmentid": "QBO Department ID", + "qbo_usa": "QBO USA" + } + }, + "card_size": "Card Size", + "cardcolor": "Colored Cards", + "cardsettings": "Card Settings", + "clm_no": "Claim Number", + "comment": "Comment", + "compact": "Compact Cards", + "detailpriority": "D/P", + "employeeassignments": "Employee Assignments", + "employeesearch": "Employee Search", + "estimator": "Estimator", + "horizontal": "Horizontal", + "ins_co_nm": "Insurance Company Name", + "jobdetail": "Job Details", + "kiosk_mode": "Kiosk Mode", + "laborhrs": "Labor Hours", + "legend": "Legend:", + "model_info": "Vehicle Info", + "note": "Production Note", + "off": "Off", + "on": "On", + "orientation": "Board Orientation", + "ownr_nm": "Customer Name", + "paintpriority": "P/P", + "partsstatus": "Parts Status", + "production_note": "Production Note", + "refinishhours": "R", + "scheduled_completion": "Scheduled Completion", + "selectview": "Select a View", + "stickyheader": "Sticky Header (BETA)", + "sublets": "Sublets", + "subtotal": "Subtotal", + "tall": "Tall", + "tasks": "Tasks", + "totalhours": "Total Hrs ", + "touchtime": "T/T", + "unassigned": "Unassigned", + "vertical": "Vertical", + "viewname": "View Name", + "wide": "Wide" + }, + "options": { + "horizontal": "Horizontal", + "large": "Large", + "medium": "Medium", + "small": "Small", + "vertical": "Vertical" + }, + "settings": { + "board_settings": "Board Settings", + "filters": { + "md_estimators": "Estimators", + "md_ins_cos": "Insurance Companies" + }, + "filters_title": "Filters", + "information": "Information", + "layout": "Layout", + "statistics": { + "jobs_in_production": "Jobs in Production", + "tasks_in_production": "Tasks in Production", + "tasks_in_view": "Tasks in View", + "tasks_on_board": "Tasks on Board", + "total_amount_in_production": "Dollars in Production", + "total_amount_in_view": "Dollars in View", + "total_amount_on_board": "Dollars on Board", + "total_hours_in_production": "Hours in Production", + "total_hours_in_view": "Hours in View", + "total_hours_on_board": "Hours on Board", + "total_jobs_in_view": "Jobs in View", + "total_jobs_on_board": "Jobs on Board", + "total_lab_in_production": "Body Hours in Production", + "total_lab_in_view": "Body Hours in View", + "total_lab_on_board": "Body Hours on Board", + "total_lar_in_production": "Refinish Hours in Production", + "total_lar_in_view": "Refinish Hours in View", + "total_lar_on_board": "Refinish Hours on Board" + }, + "statistics_title": "Statistics" + }, + "statistics": { + "currency_symbol": "$", + "hours": "Hours", + "jobs": "Jobs", + "jobs_in_production": "Jobs in Production", + "tasks": "Tasks", + "tasks_in_production": "Tasks in Production", + "tasks_in_view": "Tasks in View", + "tasks_on_board": "Tasks on Board", + "total_amount_in_production": "Dollars in Production", + "total_amount_in_view": "Dollars in View", + "total_amount_on_board": "Dollars on Board", + "total_hours_in_production": "Hours in Production", + "total_hours_in_view": "Hours in View", + "total_hours_on_board": "Hours on Board", + "total_jobs_in_view": "Jobs in View", + "total_jobs_on_board": "Jobs on Board", + "total_lab_in_production": "Body Hours in Production", + "total_lab_in_view": "Body Hours in View", + "total_lab_on_board": "Body Hours on Board", + "total_lar_in_production": "Refinish Hours in Production", + "total_lar_in_view": "Refinish Hours in View", + "total_lar_on_board": "Refinish Hours on Board" + }, + "successes": { + "removed": "Job removed from production." + } + }, + "profile": { + "errors": { + "state": "Error reading page state. Please refresh." + }, + "labels": { + "activeshop": "Active Shop" + }, + "successes": { + "updated": "Profile updated successfully." + } + }, + "reportcenter": { + "actions": { + "generate": "Generate" + }, + "labels": { + "advanced_filters": "Advanced Filters and Sorters", + "advanced_filters_false": "False", + "advanced_filters_filter_field": "Field", + "advanced_filters_filter_operator": "Operator", + "advanced_filters_filter_value": "Value", + "advanced_filters_filters": "Filters", + "advanced_filters_hide": "Hide", + "advanced_filters_show": "Show", + "advanced_filters_sorter_direction": "Direction", + "advanced_filters_sorter_field": "Field", + "advanced_filters_sorters": "Sorters", + "advanced_filters_true": "True", + "dates": "Dates", + "employee": "Employee", + "filterson": "Filters on {{object}}: {{field}}", + "generateasemail": "Generate as Email?", + "groups": { + "customers": "Customers", + "jobs": "Jobs & Costing", + "payroll": "Payroll", + "purchases": "Purchases", + "sales": "Sales" + }, + "key": "Report", + "objects": { + "appointments": "Appointments", + "bills": "Bills", + "csi": "CSI", + "exportlogs": "Export Logs", + "jobs": "Jobs", + "parts_orders": "Parts Orders", + "payments": "Payments", + "scoreboard": "Scoreboard", + "tasks": "Tasks", + "timetickets": "Timetickets" + }, + "vendor": "Vendor" + }, + "templates": { + "adp_payroll_flat": "ADP Payroll - Flat Rate", + "adp_payroll_straight": "ADP Payroll - Straight Time", + "anticipated_revenue": "Anticipated Revenue", + "ar_aging": "AR Aging", + "attendance_detail": "Attendance (All Employees)", + "attendance_employee": "Employee Attendance", + "attendance_summary": "Attendance Summary (All Employees)", + "committed_timetickets": "Committed Time Tickets", + "committed_timetickets_employee": "Committed Employee Time Tickets", + "committed_timetickets_summary": "Committed Time Tickets Summary", + "credits_not_received_date": "Credits not Received by Date", + "credits_not_received_date_vendorid": "Credits not Received by Vendor", + "csi": "CSI Responses", + "customer_list": "Customer List", + "cycle_time_analysis": "Cycle Time Analysis", + "estimates_written_converted": "Estimates Written/Converted", + "estimator_detail": "Jobs by Estimator (Detail)", + "estimator_summary": "Jobs by Estimator (Summary)", + "export_payables": "Export Log - Payables", + "export_payments": "Export Log - Payments", + "export_receivables": "Export Log - Receivables", + "exported_gsr_by_ro": "Exported Gross Sales - Excel", + "exported_gsr_by_ro_labor": "Exported Gross Sales (Labor) - Excel", + "gsr_by_atp": "", + "gsr_by_ats": "Gross Sales by ATS", + "gsr_by_category": "Gross Sales by Category", + "gsr_by_csr": "Gross Sales by CSR", + "gsr_by_delivery_date": "Gross Sales by Delivery Date", + "gsr_by_estimator": "Gross Sales by Estimator", + "gsr_by_exported_date": "Exported Gross Sales", + "gsr_by_ins_co": "Gross Sales by Insurance Company", + "gsr_by_make": "Gross Sales by Vehicle Make", + "gsr_by_referral": "Gross Sales by Referral Source", + "gsr_by_ro": "Gross Sales by RO", + "gsr_labor_only": "Gross Sales - Labor Only", + "hours_sold_detail_closed": "Hours Sold Detail - Closed", + "hours_sold_detail_closed_csr": "Hours Sold Detail - Closed by CSR", + "hours_sold_detail_closed_estimator": "Hours Sold Detail - Closed by Estimator", + "hours_sold_detail_closed_ins_co": "Hours Sold Detail - Closed by Source", + "hours_sold_detail_closed_status": "Hours Sold Detail - Closed by Status", + "hours_sold_detail_open": "Hours Sold Detail - Open", + "hours_sold_detail_open_csr": "Hours Sold Detail - Open by CSR", + "hours_sold_detail_open_estimator": "Hours Sold Detail - Open by Estimator", + "hours_sold_detail_open_ins_co": "Hours Sold Detail - Open by Source", + "hours_sold_detail_open_status": "Hours Sold Detail - Open by Status", + "hours_sold_summary_closed": "Hours Sold Summary - Closed", + "hours_sold_summary_closed_csr": "Hours Sold Summary - Closed by CSR", + "hours_sold_summary_closed_estimator": "Hours Sold Summary - Closed by Estimator", + "hours_sold_summary_closed_ins_co": "Hours Sold Summary - Closed by Source", + "hours_sold_summary_closed_status": "Hours Sold Summary - Closed by Status", + "hours_sold_summary_open": "Hours Sold Summary - Open", + "hours_sold_summary_open_csr": "Hours Sold Summary - Open CSR", + "hours_sold_summary_open_estimator": "Hours Sold Summary - Open Estimator", + "hours_sold_summary_open_ins_co": "Hours Sold Summary - Open by Source", + "hours_sold_summary_open_status": "Hours Sold Summary - Open by Status", + "job_costing_ro_csr": "Job Costing by CSR", + "job_costing_ro_date_detail": "Job Costing by RO - Detail", + "job_costing_ro_date_summary": "Job Costing by RO - Summary", + "job_costing_ro_estimator": "Job Costing by Estimator", + "job_costing_ro_ins_co": "Job Costing by RO Source", + "job_lifecycle_date_detail": "Job Lifecycle by Date - Detail", + "job_lifecycle_date_summary": "Job Lifecycle by Date - Summary", + "jobs_completed_not_invoiced": "Jobs Completed not Invoiced", + "jobs_invoiced_not_exported": "Jobs Invoiced not Exported", + "jobs_reconcile": "Parts/Sublet/Labor Reconciliation", + "jobs_scheduled_completion": "Jobs Scheduled Completion", + "lag_time": "Lag Time", + "load_level": "Load Level", + "lost_sales": "Lost Sales", + "open_orders": "Open Orders by Date", + "open_orders_csr": "Open Orders by CSR", + "open_orders_estimator": "Open Orders by Estimator", + "open_orders_excel": "Open Orders - Excel", + "open_orders_ins_co": "Open Orders by Insurance Company", + "open_orders_referral": "Open Orders by Referral Source", + "open_orders_specific_csr": "Open Orders filtered by CSR", + "open_orders_status": "Open Orders by Status", + "parts_backorder": "IOU Parts List", + "parts_not_recieved": "Parts Not Received", + "parts_not_recieved_vendor": "Parts Not Received by Vendor", + "parts_received_not_scheduled": "Parts Received for Jobs Not Scheduled", + "payments_by_date": "Payments by Date", + "payments_by_date_payment": "Payments by Date and Payment Type", + "payments_by_date_type": "Payments by Date and Customer Type", + "production_by_category": "Production by Category", + "production_by_category_one": "Production filtered by Category", + "production_by_csr": "Production by CSR", + "production_by_last_name": "Production by Last Name", + "production_by_repair_status": "Production by Status", + "production_by_repair_status_one": "Production filtered by Status", + "production_by_ro": "Production by RO", + "production_by_target_date": "Production by Scheduled Completion", + "production_by_technician": "Production by Technician", + "production_by_technician_one": "Production filtered by Technician", + "production_not_production_status": "Production not in Production Status", + "production_over_time": "Production Level over Time", + "psr_by_make": "Percent of Sales by Vehicle Make", + "purchase_return_ratio_excel": "Purchase & Return Ratio - Excel", + "purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)", + "purchase_return_ratio_grouped_by_vendor_summary": "Purchase & Return Ratio by Vendor (Summary)", + "purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)", + "purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)", + "purchases_by_date_excel": "Purchases by Date - Excel", + "purchases_by_date_range_detail": "Purchases by Date - Detail", + "purchases_by_date_range_summary": "Purchases by Date - Summary", + "purchases_by_ro_detail_date": "Purchases by RO - Detail", + "purchases_by_ro_summary_date": "Purchases by RO - Summary", + "purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed", + "purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary", + "purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed", + "purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary", + "returns_grouped_by_vendor_detailed": "Returns Grouped by Vendor - Detailed", + "returns_grouped_by_vendor_summary": "Returns Grouped by Vendor - Summary", + "schedule": "Appointment Schedule", + "scheduled_parts_list": "Parts for Jobs Scheduled In", + "scoreboard_detail": "Scoreboard Detail", + "scoreboard_summary": "Scoreboard Summary", + "supplement_ratio_ins_co": "Supplement Ratio by Source", + "tasks_date": "Tasks by Date", + "tasks_date_employee": "Employee Tasks by Date", + "thank_you_date": "Thank You Letters", + "timetickets": "Time Tickets", + "timetickets_employee": "Employee Time Tickets", + "timetickets_summary": "Time Tickets Summary", + "total_loss_jobs": "Jobs Marked as Total Loss", + "unclaimed_hrs": "Unflagged Hours", + "void_ros": "Void ROs", + "work_in_progress_committed_labour": "Work in Progress - Committed Labor", + "work_in_progress_jobs": "Work in Progress - Jobs", + "work_in_progress_labour": "Work in Progress - Labor", + "work_in_progress_payables": "Work in Progress - Payables" + } + }, + "schedule": { + "labels": { + "atssummary": "ATS Summary", + "employeevacation": "Employee Vacations", + "estimators": "Filter by Writer/Customer Rep.", + "ins_co_nm_filter": "Filter by Insurance Company", + "intake": "Intake Events", + "manual": "Manual Events", + "manualevent": "Add Manual Event" + } + }, + "scoreboard": { + "actions": { + "edit": "Edit" + }, + "errors": { + "adding": "Error adding Job to Scoreboard. {{message}}", + "removing": "Error removing Job from Scoreboard. {{message}}", + "updating": "Error updating Scoreboard. {{message}}" + }, + "fields": { + "bodyhrs": "Body Hours", + "date": "Date", + "painthrs": "Paint Hours" + }, + "labels": { + "allemployeetimetickets": "All Employee Time Tickets", + "asoftodaytarget": "As of Today", + "body": "Body", + "bodyabbrev": "B", + "bodycharttitle": "Body Targets vs Actual", + "calendarperiod": "Periods based on calendar weeks/months.", + "combinedcharttitle": "Combined Targets vs Actual", + "dailyactual": "Actual (D)", + "dailytarget": "Daily", + "efficiencyoverperiod": "Efficiency over Selected Dates", + "entries": "Scoreboard Entries", + "jobs": "Jobs", + "jobscompletednotinvoiced": "Completed Not Invoiced", + "lastmonth": "Last Month", + "lastweek": "Last Week", + "monthlytarget": "Monthly", + "priorweek": "Prior Week", + "productivestatistics": "Productive Hours Statistics", + "productivetimeticketsoverdate": "Productive Hours over Selected Dates", + "refinish": "Refinish", + "refinishabbrev": "R", + "refinishcharttitle": "Refinish Targets vs Actual", + "targets": "Targets", + "thismonth": "This Month", + "thisweek": "This Week", + "timetickets": "Time Tickets", + "timeticketsemployee": "Time Tickets by Employee", + "todateactual": "Actual (MTD)", + "total": "Total", + "totalhrs": "Total Hours", + "totaloverperiod": "Total over Selected Dates", + "weeklyactual": "Actual (W)", + "weeklytarget": "Weekly", + "workingdays": "Working Days / Month" + }, + "successes": { + "added": "Job added to scoreboard.", + "removed": "Job removed from scoreboard.", + "updated": "Scoreboard updated." + } + }, + "tasks": { + "actions": { + "edit": "Edit Task", + "new": "New Task", + "view": "View Task" + }, + "buttons": { + "allTasks": "All", + "complete": "Toggle Complete", + "create": "Create Task", + "delete": "Toggle Delete", + "edit": "Edit", + "myTasks": "Mine", + "refresh": "Refresh" + }, + "date_presets": { + "completion": "Completion", + "day": "Day", + "days": "Days", + "delivery": "Delivery", + "next_week": "Next Week", + "one_month": "One Month", + "three_months": "Three Months", + "three_weeks": "Three Weeks", + "today": "Today", + "tomorrow": "Tomorrow", + "two_weeks": "Two Weeks" + }, + "failures": { + "completed": "Failed to toggle Task completion.", + "created": "Failed to create Task.", + "deleted": "Failed to toggle Task deletion.", + "updated": "Failed to update Task." + }, + "fields": { + "actions": "Actions", + "assigned_to": "Assigned To", + "bill": "Bill", + "billid": "Bill", + "completed": "Completed", + "created_at": "Created At", + "created_by": "Created By", + "description": "Description", + "due_date": "Due Date", + "job": { + "ro_number": "RO #" + }, + "jobid": "Job", + "jobline": "Job Line", + "joblineid": "Job Line", + "parts_order": "Parts Order", + "partsorderid": "Parts Order", + "priorities": { + "high": "High", + "low": "Low", + "medium": "Medium" + }, + "priority": "Priority", + "related_items": "Related Items", + "remind_at": "Remind At", + "title": "Title" + }, + "placeholders": { + "assigned_to": "Select an Employee", + "billid": "Select a Bill", + "description": "Enter a description", + "jobid": "Select a Job", + "joblineid": "Select a Job Line", + "partsorderid": "Select a Parts Order" + }, + "successes": { + "completed": "Toggled Task completion successfully.", + "created": "Task created successfully.", + "deleted": "Toggled Task deletion successfully.", + "updated": "Task updated successfully." + }, + "titles": { + "all_tasks": "All Tasks", + "completed": "Completed Tasks", + "deleted": "Deleted Tasks", + "job_tasks": "Job Tasks", + "mine": "My Tasks", + "my_tasks": "My Tasks" + }, + "validation": { + "due_at_error_message": "The due date must be in the future!", + "remind_at_error_message": "The reminder date and time must be at least 30 minutes in the future!" + } + }, + "tech": { + "fields": { + "employeeid": "Employee ID", + "pin": "PIN" + }, + "labels": { + "loggedin": "Logged in as {{name}}", + "notloggedin": "Not logged in." + } + }, + "templates": { + "errors": { + "updating": "Error updating template {{error}}." + }, + "successes": { + "updated": "Template updated successfully." + } + }, + "timetickets": { + "actions": { + "claimtasks": "Flag Hours", + "clockin": "Clock In", + "clockout": "Clock Out", + "commit": "Commit Tickets ({{count}})", + "commitone": "Commit", + "enter": "Enter New Time Ticket", + "payall": "Pay All", + "printemployee": "Print Time Tickets", + "uncommit": "Uncommit" + }, + "errors": { + "clockingin": "Error while clocking in. {{message}}", + "clockingout": "Error while clocking out. {{message}}", + "creating": "Error creating time ticket. {{message}}", + "deleting": "Error deleting time ticket. {{message}}", + "noemployeeforuser": "Unable to use Shift Clock", + "noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. ", + "payall": "Error flagging hours. {{error}}", + "shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry." + }, + "fields": { + "actualhrs": "Actual Hours", + "ciecacode": "CIECA Code", + "clockhours": "Clock Hours", + "clockoff": "Clock Off", + "clockon": "Clocked In", + "committed": "Committed", + "committed_at": "Committed At", + "cost_center": "Cost Center", + "created_by": "Created By", + "date": "Ticket Date", + "efficiency": "Efficiency", + "employee": "Employee", + "employee_team": "Employee Team", + "flat_rate": "Flat Rate?", + "memo": "Memo", + "productivehrs": "Productive Hours", + "ro_number": "Job to Post Against", + "task_name": "Task" + }, + "labels": { + "alreadyclockedon": "You are already clocked in to the following Job(s):", + "ambreak": "AM Break", + "amshift": "AM Shift", + "claimtaskpreview": "Flagged Hours Preview", + "clockhours": "Shift Clock Hours Summary", + "clockintojob": "Clock In to Job", + "deleteconfirm": "Are you sure you want to delete this time ticket? This cannot be undone.", + "edit": "Edit Time Ticket", + "efficiency": "Efficiency", + "flat_rate": "Flat Rate", + "jobhours": "Job Related Time Tickets Summary", + "lunch": "Lunch", + "new": "New Time Ticket", + "payrollclaimedtasks": "These time tickets will be automatically entered to the system as a part of claiming this task. These numbers are calculated using the jobs assigned lines. If lines are unassigned, they will be excluded from created tickets.", + "pmbreak": "PM Break", + "pmshift": "PM Shift", + "shift": "Shift", + "shiftalreadyclockedon": "Active Shift Time Tickets", + "straight_time": "Straight Time", + "task": "Task", + "timetickets": "Time Tickets", + "unassigned": "Unassigned", + "zeroactualnegativeprod": "Actual hours must be 0 if entering negative productive hours." + }, + "successes": { + "clockedin": "Clocked in successfully.", + "clockedout": "Clocked out successfully.", + "committed": "Time Tickets Committed Successfully", + "created": "Time ticket entered successfully.", + "deleted": "Time ticket deleted successfully.", + "payall": "All hours paid out successfully." + }, + "validation": { + "clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.", + "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time.", + "hoursenteredmorethanavailable": "The number of hours entered is more than what is available for this cost center.", + "unassignedlines": "There are currently {{unassignedHours}} hours of repair lines that are unassigned. These hours are not including in the above calculations and must be paid manually." + } + }, + "titles": { + "accounting-payables": "Payables | {{app}}", + "accounting-payments": "Payments | {{app}}", + "accounting-receivables": "Receivables | {{app}}", + "all_tasks": "All Tasks", + "app": "", + "bc": { + "accounting-payables": "Payables", + "accounting-payments": "Payments", + "accounting-receivables": "Receivables", + "all_tasks": "All Tasks", + "availablejobs": "Available Jobs", + "bills-list": "Bills", + "contracts": "Contracts", + "contracts-create": "New Contract", + "contracts-detail": "Contract #{{number}}", + "courtesycars": "Courtesy Cars", + "courtesycars-detail": "Courtesy Car {{number}}", + "courtesycars-new": "New Courtesy Car", + "dashboard": "Dashboard", + "dms": "DMS Export", + "export-logs": "Export Logs", + "inventory": "Inventory", + "jobs": "Jobs", + "jobs-active": "Active Jobs", + "jobs-admin": "Admin", + "jobs-all": "All Jobs", + "jobs-checklist": "Checklist", + "jobs-close": "Close Job", + "jobs-deliver": "Deliver Job", + "jobs-detail": "Job {{number}}", + "jobs-intake": "Intake", + "jobs-new": "Create a New Job", + "jobs-ready": "Ready Jobs", + "my_tasks": "My Tasks", + "owner-detail": "{{name}}", + "owners": "Owners", + "parts-queue": "Parts Queue", + "payments-all": "All Payments", + "phonebook": "Phonebook", + "productionboard": "Production Board - Visual", + "productionlist": "Production Board - List", + "profile": "My Profile", + "schedule": "Schedule", + "scoreboard": "Scoreboard", + "shop": "Manage my Shop ({{shopname}})", + "shop-csi": "CSI Responses", + "shop-templates": "Shop Templates", + "shop-vendors": "Vendors", + "tasks": "Tasks", + "temporarydocs": "Temporary Documents", + "timetickets": "Time Tickets", + "ttapprovals": "Time Ticket Approvals", + "vehicle-details": "Vehicle: {{vehicle}}", + "vehicles": "Vehicles" + }, + "bills-list": "Bills | {{app}}", + "contracts": "Courtesy Car Contracts | {{app}}", + "contracts-create": "New Contract | {{app}}", + "contracts-detail": "Contract {{id}} | {{app}}", + "courtesycars": "Courtesy Cars | {{app}}", + "courtesycars-create": "New Courtesy Car | {{app}}", + "courtesycars-detail": "Courtesy Car {{id}} | {{app}}", + "dashboard": "Dashboard | {{app}}", + "dms": "DMS Export | {{app}}", + "export-logs": "Export Logs | {{app}}", + "imexonline": "ImEX Online", + "inventory": "Inventory | {{app}}", + "jobs": "Active Jobs | {{app}}", + "jobs-admin": "Job {{ro_number}} - Admin | {{app}}", + "jobs-all": "All Jobs | {{app}}", + "jobs-checklist": "Job Checklist | {{app}}", + "jobs-close": "Close Job {{number}} | {{app}}", + "jobs-create": "Create a New Job | {{app}}", + "jobs-deliver": "Deliver Job | {{app}}", + "jobs-intake": "Intake | {{app}}", + "jobsavailable": "Available Jobs | {{app}}", + "jobsdetail": "Job {{ro_number}} | {{app}}", + "jobsdocuments": "Job Documents {{ro_number}} | {{app}}", + "manageroot": "Home | {{app}}", + "my_tasks": "My Tasks", + "owners": "All Owners | {{app}}", + "owners-detail": "{{name}} | {{app}}", + "parts-queue": "Parts Queue | {{app}}", + "payments-all": "Payments | {{app}}", + "phonebook": "Phonebook | {{app}}", + "productionboard": "Production Board - Visual | {{app}}", + "productionlist": "Production Board - List | {{app}}", + "profile": "My Profile | {{app}}", + "readyjobs": "Ready Jobs | {{app}}", + "resetpassword": "Reset Password", + "resetpasswordvalidate": "Enter New Password", + "romeonline": "Rome Online", + "schedule": "Schedule | {{app}}", + "scoreboard": "Scoreboard | {{app}}", + "shop": "My Shop | {{app}}", + "shop-csi": "CSI Responses | {{app}}", + "shop-templates": "Shop Templates | {{app}}", + "shop_vendors": "Vendors | {{app}}", + "tasks": "Tasks", + "techconsole": "Technician Console | {{app}}", + "techjobclock": "Technician Job Clock | {{app}}", + "techjoblookup": "Technician Job Lookup | {{app}}", + "techshiftclock": "Technician Shift Clock | {{app}}", + "temporarydocs": "Temporary Documents | {{app}}", + "timetickets": "Time Tickets | {{app}}", + "ttapprovals": "Time Ticket Approvals | {{app}}", + "vehicledetail": "Vehicle Details {{vehicle}} | {{app}}", + "vehicles": "All Vehicles | {{app}}" + }, + "trello": { + "labels": { + "add_card": "Add Card", + "add_lane": "Add Lane", + "cancel": "Cancel", + "delete_lane": "Delete Lane", + "description": "Description", + "label": "Label", + "lane_actions": "Lane Actions", + "title": "Title" + } + }, + "tt_approvals": { + "actions": { + "approveselected": "Approve Selected" + }, + "labels": { + "approval_queue_in_use": "Time tickets will be added to the approval queue.", + "calculate": "Calculate" + } + }, + "upsell": { + "cta": { + "learnmore": "Learn More" + }, + "messages": { + "accounting": { + "payables": { + "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + }, + "payments": { + "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + }, + "receivables": { + "subtitle": "Effortlessly send your invoices to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + } + }, + "audit": { + "general": { + "subtitle": "Know exactly what happened and when through the entire repair process.", + "title": "Comprehensive Audit Trails" + } + }, + "bills": { + "autoreconcile": { + "subtitle": "Let your management system do the tedious work - take advantage of automatic job reconciliation today.", + "title": "Did you account for every invoice?" + }, + "general": { + "subtitle": "Our Bills module allows you to precisely account for every penny on the repair order to ensure you maximize your bottom line.", + "title": "Boost your profits by taking control of costs!" + } + }, + "checklist": { + "general": { + "subtitle": "Standardize your intake and delivery with digitized checklists and SOPs.", + "title": "Done right, the first time." + } + }, + "courtesycars": { + "general": { + "subtitle": "Keep track of vehicles and contracts for your courtesy cars, all seamlessly synchronized with your Jobs.", + "title": "Manage your fleet with ease" + } + }, + "csi": { + "general": { + "subtitle": "With our integrated CSI module, send follow up surveys to your customers to see how well you did.", + "title": "See what your customers have to say" + } + }, + "dashboard": { + "general": { + "subtitle": "Make data based decisions and take control of your business using our real-time dashboard.", + "title": "Realtime Insight & Analytics" + } + }, + "lifecycle": { + "general": { + "subtitle": "Job life cycles tell you exactly how long the job stayed in each stage of the repair process to identify bottle necks and inefficiencies.", + "title": "Are your repair KPIs suffering?" + } + }, + "media": { + "general": { + "subtitle": "Store your vehicle repair documentation, invoices, and related documents digitally to access them anywhere, any time.", + "title": "Go paperless." + }, + "mobile": { + "subtitle": "Use our mobile app to attach images from your device to the job, increasing your efficiency.", + "title": "Accelerate repair documentation with Mobile" + } + }, + "payments": { + "general": { + "subtitle": "Manage outstanding balances and collect payments by credit card from your customers.", + "title": "Integrated Accounts Receivable & Payments" + } + }, + "scoreboard": { + "general": { + "subtitle": "Understand hours produced and sold to facilitate employee incentive programs.", + "title": "Give credit where credit is due" + } + }, + "smartscheduling": { + "datepicker": { + "subtitle": "Smart Scsheduling gives you the best dates for a vehicle to come in based on your current and predicted production load.", + "title": "When's the best time for this job to arrive?" + }, + "general": { + "subtitle": "Know exactly how busy you will be tomorrow, the day after, or next week to know exactly when to schedule your next repair.", + "title": "Forecast your production with Smart Scheduling" + }, + "hrsdelta": { + "subtitle": "Understand changes to your Work in Progress and production load instantly.", + "title": "Cars come and cars go." + } + }, + "techconsole": { + "general": { + "subtitle": "The technician's console allows technicians to see job information, media, documents and keep track of their time.", + "title": "Empower your Technicians" + } + }, + "timetickets": { + "allocations": { + "subtitle": "Ensure your technicians are paid out exactly what they are owed - not a penny less, not a penny more.", + "title": "Technician Payments Done Just Right" + }, + "general": { + "subtitle": "Track your technicians time with precision, giving you insight to repair progress and labor efficiency.", + "title": "Who did what and for how long?" + } + }, + "visualboard": { + "general": { + "subtitle": "The Visual Production Board makes it easier than ever before to manage your work in progress.", + "title": "A whole new kind of production board" + } + } + } + }, + "user": { + "actions": { + "changepassword": "Change Password", + "signout": "Sign Out", + "updateprofile": "Update Profile" + }, + "errors": { + "updating": "Error updating user or association {{message}}" + }, + "fields": { + "authlevel": "Authorization Level", + "displayname": "Display Name", + "email": "Email", + "photourl": "Avatar URL" + }, + "labels": { + "actions": "Actions", + "changepassword": "Change Password", + "profileinfo": "Profile Info" + }, + "successess": { + "passwordchanged": "Password changed successfully. " + } + }, + "users": { + "errors": { + "signinerror": { + "auth/user-disabled": "User account disabled. ", + "auth/user-not-found": "A user with this email does not exist.", + "auth/wrong-password": "The email and password combination you provided is incorrect." + } + } + }, + "vehicles": { + "errors": { + "deleting": "Error deleting vehicle. {{error}}.", + "noaccess": "The vehicle does not exist or you do not have access to it.", + "selectexistingornew": "Select an existing vehicle record or create a new one. ", + "validation": "Please ensure all fields are entered correctly.", + "validationtitle": "Validation Error" + }, + "fields": { + "description": "Vehicle Description", + "notes": "Vehicle Notes", + "plate_no": "License Plate", + "plate_st": "Plate Jurisdiction", + "trim_color": "Trim Color", + "v_bstyle": "Body Style", + "v_color": "Color", + "v_cond": "Condition", + "v_engine": "Engine", + "v_make_desc": "Make", + "v_makecode": "Make Code", + "v_mldgcode": "Molding Code", + "v_model_desc": "Model", + "v_model_yr": "Year", + "v_options": "Options", + "v_paint_codes": "Paint Codes {{number}}", + "v_prod_dt": "Production Date", + "v_stage": "Stage", + "v_tone": "Tone", + "v_trimcode": "Trim Code", + "v_type": "Type", + "v_vin": "V.I.N." + }, + "forms": { + "detail": "Vehicle Details", + "misc": "Miscellaneous", + "registration": "Registration" + }, + "labels": { + "deleteconfirm": "Are you sure you want to delete this vehicle? This cannot be undone.", + "fromvehicle": "Historical Vehicle Record", + "novehinfo": "No Vehicle Information", + "relatedjobs": "Related Jobs", + "updatevehicle": "Update Vehicle Information" + }, + "successes": { + "delete": "Vehicle deleted successfully.", + "save": "Vehicle saved successfully." + } + }, + "vendors": { + "actions": { + "addtophonebook": "Add to Phonebook", + "new": "New Vendor", + "newpreferredmake": "New Preferred Make" + }, + "errors": { + "deleting": "Error encountered while deleting vendor. ", + "saving": "Error encountered while saving vendor. " + }, + "fields": { + "active": "Active", + "am": "Aftermarket", + "city": "City", + "cost_center": "Cost Center", + "country": "Country", + "discount": "Discount % (as decimal)", + "display_name": "Display Name", + "dmsid": "DMS ID", + "due_date": "Payment Due Date (# of days)", + "email": "Contact Email", + "favorite": "Favorite?", + "lkq": "LKQ", + "make": "Make", + "name": "Vendor Name", + "oem": "OEM", + "phone": "Phone", + "prompt_discount": "Prompt Discount %", + "state": "Province/State", + "street1": "Street", + "street2": "Address 2", + "taxid": "Tax ID", + "terms": "Payment Terms", + "zip": "Zip/Postal Code" + }, + "labels": { + "noneselected": "No vendor is selected.", + "preferredmakes": "Preferred Makes for Vendor", + "search": "Type a Vendor's Name" + }, + "successes": { + "deleted": "Vendor deleted successfully. ", + "saved": "Vendor saved successfully." + }, + "validation": { + "unique_vendor_name": "You must enter a unique vendor name." + } + }, "notifications": { "labels": { "notification-center": "Notification Center", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index be571cf12..6aa64961a 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1,3772 +1,3782 @@ { - "translation": { - "allocations": { - "actions": { - "assign": "Asignar" - }, - "errors": { - "deleting": "", - "saving": "", - "validation": "" - }, - "fields": { - "employee": "Asignado a" - }, - "successes": { - "deleted": "", - "save": "" - } - }, - "appointments": { - "actions": { - "block": "", - "calculate": "", - "cancel": "Cancelar", - "intake": "Consumo", - "new": "Nueva cita", - "preview": "", - "reschedule": "Reprogramar", - "sendreminder": "", - "unblock": "", - "viewjob": "Ver trabajo" - }, - "errors": { - "blocking": "", - "canceling": "Error al cancelar la cita. {{message}}", - "saving": "Error al programar la cita. {{message}}" - }, - "fields": { - "alt_transport": "", - "color": "", - "end": "", - "note": "", - "start": "", - "time": "", - "title": "Título" - }, - "labels": { - "arrivedon": "Llegado el:", - "arrivingjobs": "", - "blocked": "", - "cancelledappointment": "Cita cancelada para:", - "completingjobs": "", - "dataconsistency": "", - "expectedjobs": "", - "expectedprodhrs": "", - "history": "", - "inproduction": "", - "manualevent": "", - "noarrivingjobs": "", - "nocompletingjobs": "", - "nodateselected": "No se ha seleccionado ninguna fecha.", - "priorappointments": "Nombramientos previos", - "reminder": "", - "scheduledfor": "Cita programada para:", - "severalerrorsfound": "", - "smartscheduling": "", - "smspaymentreminder": "", - "suggesteddates": "" - }, - "successes": { - "canceled": "Cita cancelada con éxito.", - "created": "Cita programada con éxito.", - "saved": "" - } - }, - "associations": { - "actions": { - "activate": "Activar" - }, - "fields": { - "active": "¿Activo?", - "shopname": "Nombre de tienda" - }, - "labels": { - "actions": "Comportamiento" - } - }, - "audit": { - "fields": { - "cc": "", - "contents": "", - "created": "", - "operation": "", - "status": "", - "subject": "", - "to": "", - "useremail": "", - "values": "" - } - }, - "audit_trail": { - "messages": { - "admin_job_remove_from_ar": "", - "admin_jobmarkexported": "", - "admin_jobmarkforreexport": "", - "admin_jobuninvoice": "", - "admin_jobunvoid": "", - "alerttoggle": "", - "appointmentcancel": "", - "appointmentinsert": "", - "assignedlinehours": "", - "billdeleted": "", - "billposted": "", - "billupdated": "", - "failedpayment": "", - "jobassignmentchange": "", - "jobassignmentremoved": "", - "jobchecklist": "", - "jobclosedwithbypass": "", - "jobconverted": "", - "jobdelivery": "", - "jobexported": "", - "jobfieldchanged": "", - "jobimported": "", - "jobinproductionchange": "", - "jobintake": "", - "jobinvoiced": "", - "jobioucreated": "", - "jobmodifylbradj": "", - "jobnoteadded": "", - "jobnotedeleted": "", - "jobnoteupdated": "", - "jobspartsorder": "", - "jobspartsreturn": "", - "jobstatuschange": "", - "jobsupplement": "", - "jobsuspend": "", - "jobvoid": "", - "tasks_completed": "", - "tasks_created": "", - "tasks_deleted": "", - "tasks_uncompleted": "", - "tasks_undeleted": "", - "tasks_updated": "" - } - }, - "billlines": { - "actions": { - "newline": "" - }, - "fields": { - "actual_cost": "", - "actual_price": "", - "cost_center": "", - "federal_tax_applicable": "", - "jobline": "", - "line_desc": "", - "local_tax_applicable": "", - "location": "", - "quantity": "", - "state_tax_applicable": "" - }, - "labels": { - "deductedfromlbr": "", - "entered": "", - "from": "", - "mod_lbr_adjustment": "", - "other": "", - "reconciled": "", - "unreconciled": "" - }, - "validation": { - "atleastone": "" - } - }, - "bills": { - "actions": { - "deductallhours": "", - "edit": "", - "receive": "", - "return": "" - }, - "errors": { - "creating": "", - "deleting": "", - "existinginventoryline": "", - "exporting": "", - "exporting-partner": "", - "invalidro": "", - "invalidvendor": "", - "validation": "" - }, - "fields": { - "allpartslocation": "", - "date": "", - "exported": "", - "federal_tax_rate": "", - "invoice_number": "", - "is_credit_memo": "", - "is_credit_memo_short": "", - "local_tax_rate": "", - "ro_number": "", - "state_tax_rate": "", - "total": "", - "vendor": "", - "vendorname": "" - }, - "labels": { - "actions": "", - "bill_lines": "", - "bill_total": "", - "billcmtotal": "", - "bills": "", - "calculatedcreditsnotreceived": "", - "creditsnotreceived": "", - "creditsreceived": "", - "dedfromlbr": "", - "deleteconfirm": "", - "discrepancy": "", - "discrepwithcms": "", - "discrepwithlbradj": "", - "editadjwarning": "", - "entered_total": "", - "enteringcreditmemo": "", - "federal_tax": "", - "federal_tax_exempt": "", - "generatepartslabel": "", - "iouexists": "", - "local_tax": "", - "markexported": "", - "markforreexport": "", - "new": "", - "nobilllines": "", - "noneselected": "", - "onlycmforinvoiced": "", - "printlabels": "", - "retailtotal": "", - "returnfrombill": "", - "savewithdiscrepancy": "", - "state_tax": "", - "subtotal": "", - "totalreturns": "" - }, - "successes": { - "created": "", - "deleted": "", - "exported": "", - "markexported": "", - "reexport": "" - }, - "validation": { - "closingperiod": "", - "inventoryquantity": "", - "manualinhouse": "", - "unique_invoice_number": "" - } - }, - "bodyshop": { - "actions": { - "add_task_preset": "", - "addapptcolor": "", - "addbucket": "", - "addpartslocation": "", - "addpartsrule": "", - "addspeedprint": "", - "addtemplate": "", - "newlaborrate": "", - "newsalestaxcode": "", - "newstatus": "", - "testrender": "" - }, - "errors": { - "creatingdefaultview": "", - "loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.", - "saving": "" - }, - "fields": { - "ReceivableCustomField": "", - "address1": "", - "address2": "", - "appt_alt_transport": "", - "appt_colors": { - "color": "", - "label": "" - }, - "appt_length": "", - "attach_pdf_to_email": "", - "batchid": "", - "bill_allow_post_to_closed": "", - "bill_federal_tax_rate": "", - "bill_local_tax_rate": "", - "bill_state_tax_rate": "", - "city": "", - "closingperiod": "", - "companycode": "", - "country": "", - "dailybodytarget": "", - "dailypainttarget": "", - "default_adjustment_rate": "", - "deliver": { - "require_actual_delivery_date": "", - "templates": "" - }, - "dms": { - "apcontrol": "", - "appostingaccount": "", - "cashierid": "", - "default_journal": "", - "disablebillwip": "", - "disablecontactvehiclecreation": "", - "dms_acctnumber": "", - "dms_control_override": "", - "dms_wip_acctnumber": "", - "generic_customer_number": "", - "itc_federal": "", - "itc_local": "", - "itc_state": "", - "mappingname": "", - "sendmaterialscosting": "", - "srcco": "" - }, - "email": "", - "enforce_class": "", - "enforce_conversion_category": "", - "enforce_conversion_csr": "", - "enforce_referral": "", - "federal_tax_id": "", - "ignoreblockeddays": "", - "inhousevendorid": "", - "insurance_vendor_id": "", - "intake": { - "next_contact_hours": "", - "templates": "" - }, - "intellipay_config": { - "cash_discount_percentage": "", - "enable_cash_discount": "" - }, - "invoice_federal_tax_rate": "", - "invoice_local_tax_rate": "", - "invoice_state_tax_rate": "", - "jc_hourly_rates": { - "mapa": "", - "mash": "" - }, - "last_name_first": "", - "lastnumberworkingdays": "", - "localmediaserverhttp": "", - "localmediaservernetwork": "", - "localmediatoken": "", - "logo_img_footer_margin": "", - "logo_img_header_margin": "", - "logo_img_path": "", - "logo_img_path_height": "", - "logo_img_path_width": "", - "md_categories": "", - "md_ccc_rates": "", - "md_classes": "", - "md_ded_notes": "", - "md_email_cc": "", - "md_from_emails": "", - "md_functionality_toggles": { - "parts_queue_toggle": "" - }, - "md_hour_split": { - "paint": "", - "prep": "" - }, - "md_ins_co": { - "city": "", - "name": "", - "private": "", - "state": "", - "street1": "", - "street2": "", - "zip": "" - }, - "md_jobline_presets": "", - "md_lost_sale_reasons": "", - "md_parts_order_comment": "", - "md_parts_scan": { - "caseInsensitive": "", - "expression": "", - "field": "", - "flags": "", - "mark_critical": "", - "operation": "", - "update_field": "", - "update_value": "", - "value": "" - }, - "md_payment_types": "", - "md_referral_sources": "", - "md_ro_guard": { - "enabled": "", - "enforce_ar": "", - "enforce_bills": "", - "enforce_cm": "", - "enforce_labor": "", - "enforce_ppd": "", - "enforce_profit": "", - "enforce_sublet": "", - "masterbypass": "", - "totalgppercent_minimum": "" - }, - "md_tasks_presets": { - "enable_tasks": "", - "hourstype": "", - "memo": "", - "name": "", - "nextstatus": "", - "percent": "", - "use_approvals": "" - }, - "messaginglabel": "", - "messagingtext": "", - "noteslabel": "", - "notestext": "", - "partslocation": "", - "phone": "", - "prodtargethrs": "", - "rbac": { - "accounting": { - "exportlog": "", - "payables": "", - "payments": "", - "receivables": "" - }, - "bills": { - "delete": "", - "enter": "", - "list": "", - "reexport": "", - "view": "" - }, - "contracts": { - "create": "", - "detail": "", - "list": "" - }, - "courtesycar": { - "create": "", - "detail": "", - "list": "" - }, - "csi": { - "export": "", - "page": "" - }, - "employee_teams": { - "page": "" - }, - "employees": { - "page": "" - }, - "inventory": { - "delete": "", - "list": "" - }, - "jobs": { - "admin": "", - "available-list": "", - "checklist-view": "", - "close": "", - "create": "", - "deliver": "", - "detail": "", - "intake": "", - "list-active": "", - "list-all": "", - "list-ready": "", - "partsqueue": "", - "void": "" - }, - "owners": { - "detail": "", - "list": "" - }, - "payments": { - "enter": "", - "list": "" - }, - "phonebook": { - "edit": "", - "view": "" - }, - "production": { - "board": "", - "list": "" - }, - "schedule": { - "view": "" - }, - "scoreboard": { - "view": "" - }, - "shiftclock": { - "view": "" - }, - "shop": { - "config": "", - "dashboard": "", - "rbac": "", - "reportcenter": "", - "templates": "", - "vendors": "" - }, - "temporarydocs": { - "view": "" - }, - "timetickets": { - "edit": "", - "editcommitted": "", - "enter": "", - "list": "", - "shiftedit": "" - }, - "ttapprovals": { - "approve": "", - "view": "" - }, - "users": { - "editaccess": "" - } - }, - "responsibilitycenter": "", - "responsibilitycenter_accountdesc": "", - "responsibilitycenter_accountitem": "", - "responsibilitycenter_accountname": "", - "responsibilitycenter_accountnumber": "", - "responsibilitycenter_rate": "", - "responsibilitycenter_tax_rate": "", - "responsibilitycenter_tax_sur": "", - "responsibilitycenter_tax_thres": "", - "responsibilitycenter_tax_tier": "", - "responsibilitycenter_tax_type": "", - "responsibilitycenters": { - "ap": "", - "ar": "", - "ats": "", - "federal_tax": "", - "federal_tax_itc": "", - "gst_override": "", - "invoiceexemptcode": "", - "itemexemptcode": "", - "la1": "", - "la2": "", - "la3": "", - "la4": "", - "laa": "", - "lab": "", - "lad": "", - "lae": "", - "laf": "", - "lag": "", - "lam": "", - "lar": "", - "las": "", - "lau": "", - "local_tax": "", - "mapa": "", - "mash": "", - "paa": "", - "pac": "", - "pag": "", - "pal": "", - "pam": "", - "pan": "", - "pao": "", - "pap": "", - "par": "", - "pas": "", - "pasl": "", - "refund": "", - "sales_tax_codes": { - "code": "", - "description": "", - "federal": "", - "local": "", - "state": "" - }, - "state_tax": "", - "tow": "" - }, - "schedule_end_time": "", - "schedule_start_time": "", - "shopname": "", - "speedprint": { - "id": "", - "label": "", - "templates": "" - }, - "ss_configuration": { - "dailyhrslimit": "" - }, - "ssbuckets": { - "color": "", - "gte": "", - "id": "", - "label": "", - "lt": "", - "target": "" - }, - "state": "", - "state_tax_id": "", - "status": "", - "statuses": { - "active_statuses": "", - "additional_board_statuses": "", - "color": "", - "default_arrived": "", - "default_bo": "", - "default_canceled": "", - "default_completed": "", - "default_delivered": "", - "default_exported": "", - "default_imported": "", - "default_invoiced": "", - "default_ordered": "", - "default_quote": "", - "default_received": "", - "default_returned": "", - "default_scheduled": "", - "default_void": "", - "open_statuses": "", - "post_production_statuses": "", - "pre_production_statuses": "", - "production_colors": "", - "production_statuses": "", - "ready_statuses": "" - }, - "target_touchtime": "", - "timezone": "", - "tt_allow_post_to_invoiced": "", - "tt_enforce_hours_for_tech_console": "", - "use_fippa": "", - "use_paint_scale_data": "", - "uselocalmediaserver": "", - "website": "", - "zip_post": "" - }, - "labels": { - "2tiername": "", - "2tiersetup": "", - "2tiersource": "", - "accountingsetup": "", - "accountingtiers": "", - "alljobstatuses": "", - "allopenjobstatuses": "", - "apptcolors": "", - "businessinformation": "", - "checklists": "", - "csiq": "", - "customtemplates": "", - "defaultcostsmapping": "", - "defaultprofitsmapping": "", - "deliverchecklist": "", - "dms": { - "cdk": { - "controllist": "", - "payers": "" - }, - "cdk_dealerid": "", - "costsmapping": "", - "dms_allocations": "", - "pbs_serialnumber": "", - "profitsmapping": "", - "title": "" - }, - "emaillater": "", - "employee_teams": "", - "employees": "", - "estimators": "", - "filehandlers": "", - "imexpay": "", - "insurancecos": "", - "intakechecklist": "", - "intellipay_cash_discount": "", - "jobstatuses": "", - "laborrates": "", - "licensing": "", - "md_parts_scan": "", - "md_ro_guard": "", - "md_tasks_presets": "", - "md_to_emails": "", - "md_to_emails_emails": "", - "messagingpresets": "", - "notemplatesavailable": "", - "notespresets": "", - "orderstatuses": "", - "partslocations": "", - "partsscan": "", - "printlater": "", - "qbo": "", - "qbo_departmentid": "", - "qbo_usa": "", - "rbac": "", - "responsibilitycenters": { - "costs": "", - "profits": "", - "sales_tax_codes": "", - "tax_accounts": "", - "title": "", - "ttl_adjustment": "", - "ttl_tax_adjustment": "" - }, - "roguard": { - "title": "" - }, - "romepay": "", - "scheduling": "", - "scoreboardsetup": "", - "shop_enabled_features": "", - "shopinfo": "", - "speedprint": "", - "ssbuckets": "", - "systemsettings": "", - "task-presets": "", - "workingdays": "" - }, - "operations": { - "contains": "", - "ends_with": "", - "equals": "", - "greater_than": "", - "less_than": "", - "not_equals": "", - "starts_with": "" - }, - "successes": { - "areyousure": "", - "defaultviewcreated": "", - "save": "", - "unsavedchanges": "" - }, - "tooltips": { - "md_parts_scan": { - "update_value_tooltip": "" - } - }, - "validation": { - "centermustexist": "", - "larsplit": "", - "useremailmustexist": "" - } - }, - "checklist": { - "actions": { - "printall": "" - }, - "errors": { - "complete": "", - "nochecklist": "" - }, - "labels": { - "addtoproduction": "", - "allow_text_message": "", - "checklist": "", - "printpack": "", - "removefromproduction": "" - }, - "successes": { - "completed": "" - } - }, - "contracts": { - "actions": { - "changerate": "", - "convertoro": "", - "decodelicense": "", - "find": "", - "printcontract": "", - "senddltoform": "" - }, - "errors": { - "fetchingjobinfo": "", - "returning": "", - "saving": "", - "selectjobandcar": "" - }, - "fields": { - "actax": "", - "actualreturn": "", - "agreementnumber": "", - "cc_cardholder": "", - "cc_expiry": "", - "cc_num": "", - "cleanupcharge": "", - "coverage": "", - "dailyfreekm": "", - "dailyrate": "", - "damage": "", - "damagewaiver": "", - "driver": "", - "driver_addr1": "", - "driver_addr2": "", - "driver_city": "", - "driver_dlexpiry": "", - "driver_dlnumber": "", - "driver_dlst": "", - "driver_dob": "", - "driver_fn": "", - "driver_ln": "", - "driver_ph1": "", - "driver_state": "", - "driver_zip": "", - "excesskmrate": "", - "federaltax": "", - "fuelin": "", - "fuelout": "", - "kmend": "", - "kmstart": "", - "length": "", - "localtax": "", - "refuelcharge": "", - "scheduledreturn": "", - "start": " ", - "statetax": "", - "status": "" - }, - "labels": { - "agreement": "", - "availablecars": "", - "cardueforservice": "", - "convertform": { - "applycleanupcharge": "", - "refuelqty": "" - }, - "correctdataonform": "", - "dateinpast": "", - "dlexpirebeforereturn": "", - "driverinformation": "", - "findcontract": "", - "findermodal": "", - "insuranceexpired": "", - "noteconvertedfrom": "", - "populatefromjob": "", - "rates": "", - "time": "", - "vehicle": "", - "waitingforscan": "" - }, - "status": { - "new": "", - "out": "", - "returned": "" - }, - "successes": { - "saved": "" - } - }, - "courtesycars": { - "actions": { - "new": "", - "return": "" - }, - "errors": { - "saving": "" - }, - "fields": { - "color": "", - "dailycost": "", - "damage": "", - "fleetnumber": "", - "fuel": "", - "insuranceexpires": "", - "leaseenddate": "", - "make": "", - "mileage": "", - "model": "", - "nextservicedate": "", - "nextservicekm": "", - "notes": "", - "plate": "", - "purchasedate": "", - "readiness": "", - "registrationexpires": "", - "serviceenddate": "", - "servicestartdate": "", - "status": "", - "vin": "", - "year": "" - }, - "labels": { - "courtesycar": "", - "fuel": { - "12": "", - "14": "", - "18": "", - "34": "", - "38": "", - "58": "", - "78": "", - "empty": "", - "full": "" - }, - "outwith": "", - "return": "", - "status": "", - "uniquefleet": "", - "usage": "", - "vehicle": "" - }, - "readiness": { - "notready": "", - "ready": "" - }, - "status": { - "in": "", - "inservice": "", - "leasereturn": "", - "out": "", - "sold": "", - "unavailable": "" - }, - "successes": { - "saved": "" - } - }, - "csi": { - "actions": { - "activate": "" - }, - "errors": { - "creating": "", - "notconfigured": "", - "notfoundsubtitle": "", - "notfoundtitle": "", - "surveycompletesubtitle": "", - "surveycompletetitle": "" - }, - "fields": { - "completedon": "", - "created_at": "", - "surveyid": "", - "validuntil": "" - }, - "labels": { - "copyright": "", - "greeting": "", - "intro": "", - "nologgedinuser": "", - "nologgedinuser_sub": "", - "noneselected": "", - "title": "" - }, - "successes": { - "created": "", - "submitted": "", - "submittedsub": "" - } - }, - "dashboard": { - "actions": { - "addcomponent": "" - }, - "errors": { - "refreshrequired": "", - "updatinglayout": "" - }, - "labels": { - "bodyhrs": "", - "dollarsinproduction": "", - "phone": "", - "prodhrs": "", - "refhrs": "" - }, - "titles": { - "joblifecycle": "", - "labhours": "", - "larhours": "", - "monthlyemployeeefficiency": "", - "monthlyjobcosting": "", - "monthlylaborsales": "", - "monthlypartssales": "", - "monthlyrevenuegraph": "", - "prodhrssummary": "", - "productiondollars": "", - "productionhours": "", - "projectedmonthlysales": "", - "scheduledindate": "", - "scheduledintoday": "", - "scheduledoutdate": "", - "scheduledouttoday": "", - "tasks": "" - } - }, - "dms": { - "errors": { - "alreadyexported": "" - }, - "labels": { - "refreshallocations": "" - } - }, - "documents": { - "actions": { - "delete": "", - "download": "", - "reassign": "", - "selectallimages": "", - "selectallotherdocuments": "" - }, - "errors": { - "deletes3": "Error al eliminar el documento del almacenamiento.", - "deleting": "", - "deleting_cloudinary": "", - "getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}", - "insert": "Incapaz de cargar el archivo. {{message}}", - "nodocuments": "No hay documentos", - "updating": "" - }, - "labels": { - "confirmdelete": "", - "doctype": "", - "dragtoupload": "", - "newjobid": "", - "openinexplorer": "", - "optimizedimage": "", - "reassign_limitexceeded": "", - "reassign_limitexceeded_title": "", - "storageexceeded": "", - "storageexceeded_title": "", - "upload": "Subir", - "upload_limitexceeded": "", - "upload_limitexceeded_title": "", - "uploading": "", - "usage": "" - }, - "successes": { - "delete": "Documento eliminado con éxito.", - "edituploaded": "", - "insert": "Documento cargado con éxito.", - "updated": "" - } - }, - "emails": { - "errors": { - "notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}" - }, - "fields": { - "cc": "", - "from": "", - "subject": "", - "to": "" - }, - "labels": { - "attachments": "", - "documents": "", - "emailpreview": "", - "generatingemail": "", - "pdfcopywillbeattached": "", - "preview": "" - }, - "successes": { - "sent": "Correo electrónico enviado con éxito." - } - }, - "employee_teams": { - "actions": { - "new": "", - "newmember": "" - }, - "fields": { - "active": "", - "employeeid": "", - "max_load": "", - "name": "", - "percentage": "" - } - }, - "employees": { - "actions": { - "addvacation": "", - "new": "Nuevo empleado", - "newrate": "" - }, - "errors": { - "delete": "Se encontró un error al eliminar al empleado. {{message}}", - "save": "Se encontró un error al salvar al empleado. {{message}}", - "validation": "Por favor verifique todos los campos.", - "validationtitle": "No se puede salvar al empleado." - }, - "fields": { - "active": "¿Activo?", - "base_rate": "Tasa básica", - "cost_center": "Centro de costos", - "employee_number": "Numero de empleado", - "external_id": "", - "first_name": "Nombre de pila", - "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)", - "hire_date": "Fecha de contratación", - "last_name": "Apellido", - "pin": "", - "rate": "", - "termination_date": "Fecha de conclusión", - "user_email": "", - "vacation": { - "end": "", - "length": "", - "start": "" - } - }, - "labels": { - "actions": "", - "active": "", - "endmustbeafterstart": "", - "flat_rate": "", - "inactive": "", - "name": "", - "rate_type": "", - "status": "", - "straight_time": "" - }, - "successes": { - "delete": "Empleado eliminado con éxito.", - "save": "Empleado guardado con éxito.", - "vacationadded": "" - }, - "validation": { - "unique_employee_number": "" - } - }, - "eula": { - "buttons": { - "accept": "Accept EULA" - }, - "content": { - "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." - }, - "errors": { - "acceptance": { - "description": "Something went wrong while accepting the EULA. Please try again.", - "message": "Eula Acceptance Error" - } - }, - "labels": { - "accepted_terms": "I accept the terms and conditions of this agreement.", - "address": "Address", - "business_name": "Legal Business Name", - "date_accepted": "Date Accepted", - "first_name": "First Name", - "last_name": "Last Name", - "phone_number": "Phone Number" - }, - "messages": { - "accepted_terms": "Please accept the terms and conditions of this agreement.", - "business_name": "Please enter your legal business name.", - "date_accepted": "Please enter Today's Date.", - "first_name": "Please enter your first name.", - "last_name": "Please enter your last name.", - "phone_number": "Please enter your phone number." - }, - "titles": { - "modal": "Terms and Conditions", - "upper_card": "Acknowledgement" - } - }, - "exportlogs": { - "fields": { - "createdat": "" - }, - "labels": { - "attempts": "", - "priorsuccesfulexport": "" - } - }, - "general": { - "actions": { - "add": "", - "autoupdate": "", - "calculate": "", - "cancel": "", - "clear": "", - "close": "", - "copied": "", - "copylink": "", - "create": "", - "defaults": "defaults", - "delay": "", - "delete": "Borrar", - "deleteall": "", - "deselectall": "", - "download": "", - "edit": "Editar", - "login": "", - "next": "", - "ok": "", - "previous": "", - "print": "", - "refresh": "", - "remove": "", - "remove_alert": "", - "reset": " Restablecer a original.", - "resetpassword": "", - "save": "Salvar", - "saveandnew": "", - "saveas": "", - "selectall": "", - "send": "", - "sendbysms": "", - "senderrortosupport": "", - "sharetoteams": "", - "submit": "", - "tryagain": "", - "view": "", - "viewreleasenotes": "" - }, - "errors": { - "fcm": "", - "notfound": "", - "sizelimit": "" - }, - "itemtypes": { - "contract": "", - "courtesycar": "", - "job": "", - "owner": "", - "vehicle": "" - }, - "labels": { - "actions": "Comportamiento", - "areyousure": "", - "barcode": "código de barras", - "cancel": "", - "clear": "", - "confirmpassword": "", - "created_at": "", - "date": "", - "datetime": "", - "email": "", - "errors": "", - "excel": "", - "exceptiontitle": "", - "friday": "", - "globalsearch": "", - "help": "", - "hours": "", - "in": "en", - "instanceconflictext": "", - "instanceconflictitle": "", - "item": "", - "label": "", - "loading": "Cargando...", - "loadingapp": "Cargando {{app}}", - "loadingshop": "Cargando datos de la tienda ...", - "loggingin": "Iniciando sesión ...", - "markedexported": "", - "media": "", - "message": "", - "monday": "", - "na": "N / A", - "newpassword": "", - "no": "", - "nointernet": "", - "nointernet_sub": "", - "none": "", - "out": "Afuera", - "password": "", - "passwordresetsuccess": "", - "passwordresetsuccess_sub": "", - "passwordresetvalidatesuccess": "", - "passwordresetvalidatesuccess_sub": "", - "passwordsdonotmatch": "", - "print": "", - "refresh": "", - "reports": "", - "required": "", - "saturday": "", - "search": "Buscar...", - "searchresults": "", - "selectdate": "", - "sendagain": "", - "sendby": "", - "signin": "", - "sms": "", - "status": "", - "sub_status": { - "expired": "" - }, - "successful": "", - "sunday": "", - "text": "", - "thursday": "", - "time": "", - "total": "", - "totals": "", - "tuesday": "", - "tvmode": "", - "unknown": "Desconocido", - "unsavedchanges": "", - "username": "", - "view": "", - "wednesday": "", - "yes": "" - }, - "languages": { - "english": "Inglés", - "french": "francés", - "spanish": "español" - }, - "messages": { - "exception": "", - "newversionmessage": "", - "newversiontitle": "", - "noacctfilepath": "", - "nofeatureaccess": "", - "noshop": "", - "notfoundsub": "", - "notfoundtitle": "", - "partnernotrunning": "", - "rbacunauth": "", - "unsavedchanges": "Usted tiene cambios no guardados.", - "unsavedchangespopup": "" - }, - "validation": { - "dateRangeExceeded": "", - "invalidemail": "Por favor introduzca una dirección de correo electrónico válida.", - "invalidphone": "", - "required": "Este campo es requerido." - } - }, - "help": { - "actions": { - "connect": "" - }, - "labels": { - "codeplacholder": "", - "rescuedesc": "", - "rescuetitle": "" - } - }, - "intake": { - "labels": { - "printpack": "" - } - }, - "inventory": { - "actions": { - "addtoinventory": "", - "addtoro": "", - "consumefrominventory": "", - "edit": "", - "new": "" - }, - "errors": { - "inserting": "" - }, - "fields": { - "comment": "", - "manualinvoicenumber": "", - "manualvendor": "" - }, - "labels": { - "consumedbyjob": "", - "deleteconfirm": "", - "frombillinvoicenumber": "", - "fromvendor": "", - "inventory": "", - "showall": "", - "showavailable": "" - }, - "successes": { - "deleted": "", - "inserted": "", - "updated": "" - } - }, - "job_lifecycle": { - "columns": { - "average_human_readable": "", - "average_value": "", - "duration": "", - "end": "", - "human_readable": "", - "percentage": "", - "relative_end": "", - "relative_start": "", - "start": "", - "status": "", - "status_count": "", - "value": "" - }, - "content": { - "calculated_based_on": "", - "current_status_accumulated_time": "", - "data_unavailable": "", - "jobs_in_since": "", - "legend_title": "", - "loading": "", - "not_available": "", - "previous_status_accumulated_time": "", - "title": "", - "title_durations": "", - "title_loading": "", - "title_transitions": "" - }, - "errors": { - "fetch": "Error al obtener los datos del ciclo de vida del trabajo" - }, - "titles": { - "dashboard": "", - "top_durations": "" - } - }, - "job_payments": { - "buttons": { - "create_short_link": "", - "goback": "", - "proceedtopayment": "", - "refundpayment": "" - }, - "notifications": { - "error": { - "description": "", - "openingip": "", - "title": "" - } - }, - "titles": { - "amount": "", - "dateOfPayment": "", - "descriptions": "", - "hint": "", - "payer": "", - "payername": "", - "paymentid": "", - "paymentnum": "", - "paymenttype": "", - "refundamount": "", - "transactionid": "" - } - }, - "joblines": { - "actions": { - "assign_team": "", - "converttolabor": "", - "dispatchparts": "", - "new": "" - }, - "errors": { - "creating": "", - "updating": "" - }, - "fields": { - "act_price": "Precio actual", - "act_price_before_ppc": "", - "adjustment": "", - "ah_detail_line": "", - "alt_partno": "", - "amount": "", - "assigned_team": "", - "assigned_team_name": "", - "create_ppc": "", - "db_price": "Precio de base de datos", - "include_in_part_cnt": "", - "lbr_types": { - "LA1": "", - "LA2": "", - "LA3": "", - "LA4": "", - "LAA": "", - "LAB": "", - "LAD": "", - "LAE": "", - "LAF": "", - "LAG": "", - "LAM": "", - "LAR": "", - "LAS": "", - "LAU": "" - }, - "line_desc": "Descripción de línea", - "line_ind": "S#", - "line_no": "", - "location": "", - "mod_lb_hrs": "Horas laborales", - "mod_lbr_ty": "Tipo de trabajo", - "notes": "", - "oem_partno": "OEM parte #", - "op_code_desc": "", - "part_qty": "", - "part_type": "Tipo de parte", - "part_types": { - "CCC": "", - "CCD": "", - "CCDR": "", - "CCF": "", - "CCM": "", - "PAA": "", - "PAC": "", - "PAE": "", - "PAG": "", - "PAL": "", - "PAM": "", - "PAN": "", - "PAO": "", - "PAP": "", - "PAR": "", - "PAS": "", - "PASL": "" - }, - "profitcenter_labor": "", - "profitcenter_part": "", - "prt_dsmk_m": "", - "prt_dsmk_p": "", - "status": "Estado", - "tax_part": "", - "total": "", - "unq_seq": "Seq #" - }, - "labels": { - "adjustmenttobeadded": "", - "billref": "", - "convertedtolabor": "", - "edit": "Línea de edición", - "ioucreated": "", - "new": "Nueva línea", - "nostatus": "", - "presets": "" - }, - "successes": { - "created": "", - "saved": "", - "updated": "" - }, - "validations": { - "ahdetailonlyonuserdefinedtypes": "", - "hrsrequirediflbrtyp": "", - "requiredifparttype": "", - "zeropriceexistingpart": "" - } - }, - "jobs": { - "actions": { - "addDocuments": "Agregar documentos de trabajo", - "addNote": "Añadir la nota", - "addtopartsqueue": "", - "addtoproduction": "", - "addtoscoreboard": "", - "allocate": "", - "autoallocate": "", - "changefilehandler": "", - "changelaborrate": "", - "changestatus": "Cambiar Estado", - "changestimator": "", - "convert": "Convertir", - "createiou": "", - "deliver": "", - "deliver_quick": "", - "dms": { - "addpayer": "", - "createnewcustomer": "", - "findmakemodelcode": "", - "getmakes": "", - "labels": { - "refreshallocations": "" - }, - "post": "", - "refetchmakesmodels": "", - "usegeneric": "", - "useselected": "" - }, - "dmsautoallocate": "", - "export": "", - "exportcustdata": "", - "exportselected": "", - "filterpartsonly": "", - "generatecsi": "", - "gotojob": "", - "intake": "", - "intake_quick": "", - "manualnew": "", - "mark": "", - "markasexported": "", - "markpstexempt": "", - "markpstexemptconfirm": "", - "postbills": "Contabilizar facturas", - "printCenter": "Centro de impresión", - "recalculate": "", - "reconcile": "", - "removefromproduction": "", - "schedule": "Programar", - "sendcsi": "", - "sendpartspricechange": "", - "sendtodms": "", - "sync": "", - "taxprofileoverride": "", - "taxprofileoverride_confirm": "", - "uninvoice": "", - "unvoid": "", - "viewchecklist": "", - "viewdetail": "" - }, - "errors": { - "addingtoproduction": "", - "cannotintake": "", - "closing": "", - "creating": "", - "deleted": "Error al eliminar el trabajo.", - "exporting": "", - "exporting-partner": "", - "invoicing": "", - "noaccess": "Este trabajo no existe o no tiene acceso a él.", - "nodamage": "", - "nodates": "No hay fechas especificadas para este trabajo.", - "nofinancial": "", - "nojobselected": "No hay trabajo seleccionado.", - "noowner": "Ningún propietario asociado.", - "novehicle": "No hay vehículo asociado.", - "partspricechange": "", - "saving": "Se encontró un error al guardar el registro.", - "scanimport": "", - "totalscalc": "", - "updating": "", - "validation": "Asegúrese de que todos los campos se ingresen correctamente.", - "validationtitle": "Error de validacion", - "voiding": "" - }, - "fields": { - "active_tasks": "", - "actual_completion": "Realización real", - "actual_delivery": "Entrega real", - "actual_in": "Real en", - "adjustment_bottom_line": "Ajustes", - "adjustmenthours": "", - "alt_transport": "", - "area_of_damage_impact": { - "10": "", - "11": "", - "12": "", - "13": "", - "14": "", - "15": "", - "16": "", - "25": "", - "26": "", - "27": "", - "28": "", - "34": "", - "01": "", - "02": "", - "03": "", - "04": "", - "05": "", - "06": "", - "07": "", - "08": "", - "09": "" - }, - "auto_add_ats": "", - "ca_bc_pvrt": "", - "ca_customer_gst": "", - "ca_gst_registrant": "", - "category": "", - "ccc": "", - "ccd": "", - "ccdr": "", - "ccf": "", - "ccm": "", - "cieca_id": "CIECA ID", - "cieca_pfl": { - "lbr_adjp": "", - "lbr_tax_in": "", - "lbr_taxp": "", - "lbr_tx_in1": "", - "lbr_tx_in2": "", - "lbr_tx_in3": "", - "lbr_tx_in4": "", - "lbr_tx_in5": "" - }, - "cieca_pfo": { - "stor_t_in1": "", - "stor_t_in2": "", - "stor_t_in3": "", - "stor_t_in4": "", - "stor_t_in5": "", - "tow_t_in1": "", - "tow_t_in2": "", - "tow_t_in3": "", - "tow_t_in4": "", - "tow_t_in5": "" - }, - "claim_total": "Reclamar total", - "class": "", - "clm_no": "Reclamación #", - "clm_total": "Reclamar total", - "comment": "", - "customerowing": "Cliente debido", - "date_estimated": "Fecha estimada", - "date_exported": "Exportado", - "date_invoiced": "Facturado", - "date_last_contacted": "", - "date_lost_sale": "", - "date_next_contact": "", - "date_open": "Abierto", - "date_rentalresp": "", - "date_repairstarted": "", - "date_scheduled": "Programado", - "date_towin": "", - "date_void": "", - "ded_amt": "Deducible", - "ded_note": "", - "ded_status": "Estado deducible", - "depreciation_taxes": "Depreciación / Impuestos", - "dms": { - "address": "", - "amount": "", - "center": "", - "control_type": { - "account_number": "" - }, - "cost": "", - "cost_dms_acctnumber": "", - "dms_make": "", - "dms_model": "", - "dms_model_override": "", - "dms_unsold": "", - "dms_wip_acctnumber": "", - "id": "", - "inservicedate": "", - "journal": "", - "lines": "", - "name1": "", - "payer": { - "amount": "", - "control_type": "", - "controlnumber": "", - "dms_acctnumber": "", - "name": "" - }, - "sale": "", - "sale_dms_acctnumber": "", - "story": "", - "vinowner": "" - }, - "dms_allocation": "", - "driveable": "", - "employee_body": "", - "employee_csr": "Representante de servicio al cliente.", - "employee_csr_writer": "", - "employee_prep": "", - "employee_refinish": "", - "est_addr1": "Dirección del tasador", - "est_co_nm": "Tasador", - "est_ct_fn": "Nombre del tasador", - "est_ct_ln": "Apellido del tasador", - "est_ea": "Correo electrónico del tasador", - "est_ph1": "Número de teléfono del tasador", - "federal_tax_payable": "Impuesto federal por pagar", - "federal_tax_rate": "", - "ins_addr1": "Dirección de Insurance Co.", - "ins_city": "Ciudad de seguros", - "ins_co_id": "ID de la compañía de seguros", - "ins_co_nm": "Nombre de la compañía de seguros", - "ins_co_nm_short": "", - "ins_ct_fn": "Nombre del controlador de archivos", - "ins_ct_ln": "Apellido del manejador de archivos", - "ins_ea": "Correo electrónico del controlador de archivos", - "ins_ph1": "File Handler Phone #", - "intake": { - "label": "", - "max": "", - "min": "", - "name": "", - "required": "", - "type": "" - }, - "invoice_final_note": "", - "kmin": "Kilometraje en", - "kmout": "Kilometraje", - "la1": "", - "la2": "", - "la3": "", - "la4": "", - "laa": "", - "lab": "", - "labor_rate_desc": "Nombre de la tasa laboral", - "lad": "", - "lae": "", - "laf": "", - "lag": "", - "lam": "", - "lar": "", - "las": "", - "lau": "", - "local_tax_rate": "", - "loss_date": "Fecha de pérdida", - "loss_desc": "", - "loss_of_use": "", - "lost_sale_reason": "", - "ma2s": "", - "ma3s": "", - "mabl": "", - "macs": "", - "mahw": "", - "mapa": "", - "mash": "", - "matd": "", - "materials": { - "MAPA": "", - "MASH": "", - "cal_maxdlr": "", - "cal_opcode": "", - "mat_adjp": "", - "mat_taxp": "", - "mat_tx_in1": "", - "mat_tx_in2": "", - "mat_tx_in3": "", - "mat_tx_in4": "", - "mat_tx_in5": "", - "materials": "", - "tax_ind": "" - }, - "other_amount_payable": "Otra cantidad a pagar", - "owner": "Propietario", - "owner_owing": "Cust. Debe", - "ownr_ea": "Email", - "ownr_ph1": "Teléfono 1", - "ownr_ph2": "", - "paa": "", - "pac": "", - "pae": "", - "pag": "", - "pal": "", - "pam": "", - "pan": "", - "pao": "", - "pap": "", - "par": "", - "parts_tax_rates": { - "prt_discp": "", - "prt_mktyp": "", - "prt_mkupp": "", - "prt_tax_in": "", - "prt_tax_rt": "", - "prt_tx_in1": "", - "prt_tx_in2": "", - "prt_tx_in3": "", - "prt_tx_in4": "", - "prt_tx_in5": "", - "prt_tx_ty1": "", - "prt_type": "" - }, - "partsstatus": "", - "pas": "", - "pay_date": "Fecha de Pay", - "phoneshort": "PH", - "po_number": "", - "policy_no": "Política #", - "ponumber": "numero postal", - "production_vars": { - "note": "" - }, - "qb_multiple_payers": { - "amount": "", - "name": "" - }, - "queued_for_parts": "", - "rate_ats": "", - "rate_la1": "Tarifa LA1", - "rate_la2": "Tarifa LA2", - "rate_la3": "Tarifa LA3", - "rate_la4": "Tarifa LA4", - "rate_laa": "Tasa de aluminio", - "rate_lab": "Tasa de trabajo", - "rate_lad": "Tasa de diagnóstico", - "rate_lae": "tarifa eléctrica", - "rate_laf": "Cuadros por segundo", - "rate_lag": "Tasa de vidrio", - "rate_lam": "Tasa mecánica", - "rate_lar": "Tasa de acabado", - "rate_las": "", - "rate_lau": "", - "rate_ma2s": "Velocidad de pintura de 2 etapas", - "rate_ma3s": "Tasa de pintura de 3 etapas", - "rate_mabl": "MABL ??", - "rate_macs": "MACS ??", - "rate_mahw": "Tasa de residuos peligrosos", - "rate_mapa": "Tasa de materiales de pintura", - "rate_mash": "Comprar material de tarifa", - "rate_matd": "Tasa de eliminación de neumáticos", - "referral_source_extra": "", - "referral_source_other": "", - "referralsource": "Fuente de referencia", - "regie_number": "N. ° de registro", - "repairtotal": "Reparación total", - "ro_number": "RO #", - "scheduled_completion": "Finalización programada", - "scheduled_delivery": "Entrega programada", - "scheduled_in": "Programado en", - "selling_dealer": "Distribuidor vendedor", - "selling_dealer_contact": "Contacto con el vendedor", - "servicecar": "Auto de servicio", - "servicing_dealer": "Distribuidor de servicio", - "servicing_dealer_contact": "Servicio Contacto con el concesionario", - "special_coverage_policy": "Política de cobertura especial", - "specialcoveragepolicy": "Política de cobertura especial", - "state_tax_rate": "", - "status": "Estado del trabajo", - "storage_payable": "Almacenamiento ", - "tax_lbr_rt": "", - "tax_levies_rt": "", - "tax_paint_mat_rt": "", - "tax_registration_number": "", - "tax_shop_mat_rt": "", - "tax_str_rt": "", - "tax_sub_rt": "", - "tax_tow_rt": "", - "tlos_ind": "", - "towin": "", - "towing_payable": "Remolque a pagar", - "unitnumber": "Unidad #", - "updated_at": "Actualizado en", - "uploaded_by": "Subido por", - "vehicle": "Vehículo" - }, - "forms": { - "admindates": "", - "appraiserinfo": "", - "claiminfo": "", - "estdates": "", - "laborrates": "", - "lossinfo": "", - "other": "", - "repairdates": "", - "scheddates": "" - }, - "labels": { - "accountsreceivable": "", - "act_price_ppc": "", - "actual_completion_inferred": "", - "actual_delivery_inferred": "", - "actual_in_inferred": "", - "additionalpayeroverallocation": "", - "additionaltotal": "", - "adjustmentrate": "", - "adjustments": "", - "adminwarning": "", - "allocations": "", - "alreadyaddedtoscoreboard": "", - "alreadyclosed": "", - "appointmentconfirmation": "¿Enviar confirmación al cliente?", - "associationwarning": "", - "audit": "", - "available": "", - "availablejobs": "", - "ca_bc_pvrt": { - "days": "", - "rate": "" - }, - "ca_gst_all_if_null": "", - "calc_repair_days": "", - "calc_repair_days_tt": "", - "calc_scheuled_completion": "", - "cards": { - "customer": "Información al cliente", - "damage": "Área de Daño", - "dates": "fechas", - "documents": "Documentos recientes", - "estimator": "Estimador", - "filehandler": "File Handler", - "insurance": "detalles del seguro", - "more": "Más", - "notes": "Notas", - "parts": "Partes", - "totals": "Totales", - "vehicle": "Vehículo" - }, - "changeclass": "", - "checklistcompletedby": "", - "checklistdocuments": "", - "checklists": "", - "cieca_pfl": "", - "cieca_pfo": "", - "cieca_pft": "", - "closeconfirm": "", - "closejob": "", - "closingperiod": "", - "contracts": "", - "convertedtolabor": "", - "cost": "", - "cost_Additional": "", - "cost_labor": "", - "cost_parts": "", - "cost_sublet": "", - "costs": "", - "create": { - "jobinfo": "", - "newowner": "", - "newvehicle": "", - "novehicle": "", - "ownerinfo": "", - "vehicleinfo": "" - }, - "createiouwarning": "", - "creating_new_job": "Creando nuevo trabajo ...", - "deductible": { - "stands": "", - "waived": "" - }, - "deleteconfirm": "", - "deletedelivery": "", - "deleteintake": "", - "deliverchecklist": "", - "difference": "", - "diskscan": "", - "dms": { - "apexported": "", - "damageto": "", - "defaultstory": "", - "disablebillwip": "", - "invoicedatefuture": "", - "kmoutnotgreaterthankmin": "", - "logs": "", - "notallocated": "", - "postingform": "", - "totalallocated": "" - }, - "documents": "documentos", - "documents-images": "", - "documents-other": "", - "duplicateconfirm": "", - "emailaudit": "", - "employeeassignments": "", - "estimatelines": "", - "estimator": "", - "existing_jobs": "Empleos existentes", - "federal_tax_amt": "", - "gpdollars": "", - "gppercent": "", - "hrs_claimed": "", - "hrs_total": "", - "importnote": "", - "inproduction": "", - "intakechecklist": "", - "iou": "", - "job": "", - "jobcosting": "", - "jobtotals": "", - "labor_hrs": "", - "labor_rates_subtotal": "", - "laborallocations": "", - "labortotals": "", - "lines": "Líneas estimadas", - "local_tax_amt": "", - "mapa": "", - "markforreexport": "", - "mash": "", - "masterbypass": "", - "materials": { - "mapa": "" - }, - "missingprofileinfo": "", - "multipayers": "", - "net_repairs": "", - "notes": "Notas", - "othertotal": "", - "outstanding_ar": "", - "outstanding_credit_memos": "", - "outstanding_ppd": "", - "outstanding_reconciliation_discrep": "", - "outstanding_sublets": "", - "outstandinghours": "", - "override_header": "¿Anular encabezado estimado al importar?", - "ownerassociation": "", - "parts": "Partes", - "parts_lines": "", - "parts_received": "", - "parts_tax_rates": "", - "partsfilter": "", - "partssubletstotal": "", - "partstotal": "", - "performance": "", - "pimraryamountpayable": "", - "plitooltips": { - "billtotal": "", - "calculatedcreditsnotreceived": "", - "creditmemos": "", - "creditsnotreceived": "", - "discrep1": "", - "discrep2": "", - "discrep3": "", - "laboradj": "", - "partstotal": "", - "totalreturns": "" - }, - "ppc": "", - "ppdnotexported": "", - "profileadjustments": "", - "profitbypassrequired": "", - "profits": "", - "prt_dsmk_total": "", - "rates": "Tarifas", - "rates_subtotal": "", - "reconciliation": { - "billlinestotal": "", - "byassoc": "", - "byprice": "", - "clear": "", - "discrepancy": "", - "joblinestotal": "", - "multipleactprices": "", - "multiplebilllines": "", - "multiplebillsforactprice": "", - "removedpartsstrikethrough": "" - }, - "reconciliationheader": "", - "relatedros": "", - "remove_from_ar": "", - "returntotals": "", - "ro_guard": { - "enforce_ar": "", - "enforce_bills": "", - "enforce_cm": "", - "enforce_labor": "", - "enforce_ppd": "", - "enforce_profit": "", - "enforce_sublet": "", - "enforce_validation": "", - "enforced": "" - }, - "roguard": "", - "roguardwarnings": "", - "rosaletotal": "", - "sale_additional": "", - "sale_labor": "", - "sale_parts": "", - "sale_sublet": "", - "sales": "", - "savebeforeconversion": "", - "scheduledinchange": "", - "specialcoveragepolicy": "", - "state_tax_amt": "", - "subletsnotcompleted": "", - "subletstotal": "", - "subtotal": "", - "supplementnote": "", - "suspended": "", - "suspense": "", - "tasks": "", - "threshhold": "", - "total_cost": "", - "total_cust_payable": "", - "total_cust_payable_cash_discount": "", - "total_repairs": "", - "total_repairs_cash_discount": "", - "total_sales": "", - "total_sales_tax": "", - "totals": "", - "unvoidnote": "", - "update_scheduled_completion": "", - "vehicle_info": "Vehículo", - "vehicleassociation": "", - "viewallocations": "", - "voidjob": "", - "voidnote": "" - }, - "successes": { - "addedtoproduction": "", - "all_deleted": "{{count}} trabajos eliminados con éxito.", - "closed": "", - "converted": "Trabajo convertido con éxito.", - "created": "Trabajo creado con éxito. Click para ver.", - "creatednoclick": "", - "delete": "", - "deleted": "Trabajo eliminado con éxito.", - "duplicated": "", - "exported": "", - "invoiced": "", - "ioucreated": "", - "partsqueue": "", - "save": "Trabajo guardado con éxito.", - "savetitle": "Registro guardado con éxito.", - "supplemented": "Trabajo complementado con éxito.", - "updated": "", - "voided": "" - } - }, - "landing": { - "bigfeature": { - "subtitle": "", - "title": "" - }, - "footer": { - "company": { - "about": "", - "contact": "", - "disclaimers": "", - "name": "", - "privacypolicy": "" - }, - "io": { - "help": "", - "name": "", - "status": "" - }, - "slogan": "" - }, - "hero": { - "button": "", - "title": "" - }, - "labels": { - "features": "", - "managemyshop": "", - "pricing": "" - }, - "pricing": { - "basic": { - "name": "", - "sub": "" - }, - "essentials": { - "name": "", - "sub": "" - }, - "pricingtitle": "", - "pro": { - "name": "", - "sub": "" - }, - "title": "", - "unlimited": { - "name": "", - "sub": "" - } - } - }, - "menus": { - "currentuser": { - "languageselector": "idioma", - "profile": "Perfil" - }, - "header": { - "accounting": "", - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "activejobs": "Empleos activos", - "all_tasks": "", - "alljobs": "", - "allpayments": "", - "availablejobs": "Trabajos disponibles", - "bills": "", - "courtesycars": "", - "courtesycars-all": "", - "courtesycars-contracts": "", - "courtesycars-newcontract": "", - "create_task": "", - "customers": "Clientes", - "dashboard": "", - "enterbills": "", - "entercardpayment": "", - "enterpayment": "", - "entertimeticket": "", - "export": "", - "export-logs": "", - "help": "", - "home": "Casa", - "inventory": "", - "jobs": "Trabajos", - "my_tasks": "", - "newjob": "", - "owners": "propietarios", - "parts-queue": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "readyjobs": "", - "recent": "", - "reportcenter": "", - "rescueme": "", - "schedule": "Programar", - "scoreboard": "", - "search": { - "bills": "", - "jobs": "", - "owners": "", - "payments": "", - "phonebook": "", - "vehicles": "" - }, - "shiftclock": "", - "shop": "Mi tienda", - "shop_config": "Configuración", - "shop_csi": "", - "shop_templates": "", - "shop_vendors": "Vendedores", - "tasks": "", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicles": "Vehículos" - }, - "jobsactions": { - "admin": "", - "cancelallappointments": "", - "closejob": "", - "deletejob": "", - "duplicate": "", - "duplicatenolines": "", - "newcccontract": "", - "void": "" - }, - "jobsdetail": { - "claimdetail": "Detalles de la reclamación", - "dates": "fechas", - "financials": "", - "general": "", - "insurance": "", - "labor": "Labor", - "lifecycle": "", - "parts": "", - "partssublet": "Piezas / Subarrendamiento", - "rates": "", - "repairdata": "Datos de reparación", - "totals": "" - }, - "profilesidebar": { - "profile": "Mi perfil", - "shops": "Mis tiendas" - }, - "tech": { - "assignedjobs": "", - "claimtask": "", - "dispatchedparts": "", - "home": "", - "jobclockin": "", - "jobclockout": "", - "joblookup": "", - "login": "", - "logout": "", - "productionboard": "", - "productionlist": "", - "shiftclockin": "" - } - }, - "messaging": { - "actions": { - "link": "", - "new": "" - }, - "errors": { - "invalidphone": "", - "noattachedjobs": "", - "updatinglabel": "" - }, - "labels": { - "addlabel": "", - "archive": "", - "maxtenimages": "", - "messaging": "Mensajería", - "noallowtxt": "", - "nojobs": "", - "nopush": "", - "phonenumber": "", - "presets": "", - "recentonly": "", - "selectmedia": "", - "sentby": "", - "typeamessage": "Enviar un mensaje...", - "unarchive": "" - }, - "render": { - "conversation_list": "" - } - }, - "notes": { - "actions": { - "actions": "Comportamiento", - "deletenote": "Borrar nota", - "edit": "Editar nota", - "new": "Nueva nota", - "savetojobnotes": "" - }, - "errors": { - "inserting": "" - }, - "fields": { - "createdby": "Creado por", - "critical": "Crítico", - "private": "Privado", - "text": "Contenido", - "type": "", - "types": { - "customer": "", - "general": "", - "office": "", - "paint": "", - "parts": "", - "shop": "", - "supplement": "" - }, - "updatedat": "Actualizado en" - }, - "labels": { - "addtorelatedro": "", - "newnoteplaceholder": "Agrega una nota...", - "notetoadd": "", - "systemnotes": "", - "usernotes": "" - }, - "successes": { - "create": "Nota creada con éxito.", - "deleted": "Nota eliminada con éxito.", - "updated": "Nota actualizada con éxito." - } - }, - "owner": { - "labels": { - "noownerinfo": "" - } - }, - "owners": { - "actions": { - "update": "" - }, - "errors": { - "deleting": "", - "noaccess": "El registro no existe o no tiene acceso a él.", - "saving": "", - "selectexistingornew": "" - }, - "fields": { - "accountingid": "", - "address": "Dirección", - "allow_text_message": "Permiso de texto?", - "name": "Nombre", - "note": "", - "ownr_addr1": "Dirección", - "ownr_addr2": "Dirección 2", - "ownr_city": "ciudad", - "ownr_co_nm": "", - "ownr_ctry": "País", - "ownr_ea": "Email", - "ownr_fn": "Nombre de pila", - "ownr_ln": "Apellido", - "ownr_ph1": "Teléfono 1", - "ownr_ph2": "", - "ownr_st": "Provincia del estado", - "ownr_title": "Título", - "ownr_zip": "código postal", - "preferred_contact": "Método de Contacto Preferido", - "tax_number": "" - }, - "forms": { - "address": "", - "contact": "", - "name": "" - }, - "labels": { - "create_new": "Crea un nuevo registro de propietario.", - "deleteconfirm": "", - "existing_owners": "Propietarios existentes", - "fromclaim": "", - "fromowner": "", - "relatedjobs": "", - "updateowner": "" - }, - "successes": { - "delete": "", - "save": "Propietario guardado con éxito." - } - }, - "parts": { - "actions": { - "order": "Pedido de piezas", - "orderinhouse": "" - } - }, - "parts_dispatch": { - "actions": { - "accept": "" - }, - "errors": { - "accepting": "", - "creating": "" - }, - "fields": { - "number": "", - "percent_accepted": "" - }, - "labels": { - "notyetdispatched": "", - "parts_dispatch": "" - } - }, - "parts_dispatch_lines": { - "fields": { - "accepted_at": "" - } - }, - "parts_orders": { - "actions": { - "backordered": "", - "receive": "", - "receivebill": "" - }, - "errors": { - "associatedbills": "", - "backordering": "", - "creating": "Se encontró un error al crear el pedido de piezas.", - "oec": "", - "saving": "", - "updating": "" - }, - "fields": { - "act_price": "", - "backordered_eta": "", - "backordered_on": "", - "cm_received": "", - "comments": "", - "cost": "", - "db_price": "", - "deliver_by": "", - "job_line_id": "", - "line_desc": "", - "line_remarks": "", - "lineremarks": "Comentarios de línea", - "oem_partno": "", - "order_date": "", - "order_number": "", - "orderedby": "", - "part_type": "", - "quantity": "", - "return": "", - "status": "" - }, - "labels": { - "allpartsto": "", - "confirmdelete": "", - "custompercent": "", - "discount": "", - "email": "Enviar por correo electrónico", - "inthisorder": "Partes en este pedido", - "is_quote": "", - "mark_as_received": "", - "newpartsorder": "", - "notyetordered": "", - "oec": "", - "order_type": "", - "orderhistory": "Historial de pedidos", - "parts_order": "", - "parts_orders": "", - "parts_returns": "", - "print": "Mostrar formulario impreso", - "receive": "", - "removefrompartsqueue": "", - "returnpartsorder": "", - "sublet_order": "" - }, - "successes": { - "created": "Pedido de piezas creado con éxito.", - "line_updated": "", - "received": "", - "return_created": "" - } - }, - "payments": { - "actions": { - "generatepaymentlink": "" - }, - "errors": { - "exporting": "", - "exporting-partner": "", - "inserting": "" - }, - "fields": { - "amount": "", - "created_at": "", - "date": "", - "exportedat": "", - "memo": "", - "payer": "", - "paymentnum": "", - "stripeid": "", - "transactionid": "", - "type": "" - }, - "labels": { - "balance": "", - "ca_bc_etf_table": "", - "customer": "", - "edit": "", - "electronicpayment": "", - "external": "", - "findermodal": "", - "insurance": "", - "markexported": "", - "markforreexport": "", - "new": "", - "signup": "", - "smspaymentreminder": "", - "title": "", - "totalpayments": "" - }, - "successes": { - "exported": "", - "markexported": "", - "markreexported": "", - "payment": "", - "paymentupdate": "", - "stripe": "" - } - }, - "phonebook": { - "actions": { - "new": "" - }, - "errors": { - "adding": "", - "saving": "" - }, - "fields": { - "address1": "", - "address2": "", - "category": "", - "city": "", - "company": "", - "country": "", - "email": "", - "fax": "", - "firstname": "", - "lastname": "", - "phone1": "", - "phone2": "", - "state": "" - }, - "labels": { - "noneselected": "", - "onenamerequired": "", - "vendorcategory": "" - }, - "successes": { - "added": "", - "deleted": "", - "saved": "" - } - }, - "printcenter": { - "appointments": { - "appointment_confirmation": "" - }, - "bills": { - "inhouse_invoice": "" - }, - "courtesycarcontract": { - "courtesy_car_contract": "", - "courtesy_car_impound": "", - "courtesy_car_inventory": "", - "courtesy_car_terms": "" - }, - "errors": { - "nocontexttype": "" - }, - "jobs": { - "3rdpartyfields": { - "addr1": "", - "addr2": "", - "addr3": "", - "attn": "", - "city": "", - "custgst": "", - "ded_amt": "", - "depreciation": "", - "other": "", - "ponumber": "", - "refnumber": "", - "sendtype": "", - "state": "", - "zip": "" - }, - "3rdpartypayer": "", - "ab_proof_of_loss": "", - "appointment_confirmation": "", - "appointment_reminder": "", - "casl_authorization": "", - "committed_timetickets_ro": "", - "coversheet_landscape": "", - "coversheet_portrait": "", - "csi_invitation": "", - "csi_invitation_action": "", - "diagnostic_authorization": "", - "dms_posting_sheet": "", - "envelope_return_address": "", - "estimate": "", - "estimate_detail": "", - "estimate_followup": "", - "express_repair_checklist": "", - "filing_coversheet_landscape": "", - "filing_coversheet_portrait": "", - "final_invoice": "", - "fippa_authorization": "", - "folder_label_multiple": "", - "glass_express_checklist": "", - "guarantee": "", - "individual_job_note": "", - "invoice_customer_payable": "", - "invoice_total_payable": "", - "iou_form": "", - "job_costing_ro": "", - "job_lifecycle_ro": "", - "job_notes": "", - "job_tasks": "", - "key_tag": "", - "labels": { - "count": "", - "labels": "", - "position": "" - }, - "lag_time_ro": "", - "mechanical_authorization": "", - "mpi_animal_checklist": "", - "mpi_eglass_auth": "", - "mpi_final_acct_sheet": "", - "mpi_final_repair_acct_sheet": "", - "paint_grid": "", - "parts_dispatch": "", - "parts_invoice_label_single": "", - "parts_label_multiple": "", - "parts_label_single": "", - "parts_list": "", - "parts_order": "", - "parts_order_confirmation": "", - "parts_order_history": "", - "parts_return_slip": "", - "payment_receipt": "", - "payment_request": "", - "payments_by_job": "", - "purchases_by_ro_detail": "", - "purchases_by_ro_summary": "", - "qc_sheet": "", - "rental_reservation": "", - "ro_totals": "", - "ro_with_description": "", - "sgi_certificate_of_repairs": "", - "sgi_windshield_auth": "", - "stolen_recovery_checklist": "", - "sublet_order": "", - "supplement_request": "", - "thank_you_ro": "", - "thirdpartypayer": "", - "timetickets_ro": "", - "vehicle_check_in": "", - "vehicle_delivery_check": "", - "window_tag": "", - "window_tag_sublet": "", - "work_authorization": "", - "worksheet_by_line_number": "", - "worksheet_sorted_by_operation": "", - "worksheet_sorted_by_operation_no_hours": "", - "worksheet_sorted_by_operation_part_type": "", - "worksheet_sorted_by_operation_type": "", - "worksheet_sorted_by_team": "" - }, - "labels": { - "groups": { - "authorization": "", - "financial": "", - "post": "", - "pre": "", - "ro": "", - "worksheet": "" - }, - "misc": "", - "repairorder": "", - "reportcentermodal": "", - "speedprint": "", - "title": "" - }, - "payments": { - "ca_bc_etf_table": "", - "exported_payroll": "" - }, - "special": { - "attendance_detail_csv": "" - }, - "subjects": { - "jobs": { - "individual_job_note": "", - "parts_dispatch": "", - "parts_order": "", - "parts_return_slip": "", - "sublet_order": "" - } - }, - "vendors": { - "purchases_by_vendor_detailed": "", - "purchases_by_vendor_summary": "" - } - }, - "production": { - "actions": { - "addcolumns": "", - "bodypriority-clear": "", - "bodypriority-set": "", - "detailpriority-clear": "", - "detailpriority-set": "", - "paintpriority-clear": "", - "paintpriority-set": "", - "remove": "", - "removecolumn": "", - "saveconfig": "", - "suspend": "", - "unsuspend": "" - }, - "constants": { - "main_profile": "" - }, - "errors": { - "boardupdate": "", - "name_exists": "", - "name_required": "", - "removing": "", - "settings": "" - }, - "labels": { - "actual_in": "", - "addnewprofile": "", - "alert": "", - "alertoff": "", - "alerton": "", - "alerts": "", - "ats": "", - "bodyhours": "", - "bodypriority": "", - "bodyshop": { - "labels": { - "qbo_departmentid": "", - "qbo_usa": "" - } - }, - "card_size": "", - "cardcolor": "", - "cardsettings": "", - "clm_no": "", - "comment": "", - "compact": "", - "detailpriority": "", - "employeeassignments": "", - "employeesearch": "", - "estimator": "", - "horizontal": "", - "ins_co_nm": "", - "jobdetail": "", - "kiosk_mode": "", - "laborhrs": "", - "legend": "", - "model_info": "", - "note": "", - "off": "", - "on": "", - "orientation": "", - "ownr_nm": "", - "paintpriority": "", - "partsstatus": "", - "production_note": "", - "refinishhours": "", - "scheduled_completion": "", - "selectview": "", - "stickyheader": "", - "sublets": "", - "subtotal": "", - "tall": "", - "tasks": "", - "totalhours": "", - "touchtime": "", - "unassigned": "", - "vertical": "", - "viewname": "", - "wide": "" - }, - "options": { - "horizontal": "", - "large": "", - "medium": "", - "small": "", - "vertical": "" - }, - "settings": { - "board_settings": "", - "filters": { - "md_estimators": "", - "md_ins_cos": "" - }, - "filters_title": "", - "information": "", - "layout": "", - "statistics": { - "jobs_in_production": "", - "tasks_in_production": "", - "tasks_in_view": "", - "tasks_on_board": "", - "total_amount_in_production": "", - "total_amount_in_view": "", - "total_amount_on_board": "", - "total_hours_in_production": "", - "total_hours_in_view": "", - "total_hours_on_board": "", - "total_jobs_in_view": "", - "total_jobs_on_board": "", - "total_lab_in_production": "", - "total_lab_in_view": "", - "total_lab_on_board": "", - "total_lar_in_production": "", - "total_lar_in_view": "", - "total_lar_on_board": "" - }, - "statistics_title": "" - }, - "statistics": { - "currency_symbol": "", - "hours": "", - "jobs": "", - "jobs_in_production": "", - "tasks": "", - "tasks_in_production": "", - "tasks_in_view": "", - "tasks_on_board": "", - "total_amount_in_production": "", - "total_amount_in_view": "", - "total_amount_on_board": "", - "total_hours_in_production": "", - "total_hours_in_view": "", - "total_hours_on_board": "", - "total_jobs_in_view": "", - "total_jobs_on_board": "", - "total_lab_in_production": "", - "total_lab_in_view": "", - "total_lab_on_board": "", - "total_lar_in_production": "", - "total_lar_in_view": "", - "total_lar_on_board": "" - }, - "successes": { - "removed": "" - } - }, - "profile": { - "errors": { - "state": "Error al leer el estado de la página. Porfavor refresca." - }, - "labels": { - "activeshop": "" - }, - "successes": { - "updated": "" - } - }, - "reportcenter": { - "actions": { - "generate": "" - }, - "labels": { - "advanced_filters": "", - "advanced_filters_false": "", - "advanced_filters_filter_field": "", - "advanced_filters_filter_operator": "", - "advanced_filters_filter_value": "", - "advanced_filters_filters": "", - "advanced_filters_hide": "", - "advanced_filters_show": "", - "advanced_filters_sorter_direction": "", - "advanced_filters_sorter_field": "", - "advanced_filters_sorters": "", - "advanced_filters_true": "", - "dates": "", - "employee": "", - "filterson": "", - "generateasemail": "", - "groups": { - "customers": "", - "jobs": "", - "payroll": "", - "purchases": "", - "sales": "" - }, - "key": "", - "objects": { - "appointments": "", - "bills": "", - "csi": "", - "exportlogs": "", - "jobs": "", - "parts_orders": "", - "payments": "", - "scoreboard": "", - "tasks": "", - "timetickets": "" - }, - "vendor": "" - }, - "templates": { - "adp_payroll_flat": "", - "adp_payroll_straight": "", - "anticipated_revenue": "", - "ar_aging": "", - "attendance_detail": "", - "attendance_employee": "", - "attendance_summary": "", - "committed_timetickets": "", - "committed_timetickets_employee": "", - "committed_timetickets_summary": "", - "credits_not_received_date": "", - "credits_not_received_date_vendorid": "", - "csi": "", - "customer_list": "", - "cycle_time_analysis": "", - "estimates_written_converted": "", - "estimator_detail": "", - "estimator_summary": "", - "export_payables": "", - "export_payments": "", - "export_receivables": "", - "exported_gsr_by_ro": "", - "exported_gsr_by_ro_labor": "", - "gsr_by_atp": "", - "gsr_by_ats": "", - "gsr_by_category": "", - "gsr_by_csr": "", - "gsr_by_delivery_date": "", - "gsr_by_estimator": "", - "gsr_by_exported_date": "", - "gsr_by_ins_co": "", - "gsr_by_make": "", - "gsr_by_referral": "", - "gsr_by_ro": "", - "gsr_labor_only": "", - "hours_sold_detail_closed": "", - "hours_sold_detail_closed_csr": "", - "hours_sold_detail_closed_estimator": "", - "hours_sold_detail_closed_ins_co": "", - "hours_sold_detail_closed_status": "", - "hours_sold_detail_open": "", - "hours_sold_detail_open_csr": "", - "hours_sold_detail_open_estimator": "", - "hours_sold_detail_open_ins_co": "", - "hours_sold_detail_open_status": "", - "hours_sold_summary_closed": "", - "hours_sold_summary_closed_csr": "", - "hours_sold_summary_closed_estimator": "", - "hours_sold_summary_closed_ins_co": "", - "hours_sold_summary_closed_status": "", - "hours_sold_summary_open": "", - "hours_sold_summary_open_csr": "", - "hours_sold_summary_open_estimator": "", - "hours_sold_summary_open_ins_co": "", - "hours_sold_summary_open_status": "", - "job_costing_ro_csr": "", - "job_costing_ro_date_detail": "", - "job_costing_ro_date_summary": "", - "job_costing_ro_estimator": "", - "job_costing_ro_ins_co": "", - "job_lifecycle_date_detail": "", - "job_lifecycle_date_summary": "", - "jobs_completed_not_invoiced": "", - "jobs_invoiced_not_exported": "", - "jobs_reconcile": "", - "jobs_scheduled_completion": "", - "lag_time": "", - "load_level": "", - "lost_sales": "", - "open_orders": "", - "open_orders_csr": "", - "open_orders_estimator": "", - "open_orders_excel": "", - "open_orders_ins_co": "", - "open_orders_referral": "", - "open_orders_specific_csr": "", - "open_orders_status": "", - "parts_backorder": "", - "parts_not_recieved": "", - "parts_not_recieved_vendor": "", - "parts_received_not_scheduled": "", - "payments_by_date": "", - "payments_by_date_payment": "", - "payments_by_date_type": "", - "production_by_category": "", - "production_by_category_one": "", - "production_by_csr": "", - "production_by_last_name": "", - "production_by_repair_status": "", - "production_by_repair_status_one": "", - "production_by_ro": "", - "production_by_target_date": "", - "production_by_technician": "", - "production_by_technician_one": "", - "production_not_production_status": "", - "production_over_time": "", - "psr_by_make": "", - "purchase_return_ratio_excel": "", - "purchase_return_ratio_grouped_by_vendor_detail": "", - "purchase_return_ratio_grouped_by_vendor_summary": "", - "purchases_by_cost_center_detail": "", - "purchases_by_cost_center_summary": "", - "purchases_by_date_excel": "", - "purchases_by_date_range_detail": "", - "purchases_by_date_range_summary": "", - "purchases_by_ro_detail_date": "", - "purchases_by_ro_summary_date": "", - "purchases_by_vendor_detailed_date_range": "", - "purchases_by_vendor_summary_date_range": "", - "purchases_grouped_by_vendor_detailed": "", - "purchases_grouped_by_vendor_summary": "", - "returns_grouped_by_vendor_detailed": "", - "returns_grouped_by_vendor_summary": "", - "schedule": "", - "scheduled_parts_list": "", - "scoreboard_detail": "", - "scoreboard_summary": "", - "supplement_ratio_ins_co": "", - "tasks_date": "", - "tasks_date_employee": "", - "thank_you_date": "", - "timetickets": "", - "timetickets_employee": "", - "timetickets_summary": "", - "total_loss_jobs": "", - "unclaimed_hrs": "", - "void_ros": "", - "work_in_progress_committed_labour": "", - "work_in_progress_jobs": "", - "work_in_progress_labour": "", - "work_in_progress_payables": "" - } - }, - "schedule": { - "labels": { - "atssummary": "", - "employeevacation": "", - "estimators": "", - "ins_co_nm_filter": "", - "intake": "", - "manual": "", - "manualevent": "" - } - }, - "scoreboard": { - "actions": { - "edit": "" - }, - "errors": { - "adding": "", - "removing": "", - "updating": "" - }, - "fields": { - "bodyhrs": "", - "date": "", - "painthrs": "" - }, - "labels": { - "allemployeetimetickets": "", - "asoftodaytarget": "", - "body": "", - "bodyabbrev": "", - "bodycharttitle": "", - "calendarperiod": "", - "combinedcharttitle": "", - "dailyactual": "", - "dailytarget": "", - "efficiencyoverperiod": "", - "entries": "", - "jobs": "", - "jobscompletednotinvoiced": "", - "lastmonth": "", - "lastweek": "", - "monthlytarget": "", - "priorweek": "", - "productivestatistics": "", - "productivetimeticketsoverdate": "", - "refinish": "", - "refinishabbrev": "", - "refinishcharttitle": "", - "targets": "", - "thismonth": "", - "thisweek": "", - "timetickets": "", - "timeticketsemployee": "", - "todateactual": "", - "total": "", - "totalhrs": "", - "totaloverperiod": "", - "weeklyactual": "", - "weeklytarget": "", - "workingdays": "" - }, - "successes": { - "added": "", - "removed": "", - "updated": "" - } - }, - "tasks": { - "actions": { - "edit": "", - "new": "", - "view": "" - }, - "buttons": { - "allTasks": "", - "complete": "", - "create": "", - "delete": "", - "edit": "", - "myTasks": "", - "refresh": "" - }, - "date_presets": { - "completion": "", - "day": "", - "days": "", - "delivery": "", - "next_week": "", - "one_month": "", - "three_months": "", - "three_weeks": "", - "today": "", - "tomorrow": "", - "two_weeks": "" - }, - "failures": { - "completed": "", - "created": "", - "deleted": "", - "updated": "" - }, - "fields": { - "actions": "", - "assigned_to": "", - "bill": "", - "billid": "", - "completed": "", - "created_at": "", - "created_by": "", - "description": "", - "due_date": "", - "job": { - "ro_number": "" - }, - "jobid": "", - "jobline": "", - "joblineid": "", - "parts_order": "", - "partsorderid": "", - "priorities": { - "high": "", - "low": "", - "medium": "" - }, - "priority": "", - "related_items": "", - "remind_at": "", - "title": "" - }, - "placeholders": { - "assigned_to": "", - "billid": "", - "description": "", - "jobid": "", - "joblineid": "", - "partsorderid": "" - }, - "successes": { - "completed": "", - "created": "", - "deleted": "", - "updated": "" - }, - "titles": { - "all_tasks": "", - "completed": "", - "deleted": "", - "job_tasks": "", - "mine": "", - "my_tasks": "" - }, - "validation": { - "due_at_error_message": "", - "remind_at_error_message": "" - } - }, - "tech": { - "fields": { - "employeeid": "", - "pin": "" - }, - "labels": { - "loggedin": "", - "notloggedin": "" - } - }, - "templates": { - "errors": { - "updating": "" - }, - "successes": { - "updated": "" - } - }, - "timetickets": { - "actions": { - "claimtasks": "", - "clockin": "", - "clockout": "", - "commit": "", - "commitone": "", - "enter": "", - "payall": "", - "printemployee": "", - "uncommit": "" - }, - "errors": { - "clockingin": "", - "clockingout": "", - "creating": "", - "deleting": "", - "noemployeeforuser": "", - "noemployeeforuser_sub": "", - "payall": "", - "shiftalreadyclockedon": "" - }, - "fields": { - "actualhrs": "", - "ciecacode": "", - "clockhours": "", - "clockoff": "", - "clockon": "", - "committed": "", - "committed_at": "", - "cost_center": "", - "created_by": "", - "date": "", - "efficiency": "", - "employee": "", - "employee_team": "", - "flat_rate": "", - "memo": "", - "productivehrs": "", - "ro_number": "", - "task_name": "" - }, - "labels": { - "alreadyclockedon": "", - "ambreak": "", - "amshift": "", - "claimtaskpreview": "", - "clockhours": "", - "clockintojob": "", - "deleteconfirm": "", - "edit": "", - "efficiency": "", - "flat_rate": "", - "jobhours": "", - "lunch": "", - "new": "", - "payrollclaimedtasks": "", - "pmbreak": "", - "pmshift": "", - "shift": "", - "shiftalreadyclockedon": "", - "straight_time": "", - "task": "", - "timetickets": "", - "unassigned": "", - "zeroactualnegativeprod": "" - }, - "successes": { - "clockedin": "", - "clockedout": "", - "committed": "", - "created": "", - "deleted": "", - "payall": "" - }, - "validation": { - "clockoffmustbeafterclockon": "", - "clockoffwithoutclockon": "", - "hoursenteredmorethanavailable": "", - "unassignedlines": "" - } - }, - "titles": { - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "all_tasks": "", - "app": "", - "bc": { - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "all_tasks": "", - "availablejobs": "", - "bills-list": "", - "contracts": "", - "contracts-create": "", - "contracts-detail": "", - "courtesycars": "", - "courtesycars-detail": "", - "courtesycars-new": "", - "dashboard": "", - "dms": "", - "export-logs": "", - "inventory": "", - "jobs": "", - "jobs-active": "", - "jobs-admin": "", - "jobs-all": "", - "jobs-checklist": "", - "jobs-close": "", - "jobs-deliver": "", - "jobs-detail": "", - "jobs-intake": "", - "jobs-new": "", - "jobs-ready": "", - "my_tasks": "", - "owner-detail": "", - "owners": "", - "parts-queue": "", - "payments-all": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "profile": "", - "schedule": "", - "scoreboard": "", - "shop": "", - "shop-csi": "", - "shop-templates": "", - "shop-vendors": "", - "tasks": "", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicle-details": "", - "vehicles": "" - }, - "bills-list": "", - "contracts": "", - "contracts-create": "", - "contracts-detail": "", - "courtesycars": "", - "courtesycars-create": "", - "courtesycars-detail": "", - "dashboard": "", - "dms": "", - "export-logs": "", - "imexonline": "", - "inventory": "", - "jobs": "Todos los trabajos | {{app}}", - "jobs-admin": "", - "jobs-all": "", - "jobs-checklist": "", - "jobs-close": "", - "jobs-create": "", - "jobs-deliver": "", - "jobs-intake": "", - "jobsavailable": "Empleos disponibles | {{app}}", - "jobsdetail": "Trabajo {{ro_number}} | {{app}}", - "jobsdocuments": "Documentos de trabajo {{ro_number}} | {{app}}", - "manageroot": "Casa | {{app}}", - "my_tasks": "", - "owners": "Todos los propietarios | {{app}}", - "owners-detail": "", - "parts-queue": "", - "payments-all": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "profile": "Mi perfil | {{app}}", - "readyjobs": "", - "resetpassword": "", - "resetpasswordvalidate": "", - "romeonline": "", - "schedule": "Horario | {{app}}", - "scoreboard": "", - "shop": "Mi tienda | {{app}}", - "shop-csi": "", - "shop-templates": "", - "shop_vendors": "Vendedores | {{app}}", - "tasks": "", - "techconsole": "{{app}}", - "techjobclock": "{{app}}", - "techjoblookup": "{{app}}", - "techshiftclock": "{{app}}", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicledetail": "Detalles del vehículo {{vehicle}} | {{app}}", - "vehicles": "Todos los vehiculos | {{app}}" - }, - "trello": { - "labels": { - "add_card": "", - "add_lane": "", - "cancel": "", - "delete_lane": "", - "description": "", - "label": "", - "lane_actions": "", - "title": "" - } - }, - "tt_approvals": { - "actions": { - "approveselected": "" - }, - "labels": { - "approval_queue_in_use": "", - "calculate": "" - } - }, - "upsell": { - "cta": { - "learnmore": "" - }, - "messages": { - "accounting": { - "payables": { - "subtitle": "", - "title": "" - }, - "payments": { - "subtitle": "", - "title": "" - }, - "receivables": { - "subtitle": "", - "title": "" - } - }, - "audit": { - "general": { - "subtitle": "", - "title": "" - } - }, - "bills": { - "autoreconcile": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - } - }, - "checklist": { - "general": { - "subtitle": "", - "title": "" - } - }, - "courtesycars": { - "general": { - "subtitle": "", - "title": "" - } - }, - "csi": { - "general": { - "subtitle": "", - "title": "" - } - }, - "dashboard": { - "general": { - "subtitle": "", - "title": "" - } - }, - "lifecycle": { - "general": { - "subtitle": "", - "title": "" - } - }, - "media": { - "general": { - "subtitle": "", - "title": "" - }, - "mobile": { - "subtitle": "", - "title": "" - } - }, - "payments": { - "general": { - "subtitle": "", - "title": "" - } - }, - "scoreboard": { - "general": { - "subtitle": "", - "title": "" - } - }, - "smartscheduling": { - "datepicker": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - }, - "hrsdelta": { - "subtitle": "", - "title": "" - } - }, - "techconsole": { - "general": { - "subtitle": "", - "title": "" - } - }, - "timetickets": { - "allocations": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - } - }, - "visualboard": { - "general": { - "subtitle": "", - "title": "" - } - } - } - }, - "user": { - "actions": { - "changepassword": "", - "signout": "desconectar", - "updateprofile": "Actualización del perfil" - }, - "errors": { - "updating": "" - }, - "fields": { - "authlevel": "", - "displayname": "Nombre para mostrar", - "email": "", - "photourl": "URL de avatar" - }, - "labels": { - "actions": "", - "changepassword": "", - "profileinfo": "" - }, - "successess": { - "passwordchanged": "" - } - }, - "users": { - "errors": { - "signinerror": { - "auth/user-disabled": "", - "auth/user-not-found": "", - "auth/wrong-password": "" - } - } - }, - "vehicles": { - "errors": { - "deleting": "", - "noaccess": "El vehículo no existe o usted no tiene acceso a él.", - "selectexistingornew": "", - "validation": "Asegúrese de que todos los campos se ingresen correctamente.", - "validationtitle": "Error de validacion" - }, - "fields": { - "description": "Descripcion del vehiculo", - "notes": "", - "plate_no": "Placa", - "plate_st": "Jurisdicción de placas", - "trim_color": "Recortar color", - "v_bstyle": "Tipo de cuerpo", - "v_color": "Color", - "v_cond": "condición", - "v_engine": "Motor", - "v_make_desc": "Hacer", - "v_makecode": "Hacer código", - "v_mldgcode": "Código de moldeo", - "v_model_desc": "Modelo", - "v_model_yr": "año", - "v_options": "Opciones", - "v_paint_codes": "Códigos de pintura", - "v_prod_dt": "Fecha de producción", - "v_stage": "Escenario", - "v_tone": "Tono", - "v_trimcode": "Código de recorte", - "v_type": "Tipo", - "v_vin": "V.I.N." - }, - "forms": { - "detail": "", - "misc": "", - "registration": "" - }, - "labels": { - "deleteconfirm": "", - "fromvehicle": "", - "novehinfo": "", - "relatedjobs": "", - "updatevehicle": "" - }, - "successes": { - "delete": "", - "save": "Vehículo guardado con éxito." - } - }, - "vendors": { - "actions": { - "addtophonebook": "", - "new": "Nuevo vendedor", - "newpreferredmake": "" - }, - "errors": { - "deleting": "Se encontró un error al eliminar el proveedor.", - "saving": "Se encontró un error al guardar el proveedor." - }, - "fields": { - "active": "", - "am": "", - "city": "ciudad", - "cost_center": "Centro de costos", - "country": "País", - "discount": "% De descuento", - "display_name": "Nombre para mostrar", - "dmsid": "", - "due_date": "Fecha de vencimiento del pago", - "email": "Email de contacto", - "favorite": "¿Favorito?", - "lkq": "", - "make": "", - "name": "Nombre del vendedor", - "oem": "", - "phone": "", - "prompt_discount": "Descuento pronto", - "state": "Provincia del estado", - "street1": "calle", - "street2": "Dirección 2", - "taxid": "Identificación del impuesto", - "terms": "Términos de pago", - "zip": "código postal" - }, - "labels": { - "noneselected": "Ningún vendedor está seleccionado.", - "preferredmakes": "", - "search": "Escriba el nombre de un proveedor" - }, - "successes": { - "deleted": "Proveedor eliminado correctamente.", - "saved": "Proveedor guardado con éxito." - }, - "validation": { - "unique_vendor_name": "" - } - }, + "translation": { + "allocations": { + "actions": { + "assign": "Asignar" + }, + "errors": { + "deleting": "", + "saving": "", + "validation": "" + }, + "fields": { + "employee": "Asignado a" + }, + "successes": { + "deleted": "", + "save": "" + } + }, + "appointments": { + "actions": { + "block": "", + "calculate": "", + "cancel": "Cancelar", + "intake": "Consumo", + "new": "Nueva cita", + "preview": "", + "reschedule": "Reprogramar", + "sendreminder": "", + "unblock": "", + "viewjob": "Ver trabajo" + }, + "errors": { + "blocking": "", + "canceling": "Error al cancelar la cita. {{message}}", + "saving": "Error al programar la cita. {{message}}" + }, + "fields": { + "alt_transport": "", + "color": "", + "end": "", + "note": "", + "start": "", + "time": "", + "title": "Título" + }, + "labels": { + "arrivedon": "Llegado el:", + "arrivingjobs": "", + "blocked": "", + "cancelledappointment": "Cita cancelada para:", + "completingjobs": "", + "dataconsistency": "", + "expectedjobs": "", + "expectedprodhrs": "", + "history": "", + "inproduction": "", + "manualevent": "", + "noarrivingjobs": "", + "nocompletingjobs": "", + "nodateselected": "No se ha seleccionado ninguna fecha.", + "priorappointments": "Nombramientos previos", + "reminder": "", + "scheduledfor": "Cita programada para:", + "severalerrorsfound": "", + "smartscheduling": "", + "smspaymentreminder": "", + "suggesteddates": "" + }, + "successes": { + "canceled": "Cita cancelada con éxito.", + "created": "Cita programada con éxito.", + "saved": "" + } + }, + "associations": { + "actions": { + "activate": "Activar" + }, + "fields": { + "active": "¿Activo?", + "shopname": "Nombre de tienda" + }, + "labels": { + "actions": "Comportamiento" + } + }, + "audit": { + "fields": { + "cc": "", + "contents": "", + "created": "", + "operation": "", + "status": "", + "subject": "", + "to": "", + "useremail": "", + "values": "" + } + }, + "audit_trail": { + "messages": { + "admin_job_remove_from_ar": "", + "admin_jobmarkexported": "", + "admin_jobmarkforreexport": "", + "admin_jobuninvoice": "", + "admin_jobunvoid": "", + "alerttoggle": "", + "appointmentcancel": "", + "appointmentinsert": "", + "assignedlinehours": "", + "billdeleted": "", + "billposted": "", + "billupdated": "", + "failedpayment": "", + "jobassignmentchange": "", + "jobassignmentremoved": "", + "jobchecklist": "", + "jobclosedwithbypass": "", + "jobconverted": "", + "jobdelivery": "", + "jobexported": "", + "jobfieldchanged": "", + "jobimported": "", + "jobinproductionchange": "", + "jobintake": "", + "jobinvoiced": "", + "jobioucreated": "", + "jobmodifylbradj": "", + "jobnoteadded": "", + "jobnotedeleted": "", + "jobnoteupdated": "", + "jobspartsorder": "", + "jobspartsreturn": "", + "jobstatuschange": "", + "jobsupplement": "", + "jobsuspend": "", + "jobvoid": "", + "tasks_completed": "", + "tasks_created": "", + "tasks_deleted": "", + "tasks_uncompleted": "", + "tasks_undeleted": "", + "tasks_updated": "" + } + }, + "billlines": { + "actions": { + "newline": "" + }, + "fields": { + "actual_cost": "", + "actual_price": "", + "cost_center": "", + "federal_tax_applicable": "", + "jobline": "", + "line_desc": "", + "local_tax_applicable": "", + "location": "", + "quantity": "", + "state_tax_applicable": "" + }, + "labels": { + "deductedfromlbr": "", + "entered": "", + "from": "", + "mod_lbr_adjustment": "", + "other": "", + "reconciled": "", + "unreconciled": "" + }, + "validation": { + "atleastone": "" + } + }, + "bills": { + "actions": { + "deductallhours": "", + "edit": "", + "receive": "", + "return": "" + }, + "errors": { + "creating": "", + "deleting": "", + "existinginventoryline": "", + "exporting": "", + "exporting-partner": "", + "invalidro": "", + "invalidvendor": "", + "validation": "" + }, + "fields": { + "allpartslocation": "", + "date": "", + "exported": "", + "federal_tax_rate": "", + "invoice_number": "", + "is_credit_memo": "", + "is_credit_memo_short": "", + "local_tax_rate": "", + "ro_number": "", + "state_tax_rate": "", + "total": "", + "vendor": "", + "vendorname": "" + }, + "labels": { + "actions": "", + "bill_lines": "", + "bill_total": "", + "billcmtotal": "", + "bills": "", + "calculatedcreditsnotreceived": "", + "creditsnotreceived": "", + "creditsreceived": "", + "dedfromlbr": "", + "deleteconfirm": "", + "discrepancy": "", + "discrepwithcms": "", + "discrepwithlbradj": "", + "editadjwarning": "", + "entered_total": "", + "enteringcreditmemo": "", + "federal_tax": "", + "federal_tax_exempt": "", + "generatepartslabel": "", + "iouexists": "", + "local_tax": "", + "markexported": "", + "markforreexport": "", + "new": "", + "nobilllines": "", + "noneselected": "", + "onlycmforinvoiced": "", + "printlabels": "", + "retailtotal": "", + "returnfrombill": "", + "savewithdiscrepancy": "", + "state_tax": "", + "subtotal": "", + "totalreturns": "" + }, + "successes": { + "created": "", + "deleted": "", + "exported": "", + "markexported": "", + "reexport": "" + }, + "validation": { + "closingperiod": "", + "inventoryquantity": "", + "manualinhouse": "", + "unique_invoice_number": "" + } + }, + "bodyshop": { + "actions": { + "add_task_preset": "", + "addapptcolor": "", + "addbucket": "", + "addpartslocation": "", + "addpartsrule": "", + "addspeedprint": "", + "addtemplate": "", + "newlaborrate": "", + "newsalestaxcode": "", + "newstatus": "", + "testrender": "" + }, + "errors": { + "creatingdefaultview": "", + "loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.", + "saving": "" + }, + "fields": { + "ReceivableCustomField": "", + "address1": "", + "address2": "", + "appt_alt_transport": "", + "appt_colors": { + "color": "", + "label": "" + }, + "appt_length": "", + "attach_pdf_to_email": "", + "batchid": "", + "bill_allow_post_to_closed": "", + "bill_federal_tax_rate": "", + "bill_local_tax_rate": "", + "bill_state_tax_rate": "", + "city": "", + "closingperiod": "", + "companycode": "", + "country": "", + "dailybodytarget": "", + "dailypainttarget": "", + "default_adjustment_rate": "", + "deliver": { + "require_actual_delivery_date": "", + "templates": "" + }, + "dms": { + "apcontrol": "", + "appostingaccount": "", + "cashierid": "", + "default_journal": "", + "disablebillwip": "", + "disablecontactvehiclecreation": "", + "dms_acctnumber": "", + "dms_control_override": "", + "dms_wip_acctnumber": "", + "generic_customer_number": "", + "itc_federal": "", + "itc_local": "", + "itc_state": "", + "mappingname": "", + "sendmaterialscosting": "", + "srcco": "" + }, + "email": "", + "enforce_class": "", + "enforce_conversion_category": "", + "enforce_conversion_csr": "", + "enforce_referral": "", + "federal_tax_id": "", + "ignoreblockeddays": "", + "inhousevendorid": "", + "insurance_vendor_id": "", + "intake": { + "next_contact_hours": "", + "templates": "" + }, + "intellipay_config": { + "cash_discount_percentage": "", + "enable_cash_discount": "", + "payment_type": "", + "payment_map": { + "amex": "American Express", + "disc": "Discover", + "dnrs": "Diners", + "intr": "Interac", + "jcb": "JCB", + "mast": "MasterCard", + "visa": "Visa" + } + }, + "invoice_federal_tax_rate": "", + "invoice_local_tax_rate": "", + "invoice_state_tax_rate": "", + "jc_hourly_rates": { + "mapa": "", + "mash": "" + }, + "last_name_first": "", + "lastnumberworkingdays": "", + "localmediaserverhttp": "", + "localmediaservernetwork": "", + "localmediatoken": "", + "logo_img_footer_margin": "", + "logo_img_header_margin": "", + "logo_img_path": "", + "logo_img_path_height": "", + "logo_img_path_width": "", + "md_categories": "", + "md_ccc_rates": "", + "md_classes": "", + "md_ded_notes": "", + "md_email_cc": "", + "md_from_emails": "", + "md_functionality_toggles": { + "parts_queue_toggle": "" + }, + "md_hour_split": { + "paint": "", + "prep": "" + }, + "md_ins_co": { + "city": "", + "name": "", + "private": "", + "state": "", + "street1": "", + "street2": "", + "zip": "" + }, + "md_jobline_presets": "", + "md_lost_sale_reasons": "", + "md_parts_order_comment": "", + "md_parts_scan": { + "caseInsensitive": "", + "expression": "", + "field": "", + "flags": "", + "mark_critical": "", + "operation": "", + "update_field": "", + "update_value": "", + "value": "" + }, + "md_payment_types": "", + "md_referral_sources": "", + "md_ro_guard": { + "enabled": "", + "enforce_ar": "", + "enforce_bills": "", + "enforce_cm": "", + "enforce_labor": "", + "enforce_ppd": "", + "enforce_profit": "", + "enforce_sublet": "", + "masterbypass": "", + "totalgppercent_minimum": "" + }, + "md_tasks_presets": { + "enable_tasks": "", + "hourstype": "", + "memo": "", + "name": "", + "nextstatus": "", + "percent": "", + "use_approvals": "" + }, + "messaginglabel": "", + "messagingtext": "", + "noteslabel": "", + "notestext": "", + "partslocation": "", + "phone": "", + "prodtargethrs": "", + "rbac": { + "accounting": { + "exportlog": "", + "payables": "", + "payments": "", + "receivables": "" + }, + "bills": { + "delete": "", + "enter": "", + "list": "", + "reexport": "", + "view": "" + }, + "contracts": { + "create": "", + "detail": "", + "list": "" + }, + "courtesycar": { + "create": "", + "detail": "", + "list": "" + }, + "csi": { + "export": "", + "page": "" + }, + "employee_teams": { + "page": "" + }, + "employees": { + "page": "" + }, + "inventory": { + "delete": "", + "list": "" + }, + "jobs": { + "admin": "", + "available-list": "", + "checklist-view": "", + "close": "", + "create": "", + "deliver": "", + "detail": "", + "intake": "", + "list-active": "", + "list-all": "", + "list-ready": "", + "partsqueue": "", + "void": "" + }, + "owners": { + "detail": "", + "list": "" + }, + "payments": { + "enter": "", + "list": "" + }, + "phonebook": { + "edit": "", + "view": "" + }, + "production": { + "board": "", + "list": "" + }, + "schedule": { + "view": "" + }, + "scoreboard": { + "view": "" + }, + "shiftclock": { + "view": "" + }, + "shop": { + "config": "", + "dashboard": "", + "rbac": "", + "reportcenter": "", + "templates": "", + "vendors": "" + }, + "temporarydocs": { + "view": "" + }, + "timetickets": { + "edit": "", + "editcommitted": "", + "enter": "", + "list": "", + "shiftedit": "" + }, + "ttapprovals": { + "approve": "", + "view": "" + }, + "users": { + "editaccess": "" + } + }, + "responsibilitycenter": "", + "responsibilitycenter_accountdesc": "", + "responsibilitycenter_accountitem": "", + "responsibilitycenter_accountname": "", + "responsibilitycenter_accountnumber": "", + "responsibilitycenter_rate": "", + "responsibilitycenter_tax_rate": "", + "responsibilitycenter_tax_sur": "", + "responsibilitycenter_tax_thres": "", + "responsibilitycenter_tax_tier": "", + "responsibilitycenter_tax_type": "", + "responsibilitycenters": { + "ap": "", + "ar": "", + "ats": "", + "federal_tax": "", + "federal_tax_itc": "", + "gst_override": "", + "invoiceexemptcode": "", + "itemexemptcode": "", + "la1": "", + "la2": "", + "la3": "", + "la4": "", + "laa": "", + "lab": "", + "lad": "", + "lae": "", + "laf": "", + "lag": "", + "lam": "", + "lar": "", + "las": "", + "lau": "", + "local_tax": "", + "mapa": "", + "mash": "", + "paa": "", + "pac": "", + "pag": "", + "pal": "", + "pam": "", + "pan": "", + "pao": "", + "pap": "", + "par": "", + "pas": "", + "pasl": "", + "refund": "", + "sales_tax_codes": { + "code": "", + "description": "", + "federal": "", + "local": "", + "state": "" + }, + "state_tax": "", + "tow": "" + }, + "schedule_end_time": "", + "schedule_start_time": "", + "shopname": "", + "speedprint": { + "id": "", + "label": "", + "templates": "" + }, + "ss_configuration": { + "dailyhrslimit": "" + }, + "ssbuckets": { + "color": "", + "gte": "", + "id": "", + "label": "", + "lt": "", + "target": "" + }, + "state": "", + "state_tax_id": "", + "status": "", + "statuses": { + "active_statuses": "", + "additional_board_statuses": "", + "color": "", + "default_arrived": "", + "default_bo": "", + "default_canceled": "", + "default_completed": "", + "default_delivered": "", + "default_exported": "", + "default_imported": "", + "default_invoiced": "", + "default_ordered": "", + "default_quote": "", + "default_received": "", + "default_returned": "", + "default_scheduled": "", + "default_void": "", + "open_statuses": "", + "post_production_statuses": "", + "pre_production_statuses": "", + "production_colors": "", + "production_statuses": "", + "ready_statuses": "" + }, + "target_touchtime": "", + "timezone": "", + "tt_allow_post_to_invoiced": "", + "tt_enforce_hours_for_tech_console": "", + "use_fippa": "", + "use_paint_scale_data": "", + "uselocalmediaserver": "", + "website": "", + "zip_post": "" + }, + "labels": { + "2tiername": "", + "2tiersetup": "", + "2tiersource": "", + "accountingsetup": "", + "accountingtiers": "", + "alljobstatuses": "", + "allopenjobstatuses": "", + "apptcolors": "", + "businessinformation": "", + "checklists": "", + "csiq": "", + "customtemplates": "", + "defaultcostsmapping": "", + "defaultprofitsmapping": "", + "deliverchecklist": "", + "dms": { + "cdk": { + "controllist": "", + "payers": "" + }, + "cdk_dealerid": "", + "costsmapping": "", + "dms_allocations": "", + "pbs_serialnumber": "", + "profitsmapping": "", + "title": "" + }, + "emaillater": "", + "employee_teams": "", + "employees": "", + "estimators": "", + "filehandlers": "", + "imexpay": "", + "insurancecos": "", + "intakechecklist": "", + "intellipay_cash_discount": "", + "jobstatuses": "", + "laborrates": "", + "licensing": "", + "md_parts_scan": "", + "md_ro_guard": "", + "md_tasks_presets": "", + "md_to_emails": "", + "md_to_emails_emails": "", + "messagingpresets": "", + "notemplatesavailable": "", + "notespresets": "", + "orderstatuses": "", + "partslocations": "", + "partsscan": "", + "printlater": "", + "qbo": "", + "qbo_departmentid": "", + "qbo_usa": "", + "rbac": "", + "responsibilitycenters": { + "costs": "", + "profits": "", + "sales_tax_codes": "", + "tax_accounts": "", + "title": "", + "ttl_adjustment": "", + "ttl_tax_adjustment": "" + }, + "roguard": { + "title": "" + }, + "romepay": "", + "scheduling": "", + "scoreboardsetup": "", + "shop_enabled_features": "", + "shopinfo": "", + "speedprint": "", + "ssbuckets": "", + "systemsettings": "", + "task-presets": "", + "workingdays": "" + }, + "operations": { + "contains": "", + "ends_with": "", + "equals": "", + "greater_than": "", + "less_than": "", + "not_equals": "", + "starts_with": "" + }, + "successes": { + "areyousure": "", + "defaultviewcreated": "", + "save": "", + "unsavedchanges": "" + }, + "tooltips": { + "md_parts_scan": { + "update_value_tooltip": "" + } + }, + "validation": { + "centermustexist": "", + "larsplit": "", + "useremailmustexist": "" + } + }, + "checklist": { + "actions": { + "printall": "" + }, + "errors": { + "complete": "", + "nochecklist": "" + }, + "labels": { + "addtoproduction": "", + "allow_text_message": "", + "checklist": "", + "printpack": "", + "removefromproduction": "" + }, + "successes": { + "completed": "" + } + }, + "contracts": { + "actions": { + "changerate": "", + "convertoro": "", + "decodelicense": "", + "find": "", + "printcontract": "", + "senddltoform": "" + }, + "errors": { + "fetchingjobinfo": "", + "returning": "", + "saving": "", + "selectjobandcar": "" + }, + "fields": { + "actax": "", + "actualreturn": "", + "agreementnumber": "", + "cc_cardholder": "", + "cc_expiry": "", + "cc_num": "", + "cleanupcharge": "", + "coverage": "", + "dailyfreekm": "", + "dailyrate": "", + "damage": "", + "damagewaiver": "", + "driver": "", + "driver_addr1": "", + "driver_addr2": "", + "driver_city": "", + "driver_dlexpiry": "", + "driver_dlnumber": "", + "driver_dlst": "", + "driver_dob": "", + "driver_fn": "", + "driver_ln": "", + "driver_ph1": "", + "driver_state": "", + "driver_zip": "", + "excesskmrate": "", + "federaltax": "", + "fuelin": "", + "fuelout": "", + "kmend": "", + "kmstart": "", + "length": "", + "localtax": "", + "refuelcharge": "", + "scheduledreturn": "", + "start": " ", + "statetax": "", + "status": "" + }, + "labels": { + "agreement": "", + "availablecars": "", + "cardueforservice": "", + "convertform": { + "applycleanupcharge": "", + "refuelqty": "" + }, + "correctdataonform": "", + "dateinpast": "", + "dlexpirebeforereturn": "", + "driverinformation": "", + "findcontract": "", + "findermodal": "", + "insuranceexpired": "", + "noteconvertedfrom": "", + "populatefromjob": "", + "rates": "", + "time": "", + "vehicle": "", + "waitingforscan": "" + }, + "status": { + "new": "", + "out": "", + "returned": "" + }, + "successes": { + "saved": "" + } + }, + "courtesycars": { + "actions": { + "new": "", + "return": "" + }, + "errors": { + "saving": "" + }, + "fields": { + "color": "", + "dailycost": "", + "damage": "", + "fleetnumber": "", + "fuel": "", + "insuranceexpires": "", + "leaseenddate": "", + "make": "", + "mileage": "", + "model": "", + "nextservicedate": "", + "nextservicekm": "", + "notes": "", + "plate": "", + "purchasedate": "", + "readiness": "", + "registrationexpires": "", + "serviceenddate": "", + "servicestartdate": "", + "status": "", + "vin": "", + "year": "" + }, + "labels": { + "courtesycar": "", + "fuel": { + "12": "", + "14": "", + "18": "", + "34": "", + "38": "", + "58": "", + "78": "", + "empty": "", + "full": "" + }, + "outwith": "", + "return": "", + "status": "", + "uniquefleet": "", + "usage": "", + "vehicle": "" + }, + "readiness": { + "notready": "", + "ready": "" + }, + "status": { + "in": "", + "inservice": "", + "leasereturn": "", + "out": "", + "sold": "", + "unavailable": "" + }, + "successes": { + "saved": "" + } + }, + "csi": { + "actions": { + "activate": "" + }, + "errors": { + "creating": "", + "notconfigured": "", + "notfoundsubtitle": "", + "notfoundtitle": "", + "surveycompletesubtitle": "", + "surveycompletetitle": "" + }, + "fields": { + "completedon": "", + "created_at": "", + "surveyid": "", + "validuntil": "" + }, + "labels": { + "copyright": "", + "greeting": "", + "intro": "", + "nologgedinuser": "", + "nologgedinuser_sub": "", + "noneselected": "", + "title": "" + }, + "successes": { + "created": "", + "submitted": "", + "submittedsub": "" + } + }, + "dashboard": { + "actions": { + "addcomponent": "" + }, + "errors": { + "refreshrequired": "", + "updatinglayout": "" + }, + "labels": { + "bodyhrs": "", + "dollarsinproduction": "", + "phone": "", + "prodhrs": "", + "refhrs": "" + }, + "titles": { + "joblifecycle": "", + "labhours": "", + "larhours": "", + "monthlyemployeeefficiency": "", + "monthlyjobcosting": "", + "monthlylaborsales": "", + "monthlypartssales": "", + "monthlyrevenuegraph": "", + "prodhrssummary": "", + "productiondollars": "", + "productionhours": "", + "projectedmonthlysales": "", + "scheduledindate": "", + "scheduledintoday": "", + "scheduledoutdate": "", + "scheduledouttoday": "", + "tasks": "" + } + }, + "dms": { + "errors": { + "alreadyexported": "" + }, + "labels": { + "refreshallocations": "" + } + }, + "documents": { + "actions": { + "delete": "", + "download": "", + "reassign": "", + "selectallimages": "", + "selectallotherdocuments": "" + }, + "errors": { + "deletes3": "Error al eliminar el documento del almacenamiento.", + "deleting": "", + "deleting_cloudinary": "", + "getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}", + "insert": "Incapaz de cargar el archivo. {{message}}", + "nodocuments": "No hay documentos", + "updating": "" + }, + "labels": { + "confirmdelete": "", + "doctype": "", + "dragtoupload": "", + "newjobid": "", + "openinexplorer": "", + "optimizedimage": "", + "reassign_limitexceeded": "", + "reassign_limitexceeded_title": "", + "storageexceeded": "", + "storageexceeded_title": "", + "upload": "Subir", + "upload_limitexceeded": "", + "upload_limitexceeded_title": "", + "uploading": "", + "usage": "" + }, + "successes": { + "delete": "Documento eliminado con éxito.", + "edituploaded": "", + "insert": "Documento cargado con éxito.", + "updated": "" + } + }, + "emails": { + "errors": { + "notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}" + }, + "fields": { + "cc": "", + "from": "", + "subject": "", + "to": "" + }, + "labels": { + "attachments": "", + "documents": "", + "emailpreview": "", + "generatingemail": "", + "pdfcopywillbeattached": "", + "preview": "" + }, + "successes": { + "sent": "Correo electrónico enviado con éxito." + } + }, + "employee_teams": { + "actions": { + "new": "", + "newmember": "" + }, + "fields": { + "active": "", + "employeeid": "", + "max_load": "", + "name": "", + "percentage": "" + } + }, + "employees": { + "actions": { + "addvacation": "", + "new": "Nuevo empleado", + "newrate": "" + }, + "errors": { + "delete": "Se encontró un error al eliminar al empleado. {{message}}", + "save": "Se encontró un error al salvar al empleado. {{message}}", + "validation": "Por favor verifique todos los campos.", + "validationtitle": "No se puede salvar al empleado." + }, + "fields": { + "active": "¿Activo?", + "base_rate": "Tasa básica", + "cost_center": "Centro de costos", + "employee_number": "Numero de empleado", + "external_id": "", + "first_name": "Nombre de pila", + "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)", + "hire_date": "Fecha de contratación", + "last_name": "Apellido", + "pin": "", + "rate": "", + "termination_date": "Fecha de conclusión", + "user_email": "", + "vacation": { + "end": "", + "length": "", + "start": "" + } + }, + "labels": { + "actions": "", + "active": "", + "endmustbeafterstart": "", + "flat_rate": "", + "inactive": "", + "name": "", + "rate_type": "", + "status": "", + "straight_time": "" + }, + "successes": { + "delete": "Empleado eliminado con éxito.", + "save": "Empleado guardado con éxito.", + "vacationadded": "" + }, + "validation": { + "unique_employee_number": "" + } + }, + "eula": { + "buttons": { + "accept": "Accept EULA" + }, + "content": { + "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." + }, + "errors": { + "acceptance": { + "description": "Something went wrong while accepting the EULA. Please try again.", + "message": "Eula Acceptance Error" + } + }, + "labels": { + "accepted_terms": "I accept the terms and conditions of this agreement.", + "address": "Address", + "business_name": "Legal Business Name", + "date_accepted": "Date Accepted", + "first_name": "First Name", + "last_name": "Last Name", + "phone_number": "Phone Number" + }, + "messages": { + "accepted_terms": "Please accept the terms and conditions of this agreement.", + "business_name": "Please enter your legal business name.", + "date_accepted": "Please enter Today's Date.", + "first_name": "Please enter your first name.", + "last_name": "Please enter your last name.", + "phone_number": "Please enter your phone number." + }, + "titles": { + "modal": "Terms and Conditions", + "upper_card": "Acknowledgement" + } + }, + "exportlogs": { + "fields": { + "createdat": "" + }, + "labels": { + "attempts": "", + "priorsuccesfulexport": "" + } + }, + "general": { + "actions": { + "add": "", + "autoupdate": "", + "calculate": "", + "cancel": "", + "clear": "", + "close": "", + "copied": "", + "copylink": "", + "create": "", + "defaults": "defaults", + "delay": "", + "delete": "Borrar", + "deleteall": "", + "deselectall": "", + "download": "", + "edit": "Editar", + "login": "", + "next": "", + "ok": "", + "previous": "", + "print": "", + "refresh": "", + "remove": "", + "remove_alert": "", + "reset": " Restablecer a original.", + "resetpassword": "", + "save": "Salvar", + "saveandnew": "", + "saveas": "", + "selectall": "", + "send": "", + "sendbysms": "", + "senderrortosupport": "", + "sharetoteams": "", + "submit": "", + "tryagain": "", + "view": "", + "viewreleasenotes": "" + }, + "errors": { + "fcm": "", + "notfound": "", + "sizelimit": "" + }, + "itemtypes": { + "contract": "", + "courtesycar": "", + "job": "", + "owner": "", + "vehicle": "" + }, + "labels": { + "actions": "Comportamiento", + "areyousure": "", + "barcode": "código de barras", + "cancel": "", + "clear": "", + "confirmpassword": "", + "created_at": "", + "date": "", + "datetime": "", + "email": "", + "errors": "", + "excel": "", + "exceptiontitle": "", + "friday": "", + "globalsearch": "", + "help": "", + "hours": "", + "in": "en", + "instanceconflictext": "", + "instanceconflictitle": "", + "item": "", + "label": "", + "loading": "Cargando...", + "loadingapp": "Cargando {{app}}", + "loadingshop": "Cargando datos de la tienda ...", + "loggingin": "Iniciando sesión ...", + "markedexported": "", + "media": "", + "message": "", + "monday": "", + "na": "N / A", + "newpassword": "", + "no": "", + "nointernet": "", + "nointernet_sub": "", + "none": "", + "out": "Afuera", + "password": "", + "passwordresetsuccess": "", + "passwordresetsuccess_sub": "", + "passwordresetvalidatesuccess": "", + "passwordresetvalidatesuccess_sub": "", + "passwordsdonotmatch": "", + "print": "", + "refresh": "", + "reports": "", + "required": "", + "saturday": "", + "search": "Buscar...", + "searchresults": "", + "selectdate": "", + "sendagain": "", + "sendby": "", + "signin": "", + "sms": "", + "status": "", + "sub_status": { + "expired": "" + }, + "successful": "", + "sunday": "", + "text": "", + "thursday": "", + "time": "", + "total": "", + "totals": "", + "tuesday": "", + "tvmode": "", + "unknown": "Desconocido", + "unsavedchanges": "", + "username": "", + "view": "", + "wednesday": "", + "yes": "" + }, + "languages": { + "english": "Inglés", + "french": "francés", + "spanish": "español" + }, + "messages": { + "exception": "", + "newversionmessage": "", + "newversiontitle": "", + "noacctfilepath": "", + "nofeatureaccess": "", + "noshop": "", + "notfoundsub": "", + "notfoundtitle": "", + "partnernotrunning": "", + "rbacunauth": "", + "unsavedchanges": "Usted tiene cambios no guardados.", + "unsavedchangespopup": "" + }, + "validation": { + "dateRangeExceeded": "", + "invalidemail": "Por favor introduzca una dirección de correo electrónico válida.", + "invalidphone": "", + "required": "Este campo es requerido." + } + }, + "help": { + "actions": { + "connect": "" + }, + "labels": { + "codeplacholder": "", + "rescuedesc": "", + "rescuetitle": "" + } + }, + "intake": { + "labels": { + "printpack": "" + } + }, + "inventory": { + "actions": { + "addtoinventory": "", + "addtoro": "", + "consumefrominventory": "", + "edit": "", + "new": "" + }, + "errors": { + "inserting": "" + }, + "fields": { + "comment": "", + "manualinvoicenumber": "", + "manualvendor": "" + }, + "labels": { + "consumedbyjob": "", + "deleteconfirm": "", + "frombillinvoicenumber": "", + "fromvendor": "", + "inventory": "", + "showall": "", + "showavailable": "" + }, + "successes": { + "deleted": "", + "inserted": "", + "updated": "" + } + }, + "job_lifecycle": { + "columns": { + "average_human_readable": "", + "average_value": "", + "duration": "", + "end": "", + "human_readable": "", + "percentage": "", + "relative_end": "", + "relative_start": "", + "start": "", + "status": "", + "status_count": "", + "value": "" + }, + "content": { + "calculated_based_on": "", + "current_status_accumulated_time": "", + "data_unavailable": "", + "jobs_in_since": "", + "legend_title": "", + "loading": "", + "not_available": "", + "previous_status_accumulated_time": "", + "title": "", + "title_durations": "", + "title_loading": "", + "title_transitions": "" + }, + "errors": { + "fetch": "Error al obtener los datos del ciclo de vida del trabajo" + }, + "titles": { + "dashboard": "", + "top_durations": "" + } + }, + "job_payments": { + "buttons": { + "create_short_link": "", + "goback": "", + "proceedtopayment": "", + "refundpayment": "" + }, + "notifications": { + "error": { + "description": "", + "openingip": "", + "title": "" + } + }, + "titles": { + "amount": "", + "dateOfPayment": "", + "descriptions": "", + "hint": "", + "payer": "", + "payername": "", + "paymentid": "", + "paymentnum": "", + "paymenttype": "", + "refundamount": "", + "transactionid": "" + } + }, + "joblines": { + "actions": { + "assign_team": "", + "converttolabor": "", + "dispatchparts": "", + "new": "" + }, + "errors": { + "creating": "", + "updating": "" + }, + "fields": { + "act_price": "Precio actual", + "act_price_before_ppc": "", + "adjustment": "", + "ah_detail_line": "", + "alt_partno": "", + "amount": "", + "assigned_team": "", + "assigned_team_name": "", + "create_ppc": "", + "db_price": "Precio de base de datos", + "include_in_part_cnt": "", + "lbr_types": { + "LA1": "", + "LA2": "", + "LA3": "", + "LA4": "", + "LAA": "", + "LAB": "", + "LAD": "", + "LAE": "", + "LAF": "", + "LAG": "", + "LAM": "", + "LAR": "", + "LAS": "", + "LAU": "" + }, + "line_desc": "Descripción de línea", + "line_ind": "S#", + "line_no": "", + "location": "", + "mod_lb_hrs": "Horas laborales", + "mod_lbr_ty": "Tipo de trabajo", + "notes": "", + "oem_partno": "OEM parte #", + "op_code_desc": "", + "part_qty": "", + "part_type": "Tipo de parte", + "part_types": { + "CCC": "", + "CCD": "", + "CCDR": "", + "CCF": "", + "CCM": "", + "PAA": "", + "PAC": "", + "PAE": "", + "PAG": "", + "PAL": "", + "PAM": "", + "PAN": "", + "PAO": "", + "PAP": "", + "PAR": "", + "PAS": "", + "PASL": "" + }, + "profitcenter_labor": "", + "profitcenter_part": "", + "prt_dsmk_m": "", + "prt_dsmk_p": "", + "status": "Estado", + "tax_part": "", + "total": "", + "unq_seq": "Seq #" + }, + "labels": { + "adjustmenttobeadded": "", + "billref": "", + "convertedtolabor": "", + "edit": "Línea de edición", + "ioucreated": "", + "new": "Nueva línea", + "nostatus": "", + "presets": "" + }, + "successes": { + "created": "", + "saved": "", + "updated": "" + }, + "validations": { + "ahdetailonlyonuserdefinedtypes": "", + "hrsrequirediflbrtyp": "", + "requiredifparttype": "", + "zeropriceexistingpart": "" + } + }, + "jobs": { + "actions": { + "addDocuments": "Agregar documentos de trabajo", + "addNote": "Añadir la nota", + "addtopartsqueue": "", + "addtoproduction": "", + "addtoscoreboard": "", + "allocate": "", + "autoallocate": "", + "changefilehandler": "", + "changelaborrate": "", + "changestatus": "Cambiar Estado", + "changestimator": "", + "convert": "Convertir", + "createiou": "", + "deliver": "", + "deliver_quick": "", + "dms": { + "addpayer": "", + "createnewcustomer": "", + "findmakemodelcode": "", + "getmakes": "", + "labels": { + "refreshallocations": "" + }, + "post": "", + "refetchmakesmodels": "", + "usegeneric": "", + "useselected": "" + }, + "dmsautoallocate": "", + "export": "", + "exportcustdata": "", + "exportselected": "", + "filterpartsonly": "", + "generatecsi": "", + "gotojob": "", + "intake": "", + "intake_quick": "", + "manualnew": "", + "mark": "", + "markasexported": "", + "markpstexempt": "", + "markpstexemptconfirm": "", + "postbills": "Contabilizar facturas", + "printCenter": "Centro de impresión", + "recalculate": "", + "reconcile": "", + "removefromproduction": "", + "schedule": "Programar", + "sendcsi": "", + "sendpartspricechange": "", + "sendtodms": "", + "sync": "", + "taxprofileoverride": "", + "taxprofileoverride_confirm": "", + "uninvoice": "", + "unvoid": "", + "viewchecklist": "", + "viewdetail": "" + }, + "errors": { + "addingtoproduction": "", + "cannotintake": "", + "closing": "", + "creating": "", + "deleted": "Error al eliminar el trabajo.", + "exporting": "", + "exporting-partner": "", + "invoicing": "", + "noaccess": "Este trabajo no existe o no tiene acceso a él.", + "nodamage": "", + "nodates": "No hay fechas especificadas para este trabajo.", + "nofinancial": "", + "nojobselected": "No hay trabajo seleccionado.", + "noowner": "Ningún propietario asociado.", + "novehicle": "No hay vehículo asociado.", + "partspricechange": "", + "saving": "Se encontró un error al guardar el registro.", + "scanimport": "", + "totalscalc": "", + "updating": "", + "validation": "Asegúrese de que todos los campos se ingresen correctamente.", + "validationtitle": "Error de validacion", + "voiding": "" + }, + "fields": { + "active_tasks": "", + "actual_completion": "Realización real", + "actual_delivery": "Entrega real", + "actual_in": "Real en", + "adjustment_bottom_line": "Ajustes", + "adjustmenthours": "", + "alt_transport": "", + "area_of_damage_impact": { + "10": "", + "11": "", + "12": "", + "13": "", + "14": "", + "15": "", + "16": "", + "25": "", + "26": "", + "27": "", + "28": "", + "34": "", + "01": "", + "02": "", + "03": "", + "04": "", + "05": "", + "06": "", + "07": "", + "08": "", + "09": "" + }, + "auto_add_ats": "", + "ca_bc_pvrt": "", + "ca_customer_gst": "", + "ca_gst_registrant": "", + "category": "", + "ccc": "", + "ccd": "", + "ccdr": "", + "ccf": "", + "ccm": "", + "cieca_id": "CIECA ID", + "cieca_pfl": { + "lbr_adjp": "", + "lbr_tax_in": "", + "lbr_taxp": "", + "lbr_tx_in1": "", + "lbr_tx_in2": "", + "lbr_tx_in3": "", + "lbr_tx_in4": "", + "lbr_tx_in5": "" + }, + "cieca_pfo": { + "stor_t_in1": "", + "stor_t_in2": "", + "stor_t_in3": "", + "stor_t_in4": "", + "stor_t_in5": "", + "tow_t_in1": "", + "tow_t_in2": "", + "tow_t_in3": "", + "tow_t_in4": "", + "tow_t_in5": "" + }, + "claim_total": "Reclamar total", + "class": "", + "clm_no": "Reclamación #", + "clm_total": "Reclamar total", + "comment": "", + "customerowing": "Cliente debido", + "date_estimated": "Fecha estimada", + "date_exported": "Exportado", + "date_invoiced": "Facturado", + "date_last_contacted": "", + "date_lost_sale": "", + "date_next_contact": "", + "date_open": "Abierto", + "date_rentalresp": "", + "date_repairstarted": "", + "date_scheduled": "Programado", + "date_towin": "", + "date_void": "", + "ded_amt": "Deducible", + "ded_note": "", + "ded_status": "Estado deducible", + "depreciation_taxes": "Depreciación / Impuestos", + "dms": { + "address": "", + "amount": "", + "center": "", + "control_type": { + "account_number": "" + }, + "cost": "", + "cost_dms_acctnumber": "", + "dms_make": "", + "dms_model": "", + "dms_model_override": "", + "dms_unsold": "", + "dms_wip_acctnumber": "", + "id": "", + "inservicedate": "", + "journal": "", + "lines": "", + "name1": "", + "payer": { + "amount": "", + "control_type": "", + "controlnumber": "", + "dms_acctnumber": "", + "name": "" + }, + "sale": "", + "sale_dms_acctnumber": "", + "story": "", + "vinowner": "" + }, + "dms_allocation": "", + "driveable": "", + "employee_body": "", + "employee_csr": "Representante de servicio al cliente.", + "employee_csr_writer": "", + "employee_prep": "", + "employee_refinish": "", + "est_addr1": "Dirección del tasador", + "est_co_nm": "Tasador", + "est_ct_fn": "Nombre del tasador", + "est_ct_ln": "Apellido del tasador", + "est_ea": "Correo electrónico del tasador", + "est_ph1": "Número de teléfono del tasador", + "federal_tax_payable": "Impuesto federal por pagar", + "federal_tax_rate": "", + "ins_addr1": "Dirección de Insurance Co.", + "ins_city": "Ciudad de seguros", + "ins_co_id": "ID de la compañía de seguros", + "ins_co_nm": "Nombre de la compañía de seguros", + "ins_co_nm_short": "", + "ins_ct_fn": "Nombre del controlador de archivos", + "ins_ct_ln": "Apellido del manejador de archivos", + "ins_ea": "Correo electrónico del controlador de archivos", + "ins_ph1": "File Handler Phone #", + "intake": { + "label": "", + "max": "", + "min": "", + "name": "", + "required": "", + "type": "" + }, + "invoice_final_note": "", + "kmin": "Kilometraje en", + "kmout": "Kilometraje", + "la1": "", + "la2": "", + "la3": "", + "la4": "", + "laa": "", + "lab": "", + "labor_rate_desc": "Nombre de la tasa laboral", + "lad": "", + "lae": "", + "laf": "", + "lag": "", + "lam": "", + "lar": "", + "las": "", + "lau": "", + "local_tax_rate": "", + "loss_date": "Fecha de pérdida", + "loss_desc": "", + "loss_of_use": "", + "lost_sale_reason": "", + "ma2s": "", + "ma3s": "", + "mabl": "", + "macs": "", + "mahw": "", + "mapa": "", + "mash": "", + "matd": "", + "materials": { + "MAPA": "", + "MASH": "", + "cal_maxdlr": "", + "cal_opcode": "", + "mat_adjp": "", + "mat_taxp": "", + "mat_tx_in1": "", + "mat_tx_in2": "", + "mat_tx_in3": "", + "mat_tx_in4": "", + "mat_tx_in5": "", + "materials": "", + "tax_ind": "" + }, + "other_amount_payable": "Otra cantidad a pagar", + "owner": "Propietario", + "owner_owing": "Cust. Debe", + "ownr_ea": "Email", + "ownr_ph1": "Teléfono 1", + "ownr_ph2": "", + "paa": "", + "pac": "", + "pae": "", + "pag": "", + "pal": "", + "pam": "", + "pan": "", + "pao": "", + "pap": "", + "par": "", + "parts_tax_rates": { + "prt_discp": "", + "prt_mktyp": "", + "prt_mkupp": "", + "prt_tax_in": "", + "prt_tax_rt": "", + "prt_tx_in1": "", + "prt_tx_in2": "", + "prt_tx_in3": "", + "prt_tx_in4": "", + "prt_tx_in5": "", + "prt_tx_ty1": "", + "prt_type": "" + }, + "partsstatus": "", + "pas": "", + "pay_date": "Fecha de Pay", + "phoneshort": "PH", + "po_number": "", + "policy_no": "Política #", + "ponumber": "numero postal", + "production_vars": { + "note": "" + }, + "qb_multiple_payers": { + "amount": "", + "name": "" + }, + "queued_for_parts": "", + "rate_ats": "", + "rate_la1": "Tarifa LA1", + "rate_la2": "Tarifa LA2", + "rate_la3": "Tarifa LA3", + "rate_la4": "Tarifa LA4", + "rate_laa": "Tasa de aluminio", + "rate_lab": "Tasa de trabajo", + "rate_lad": "Tasa de diagnóstico", + "rate_lae": "tarifa eléctrica", + "rate_laf": "Cuadros por segundo", + "rate_lag": "Tasa de vidrio", + "rate_lam": "Tasa mecánica", + "rate_lar": "Tasa de acabado", + "rate_las": "", + "rate_lau": "", + "rate_ma2s": "Velocidad de pintura de 2 etapas", + "rate_ma3s": "Tasa de pintura de 3 etapas", + "rate_mabl": "MABL ??", + "rate_macs": "MACS ??", + "rate_mahw": "Tasa de residuos peligrosos", + "rate_mapa": "Tasa de materiales de pintura", + "rate_mash": "Comprar material de tarifa", + "rate_matd": "Tasa de eliminación de neumáticos", + "referral_source_extra": "", + "referral_source_other": "", + "referralsource": "Fuente de referencia", + "regie_number": "N. ° de registro", + "repairtotal": "Reparación total", + "ro_number": "RO #", + "scheduled_completion": "Finalización programada", + "scheduled_delivery": "Entrega programada", + "scheduled_in": "Programado en", + "selling_dealer": "Distribuidor vendedor", + "selling_dealer_contact": "Contacto con el vendedor", + "servicecar": "Auto de servicio", + "servicing_dealer": "Distribuidor de servicio", + "servicing_dealer_contact": "Servicio Contacto con el concesionario", + "special_coverage_policy": "Política de cobertura especial", + "specialcoveragepolicy": "Política de cobertura especial", + "state_tax_rate": "", + "status": "Estado del trabajo", + "storage_payable": "Almacenamiento ", + "tax_lbr_rt": "", + "tax_levies_rt": "", + "tax_paint_mat_rt": "", + "tax_registration_number": "", + "tax_shop_mat_rt": "", + "tax_str_rt": "", + "tax_sub_rt": "", + "tax_tow_rt": "", + "tlos_ind": "", + "towin": "", + "towing_payable": "Remolque a pagar", + "unitnumber": "Unidad #", + "updated_at": "Actualizado en", + "uploaded_by": "Subido por", + "vehicle": "Vehículo" + }, + "forms": { + "admindates": "", + "appraiserinfo": "", + "claiminfo": "", + "estdates": "", + "laborrates": "", + "lossinfo": "", + "other": "", + "repairdates": "", + "scheddates": "" + }, + "labels": { + "accountsreceivable": "", + "act_price_ppc": "", + "actual_completion_inferred": "", + "actual_delivery_inferred": "", + "actual_in_inferred": "", + "additionalpayeroverallocation": "", + "additionaltotal": "", + "adjustmentrate": "", + "adjustments": "", + "adminwarning": "", + "allocations": "", + "alreadyaddedtoscoreboard": "", + "alreadyclosed": "", + "appointmentconfirmation": "¿Enviar confirmación al cliente?", + "associationwarning": "", + "audit": "", + "available": "", + "availablejobs": "", + "ca_bc_pvrt": { + "days": "", + "rate": "" + }, + "ca_gst_all_if_null": "", + "calc_repair_days": "", + "calc_repair_days_tt": "", + "calc_scheuled_completion": "", + "cards": { + "customer": "Información al cliente", + "damage": "Área de Daño", + "dates": "fechas", + "documents": "Documentos recientes", + "estimator": "Estimador", + "filehandler": "File Handler", + "insurance": "detalles del seguro", + "more": "Más", + "notes": "Notas", + "parts": "Partes", + "totals": "Totales", + "vehicle": "Vehículo" + }, + "changeclass": "", + "checklistcompletedby": "", + "checklistdocuments": "", + "checklists": "", + "cieca_pfl": "", + "cieca_pfo": "", + "cieca_pft": "", + "closeconfirm": "", + "closejob": "", + "closingperiod": "", + "contracts": "", + "convertedtolabor": "", + "cost": "", + "cost_Additional": "", + "cost_labor": "", + "cost_parts": "", + "cost_sublet": "", + "costs": "", + "create": { + "jobinfo": "", + "newowner": "", + "newvehicle": "", + "novehicle": "", + "ownerinfo": "", + "vehicleinfo": "" + }, + "createiouwarning": "", + "creating_new_job": "Creando nuevo trabajo ...", + "deductible": { + "stands": "", + "waived": "" + }, + "deleteconfirm": "", + "deletedelivery": "", + "deleteintake": "", + "deliverchecklist": "", + "difference": "", + "diskscan": "", + "dms": { + "apexported": "", + "damageto": "", + "defaultstory": "", + "disablebillwip": "", + "invoicedatefuture": "", + "kmoutnotgreaterthankmin": "", + "logs": "", + "notallocated": "", + "postingform": "", + "totalallocated": "" + }, + "documents": "documentos", + "documents-images": "", + "documents-other": "", + "duplicateconfirm": "", + "emailaudit": "", + "employeeassignments": "", + "estimatelines": "", + "estimator": "", + "existing_jobs": "Empleos existentes", + "federal_tax_amt": "", + "gpdollars": "", + "gppercent": "", + "hrs_claimed": "", + "hrs_total": "", + "importnote": "", + "inproduction": "", + "intakechecklist": "", + "iou": "", + "job": "", + "jobcosting": "", + "jobtotals": "", + "labor_hrs": "", + "labor_rates_subtotal": "", + "laborallocations": "", + "labortotals": "", + "lines": "Líneas estimadas", + "local_tax_amt": "", + "mapa": "", + "markforreexport": "", + "mash": "", + "masterbypass": "", + "materials": { + "mapa": "" + }, + "missingprofileinfo": "", + "multipayers": "", + "net_repairs": "", + "notes": "Notas", + "othertotal": "", + "outstanding_ar": "", + "outstanding_credit_memos": "", + "outstanding_ppd": "", + "outstanding_reconciliation_discrep": "", + "outstanding_sublets": "", + "outstandinghours": "", + "override_header": "¿Anular encabezado estimado al importar?", + "ownerassociation": "", + "parts": "Partes", + "parts_lines": "", + "parts_received": "", + "parts_tax_rates": "", + "partsfilter": "", + "partssubletstotal": "", + "partstotal": "", + "performance": "", + "pimraryamountpayable": "", + "plitooltips": { + "billtotal": "", + "calculatedcreditsnotreceived": "", + "creditmemos": "", + "creditsnotreceived": "", + "discrep1": "", + "discrep2": "", + "discrep3": "", + "laboradj": "", + "partstotal": "", + "totalreturns": "" + }, + "ppc": "", + "ppdnotexported": "", + "profileadjustments": "", + "profitbypassrequired": "", + "profits": "", + "prt_dsmk_total": "", + "rates": "Tarifas", + "rates_subtotal": "", + "reconciliation": { + "billlinestotal": "", + "byassoc": "", + "byprice": "", + "clear": "", + "discrepancy": "", + "joblinestotal": "", + "multipleactprices": "", + "multiplebilllines": "", + "multiplebillsforactprice": "", + "removedpartsstrikethrough": "" + }, + "reconciliationheader": "", + "relatedros": "", + "remove_from_ar": "", + "returntotals": "", + "ro_guard": { + "enforce_ar": "", + "enforce_bills": "", + "enforce_cm": "", + "enforce_labor": "", + "enforce_ppd": "", + "enforce_profit": "", + "enforce_sublet": "", + "enforce_validation": "", + "enforced": "" + }, + "roguard": "", + "roguardwarnings": "", + "rosaletotal": "", + "sale_additional": "", + "sale_labor": "", + "sale_parts": "", + "sale_sublet": "", + "sales": "", + "savebeforeconversion": "", + "scheduledinchange": "", + "specialcoveragepolicy": "", + "state_tax_amt": "", + "subletsnotcompleted": "", + "subletstotal": "", + "subtotal": "", + "supplementnote": "", + "suspended": "", + "suspense": "", + "tasks": "", + "threshhold": "", + "total_cost": "", + "total_cust_payable": "", + "total_cust_payable_cash_discount": "", + "total_repairs": "", + "total_repairs_cash_discount": "", + "total_sales": "", + "total_sales_tax": "", + "totals": "", + "unvoidnote": "", + "update_scheduled_completion": "", + "vehicle_info": "Vehículo", + "vehicleassociation": "", + "viewallocations": "", + "voidjob": "", + "voidnote": "" + }, + "successes": { + "addedtoproduction": "", + "all_deleted": "{{count}} trabajos eliminados con éxito.", + "closed": "", + "converted": "Trabajo convertido con éxito.", + "created": "Trabajo creado con éxito. Click para ver.", + "creatednoclick": "", + "delete": "", + "deleted": "Trabajo eliminado con éxito.", + "duplicated": "", + "exported": "", + "invoiced": "", + "ioucreated": "", + "partsqueue": "", + "save": "Trabajo guardado con éxito.", + "savetitle": "Registro guardado con éxito.", + "supplemented": "Trabajo complementado con éxito.", + "updated": "", + "voided": "" + } + }, + "landing": { + "bigfeature": { + "subtitle": "", + "title": "" + }, + "footer": { + "company": { + "about": "", + "contact": "", + "disclaimers": "", + "name": "", + "privacypolicy": "" + }, + "io": { + "help": "", + "name": "", + "status": "" + }, + "slogan": "" + }, + "hero": { + "button": "", + "title": "" + }, + "labels": { + "features": "", + "managemyshop": "", + "pricing": "" + }, + "pricing": { + "basic": { + "name": "", + "sub": "" + }, + "essentials": { + "name": "", + "sub": "" + }, + "pricingtitle": "", + "pro": { + "name": "", + "sub": "" + }, + "title": "", + "unlimited": { + "name": "", + "sub": "" + } + } + }, + "menus": { + "currentuser": { + "languageselector": "idioma", + "profile": "Perfil" + }, + "header": { + "accounting": "", + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "activejobs": "Empleos activos", + "all_tasks": "", + "alljobs": "", + "allpayments": "", + "availablejobs": "Trabajos disponibles", + "bills": "", + "courtesycars": "", + "courtesycars-all": "", + "courtesycars-contracts": "", + "courtesycars-newcontract": "", + "create_task": "", + "customers": "Clientes", + "dashboard": "", + "enterbills": "", + "entercardpayment": "", + "enterpayment": "", + "entertimeticket": "", + "export": "", + "export-logs": "", + "help": "", + "home": "Casa", + "inventory": "", + "jobs": "Trabajos", + "my_tasks": "", + "newjob": "", + "owners": "propietarios", + "parts-queue": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "readyjobs": "", + "recent": "", + "reportcenter": "", + "rescueme": "", + "schedule": "Programar", + "scoreboard": "", + "search": { + "bills": "", + "jobs": "", + "owners": "", + "payments": "", + "phonebook": "", + "vehicles": "" + }, + "shiftclock": "", + "shop": "Mi tienda", + "shop_config": "Configuración", + "shop_csi": "", + "shop_templates": "", + "shop_vendors": "Vendedores", + "tasks": "", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicles": "Vehículos" + }, + "jobsactions": { + "admin": "", + "cancelallappointments": "", + "closejob": "", + "deletejob": "", + "duplicate": "", + "duplicatenolines": "", + "newcccontract": "", + "void": "" + }, + "jobsdetail": { + "claimdetail": "Detalles de la reclamación", + "dates": "fechas", + "financials": "", + "general": "", + "insurance": "", + "labor": "Labor", + "lifecycle": "", + "parts": "", + "partssublet": "Piezas / Subarrendamiento", + "rates": "", + "repairdata": "Datos de reparación", + "totals": "" + }, + "profilesidebar": { + "profile": "Mi perfil", + "shops": "Mis tiendas" + }, + "tech": { + "assignedjobs": "", + "claimtask": "", + "dispatchedparts": "", + "home": "", + "jobclockin": "", + "jobclockout": "", + "joblookup": "", + "login": "", + "logout": "", + "productionboard": "", + "productionlist": "", + "shiftclockin": "" + } + }, + "messaging": { + "actions": { + "link": "", + "new": "" + }, + "errors": { + "invalidphone": "", + "noattachedjobs": "", + "updatinglabel": "" + }, + "labels": { + "addlabel": "", + "archive": "", + "maxtenimages": "", + "messaging": "Mensajería", + "noallowtxt": "", + "nojobs": "", + "nopush": "", + "phonenumber": "", + "presets": "", + "recentonly": "", + "selectmedia": "", + "sentby": "", + "typeamessage": "Enviar un mensaje...", + "unarchive": "" + }, + "render": { + "conversation_list": "" + } + }, + "notes": { + "actions": { + "actions": "Comportamiento", + "deletenote": "Borrar nota", + "edit": "Editar nota", + "new": "Nueva nota", + "savetojobnotes": "" + }, + "errors": { + "inserting": "" + }, + "fields": { + "createdby": "Creado por", + "critical": "Crítico", + "private": "Privado", + "text": "Contenido", + "type": "", + "types": { + "customer": "", + "general": "", + "office": "", + "paint": "", + "parts": "", + "shop": "", + "supplement": "" + }, + "updatedat": "Actualizado en" + }, + "labels": { + "addtorelatedro": "", + "newnoteplaceholder": "Agrega una nota...", + "notetoadd": "", + "systemnotes": "", + "usernotes": "" + }, + "successes": { + "create": "Nota creada con éxito.", + "deleted": "Nota eliminada con éxito.", + "updated": "Nota actualizada con éxito." + } + }, + "owner": { + "labels": { + "noownerinfo": "" + } + }, + "owners": { + "actions": { + "update": "" + }, + "errors": { + "deleting": "", + "noaccess": "El registro no existe o no tiene acceso a él.", + "saving": "", + "selectexistingornew": "" + }, + "fields": { + "accountingid": "", + "address": "Dirección", + "allow_text_message": "Permiso de texto?", + "name": "Nombre", + "note": "", + "ownr_addr1": "Dirección", + "ownr_addr2": "Dirección 2", + "ownr_city": "ciudad", + "ownr_co_nm": "", + "ownr_ctry": "País", + "ownr_ea": "Email", + "ownr_fn": "Nombre de pila", + "ownr_ln": "Apellido", + "ownr_ph1": "Teléfono 1", + "ownr_ph2": "", + "ownr_st": "Provincia del estado", + "ownr_title": "Título", + "ownr_zip": "código postal", + "preferred_contact": "Método de Contacto Preferido", + "tax_number": "" + }, + "forms": { + "address": "", + "contact": "", + "name": "" + }, + "labels": { + "create_new": "Crea un nuevo registro de propietario.", + "deleteconfirm": "", + "existing_owners": "Propietarios existentes", + "fromclaim": "", + "fromowner": "", + "relatedjobs": "", + "updateowner": "" + }, + "successes": { + "delete": "", + "save": "Propietario guardado con éxito." + } + }, + "parts": { + "actions": { + "order": "Pedido de piezas", + "orderinhouse": "" + } + }, + "parts_dispatch": { + "actions": { + "accept": "" + }, + "errors": { + "accepting": "", + "creating": "" + }, + "fields": { + "number": "", + "percent_accepted": "" + }, + "labels": { + "notyetdispatched": "", + "parts_dispatch": "" + } + }, + "parts_dispatch_lines": { + "fields": { + "accepted_at": "" + } + }, + "parts_orders": { + "actions": { + "backordered": "", + "receive": "", + "receivebill": "" + }, + "errors": { + "associatedbills": "", + "backordering": "", + "creating": "Se encontró un error al crear el pedido de piezas.", + "oec": "", + "saving": "", + "updating": "" + }, + "fields": { + "act_price": "", + "backordered_eta": "", + "backordered_on": "", + "cm_received": "", + "comments": "", + "cost": "", + "db_price": "", + "deliver_by": "", + "job_line_id": "", + "line_desc": "", + "line_remarks": "", + "lineremarks": "Comentarios de línea", + "oem_partno": "", + "order_date": "", + "order_number": "", + "orderedby": "", + "part_type": "", + "quantity": "", + "return": "", + "status": "" + }, + "labels": { + "allpartsto": "", + "confirmdelete": "", + "custompercent": "", + "discount": "", + "email": "Enviar por correo electrónico", + "inthisorder": "Partes en este pedido", + "is_quote": "", + "mark_as_received": "", + "newpartsorder": "", + "notyetordered": "", + "oec": "", + "order_type": "", + "orderhistory": "Historial de pedidos", + "parts_order": "", + "parts_orders": "", + "parts_returns": "", + "print": "Mostrar formulario impreso", + "receive": "", + "removefrompartsqueue": "", + "returnpartsorder": "", + "sublet_order": "" + }, + "successes": { + "created": "Pedido de piezas creado con éxito.", + "line_updated": "", + "received": "", + "return_created": "" + } + }, + "payments": { + "actions": { + "generatepaymentlink": "" + }, + "errors": { + "exporting": "", + "exporting-partner": "", + "inserting": "" + }, + "fields": { + "amount": "", + "created_at": "", + "date": "", + "exportedat": "", + "memo": "", + "payer": "", + "paymentnum": "", + "stripeid": "", + "transactionid": "", + "type": "" + }, + "labels": { + "balance": "", + "ca_bc_etf_table": "", + "customer": "", + "edit": "", + "electronicpayment": "", + "external": "", + "findermodal": "", + "insurance": "", + "markexported": "", + "markforreexport": "", + "new": "", + "signup": "", + "smspaymentreminder": "", + "title": "", + "totalpayments": "" + }, + "successes": { + "exported": "", + "markexported": "", + "markreexported": "", + "payment": "", + "paymentupdate": "", + "stripe": "" + } + }, + "phonebook": { + "actions": { + "new": "" + }, + "errors": { + "adding": "", + "saving": "" + }, + "fields": { + "address1": "", + "address2": "", + "category": "", + "city": "", + "company": "", + "country": "", + "email": "", + "fax": "", + "firstname": "", + "lastname": "", + "phone1": "", + "phone2": "", + "state": "" + }, + "labels": { + "noneselected": "", + "onenamerequired": "", + "vendorcategory": "" + }, + "successes": { + "added": "", + "deleted": "", + "saved": "" + } + }, + "printcenter": { + "appointments": { + "appointment_confirmation": "" + }, + "bills": { + "inhouse_invoice": "" + }, + "courtesycarcontract": { + "courtesy_car_contract": "", + "courtesy_car_impound": "", + "courtesy_car_inventory": "", + "courtesy_car_terms": "" + }, + "errors": { + "nocontexttype": "" + }, + "jobs": { + "3rdpartyfields": { + "addr1": "", + "addr2": "", + "addr3": "", + "attn": "", + "city": "", + "custgst": "", + "ded_amt": "", + "depreciation": "", + "other": "", + "ponumber": "", + "refnumber": "", + "sendtype": "", + "state": "", + "zip": "" + }, + "3rdpartypayer": "", + "ab_proof_of_loss": "", + "appointment_confirmation": "", + "appointment_reminder": "", + "casl_authorization": "", + "committed_timetickets_ro": "", + "coversheet_landscape": "", + "coversheet_portrait": "", + "csi_invitation": "", + "csi_invitation_action": "", + "diagnostic_authorization": "", + "dms_posting_sheet": "", + "envelope_return_address": "", + "estimate": "", + "estimate_detail": "", + "estimate_followup": "", + "express_repair_checklist": "", + "filing_coversheet_landscape": "", + "filing_coversheet_portrait": "", + "final_invoice": "", + "fippa_authorization": "", + "folder_label_multiple": "", + "glass_express_checklist": "", + "guarantee": "", + "individual_job_note": "", + "invoice_customer_payable": "", + "invoice_total_payable": "", + "iou_form": "", + "job_costing_ro": "", + "job_lifecycle_ro": "", + "job_notes": "", + "job_tasks": "", + "key_tag": "", + "labels": { + "count": "", + "labels": "", + "position": "" + }, + "lag_time_ro": "", + "mechanical_authorization": "", + "mpi_animal_checklist": "", + "mpi_eglass_auth": "", + "mpi_final_acct_sheet": "", + "mpi_final_repair_acct_sheet": "", + "paint_grid": "", + "parts_dispatch": "", + "parts_invoice_label_single": "", + "parts_label_multiple": "", + "parts_label_single": "", + "parts_list": "", + "parts_order": "", + "parts_order_confirmation": "", + "parts_order_history": "", + "parts_return_slip": "", + "payment_receipt": "", + "payment_request": "", + "payments_by_job": "", + "purchases_by_ro_detail": "", + "purchases_by_ro_summary": "", + "qc_sheet": "", + "rental_reservation": "", + "ro_totals": "", + "ro_with_description": "", + "sgi_certificate_of_repairs": "", + "sgi_windshield_auth": "", + "stolen_recovery_checklist": "", + "sublet_order": "", + "supplement_request": "", + "thank_you_ro": "", + "thirdpartypayer": "", + "timetickets_ro": "", + "vehicle_check_in": "", + "vehicle_delivery_check": "", + "window_tag": "", + "window_tag_sublet": "", + "work_authorization": "", + "worksheet_by_line_number": "", + "worksheet_sorted_by_operation": "", + "worksheet_sorted_by_operation_no_hours": "", + "worksheet_sorted_by_operation_part_type": "", + "worksheet_sorted_by_operation_type": "", + "worksheet_sorted_by_team": "" + }, + "labels": { + "groups": { + "authorization": "", + "financial": "", + "post": "", + "pre": "", + "ro": "", + "worksheet": "" + }, + "misc": "", + "repairorder": "", + "reportcentermodal": "", + "speedprint": "", + "title": "" + }, + "payments": { + "ca_bc_etf_table": "", + "exported_payroll": "" + }, + "special": { + "attendance_detail_csv": "" + }, + "subjects": { + "jobs": { + "individual_job_note": "", + "parts_dispatch": "", + "parts_order": "", + "parts_return_slip": "", + "sublet_order": "" + } + }, + "vendors": { + "purchases_by_vendor_detailed": "", + "purchases_by_vendor_summary": "" + } + }, + "production": { + "actions": { + "addcolumns": "", + "bodypriority-clear": "", + "bodypriority-set": "", + "detailpriority-clear": "", + "detailpriority-set": "", + "paintpriority-clear": "", + "paintpriority-set": "", + "remove": "", + "removecolumn": "", + "saveconfig": "", + "suspend": "", + "unsuspend": "" + }, + "constants": { + "main_profile": "" + }, + "errors": { + "boardupdate": "", + "name_exists": "", + "name_required": "", + "removing": "", + "settings": "" + }, + "labels": { + "actual_in": "", + "addnewprofile": "", + "alert": "", + "alertoff": "", + "alerton": "", + "alerts": "", + "ats": "", + "bodyhours": "", + "bodypriority": "", + "bodyshop": { + "labels": { + "qbo_departmentid": "", + "qbo_usa": "" + } + }, + "card_size": "", + "cardcolor": "", + "cardsettings": "", + "clm_no": "", + "comment": "", + "compact": "", + "detailpriority": "", + "employeeassignments": "", + "employeesearch": "", + "estimator": "", + "horizontal": "", + "ins_co_nm": "", + "jobdetail": "", + "kiosk_mode": "", + "laborhrs": "", + "legend": "", + "model_info": "", + "note": "", + "off": "", + "on": "", + "orientation": "", + "ownr_nm": "", + "paintpriority": "", + "partsstatus": "", + "production_note": "", + "refinishhours": "", + "scheduled_completion": "", + "selectview": "", + "stickyheader": "", + "sublets": "", + "subtotal": "", + "tall": "", + "tasks": "", + "totalhours": "", + "touchtime": "", + "unassigned": "", + "vertical": "", + "viewname": "", + "wide": "" + }, + "options": { + "horizontal": "", + "large": "", + "medium": "", + "small": "", + "vertical": "" + }, + "settings": { + "board_settings": "", + "filters": { + "md_estimators": "", + "md_ins_cos": "" + }, + "filters_title": "", + "information": "", + "layout": "", + "statistics": { + "jobs_in_production": "", + "tasks_in_production": "", + "tasks_in_view": "", + "tasks_on_board": "", + "total_amount_in_production": "", + "total_amount_in_view": "", + "total_amount_on_board": "", + "total_hours_in_production": "", + "total_hours_in_view": "", + "total_hours_on_board": "", + "total_jobs_in_view": "", + "total_jobs_on_board": "", + "total_lab_in_production": "", + "total_lab_in_view": "", + "total_lab_on_board": "", + "total_lar_in_production": "", + "total_lar_in_view": "", + "total_lar_on_board": "" + }, + "statistics_title": "" + }, + "statistics": { + "currency_symbol": "", + "hours": "", + "jobs": "", + "jobs_in_production": "", + "tasks": "", + "tasks_in_production": "", + "tasks_in_view": "", + "tasks_on_board": "", + "total_amount_in_production": "", + "total_amount_in_view": "", + "total_amount_on_board": "", + "total_hours_in_production": "", + "total_hours_in_view": "", + "total_hours_on_board": "", + "total_jobs_in_view": "", + "total_jobs_on_board": "", + "total_lab_in_production": "", + "total_lab_in_view": "", + "total_lab_on_board": "", + "total_lar_in_production": "", + "total_lar_in_view": "", + "total_lar_on_board": "" + }, + "successes": { + "removed": "" + } + }, + "profile": { + "errors": { + "state": "Error al leer el estado de la página. Porfavor refresca." + }, + "labels": { + "activeshop": "" + }, + "successes": { + "updated": "" + } + }, + "reportcenter": { + "actions": { + "generate": "" + }, + "labels": { + "advanced_filters": "", + "advanced_filters_false": "", + "advanced_filters_filter_field": "", + "advanced_filters_filter_operator": "", + "advanced_filters_filter_value": "", + "advanced_filters_filters": "", + "advanced_filters_hide": "", + "advanced_filters_show": "", + "advanced_filters_sorter_direction": "", + "advanced_filters_sorter_field": "", + "advanced_filters_sorters": "", + "advanced_filters_true": "", + "dates": "", + "employee": "", + "filterson": "", + "generateasemail": "", + "groups": { + "customers": "", + "jobs": "", + "payroll": "", + "purchases": "", + "sales": "" + }, + "key": "", + "objects": { + "appointments": "", + "bills": "", + "csi": "", + "exportlogs": "", + "jobs": "", + "parts_orders": "", + "payments": "", + "scoreboard": "", + "tasks": "", + "timetickets": "" + }, + "vendor": "" + }, + "templates": { + "adp_payroll_flat": "", + "adp_payroll_straight": "", + "anticipated_revenue": "", + "ar_aging": "", + "attendance_detail": "", + "attendance_employee": "", + "attendance_summary": "", + "committed_timetickets": "", + "committed_timetickets_employee": "", + "committed_timetickets_summary": "", + "credits_not_received_date": "", + "credits_not_received_date_vendorid": "", + "csi": "", + "customer_list": "", + "cycle_time_analysis": "", + "estimates_written_converted": "", + "estimator_detail": "", + "estimator_summary": "", + "export_payables": "", + "export_payments": "", + "export_receivables": "", + "exported_gsr_by_ro": "", + "exported_gsr_by_ro_labor": "", + "gsr_by_atp": "", + "gsr_by_ats": "", + "gsr_by_category": "", + "gsr_by_csr": "", + "gsr_by_delivery_date": "", + "gsr_by_estimator": "", + "gsr_by_exported_date": "", + "gsr_by_ins_co": "", + "gsr_by_make": "", + "gsr_by_referral": "", + "gsr_by_ro": "", + "gsr_labor_only": "", + "hours_sold_detail_closed": "", + "hours_sold_detail_closed_csr": "", + "hours_sold_detail_closed_estimator": "", + "hours_sold_detail_closed_ins_co": "", + "hours_sold_detail_closed_status": "", + "hours_sold_detail_open": "", + "hours_sold_detail_open_csr": "", + "hours_sold_detail_open_estimator": "", + "hours_sold_detail_open_ins_co": "", + "hours_sold_detail_open_status": "", + "hours_sold_summary_closed": "", + "hours_sold_summary_closed_csr": "", + "hours_sold_summary_closed_estimator": "", + "hours_sold_summary_closed_ins_co": "", + "hours_sold_summary_closed_status": "", + "hours_sold_summary_open": "", + "hours_sold_summary_open_csr": "", + "hours_sold_summary_open_estimator": "", + "hours_sold_summary_open_ins_co": "", + "hours_sold_summary_open_status": "", + "job_costing_ro_csr": "", + "job_costing_ro_date_detail": "", + "job_costing_ro_date_summary": "", + "job_costing_ro_estimator": "", + "job_costing_ro_ins_co": "", + "job_lifecycle_date_detail": "", + "job_lifecycle_date_summary": "", + "jobs_completed_not_invoiced": "", + "jobs_invoiced_not_exported": "", + "jobs_reconcile": "", + "jobs_scheduled_completion": "", + "lag_time": "", + "load_level": "", + "lost_sales": "", + "open_orders": "", + "open_orders_csr": "", + "open_orders_estimator": "", + "open_orders_excel": "", + "open_orders_ins_co": "", + "open_orders_referral": "", + "open_orders_specific_csr": "", + "open_orders_status": "", + "parts_backorder": "", + "parts_not_recieved": "", + "parts_not_recieved_vendor": "", + "parts_received_not_scheduled": "", + "payments_by_date": "", + "payments_by_date_payment": "", + "payments_by_date_type": "", + "production_by_category": "", + "production_by_category_one": "", + "production_by_csr": "", + "production_by_last_name": "", + "production_by_repair_status": "", + "production_by_repair_status_one": "", + "production_by_ro": "", + "production_by_target_date": "", + "production_by_technician": "", + "production_by_technician_one": "", + "production_not_production_status": "", + "production_over_time": "", + "psr_by_make": "", + "purchase_return_ratio_excel": "", + "purchase_return_ratio_grouped_by_vendor_detail": "", + "purchase_return_ratio_grouped_by_vendor_summary": "", + "purchases_by_cost_center_detail": "", + "purchases_by_cost_center_summary": "", + "purchases_by_date_excel": "", + "purchases_by_date_range_detail": "", + "purchases_by_date_range_summary": "", + "purchases_by_ro_detail_date": "", + "purchases_by_ro_summary_date": "", + "purchases_by_vendor_detailed_date_range": "", + "purchases_by_vendor_summary_date_range": "", + "purchases_grouped_by_vendor_detailed": "", + "purchases_grouped_by_vendor_summary": "", + "returns_grouped_by_vendor_detailed": "", + "returns_grouped_by_vendor_summary": "", + "schedule": "", + "scheduled_parts_list": "", + "scoreboard_detail": "", + "scoreboard_summary": "", + "supplement_ratio_ins_co": "", + "tasks_date": "", + "tasks_date_employee": "", + "thank_you_date": "", + "timetickets": "", + "timetickets_employee": "", + "timetickets_summary": "", + "total_loss_jobs": "", + "unclaimed_hrs": "", + "void_ros": "", + "work_in_progress_committed_labour": "", + "work_in_progress_jobs": "", + "work_in_progress_labour": "", + "work_in_progress_payables": "" + } + }, + "schedule": { + "labels": { + "atssummary": "", + "employeevacation": "", + "estimators": "", + "ins_co_nm_filter": "", + "intake": "", + "manual": "", + "manualevent": "" + } + }, + "scoreboard": { + "actions": { + "edit": "" + }, + "errors": { + "adding": "", + "removing": "", + "updating": "" + }, + "fields": { + "bodyhrs": "", + "date": "", + "painthrs": "" + }, + "labels": { + "allemployeetimetickets": "", + "asoftodaytarget": "", + "body": "", + "bodyabbrev": "", + "bodycharttitle": "", + "calendarperiod": "", + "combinedcharttitle": "", + "dailyactual": "", + "dailytarget": "", + "efficiencyoverperiod": "", + "entries": "", + "jobs": "", + "jobscompletednotinvoiced": "", + "lastmonth": "", + "lastweek": "", + "monthlytarget": "", + "priorweek": "", + "productivestatistics": "", + "productivetimeticketsoverdate": "", + "refinish": "", + "refinishabbrev": "", + "refinishcharttitle": "", + "targets": "", + "thismonth": "", + "thisweek": "", + "timetickets": "", + "timeticketsemployee": "", + "todateactual": "", + "total": "", + "totalhrs": "", + "totaloverperiod": "", + "weeklyactual": "", + "weeklytarget": "", + "workingdays": "" + }, + "successes": { + "added": "", + "removed": "", + "updated": "" + } + }, + "tasks": { + "actions": { + "edit": "", + "new": "", + "view": "" + }, + "buttons": { + "allTasks": "", + "complete": "", + "create": "", + "delete": "", + "edit": "", + "myTasks": "", + "refresh": "" + }, + "date_presets": { + "completion": "", + "day": "", + "days": "", + "delivery": "", + "next_week": "", + "one_month": "", + "three_months": "", + "three_weeks": "", + "today": "", + "tomorrow": "", + "two_weeks": "" + }, + "failures": { + "completed": "", + "created": "", + "deleted": "", + "updated": "" + }, + "fields": { + "actions": "", + "assigned_to": "", + "bill": "", + "billid": "", + "completed": "", + "created_at": "", + "created_by": "", + "description": "", + "due_date": "", + "job": { + "ro_number": "" + }, + "jobid": "", + "jobline": "", + "joblineid": "", + "parts_order": "", + "partsorderid": "", + "priorities": { + "high": "", + "low": "", + "medium": "" + }, + "priority": "", + "related_items": "", + "remind_at": "", + "title": "" + }, + "placeholders": { + "assigned_to": "", + "billid": "", + "description": "", + "jobid": "", + "joblineid": "", + "partsorderid": "" + }, + "successes": { + "completed": "", + "created": "", + "deleted": "", + "updated": "" + }, + "titles": { + "all_tasks": "", + "completed": "", + "deleted": "", + "job_tasks": "", + "mine": "", + "my_tasks": "" + }, + "validation": { + "due_at_error_message": "", + "remind_at_error_message": "" + } + }, + "tech": { + "fields": { + "employeeid": "", + "pin": "" + }, + "labels": { + "loggedin": "", + "notloggedin": "" + } + }, + "templates": { + "errors": { + "updating": "" + }, + "successes": { + "updated": "" + } + }, + "timetickets": { + "actions": { + "claimtasks": "", + "clockin": "", + "clockout": "", + "commit": "", + "commitone": "", + "enter": "", + "payall": "", + "printemployee": "", + "uncommit": "" + }, + "errors": { + "clockingin": "", + "clockingout": "", + "creating": "", + "deleting": "", + "noemployeeforuser": "", + "noemployeeforuser_sub": "", + "payall": "", + "shiftalreadyclockedon": "" + }, + "fields": { + "actualhrs": "", + "ciecacode": "", + "clockhours": "", + "clockoff": "", + "clockon": "", + "committed": "", + "committed_at": "", + "cost_center": "", + "created_by": "", + "date": "", + "efficiency": "", + "employee": "", + "employee_team": "", + "flat_rate": "", + "memo": "", + "productivehrs": "", + "ro_number": "", + "task_name": "" + }, + "labels": { + "alreadyclockedon": "", + "ambreak": "", + "amshift": "", + "claimtaskpreview": "", + "clockhours": "", + "clockintojob": "", + "deleteconfirm": "", + "edit": "", + "efficiency": "", + "flat_rate": "", + "jobhours": "", + "lunch": "", + "new": "", + "payrollclaimedtasks": "", + "pmbreak": "", + "pmshift": "", + "shift": "", + "shiftalreadyclockedon": "", + "straight_time": "", + "task": "", + "timetickets": "", + "unassigned": "", + "zeroactualnegativeprod": "" + }, + "successes": { + "clockedin": "", + "clockedout": "", + "committed": "", + "created": "", + "deleted": "", + "payall": "" + }, + "validation": { + "clockoffmustbeafterclockon": "", + "clockoffwithoutclockon": "", + "hoursenteredmorethanavailable": "", + "unassignedlines": "" + } + }, + "titles": { + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "all_tasks": "", + "app": "", + "bc": { + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "all_tasks": "", + "availablejobs": "", + "bills-list": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-detail": "", + "courtesycars-new": "", + "dashboard": "", + "dms": "", + "export-logs": "", + "inventory": "", + "jobs": "", + "jobs-active": "", + "jobs-admin": "", + "jobs-all": "", + "jobs-checklist": "", + "jobs-close": "", + "jobs-deliver": "", + "jobs-detail": "", + "jobs-intake": "", + "jobs-new": "", + "jobs-ready": "", + "my_tasks": "", + "owner-detail": "", + "owners": "", + "parts-queue": "", + "payments-all": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "profile": "", + "schedule": "", + "scoreboard": "", + "shop": "", + "shop-csi": "", + "shop-templates": "", + "shop-vendors": "", + "tasks": "", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicle-details": "", + "vehicles": "" + }, + "bills-list": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-create": "", + "courtesycars-detail": "", + "dashboard": "", + "dms": "", + "export-logs": "", + "imexonline": "", + "inventory": "", + "jobs": "Todos los trabajos | {{app}}", + "jobs-admin": "", + "jobs-all": "", + "jobs-checklist": "", + "jobs-close": "", + "jobs-create": "", + "jobs-deliver": "", + "jobs-intake": "", + "jobsavailable": "Empleos disponibles | {{app}}", + "jobsdetail": "Trabajo {{ro_number}} | {{app}}", + "jobsdocuments": "Documentos de trabajo {{ro_number}} | {{app}}", + "manageroot": "Casa | {{app}}", + "my_tasks": "", + "owners": "Todos los propietarios | {{app}}", + "owners-detail": "", + "parts-queue": "", + "payments-all": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "profile": "Mi perfil | {{app}}", + "readyjobs": "", + "resetpassword": "", + "resetpasswordvalidate": "", + "romeonline": "", + "schedule": "Horario | {{app}}", + "scoreboard": "", + "shop": "Mi tienda | {{app}}", + "shop-csi": "", + "shop-templates": "", + "shop_vendors": "Vendedores | {{app}}", + "tasks": "", + "techconsole": "{{app}}", + "techjobclock": "{{app}}", + "techjoblookup": "{{app}}", + "techshiftclock": "{{app}}", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicledetail": "Detalles del vehículo {{vehicle}} | {{app}}", + "vehicles": "Todos los vehiculos | {{app}}" + }, + "trello": { + "labels": { + "add_card": "", + "add_lane": "", + "cancel": "", + "delete_lane": "", + "description": "", + "label": "", + "lane_actions": "", + "title": "" + } + }, + "tt_approvals": { + "actions": { + "approveselected": "" + }, + "labels": { + "approval_queue_in_use": "", + "calculate": "" + } + }, + "upsell": { + "cta": { + "learnmore": "" + }, + "messages": { + "accounting": { + "payables": { + "subtitle": "", + "title": "" + }, + "payments": { + "subtitle": "", + "title": "" + }, + "receivables": { + "subtitle": "", + "title": "" + } + }, + "audit": { + "general": { + "subtitle": "", + "title": "" + } + }, + "bills": { + "autoreconcile": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + } + }, + "checklist": { + "general": { + "subtitle": "", + "title": "" + } + }, + "courtesycars": { + "general": { + "subtitle": "", + "title": "" + } + }, + "csi": { + "general": { + "subtitle": "", + "title": "" + } + }, + "dashboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "lifecycle": { + "general": { + "subtitle": "", + "title": "" + } + }, + "media": { + "general": { + "subtitle": "", + "title": "" + }, + "mobile": { + "subtitle": "", + "title": "" + } + }, + "payments": { + "general": { + "subtitle": "", + "title": "" + } + }, + "scoreboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "smartscheduling": { + "datepicker": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + }, + "hrsdelta": { + "subtitle": "", + "title": "" + } + }, + "techconsole": { + "general": { + "subtitle": "", + "title": "" + } + }, + "timetickets": { + "allocations": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + } + }, + "visualboard": { + "general": { + "subtitle": "", + "title": "" + } + } + } + }, + "user": { + "actions": { + "changepassword": "", + "signout": "desconectar", + "updateprofile": "Actualización del perfil" + }, + "errors": { + "updating": "" + }, + "fields": { + "authlevel": "", + "displayname": "Nombre para mostrar", + "email": "", + "photourl": "URL de avatar" + }, + "labels": { + "actions": "", + "changepassword": "", + "profileinfo": "" + }, + "successess": { + "passwordchanged": "" + } + }, + "users": { + "errors": { + "signinerror": { + "auth/user-disabled": "", + "auth/user-not-found": "", + "auth/wrong-password": "" + } + } + }, + "vehicles": { + "errors": { + "deleting": "", + "noaccess": "El vehículo no existe o usted no tiene acceso a él.", + "selectexistingornew": "", + "validation": "Asegúrese de que todos los campos se ingresen correctamente.", + "validationtitle": "Error de validacion" + }, + "fields": { + "description": "Descripcion del vehiculo", + "notes": "", + "plate_no": "Placa", + "plate_st": "Jurisdicción de placas", + "trim_color": "Recortar color", + "v_bstyle": "Tipo de cuerpo", + "v_color": "Color", + "v_cond": "condición", + "v_engine": "Motor", + "v_make_desc": "Hacer", + "v_makecode": "Hacer código", + "v_mldgcode": "Código de moldeo", + "v_model_desc": "Modelo", + "v_model_yr": "año", + "v_options": "Opciones", + "v_paint_codes": "Códigos de pintura", + "v_prod_dt": "Fecha de producción", + "v_stage": "Escenario", + "v_tone": "Tono", + "v_trimcode": "Código de recorte", + "v_type": "Tipo", + "v_vin": "V.I.N." + }, + "forms": { + "detail": "", + "misc": "", + "registration": "" + }, + "labels": { + "deleteconfirm": "", + "fromvehicle": "", + "novehinfo": "", + "relatedjobs": "", + "updatevehicle": "" + }, + "successes": { + "delete": "", + "save": "Vehículo guardado con éxito." + } + }, + "vendors": { + "actions": { + "addtophonebook": "", + "new": "Nuevo vendedor", + "newpreferredmake": "" + }, + "errors": { + "deleting": "Se encontró un error al eliminar el proveedor.", + "saving": "Se encontró un error al guardar el proveedor." + }, + "fields": { + "active": "", + "am": "", + "city": "ciudad", + "cost_center": "Centro de costos", + "country": "País", + "discount": "% De descuento", + "display_name": "Nombre para mostrar", + "dmsid": "", + "due_date": "Fecha de vencimiento del pago", + "email": "Email de contacto", + "favorite": "¿Favorito?", + "lkq": "", + "make": "", + "name": "Nombre del vendedor", + "oem": "", + "phone": "", + "prompt_discount": "Descuento pronto", + "state": "Provincia del estado", + "street1": "calle", + "street2": "Dirección 2", + "taxid": "Identificación del impuesto", + "terms": "Términos de pago", + "zip": "código postal" + }, + "labels": { + "noneselected": "Ningún vendedor está seleccionado.", + "preferredmakes": "", + "search": "Escriba el nombre de un proveedor" + }, + "successes": { + "deleted": "Proveedor eliminado correctamente.", + "saved": "Proveedor guardado con éxito." + }, + "validation": { + "unique_vendor_name": "" + } + }, "notifications": { "labels": { "notification-center": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 6dcb4fefd..6e9713285 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1,3772 +1,3782 @@ { - "translation": { - "allocations": { - "actions": { - "assign": "Attribuer" - }, - "errors": { - "deleting": "", - "saving": "", - "validation": "" - }, - "fields": { - "employee": "Alloué à" - }, - "successes": { - "deleted": "", - "save": "" - } - }, - "appointments": { - "actions": { - "block": "", - "calculate": "", - "cancel": "annuler", - "intake": "Admission", - "new": "Nouveau rendez-vous", - "preview": "", - "reschedule": "Replanifier", - "sendreminder": "", - "unblock": "", - "viewjob": "Voir le travail" - }, - "errors": { - "blocking": "", - "canceling": "Erreur lors de l'annulation du rendez-vous. {{message}}", - "saving": "Erreur lors de la planification du rendez-vous. {{message}}" - }, - "fields": { - "alt_transport": "", - "color": "", - "end": "", - "note": "", - "start": "", - "time": "", - "title": "Titre" - }, - "labels": { - "arrivedon": "Arrivé le:", - "arrivingjobs": "", - "blocked": "", - "cancelledappointment": "Rendez-vous annulé pour:", - "completingjobs": "", - "dataconsistency": "", - "expectedjobs": "", - "expectedprodhrs": "", - "history": "", - "inproduction": "", - "manualevent": "", - "noarrivingjobs": "", - "nocompletingjobs": "", - "nodateselected": "Aucune date n'a été sélectionnée.", - "priorappointments": "Rendez-vous précédents", - "reminder": "", - "scheduledfor": "Rendez-vous prévu pour:", - "severalerrorsfound": "", - "smartscheduling": "", - "smspaymentreminder": "", - "suggesteddates": "" - }, - "successes": { - "canceled": "Rendez-vous annulé avec succès.", - "created": "Rendez-vous planifié avec succès.", - "saved": "" - } - }, - "associations": { - "actions": { - "activate": "Activer" - }, - "fields": { - "active": "Actif?", - "shopname": "nom de la boutique" - }, - "labels": { - "actions": "actes" - } - }, - "audit": { - "fields": { - "cc": "", - "contents": "", - "created": "", - "operation": "", - "status": "", - "subject": "", - "to": "", - "useremail": "", - "values": "" - } - }, - "audit_trail": { - "messages": { - "admin_job_remove_from_ar": "", - "admin_jobmarkexported": "", - "admin_jobmarkforreexport": "", - "admin_jobuninvoice": "", - "admin_jobunvoid": "", - "alerttoggle": "", - "appointmentcancel": "", - "appointmentinsert": "", - "assignedlinehours": "", - "billdeleted": "", - "billposted": "", - "billupdated": "", - "failedpayment": "", - "jobassignmentchange": "", - "jobassignmentremoved": "", - "jobchecklist": "", - "jobclosedwithbypass": "", - "jobconverted": "", - "jobdelivery": "", - "jobexported": "", - "jobfieldchanged": "", - "jobimported": "", - "jobinproductionchange": "", - "jobintake": "", - "jobinvoiced": "", - "jobioucreated": "", - "jobmodifylbradj": "", - "jobnoteadded": "", - "jobnotedeleted": "", - "jobnoteupdated": "", - "jobspartsorder": "", - "jobspartsreturn": "", - "jobstatuschange": "", - "jobsupplement": "", - "jobsuspend": "", - "jobvoid": "", - "tasks_completed": "", - "tasks_created": "", - "tasks_deleted": "", - "tasks_uncompleted": "", - "tasks_undeleted": "", - "tasks_updated": "" - } - }, - "billlines": { - "actions": { - "newline": "" - }, - "fields": { - "actual_cost": "", - "actual_price": "", - "cost_center": "", - "federal_tax_applicable": "", - "jobline": "", - "line_desc": "", - "local_tax_applicable": "", - "location": "", - "quantity": "", - "state_tax_applicable": "" - }, - "labels": { - "deductedfromlbr": "", - "entered": "", - "from": "", - "mod_lbr_adjustment": "", - "other": "", - "reconciled": "", - "unreconciled": "" - }, - "validation": { - "atleastone": "" - } - }, - "bills": { - "actions": { - "deductallhours": "", - "edit": "", - "receive": "", - "return": "" - }, - "errors": { - "creating": "", - "deleting": "", - "existinginventoryline": "", - "exporting": "", - "exporting-partner": "", - "invalidro": "", - "invalidvendor": "", - "validation": "" - }, - "fields": { - "allpartslocation": "", - "date": "", - "exported": "", - "federal_tax_rate": "", - "invoice_number": "", - "is_credit_memo": "", - "is_credit_memo_short": "", - "local_tax_rate": "", - "ro_number": "", - "state_tax_rate": "", - "total": "", - "vendor": "", - "vendorname": "" - }, - "labels": { - "actions": "", - "bill_lines": "", - "bill_total": "", - "billcmtotal": "", - "bills": "", - "calculatedcreditsnotreceived": "", - "creditsnotreceived": "", - "creditsreceived": "", - "dedfromlbr": "", - "deleteconfirm": "", - "discrepancy": "", - "discrepwithcms": "", - "discrepwithlbradj": "", - "editadjwarning": "", - "entered_total": "", - "enteringcreditmemo": "", - "federal_tax": "", - "federal_tax_exempt": "", - "generatepartslabel": "", - "iouexists": "", - "local_tax": "", - "markexported": "", - "markforreexport": "", - "new": "", - "nobilllines": "", - "noneselected": "", - "onlycmforinvoiced": "", - "printlabels": "", - "retailtotal": "", - "returnfrombill": "", - "savewithdiscrepancy": "", - "state_tax": "", - "subtotal": "", - "totalreturns": "" - }, - "successes": { - "created": "", - "deleted": "", - "exported": "", - "markexported": "", - "reexport": "" - }, - "validation": { - "closingperiod": "", - "inventoryquantity": "", - "manualinhouse": "", - "unique_invoice_number": "" - } - }, - "bodyshop": { - "actions": { - "add_task_preset": "", - "addapptcolor": "", - "addbucket": "", - "addpartslocation": "", - "addpartsrule": "", - "addspeedprint": "", - "addtemplate": "", - "newlaborrate": "", - "newsalestaxcode": "", - "newstatus": "", - "testrender": "" - }, - "errors": { - "creatingdefaultview": "", - "loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.", - "saving": "" - }, - "fields": { - "ReceivableCustomField": "", - "address1": "", - "address2": "", - "appt_alt_transport": "", - "appt_colors": { - "color": "", - "label": "" - }, - "appt_length": "", - "attach_pdf_to_email": "", - "batchid": "", - "bill_allow_post_to_closed": "", - "bill_federal_tax_rate": "", - "bill_local_tax_rate": "", - "bill_state_tax_rate": "", - "city": "", - "closingperiod": "", - "companycode": "", - "country": "", - "dailybodytarget": "", - "dailypainttarget": "", - "default_adjustment_rate": "", - "deliver": { - "require_actual_delivery_date": "", - "templates": "" - }, - "dms": { - "apcontrol": "", - "appostingaccount": "", - "cashierid": "", - "default_journal": "", - "disablebillwip": "", - "disablecontactvehiclecreation": "", - "dms_acctnumber": "", - "dms_control_override": "", - "dms_wip_acctnumber": "", - "generic_customer_number": "", - "itc_federal": "", - "itc_local": "", - "itc_state": "", - "mappingname": "", - "sendmaterialscosting": "", - "srcco": "" - }, - "email": "", - "enforce_class": "", - "enforce_conversion_category": "", - "enforce_conversion_csr": "", - "enforce_referral": "", - "federal_tax_id": "", - "ignoreblockeddays": "", - "inhousevendorid": "", - "insurance_vendor_id": "", - "intake": { - "next_contact_hours": "", - "templates": "" - }, - "intellipay_config": { - "cash_discount_percentage": "", - "enable_cash_discount": "" - }, - "invoice_federal_tax_rate": "", - "invoice_local_tax_rate": "", - "invoice_state_tax_rate": "", - "jc_hourly_rates": { - "mapa": "", - "mash": "" - }, - "last_name_first": "", - "lastnumberworkingdays": "", - "localmediaserverhttp": "", - "localmediaservernetwork": "", - "localmediatoken": "", - "logo_img_footer_margin": "", - "logo_img_header_margin": "", - "logo_img_path": "", - "logo_img_path_height": "", - "logo_img_path_width": "", - "md_categories": "", - "md_ccc_rates": "", - "md_classes": "", - "md_ded_notes": "", - "md_email_cc": "", - "md_from_emails": "", - "md_functionality_toggles": { - "parts_queue_toggle": "" - }, - "md_hour_split": { - "paint": "", - "prep": "" - }, - "md_ins_co": { - "city": "", - "name": "", - "private": "", - "state": "", - "street1": "", - "street2": "", - "zip": "" - }, - "md_jobline_presets": "", - "md_lost_sale_reasons": "", - "md_parts_order_comment": "", - "md_parts_scan": { - "caseInsensitive": "", - "expression": "", - "field": "", - "flags": "", - "mark_critical": "", - "operation": "", - "update_field": "", - "update_value": "", - "value": "" - }, - "md_payment_types": "", - "md_referral_sources": "", - "md_ro_guard": { - "enabled": "", - "enforce_ar": "", - "enforce_bills": "", - "enforce_cm": "", - "enforce_labor": "", - "enforce_ppd": "", - "enforce_profit": "", - "enforce_sublet": "", - "masterbypass": "", - "totalgppercent_minimum": "" - }, - "md_tasks_presets": { - "enable_tasks": "", - "hourstype": "", - "memo": "", - "name": "", - "nextstatus": "", - "percent": "", - "use_approvals": "" - }, - "messaginglabel": "", - "messagingtext": "", - "noteslabel": "", - "notestext": "", - "partslocation": "", - "phone": "", - "prodtargethrs": "", - "rbac": { - "accounting": { - "exportlog": "", - "payables": "", - "payments": "", - "receivables": "" - }, - "bills": { - "delete": "", - "enter": "", - "list": "", - "reexport": "", - "view": "" - }, - "contracts": { - "create": "", - "detail": "", - "list": "" - }, - "courtesycar": { - "create": "", - "detail": "", - "list": "" - }, - "csi": { - "export": "", - "page": "" - }, - "employee_teams": { - "page": "" - }, - "employees": { - "page": "" - }, - "inventory": { - "delete": "", - "list": "" - }, - "jobs": { - "admin": "", - "available-list": "", - "checklist-view": "", - "close": "", - "create": "", - "deliver": "", - "detail": "", - "intake": "", - "list-active": "", - "list-all": "", - "list-ready": "", - "partsqueue": "", - "void": "" - }, - "owners": { - "detail": "", - "list": "" - }, - "payments": { - "enter": "", - "list": "" - }, - "phonebook": { - "edit": "", - "view": "" - }, - "production": { - "board": "", - "list": "" - }, - "schedule": { - "view": "" - }, - "scoreboard": { - "view": "" - }, - "shiftclock": { - "view": "" - }, - "shop": { - "config": "", - "dashboard": "", - "rbac": "", - "reportcenter": "", - "templates": "", - "vendors": "" - }, - "temporarydocs": { - "view": "" - }, - "timetickets": { - "edit": "", - "editcommitted": "", - "enter": "", - "list": "", - "shiftedit": "" - }, - "ttapprovals": { - "approve": "", - "view": "" - }, - "users": { - "editaccess": "" - } - }, - "responsibilitycenter": "", - "responsibilitycenter_accountdesc": "", - "responsibilitycenter_accountitem": "", - "responsibilitycenter_accountname": "", - "responsibilitycenter_accountnumber": "", - "responsibilitycenter_rate": "", - "responsibilitycenter_tax_rate": "", - "responsibilitycenter_tax_sur": "", - "responsibilitycenter_tax_thres": "", - "responsibilitycenter_tax_tier": "", - "responsibilitycenter_tax_type": "", - "responsibilitycenters": { - "ap": "", - "ar": "", - "ats": "", - "federal_tax": "", - "federal_tax_itc": "", - "gst_override": "", - "invoiceexemptcode": "", - "itemexemptcode": "", - "la1": "", - "la2": "", - "la3": "", - "la4": "", - "laa": "", - "lab": "", - "lad": "", - "lae": "", - "laf": "", - "lag": "", - "lam": "", - "lar": "", - "las": "", - "lau": "", - "local_tax": "", - "mapa": "", - "mash": "", - "paa": "", - "pac": "", - "pag": "", - "pal": "", - "pam": "", - "pan": "", - "pao": "", - "pap": "", - "par": "", - "pas": "", - "pasl": "", - "refund": "", - "sales_tax_codes": { - "code": "", - "description": "", - "federal": "", - "local": "", - "state": "" - }, - "state_tax": "", - "tow": "" - }, - "schedule_end_time": "", - "schedule_start_time": "", - "shopname": "", - "speedprint": { - "id": "", - "label": "", - "templates": "" - }, - "ss_configuration": { - "dailyhrslimit": "" - }, - "ssbuckets": { - "color": "", - "gte": "", - "id": "", - "label": "", - "lt": "", - "target": "" - }, - "state": "", - "state_tax_id": "", - "status": "", - "statuses": { - "active_statuses": "", - "additional_board_statuses": "", - "color": "", - "default_arrived": "", - "default_bo": "", - "default_canceled": "", - "default_completed": "", - "default_delivered": "", - "default_exported": "", - "default_imported": "", - "default_invoiced": "", - "default_ordered": "", - "default_quote": "", - "default_received": "", - "default_returned": "", - "default_scheduled": "", - "default_void": "", - "open_statuses": "", - "post_production_statuses": "", - "pre_production_statuses": "", - "production_colors": "", - "production_statuses": "", - "ready_statuses": "" - }, - "target_touchtime": "", - "timezone": "", - "tt_allow_post_to_invoiced": "", - "tt_enforce_hours_for_tech_console": "", - "use_fippa": "", - "use_paint_scale_data": "", - "uselocalmediaserver": "", - "website": "", - "zip_post": "" - }, - "labels": { - "2tiername": "", - "2tiersetup": "", - "2tiersource": "", - "accountingsetup": "", - "accountingtiers": "", - "alljobstatuses": "", - "allopenjobstatuses": "", - "apptcolors": "", - "businessinformation": "", - "checklists": "", - "csiq": "", - "customtemplates": "", - "defaultcostsmapping": "", - "defaultprofitsmapping": "", - "deliverchecklist": "", - "dms": { - "cdk": { - "controllist": "", - "payers": "" - }, - "cdk_dealerid": "", - "costsmapping": "", - "dms_allocations": "", - "pbs_serialnumber": "", - "profitsmapping": "", - "title": "" - }, - "emaillater": "", - "employee_teams": "", - "employees": "", - "estimators": "", - "filehandlers": "", - "imexpay": "", - "insurancecos": "", - "intakechecklist": "", - "intellipay_cash_discount": "", - "jobstatuses": "", - "laborrates": "", - "licensing": "", - "md_parts_scan": "", - "md_ro_guard": "", - "md_tasks_presets": "", - "md_to_emails": "", - "md_to_emails_emails": "", - "messagingpresets": "", - "notemplatesavailable": "", - "notespresets": "", - "orderstatuses": "", - "partslocations": "", - "partsscan": "", - "printlater": "", - "qbo": "", - "qbo_departmentid": "", - "qbo_usa": "", - "rbac": "", - "responsibilitycenters": { - "costs": "", - "profits": "", - "sales_tax_codes": "", - "tax_accounts": "", - "title": "", - "ttl_adjustment": "", - "ttl_tax_adjustment": "" - }, - "roguard": { - "title": "" - }, - "romepay": "", - "scheduling": "", - "scoreboardsetup": "", - "shop_enabled_features": "", - "shopinfo": "", - "speedprint": "", - "ssbuckets": "", - "systemsettings": "", - "task-presets": "", - "workingdays": "" - }, - "operations": { - "contains": "", - "ends_with": "", - "equals": "", - "greater_than": "", - "less_than": "", - "not_equals": "", - "starts_with": "" - }, - "successes": { - "areyousure": "", - "defaultviewcreated": "", - "save": "", - "unsavedchanges": "" - }, - "tooltips": { - "md_parts_scan": { - "update_value_tooltip": "" - } - }, - "validation": { - "centermustexist": "", - "larsplit": "", - "useremailmustexist": "" - } - }, - "checklist": { - "actions": { - "printall": "" - }, - "errors": { - "complete": "", - "nochecklist": "" - }, - "labels": { - "addtoproduction": "", - "allow_text_message": "", - "checklist": "", - "printpack": "", - "removefromproduction": "" - }, - "successes": { - "completed": "" - } - }, - "contracts": { - "actions": { - "changerate": "", - "convertoro": "", - "decodelicense": "", - "find": "", - "printcontract": "", - "senddltoform": "" - }, - "errors": { - "fetchingjobinfo": "", - "returning": "", - "saving": "", - "selectjobandcar": "" - }, - "fields": { - "actax": "", - "actualreturn": "", - "agreementnumber": "", - "cc_cardholder": "", - "cc_expiry": "", - "cc_num": "", - "cleanupcharge": "", - "coverage": "", - "dailyfreekm": "", - "dailyrate": "", - "damage": "", - "damagewaiver": "", - "driver": "", - "driver_addr1": "", - "driver_addr2": "", - "driver_city": "", - "driver_dlexpiry": "", - "driver_dlnumber": "", - "driver_dlst": "", - "driver_dob": "", - "driver_fn": "", - "driver_ln": "", - "driver_ph1": "", - "driver_state": "", - "driver_zip": "", - "excesskmrate": "", - "federaltax": "", - "fuelin": "", - "fuelout": "", - "kmend": "", - "kmstart": "", - "length": "", - "localtax": "", - "refuelcharge": "", - "scheduledreturn": "", - "start": "", - "statetax": "", - "status": "" - }, - "labels": { - "agreement": "", - "availablecars": "", - "cardueforservice": "", - "convertform": { - "applycleanupcharge": "", - "refuelqty": "" - }, - "correctdataonform": "", - "dateinpast": "", - "dlexpirebeforereturn": "", - "driverinformation": "", - "findcontract": "", - "findermodal": "", - "insuranceexpired": "", - "noteconvertedfrom": "", - "populatefromjob": "", - "rates": "", - "time": "", - "vehicle": "", - "waitingforscan": "" - }, - "status": { - "new": "", - "out": "", - "returned": "" - }, - "successes": { - "saved": "" - } - }, - "courtesycars": { - "actions": { - "new": "", - "return": "" - }, - "errors": { - "saving": "" - }, - "fields": { - "color": "", - "dailycost": "", - "damage": "", - "fleetnumber": "", - "fuel": "", - "insuranceexpires": "", - "leaseenddate": "", - "make": "", - "mileage": "", - "model": "", - "nextservicedate": "", - "nextservicekm": "", - "notes": "", - "plate": "", - "purchasedate": "", - "readiness": "", - "registrationexpires": "", - "serviceenddate": "", - "servicestartdate": "", - "status": "", - "vin": "", - "year": "" - }, - "labels": { - "courtesycar": "", - "fuel": { - "12": "", - "14": "", - "18": "", - "34": "", - "38": "", - "58": "", - "78": "", - "empty": "", - "full": "" - }, - "outwith": "", - "return": "", - "status": "", - "uniquefleet": "", - "usage": "", - "vehicle": "" - }, - "readiness": { - "notready": "", - "ready": "" - }, - "status": { - "in": "", - "inservice": "", - "leasereturn": "", - "out": "", - "sold": "", - "unavailable": "" - }, - "successes": { - "saved": "" - } - }, - "csi": { - "actions": { - "activate": "" - }, - "errors": { - "creating": "", - "notconfigured": "", - "notfoundsubtitle": "", - "notfoundtitle": "", - "surveycompletesubtitle": "", - "surveycompletetitle": "" - }, - "fields": { - "completedon": "", - "created_at": "", - "surveyid": "", - "validuntil": "" - }, - "labels": { - "copyright": "", - "greeting": "", - "intro": "", - "nologgedinuser": "", - "nologgedinuser_sub": "", - "noneselected": "", - "title": "" - }, - "successes": { - "created": "", - "submitted": "", - "submittedsub": "" - } - }, - "dashboard": { - "actions": { - "addcomponent": "" - }, - "errors": { - "refreshrequired": "", - "updatinglayout": "" - }, - "labels": { - "bodyhrs": "", - "dollarsinproduction": "", - "phone": "", - "prodhrs": "", - "refhrs": "" - }, - "titles": { - "joblifecycle": "", - "labhours": "", - "larhours": "", - "monthlyemployeeefficiency": "", - "monthlyjobcosting": "", - "monthlylaborsales": "", - "monthlypartssales": "", - "monthlyrevenuegraph": "", - "prodhrssummary": "", - "productiondollars": "", - "productionhours": "", - "projectedmonthlysales": "", - "scheduledindate": "", - "scheduledintoday": "", - "scheduledoutdate": "", - "scheduledouttoday": "", - "tasks": "" - } - }, - "dms": { - "errors": { - "alreadyexported": "" - }, - "labels": { - "refreshallocations": "" - } - }, - "documents": { - "actions": { - "delete": "", - "download": "", - "reassign": "", - "selectallimages": "", - "selectallotherdocuments": "" - }, - "errors": { - "deletes3": "Erreur lors de la suppression du document du stockage.", - "deleting": "", - "deleting_cloudinary": "", - "getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}", - "insert": "Incapable de télécharger le fichier. {{message}}", - "nodocuments": "Il n'y a pas de documents.", - "updating": "" - }, - "labels": { - "confirmdelete": "", - "doctype": "", - "dragtoupload": "", - "newjobid": "", - "openinexplorer": "", - "optimizedimage": "", - "reassign_limitexceeded": "", - "reassign_limitexceeded_title": "", - "storageexceeded": "", - "storageexceeded_title": "", - "upload": "Télécharger", - "upload_limitexceeded": "", - "upload_limitexceeded_title": "", - "uploading": "", - "usage": "" - }, - "successes": { - "delete": "Le document a bien été supprimé.", - "edituploaded": "", - "insert": "Document téléchargé avec succès.", - "updated": "" - } - }, - "emails": { - "errors": { - "notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}" - }, - "fields": { - "cc": "", - "from": "", - "subject": "", - "to": "" - }, - "labels": { - "attachments": "", - "documents": "", - "emailpreview": "", - "generatingemail": "", - "pdfcopywillbeattached": "", - "preview": "" - }, - "successes": { - "sent": "E-mail envoyé avec succès." - } - }, - "employee_teams": { - "actions": { - "new": "", - "newmember": "" - }, - "fields": { - "active": "", - "employeeid": "", - "max_load": "", - "name": "", - "percentage": "" - } - }, - "employees": { - "actions": { - "addvacation": "", - "new": "Nouvel employé", - "newrate": "" - }, - "errors": { - "delete": "Erreur rencontrée lors de la suppression de l'employé. {{message}}", - "save": "Une erreur s'est produite lors de l'enregistrement de l'employé. {{message}}", - "validation": "Veuillez cocher tous les champs.", - "validationtitle": "Impossible d'enregistrer l'employé." - }, - "fields": { - "active": "Actif?", - "base_rate": "Taux de base", - "cost_center": "Centre de coûts", - "employee_number": "Numéro d'employé", - "external_id": "", - "first_name": "Prénom", - "flat_rate": "Taux fixe (désactivé est le temps normal)", - "hire_date": "Date d'embauche", - "last_name": "Nom de famille", - "pin": "", - "rate": "", - "termination_date": "Date de résiliation", - "user_email": "", - "vacation": { - "end": "", - "length": "", - "start": "" - } - }, - "labels": { - "actions": "", - "active": "", - "endmustbeafterstart": "", - "flat_rate": "", - "inactive": "", - "name": "", - "rate_type": "", - "status": "", - "straight_time": "" - }, - "successes": { - "delete": "L'employé a bien été supprimé.", - "save": "L'employé a enregistré avec succès.", - "vacationadded": "" - }, - "validation": { - "unique_employee_number": "" - } - }, - "eula": { - "buttons": { - "accept": "Accept EULA" - }, - "content": { - "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." - }, - "errors": { - "acceptance": { - "description": "Something went wrong while accepting the EULA. Please try again.", - "message": "Eula Acceptance Error" - } - }, - "labels": { - "accepted_terms": "I accept the terms and conditions of this agreement.", - "address": "Address", - "business_name": "Legal Business Name", - "date_accepted": "Date Accepted", - "first_name": "First Name", - "last_name": "Last Name", - "phone_number": "Phone Number" - }, - "messages": { - "accepted_terms": "Please accept the terms and conditions of this agreement.", - "business_name": "Please enter your legal business name.", - "date_accepted": "Please enter Today's Date.", - "first_name": "Please enter your first name.", - "last_name": "Please enter your last name.", - "phone_number": "Please enter your phone number." - }, - "titles": { - "modal": "Terms and Conditions", - "upper_card": "Acknowledgement" - } - }, - "exportlogs": { - "fields": { - "createdat": "" - }, - "labels": { - "attempts": "", - "priorsuccesfulexport": "" - } - }, - "general": { - "actions": { - "add": "", - "autoupdate": "", - "calculate": "", - "cancel": "", - "clear": "", - "close": "", - "copied": "", - "copylink": "", - "create": "", - "defaults": "", - "delay": "", - "delete": "Effacer", - "deleteall": "", - "deselectall": "", - "download": "", - "edit": "modifier", - "login": "", - "next": "", - "ok": "", - "previous": "", - "print": "", - "refresh": "", - "remove": "", - "remove_alert": "", - "reset": " Rétablir l'original.", - "resetpassword": "", - "save": "sauvegarder", - "saveandnew": "", - "saveas": "", - "selectall": "", - "send": "", - "sendbysms": "", - "senderrortosupport": "", - "sharetoteams": "", - "submit": "", - "tryagain": "", - "view": "", - "viewreleasenotes": "" - }, - "errors": { - "fcm": "", - "notfound": "", - "sizelimit": "" - }, - "itemtypes": { - "contract": "", - "courtesycar": "", - "job": "", - "owner": "", - "vehicle": "" - }, - "labels": { - "actions": "actes", - "areyousure": "", - "barcode": "code à barre", - "cancel": "", - "clear": "", - "confirmpassword": "", - "created_at": "", - "date": "", - "datetime": "", - "email": "", - "errors": "", - "excel": "", - "exceptiontitle": "", - "friday": "", - "globalsearch": "", - "help": "", - "hours": "", - "in": "dans", - "instanceconflictext": "", - "instanceconflictitle": "", - "item": "", - "label": "", - "loading": "Chargement...", - "loadingapp": "Chargement de {{app}}", - "loadingshop": "Chargement des données de la boutique ...", - "loggingin": "Vous connecter ...", - "markedexported": "", - "media": "", - "message": "", - "monday": "", - "na": "N / A", - "newpassword": "", - "no": "", - "nointernet": "", - "nointernet_sub": "", - "none": "", - "out": "En dehors", - "password": "", - "passwordresetsuccess": "", - "passwordresetsuccess_sub": "", - "passwordresetvalidatesuccess": "", - "passwordresetvalidatesuccess_sub": "", - "passwordsdonotmatch": "", - "print": "", - "refresh": "", - "reports": "", - "required": "", - "saturday": "", - "search": "Chercher...", - "searchresults": "", - "selectdate": "", - "sendagain": "", - "sendby": "", - "signin": "", - "sms": "", - "status": "", - "sub_status": { - "expired": "" - }, - "successful": "", - "sunday": "", - "text": "", - "thursday": "", - "time": "", - "total": "", - "totals": "", - "tuesday": "", - "tvmode": "", - "unknown": "Inconnu", - "unsavedchanges": "", - "username": "", - "view": "", - "wednesday": "", - "yes": "" - }, - "languages": { - "english": "Anglais", - "french": "Francais", - "spanish": "Espanol" - }, - "messages": { - "exception": "", - "newversionmessage": "", - "newversiontitle": "", - "noacctfilepath": "", - "nofeatureaccess": "", - "noshop": "", - "notfoundsub": "", - "notfoundtitle": "", - "partnernotrunning": "", - "rbacunauth": "", - "unsavedchanges": "Vous avez des changements non enregistrés.", - "unsavedchangespopup": "" - }, - "validation": { - "dateRangeExceeded": "", - "invalidemail": "S'il vous plaît entrer un email valide.", - "invalidphone": "", - "required": "Ce champ est requis." - } - }, - "help": { - "actions": { - "connect": "" - }, - "labels": { - "codeplacholder": "", - "rescuedesc": "", - "rescuetitle": "" - } - }, - "intake": { - "labels": { - "printpack": "" - } - }, - "inventory": { - "actions": { - "addtoinventory": "", - "addtoro": "", - "consumefrominventory": "", - "edit": "", - "new": "" - }, - "errors": { - "inserting": "" - }, - "fields": { - "comment": "", - "manualinvoicenumber": "", - "manualvendor": "" - }, - "labels": { - "consumedbyjob": "", - "deleteconfirm": "", - "frombillinvoicenumber": "", - "fromvendor": "", - "inventory": "", - "showall": "", - "showavailable": "" - }, - "successes": { - "deleted": "", - "inserted": "", - "updated": "" - } - }, - "job_lifecycle": { - "columns": { - "average_human_readable": "", - "average_value": "", - "duration": "", - "end": "", - "human_readable": "", - "percentage": "", - "relative_end": "", - "relative_start": "", - "start": "", - "status": "", - "status_count": "", - "value": "" - }, - "content": { - "calculated_based_on": "", - "current_status_accumulated_time": "", - "data_unavailable": "", - "jobs_in_since": "", - "legend_title": "", - "loading": "", - "not_available": "", - "previous_status_accumulated_time": "", - "title": "", - "title_durations": "", - "title_loading": "", - "title_transitions": "" - }, - "errors": { - "fetch": "Erreur lors de l'obtention des données du cycle de vie des tâches" - }, - "titles": { - "dashboard": "", - "top_durations": "" - } - }, - "job_payments": { - "buttons": { - "create_short_link": "", - "goback": "", - "proceedtopayment": "", - "refundpayment": "" - }, - "notifications": { - "error": { - "description": "", - "openingip": "", - "title": "" - } - }, - "titles": { - "amount": "", - "dateOfPayment": "", - "descriptions": "", - "hint": "", - "payer": "", - "payername": "", - "paymentid": "", - "paymentnum": "", - "paymenttype": "", - "refundamount": "", - "transactionid": "" - } - }, - "joblines": { - "actions": { - "assign_team": "", - "converttolabor": "", - "dispatchparts": "", - "new": "" - }, - "errors": { - "creating": "", - "updating": "" - }, - "fields": { - "act_price": "Prix actuel", - "act_price_before_ppc": "", - "adjustment": "", - "ah_detail_line": "", - "alt_partno": "", - "amount": "", - "assigned_team": "", - "assigned_team_name": "", - "create_ppc": "", - "db_price": "Prix de la base de données", - "include_in_part_cnt": "", - "lbr_types": { - "LA1": "", - "LA2": "", - "LA3": "", - "LA4": "", - "LAA": "", - "LAB": "", - "LAD": "", - "LAE": "", - "LAF": "", - "LAG": "", - "LAM": "", - "LAR": "", - "LAS": "", - "LAU": "" - }, - "line_desc": "Description de la ligne", - "line_ind": "S#", - "line_no": "", - "location": "", - "mod_lb_hrs": "Heures de travail", - "mod_lbr_ty": "Type de travail", - "notes": "", - "oem_partno": "Pièce OEM #", - "op_code_desc": "", - "part_qty": "", - "part_type": "Type de pièce", - "part_types": { - "CCC": "", - "CCD": "", - "CCDR": "", - "CCF": "", - "CCM": "", - "PAA": "", - "PAC": "", - "PAE": "", - "PAG": "", - "PAL": "", - "PAM": "", - "PAN": "", - "PAO": "", - "PAP": "", - "PAR": "", - "PAS": "", - "PASL": "" - }, - "profitcenter_labor": "", - "profitcenter_part": "", - "prt_dsmk_m": "", - "prt_dsmk_p": "", - "status": "Statut", - "tax_part": "", - "total": "", - "unq_seq": "Seq #" - }, - "labels": { - "adjustmenttobeadded": "", - "billref": "", - "convertedtolabor": "", - "edit": "Ligne d'édition", - "ioucreated": "", - "new": "Nouvelle ligne", - "nostatus": "", - "presets": "" - }, - "successes": { - "created": "", - "saved": "", - "updated": "" - }, - "validations": { - "ahdetailonlyonuserdefinedtypes": "", - "hrsrequirediflbrtyp": "", - "requiredifparttype": "", - "zeropriceexistingpart": "" - } - }, - "jobs": { - "actions": { - "addDocuments": "Ajouter des documents de travail", - "addNote": "Ajouter une note", - "addtopartsqueue": "", - "addtoproduction": "", - "addtoscoreboard": "", - "allocate": "", - "autoallocate": "", - "changefilehandler": "", - "changelaborrate": "", - "changestatus": "Changer le statut", - "changestimator": "", - "convert": "Convertir", - "createiou": "", - "deliver": "", - "deliver_quick": "", - "dms": { - "addpayer": "", - "createnewcustomer": "", - "findmakemodelcode": "", - "getmakes": "", - "labels": { - "refreshallocations": "" - }, - "post": "", - "refetchmakesmodels": "", - "usegeneric": "", - "useselected": "" - }, - "dmsautoallocate": "", - "export": "", - "exportcustdata": "", - "exportselected": "", - "filterpartsonly": "", - "generatecsi": "", - "gotojob": "", - "intake": "", - "intake_quick": "", - "manualnew": "", - "mark": "", - "markasexported": "", - "markpstexempt": "", - "markpstexemptconfirm": "", - "postbills": "Poster des factures", - "printCenter": "Centre d'impression", - "recalculate": "", - "reconcile": "", - "removefromproduction": "", - "schedule": "Programme", - "sendcsi": "", - "sendpartspricechange": "", - "sendtodms": "", - "sync": "", - "taxprofileoverride": "", - "taxprofileoverride_confirm": "", - "uninvoice": "", - "unvoid": "", - "viewchecklist": "", - "viewdetail": "" - }, - "errors": { - "addingtoproduction": "", - "cannotintake": "", - "closing": "", - "creating": "", - "deleted": "Erreur lors de la suppression du travail.", - "exporting": "", - "exporting-partner": "", - "invoicing": "", - "noaccess": "Ce travail n'existe pas ou vous n'y avez pas accès.", - "nodamage": "", - "nodates": "Aucune date spécifiée pour ce travail.", - "nofinancial": "", - "nojobselected": "Aucun travail n'est sélectionné.", - "noowner": "Aucun propriétaire associé.", - "novehicle": "Aucun véhicule associé.", - "partspricechange": "", - "saving": "Erreur rencontrée lors de la sauvegarde de l'enregistrement.", - "scanimport": "", - "totalscalc": "", - "updating": "", - "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.", - "validationtitle": "Erreur de validation", - "voiding": "" - }, - "fields": { - "active_tasks": "", - "actual_completion": "Achèvement réel", - "actual_delivery": "Livraison réelle", - "actual_in": "En réel", - "adjustment_bottom_line": "Ajustements", - "adjustmenthours": "", - "alt_transport": "", - "area_of_damage_impact": { - "10": "", - "11": "", - "12": "", - "13": "", - "14": "", - "15": "", - "16": "", - "25": "", - "26": "", - "27": "", - "28": "", - "34": "", - "01": "", - "02": "", - "03": "", - "04": "", - "05": "", - "06": "", - "07": "", - "08": "", - "09": "" - }, - "auto_add_ats": "", - "ca_bc_pvrt": "", - "ca_customer_gst": "", - "ca_gst_registrant": "", - "category": "", - "ccc": "", - "ccd": "", - "ccdr": "", - "ccf": "", - "ccm": "", - "cieca_id": "CIECA ID", - "cieca_pfl": { - "lbr_adjp": "", - "lbr_tax_in": "", - "lbr_taxp": "", - "lbr_tx_in1": "", - "lbr_tx_in2": "", - "lbr_tx_in3": "", - "lbr_tx_in4": "", - "lbr_tx_in5": "" - }, - "cieca_pfo": { - "stor_t_in1": "", - "stor_t_in2": "", - "stor_t_in3": "", - "stor_t_in4": "", - "stor_t_in5": "", - "tow_t_in1": "", - "tow_t_in2": "", - "tow_t_in3": "", - "tow_t_in4": "", - "tow_t_in5": "" - }, - "claim_total": "Total réclamation", - "class": "", - "clm_no": "Prétendre #", - "clm_total": "Total réclamation", - "comment": "", - "customerowing": "Client propriétaire", - "date_estimated": "Date estimée", - "date_exported": "Exportés", - "date_invoiced": "Facturé", - "date_last_contacted": "", - "date_lost_sale": "", - "date_next_contact": "", - "date_open": "Ouvrir", - "date_rentalresp": "", - "date_repairstarted": "", - "date_scheduled": "Prévu", - "date_towin": "", - "date_void": "", - "ded_amt": "Déductible", - "ded_note": "", - "ded_status": "Statut de franchise", - "depreciation_taxes": "Amortissement / taxes", - "dms": { - "address": "", - "amount": "", - "center": "", - "control_type": { - "account_number": "" - }, - "cost": "", - "cost_dms_acctnumber": "", - "dms_make": "", - "dms_model": "", - "dms_model_override": "", - "dms_unsold": "", - "dms_wip_acctnumber": "", - "id": "", - "inservicedate": "", - "journal": "", - "lines": "", - "name1": "", - "payer": { - "amount": "", - "control_type": "", - "controlnumber": "", - "dms_acctnumber": "", - "name": "" - }, - "sale": "", - "sale_dms_acctnumber": "", - "story": "", - "vinowner": "" - }, - "dms_allocation": "", - "driveable": "", - "employee_body": "", - "employee_csr": "représentant du service à la clientèle", - "employee_csr_writer": "", - "employee_prep": "", - "employee_refinish": "", - "est_addr1": "Adresse de l'évaluateur", - "est_co_nm": "Expert", - "est_ct_fn": "Prénom de l'évaluateur", - "est_ct_ln": "Nom de l'évaluateur", - "est_ea": "Courriel de l'évaluateur", - "est_ph1": "Numéro de téléphone de l'évaluateur", - "federal_tax_payable": "Impôt fédéral à payer", - "federal_tax_rate": "", - "ins_addr1": "Adresse Insurance Co.", - "ins_city": "Insurance City", - "ins_co_id": "ID de la compagnie d'assurance", - "ins_co_nm": "Nom de la compagnie d'assurance", - "ins_co_nm_short": "", - "ins_ct_fn": "Prénom du gestionnaire de fichiers", - "ins_ct_ln": "Nom du gestionnaire de fichiers", - "ins_ea": "Courriel du gestionnaire de fichiers", - "ins_ph1": "Numéro de téléphone du gestionnaire de fichiers", - "intake": { - "label": "", - "max": "", - "min": "", - "name": "", - "required": "", - "type": "" - }, - "invoice_final_note": "", - "kmin": "Kilométrage en", - "kmout": "Kilométrage hors", - "la1": "", - "la2": "", - "la3": "", - "la4": "", - "laa": "", - "lab": "", - "labor_rate_desc": "Nom du taux de main-d'œuvre", - "lad": "", - "lae": "", - "laf": "", - "lag": "", - "lam": "", - "lar": "", - "las": "", - "lau": "", - "local_tax_rate": "", - "loss_date": "Date de perte", - "loss_desc": "", - "loss_of_use": "", - "lost_sale_reason": "", - "ma2s": "", - "ma3s": "", - "mabl": "", - "macs": "", - "mahw": "", - "mapa": "", - "mash": "", - "matd": "", - "materials": { - "MAPA": "", - "MASH": "", - "cal_maxdlr": "", - "cal_opcode": "", - "mat_adjp": "", - "mat_taxp": "", - "mat_tx_in1": "", - "mat_tx_in2": "", - "mat_tx_in3": "", - "mat_tx_in4": "", - "mat_tx_in5": "", - "materials": "", - "tax_ind": "" - }, - "other_amount_payable": "Autre montant à payer", - "owner": "Propriétaire", - "owner_owing": "Cust. Owes", - "ownr_ea": "Email", - "ownr_ph1": "Téléphone 1", - "ownr_ph2": "", - "paa": "", - "pac": "", - "pae": "", - "pag": "", - "pal": "", - "pam": "", - "pan": "", - "pao": "", - "pap": "", - "par": "", - "parts_tax_rates": { - "prt_discp": "", - "prt_mktyp": "", - "prt_mkupp": "", - "prt_tax_in": "", - "prt_tax_rt": "", - "prt_tx_in1": "", - "prt_tx_in2": "", - "prt_tx_in3": "", - "prt_tx_in4": "", - "prt_tx_in5": "", - "prt_tx_ty1": "", - "prt_type": "" - }, - "partsstatus": "", - "pas": "", - "pay_date": "Date d'Pay", - "phoneshort": "PH", - "po_number": "", - "policy_no": "Politique #", - "ponumber": "Numéro de bon de commande", - "production_vars": { - "note": "" - }, - "qb_multiple_payers": { - "amount": "", - "name": "" - }, - "queued_for_parts": "", - "rate_ats": "", - "rate_la1": "Taux LA1", - "rate_la2": "Taux LA2", - "rate_la3": "Taux LA3", - "rate_la4": "Taux LA4", - "rate_laa": "Taux d'aluminium", - "rate_lab": "Taux de la main-d'œuvre", - "rate_lad": "Taux de diagnostic", - "rate_lae": "Tarif électrique", - "rate_laf": "Taux de trame", - "rate_lag": "Taux de verre", - "rate_lam": "Taux mécanique", - "rate_lar": "Taux de finition", - "rate_las": "", - "rate_lau": "Taux d'aluminium", - "rate_ma2s": "Taux de peinture en 2 étapes", - "rate_ma3s": "Taux de peinture en 3 étapes", - "rate_mabl": "MABL ??", - "rate_macs": "MACS ??", - "rate_mahw": "Taux de déchets dangereux", - "rate_mapa": "Taux de matériaux de peinture", - "rate_mash": "Tarif du matériel de la boutique", - "rate_matd": "Taux d'élimination des pneus", - "referral_source_extra": "", - "referral_source_other": "", - "referralsource": "Source de référence", - "regie_number": "Enregistrement #", - "repairtotal": "Réparation totale", - "ro_number": "RO #", - "scheduled_completion": "Achèvement planifié", - "scheduled_delivery": "Livraison programmée", - "scheduled_in": "Planifié dans", - "selling_dealer": "Revendeur vendeur", - "selling_dealer_contact": "Contacter le revendeur", - "servicecar": "Voiture de service", - "servicing_dealer": "Concessionnaire", - "servicing_dealer_contact": "Contacter le concessionnaire", - "special_coverage_policy": "Politique de couverture spéciale", - "specialcoveragepolicy": "Politique de couverture spéciale", - "state_tax_rate": "", - "status": "Statut de l'emploi", - "storage_payable": "Stockage", - "tax_lbr_rt": "", - "tax_levies_rt": "", - "tax_paint_mat_rt": "", - "tax_registration_number": "", - "tax_shop_mat_rt": "", - "tax_str_rt": "", - "tax_sub_rt": "", - "tax_tow_rt": "", - "tlos_ind": "", - "towin": "", - "towing_payable": "Remorquage à payer", - "unitnumber": "Unité #", - "updated_at": "Mis à jour à", - "uploaded_by": "Telechargé par", - "vehicle": "Véhicule" - }, - "forms": { - "admindates": "", - "appraiserinfo": "", - "claiminfo": "", - "estdates": "", - "laborrates": "", - "lossinfo": "", - "other": "", - "repairdates": "", - "scheddates": "" - }, - "labels": { - "accountsreceivable": "", - "act_price_ppc": "", - "actual_completion_inferred": "", - "actual_delivery_inferred": "", - "actual_in_inferred": "", - "additionalpayeroverallocation": "", - "additionaltotal": "", - "adjustmentrate": "", - "adjustments": "", - "adminwarning": "", - "allocations": "", - "alreadyaddedtoscoreboard": "", - "alreadyclosed": "", - "appointmentconfirmation": "Envoyer une confirmation au client?", - "associationwarning": "", - "audit": "", - "available": "", - "availablejobs": "", - "ca_bc_pvrt": { - "days": "", - "rate": "" - }, - "ca_gst_all_if_null": "", - "calc_repair_days": "", - "calc_repair_days_tt": "", - "calc_scheuled_completion": "", - "cards": { - "customer": "Informations client", - "damage": "Zone de dommages", - "dates": "Rendez-vous", - "documents": "Documents récents", - "estimator": "Estimateur", - "filehandler": "Gestionnaire de fichiers", - "insurance": "Détails de l'assurance", - "more": "Plus", - "notes": "Remarques", - "parts": "les pièces", - "totals": "Totaux", - "vehicle": "Véhicule" - }, - "changeclass": "", - "checklistcompletedby": "", - "checklistdocuments": "", - "checklists": "", - "cieca_pfl": "", - "cieca_pfo": "", - "cieca_pft": "", - "closeconfirm": "", - "closejob": "", - "closingperiod": "", - "contracts": "", - "convertedtolabor": "", - "cost": "", - "cost_Additional": "", - "cost_labor": "", - "cost_parts": "", - "cost_sublet": "", - "costs": "", - "create": { - "jobinfo": "", - "newowner": "", - "newvehicle": "", - "novehicle": "", - "ownerinfo": "", - "vehicleinfo": "" - }, - "createiouwarning": "", - "creating_new_job": "Création d'un nouvel emploi ...", - "deductible": { - "stands": "", - "waived": "" - }, - "deleteconfirm": "", - "deletedelivery": "", - "deleteintake": "", - "deliverchecklist": "", - "difference": "", - "diskscan": "", - "dms": { - "apexported": "", - "damageto": "", - "defaultstory": "", - "disablebillwip": "", - "invoicedatefuture": "", - "kmoutnotgreaterthankmin": "", - "logs": "", - "notallocated": "", - "postingform": "", - "totalallocated": "" - }, - "documents": "Les documents", - "documents-images": "", - "documents-other": "", - "duplicateconfirm": "", - "emailaudit": "", - "employeeassignments": "", - "estimatelines": "", - "estimator": "", - "existing_jobs": "Emplois existants", - "federal_tax_amt": "", - "gpdollars": "", - "gppercent": "", - "hrs_claimed": "", - "hrs_total": "", - "importnote": "", - "inproduction": "", - "intakechecklist": "", - "iou": "", - "job": "", - "jobcosting": "", - "jobtotals": "", - "labor_hrs": "", - "labor_rates_subtotal": "", - "laborallocations": "", - "labortotals": "", - "lines": "Estimer les lignes", - "local_tax_amt": "", - "mapa": "", - "markforreexport": "", - "mash": "", - "masterbypass": "", - "materials": { - "mapa": "" - }, - "missingprofileinfo": "", - "multipayers": "", - "net_repairs": "", - "notes": "Remarques", - "othertotal": "", - "outstanding_ar": "", - "outstanding_credit_memos": "", - "outstanding_ppd": "", - "outstanding_reconciliation_discrep": "", - "outstanding_sublets": "", - "outstandinghours": "", - "override_header": "Remplacer l'en-tête d'estimation à l'importation?", - "ownerassociation": "", - "parts": "les pièces", - "parts_lines": "", - "parts_received": "", - "parts_tax_rates": "", - "partsfilter": "", - "partssubletstotal": "", - "partstotal": "", - "performance": "", - "pimraryamountpayable": "", - "plitooltips": { - "billtotal": "", - "calculatedcreditsnotreceived": "", - "creditmemos": "", - "creditsnotreceived": "", - "discrep1": "", - "discrep2": "", - "discrep3": "", - "laboradj": "", - "partstotal": "", - "totalreturns": "" - }, - "ppc": "", - "ppdnotexported": "", - "profileadjustments": "", - "profitbypassrequired": "", - "profits": "", - "prt_dsmk_total": "", - "rates": "Les taux", - "rates_subtotal": "", - "reconciliation": { - "billlinestotal": "", - "byassoc": "", - "byprice": "", - "clear": "", - "discrepancy": "", - "joblinestotal": "", - "multipleactprices": "", - "multiplebilllines": "", - "multiplebillsforactprice": "", - "removedpartsstrikethrough": "" - }, - "reconciliationheader": "", - "relatedros": "", - "remove_from_ar": "", - "returntotals": "", - "ro_guard": { - "enforce_ar": "", - "enforce_bills": "", - "enforce_cm": "", - "enforce_labor": "", - "enforce_ppd": "", - "enforce_profit": "", - "enforce_sublet": "", - "enforce_validation": "", - "enforced": "" - }, - "roguard": "", - "roguardwarnings": "", - "rosaletotal": "", - "sale_additional": "", - "sale_labor": "", - "sale_parts": "", - "sale_sublet": "", - "sales": "", - "savebeforeconversion": "", - "scheduledinchange": "", - "specialcoveragepolicy": "", - "state_tax_amt": "", - "subletsnotcompleted": "", - "subletstotal": "", - "subtotal": "", - "supplementnote": "", - "suspended": "", - "suspense": "", - "tasks": "", - "threshhold": "", - "total_cost": "", - "total_cust_payable": "", - "total_cust_payable_cash_discount": "", - "total_repairs": "", - "total_repairs_cash_discount": "", - "total_sales": "", - "total_sales_tax": "", - "totals": "", - "unvoidnote": "", - "update_scheduled_completion": "", - "vehicle_info": "Véhicule", - "vehicleassociation": "", - "viewallocations": "", - "voidjob": "", - "voidnote": "" - }, - "successes": { - "addedtoproduction": "", - "all_deleted": "{{count}} travaux supprimés avec succès.", - "closed": "", - "converted": "Travail converti avec succès.", - "created": "Le travail a été créé avec succès. Clique pour voir.", - "creatednoclick": "", - "delete": "", - "deleted": "Le travail a bien été supprimé.", - "duplicated": "", - "exported": "", - "invoiced": "", - "ioucreated": "", - "partsqueue": "", - "save": "Le travail a été enregistré avec succès.", - "savetitle": "Enregistrement enregistré avec succès.", - "supplemented": "Travail complété avec succès.", - "updated": "", - "voided": "" - } - }, - "landing": { - "bigfeature": { - "subtitle": "", - "title": "" - }, - "footer": { - "company": { - "about": "", - "contact": "", - "disclaimers": "", - "name": "", - "privacypolicy": "" - }, - "io": { - "help": "", - "name": "", - "status": "" - }, - "slogan": "" - }, - "hero": { - "button": "", - "title": "" - }, - "labels": { - "features": "", - "managemyshop": "", - "pricing": "" - }, - "pricing": { - "basic": { - "name": "", - "sub": "" - }, - "essentials": { - "name": "", - "sub": "" - }, - "pricingtitle": "", - "pro": { - "name": "", - "sub": "" - }, - "title": "", - "unlimited": { - "name": "", - "sub": "" - } - } - }, - "menus": { - "currentuser": { - "languageselector": "La langue", - "profile": "Profil" - }, - "header": { - "accounting": "", - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "activejobs": "Emplois actifs", - "all_tasks": "", - "alljobs": "", - "allpayments": "", - "availablejobs": "Emplois disponibles", - "bills": "", - "courtesycars": "", - "courtesycars-all": "", - "courtesycars-contracts": "", - "courtesycars-newcontract": "", - "create_task": "", - "customers": "Les clients", - "dashboard": "", - "enterbills": "", - "entercardpayment": "", - "enterpayment": "", - "entertimeticket": "", - "export": "", - "export-logs": "", - "help": "", - "home": "Accueil", - "inventory": "", - "jobs": "Emplois", - "my_tasks": "", - "newjob": "", - "owners": "Propriétaires", - "parts-queue": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "readyjobs": "", - "recent": "", - "reportcenter": "", - "rescueme": "", - "schedule": "Programme", - "scoreboard": "", - "search": { - "bills": "", - "jobs": "", - "owners": "", - "payments": "", - "phonebook": "", - "vehicles": "" - }, - "shiftclock": "", - "shop": "Mon magasin", - "shop_config": "Configuration", - "shop_csi": "", - "shop_templates": "", - "shop_vendors": "Vendeurs", - "tasks": "", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicles": "Véhicules" - }, - "jobsactions": { - "admin": "", - "cancelallappointments": "", - "closejob": "", - "deletejob": "", - "duplicate": "", - "duplicatenolines": "", - "newcccontract": "", - "void": "" - }, - "jobsdetail": { - "claimdetail": "Détails de la réclamation", - "dates": "Rendez-vous", - "financials": "", - "general": "", - "insurance": "", - "labor": "La main d'oeuvre", - "lifecycle": "", - "parts": "", - "partssublet": "Pièces / Sous-location", - "rates": "", - "repairdata": "Données de réparation", - "totals": "" - }, - "profilesidebar": { - "profile": "Mon profil", - "shops": "Mes boutiques" - }, - "tech": { - "assignedjobs": "", - "claimtask": "", - "dispatchedparts": "", - "home": "", - "jobclockin": "", - "jobclockout": "", - "joblookup": "", - "login": "", - "logout": "", - "productionboard": "", - "productionlist": "", - "shiftclockin": "" - } - }, - "messaging": { - "actions": { - "link": "", - "new": "" - }, - "errors": { - "invalidphone": "", - "noattachedjobs": "", - "updatinglabel": "" - }, - "labels": { - "addlabel": "", - "archive": "", - "maxtenimages": "", - "messaging": "Messagerie", - "noallowtxt": "", - "nojobs": "", - "nopush": "", - "phonenumber": "", - "presets": "", - "recentonly": "", - "selectmedia": "", - "sentby": "", - "typeamessage": "Envoyer un message...", - "unarchive": "" - }, - "render": { - "conversation_list": "" - } - }, - "notes": { - "actions": { - "actions": "actes", - "deletenote": "Supprimer la note", - "edit": "Note éditée", - "new": "Nouvelle note", - "savetojobnotes": "" - }, - "errors": { - "inserting": "" - }, - "fields": { - "createdby": "Créé par", - "critical": "Critique", - "private": "privé", - "text": "Contenu", - "type": "", - "types": { - "customer": "", - "general": "", - "office": "", - "paint": "", - "parts": "", - "shop": "", - "supplement": "" - }, - "updatedat": "Mis à jour à" - }, - "labels": { - "addtorelatedro": "", - "newnoteplaceholder": "Ajouter une note...", - "notetoadd": "", - "systemnotes": "", - "usernotes": "" - }, - "successes": { - "create": "Remarque créée avec succès.", - "deleted": "Remarque supprimée avec succès.", - "updated": "Remarque mise à jour avec succès." - } - }, - "owner": { - "labels": { - "noownerinfo": "" - } - }, - "owners": { - "actions": { - "update": "" - }, - "errors": { - "deleting": "", - "noaccess": "L'enregistrement n'existe pas ou vous n'y avez pas accès.", - "saving": "", - "selectexistingornew": "" - }, - "fields": { - "accountingid": "", - "address": "Adresse", - "allow_text_message": "Autorisation de texte?", - "name": "Prénom", - "note": "", - "ownr_addr1": "Adresse", - "ownr_addr2": "Adresse 2 ", - "ownr_city": "Ville", - "ownr_co_nm": "", - "ownr_ctry": "Pays", - "ownr_ea": "Email", - "ownr_fn": "Prénom", - "ownr_ln": "Nom de famille", - "ownr_ph1": "Téléphone 1", - "ownr_ph2": "", - "ownr_st": "Etat / Province", - "ownr_title": "Titre", - "ownr_zip": "Zip / code postal", - "preferred_contact": "Méthode de contact préférée", - "tax_number": "" - }, - "forms": { - "address": "", - "contact": "", - "name": "" - }, - "labels": { - "create_new": "Créez un nouvel enregistrement de propriétaire.", - "deleteconfirm": "", - "existing_owners": "Propriétaires existants", - "fromclaim": "", - "fromowner": "", - "relatedjobs": "", - "updateowner": "" - }, - "successes": { - "delete": "", - "save": "Le propriétaire a bien enregistré." - } - }, - "parts": { - "actions": { - "order": "Commander des pièces", - "orderinhouse": "" - } - }, - "parts_dispatch": { - "actions": { - "accept": "" - }, - "errors": { - "accepting": "", - "creating": "" - }, - "fields": { - "number": "", - "percent_accepted": "" - }, - "labels": { - "notyetdispatched": "", - "parts_dispatch": "" - } - }, - "parts_dispatch_lines": { - "fields": { - "accepted_at": "" - } - }, - "parts_orders": { - "actions": { - "backordered": "", - "receive": "", - "receivebill": "" - }, - "errors": { - "associatedbills": "", - "backordering": "", - "creating": "Erreur rencontrée lors de la création de la commande de pièces.", - "oec": "", - "saving": "", - "updating": "" - }, - "fields": { - "act_price": "", - "backordered_eta": "", - "backordered_on": "", - "cm_received": "", - "comments": "", - "cost": "", - "db_price": "", - "deliver_by": "", - "job_line_id": "", - "line_desc": "", - "line_remarks": "", - "lineremarks": "Remarques sur la ligne", - "oem_partno": "", - "order_date": "", - "order_number": "", - "orderedby": "", - "part_type": "", - "quantity": "", - "return": "", - "status": "" - }, - "labels": { - "allpartsto": "", - "confirmdelete": "", - "custompercent": "", - "discount": "", - "email": "Envoyé par email", - "inthisorder": "Pièces dans cette commande", - "is_quote": "", - "mark_as_received": "", - "newpartsorder": "", - "notyetordered": "", - "oec": "", - "order_type": "", - "orderhistory": "Historique des commandes", - "parts_order": "", - "parts_orders": "", - "parts_returns": "", - "print": "Afficher le formulaire imprimé", - "receive": "", - "removefrompartsqueue": "", - "returnpartsorder": "", - "sublet_order": "" - }, - "successes": { - "created": "Commande de pièces créée avec succès.", - "line_updated": "", - "received": "", - "return_created": "" - } - }, - "payments": { - "actions": { - "generatepaymentlink": "" - }, - "errors": { - "exporting": "", - "exporting-partner": "", - "inserting": "" - }, - "fields": { - "amount": "", - "created_at": "", - "date": "", - "exportedat": "", - "memo": "", - "payer": "", - "paymentnum": "", - "stripeid": "", - "transactionid": "", - "type": "" - }, - "labels": { - "balance": "", - "ca_bc_etf_table": "", - "customer": "", - "edit": "", - "electronicpayment": "", - "external": "", - "findermodal": "", - "insurance": "", - "markexported": "", - "markforreexport": "", - "new": "", - "signup": "", - "smspaymentreminder": "", - "title": "", - "totalpayments": "" - }, - "successes": { - "exported": "", - "markexported": "", - "markreexported": "", - "payment": "", - "paymentupdate": "", - "stripe": "" - } - }, - "phonebook": { - "actions": { - "new": "" - }, - "errors": { - "adding": "", - "saving": "" - }, - "fields": { - "address1": "", - "address2": "", - "category": "", - "city": "", - "company": "", - "country": "", - "email": "", - "fax": "", - "firstname": "", - "lastname": "", - "phone1": "", - "phone2": "", - "state": "" - }, - "labels": { - "noneselected": "", - "onenamerequired": "", - "vendorcategory": "" - }, - "successes": { - "added": "", - "deleted": "", - "saved": "" - } - }, - "printcenter": { - "appointments": { - "appointment_confirmation": "" - }, - "bills": { - "inhouse_invoice": "" - }, - "courtesycarcontract": { - "courtesy_car_contract": "", - "courtesy_car_impound": "", - "courtesy_car_inventory": "", - "courtesy_car_terms": "" - }, - "errors": { - "nocontexttype": "" - }, - "jobs": { - "3rdpartyfields": { - "addr1": "", - "addr2": "", - "addr3": "", - "attn": "", - "city": "", - "custgst": "", - "ded_amt": "", - "depreciation": "", - "other": "", - "ponumber": "", - "refnumber": "", - "sendtype": "", - "state": "", - "zip": "" - }, - "3rdpartypayer": "", - "ab_proof_of_loss": "", - "appointment_confirmation": "", - "appointment_reminder": "", - "casl_authorization": "", - "committed_timetickets_ro": "", - "coversheet_landscape": "", - "coversheet_portrait": "", - "csi_invitation": "", - "csi_invitation_action": "", - "diagnostic_authorization": "", - "dms_posting_sheet": "", - "envelope_return_address": "", - "estimate": "", - "estimate_detail": "", - "estimate_followup": "", - "express_repair_checklist": "", - "filing_coversheet_landscape": "", - "filing_coversheet_portrait": "", - "final_invoice": "", - "fippa_authorization": "", - "folder_label_multiple": "", - "glass_express_checklist": "", - "guarantee": "", - "individual_job_note": "", - "invoice_customer_payable": "", - "invoice_total_payable": "", - "iou_form": "", - "job_costing_ro": "", - "job_lifecycle_ro": "", - "job_notes": "", - "job_tasks": "", - "key_tag": "", - "labels": { - "count": "", - "labels": "", - "position": "" - }, - "lag_time_ro": "", - "mechanical_authorization": "", - "mpi_animal_checklist": "", - "mpi_eglass_auth": "", - "mpi_final_acct_sheet": "", - "mpi_final_repair_acct_sheet": "", - "paint_grid": "", - "parts_dispatch": "", - "parts_invoice_label_single": "", - "parts_label_multiple": "", - "parts_label_single": "", - "parts_list": "", - "parts_order": "", - "parts_order_confirmation": "", - "parts_order_history": "", - "parts_return_slip": "", - "payment_receipt": "", - "payment_request": "", - "payments_by_job": "", - "purchases_by_ro_detail": "", - "purchases_by_ro_summary": "", - "qc_sheet": "", - "rental_reservation": "", - "ro_totals": "", - "ro_with_description": "", - "sgi_certificate_of_repairs": "", - "sgi_windshield_auth": "", - "stolen_recovery_checklist": "", - "sublet_order": "", - "supplement_request": "", - "thank_you_ro": "", - "thirdpartypayer": "", - "timetickets_ro": "", - "vehicle_check_in": "", - "vehicle_delivery_check": "", - "window_tag": "", - "window_tag_sublet": "", - "work_authorization": "", - "worksheet_by_line_number": "", - "worksheet_sorted_by_operation": "", - "worksheet_sorted_by_operation_no_hours": "", - "worksheet_sorted_by_operation_part_type": "", - "worksheet_sorted_by_operation_type": "", - "worksheet_sorted_by_team": "" - }, - "labels": { - "groups": { - "authorization": "", - "financial": "", - "post": "", - "pre": "", - "ro": "", - "worksheet": "" - }, - "misc": "", - "repairorder": "", - "reportcentermodal": "", - "speedprint": "", - "title": "" - }, - "payments": { - "ca_bc_etf_table": "", - "exported_payroll": "" - }, - "special": { - "attendance_detail_csv": "" - }, - "subjects": { - "jobs": { - "individual_job_note": "", - "parts_dispatch": "", - "parts_order": "", - "parts_return_slip": "", - "sublet_order": "" - } - }, - "vendors": { - "purchases_by_vendor_detailed": "", - "purchases_by_vendor_summary": "" - } - }, - "production": { - "actions": { - "addcolumns": "", - "bodypriority-clear": "", - "bodypriority-set": "", - "detailpriority-clear": "", - "detailpriority-set": "", - "paintpriority-clear": "", - "paintpriority-set": "", - "remove": "", - "removecolumn": "", - "saveconfig": "", - "suspend": "", - "unsuspend": "" - }, - "constants": { - "main_profile": "" - }, - "errors": { - "boardupdate": "", - "name_exists": "", - "name_required": "", - "removing": "", - "settings": "" - }, - "labels": { - "actual_in": "", - "addnewprofile": "", - "alert": "", - "alertoff": "", - "alerton": "", - "alerts": "", - "ats": "", - "bodyhours": "", - "bodypriority": "", - "bodyshop": { - "labels": { - "qbo_departmentid": "", - "qbo_usa": "" - } - }, - "card_size": "", - "cardcolor": "", - "cardsettings": "", - "clm_no": "", - "comment": "", - "compact": "", - "detailpriority": "", - "employeeassignments": "", - "employeesearch": "", - "estimator": "", - "horizontal": "", - "ins_co_nm": "", - "jobdetail": "", - "kiosk_mode": "", - "laborhrs": "", - "legend": "", - "model_info": "", - "note": "", - "off": "", - "on": "", - "orientation": "", - "ownr_nm": "", - "paintpriority": "", - "partsstatus": "", - "production_note": "", - "refinishhours": "", - "scheduled_completion": "", - "selectview": "", - "stickyheader": "", - "sublets": "", - "subtotal": "", - "tall": "", - "tasks": "", - "totalhours": "", - "touchtime": "", - "unassigned": "", - "vertical": "", - "viewname": "", - "wide": "" - }, - "options": { - "horizontal": "", - "large": "", - "medium": "", - "small": "", - "vertical": "" - }, - "settings": { - "board_settings": "", - "filters": { - "md_estimators": "", - "md_ins_cos": "" - }, - "filters_title": "", - "information": "", - "layout": "", - "statistics": { - "jobs_in_production": "", - "tasks_in_production": "", - "tasks_in_view": "", - "tasks_on_board": "", - "total_amount_in_production": "", - "total_amount_in_view": "", - "total_amount_on_board": "", - "total_hours_in_production": "", - "total_hours_in_view": "", - "total_hours_on_board": "", - "total_jobs_in_view": "", - "total_jobs_on_board": "", - "total_lab_in_production": "", - "total_lab_in_view": "", - "total_lab_on_board": "", - "total_lar_in_production": "", - "total_lar_in_view": "", - "total_lar_on_board": "" - }, - "statistics_title": "" - }, - "statistics": { - "currency_symbol": "", - "hours": "", - "jobs": "", - "jobs_in_production": "", - "tasks": "", - "tasks_in_production": "", - "tasks_in_view": "", - "tasks_on_board": "", - "total_amount_in_production": "", - "total_amount_in_view": "", - "total_amount_on_board": "", - "total_hours_in_production": "", - "total_hours_in_view": "", - "total_hours_on_board": "", - "total_jobs_in_view": "", - "total_jobs_on_board": "", - "total_lab_in_production": "", - "total_lab_in_view": "", - "total_lab_on_board": "", - "total_lar_in_production": "", - "total_lar_in_view": "", - "total_lar_on_board": "" - }, - "successes": { - "removed": "" - } - }, - "profile": { - "errors": { - "state": "Erreur lors de la lecture de l'état de la page. Rafraichissez, s'il vous plait." - }, - "labels": { - "activeshop": "" - }, - "successes": { - "updated": "" - } - }, - "reportcenter": { - "actions": { - "generate": "" - }, - "labels": { - "advanced_filters": "", - "advanced_filters_false": "", - "advanced_filters_filter_field": "", - "advanced_filters_filter_operator": "", - "advanced_filters_filter_value": "", - "advanced_filters_filters": "", - "advanced_filters_hide": "", - "advanced_filters_show": "", - "advanced_filters_sorter_direction": "", - "advanced_filters_sorter_field": "", - "advanced_filters_sorters": "", - "advanced_filters_true": "", - "dates": "", - "employee": "", - "filterson": "", - "generateasemail": "", - "groups": { - "customers": "", - "jobs": "", - "payroll": "", - "purchases": "", - "sales": "" - }, - "key": "", - "objects": { - "appointments": "", - "bills": "", - "csi": "", - "exportlogs": "", - "jobs": "", - "parts_orders": "", - "payments": "", - "scoreboard": "", - "tasks": "", - "timetickets": "" - }, - "vendor": "" - }, - "templates": { - "adp_payroll_flat": "", - "adp_payroll_straight": "", - "anticipated_revenue": "", - "ar_aging": "", - "attendance_detail": "", - "attendance_employee": "", - "attendance_summary": "", - "committed_timetickets": "", - "committed_timetickets_employee": "", - "committed_timetickets_summary": "", - "credits_not_received_date": "", - "credits_not_received_date_vendorid": "", - "csi": "", - "customer_list": "", - "cycle_time_analysis": "", - "estimates_written_converted": "", - "estimator_detail": "", - "estimator_summary": "", - "export_payables": "", - "export_payments": "", - "export_receivables": "", - "exported_gsr_by_ro": "", - "exported_gsr_by_ro_labor": "", - "gsr_by_atp": "", - "gsr_by_ats": "", - "gsr_by_category": "", - "gsr_by_csr": "", - "gsr_by_delivery_date": "", - "gsr_by_estimator": "", - "gsr_by_exported_date": "", - "gsr_by_ins_co": "", - "gsr_by_make": "", - "gsr_by_referral": "", - "gsr_by_ro": "", - "gsr_labor_only": "", - "hours_sold_detail_closed": "", - "hours_sold_detail_closed_csr": "", - "hours_sold_detail_closed_estimator": "", - "hours_sold_detail_closed_ins_co": "", - "hours_sold_detail_closed_status": "", - "hours_sold_detail_open": "", - "hours_sold_detail_open_csr": "", - "hours_sold_detail_open_estimator": "", - "hours_sold_detail_open_ins_co": "", - "hours_sold_detail_open_status": "", - "hours_sold_summary_closed": "", - "hours_sold_summary_closed_csr": "", - "hours_sold_summary_closed_estimator": "", - "hours_sold_summary_closed_ins_co": "", - "hours_sold_summary_closed_status": "", - "hours_sold_summary_open": "", - "hours_sold_summary_open_csr": "", - "hours_sold_summary_open_estimator": "", - "hours_sold_summary_open_ins_co": "", - "hours_sold_summary_open_status": "", - "job_costing_ro_csr": "", - "job_costing_ro_date_detail": "", - "job_costing_ro_date_summary": "", - "job_costing_ro_estimator": "", - "job_costing_ro_ins_co": "", - "job_lifecycle_date_detail": "", - "job_lifecycle_date_summary": "", - "jobs_completed_not_invoiced": "", - "jobs_invoiced_not_exported": "", - "jobs_reconcile": "", - "jobs_scheduled_completion": "", - "lag_time": "", - "load_level": "", - "lost_sales": "", - "open_orders": "", - "open_orders_csr": "", - "open_orders_estimator": "", - "open_orders_excel": "", - "open_orders_ins_co": "", - "open_orders_referral": "", - "open_orders_specific_csr": "", - "open_orders_status": "", - "parts_backorder": "", - "parts_not_recieved": "", - "parts_not_recieved_vendor": "", - "parts_received_not_scheduled": "", - "payments_by_date": "", - "payments_by_date_payment": "", - "payments_by_date_type": "", - "production_by_category": "", - "production_by_category_one": "", - "production_by_csr": "", - "production_by_last_name": "", - "production_by_repair_status": "", - "production_by_repair_status_one": "", - "production_by_ro": "", - "production_by_target_date": "", - "production_by_technician": "", - "production_by_technician_one": "", - "production_not_production_status": "", - "production_over_time": "", - "psr_by_make": "", - "purchase_return_ratio_excel": "", - "purchase_return_ratio_grouped_by_vendor_detail": "", - "purchase_return_ratio_grouped_by_vendor_summary": "", - "purchases_by_cost_center_detail": "", - "purchases_by_cost_center_summary": "", - "purchases_by_date_excel": "", - "purchases_by_date_range_detail": "", - "purchases_by_date_range_summary": "", - "purchases_by_ro_detail_date": "", - "purchases_by_ro_summary_date": "", - "purchases_by_vendor_detailed_date_range": "", - "purchases_by_vendor_summary_date_range": "", - "purchases_grouped_by_vendor_detailed": "", - "purchases_grouped_by_vendor_summary": "", - "returns_grouped_by_vendor_detailed": "", - "returns_grouped_by_vendor_summary": "", - "schedule": "", - "scheduled_parts_list": "", - "scoreboard_detail": "", - "scoreboard_summary": "", - "supplement_ratio_ins_co": "", - "tasks_date": "", - "tasks_date_employee": "", - "thank_you_date": "", - "timetickets": "", - "timetickets_employee": "", - "timetickets_summary": "", - "total_loss_jobs": "", - "unclaimed_hrs": "", - "void_ros": "", - "work_in_progress_committed_labour": "", - "work_in_progress_jobs": "", - "work_in_progress_labour": "", - "work_in_progress_payables": "" - } - }, - "schedule": { - "labels": { - "atssummary": "", - "employeevacation": "", - "estimators": "", - "ins_co_nm_filter": "", - "intake": "", - "manual": "", - "manualevent": "" - } - }, - "scoreboard": { - "actions": { - "edit": "" - }, - "errors": { - "adding": "", - "removing": "", - "updating": "" - }, - "fields": { - "bodyhrs": "", - "date": "", - "painthrs": "" - }, - "labels": { - "allemployeetimetickets": "", - "asoftodaytarget": "", - "body": "", - "bodyabbrev": "", - "bodycharttitle": "", - "calendarperiod": "", - "combinedcharttitle": "", - "dailyactual": "", - "dailytarget": "", - "efficiencyoverperiod": "", - "entries": "", - "jobs": "", - "jobscompletednotinvoiced": "", - "lastmonth": "", - "lastweek": "", - "monthlytarget": "", - "priorweek": "", - "productivestatistics": "", - "productivetimeticketsoverdate": "", - "refinish": "", - "refinishabbrev": "", - "refinishcharttitle": "", - "targets": "", - "thismonth": "", - "thisweek": "", - "timetickets": "", - "timeticketsemployee": "", - "todateactual": "", - "total": "", - "totalhrs": "", - "totaloverperiod": "", - "weeklyactual": "", - "weeklytarget": "", - "workingdays": "" - }, - "successes": { - "added": "", - "removed": "", - "updated": "" - } - }, - "tasks": { - "actions": { - "edit": "", - "new": "", - "view": "" - }, - "buttons": { - "allTasks": "", - "complete": "", - "create": "", - "delete": "", - "edit": "", - "myTasks": "", - "refresh": "" - }, - "date_presets": { - "completion": "", - "day": "", - "days": "", - "delivery": "", - "next_week": "", - "one_month": "", - "three_months": "", - "three_weeks": "", - "today": "", - "tomorrow": "", - "two_weeks": "" - }, - "failures": { - "completed": "", - "created": "", - "deleted": "", - "updated": "" - }, - "fields": { - "actions": "", - "assigned_to": "", - "bill": "", - "billid": "", - "completed": "", - "created_at": "", - "created_by": "", - "description": "", - "due_date": "", - "job": { - "ro_number": "" - }, - "jobid": "", - "jobline": "", - "joblineid": "", - "parts_order": "", - "partsorderid": "", - "priorities": { - "high": "", - "low": "", - "medium": "" - }, - "priority": "", - "related_items": "", - "remind_at": "", - "title": "" - }, - "placeholders": { - "assigned_to": "", - "billid": "", - "description": "", - "jobid": "", - "joblineid": "", - "partsorderid": "" - }, - "successes": { - "completed": "", - "created": "", - "deleted": "", - "updated": "" - }, - "titles": { - "all_tasks": "", - "completed": "", - "deleted": "", - "job_tasks": "", - "mine": "", - "my_tasks": "" - }, - "validation": { - "due_at_error_message": "", - "remind_at_error_message": "" - } - }, - "tech": { - "fields": { - "employeeid": "", - "pin": "" - }, - "labels": { - "loggedin": "", - "notloggedin": "" - } - }, - "templates": { - "errors": { - "updating": "" - }, - "successes": { - "updated": "" - } - }, - "timetickets": { - "actions": { - "claimtasks": "", - "clockin": "", - "clockout": "", - "commit": "", - "commitone": "", - "enter": "", - "payall": "", - "printemployee": "", - "uncommit": "" - }, - "errors": { - "clockingin": "", - "clockingout": "", - "creating": "", - "deleting": "", - "noemployeeforuser": "", - "noemployeeforuser_sub": "", - "payall": "", - "shiftalreadyclockedon": "" - }, - "fields": { - "actualhrs": "", - "ciecacode": "", - "clockhours": "", - "clockoff": "", - "clockon": "", - "committed": "", - "committed_at": "", - "cost_center": "", - "created_by": "", - "date": "", - "efficiency": "", - "employee": "", - "employee_team": "", - "flat_rate": "", - "memo": "", - "productivehrs": "", - "ro_number": "", - "task_name": "" - }, - "labels": { - "alreadyclockedon": "", - "ambreak": "", - "amshift": "", - "claimtaskpreview": "", - "clockhours": "", - "clockintojob": "", - "deleteconfirm": "", - "edit": "", - "efficiency": "", - "flat_rate": "", - "jobhours": "", - "lunch": "", - "new": "", - "payrollclaimedtasks": "", - "pmbreak": "", - "pmshift": "", - "shift": "", - "shiftalreadyclockedon": "", - "straight_time": "", - "task": "", - "timetickets": "", - "unassigned": "", - "zeroactualnegativeprod": "" - }, - "successes": { - "clockedin": "", - "clockedout": "", - "committed": "", - "created": "", - "deleted": "", - "payall": "" - }, - "validation": { - "clockoffmustbeafterclockon": "", - "clockoffwithoutclockon": "", - "hoursenteredmorethanavailable": "", - "unassignedlines": "" - } - }, - "titles": { - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "all_tasks": "", - "app": "", - "bc": { - "accounting-payables": "", - "accounting-payments": "", - "accounting-receivables": "", - "all_tasks": "", - "availablejobs": "", - "bills-list": "", - "contracts": "", - "contracts-create": "", - "contracts-detail": "", - "courtesycars": "", - "courtesycars-detail": "", - "courtesycars-new": "", - "dashboard": "", - "dms": "", - "export-logs": "", - "inventory": "", - "jobs": "", - "jobs-active": "", - "jobs-admin": "", - "jobs-all": "", - "jobs-checklist": "", - "jobs-close": "", - "jobs-deliver": "", - "jobs-detail": "", - "jobs-intake": "", - "jobs-new": "", - "jobs-ready": "", - "my_tasks": "", - "owner-detail": "", - "owners": "", - "parts-queue": "", - "payments-all": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "profile": "", - "schedule": "", - "scoreboard": "", - "shop": "", - "shop-csi": "", - "shop-templates": "", - "shop-vendors": "", - "tasks": "", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicle-details": "", - "vehicles": "" - }, - "bills-list": "", - "contracts": "", - "contracts-create": "", - "contracts-detail": "", - "courtesycars": "", - "courtesycars-create": "", - "courtesycars-detail": "", - "dashboard": "", - "dms": "", - "export-logs": "", - "imexonline": "", - "inventory": "", - "jobs": "Tous les emplois | {{app}}", - "jobs-admin": "", - "jobs-all": "", - "jobs-checklist": "", - "jobs-close": "", - "jobs-create": "", - "jobs-deliver": "", - "jobs-intake": "", - "jobsavailable": "Emplois disponibles | {{app}}", - "jobsdetail": "Travail {{ro_number}} | {{app}}", - "jobsdocuments": "Documents de travail {{ro_number}} | {{app}}", - "manageroot": "Accueil | {{app}}", - "my_tasks": "", - "owners": "Tous les propriétaires | {{app}}", - "owners-detail": "", - "parts-queue": "", - "payments-all": "", - "phonebook": "", - "productionboard": "", - "productionlist": "", - "profile": "Mon profil | {{app}}", - "readyjobs": "", - "resetpassword": "", - "resetpasswordvalidate": "", - "romeonline": "", - "schedule": "Horaire | {{app}}", - "scoreboard": "", - "shop": "Mon magasin | {{app}}", - "shop-csi": "", - "shop-templates": "", - "shop_vendors": "Vendeurs | {{app}}", - "tasks": "", - "techconsole": "{{app}}", - "techjobclock": "{{app}}", - "techjoblookup": "{{app}}", - "techshiftclock": "{{app}}", - "temporarydocs": "", - "timetickets": "", - "ttapprovals": "", - "vehicledetail": "Détails du véhicule {{vehicle} | {{app}}", - "vehicles": "Tous les véhicules | {{app}}" - }, - "trello": { - "labels": { - "add_card": "", - "add_lane": "", - "cancel": "", - "delete_lane": "", - "description": "", - "label": "", - "lane_actions": "", - "title": "" - } - }, - "tt_approvals": { - "actions": { - "approveselected": "" - }, - "labels": { - "approval_queue_in_use": "", - "calculate": "" - } - }, - "upsell": { - "cta": { - "learnmore": "" - }, - "messages": { - "accounting": { - "payables": { - "subtitle": "", - "title": "" - }, - "payments": { - "subtitle": "", - "title": "" - }, - "receivables": { - "subtitle": "", - "title": "" - } - }, - "audit": { - "general": { - "subtitle": "", - "title": "" - } - }, - "bills": { - "autoreconcile": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - } - }, - "checklist": { - "general": { - "subtitle": "", - "title": "" - } - }, - "courtesycars": { - "general": { - "subtitle": "", - "title": "" - } - }, - "csi": { - "general": { - "subtitle": "", - "title": "" - } - }, - "dashboard": { - "general": { - "subtitle": "", - "title": "" - } - }, - "lifecycle": { - "general": { - "subtitle": "", - "title": "" - } - }, - "media": { - "general": { - "subtitle": "", - "title": "" - }, - "mobile": { - "subtitle": "", - "title": "" - } - }, - "payments": { - "general": { - "subtitle": "", - "title": "" - } - }, - "scoreboard": { - "general": { - "subtitle": "", - "title": "" - } - }, - "smartscheduling": { - "datepicker": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - }, - "hrsdelta": { - "subtitle": "", - "title": "" - } - }, - "techconsole": { - "general": { - "subtitle": "", - "title": "" - } - }, - "timetickets": { - "allocations": { - "subtitle": "", - "title": "" - }, - "general": { - "subtitle": "", - "title": "" - } - }, - "visualboard": { - "general": { - "subtitle": "", - "title": "" - } - } - } - }, - "user": { - "actions": { - "changepassword": "", - "signout": "Déconnexion", - "updateprofile": "Mettre à jour le profil" - }, - "errors": { - "updating": "" - }, - "fields": { - "authlevel": "", - "displayname": "Afficher un nom", - "email": "", - "photourl": "URL de l'avatar" - }, - "labels": { - "actions": "", - "changepassword": "", - "profileinfo": "" - }, - "successess": { - "passwordchanged": "" - } - }, - "users": { - "errors": { - "signinerror": { - "auth/user-disabled": "", - "auth/user-not-found": "", - "auth/wrong-password": "" - } - } - }, - "vehicles": { - "errors": { - "deleting": "", - "noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.", - "selectexistingornew": "", - "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.", - "validationtitle": "Erreur de validation" - }, - "fields": { - "description": "Description du véhicule", - "notes": "", - "plate_no": "Plaque d'immatriculation", - "plate_st": "Juridiction de la plaque", - "trim_color": "Couleur de garniture", - "v_bstyle": "Style corporel", - "v_color": "Couleur", - "v_cond": "Etat", - "v_engine": "moteur", - "v_make_desc": "Faire", - "v_makecode": "Faire du code", - "v_mldgcode": "Code de moulage", - "v_model_desc": "Modèle", - "v_model_yr": "année", - "v_options": "Les options", - "v_paint_codes": "Codes de peinture", - "v_prod_dt": "Date de production", - "v_stage": "Étape", - "v_tone": "ton", - "v_trimcode": "Code de coupe", - "v_type": "Type", - "v_vin": "V.I.N." - }, - "forms": { - "detail": "", - "misc": "", - "registration": "" - }, - "labels": { - "deleteconfirm": "", - "fromvehicle": "", - "novehinfo": "", - "relatedjobs": "", - "updatevehicle": "" - }, - "successes": { - "delete": "", - "save": "Le véhicule a été enregistré avec succès." - } - }, - "vendors": { - "actions": { - "addtophonebook": "", - "new": "Nouveau vendeur", - "newpreferredmake": "" - }, - "errors": { - "deleting": "Erreur rencontrée lors de la suppression du fournisseur.", - "saving": "Erreur rencontrée lors de l'enregistrement du fournisseur." - }, - "fields": { - "active": "", - "am": "", - "city": "Ville", - "cost_center": "Centre de coûts", - "country": "Pays", - "discount": "Remise %", - "display_name": "Afficher un nom", - "dmsid": "", - "due_date": "Date limite de paiement", - "email": "Email du contact", - "favorite": "Préféré?", - "lkq": "", - "make": "", - "name": "Nom du vendeur", - "oem": "", - "phone": "", - "prompt_discount": "Remise rapide%", - "state": "Etat / Province", - "street1": "rue", - "street2": "Adresse 2 ", - "taxid": "Identifiant de taxe", - "terms": "Modalités de paiement", - "zip": "Zip / code postal" - }, - "labels": { - "noneselected": "Aucun fournisseur n'est sélectionné.", - "preferredmakes": "", - "search": "Tapez le nom d'un vendeur" - }, - "successes": { - "deleted": "Le fournisseur a bien été supprimé.", - "saved": "Le fournisseur a bien enregistré." - }, - "validation": { - "unique_vendor_name": "" - } - }, + "translation": { + "allocations": { + "actions": { + "assign": "Attribuer" + }, + "errors": { + "deleting": "", + "saving": "", + "validation": "" + }, + "fields": { + "employee": "Alloué à" + }, + "successes": { + "deleted": "", + "save": "" + } + }, + "appointments": { + "actions": { + "block": "", + "calculate": "", + "cancel": "annuler", + "intake": "Admission", + "new": "Nouveau rendez-vous", + "preview": "", + "reschedule": "Replanifier", + "sendreminder": "", + "unblock": "", + "viewjob": "Voir le travail" + }, + "errors": { + "blocking": "", + "canceling": "Erreur lors de l'annulation du rendez-vous. {{message}}", + "saving": "Erreur lors de la planification du rendez-vous. {{message}}" + }, + "fields": { + "alt_transport": "", + "color": "", + "end": "", + "note": "", + "start": "", + "time": "", + "title": "Titre" + }, + "labels": { + "arrivedon": "Arrivé le:", + "arrivingjobs": "", + "blocked": "", + "cancelledappointment": "Rendez-vous annulé pour:", + "completingjobs": "", + "dataconsistency": "", + "expectedjobs": "", + "expectedprodhrs": "", + "history": "", + "inproduction": "", + "manualevent": "", + "noarrivingjobs": "", + "nocompletingjobs": "", + "nodateselected": "Aucune date n'a été sélectionnée.", + "priorappointments": "Rendez-vous précédents", + "reminder": "", + "scheduledfor": "Rendez-vous prévu pour:", + "severalerrorsfound": "", + "smartscheduling": "", + "smspaymentreminder": "", + "suggesteddates": "" + }, + "successes": { + "canceled": "Rendez-vous annulé avec succès.", + "created": "Rendez-vous planifié avec succès.", + "saved": "" + } + }, + "associations": { + "actions": { + "activate": "Activer" + }, + "fields": { + "active": "Actif?", + "shopname": "nom de la boutique" + }, + "labels": { + "actions": "actes" + } + }, + "audit": { + "fields": { + "cc": "", + "contents": "", + "created": "", + "operation": "", + "status": "", + "subject": "", + "to": "", + "useremail": "", + "values": "" + } + }, + "audit_trail": { + "messages": { + "admin_job_remove_from_ar": "", + "admin_jobmarkexported": "", + "admin_jobmarkforreexport": "", + "admin_jobuninvoice": "", + "admin_jobunvoid": "", + "alerttoggle": "", + "appointmentcancel": "", + "appointmentinsert": "", + "assignedlinehours": "", + "billdeleted": "", + "billposted": "", + "billupdated": "", + "failedpayment": "", + "jobassignmentchange": "", + "jobassignmentremoved": "", + "jobchecklist": "", + "jobclosedwithbypass": "", + "jobconverted": "", + "jobdelivery": "", + "jobexported": "", + "jobfieldchanged": "", + "jobimported": "", + "jobinproductionchange": "", + "jobintake": "", + "jobinvoiced": "", + "jobioucreated": "", + "jobmodifylbradj": "", + "jobnoteadded": "", + "jobnotedeleted": "", + "jobnoteupdated": "", + "jobspartsorder": "", + "jobspartsreturn": "", + "jobstatuschange": "", + "jobsupplement": "", + "jobsuspend": "", + "jobvoid": "", + "tasks_completed": "", + "tasks_created": "", + "tasks_deleted": "", + "tasks_uncompleted": "", + "tasks_undeleted": "", + "tasks_updated": "" + } + }, + "billlines": { + "actions": { + "newline": "" + }, + "fields": { + "actual_cost": "", + "actual_price": "", + "cost_center": "", + "federal_tax_applicable": "", + "jobline": "", + "line_desc": "", + "local_tax_applicable": "", + "location": "", + "quantity": "", + "state_tax_applicable": "" + }, + "labels": { + "deductedfromlbr": "", + "entered": "", + "from": "", + "mod_lbr_adjustment": "", + "other": "", + "reconciled": "", + "unreconciled": "" + }, + "validation": { + "atleastone": "" + } + }, + "bills": { + "actions": { + "deductallhours": "", + "edit": "", + "receive": "", + "return": "" + }, + "errors": { + "creating": "", + "deleting": "", + "existinginventoryline": "", + "exporting": "", + "exporting-partner": "", + "invalidro": "", + "invalidvendor": "", + "validation": "" + }, + "fields": { + "allpartslocation": "", + "date": "", + "exported": "", + "federal_tax_rate": "", + "invoice_number": "", + "is_credit_memo": "", + "is_credit_memo_short": "", + "local_tax_rate": "", + "ro_number": "", + "state_tax_rate": "", + "total": "", + "vendor": "", + "vendorname": "" + }, + "labels": { + "actions": "", + "bill_lines": "", + "bill_total": "", + "billcmtotal": "", + "bills": "", + "calculatedcreditsnotreceived": "", + "creditsnotreceived": "", + "creditsreceived": "", + "dedfromlbr": "", + "deleteconfirm": "", + "discrepancy": "", + "discrepwithcms": "", + "discrepwithlbradj": "", + "editadjwarning": "", + "entered_total": "", + "enteringcreditmemo": "", + "federal_tax": "", + "federal_tax_exempt": "", + "generatepartslabel": "", + "iouexists": "", + "local_tax": "", + "markexported": "", + "markforreexport": "", + "new": "", + "nobilllines": "", + "noneselected": "", + "onlycmforinvoiced": "", + "printlabels": "", + "retailtotal": "", + "returnfrombill": "", + "savewithdiscrepancy": "", + "state_tax": "", + "subtotal": "", + "totalreturns": "" + }, + "successes": { + "created": "", + "deleted": "", + "exported": "", + "markexported": "", + "reexport": "" + }, + "validation": { + "closingperiod": "", + "inventoryquantity": "", + "manualinhouse": "", + "unique_invoice_number": "" + } + }, + "bodyshop": { + "actions": { + "add_task_preset": "", + "addapptcolor": "", + "addbucket": "", + "addpartslocation": "", + "addpartsrule": "", + "addspeedprint": "", + "addtemplate": "", + "newlaborrate": "", + "newsalestaxcode": "", + "newstatus": "", + "testrender": "" + }, + "errors": { + "creatingdefaultview": "", + "loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.", + "saving": "" + }, + "fields": { + "ReceivableCustomField": "", + "address1": "", + "address2": "", + "appt_alt_transport": "", + "appt_colors": { + "color": "", + "label": "" + }, + "appt_length": "", + "attach_pdf_to_email": "", + "batchid": "", + "bill_allow_post_to_closed": "", + "bill_federal_tax_rate": "", + "bill_local_tax_rate": "", + "bill_state_tax_rate": "", + "city": "", + "closingperiod": "", + "companycode": "", + "country": "", + "dailybodytarget": "", + "dailypainttarget": "", + "default_adjustment_rate": "", + "deliver": { + "require_actual_delivery_date": "", + "templates": "" + }, + "dms": { + "apcontrol": "", + "appostingaccount": "", + "cashierid": "", + "default_journal": "", + "disablebillwip": "", + "disablecontactvehiclecreation": "", + "dms_acctnumber": "", + "dms_control_override": "", + "dms_wip_acctnumber": "", + "generic_customer_number": "", + "itc_federal": "", + "itc_local": "", + "itc_state": "", + "mappingname": "", + "sendmaterialscosting": "", + "srcco": "" + }, + "email": "", + "enforce_class": "", + "enforce_conversion_category": "", + "enforce_conversion_csr": "", + "enforce_referral": "", + "federal_tax_id": "", + "ignoreblockeddays": "", + "inhousevendorid": "", + "insurance_vendor_id": "", + "intake": { + "next_contact_hours": "", + "templates": "" + }, + "intellipay_config": { + "cash_discount_percentage": "", + "enable_cash_discount": "", + "payment_type": "", + "payment_map": { + "amex": "American Express", + "disc": "Discover", + "dnrs": "Diners", + "intr": "Interac", + "jcb": "JCB", + "mast": "MasterCard", + "visa": "Visa" + } + }, + "invoice_federal_tax_rate": "", + "invoice_local_tax_rate": "", + "invoice_state_tax_rate": "", + "jc_hourly_rates": { + "mapa": "", + "mash": "" + }, + "last_name_first": "", + "lastnumberworkingdays": "", + "localmediaserverhttp": "", + "localmediaservernetwork": "", + "localmediatoken": "", + "logo_img_footer_margin": "", + "logo_img_header_margin": "", + "logo_img_path": "", + "logo_img_path_height": "", + "logo_img_path_width": "", + "md_categories": "", + "md_ccc_rates": "", + "md_classes": "", + "md_ded_notes": "", + "md_email_cc": "", + "md_from_emails": "", + "md_functionality_toggles": { + "parts_queue_toggle": "" + }, + "md_hour_split": { + "paint": "", + "prep": "" + }, + "md_ins_co": { + "city": "", + "name": "", + "private": "", + "state": "", + "street1": "", + "street2": "", + "zip": "" + }, + "md_jobline_presets": "", + "md_lost_sale_reasons": "", + "md_parts_order_comment": "", + "md_parts_scan": { + "caseInsensitive": "", + "expression": "", + "field": "", + "flags": "", + "mark_critical": "", + "operation": "", + "update_field": "", + "update_value": "", + "value": "" + }, + "md_payment_types": "", + "md_referral_sources": "", + "md_ro_guard": { + "enabled": "", + "enforce_ar": "", + "enforce_bills": "", + "enforce_cm": "", + "enforce_labor": "", + "enforce_ppd": "", + "enforce_profit": "", + "enforce_sublet": "", + "masterbypass": "", + "totalgppercent_minimum": "" + }, + "md_tasks_presets": { + "enable_tasks": "", + "hourstype": "", + "memo": "", + "name": "", + "nextstatus": "", + "percent": "", + "use_approvals": "" + }, + "messaginglabel": "", + "messagingtext": "", + "noteslabel": "", + "notestext": "", + "partslocation": "", + "phone": "", + "prodtargethrs": "", + "rbac": { + "accounting": { + "exportlog": "", + "payables": "", + "payments": "", + "receivables": "" + }, + "bills": { + "delete": "", + "enter": "", + "list": "", + "reexport": "", + "view": "" + }, + "contracts": { + "create": "", + "detail": "", + "list": "" + }, + "courtesycar": { + "create": "", + "detail": "", + "list": "" + }, + "csi": { + "export": "", + "page": "" + }, + "employee_teams": { + "page": "" + }, + "employees": { + "page": "" + }, + "inventory": { + "delete": "", + "list": "" + }, + "jobs": { + "admin": "", + "available-list": "", + "checklist-view": "", + "close": "", + "create": "", + "deliver": "", + "detail": "", + "intake": "", + "list-active": "", + "list-all": "", + "list-ready": "", + "partsqueue": "", + "void": "" + }, + "owners": { + "detail": "", + "list": "" + }, + "payments": { + "enter": "", + "list": "" + }, + "phonebook": { + "edit": "", + "view": "" + }, + "production": { + "board": "", + "list": "" + }, + "schedule": { + "view": "" + }, + "scoreboard": { + "view": "" + }, + "shiftclock": { + "view": "" + }, + "shop": { + "config": "", + "dashboard": "", + "rbac": "", + "reportcenter": "", + "templates": "", + "vendors": "" + }, + "temporarydocs": { + "view": "" + }, + "timetickets": { + "edit": "", + "editcommitted": "", + "enter": "", + "list": "", + "shiftedit": "" + }, + "ttapprovals": { + "approve": "", + "view": "" + }, + "users": { + "editaccess": "" + } + }, + "responsibilitycenter": "", + "responsibilitycenter_accountdesc": "", + "responsibilitycenter_accountitem": "", + "responsibilitycenter_accountname": "", + "responsibilitycenter_accountnumber": "", + "responsibilitycenter_rate": "", + "responsibilitycenter_tax_rate": "", + "responsibilitycenter_tax_sur": "", + "responsibilitycenter_tax_thres": "", + "responsibilitycenter_tax_tier": "", + "responsibilitycenter_tax_type": "", + "responsibilitycenters": { + "ap": "", + "ar": "", + "ats": "", + "federal_tax": "", + "federal_tax_itc": "", + "gst_override": "", + "invoiceexemptcode": "", + "itemexemptcode": "", + "la1": "", + "la2": "", + "la3": "", + "la4": "", + "laa": "", + "lab": "", + "lad": "", + "lae": "", + "laf": "", + "lag": "", + "lam": "", + "lar": "", + "las": "", + "lau": "", + "local_tax": "", + "mapa": "", + "mash": "", + "paa": "", + "pac": "", + "pag": "", + "pal": "", + "pam": "", + "pan": "", + "pao": "", + "pap": "", + "par": "", + "pas": "", + "pasl": "", + "refund": "", + "sales_tax_codes": { + "code": "", + "description": "", + "federal": "", + "local": "", + "state": "" + }, + "state_tax": "", + "tow": "" + }, + "schedule_end_time": "", + "schedule_start_time": "", + "shopname": "", + "speedprint": { + "id": "", + "label": "", + "templates": "" + }, + "ss_configuration": { + "dailyhrslimit": "" + }, + "ssbuckets": { + "color": "", + "gte": "", + "id": "", + "label": "", + "lt": "", + "target": "" + }, + "state": "", + "state_tax_id": "", + "status": "", + "statuses": { + "active_statuses": "", + "additional_board_statuses": "", + "color": "", + "default_arrived": "", + "default_bo": "", + "default_canceled": "", + "default_completed": "", + "default_delivered": "", + "default_exported": "", + "default_imported": "", + "default_invoiced": "", + "default_ordered": "", + "default_quote": "", + "default_received": "", + "default_returned": "", + "default_scheduled": "", + "default_void": "", + "open_statuses": "", + "post_production_statuses": "", + "pre_production_statuses": "", + "production_colors": "", + "production_statuses": "", + "ready_statuses": "" + }, + "target_touchtime": "", + "timezone": "", + "tt_allow_post_to_invoiced": "", + "tt_enforce_hours_for_tech_console": "", + "use_fippa": "", + "use_paint_scale_data": "", + "uselocalmediaserver": "", + "website": "", + "zip_post": "" + }, + "labels": { + "2tiername": "", + "2tiersetup": "", + "2tiersource": "", + "accountingsetup": "", + "accountingtiers": "", + "alljobstatuses": "", + "allopenjobstatuses": "", + "apptcolors": "", + "businessinformation": "", + "checklists": "", + "csiq": "", + "customtemplates": "", + "defaultcostsmapping": "", + "defaultprofitsmapping": "", + "deliverchecklist": "", + "dms": { + "cdk": { + "controllist": "", + "payers": "" + }, + "cdk_dealerid": "", + "costsmapping": "", + "dms_allocations": "", + "pbs_serialnumber": "", + "profitsmapping": "", + "title": "" + }, + "emaillater": "", + "employee_teams": "", + "employees": "", + "estimators": "", + "filehandlers": "", + "imexpay": "", + "insurancecos": "", + "intakechecklist": "", + "intellipay_cash_discount": "", + "jobstatuses": "", + "laborrates": "", + "licensing": "", + "md_parts_scan": "", + "md_ro_guard": "", + "md_tasks_presets": "", + "md_to_emails": "", + "md_to_emails_emails": "", + "messagingpresets": "", + "notemplatesavailable": "", + "notespresets": "", + "orderstatuses": "", + "partslocations": "", + "partsscan": "", + "printlater": "", + "qbo": "", + "qbo_departmentid": "", + "qbo_usa": "", + "rbac": "", + "responsibilitycenters": { + "costs": "", + "profits": "", + "sales_tax_codes": "", + "tax_accounts": "", + "title": "", + "ttl_adjustment": "", + "ttl_tax_adjustment": "" + }, + "roguard": { + "title": "" + }, + "romepay": "", + "scheduling": "", + "scoreboardsetup": "", + "shop_enabled_features": "", + "shopinfo": "", + "speedprint": "", + "ssbuckets": "", + "systemsettings": "", + "task-presets": "", + "workingdays": "" + }, + "operations": { + "contains": "", + "ends_with": "", + "equals": "", + "greater_than": "", + "less_than": "", + "not_equals": "", + "starts_with": "" + }, + "successes": { + "areyousure": "", + "defaultviewcreated": "", + "save": "", + "unsavedchanges": "" + }, + "tooltips": { + "md_parts_scan": { + "update_value_tooltip": "" + } + }, + "validation": { + "centermustexist": "", + "larsplit": "", + "useremailmustexist": "" + } + }, + "checklist": { + "actions": { + "printall": "" + }, + "errors": { + "complete": "", + "nochecklist": "" + }, + "labels": { + "addtoproduction": "", + "allow_text_message": "", + "checklist": "", + "printpack": "", + "removefromproduction": "" + }, + "successes": { + "completed": "" + } + }, + "contracts": { + "actions": { + "changerate": "", + "convertoro": "", + "decodelicense": "", + "find": "", + "printcontract": "", + "senddltoform": "" + }, + "errors": { + "fetchingjobinfo": "", + "returning": "", + "saving": "", + "selectjobandcar": "" + }, + "fields": { + "actax": "", + "actualreturn": "", + "agreementnumber": "", + "cc_cardholder": "", + "cc_expiry": "", + "cc_num": "", + "cleanupcharge": "", + "coverage": "", + "dailyfreekm": "", + "dailyrate": "", + "damage": "", + "damagewaiver": "", + "driver": "", + "driver_addr1": "", + "driver_addr2": "", + "driver_city": "", + "driver_dlexpiry": "", + "driver_dlnumber": "", + "driver_dlst": "", + "driver_dob": "", + "driver_fn": "", + "driver_ln": "", + "driver_ph1": "", + "driver_state": "", + "driver_zip": "", + "excesskmrate": "", + "federaltax": "", + "fuelin": "", + "fuelout": "", + "kmend": "", + "kmstart": "", + "length": "", + "localtax": "", + "refuelcharge": "", + "scheduledreturn": "", + "start": "", + "statetax": "", + "status": "" + }, + "labels": { + "agreement": "", + "availablecars": "", + "cardueforservice": "", + "convertform": { + "applycleanupcharge": "", + "refuelqty": "" + }, + "correctdataonform": "", + "dateinpast": "", + "dlexpirebeforereturn": "", + "driverinformation": "", + "findcontract": "", + "findermodal": "", + "insuranceexpired": "", + "noteconvertedfrom": "", + "populatefromjob": "", + "rates": "", + "time": "", + "vehicle": "", + "waitingforscan": "" + }, + "status": { + "new": "", + "out": "", + "returned": "" + }, + "successes": { + "saved": "" + } + }, + "courtesycars": { + "actions": { + "new": "", + "return": "" + }, + "errors": { + "saving": "" + }, + "fields": { + "color": "", + "dailycost": "", + "damage": "", + "fleetnumber": "", + "fuel": "", + "insuranceexpires": "", + "leaseenddate": "", + "make": "", + "mileage": "", + "model": "", + "nextservicedate": "", + "nextservicekm": "", + "notes": "", + "plate": "", + "purchasedate": "", + "readiness": "", + "registrationexpires": "", + "serviceenddate": "", + "servicestartdate": "", + "status": "", + "vin": "", + "year": "" + }, + "labels": { + "courtesycar": "", + "fuel": { + "12": "", + "14": "", + "18": "", + "34": "", + "38": "", + "58": "", + "78": "", + "empty": "", + "full": "" + }, + "outwith": "", + "return": "", + "status": "", + "uniquefleet": "", + "usage": "", + "vehicle": "" + }, + "readiness": { + "notready": "", + "ready": "" + }, + "status": { + "in": "", + "inservice": "", + "leasereturn": "", + "out": "", + "sold": "", + "unavailable": "" + }, + "successes": { + "saved": "" + } + }, + "csi": { + "actions": { + "activate": "" + }, + "errors": { + "creating": "", + "notconfigured": "", + "notfoundsubtitle": "", + "notfoundtitle": "", + "surveycompletesubtitle": "", + "surveycompletetitle": "" + }, + "fields": { + "completedon": "", + "created_at": "", + "surveyid": "", + "validuntil": "" + }, + "labels": { + "copyright": "", + "greeting": "", + "intro": "", + "nologgedinuser": "", + "nologgedinuser_sub": "", + "noneselected": "", + "title": "" + }, + "successes": { + "created": "", + "submitted": "", + "submittedsub": "" + } + }, + "dashboard": { + "actions": { + "addcomponent": "" + }, + "errors": { + "refreshrequired": "", + "updatinglayout": "" + }, + "labels": { + "bodyhrs": "", + "dollarsinproduction": "", + "phone": "", + "prodhrs": "", + "refhrs": "" + }, + "titles": { + "joblifecycle": "", + "labhours": "", + "larhours": "", + "monthlyemployeeefficiency": "", + "monthlyjobcosting": "", + "monthlylaborsales": "", + "monthlypartssales": "", + "monthlyrevenuegraph": "", + "prodhrssummary": "", + "productiondollars": "", + "productionhours": "", + "projectedmonthlysales": "", + "scheduledindate": "", + "scheduledintoday": "", + "scheduledoutdate": "", + "scheduledouttoday": "", + "tasks": "" + } + }, + "dms": { + "errors": { + "alreadyexported": "" + }, + "labels": { + "refreshallocations": "" + } + }, + "documents": { + "actions": { + "delete": "", + "download": "", + "reassign": "", + "selectallimages": "", + "selectallotherdocuments": "" + }, + "errors": { + "deletes3": "Erreur lors de la suppression du document du stockage.", + "deleting": "", + "deleting_cloudinary": "", + "getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}", + "insert": "Incapable de télécharger le fichier. {{message}}", + "nodocuments": "Il n'y a pas de documents.", + "updating": "" + }, + "labels": { + "confirmdelete": "", + "doctype": "", + "dragtoupload": "", + "newjobid": "", + "openinexplorer": "", + "optimizedimage": "", + "reassign_limitexceeded": "", + "reassign_limitexceeded_title": "", + "storageexceeded": "", + "storageexceeded_title": "", + "upload": "Télécharger", + "upload_limitexceeded": "", + "upload_limitexceeded_title": "", + "uploading": "", + "usage": "" + }, + "successes": { + "delete": "Le document a bien été supprimé.", + "edituploaded": "", + "insert": "Document téléchargé avec succès.", + "updated": "" + } + }, + "emails": { + "errors": { + "notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}" + }, + "fields": { + "cc": "", + "from": "", + "subject": "", + "to": "" + }, + "labels": { + "attachments": "", + "documents": "", + "emailpreview": "", + "generatingemail": "", + "pdfcopywillbeattached": "", + "preview": "" + }, + "successes": { + "sent": "E-mail envoyé avec succès." + } + }, + "employee_teams": { + "actions": { + "new": "", + "newmember": "" + }, + "fields": { + "active": "", + "employeeid": "", + "max_load": "", + "name": "", + "percentage": "" + } + }, + "employees": { + "actions": { + "addvacation": "", + "new": "Nouvel employé", + "newrate": "" + }, + "errors": { + "delete": "Erreur rencontrée lors de la suppression de l'employé. {{message}}", + "save": "Une erreur s'est produite lors de l'enregistrement de l'employé. {{message}}", + "validation": "Veuillez cocher tous les champs.", + "validationtitle": "Impossible d'enregistrer l'employé." + }, + "fields": { + "active": "Actif?", + "base_rate": "Taux de base", + "cost_center": "Centre de coûts", + "employee_number": "Numéro d'employé", + "external_id": "", + "first_name": "Prénom", + "flat_rate": "Taux fixe (désactivé est le temps normal)", + "hire_date": "Date d'embauche", + "last_name": "Nom de famille", + "pin": "", + "rate": "", + "termination_date": "Date de résiliation", + "user_email": "", + "vacation": { + "end": "", + "length": "", + "start": "" + } + }, + "labels": { + "actions": "", + "active": "", + "endmustbeafterstart": "", + "flat_rate": "", + "inactive": "", + "name": "", + "rate_type": "", + "status": "", + "straight_time": "" + }, + "successes": { + "delete": "L'employé a bien été supprimé.", + "save": "L'employé a enregistré avec succès.", + "vacationadded": "" + }, + "validation": { + "unique_employee_number": "" + } + }, + "eula": { + "buttons": { + "accept": "Accept EULA" + }, + "content": { + "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting." + }, + "errors": { + "acceptance": { + "description": "Something went wrong while accepting the EULA. Please try again.", + "message": "Eula Acceptance Error" + } + }, + "labels": { + "accepted_terms": "I accept the terms and conditions of this agreement.", + "address": "Address", + "business_name": "Legal Business Name", + "date_accepted": "Date Accepted", + "first_name": "First Name", + "last_name": "Last Name", + "phone_number": "Phone Number" + }, + "messages": { + "accepted_terms": "Please accept the terms and conditions of this agreement.", + "business_name": "Please enter your legal business name.", + "date_accepted": "Please enter Today's Date.", + "first_name": "Please enter your first name.", + "last_name": "Please enter your last name.", + "phone_number": "Please enter your phone number." + }, + "titles": { + "modal": "Terms and Conditions", + "upper_card": "Acknowledgement" + } + }, + "exportlogs": { + "fields": { + "createdat": "" + }, + "labels": { + "attempts": "", + "priorsuccesfulexport": "" + } + }, + "general": { + "actions": { + "add": "", + "autoupdate": "", + "calculate": "", + "cancel": "", + "clear": "", + "close": "", + "copied": "", + "copylink": "", + "create": "", + "defaults": "", + "delay": "", + "delete": "Effacer", + "deleteall": "", + "deselectall": "", + "download": "", + "edit": "modifier", + "login": "", + "next": "", + "ok": "", + "previous": "", + "print": "", + "refresh": "", + "remove": "", + "remove_alert": "", + "reset": " Rétablir l'original.", + "resetpassword": "", + "save": "sauvegarder", + "saveandnew": "", + "saveas": "", + "selectall": "", + "send": "", + "sendbysms": "", + "senderrortosupport": "", + "sharetoteams": "", + "submit": "", + "tryagain": "", + "view": "", + "viewreleasenotes": "" + }, + "errors": { + "fcm": "", + "notfound": "", + "sizelimit": "" + }, + "itemtypes": { + "contract": "", + "courtesycar": "", + "job": "", + "owner": "", + "vehicle": "" + }, + "labels": { + "actions": "actes", + "areyousure": "", + "barcode": "code à barre", + "cancel": "", + "clear": "", + "confirmpassword": "", + "created_at": "", + "date": "", + "datetime": "", + "email": "", + "errors": "", + "excel": "", + "exceptiontitle": "", + "friday": "", + "globalsearch": "", + "help": "", + "hours": "", + "in": "dans", + "instanceconflictext": "", + "instanceconflictitle": "", + "item": "", + "label": "", + "loading": "Chargement...", + "loadingapp": "Chargement de {{app}}", + "loadingshop": "Chargement des données de la boutique ...", + "loggingin": "Vous connecter ...", + "markedexported": "", + "media": "", + "message": "", + "monday": "", + "na": "N / A", + "newpassword": "", + "no": "", + "nointernet": "", + "nointernet_sub": "", + "none": "", + "out": "En dehors", + "password": "", + "passwordresetsuccess": "", + "passwordresetsuccess_sub": "", + "passwordresetvalidatesuccess": "", + "passwordresetvalidatesuccess_sub": "", + "passwordsdonotmatch": "", + "print": "", + "refresh": "", + "reports": "", + "required": "", + "saturday": "", + "search": "Chercher...", + "searchresults": "", + "selectdate": "", + "sendagain": "", + "sendby": "", + "signin": "", + "sms": "", + "status": "", + "sub_status": { + "expired": "" + }, + "successful": "", + "sunday": "", + "text": "", + "thursday": "", + "time": "", + "total": "", + "totals": "", + "tuesday": "", + "tvmode": "", + "unknown": "Inconnu", + "unsavedchanges": "", + "username": "", + "view": "", + "wednesday": "", + "yes": "" + }, + "languages": { + "english": "Anglais", + "french": "Francais", + "spanish": "Espanol" + }, + "messages": { + "exception": "", + "newversionmessage": "", + "newversiontitle": "", + "noacctfilepath": "", + "nofeatureaccess": "", + "noshop": "", + "notfoundsub": "", + "notfoundtitle": "", + "partnernotrunning": "", + "rbacunauth": "", + "unsavedchanges": "Vous avez des changements non enregistrés.", + "unsavedchangespopup": "" + }, + "validation": { + "dateRangeExceeded": "", + "invalidemail": "S'il vous plaît entrer un email valide.", + "invalidphone": "", + "required": "Ce champ est requis." + } + }, + "help": { + "actions": { + "connect": "" + }, + "labels": { + "codeplacholder": "", + "rescuedesc": "", + "rescuetitle": "" + } + }, + "intake": { + "labels": { + "printpack": "" + } + }, + "inventory": { + "actions": { + "addtoinventory": "", + "addtoro": "", + "consumefrominventory": "", + "edit": "", + "new": "" + }, + "errors": { + "inserting": "" + }, + "fields": { + "comment": "", + "manualinvoicenumber": "", + "manualvendor": "" + }, + "labels": { + "consumedbyjob": "", + "deleteconfirm": "", + "frombillinvoicenumber": "", + "fromvendor": "", + "inventory": "", + "showall": "", + "showavailable": "" + }, + "successes": { + "deleted": "", + "inserted": "", + "updated": "" + } + }, + "job_lifecycle": { + "columns": { + "average_human_readable": "", + "average_value": "", + "duration": "", + "end": "", + "human_readable": "", + "percentage": "", + "relative_end": "", + "relative_start": "", + "start": "", + "status": "", + "status_count": "", + "value": "" + }, + "content": { + "calculated_based_on": "", + "current_status_accumulated_time": "", + "data_unavailable": "", + "jobs_in_since": "", + "legend_title": "", + "loading": "", + "not_available": "", + "previous_status_accumulated_time": "", + "title": "", + "title_durations": "", + "title_loading": "", + "title_transitions": "" + }, + "errors": { + "fetch": "Erreur lors de l'obtention des données du cycle de vie des tâches" + }, + "titles": { + "dashboard": "", + "top_durations": "" + } + }, + "job_payments": { + "buttons": { + "create_short_link": "", + "goback": "", + "proceedtopayment": "", + "refundpayment": "" + }, + "notifications": { + "error": { + "description": "", + "openingip": "", + "title": "" + } + }, + "titles": { + "amount": "", + "dateOfPayment": "", + "descriptions": "", + "hint": "", + "payer": "", + "payername": "", + "paymentid": "", + "paymentnum": "", + "paymenttype": "", + "refundamount": "", + "transactionid": "" + } + }, + "joblines": { + "actions": { + "assign_team": "", + "converttolabor": "", + "dispatchparts": "", + "new": "" + }, + "errors": { + "creating": "", + "updating": "" + }, + "fields": { + "act_price": "Prix actuel", + "act_price_before_ppc": "", + "adjustment": "", + "ah_detail_line": "", + "alt_partno": "", + "amount": "", + "assigned_team": "", + "assigned_team_name": "", + "create_ppc": "", + "db_price": "Prix de la base de données", + "include_in_part_cnt": "", + "lbr_types": { + "LA1": "", + "LA2": "", + "LA3": "", + "LA4": "", + "LAA": "", + "LAB": "", + "LAD": "", + "LAE": "", + "LAF": "", + "LAG": "", + "LAM": "", + "LAR": "", + "LAS": "", + "LAU": "" + }, + "line_desc": "Description de la ligne", + "line_ind": "S#", + "line_no": "", + "location": "", + "mod_lb_hrs": "Heures de travail", + "mod_lbr_ty": "Type de travail", + "notes": "", + "oem_partno": "Pièce OEM #", + "op_code_desc": "", + "part_qty": "", + "part_type": "Type de pièce", + "part_types": { + "CCC": "", + "CCD": "", + "CCDR": "", + "CCF": "", + "CCM": "", + "PAA": "", + "PAC": "", + "PAE": "", + "PAG": "", + "PAL": "", + "PAM": "", + "PAN": "", + "PAO": "", + "PAP": "", + "PAR": "", + "PAS": "", + "PASL": "" + }, + "profitcenter_labor": "", + "profitcenter_part": "", + "prt_dsmk_m": "", + "prt_dsmk_p": "", + "status": "Statut", + "tax_part": "", + "total": "", + "unq_seq": "Seq #" + }, + "labels": { + "adjustmenttobeadded": "", + "billref": "", + "convertedtolabor": "", + "edit": "Ligne d'édition", + "ioucreated": "", + "new": "Nouvelle ligne", + "nostatus": "", + "presets": "" + }, + "successes": { + "created": "", + "saved": "", + "updated": "" + }, + "validations": { + "ahdetailonlyonuserdefinedtypes": "", + "hrsrequirediflbrtyp": "", + "requiredifparttype": "", + "zeropriceexistingpart": "" + } + }, + "jobs": { + "actions": { + "addDocuments": "Ajouter des documents de travail", + "addNote": "Ajouter une note", + "addtopartsqueue": "", + "addtoproduction": "", + "addtoscoreboard": "", + "allocate": "", + "autoallocate": "", + "changefilehandler": "", + "changelaborrate": "", + "changestatus": "Changer le statut", + "changestimator": "", + "convert": "Convertir", + "createiou": "", + "deliver": "", + "deliver_quick": "", + "dms": { + "addpayer": "", + "createnewcustomer": "", + "findmakemodelcode": "", + "getmakes": "", + "labels": { + "refreshallocations": "" + }, + "post": "", + "refetchmakesmodels": "", + "usegeneric": "", + "useselected": "" + }, + "dmsautoallocate": "", + "export": "", + "exportcustdata": "", + "exportselected": "", + "filterpartsonly": "", + "generatecsi": "", + "gotojob": "", + "intake": "", + "intake_quick": "", + "manualnew": "", + "mark": "", + "markasexported": "", + "markpstexempt": "", + "markpstexemptconfirm": "", + "postbills": "Poster des factures", + "printCenter": "Centre d'impression", + "recalculate": "", + "reconcile": "", + "removefromproduction": "", + "schedule": "Programme", + "sendcsi": "", + "sendpartspricechange": "", + "sendtodms": "", + "sync": "", + "taxprofileoverride": "", + "taxprofileoverride_confirm": "", + "uninvoice": "", + "unvoid": "", + "viewchecklist": "", + "viewdetail": "" + }, + "errors": { + "addingtoproduction": "", + "cannotintake": "", + "closing": "", + "creating": "", + "deleted": "Erreur lors de la suppression du travail.", + "exporting": "", + "exporting-partner": "", + "invoicing": "", + "noaccess": "Ce travail n'existe pas ou vous n'y avez pas accès.", + "nodamage": "", + "nodates": "Aucune date spécifiée pour ce travail.", + "nofinancial": "", + "nojobselected": "Aucun travail n'est sélectionné.", + "noowner": "Aucun propriétaire associé.", + "novehicle": "Aucun véhicule associé.", + "partspricechange": "", + "saving": "Erreur rencontrée lors de la sauvegarde de l'enregistrement.", + "scanimport": "", + "totalscalc": "", + "updating": "", + "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.", + "validationtitle": "Erreur de validation", + "voiding": "" + }, + "fields": { + "active_tasks": "", + "actual_completion": "Achèvement réel", + "actual_delivery": "Livraison réelle", + "actual_in": "En réel", + "adjustment_bottom_line": "Ajustements", + "adjustmenthours": "", + "alt_transport": "", + "area_of_damage_impact": { + "10": "", + "11": "", + "12": "", + "13": "", + "14": "", + "15": "", + "16": "", + "25": "", + "26": "", + "27": "", + "28": "", + "34": "", + "01": "", + "02": "", + "03": "", + "04": "", + "05": "", + "06": "", + "07": "", + "08": "", + "09": "" + }, + "auto_add_ats": "", + "ca_bc_pvrt": "", + "ca_customer_gst": "", + "ca_gst_registrant": "", + "category": "", + "ccc": "", + "ccd": "", + "ccdr": "", + "ccf": "", + "ccm": "", + "cieca_id": "CIECA ID", + "cieca_pfl": { + "lbr_adjp": "", + "lbr_tax_in": "", + "lbr_taxp": "", + "lbr_tx_in1": "", + "lbr_tx_in2": "", + "lbr_tx_in3": "", + "lbr_tx_in4": "", + "lbr_tx_in5": "" + }, + "cieca_pfo": { + "stor_t_in1": "", + "stor_t_in2": "", + "stor_t_in3": "", + "stor_t_in4": "", + "stor_t_in5": "", + "tow_t_in1": "", + "tow_t_in2": "", + "tow_t_in3": "", + "tow_t_in4": "", + "tow_t_in5": "" + }, + "claim_total": "Total réclamation", + "class": "", + "clm_no": "Prétendre #", + "clm_total": "Total réclamation", + "comment": "", + "customerowing": "Client propriétaire", + "date_estimated": "Date estimée", + "date_exported": "Exportés", + "date_invoiced": "Facturé", + "date_last_contacted": "", + "date_lost_sale": "", + "date_next_contact": "", + "date_open": "Ouvrir", + "date_rentalresp": "", + "date_repairstarted": "", + "date_scheduled": "Prévu", + "date_towin": "", + "date_void": "", + "ded_amt": "Déductible", + "ded_note": "", + "ded_status": "Statut de franchise", + "depreciation_taxes": "Amortissement / taxes", + "dms": { + "address": "", + "amount": "", + "center": "", + "control_type": { + "account_number": "" + }, + "cost": "", + "cost_dms_acctnumber": "", + "dms_make": "", + "dms_model": "", + "dms_model_override": "", + "dms_unsold": "", + "dms_wip_acctnumber": "", + "id": "", + "inservicedate": "", + "journal": "", + "lines": "", + "name1": "", + "payer": { + "amount": "", + "control_type": "", + "controlnumber": "", + "dms_acctnumber": "", + "name": "" + }, + "sale": "", + "sale_dms_acctnumber": "", + "story": "", + "vinowner": "" + }, + "dms_allocation": "", + "driveable": "", + "employee_body": "", + "employee_csr": "représentant du service à la clientèle", + "employee_csr_writer": "", + "employee_prep": "", + "employee_refinish": "", + "est_addr1": "Adresse de l'évaluateur", + "est_co_nm": "Expert", + "est_ct_fn": "Prénom de l'évaluateur", + "est_ct_ln": "Nom de l'évaluateur", + "est_ea": "Courriel de l'évaluateur", + "est_ph1": "Numéro de téléphone de l'évaluateur", + "federal_tax_payable": "Impôt fédéral à payer", + "federal_tax_rate": "", + "ins_addr1": "Adresse Insurance Co.", + "ins_city": "Insurance City", + "ins_co_id": "ID de la compagnie d'assurance", + "ins_co_nm": "Nom de la compagnie d'assurance", + "ins_co_nm_short": "", + "ins_ct_fn": "Prénom du gestionnaire de fichiers", + "ins_ct_ln": "Nom du gestionnaire de fichiers", + "ins_ea": "Courriel du gestionnaire de fichiers", + "ins_ph1": "Numéro de téléphone du gestionnaire de fichiers", + "intake": { + "label": "", + "max": "", + "min": "", + "name": "", + "required": "", + "type": "" + }, + "invoice_final_note": "", + "kmin": "Kilométrage en", + "kmout": "Kilométrage hors", + "la1": "", + "la2": "", + "la3": "", + "la4": "", + "laa": "", + "lab": "", + "labor_rate_desc": "Nom du taux de main-d'œuvre", + "lad": "", + "lae": "", + "laf": "", + "lag": "", + "lam": "", + "lar": "", + "las": "", + "lau": "", + "local_tax_rate": "", + "loss_date": "Date de perte", + "loss_desc": "", + "loss_of_use": "", + "lost_sale_reason": "", + "ma2s": "", + "ma3s": "", + "mabl": "", + "macs": "", + "mahw": "", + "mapa": "", + "mash": "", + "matd": "", + "materials": { + "MAPA": "", + "MASH": "", + "cal_maxdlr": "", + "cal_opcode": "", + "mat_adjp": "", + "mat_taxp": "", + "mat_tx_in1": "", + "mat_tx_in2": "", + "mat_tx_in3": "", + "mat_tx_in4": "", + "mat_tx_in5": "", + "materials": "", + "tax_ind": "" + }, + "other_amount_payable": "Autre montant à payer", + "owner": "Propriétaire", + "owner_owing": "Cust. Owes", + "ownr_ea": "Email", + "ownr_ph1": "Téléphone 1", + "ownr_ph2": "", + "paa": "", + "pac": "", + "pae": "", + "pag": "", + "pal": "", + "pam": "", + "pan": "", + "pao": "", + "pap": "", + "par": "", + "parts_tax_rates": { + "prt_discp": "", + "prt_mktyp": "", + "prt_mkupp": "", + "prt_tax_in": "", + "prt_tax_rt": "", + "prt_tx_in1": "", + "prt_tx_in2": "", + "prt_tx_in3": "", + "prt_tx_in4": "", + "prt_tx_in5": "", + "prt_tx_ty1": "", + "prt_type": "" + }, + "partsstatus": "", + "pas": "", + "pay_date": "Date d'Pay", + "phoneshort": "PH", + "po_number": "", + "policy_no": "Politique #", + "ponumber": "Numéro de bon de commande", + "production_vars": { + "note": "" + }, + "qb_multiple_payers": { + "amount": "", + "name": "" + }, + "queued_for_parts": "", + "rate_ats": "", + "rate_la1": "Taux LA1", + "rate_la2": "Taux LA2", + "rate_la3": "Taux LA3", + "rate_la4": "Taux LA4", + "rate_laa": "Taux d'aluminium", + "rate_lab": "Taux de la main-d'œuvre", + "rate_lad": "Taux de diagnostic", + "rate_lae": "Tarif électrique", + "rate_laf": "Taux de trame", + "rate_lag": "Taux de verre", + "rate_lam": "Taux mécanique", + "rate_lar": "Taux de finition", + "rate_las": "", + "rate_lau": "Taux d'aluminium", + "rate_ma2s": "Taux de peinture en 2 étapes", + "rate_ma3s": "Taux de peinture en 3 étapes", + "rate_mabl": "MABL ??", + "rate_macs": "MACS ??", + "rate_mahw": "Taux de déchets dangereux", + "rate_mapa": "Taux de matériaux de peinture", + "rate_mash": "Tarif du matériel de la boutique", + "rate_matd": "Taux d'élimination des pneus", + "referral_source_extra": "", + "referral_source_other": "", + "referralsource": "Source de référence", + "regie_number": "Enregistrement #", + "repairtotal": "Réparation totale", + "ro_number": "RO #", + "scheduled_completion": "Achèvement planifié", + "scheduled_delivery": "Livraison programmée", + "scheduled_in": "Planifié dans", + "selling_dealer": "Revendeur vendeur", + "selling_dealer_contact": "Contacter le revendeur", + "servicecar": "Voiture de service", + "servicing_dealer": "Concessionnaire", + "servicing_dealer_contact": "Contacter le concessionnaire", + "special_coverage_policy": "Politique de couverture spéciale", + "specialcoveragepolicy": "Politique de couverture spéciale", + "state_tax_rate": "", + "status": "Statut de l'emploi", + "storage_payable": "Stockage", + "tax_lbr_rt": "", + "tax_levies_rt": "", + "tax_paint_mat_rt": "", + "tax_registration_number": "", + "tax_shop_mat_rt": "", + "tax_str_rt": "", + "tax_sub_rt": "", + "tax_tow_rt": "", + "tlos_ind": "", + "towin": "", + "towing_payable": "Remorquage à payer", + "unitnumber": "Unité #", + "updated_at": "Mis à jour à", + "uploaded_by": "Telechargé par", + "vehicle": "Véhicule" + }, + "forms": { + "admindates": "", + "appraiserinfo": "", + "claiminfo": "", + "estdates": "", + "laborrates": "", + "lossinfo": "", + "other": "", + "repairdates": "", + "scheddates": "" + }, + "labels": { + "accountsreceivable": "", + "act_price_ppc": "", + "actual_completion_inferred": "", + "actual_delivery_inferred": "", + "actual_in_inferred": "", + "additionalpayeroverallocation": "", + "additionaltotal": "", + "adjustmentrate": "", + "adjustments": "", + "adminwarning": "", + "allocations": "", + "alreadyaddedtoscoreboard": "", + "alreadyclosed": "", + "appointmentconfirmation": "Envoyer une confirmation au client?", + "associationwarning": "", + "audit": "", + "available": "", + "availablejobs": "", + "ca_bc_pvrt": { + "days": "", + "rate": "" + }, + "ca_gst_all_if_null": "", + "calc_repair_days": "", + "calc_repair_days_tt": "", + "calc_scheuled_completion": "", + "cards": { + "customer": "Informations client", + "damage": "Zone de dommages", + "dates": "Rendez-vous", + "documents": "Documents récents", + "estimator": "Estimateur", + "filehandler": "Gestionnaire de fichiers", + "insurance": "Détails de l'assurance", + "more": "Plus", + "notes": "Remarques", + "parts": "les pièces", + "totals": "Totaux", + "vehicle": "Véhicule" + }, + "changeclass": "", + "checklistcompletedby": "", + "checklistdocuments": "", + "checklists": "", + "cieca_pfl": "", + "cieca_pfo": "", + "cieca_pft": "", + "closeconfirm": "", + "closejob": "", + "closingperiod": "", + "contracts": "", + "convertedtolabor": "", + "cost": "", + "cost_Additional": "", + "cost_labor": "", + "cost_parts": "", + "cost_sublet": "", + "costs": "", + "create": { + "jobinfo": "", + "newowner": "", + "newvehicle": "", + "novehicle": "", + "ownerinfo": "", + "vehicleinfo": "" + }, + "createiouwarning": "", + "creating_new_job": "Création d'un nouvel emploi ...", + "deductible": { + "stands": "", + "waived": "" + }, + "deleteconfirm": "", + "deletedelivery": "", + "deleteintake": "", + "deliverchecklist": "", + "difference": "", + "diskscan": "", + "dms": { + "apexported": "", + "damageto": "", + "defaultstory": "", + "disablebillwip": "", + "invoicedatefuture": "", + "kmoutnotgreaterthankmin": "", + "logs": "", + "notallocated": "", + "postingform": "", + "totalallocated": "" + }, + "documents": "Les documents", + "documents-images": "", + "documents-other": "", + "duplicateconfirm": "", + "emailaudit": "", + "employeeassignments": "", + "estimatelines": "", + "estimator": "", + "existing_jobs": "Emplois existants", + "federal_tax_amt": "", + "gpdollars": "", + "gppercent": "", + "hrs_claimed": "", + "hrs_total": "", + "importnote": "", + "inproduction": "", + "intakechecklist": "", + "iou": "", + "job": "", + "jobcosting": "", + "jobtotals": "", + "labor_hrs": "", + "labor_rates_subtotal": "", + "laborallocations": "", + "labortotals": "", + "lines": "Estimer les lignes", + "local_tax_amt": "", + "mapa": "", + "markforreexport": "", + "mash": "", + "masterbypass": "", + "materials": { + "mapa": "" + }, + "missingprofileinfo": "", + "multipayers": "", + "net_repairs": "", + "notes": "Remarques", + "othertotal": "", + "outstanding_ar": "", + "outstanding_credit_memos": "", + "outstanding_ppd": "", + "outstanding_reconciliation_discrep": "", + "outstanding_sublets": "", + "outstandinghours": "", + "override_header": "Remplacer l'en-tête d'estimation à l'importation?", + "ownerassociation": "", + "parts": "les pièces", + "parts_lines": "", + "parts_received": "", + "parts_tax_rates": "", + "partsfilter": "", + "partssubletstotal": "", + "partstotal": "", + "performance": "", + "pimraryamountpayable": "", + "plitooltips": { + "billtotal": "", + "calculatedcreditsnotreceived": "", + "creditmemos": "", + "creditsnotreceived": "", + "discrep1": "", + "discrep2": "", + "discrep3": "", + "laboradj": "", + "partstotal": "", + "totalreturns": "" + }, + "ppc": "", + "ppdnotexported": "", + "profileadjustments": "", + "profitbypassrequired": "", + "profits": "", + "prt_dsmk_total": "", + "rates": "Les taux", + "rates_subtotal": "", + "reconciliation": { + "billlinestotal": "", + "byassoc": "", + "byprice": "", + "clear": "", + "discrepancy": "", + "joblinestotal": "", + "multipleactprices": "", + "multiplebilllines": "", + "multiplebillsforactprice": "", + "removedpartsstrikethrough": "" + }, + "reconciliationheader": "", + "relatedros": "", + "remove_from_ar": "", + "returntotals": "", + "ro_guard": { + "enforce_ar": "", + "enforce_bills": "", + "enforce_cm": "", + "enforce_labor": "", + "enforce_ppd": "", + "enforce_profit": "", + "enforce_sublet": "", + "enforce_validation": "", + "enforced": "" + }, + "roguard": "", + "roguardwarnings": "", + "rosaletotal": "", + "sale_additional": "", + "sale_labor": "", + "sale_parts": "", + "sale_sublet": "", + "sales": "", + "savebeforeconversion": "", + "scheduledinchange": "", + "specialcoveragepolicy": "", + "state_tax_amt": "", + "subletsnotcompleted": "", + "subletstotal": "", + "subtotal": "", + "supplementnote": "", + "suspended": "", + "suspense": "", + "tasks": "", + "threshhold": "", + "total_cost": "", + "total_cust_payable": "", + "total_cust_payable_cash_discount": "", + "total_repairs": "", + "total_repairs_cash_discount": "", + "total_sales": "", + "total_sales_tax": "", + "totals": "", + "unvoidnote": "", + "update_scheduled_completion": "", + "vehicle_info": "Véhicule", + "vehicleassociation": "", + "viewallocations": "", + "voidjob": "", + "voidnote": "" + }, + "successes": { + "addedtoproduction": "", + "all_deleted": "{{count}} travaux supprimés avec succès.", + "closed": "", + "converted": "Travail converti avec succès.", + "created": "Le travail a été créé avec succès. Clique pour voir.", + "creatednoclick": "", + "delete": "", + "deleted": "Le travail a bien été supprimé.", + "duplicated": "", + "exported": "", + "invoiced": "", + "ioucreated": "", + "partsqueue": "", + "save": "Le travail a été enregistré avec succès.", + "savetitle": "Enregistrement enregistré avec succès.", + "supplemented": "Travail complété avec succès.", + "updated": "", + "voided": "" + } + }, + "landing": { + "bigfeature": { + "subtitle": "", + "title": "" + }, + "footer": { + "company": { + "about": "", + "contact": "", + "disclaimers": "", + "name": "", + "privacypolicy": "" + }, + "io": { + "help": "", + "name": "", + "status": "" + }, + "slogan": "" + }, + "hero": { + "button": "", + "title": "" + }, + "labels": { + "features": "", + "managemyshop": "", + "pricing": "" + }, + "pricing": { + "basic": { + "name": "", + "sub": "" + }, + "essentials": { + "name": "", + "sub": "" + }, + "pricingtitle": "", + "pro": { + "name": "", + "sub": "" + }, + "title": "", + "unlimited": { + "name": "", + "sub": "" + } + } + }, + "menus": { + "currentuser": { + "languageselector": "La langue", + "profile": "Profil" + }, + "header": { + "accounting": "", + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "activejobs": "Emplois actifs", + "all_tasks": "", + "alljobs": "", + "allpayments": "", + "availablejobs": "Emplois disponibles", + "bills": "", + "courtesycars": "", + "courtesycars-all": "", + "courtesycars-contracts": "", + "courtesycars-newcontract": "", + "create_task": "", + "customers": "Les clients", + "dashboard": "", + "enterbills": "", + "entercardpayment": "", + "enterpayment": "", + "entertimeticket": "", + "export": "", + "export-logs": "", + "help": "", + "home": "Accueil", + "inventory": "", + "jobs": "Emplois", + "my_tasks": "", + "newjob": "", + "owners": "Propriétaires", + "parts-queue": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "readyjobs": "", + "recent": "", + "reportcenter": "", + "rescueme": "", + "schedule": "Programme", + "scoreboard": "", + "search": { + "bills": "", + "jobs": "", + "owners": "", + "payments": "", + "phonebook": "", + "vehicles": "" + }, + "shiftclock": "", + "shop": "Mon magasin", + "shop_config": "Configuration", + "shop_csi": "", + "shop_templates": "", + "shop_vendors": "Vendeurs", + "tasks": "", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicles": "Véhicules" + }, + "jobsactions": { + "admin": "", + "cancelallappointments": "", + "closejob": "", + "deletejob": "", + "duplicate": "", + "duplicatenolines": "", + "newcccontract": "", + "void": "" + }, + "jobsdetail": { + "claimdetail": "Détails de la réclamation", + "dates": "Rendez-vous", + "financials": "", + "general": "", + "insurance": "", + "labor": "La main d'oeuvre", + "lifecycle": "", + "parts": "", + "partssublet": "Pièces / Sous-location", + "rates": "", + "repairdata": "Données de réparation", + "totals": "" + }, + "profilesidebar": { + "profile": "Mon profil", + "shops": "Mes boutiques" + }, + "tech": { + "assignedjobs": "", + "claimtask": "", + "dispatchedparts": "", + "home": "", + "jobclockin": "", + "jobclockout": "", + "joblookup": "", + "login": "", + "logout": "", + "productionboard": "", + "productionlist": "", + "shiftclockin": "" + } + }, + "messaging": { + "actions": { + "link": "", + "new": "" + }, + "errors": { + "invalidphone": "", + "noattachedjobs": "", + "updatinglabel": "" + }, + "labels": { + "addlabel": "", + "archive": "", + "maxtenimages": "", + "messaging": "Messagerie", + "noallowtxt": "", + "nojobs": "", + "nopush": "", + "phonenumber": "", + "presets": "", + "recentonly": "", + "selectmedia": "", + "sentby": "", + "typeamessage": "Envoyer un message...", + "unarchive": "" + }, + "render": { + "conversation_list": "" + } + }, + "notes": { + "actions": { + "actions": "actes", + "deletenote": "Supprimer la note", + "edit": "Note éditée", + "new": "Nouvelle note", + "savetojobnotes": "" + }, + "errors": { + "inserting": "" + }, + "fields": { + "createdby": "Créé par", + "critical": "Critique", + "private": "privé", + "text": "Contenu", + "type": "", + "types": { + "customer": "", + "general": "", + "office": "", + "paint": "", + "parts": "", + "shop": "", + "supplement": "" + }, + "updatedat": "Mis à jour à" + }, + "labels": { + "addtorelatedro": "", + "newnoteplaceholder": "Ajouter une note...", + "notetoadd": "", + "systemnotes": "", + "usernotes": "" + }, + "successes": { + "create": "Remarque créée avec succès.", + "deleted": "Remarque supprimée avec succès.", + "updated": "Remarque mise à jour avec succès." + } + }, + "owner": { + "labels": { + "noownerinfo": "" + } + }, + "owners": { + "actions": { + "update": "" + }, + "errors": { + "deleting": "", + "noaccess": "L'enregistrement n'existe pas ou vous n'y avez pas accès.", + "saving": "", + "selectexistingornew": "" + }, + "fields": { + "accountingid": "", + "address": "Adresse", + "allow_text_message": "Autorisation de texte?", + "name": "Prénom", + "note": "", + "ownr_addr1": "Adresse", + "ownr_addr2": "Adresse 2 ", + "ownr_city": "Ville", + "ownr_co_nm": "", + "ownr_ctry": "Pays", + "ownr_ea": "Email", + "ownr_fn": "Prénom", + "ownr_ln": "Nom de famille", + "ownr_ph1": "Téléphone 1", + "ownr_ph2": "", + "ownr_st": "Etat / Province", + "ownr_title": "Titre", + "ownr_zip": "Zip / code postal", + "preferred_contact": "Méthode de contact préférée", + "tax_number": "" + }, + "forms": { + "address": "", + "contact": "", + "name": "" + }, + "labels": { + "create_new": "Créez un nouvel enregistrement de propriétaire.", + "deleteconfirm": "", + "existing_owners": "Propriétaires existants", + "fromclaim": "", + "fromowner": "", + "relatedjobs": "", + "updateowner": "" + }, + "successes": { + "delete": "", + "save": "Le propriétaire a bien enregistré." + } + }, + "parts": { + "actions": { + "order": "Commander des pièces", + "orderinhouse": "" + } + }, + "parts_dispatch": { + "actions": { + "accept": "" + }, + "errors": { + "accepting": "", + "creating": "" + }, + "fields": { + "number": "", + "percent_accepted": "" + }, + "labels": { + "notyetdispatched": "", + "parts_dispatch": "" + } + }, + "parts_dispatch_lines": { + "fields": { + "accepted_at": "" + } + }, + "parts_orders": { + "actions": { + "backordered": "", + "receive": "", + "receivebill": "" + }, + "errors": { + "associatedbills": "", + "backordering": "", + "creating": "Erreur rencontrée lors de la création de la commande de pièces.", + "oec": "", + "saving": "", + "updating": "" + }, + "fields": { + "act_price": "", + "backordered_eta": "", + "backordered_on": "", + "cm_received": "", + "comments": "", + "cost": "", + "db_price": "", + "deliver_by": "", + "job_line_id": "", + "line_desc": "", + "line_remarks": "", + "lineremarks": "Remarques sur la ligne", + "oem_partno": "", + "order_date": "", + "order_number": "", + "orderedby": "", + "part_type": "", + "quantity": "", + "return": "", + "status": "" + }, + "labels": { + "allpartsto": "", + "confirmdelete": "", + "custompercent": "", + "discount": "", + "email": "Envoyé par email", + "inthisorder": "Pièces dans cette commande", + "is_quote": "", + "mark_as_received": "", + "newpartsorder": "", + "notyetordered": "", + "oec": "", + "order_type": "", + "orderhistory": "Historique des commandes", + "parts_order": "", + "parts_orders": "", + "parts_returns": "", + "print": "Afficher le formulaire imprimé", + "receive": "", + "removefrompartsqueue": "", + "returnpartsorder": "", + "sublet_order": "" + }, + "successes": { + "created": "Commande de pièces créée avec succès.", + "line_updated": "", + "received": "", + "return_created": "" + } + }, + "payments": { + "actions": { + "generatepaymentlink": "" + }, + "errors": { + "exporting": "", + "exporting-partner": "", + "inserting": "" + }, + "fields": { + "amount": "", + "created_at": "", + "date": "", + "exportedat": "", + "memo": "", + "payer": "", + "paymentnum": "", + "stripeid": "", + "transactionid": "", + "type": "" + }, + "labels": { + "balance": "", + "ca_bc_etf_table": "", + "customer": "", + "edit": "", + "electronicpayment": "", + "external": "", + "findermodal": "", + "insurance": "", + "markexported": "", + "markforreexport": "", + "new": "", + "signup": "", + "smspaymentreminder": "", + "title": "", + "totalpayments": "" + }, + "successes": { + "exported": "", + "markexported": "", + "markreexported": "", + "payment": "", + "paymentupdate": "", + "stripe": "" + } + }, + "phonebook": { + "actions": { + "new": "" + }, + "errors": { + "adding": "", + "saving": "" + }, + "fields": { + "address1": "", + "address2": "", + "category": "", + "city": "", + "company": "", + "country": "", + "email": "", + "fax": "", + "firstname": "", + "lastname": "", + "phone1": "", + "phone2": "", + "state": "" + }, + "labels": { + "noneselected": "", + "onenamerequired": "", + "vendorcategory": "" + }, + "successes": { + "added": "", + "deleted": "", + "saved": "" + } + }, + "printcenter": { + "appointments": { + "appointment_confirmation": "" + }, + "bills": { + "inhouse_invoice": "" + }, + "courtesycarcontract": { + "courtesy_car_contract": "", + "courtesy_car_impound": "", + "courtesy_car_inventory": "", + "courtesy_car_terms": "" + }, + "errors": { + "nocontexttype": "" + }, + "jobs": { + "3rdpartyfields": { + "addr1": "", + "addr2": "", + "addr3": "", + "attn": "", + "city": "", + "custgst": "", + "ded_amt": "", + "depreciation": "", + "other": "", + "ponumber": "", + "refnumber": "", + "sendtype": "", + "state": "", + "zip": "" + }, + "3rdpartypayer": "", + "ab_proof_of_loss": "", + "appointment_confirmation": "", + "appointment_reminder": "", + "casl_authorization": "", + "committed_timetickets_ro": "", + "coversheet_landscape": "", + "coversheet_portrait": "", + "csi_invitation": "", + "csi_invitation_action": "", + "diagnostic_authorization": "", + "dms_posting_sheet": "", + "envelope_return_address": "", + "estimate": "", + "estimate_detail": "", + "estimate_followup": "", + "express_repair_checklist": "", + "filing_coversheet_landscape": "", + "filing_coversheet_portrait": "", + "final_invoice": "", + "fippa_authorization": "", + "folder_label_multiple": "", + "glass_express_checklist": "", + "guarantee": "", + "individual_job_note": "", + "invoice_customer_payable": "", + "invoice_total_payable": "", + "iou_form": "", + "job_costing_ro": "", + "job_lifecycle_ro": "", + "job_notes": "", + "job_tasks": "", + "key_tag": "", + "labels": { + "count": "", + "labels": "", + "position": "" + }, + "lag_time_ro": "", + "mechanical_authorization": "", + "mpi_animal_checklist": "", + "mpi_eglass_auth": "", + "mpi_final_acct_sheet": "", + "mpi_final_repair_acct_sheet": "", + "paint_grid": "", + "parts_dispatch": "", + "parts_invoice_label_single": "", + "parts_label_multiple": "", + "parts_label_single": "", + "parts_list": "", + "parts_order": "", + "parts_order_confirmation": "", + "parts_order_history": "", + "parts_return_slip": "", + "payment_receipt": "", + "payment_request": "", + "payments_by_job": "", + "purchases_by_ro_detail": "", + "purchases_by_ro_summary": "", + "qc_sheet": "", + "rental_reservation": "", + "ro_totals": "", + "ro_with_description": "", + "sgi_certificate_of_repairs": "", + "sgi_windshield_auth": "", + "stolen_recovery_checklist": "", + "sublet_order": "", + "supplement_request": "", + "thank_you_ro": "", + "thirdpartypayer": "", + "timetickets_ro": "", + "vehicle_check_in": "", + "vehicle_delivery_check": "", + "window_tag": "", + "window_tag_sublet": "", + "work_authorization": "", + "worksheet_by_line_number": "", + "worksheet_sorted_by_operation": "", + "worksheet_sorted_by_operation_no_hours": "", + "worksheet_sorted_by_operation_part_type": "", + "worksheet_sorted_by_operation_type": "", + "worksheet_sorted_by_team": "" + }, + "labels": { + "groups": { + "authorization": "", + "financial": "", + "post": "", + "pre": "", + "ro": "", + "worksheet": "" + }, + "misc": "", + "repairorder": "", + "reportcentermodal": "", + "speedprint": "", + "title": "" + }, + "payments": { + "ca_bc_etf_table": "", + "exported_payroll": "" + }, + "special": { + "attendance_detail_csv": "" + }, + "subjects": { + "jobs": { + "individual_job_note": "", + "parts_dispatch": "", + "parts_order": "", + "parts_return_slip": "", + "sublet_order": "" + } + }, + "vendors": { + "purchases_by_vendor_detailed": "", + "purchases_by_vendor_summary": "" + } + }, + "production": { + "actions": { + "addcolumns": "", + "bodypriority-clear": "", + "bodypriority-set": "", + "detailpriority-clear": "", + "detailpriority-set": "", + "paintpriority-clear": "", + "paintpriority-set": "", + "remove": "", + "removecolumn": "", + "saveconfig": "", + "suspend": "", + "unsuspend": "" + }, + "constants": { + "main_profile": "" + }, + "errors": { + "boardupdate": "", + "name_exists": "", + "name_required": "", + "removing": "", + "settings": "" + }, + "labels": { + "actual_in": "", + "addnewprofile": "", + "alert": "", + "alertoff": "", + "alerton": "", + "alerts": "", + "ats": "", + "bodyhours": "", + "bodypriority": "", + "bodyshop": { + "labels": { + "qbo_departmentid": "", + "qbo_usa": "" + } + }, + "card_size": "", + "cardcolor": "", + "cardsettings": "", + "clm_no": "", + "comment": "", + "compact": "", + "detailpriority": "", + "employeeassignments": "", + "employeesearch": "", + "estimator": "", + "horizontal": "", + "ins_co_nm": "", + "jobdetail": "", + "kiosk_mode": "", + "laborhrs": "", + "legend": "", + "model_info": "", + "note": "", + "off": "", + "on": "", + "orientation": "", + "ownr_nm": "", + "paintpriority": "", + "partsstatus": "", + "production_note": "", + "refinishhours": "", + "scheduled_completion": "", + "selectview": "", + "stickyheader": "", + "sublets": "", + "subtotal": "", + "tall": "", + "tasks": "", + "totalhours": "", + "touchtime": "", + "unassigned": "", + "vertical": "", + "viewname": "", + "wide": "" + }, + "options": { + "horizontal": "", + "large": "", + "medium": "", + "small": "", + "vertical": "" + }, + "settings": { + "board_settings": "", + "filters": { + "md_estimators": "", + "md_ins_cos": "" + }, + "filters_title": "", + "information": "", + "layout": "", + "statistics": { + "jobs_in_production": "", + "tasks_in_production": "", + "tasks_in_view": "", + "tasks_on_board": "", + "total_amount_in_production": "", + "total_amount_in_view": "", + "total_amount_on_board": "", + "total_hours_in_production": "", + "total_hours_in_view": "", + "total_hours_on_board": "", + "total_jobs_in_view": "", + "total_jobs_on_board": "", + "total_lab_in_production": "", + "total_lab_in_view": "", + "total_lab_on_board": "", + "total_lar_in_production": "", + "total_lar_in_view": "", + "total_lar_on_board": "" + }, + "statistics_title": "" + }, + "statistics": { + "currency_symbol": "", + "hours": "", + "jobs": "", + "jobs_in_production": "", + "tasks": "", + "tasks_in_production": "", + "tasks_in_view": "", + "tasks_on_board": "", + "total_amount_in_production": "", + "total_amount_in_view": "", + "total_amount_on_board": "", + "total_hours_in_production": "", + "total_hours_in_view": "", + "total_hours_on_board": "", + "total_jobs_in_view": "", + "total_jobs_on_board": "", + "total_lab_in_production": "", + "total_lab_in_view": "", + "total_lab_on_board": "", + "total_lar_in_production": "", + "total_lar_in_view": "", + "total_lar_on_board": "" + }, + "successes": { + "removed": "" + } + }, + "profile": { + "errors": { + "state": "Erreur lors de la lecture de l'état de la page. Rafraichissez, s'il vous plait." + }, + "labels": { + "activeshop": "" + }, + "successes": { + "updated": "" + } + }, + "reportcenter": { + "actions": { + "generate": "" + }, + "labels": { + "advanced_filters": "", + "advanced_filters_false": "", + "advanced_filters_filter_field": "", + "advanced_filters_filter_operator": "", + "advanced_filters_filter_value": "", + "advanced_filters_filters": "", + "advanced_filters_hide": "", + "advanced_filters_show": "", + "advanced_filters_sorter_direction": "", + "advanced_filters_sorter_field": "", + "advanced_filters_sorters": "", + "advanced_filters_true": "", + "dates": "", + "employee": "", + "filterson": "", + "generateasemail": "", + "groups": { + "customers": "", + "jobs": "", + "payroll": "", + "purchases": "", + "sales": "" + }, + "key": "", + "objects": { + "appointments": "", + "bills": "", + "csi": "", + "exportlogs": "", + "jobs": "", + "parts_orders": "", + "payments": "", + "scoreboard": "", + "tasks": "", + "timetickets": "" + }, + "vendor": "" + }, + "templates": { + "adp_payroll_flat": "", + "adp_payroll_straight": "", + "anticipated_revenue": "", + "ar_aging": "", + "attendance_detail": "", + "attendance_employee": "", + "attendance_summary": "", + "committed_timetickets": "", + "committed_timetickets_employee": "", + "committed_timetickets_summary": "", + "credits_not_received_date": "", + "credits_not_received_date_vendorid": "", + "csi": "", + "customer_list": "", + "cycle_time_analysis": "", + "estimates_written_converted": "", + "estimator_detail": "", + "estimator_summary": "", + "export_payables": "", + "export_payments": "", + "export_receivables": "", + "exported_gsr_by_ro": "", + "exported_gsr_by_ro_labor": "", + "gsr_by_atp": "", + "gsr_by_ats": "", + "gsr_by_category": "", + "gsr_by_csr": "", + "gsr_by_delivery_date": "", + "gsr_by_estimator": "", + "gsr_by_exported_date": "", + "gsr_by_ins_co": "", + "gsr_by_make": "", + "gsr_by_referral": "", + "gsr_by_ro": "", + "gsr_labor_only": "", + "hours_sold_detail_closed": "", + "hours_sold_detail_closed_csr": "", + "hours_sold_detail_closed_estimator": "", + "hours_sold_detail_closed_ins_co": "", + "hours_sold_detail_closed_status": "", + "hours_sold_detail_open": "", + "hours_sold_detail_open_csr": "", + "hours_sold_detail_open_estimator": "", + "hours_sold_detail_open_ins_co": "", + "hours_sold_detail_open_status": "", + "hours_sold_summary_closed": "", + "hours_sold_summary_closed_csr": "", + "hours_sold_summary_closed_estimator": "", + "hours_sold_summary_closed_ins_co": "", + "hours_sold_summary_closed_status": "", + "hours_sold_summary_open": "", + "hours_sold_summary_open_csr": "", + "hours_sold_summary_open_estimator": "", + "hours_sold_summary_open_ins_co": "", + "hours_sold_summary_open_status": "", + "job_costing_ro_csr": "", + "job_costing_ro_date_detail": "", + "job_costing_ro_date_summary": "", + "job_costing_ro_estimator": "", + "job_costing_ro_ins_co": "", + "job_lifecycle_date_detail": "", + "job_lifecycle_date_summary": "", + "jobs_completed_not_invoiced": "", + "jobs_invoiced_not_exported": "", + "jobs_reconcile": "", + "jobs_scheduled_completion": "", + "lag_time": "", + "load_level": "", + "lost_sales": "", + "open_orders": "", + "open_orders_csr": "", + "open_orders_estimator": "", + "open_orders_excel": "", + "open_orders_ins_co": "", + "open_orders_referral": "", + "open_orders_specific_csr": "", + "open_orders_status": "", + "parts_backorder": "", + "parts_not_recieved": "", + "parts_not_recieved_vendor": "", + "parts_received_not_scheduled": "", + "payments_by_date": "", + "payments_by_date_payment": "", + "payments_by_date_type": "", + "production_by_category": "", + "production_by_category_one": "", + "production_by_csr": "", + "production_by_last_name": "", + "production_by_repair_status": "", + "production_by_repair_status_one": "", + "production_by_ro": "", + "production_by_target_date": "", + "production_by_technician": "", + "production_by_technician_one": "", + "production_not_production_status": "", + "production_over_time": "", + "psr_by_make": "", + "purchase_return_ratio_excel": "", + "purchase_return_ratio_grouped_by_vendor_detail": "", + "purchase_return_ratio_grouped_by_vendor_summary": "", + "purchases_by_cost_center_detail": "", + "purchases_by_cost_center_summary": "", + "purchases_by_date_excel": "", + "purchases_by_date_range_detail": "", + "purchases_by_date_range_summary": "", + "purchases_by_ro_detail_date": "", + "purchases_by_ro_summary_date": "", + "purchases_by_vendor_detailed_date_range": "", + "purchases_by_vendor_summary_date_range": "", + "purchases_grouped_by_vendor_detailed": "", + "purchases_grouped_by_vendor_summary": "", + "returns_grouped_by_vendor_detailed": "", + "returns_grouped_by_vendor_summary": "", + "schedule": "", + "scheduled_parts_list": "", + "scoreboard_detail": "", + "scoreboard_summary": "", + "supplement_ratio_ins_co": "", + "tasks_date": "", + "tasks_date_employee": "", + "thank_you_date": "", + "timetickets": "", + "timetickets_employee": "", + "timetickets_summary": "", + "total_loss_jobs": "", + "unclaimed_hrs": "", + "void_ros": "", + "work_in_progress_committed_labour": "", + "work_in_progress_jobs": "", + "work_in_progress_labour": "", + "work_in_progress_payables": "" + } + }, + "schedule": { + "labels": { + "atssummary": "", + "employeevacation": "", + "estimators": "", + "ins_co_nm_filter": "", + "intake": "", + "manual": "", + "manualevent": "" + } + }, + "scoreboard": { + "actions": { + "edit": "" + }, + "errors": { + "adding": "", + "removing": "", + "updating": "" + }, + "fields": { + "bodyhrs": "", + "date": "", + "painthrs": "" + }, + "labels": { + "allemployeetimetickets": "", + "asoftodaytarget": "", + "body": "", + "bodyabbrev": "", + "bodycharttitle": "", + "calendarperiod": "", + "combinedcharttitle": "", + "dailyactual": "", + "dailytarget": "", + "efficiencyoverperiod": "", + "entries": "", + "jobs": "", + "jobscompletednotinvoiced": "", + "lastmonth": "", + "lastweek": "", + "monthlytarget": "", + "priorweek": "", + "productivestatistics": "", + "productivetimeticketsoverdate": "", + "refinish": "", + "refinishabbrev": "", + "refinishcharttitle": "", + "targets": "", + "thismonth": "", + "thisweek": "", + "timetickets": "", + "timeticketsemployee": "", + "todateactual": "", + "total": "", + "totalhrs": "", + "totaloverperiod": "", + "weeklyactual": "", + "weeklytarget": "", + "workingdays": "" + }, + "successes": { + "added": "", + "removed": "", + "updated": "" + } + }, + "tasks": { + "actions": { + "edit": "", + "new": "", + "view": "" + }, + "buttons": { + "allTasks": "", + "complete": "", + "create": "", + "delete": "", + "edit": "", + "myTasks": "", + "refresh": "" + }, + "date_presets": { + "completion": "", + "day": "", + "days": "", + "delivery": "", + "next_week": "", + "one_month": "", + "three_months": "", + "three_weeks": "", + "today": "", + "tomorrow": "", + "two_weeks": "" + }, + "failures": { + "completed": "", + "created": "", + "deleted": "", + "updated": "" + }, + "fields": { + "actions": "", + "assigned_to": "", + "bill": "", + "billid": "", + "completed": "", + "created_at": "", + "created_by": "", + "description": "", + "due_date": "", + "job": { + "ro_number": "" + }, + "jobid": "", + "jobline": "", + "joblineid": "", + "parts_order": "", + "partsorderid": "", + "priorities": { + "high": "", + "low": "", + "medium": "" + }, + "priority": "", + "related_items": "", + "remind_at": "", + "title": "" + }, + "placeholders": { + "assigned_to": "", + "billid": "", + "description": "", + "jobid": "", + "joblineid": "", + "partsorderid": "" + }, + "successes": { + "completed": "", + "created": "", + "deleted": "", + "updated": "" + }, + "titles": { + "all_tasks": "", + "completed": "", + "deleted": "", + "job_tasks": "", + "mine": "", + "my_tasks": "" + }, + "validation": { + "due_at_error_message": "", + "remind_at_error_message": "" + } + }, + "tech": { + "fields": { + "employeeid": "", + "pin": "" + }, + "labels": { + "loggedin": "", + "notloggedin": "" + } + }, + "templates": { + "errors": { + "updating": "" + }, + "successes": { + "updated": "" + } + }, + "timetickets": { + "actions": { + "claimtasks": "", + "clockin": "", + "clockout": "", + "commit": "", + "commitone": "", + "enter": "", + "payall": "", + "printemployee": "", + "uncommit": "" + }, + "errors": { + "clockingin": "", + "clockingout": "", + "creating": "", + "deleting": "", + "noemployeeforuser": "", + "noemployeeforuser_sub": "", + "payall": "", + "shiftalreadyclockedon": "" + }, + "fields": { + "actualhrs": "", + "ciecacode": "", + "clockhours": "", + "clockoff": "", + "clockon": "", + "committed": "", + "committed_at": "", + "cost_center": "", + "created_by": "", + "date": "", + "efficiency": "", + "employee": "", + "employee_team": "", + "flat_rate": "", + "memo": "", + "productivehrs": "", + "ro_number": "", + "task_name": "" + }, + "labels": { + "alreadyclockedon": "", + "ambreak": "", + "amshift": "", + "claimtaskpreview": "", + "clockhours": "", + "clockintojob": "", + "deleteconfirm": "", + "edit": "", + "efficiency": "", + "flat_rate": "", + "jobhours": "", + "lunch": "", + "new": "", + "payrollclaimedtasks": "", + "pmbreak": "", + "pmshift": "", + "shift": "", + "shiftalreadyclockedon": "", + "straight_time": "", + "task": "", + "timetickets": "", + "unassigned": "", + "zeroactualnegativeprod": "" + }, + "successes": { + "clockedin": "", + "clockedout": "", + "committed": "", + "created": "", + "deleted": "", + "payall": "" + }, + "validation": { + "clockoffmustbeafterclockon": "", + "clockoffwithoutclockon": "", + "hoursenteredmorethanavailable": "", + "unassignedlines": "" + } + }, + "titles": { + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "all_tasks": "", + "app": "", + "bc": { + "accounting-payables": "", + "accounting-payments": "", + "accounting-receivables": "", + "all_tasks": "", + "availablejobs": "", + "bills-list": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-detail": "", + "courtesycars-new": "", + "dashboard": "", + "dms": "", + "export-logs": "", + "inventory": "", + "jobs": "", + "jobs-active": "", + "jobs-admin": "", + "jobs-all": "", + "jobs-checklist": "", + "jobs-close": "", + "jobs-deliver": "", + "jobs-detail": "", + "jobs-intake": "", + "jobs-new": "", + "jobs-ready": "", + "my_tasks": "", + "owner-detail": "", + "owners": "", + "parts-queue": "", + "payments-all": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "profile": "", + "schedule": "", + "scoreboard": "", + "shop": "", + "shop-csi": "", + "shop-templates": "", + "shop-vendors": "", + "tasks": "", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicle-details": "", + "vehicles": "" + }, + "bills-list": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-create": "", + "courtesycars-detail": "", + "dashboard": "", + "dms": "", + "export-logs": "", + "imexonline": "", + "inventory": "", + "jobs": "Tous les emplois | {{app}}", + "jobs-admin": "", + "jobs-all": "", + "jobs-checklist": "", + "jobs-close": "", + "jobs-create": "", + "jobs-deliver": "", + "jobs-intake": "", + "jobsavailable": "Emplois disponibles | {{app}}", + "jobsdetail": "Travail {{ro_number}} | {{app}}", + "jobsdocuments": "Documents de travail {{ro_number}} | {{app}}", + "manageroot": "Accueil | {{app}}", + "my_tasks": "", + "owners": "Tous les propriétaires | {{app}}", + "owners-detail": "", + "parts-queue": "", + "payments-all": "", + "phonebook": "", + "productionboard": "", + "productionlist": "", + "profile": "Mon profil | {{app}}", + "readyjobs": "", + "resetpassword": "", + "resetpasswordvalidate": "", + "romeonline": "", + "schedule": "Horaire | {{app}}", + "scoreboard": "", + "shop": "Mon magasin | {{app}}", + "shop-csi": "", + "shop-templates": "", + "shop_vendors": "Vendeurs | {{app}}", + "tasks": "", + "techconsole": "{{app}}", + "techjobclock": "{{app}}", + "techjoblookup": "{{app}}", + "techshiftclock": "{{app}}", + "temporarydocs": "", + "timetickets": "", + "ttapprovals": "", + "vehicledetail": "Détails du véhicule {{vehicle} | {{app}}", + "vehicles": "Tous les véhicules | {{app}}" + }, + "trello": { + "labels": { + "add_card": "", + "add_lane": "", + "cancel": "", + "delete_lane": "", + "description": "", + "label": "", + "lane_actions": "", + "title": "" + } + }, + "tt_approvals": { + "actions": { + "approveselected": "" + }, + "labels": { + "approval_queue_in_use": "", + "calculate": "" + } + }, + "upsell": { + "cta": { + "learnmore": "" + }, + "messages": { + "accounting": { + "payables": { + "subtitle": "", + "title": "" + }, + "payments": { + "subtitle": "", + "title": "" + }, + "receivables": { + "subtitle": "", + "title": "" + } + }, + "audit": { + "general": { + "subtitle": "", + "title": "" + } + }, + "bills": { + "autoreconcile": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + } + }, + "checklist": { + "general": { + "subtitle": "", + "title": "" + } + }, + "courtesycars": { + "general": { + "subtitle": "", + "title": "" + } + }, + "csi": { + "general": { + "subtitle": "", + "title": "" + } + }, + "dashboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "lifecycle": { + "general": { + "subtitle": "", + "title": "" + } + }, + "media": { + "general": { + "subtitle": "", + "title": "" + }, + "mobile": { + "subtitle": "", + "title": "" + } + }, + "payments": { + "general": { + "subtitle": "", + "title": "" + } + }, + "scoreboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "smartscheduling": { + "datepicker": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + }, + "hrsdelta": { + "subtitle": "", + "title": "" + } + }, + "techconsole": { + "general": { + "subtitle": "", + "title": "" + } + }, + "timetickets": { + "allocations": { + "subtitle": "", + "title": "" + }, + "general": { + "subtitle": "", + "title": "" + } + }, + "visualboard": { + "general": { + "subtitle": "", + "title": "" + } + } + } + }, + "user": { + "actions": { + "changepassword": "", + "signout": "Déconnexion", + "updateprofile": "Mettre à jour le profil" + }, + "errors": { + "updating": "" + }, + "fields": { + "authlevel": "", + "displayname": "Afficher un nom", + "email": "", + "photourl": "URL de l'avatar" + }, + "labels": { + "actions": "", + "changepassword": "", + "profileinfo": "" + }, + "successess": { + "passwordchanged": "" + } + }, + "users": { + "errors": { + "signinerror": { + "auth/user-disabled": "", + "auth/user-not-found": "", + "auth/wrong-password": "" + } + } + }, + "vehicles": { + "errors": { + "deleting": "", + "noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.", + "selectexistingornew": "", + "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.", + "validationtitle": "Erreur de validation" + }, + "fields": { + "description": "Description du véhicule", + "notes": "", + "plate_no": "Plaque d'immatriculation", + "plate_st": "Juridiction de la plaque", + "trim_color": "Couleur de garniture", + "v_bstyle": "Style corporel", + "v_color": "Couleur", + "v_cond": "Etat", + "v_engine": "moteur", + "v_make_desc": "Faire", + "v_makecode": "Faire du code", + "v_mldgcode": "Code de moulage", + "v_model_desc": "Modèle", + "v_model_yr": "année", + "v_options": "Les options", + "v_paint_codes": "Codes de peinture", + "v_prod_dt": "Date de production", + "v_stage": "Étape", + "v_tone": "ton", + "v_trimcode": "Code de coupe", + "v_type": "Type", + "v_vin": "V.I.N." + }, + "forms": { + "detail": "", + "misc": "", + "registration": "" + }, + "labels": { + "deleteconfirm": "", + "fromvehicle": "", + "novehinfo": "", + "relatedjobs": "", + "updatevehicle": "" + }, + "successes": { + "delete": "", + "save": "Le véhicule a été enregistré avec succès." + } + }, + "vendors": { + "actions": { + "addtophonebook": "", + "new": "Nouveau vendeur", + "newpreferredmake": "" + }, + "errors": { + "deleting": "Erreur rencontrée lors de la suppression du fournisseur.", + "saving": "Erreur rencontrée lors de l'enregistrement du fournisseur." + }, + "fields": { + "active": "", + "am": "", + "city": "Ville", + "cost_center": "Centre de coûts", + "country": "Pays", + "discount": "Remise %", + "display_name": "Afficher un nom", + "dmsid": "", + "due_date": "Date limite de paiement", + "email": "Email du contact", + "favorite": "Préféré?", + "lkq": "", + "make": "", + "name": "Nom du vendeur", + "oem": "", + "phone": "", + "prompt_discount": "Remise rapide%", + "state": "Etat / Province", + "street1": "rue", + "street2": "Adresse 2 ", + "taxid": "Identifiant de taxe", + "terms": "Modalités de paiement", + "zip": "Zip / code postal" + }, + "labels": { + "noneselected": "Aucun fournisseur n'est sélectionné.", + "preferredmakes": "", + "search": "Tapez le nom d'un vendeur" + }, + "successes": { + "deleted": "Le fournisseur a bien été supprimé.", + "saved": "Le fournisseur a bien enregistré." + }, + "validation": { + "unique_vendor_name": "" + } + }, "notifications": { "labels": { "notification-center": "", diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 0106cb6da..498129d7a 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -371,6 +371,7 @@ exports.postback = async (req, res) => { iprequest: values, decodedComment }; + const ipMapping = req.body?.bodyshop?.intellipay_config?.payment_map; logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, logResponseMeta); @@ -417,7 +418,7 @@ exports.postback = async (req, res) => { amount: p.amount, transactionid: values.authcode, payer: "Customer", - type: values.cardtype, + type: ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype, jobid: p.jobid, date: moment(Date.now()), payment_responses: { @@ -481,7 +482,7 @@ exports.postback = async (req, res) => { amount: values.total, transactionid: values.authcode, payer: "Customer", - type: values.cardtype, + type: ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype, jobid: values.invoice, date: moment(Date.now()) } From 7e2a214a50759273bc7eb0604d63b39650db85b2 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 20 Mar 2025 12:07:16 -0700 Subject: [PATCH 14/45] IO-3176 IntelliPay Payment Mapping Correction Signed-off-by: Allan Carr --- server/intellipay/intellipay.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 498129d7a..49d91a88c 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -418,7 +418,7 @@ exports.postback = async (req, res) => { amount: p.amount, transactionid: values.authcode, payer: "Customer", - type: ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype, + type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype, jobid: p.jobid, date: moment(Date.now()), payment_responses: { @@ -482,7 +482,7 @@ exports.postback = async (req, res) => { amount: values.total, transactionid: values.authcode, payer: "Customer", - type: ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype, + type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype, jobid: values.invoice, date: moment(Date.now()) } From b9eb62220758069540fc8703b2aeed0aad27cadb Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 21 Mar 2025 13:16:57 -0400 Subject: [PATCH 15/45] IO-3181-Testing-Framework-Selection: Package update checkpoint --- client/package-lock.json | 383 ++++++++++++++++++++++++++++----------- client/package.json | 28 +-- package-lock.json | 235 +++++++++++------------- package.json | 26 +-- 4 files changed, 409 insertions(+), 263 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index fbd87949f..c49b5dbd4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,22 +10,22 @@ "hasInstallScript": true, "dependencies": { "@ant-design/pro-layout": "^7.22.3", - "@apollo/client": "^3.13.1", + "@apollo/client": "^3.13.5", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@jsreport/browser-client": "^3.1.0", - "@reduxjs/toolkit": "^2.6.0", - "@sentry/cli": "^2.42.2", - "@sentry/react": "^9.3.0", + "@reduxjs/toolkit": "^2.6.1", + "@sentry/cli": "^2.42.4", + "@sentry/react": "^9.7.0", "@sentry/vite-plugin": "^3.2.2", "@splitsoftware/splitio-react": "^1.13.0", "@tanem/react-nprogress": "^5.0.53", "@vitejs/plugin-react": "^4.3.4", - "antd": "^5.24.2", + "antd": "^5.24.4", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.1.0", "autosize": "^6.0.1", - "axios": "^1.8.1", + "axios": "^1.8.4", "classnames": "^2.5.1", "css-box-model": "^1.2.1", "dayjs": "^1.11.13", @@ -39,9 +39,9 @@ "i18next": "^23.15.1", "i18next-browser-languagedetector": "^8.0.4", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.12.4", + "libphonenumber-js": "^1.12.6", "logrocket": "^8.1.2", - "markerjs2": "^2.32.3", + "markerjs2": "^2.32.4", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", "object-hash": "^3.0.0", @@ -75,12 +75,12 @@ "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.85.1", + "sass": "^1.86.0", "socket.io-client": "^4.8.1", - "styled-components": "^6.1.15", + "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.8", + "userpilot": "^1.3.9", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, @@ -88,10 +88,10 @@ "@ant-design/icons": "^5.6.1", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", - "@dotenvx/dotenvx": "^1.38.3", + "@dotenvx/dotenvx": "^1.39.0", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", - "@eslint/js": "^9.21.0", + "@eslint/js": "^9.22.0", "@sentry/webpack-plugin": "^3.2.2", "@testing-library/cypress": "^10.0.2", "browserslist": "^4.24.4", @@ -109,7 +109,7 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.0", + "vite": "^6.2.2", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", @@ -323,9 +323,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.1.tgz", - "integrity": "sha512-HaAt62h3jNUXpJ1v5HNgUiCzPP1c5zc2Q/FeTb2cTk/v09YlhoqKKHQFJI7St50VCJ5q8JVIc03I5bRcBrQxsg==", + "version": "3.13.5", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.5.tgz", + "integrity": "sha512-ceHa1lApLAiGmUur4V+G/CrjwVwHYujfB7U5HM++poCgHpfGn6eet8YGM93fgeWjYX85SaqwdZbQk18IVwhRHg==", "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", @@ -2426,9 +2426,9 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.38.3", - "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.38.3.tgz", - "integrity": "sha512-6tquYDfAiJbgQbYwWfL0jJHiUumY5EiFXVswk9sTwn5lWICMwOPmMOrM9TEVLzesfNMYwDyUiMp5WAA6yXs+SQ==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.0.tgz", + "integrity": "sha512-qGfDpL/3S17MQYXpR3HkBS5xNQ7wiFlqLdpr+iIQzv17aMRcSlgL4EjMIsYFZ540Dq17J+y5FVElA1AkVoXiUA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3159,9 +3159,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "dev": true, "license": "MIT", "engines": { @@ -4669,9 +4669,9 @@ "license": "MIT" }, "node_modules/@reduxjs/toolkit": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.0.tgz", - "integrity": "sha512-mWJCYpewLRyTuuzRSEC/IwIBBkYg2dKtQas8mty5MaV2iXzcmicS3gW554FDeOvLnY3x13NIk8MB1e8wHO7rqQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz", + "integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==", "license": "MIT", "dependencies": { "immer": "^10.0.3", @@ -5261,50 +5261,50 @@ "license": "MIT" }, "node_modules/@sentry-internal/browser-utils": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.3.0.tgz", - "integrity": "sha512-G3z4HCUyb5nJe03EPUhWjnaHqMDt4mOTFJDNha3DGoB51lMYojpQI1Qo1u6bY4qkWVSO1c+HqOU0RVsXoAchtQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.7.0.tgz", + "integrity": "sha512-1wVd8mCvbeGs3wSDZFYQ9RE8I8Ii8iQ2wnHKbONk645RIT6FwSCPHlnFKWYSFVxo85Wm6SFbKcv1zvTNXUVhfQ==", "license": "MIT", "dependencies": { - "@sentry/core": "9.3.0" + "@sentry/core": "9.7.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.3.0.tgz", - "integrity": "sha512-LQmIbQaATlN5QEwCD2Xt+7VKfwfR5W3dbn0jdF1x4hQFE/srdnOj60xMz/mj3tP5BxV552xJniGsyZ8lXHDb2A==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.7.0.tgz", + "integrity": "sha512-Ld51wOfXYO90++ZGBuVF/5PAMBnVWFfvvleXRgA9VaL2hq296+tLXYVccHTgH+dZmwjJgsybDAxHdj+k1FFnmw==", "license": "MIT", "dependencies": { - "@sentry/core": "9.3.0" + "@sentry/core": "9.7.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.3.0.tgz", - "integrity": "sha512-ZkH+Gahn89JygpuiFn26ZgAqJXHtnr+HjfQ2ONOFoWQHNH6X5wk75UTma55aYk1d8VcBPFoU6WjFhZoQ55SV1g==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.7.0.tgz", + "integrity": "sha512-JOwwqe3JtcbkvC/hM7qr1x40lk3K5zm8r2HHVKVLzrf6cAuLF9x17R7h+0cDOHcilacbtIQQ9Fjjb63a1/iDLQ==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.3.0", - "@sentry/core": "9.3.0" + "@sentry-internal/browser-utils": "9.7.0", + "@sentry/core": "9.7.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.3.0.tgz", - "integrity": "sha512-MhDMJeRGa55a0D541+OzTFMWwbabthhDGbAL90/NpappfyeBbAiktmCNl0BFTZuRbCGrC2m1LLCqHegCVKW4fQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.7.0.tgz", + "integrity": "sha512-E/XESnVLV+CUyrucrxK2kHpEKTDrz7LTBwjnt3FDHA8MfwMRX+np0sYjvcIRWAG4xxBOYBGlWD2+n0Y2pqYa2Q==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "9.3.0", - "@sentry/core": "9.3.0" + "@sentry-internal/replay": "9.7.0", + "@sentry/core": "9.7.0" }, "engines": { "node": ">=18" @@ -5320,16 +5320,16 @@ } }, "node_modules/@sentry/browser": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.3.0.tgz", - "integrity": "sha512-yPwWWQo/hpN63p0NGmk/Dd1Fx5CQRWNMfuV7dtfPBtg3vRjDecA9OLyK29AqK5h3Fl8FuJOyOqB87CvtXUqh5g==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.7.0.tgz", + "integrity": "sha512-G2AZuWAfatv30rFWYcbAZNnty9826ld8k+EucYLtDGN0uBdHXX9XT/x7/C8dprtV16jGWzrfvMza8C7Z4uj8BA==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "9.3.0", - "@sentry-internal/feedback": "9.3.0", - "@sentry-internal/replay": "9.3.0", - "@sentry-internal/replay-canvas": "9.3.0", - "@sentry/core": "9.3.0" + "@sentry-internal/browser-utils": "9.7.0", + "@sentry-internal/feedback": "9.7.0", + "@sentry-internal/replay": "9.7.0", + "@sentry-internal/replay-canvas": "9.7.0", + "@sentry/core": "9.7.0" }, "engines": { "node": ">=18" @@ -5354,7 +5354,7 @@ "node": ">= 14" } }, - "node_modules/@sentry/cli": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.2.tgz", "integrity": "sha512-spb7S/RUumCGyiSTg8DlrCX4bivCNmU/A1hcfkwuciTFGu8l5CDc2I6jJWWZw8/0enDGxuj5XujgXvU5tr4bxg==", @@ -5383,7 +5383,7 @@ "@sentry/cli-win32-x64": "2.42.2" } }, - "node_modules/@sentry/cli-darwin": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-darwin": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz", "integrity": "sha512-GtJSuxER7Vrp1IpxdUyRZzcckzMnb4N5KTW7sbTwUiwqARRo+wxS+gczYrS8tdgtmXs5XYhzhs+t4d52ITHMIg==", @@ -5396,7 +5396,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-linux-arm": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz", "integrity": "sha512-7udCw+YL9lwq+9eL3WLspvnuG+k5Icg92YE7zsteTzWLwgPVzaxeZD2f8hwhsu+wmL+jNqbpCRmktPteh3i2mg==", @@ -5413,7 +5413,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-linux-arm64": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm64": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz", "integrity": "sha512-BOxzI7sgEU5Dhq3o4SblFXdE9zScpz6EXc5Zwr1UDZvzgXZGosUtKVc7d1LmkrHP8Q2o18HcDWtF3WvJRb5Zpw==", @@ -5430,7 +5430,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-linux-i686": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-i686": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz", "integrity": "sha512-Sw/dQp5ZPvKnq3/y7wIJyxTUJYPGoTX/YeMbDs8BzDlu9to2LWV3K3r7hE7W1Lpbaw4tSquUHiQjP5QHCOS7aQ==", @@ -5448,7 +5448,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-linux-x64": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-x64": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz", "integrity": "sha512-mU4zUspAal6TIwlNLBV5oq6yYqiENnCWSxtSQVzWs0Jyq97wtqGNG9U+QrnwjJZ+ta/hvye9fvL2X25D/RxHQw==", @@ -5465,7 +5465,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-win32-i686": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-i686": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz", "integrity": "sha512-iHvFHPGqgJMNqXJoQpqttfsv2GI3cGodeTq4aoVLU/BT3+hXzbV0x1VpvvEhncJkDgDicJpFLM8sEPHb3b8abw==", @@ -5482,7 +5482,7 @@ "node": ">=10" } }, - "node_modules/@sentry/cli-win32-x64": { + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-x64": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz", "integrity": "sha512-vPPGHjYoaGmfrU7xhfFxG7qlTBacroz5NdT+0FmDn6692D8IvpNXl1K+eV3Kag44ipJBBeR8g1HRJyx/F/9ACw==", @@ -5498,6 +5498,171 @@ "node": ">=10" } }, + "node_modules/@sentry/bundler-plugin-core/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.4.tgz", + "integrity": "sha512-BoSZDAWJiz/40tu6LuMDkSgwk4xTsq6zwqYoUqLU3vKBR/VsaaQGvu6EWxZXORthfZU2/5Agz0+t220cge6VQw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.42.4", + "@sentry/cli-linux-arm": "2.42.4", + "@sentry/cli-linux-arm64": "2.42.4", + "@sentry/cli-linux-i686": "2.42.4", + "@sentry/cli-linux-x64": "2.42.4", + "@sentry/cli-win32-i686": "2.42.4", + "@sentry/cli-win32-x64": "2.42.4" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.4.tgz", + "integrity": "sha512-PZV4Y97VDWBR4rIt0HkJfXaBXlebIN2s/FDzC3iHINZE5OG62CDFsnC4/lbGlf2/UZLDaGGIK7mYwSHhTvN+HQ==", + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.4.tgz", + "integrity": "sha512-lBn0oeeg62h68/4Eo6zbPq99Idz5t0VRV48rEU/WKeM4MtQCvG/iGGQ3lBFW2yNiUBzXZIK9poXLEcgbwmcRVw==", + "cpu": [ + "arm" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.4.tgz", + "integrity": "sha512-Ex8vRnryyzC/9e43daEmEqPS+9uirY/l6Hw2lAvhBblFaL7PTWNx52H+8GnYGd9Zy2H3rWNyBDYfHwnErg38zA==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.4.tgz", + "integrity": "sha512-IBJg0aHjsLCL4LvcFa3cXIjA+4t5kPqBT9y+PoDu4goIFxYD8zl7mbUdGJutvJafTk8Akf4ss4JJXQBjg019zA==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.4.tgz", + "integrity": "sha512-gXI5OEiOSNiAEz7VCE6AZcAgHJ47mlgal3+NmbE8XcHmFOnyDws9FNie6PJAy8KZjXi3nqoBP9JVAbnmOix3uA==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.4.tgz", + "integrity": "sha512-vZuR3UPHKqOMniyrijrrsNwn9usaRysXq78F6WV0cL0ZyPLAmY+KBnTDSFk1Oig2pURnzaTm+RtcZu2fc8mlzg==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.42.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz", + "integrity": "sha512-OIBj3uaQ6nAERSm5Dcf8UIhyElEEwMNsZEEppQpN4IKl0mrwb/57AznM23Dvpu6GR8WGbVQUSolt879YZR5E9g==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@sentry/cli/node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5520,22 +5685,22 @@ } }, "node_modules/@sentry/core": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.3.0.tgz", - "integrity": "sha512-SxQ4z7wTkfguvYb2ctNEMU9kVAbhl9ymfjhLnrvtygTwL5soLqAKdco/lX/4P9K9Osgb2Dl6urQWRl+AhzKVbQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.7.0.tgz", + "integrity": "sha512-EprjtU7F6eltB4Nx8fzWFXsfAC/6yNGuKo2bHKeIAmNufjD0X4ifz+iB3d0pKuwsn9jQbLrQTIGwKdTO3dstFw==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.3.0.tgz", - "integrity": "sha512-/ruDHBHLDXmZoEHNCSjdekZr9+0pbOC5+BY1oABGoDXRISGyoenOBtAsX8TsaC9oJYhr16yKDFlYxzzQRhxDyg==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.7.0.tgz", + "integrity": "sha512-qD3Jb1/fvofdw5+aC/ARJNu1lVO6Ndoma15V+jjKH+rBaYAXftkboUvhTzvpAM8o1tw3jbioJDQlmIHehUzjzg==", "license": "MIT", "dependencies": { - "@sentry/browser": "9.3.0", - "@sentry/core": "9.3.0", + "@sentry/browser": "9.7.0", + "@sentry/core": "9.7.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -6559,9 +6724,9 @@ } }, "node_modules/antd": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.2.tgz", - "integrity": "sha512-7Z9HsE3ZIK3sE/WuUqii3w7Gl1IJuRL21sDUTtkN95JS5KhRYP8ISv7m/HxsJ3Mn/yxgojBCgLPJ212+Dn+aPw==", + "version": "5.24.4", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.4.tgz", + "integrity": "sha512-s89666DcoWeekJFaIqbtz2vRlIvgPR28GuDYYGUpW1mVP08bV7HZAPBH5lFJKYNGKrN3dHbZGgRK5aNRD2iPHg==", "license": "MIT", "dependencies": { "@ant-design/colors": "^7.2.0", @@ -6579,7 +6744,7 @@ "classnames": "^2.5.1", "copy-to-clipboard": "^3.3.3", "dayjs": "^1.11.11", - "rc-cascader": "~3.33.0", + "rc-cascader": "~3.33.1", "rc-checkbox": "~3.5.0", "rc-collapse": "~3.9.0", "rc-dialog": "~9.6.0", @@ -6587,14 +6752,14 @@ "rc-dropdown": "~4.2.1", "rc-field-form": "~2.7.0", "rc-image": "~7.11.0", - "rc-input": "~1.7.2", + "rc-input": "~1.7.3", "rc-input-number": "~9.4.0", "rc-mentions": "~2.19.1", "rc-menu": "~9.16.1", "rc-motion": "^2.9.5", "rc-notification": "~5.6.3", "rc-pagination": "~5.1.0", - "rc-picker": "~4.11.2", + "rc-picker": "~4.11.3", "rc-progress": "~4.0.0", "rc-rate": "~2.13.1", "rc-resize-observer": "^1.4.3", @@ -6603,11 +6768,11 @@ "rc-slider": "~11.1.8", "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", - "rc-table": "~7.50.3", + "rc-table": "~7.50.4", "rc-tabs": "~15.5.1", "rc-textarea": "~1.9.0", "rc-tooltip": "~6.4.0", - "rc-tree": "~5.13.0", + "rc-tree": "~5.13.1", "rc-tree-select": "~5.27.0", "rc-upload": "~4.8.1", "rc-util": "^5.44.4", @@ -7037,9 +7202,9 @@ } }, "node_modules/axios": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", - "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -12486,9 +12651,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.4.tgz", - "integrity": "sha512-vLmhg7Gan7idyAKfc6pvCtNzvar4/eIzrVVk3hjNFH5+fGqyjD0gQRovdTrDl20wsmZhBtmZpcsR0tOfquwb8g==", + "version": "1.12.6", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz", + "integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw==", "license": "MIT" }, "node_modules/lines-and-columns": { @@ -12844,9 +13009,9 @@ } }, "node_modules/markerjs2": { - "version": "2.32.3", - "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.3.tgz", - "integrity": "sha512-D7oD4BT5NOsQbugdcO2TFmcw9ZMHp96Ih09A5f0UndxiQNWuz+j5zymtkTHs0WU+oOR8K6dyTufv4KtfJ6diBg==", + "version": "2.32.4", + "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.4.tgz", + "integrity": "sha512-pk8gZMqSw0iDwSuH4Rt3jsYwA2J0EYUngIFIUvkHFVTiZPK+djuwrv4wfdK81I81FqnQ5iYp9buv/Sjg3Td0Tw==", "license": "SEE LICENSE IN LICENSE" }, "node_modules/material-colors": { @@ -14775,9 +14940,9 @@ } }, "node_modules/rc-cascader": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.33.0.tgz", - "integrity": "sha512-JvZrMbKBXIbEDmpIORxqvedY/bck6hGbs3hxdWT8eS9wSQ1P7//lGxbyKjOSyQiVBbgzNWriSe6HoMcZO/+0rQ==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.33.1.tgz", + "integrity": "sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.7", @@ -14909,9 +15074,9 @@ } }, "node_modules/rc-input": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.7.2.tgz", - "integrity": "sha512-g3nYONnl4edWj2FfVoxsU3Ec4XTE+Hb39Kfh2MFxMZjp/0gGyPUgy/v7ZhS27ZxUFNkuIDYXm9PJsLyJbtg86A==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.7.3.tgz", + "integrity": "sha512-A5w4egJq8+4JzlQ55FfQjDnPvOaAbzwC3VLOAdOytyek3TboSOP9qxN+Gifup+shVXfvecBLBbWBpWxmk02SWQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.1", @@ -15220,9 +15385,9 @@ } }, "node_modules/rc-table": { - "version": "7.50.3", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.3.tgz", - "integrity": "sha512-Z4/zNCzjv7f/XzPRecb+vJU0DJKdsYt4YRkDzNl4G05m7JmxrKGYC2KqN1Ew6jw2zJq7cxVv3z39qyZOHMuf7A==", + "version": "7.50.4", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.4.tgz", + "integrity": "sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.1", @@ -15296,9 +15461,9 @@ } }, "node_modules/rc-tree": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.0.tgz", - "integrity": "sha512-2+lFvoVRnvHQ1trlpXMOWtF8BUgF+3TiipG72uOfhpL5CUdXCk931kvDdUkTL/IZVtNEDQKwEEmJbAYJSA5NnA==", + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.1", @@ -16533,9 +16698,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.85.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", - "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -17447,9 +17612,9 @@ } }, "node_modules/styled-components": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.15.tgz", - "integrity": "sha512-PpOTEztW87Ua2xbmLa7yssjNyUF9vE7wdldRfn1I2E6RTkqknkBYpj771OxM/xrvRGinLy2oysa7GOd7NcZZIA==", + "version": "6.1.16", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.16.tgz", + "integrity": "sha512-KpWB6ORAWGmbWM10cDJfEV6sXc/uVkkkQV3SLwTNQ/E/PqWgNHIoMSLh1Lnk2FkB9+JHK7uuMq1i+9ArxDD7iQ==", "license": "MIT", "dependencies": { "@emotion/is-prop-valid": "1.2.2", @@ -18578,9 +18743,9 @@ } }, "node_modules/userpilot": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.8.tgz", - "integrity": "sha512-Hoym2S7j5IvGzb3n/eOwX3FE5PgzMjk5148uU1WTNM5iw784u6+LZiu3DC7NuovVrwYzI99qy5Ossqmft9c74A==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.9.tgz", + "integrity": "sha512-V0QIuIlAJPB8s3j+qtv7BW7NKSXthlZWuowIu+IZOMGLgUbqQTaSW5m1Ct4wJviPKUNOi8kbhCXN4c4b3zcJzg==", "license": "MIT", "dependencies": { "@ndhoule/includes": "^2.0.1", @@ -18691,9 +18856,9 @@ } }, "node_modules/vite": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz", - "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz", + "integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/client/package.json b/client/package.json index e54a6a098..37a326023 100644 --- a/client/package.json +++ b/client/package.json @@ -9,22 +9,22 @@ "proxy": "http://localhost:4000", "dependencies": { "@ant-design/pro-layout": "^7.22.3", - "@apollo/client": "^3.13.1", + "@apollo/client": "^3.13.5", "@emotion/is-prop-valid": "^1.3.1", "@fingerprintjs/fingerprintjs": "^4.6.1", "@jsreport/browser-client": "^3.1.0", - "@reduxjs/toolkit": "^2.6.0", - "@sentry/cli": "^2.42.2", - "@sentry/react": "^9.3.0", + "@reduxjs/toolkit": "^2.6.1", + "@sentry/cli": "^2.42.4", + "@sentry/react": "^9.7.0", "@sentry/vite-plugin": "^3.2.2", "@splitsoftware/splitio-react": "^1.13.0", "@tanem/react-nprogress": "^5.0.53", "@vitejs/plugin-react": "^4.3.4", - "antd": "^5.24.2", + "antd": "^5.24.4", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.1.0", "autosize": "^6.0.1", - "axios": "^1.8.1", + "axios": "^1.8.4", "classnames": "^2.5.1", "css-box-model": "^1.2.1", "dayjs": "^1.11.13", @@ -38,9 +38,9 @@ "i18next": "^23.15.1", "i18next-browser-languagedetector": "^8.0.4", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.12.4", + "libphonenumber-js": "^1.12.6", "logrocket": "^8.1.2", - "markerjs2": "^2.32.3", + "markerjs2": "^2.32.4", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", "object-hash": "^3.0.0", @@ -74,12 +74,12 @@ "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", - "sass": "^1.85.1", + "sass": "^1.86.0", "socket.io-client": "^4.8.1", - "styled-components": "^6.1.15", + "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.8", + "userpilot": "^1.3.9", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, @@ -123,10 +123,10 @@ "@ant-design/icons": "^5.6.1", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", - "@dotenvx/dotenvx": "^1.38.3", + "@dotenvx/dotenvx": "^1.39.0", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", - "@eslint/js": "^9.21.0", + "@eslint/js": "^9.22.0", "@sentry/webpack-plugin": "^3.2.2", "@testing-library/cypress": "^10.0.2", "browserslist": "^4.24.4", @@ -144,7 +144,7 @@ "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^6.2.0", + "vite": "^6.2.2", "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", diff --git a/package-lock.json b/package-lock.json index ee26aab5c..484fa6d84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "0.2.0", "license": "UNLICENSED", "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.758.0", - "@aws-sdk/client-elasticache": "^3.758.0", + "@aws-sdk/client-cloudwatch-logs": "^3.767.0", + "@aws-sdk/client-elasticache": "^3.761.0", "@aws-sdk/client-s3": "^3.758.0", "@aws-sdk/client-secrets-manager": "^3.758.0", "@aws-sdk/client-ses": "^3.758.0", @@ -19,36 +19,36 @@ "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", "aws4": "^1.13.2", - "axios": "^1.8.1", + "axios": "^1.8.4", "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.3", - "bullmq": "^5.41.7", + "bullmq": "^5.44.0", "chart.js": "^4.4.8", - "cloudinary": "^2.5.1", + "cloudinary": "^2.6.0", "compression": "^1.8.0", "cookie-parser": "^1.4.7", "cors": "2.8.5", "crisp-status-reporter": "^1.2.2", "csrf": "^3.1.0", - "dd-trace": "^5.40.0", + "dd-trace": "^5.43.0", "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.21.1", - "firebase-admin": "^13.1.0", + "firebase-admin": "^13.2.0", "graphql": "^16.10.0", "graphql-request": "^6.1.0", "inline-css": "^4.0.3", "intuit-oauth": "^4.2.0", - "ioredis": "^5.5.0", - "json-2-csv": "^5.5.8", + "ioredis": "^5.6.0", + "json-2-csv": "^5.5.9", "juice": "^11.0.1", "lodash": "^4.17.21", "moment": "^2.30.1", "moment-timezone": "^0.5.47", "multer": "^1.4.5-lts.1", - "node-mailjet": "^6.0.6", + "node-mailjet": "^6.0.8", "node-persist": "^4.0.4", "nodemailer": "^6.10.0", "phone": "^3.1.58", @@ -56,7 +56,7 @@ "redis": "^4.7.0", "rimraf": "^6.0.1", "skia-canvas": "^2.0.2", - "soap": "^1.1.9", + "soap": "^1.1.10", "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", @@ -68,10 +68,10 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { - "@eslint/js": "^9.21.0", + "@eslint/js": "^9.22.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "concurrently": "^8.2.2", - "eslint": "^9.21.0", + "eslint": "^9.22.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", "p-limit": "^3.1.0", @@ -286,9 +286,9 @@ } }, "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.758.0.tgz", - "integrity": "sha512-IlEIm5h4vfeoZyY8Op4W6lX1lqcEYE3DRKl+fMKRTFttvJ+AJfuZlAgFlMh9OPFQ0ZMLe8etoxHwKN50YCLivw==", + "version": "3.767.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.767.0.tgz", + "integrity": "sha512-s2XEomADqRxBuRsefNj34ce3+bmpe+80jawdOp/pXvOALKE0T9hIMy7uHlrFEQoTFskK8kx+fs7gKL3SZvuMZg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -354,9 +354,9 @@ } }, "node_modules/@aws-sdk/client-elasticache": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.758.0.tgz", - "integrity": "sha512-qmDOTHhB0hUm/Ifypi6+zjUR4dl7H576oM4/p2RUgkjyz2RgJaLJhyX32TDDzcX2maevNHJ3TijXOkGxoGDeog==", + "version": "3.761.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.761.0.tgz", + "integrity": "sha512-ZMoT1+wLT85sus8jCP4gRmsmHukmZm2GqOQOY1i+OOHTN0sXzSVneVXYmLA5c63ykoXmFyn1Oytbf/BmQUeX4w==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -1327,15 +1327,15 @@ } }, "node_modules/@datadog/libdatadog": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@datadog/libdatadog/-/libdatadog-0.4.0.tgz", - "integrity": "sha512-kGZfFVmQInzt6J4FFGrqMbrDvOxqwk3WqhAreS6n9b/De+iMVy/NMu3V7uKsY5zAvz+uQw0liDJm3ZDVH/MVVw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@datadog/libdatadog/-/libdatadog-0.5.0.tgz", + "integrity": "sha512-YvLUVOhYVjJssm0f22/RnDQMc7ZZt/w1bA0nty1vvjyaDz5EWaHfWaaV4GYpCt5MRvnGjCBxIwwbRivmGseKeQ==", "license": "Apache-2.0" }, "node_modules/@datadog/native-appsec": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.4.0.tgz", - "integrity": "sha512-LC47AnpVLpQFEUOP/nIIs+i0wLb8XYO+et3ACaJlHa2YJM3asR4KZTqQjDQNy08PTAUbVvYWKwfSR1qVsU/BeA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.5.0.tgz", + "integrity": "sha512-95y+fm7jd+3iknzuu57pWEPw9fcK9uSBCPiB4kSPHszHu3bESlZM553tc4ANsz+X3gMkYGVg2pgSydG77nSDJw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -1394,9 +1394,9 @@ } }, "node_modules/@datadog/pprof": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-5.5.1.tgz", - "integrity": "sha512-3pZVYqc5YkZJOj9Rc8kQ/wG4qlygcnnwFU/w0QKX6dEdJh+1+dWniuUu+GSEjy/H0jc14yhdT2eJJf/F2AnHNw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-5.6.0.tgz", + "integrity": "sha512-x7yN0s4wMnRqv3PWQ6eXKH5XE5qvCOwWbOsXqpT2Irbsc7Wcl5w5JrJUcbPCdSJGihpIh6kAeIrS6w/ZCcHy2Q==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -1410,15 +1410,6 @@ "node": ">=16" } }, - "node_modules/@datadog/pprof/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/@datadog/sketches-js": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@datadog/sketches-js/-/sketches-js-2.1.1.tgz", @@ -1482,6 +1473,16 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", @@ -1533,9 +1534,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "dev": true, "license": "MIT", "engines": { @@ -3838,9 +3839,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", - "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3849,12 +3850,12 @@ } }, "node_modules/axios-ntlm": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/axios-ntlm/-/axios-ntlm-1.4.2.tgz", - "integrity": "sha512-8mS/uhmSWiRBiFKQvysPbX1eDBp6e+eXskmasuAXRHrn1Zjgji3O/oGXzXLw7tOhyD9nho1vGjZ2OYOD3cCvHg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/axios-ntlm/-/axios-ntlm-1.4.3.tgz", + "integrity": "sha512-CS6WE8chZpEDKxv4IFwr5zcG7InMC6Ek0aj2n2tHauBh+8KiYVC4qMn3N2arjR5tnyILQuTGlI0mc83hgWxS4Q==", "license": "MIT", "dependencies": { - "axios": "^1.6.1", + "axios": "^1.7.9", "des.js": "^1.1.0", "dev-null": "^0.1.1", "js-md4": "^0.3.2" @@ -4093,9 +4094,9 @@ } }, "node_modules/bullmq": { - "version": "5.41.7", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.41.7.tgz", - "integrity": "sha512-eZbKJSx15bflfzKRiR+dKeLTr/M/YKb4cIp73OdU79PEMHQ6aEFUtbG6R+f0KvLLznI/O01G581U2Eqli6S2ew==", + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.44.0.tgz", + "integrity": "sha512-OnEtkuXyrUx2Jm5BpH92+ttrobblBdCbkhOe3OoR0hxZuAilI3mPWlwELslhfImRpDv8rK+C/0/VK7I8f3xIig==", "license": "MIT", "dependencies": { "cron-parser": "^4.9.0", @@ -4298,9 +4299,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "license": "MIT" }, "node_modules/cliui": { @@ -4337,9 +4338,9 @@ } }, "node_modules/cloudinary": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.5.1.tgz", - "integrity": "sha512-CNg6uU53Hl4FEVynkTGpt5bQEAQWDHi3H+Sm62FzKf5uQHipSN2v7qVqS8GRVqeb0T1WNV+22+75DOJeRXYeSQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.6.0.tgz", + "integrity": "sha512-FIlny9RR5LPgkMioG4V7yUpC6ASyIFQMWfx4TgOi/xBeLxJTegbyQc3itiXL0b0lDlSaL0KyT2THEw6osrKqpQ==", "license": "MIT", "dependencies": { "lodash": "^4.17.21", @@ -4861,18 +4862,18 @@ } }, "node_modules/dd-trace": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.40.0.tgz", - "integrity": "sha512-/UYVCcgpZ9LnnUvIJcNfd1Hj51i8HhqLOn9PCj5gK3wJUn6MY/ie/5da2ZaFtoK2DKQ9OZmFBITLV3+KDl4pjA==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.43.0.tgz", + "integrity": "sha512-WtPUSZfEosSHYVBFR48FqfYBFor8QchKwAKo+LYtbgTPtFzYKyBV/FJUqYE6sDF15Raf4sJVt/LOscywgj2zEw==", "hasInstallScript": true, "license": "(Apache-2.0 OR BSD-3-Clause)", "dependencies": { - "@datadog/libdatadog": "^0.4.0", - "@datadog/native-appsec": "8.4.0", + "@datadog/libdatadog": "^0.5.0", + "@datadog/native-appsec": "8.5.0", "@datadog/native-iast-rewriter": "2.8.0", "@datadog/native-iast-taint-tracking": "3.3.0", "@datadog/native-metrics": "^3.1.0", - "@datadog/pprof": "5.5.1", + "@datadog/pprof": "5.6.0", "@datadog/sketches-js": "^2.1.0", "@isaacs/ttlcache": "^1.4.1", "@opentelemetry/api": ">=1.0.0 <1.9.0", @@ -4880,7 +4881,7 @@ "crypto-randomuuid": "^1.0.0", "dc-polyfill": "^0.1.4", "ignore": "^5.2.4", - "import-in-the-middle": "1.11.2", + "import-in-the-middle": "1.13.1", "istanbul-lib-coverage": "3.2.0", "jest-docblock": "^29.7.0", "koalas": "^1.0.2", @@ -4904,15 +4905,6 @@ "node": ">=18" } }, - "node_modules/dd-trace/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -5585,18 +5577,19 @@ } }, "node_modules/eslint": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", - "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.21.0", + "@eslint/js": "9.22.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5608,7 +5601,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -5688,9 +5681,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6089,9 +6082,9 @@ } }, "node_modules/firebase-admin": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.1.0.tgz", - "integrity": "sha512-XPKiTyPyvUMZ22EPk4M1oSiZ8/4qFeYwjK88o/DYpGtNbOLKrM6Oc9jTaK+P6Vwn3Vr1+OCyLLJ93Bci382UqA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.2.0.tgz", + "integrity": "sha512-qQBTKo0QWCDaWwISry989pr8YfZSSk00rNCKaucjOgltEm3cCYzEe4rODqBd1uUwma+Iu5jtAzg89Nfsjr3fGg==", "license": "Apache-2.0", "dependencies": { "@fastify/busboy": "^3.0.0", @@ -6959,12 +6952,12 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz", - "integrity": "sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.1.tgz", + "integrity": "sha512-k2V9wNm9B+ysuelDTHjI9d5KPc4l8zAZTGqj+pcynvWkypZd857ryzN8jNC7Pg2YZXNMJcHRPpaDyCBbNyVRpA==", "license": "Apache-2.0", "dependencies": { - "acorn": "^8.8.2", + "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" @@ -7051,9 +7044,9 @@ } }, "node_modules/ioredis": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz", - "integrity": "sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.0.tgz", + "integrity": "sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==", "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", @@ -7627,9 +7620,9 @@ } }, "node_modules/json-2-csv": { - "version": "5.5.8", - "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.8.tgz", - "integrity": "sha512-eMQHOwV+av8Sgo+fkbEbQWOw/kwh89AZ5fNA8TYfcooG6TG1ZOL2WcPUrngIMIK8dBJitQ8QEU0zbncQ0CX4CQ==", + "version": "5.5.9", + "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.9.tgz", + "integrity": "sha512-l4g6GZVHrsN+5SKkpOmGNSvho+saDZwXzj/xmcO0lJAgklzwsiqy70HS5tA9djcRvBEybZ9IF6R1MDFTEsaOGQ==", "license": "MIT", "dependencies": { "deeks": "3.1.0", @@ -8421,12 +8414,12 @@ } }, "node_modules/node-mailjet": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.6.tgz", - "integrity": "sha512-cr8ciqtHuxyFd3+3bpDy+oKuNzctZfRQZtwRjurVAzE+DZLTfyxjgD+GTqQ1kr0ClAjDjSh3ERlZvd5MV0fKHg==", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.8.tgz", + "integrity": "sha512-VyB2+SeD1zuxpuJLePC4bk10UN0G294CsVlF8YBxb+1tlH0Tw4wECGlTYlQOaRMtPgckdObpcfEbhUWu3UuFIQ==", "license": "MIT", "dependencies": { - "axios": "1.7.4", + "axios": "^1.8.1", "json-bigint": "^1.0.0", "url-join": "^4.0.0" }, @@ -8435,17 +8428,6 @@ "npm": ">= 6.9.0" } }, - "node_modules/node-mailjet/node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/node-persist": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-4.0.4.tgz", @@ -9920,13 +9902,13 @@ } }, "node_modules/soap": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.9.tgz", - "integrity": "sha512-x6wMhwIwGFnMQiV0tLIygERELwpV/EkidUvzjcCPRx0D16YngNL8z7j5+nFad0Fl5irisXbfY2FKzvF9SEjMog==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.10.tgz", + "integrity": "sha512-dqfX9qHhXup3ZLWsI5of6xJIJKeBCPnn3tTu9sKtASm2A53Zk6/u3drygLiUy+H1mmjRBptXfVkjY6pt8nhOjA==", "license": "MIT", "dependencies": { - "axios": "^1.7.9", - "axios-ntlm": "^1.4.2", + "axios": "^1.8.3", + "axios-ntlm": "^1.4.3", "debug": "^4.4.0", "formidable": "^3.5.2", "get-stream": "^6.0.1", @@ -9934,7 +9916,7 @@ "sax": "^1.4.1", "strip-bom": "^3.0.0", "whatwg-mimetype": "4.0.0", - "xml-crypto": "^6.0.0" + "xml-crypto": "^6.0.1" }, "engines": { "node": ">=14.17.0" @@ -10032,6 +10014,15 @@ } } }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, "node_modules/source-map-explorer": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/source-map-explorer/-/source-map-explorer-2.5.3.tgz", @@ -10094,16 +10085,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/source-map-explorer/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/source-map-explorer/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -11487,9 +11468,9 @@ } }, "node_modules/xml-crypto": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-6.0.0.tgz", - "integrity": "sha512-L3RgnkaDrHaYcCnoENv4Idzt1ZRj5U1z1BDH98QdDTQfssScx8adgxhd9qwyYo+E3fXbQZjEQH7aiXHLVgxGvw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-6.0.1.tgz", + "integrity": "sha512-v05aU7NS03z4jlZ0iZGRFeZsuKO1UfEbbYiaeRMiATBFs6Jq9+wqKquEMTn4UTrYZ9iGD8yz3KT4L9o2iF682w==", "license": "MIT", "dependencies": { "@xmldom/is-dom-node": "^1.0.1", diff --git a/package.json b/package.json index 6f0426a26..ad845ca08 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" }, "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.758.0", - "@aws-sdk/client-elasticache": "^3.758.0", + "@aws-sdk/client-cloudwatch-logs": "^3.767.0", + "@aws-sdk/client-elasticache": "^3.761.0", "@aws-sdk/client-s3": "^3.758.0", "@aws-sdk/client-secrets-manager": "^3.758.0", "@aws-sdk/client-ses": "^3.758.0", @@ -29,36 +29,36 @@ "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", "aws4": "^1.13.2", - "axios": "^1.8.1", + "axios": "^1.8.4", "bee-queue": "^1.7.1", "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.3", - "bullmq": "^5.41.7", + "bullmq": "^5.44.0", "chart.js": "^4.4.8", - "cloudinary": "^2.5.1", + "cloudinary": "^2.6.0", "compression": "^1.8.0", "cookie-parser": "^1.4.7", "cors": "2.8.5", "crisp-status-reporter": "^1.2.2", "csrf": "^3.1.0", - "dd-trace": "^5.40.0", + "dd-trace": "^5.43.0", "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.21.1", - "firebase-admin": "^13.1.0", + "firebase-admin": "^13.2.0", "graphql": "^16.10.0", "graphql-request": "^6.1.0", "inline-css": "^4.0.3", "intuit-oauth": "^4.2.0", - "ioredis": "^5.5.0", - "json-2-csv": "^5.5.8", + "ioredis": "^5.6.0", + "json-2-csv": "^5.5.9", "juice": "^11.0.1", "lodash": "^4.17.21", "moment": "^2.30.1", "moment-timezone": "^0.5.47", "multer": "^1.4.5-lts.1", - "node-mailjet": "^6.0.6", + "node-mailjet": "^6.0.8", "node-persist": "^4.0.4", "nodemailer": "^6.10.0", "phone": "^3.1.58", @@ -66,7 +66,7 @@ "redis": "^4.7.0", "rimraf": "^6.0.1", "skia-canvas": "^2.0.2", - "soap": "^1.1.9", + "soap": "^1.1.10", "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", @@ -78,10 +78,10 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { - "@eslint/js": "^9.21.0", + "@eslint/js": "^9.22.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "concurrently": "^8.2.2", - "eslint": "^9.21.0", + "eslint": "^9.22.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", "p-limit": "^3.1.0", From 85f1d5cae217b7228d1a4af64bb2f27e3782b379 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 11:04:07 -0400 Subject: [PATCH 16/45] IO-3181-Testing-Framework-Selection: Remove Cypress, upgrade Split --- client/cypress.config.js | 17 -- .../e2e/01-General Render/01-home.cy.js | 19 -- .../cypress/e2e/1-getting-started/todo.cy.js | 124 -------- .../e2e/2-advanced-examples/actions.cy.js | 284 ------------------ .../e2e/2-advanced-examples/aliasing.cy.js | 35 --- .../e2e/2-advanced-examples/assertions.cy.js | 173 ----------- .../e2e/2-advanced-examples/connectors.cy.js | 96 ------ .../e2e/2-advanced-examples/cookies.cy.js | 79 ----- .../e2e/2-advanced-examples/cypress_api.cy.js | 208 ------------- .../e2e/2-advanced-examples/files.cy.js | 86 ------ .../2-advanced-examples/local_storage.cy.js | 58 ---- .../e2e/2-advanced-examples/location.cy.js | 32 -- .../e2e/2-advanced-examples/misc.cy.js | 98 ------ .../e2e/2-advanced-examples/navigation.cy.js | 56 ---- .../network_requests.cy.js | 165 ---------- .../e2e/2-advanced-examples/querying.cy.js | 100 ------ .../spies_stubs_clocks.cy.js | 203 ------------- .../e2e/2-advanced-examples/traversal.cy.js | 97 ------ .../e2e/2-advanced-examples/utilities.cy.js | 108 ------- .../e2e/2-advanced-examples/viewport.cy.js | 59 ---- .../e2e/2-advanced-examples/waiting.cy.js | 31 -- .../e2e/2-advanced-examples/window.cy.js | 22 -- client/cypress/fixtures/example.json | 5 - client/cypress/fixtures/profile.json | 5 - client/cypress/fixtures/users.json | 1 - client/cypress/plugins/index.js | 22 -- client/cypress/support/commands.js | 27 -- client/cypress/support/e2e.js | 20 -- client/cypress/tsconfig.json | 8 - client/package-lock.json | 169 +++++------ client/package.json | 6 +- client/src/App/App.container.jsx | 32 +- client/src/redux/user/user.actions.js | 5 + client/src/redux/user/user.reducer.js | 5 + client/src/redux/user/user.sagas.js | 5 +- client/src/redux/user/user.types.js | 3 +- 36 files changed, 127 insertions(+), 2336 deletions(-) delete mode 100644 client/cypress.config.js delete mode 100644 client/cypress/e2e/01-General Render/01-home.cy.js delete mode 100644 client/cypress/e2e/1-getting-started/todo.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/actions.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/aliasing.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/assertions.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/connectors.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/cookies.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/cypress_api.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/files.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/local_storage.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/location.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/misc.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/navigation.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/network_requests.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/querying.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/traversal.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/utilities.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/viewport.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/waiting.cy.js delete mode 100644 client/cypress/e2e/2-advanced-examples/window.cy.js delete mode 100644 client/cypress/fixtures/example.json delete mode 100644 client/cypress/fixtures/profile.json delete mode 100644 client/cypress/fixtures/users.json delete mode 100644 client/cypress/plugins/index.js delete mode 100644 client/cypress/support/commands.js delete mode 100644 client/cypress/support/e2e.js delete mode 100644 client/cypress/tsconfig.json diff --git a/client/cypress.config.js b/client/cypress.config.js deleted file mode 100644 index b000b5aac..000000000 --- a/client/cypress.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { defineConfig } = require("cypress"); - -module.exports = defineConfig({ - experimentalStudio: true, - env: { - FIREBASE_USERNAME: "cypress@imex.test", - FIREBASE_PASSWORD: "cypress" - }, - e2e: { - // We've imported your old cypress plugins here. - // You may want to clean this up later by importing these. - setupNodeEvents(on, config) { - return require("./cypress/plugins/index.js")(on, config); - }, - baseUrl: "https://localhost:3000" - } -}); diff --git a/client/cypress/e2e/01-General Render/01-home.cy.js b/client/cypress/e2e/01-General Render/01-home.cy.js deleted file mode 100644 index 44202154f..000000000 --- a/client/cypress/e2e/01-General Render/01-home.cy.js +++ /dev/null @@ -1,19 +0,0 @@ -/// -const { FIREBASE_USERNAME, FIREBASE_PASSWORcD } = Cypress.env(); -describe("Renders the General Page", () => { - beforeEach(() => { - cy.visit("/"); - }); - it("Renders Correctly", () => {}); - it("Has the Slogan", () => { - cy.findByText("A whole x22new kind of shop management system.").should("exist"); - /* ==== Generated with Cypress Studio ==== */ - cy.get(".ant-menu-item-active > .ant-menu-title-content > .header0-item-block").click(); - cy.get("#email").clear(); - cy.get("#email").type("patrick@imex.dev"); - cy.get("#password").clear(); - cy.get("#password").type("patrick123{enter}"); - cy.get(".ant-form > .ant-btn").click(); - /* ==== End Cypress Studio ==== */ - }); -}); diff --git a/client/cypress/e2e/1-getting-started/todo.cy.js b/client/cypress/e2e/1-getting-started/todo.cy.js deleted file mode 100644 index 87e609ced..000000000 --- a/client/cypress/e2e/1-getting-started/todo.cy.js +++ /dev/null @@ -1,124 +0,0 @@ -/// - -// Welcome to Cypress! -// -// This spec file contains a variety of sample tests -// for a todo list app that are designed to demonstrate -// the power of writing tests in Cypress. -// -// To learn more about how Cypress works and -// what makes it such an awesome testing tool, -// please read our getting started guide: -// https://on.cypress.io/introduction-to-cypress - -describe("example to-do app", () => { - beforeEach(() => { - // Cypress starts out with a blank slate for each test - // so we must tell it to visit our website with the `cy.visit()` command. - // Since we want to visit the same URL at the start of all our tests, - // we include it in our beforeEach function so that it runs before each test - cy.visit("https://example.cypress.io/todo"); - }); - - it("displays two todo items by default", () => { - // We use the `cy.get()` command to get all elements that match the selector. - // Then, we use `should` to assert that there are two matched items, - // which are the two default items. - cy.get(".todo-list li").should("have.length", 2); - - // We can go even further and check that the default todos each contain - // the correct text. We use the `first` and `last` functions - // to get just the first and last matched elements individually, - // and then perform an assertion with `should`. - cy.get(".todo-list li").first().should("have.text", "Pay electric bill"); - cy.get(".todo-list li").last().should("have.text", "Walk the dog"); - }); - - it("can add new todo items", () => { - // We'll store our item text in a variable so we can reuse it - const newItem = "Feed the cat"; - - // Let's get the input element and use the `type` command to - // input our new list item. After typing the content of our item, - // we need to type the enter key as well in order to submit the input. - // This input has a data-test attribute so we'll use that to select the - // element in accordance with best practices: - // https://on.cypress.io/selecting-elements - cy.get("[data-test=new-todo]").type(`${newItem}{enter}`); - - // Now that we've typed our new item, let's check that it actually was added to the list. - // Since it's the newest item, it should exist as the last element in the list. - // In addition, with the two default items, we should have a total of 3 elements in the list. - // Since assertions yield the element that was asserted on, - // we can chain both of these assertions together into a single statement. - cy.get(".todo-list li").should("have.length", 3).last().should("have.text", newItem); - }); - - it("can check off an item as completed", () => { - // In addition to using the `get` command to get an element by selector, - // we can also use the `contains` command to get an element by its contents. - // However, this will yield the
+
+ ); + }} + + + ); } diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index ddfd26a2f..a9f16c111 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -509,6 +509,7 @@ export const GET_JOB_BY_PK = gql` est_ct_ln est_ea est_ph1 + flat_rate_ats federal_tax_rate id inproduction @@ -649,6 +650,7 @@ export const GET_JOB_BY_PK = gql` policy_no production_vars rate_ats + rate_ats_flat rate_la1 rate_la2 rate_la3 diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 5e062169a..ccf90fc10 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -722,6 +722,7 @@ "scoreboardsetup": "Scoreboard Setup", "shop_enabled_features": "Shop Enabled Features", "shopinfo": "Shop Information", + "shoprates": "Shop Rates", "speedprint": "Speed Print Configuration", "ssbuckets": "Job Size Definitions", "systemsettings": "System Settings", @@ -1658,7 +1659,7 @@ "08": "Left Rear Side", "09": "Left Side" }, - "auto_add_ats": "Automatically Add/Update ATS", + "auto_add_ats": "Automatically Add/Update ATS?", "ca_bc_pvrt": "PVRT", "ca_customer_gst": "Customer Portion of GST", "ca_gst_registrant": "GST Registrant", @@ -1757,6 +1758,7 @@ "est_ct_ln": "Estimator Last Name", "est_ea": "Estimator Email", "est_ph1": "Estimator Phone #", + "flat_rate_ats": "Flat Rate ATS?", "federal_tax_payable": "Federal Tax Payable", "federal_tax_rate": "Federal Tax Rate", "ins_addr1": "Insurance Co. Address", @@ -1868,6 +1870,7 @@ }, "queued_for_parts": "Queued for Parts", "rate_ats": "ATS Rate", + "rate_ats_flat": "ATS Flat Rate", "rate_la1": "LA1", "rate_la2": "LA2", "rate_la3": "LA3", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 6aa64961a..2f9fa9a2b 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -722,6 +722,7 @@ "scoreboardsetup": "", "shop_enabled_features": "", "shopinfo": "", + "shoprates": "", "speedprint": "", "ssbuckets": "", "systemsettings": "", @@ -1757,6 +1758,7 @@ "est_ct_ln": "Apellido del tasador", "est_ea": "Correo electrónico del tasador", "est_ph1": "Número de teléfono del tasador", + "flat_rate_ats": "", "federal_tax_payable": "Impuesto federal por pagar", "federal_tax_rate": "", "ins_addr1": "Dirección de Insurance Co.", @@ -1868,6 +1870,7 @@ }, "queued_for_parts": "", "rate_ats": "", + "rate_ats_flat": "", "rate_la1": "Tarifa LA1", "rate_la2": "Tarifa LA2", "rate_la3": "Tarifa LA3", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 6e9713285..888162de9 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -722,6 +722,7 @@ "scoreboardsetup": "", "shop_enabled_features": "", "shopinfo": "", + "shoprates": "", "speedprint": "", "ssbuckets": "", "systemsettings": "", @@ -1757,6 +1758,7 @@ "est_ct_ln": "Nom de l'évaluateur", "est_ea": "Courriel de l'évaluateur", "est_ph1": "Numéro de téléphone de l'évaluateur", + "flat_rate_ats": "", "federal_tax_payable": "Impôt fédéral à payer", "federal_tax_rate": "", "ins_addr1": "Adresse Insurance Co.", @@ -1868,6 +1870,7 @@ }, "queued_for_parts": "", "rate_ats": "", + "rate_ats_flat": "", "rate_la1": "Taux LA1", "rate_la2": "Taux LA2", "rate_la3": "Taux LA3", diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 6cdb4c008..4d1f5192e 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -3695,6 +3695,7 @@ - est_st - est_zip - federal_tax_rate + - flat_rate_ats - g_bett_amt - id - inproduction @@ -3789,6 +3790,7 @@ - qb_multiple_payers - queued_for_parts - rate_ats + - rate_ats_flat - rate_la1 - rate_la2 - rate_la3 @@ -3965,6 +3967,7 @@ - est_st - est_zip - federal_tax_rate + - flat_rate_ats - g_bett_amt - id - inproduction @@ -4060,6 +4063,7 @@ - qb_multiple_payers - queued_for_parts - rate_ats + - rate_ats_flat - rate_la1 - rate_la2 - rate_la3 @@ -4247,6 +4251,7 @@ - est_st - est_zip - federal_tax_rate + - flat_rate_ats - g_bett_amt - id - inproduction @@ -4342,6 +4347,7 @@ - qb_multiple_payers - queued_for_parts - rate_ats + - rate_ats_flat - rate_la1 - rate_la2 - rate_la3 diff --git a/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql new file mode 100644 index 000000000..5478f998b --- /dev/null +++ b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."jobs" add column "flat_rate_ats" boolean +-- null default 'false'; diff --git a/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql new file mode 100644 index 000000000..73fa874ae --- /dev/null +++ b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql @@ -0,0 +1,2 @@ +alter table "public"."jobs" add column "flat_rate_ats" boolean + null default 'false'; diff --git a/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql new file mode 100644 index 000000000..3f82e9770 --- /dev/null +++ b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."jobs" add column "rate_ats_flat" numeric +-- null; diff --git a/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql new file mode 100644 index 000000000..e0157edd2 --- /dev/null +++ b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql @@ -0,0 +1,2 @@ +alter table "public"."jobs" add column "rate_ats_flat" numeric + null; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index cc50b3115..3df3e810c 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -1485,6 +1485,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) { materials auto_add_ats rate_ats + flat_rate_ats + rate_ats_flat joblines(where: { removed: { _eq: false } }){ id line_no diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 4e889a658..6835dc7cb 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -1,7 +1,7 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); -const adminClient = require("../graphql-client/graphql-client").client; -const _ = require("lodash"); +// const adminClient = require("../graphql-client/graphql-client").client; +// const _ = require("lodash"); const logger = require("../utils/logger"); const InstanceMgr = require("../utils/instanceMgr").default; @@ -45,7 +45,9 @@ exports.totalsSsu = async function (req, res) { } }); - res.status(200).send(); + if (result) { + res.status(200).send(); + } } catch (error) { logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, { jobid: id, @@ -59,7 +61,7 @@ exports.totalsSsu = async function (req, res) { //IMPORTANT*** These two functions MUST be mirrrored. async function TotalsServerSide(req, res) { const { job, client } = req.body; - await AutoAddAtsIfRequired({ job: job, client: client }); + await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user }); try { let ret = { @@ -137,11 +139,12 @@ async function Totals(req, res) { const logger = req.logger; const client = req.userGraphQLClient; - logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, { - jobid: job.id + logger.log("job-totals-USA", "DEBUG", req.user.email, job.id, { + jobid: job.id, + id: id }); - await AutoAddAtsIfRequired({ job, client }); + await AtsAdjustmentsIfRequired({ job, client, user: req.user }); try { let ret = { @@ -162,40 +165,45 @@ async function Totals(req, res) { } } -async function AutoAddAtsIfRequired({ job, client }) { - //Check if ATS should be automatically added. - if (job.auto_add_ats) { - //Get the total sum of hours that should be the ATS amount. - //Check to see if an ATS line exists. +async function AtsAdjustmentsIfRequired({ job, client, user }) { + if (job.auto_add_ats || job.flat_rate_ats) { + let atsAmount = 0; let atsLineIndex = null; - const atsHours = job.joblines.reduce((acc, val, index) => { - if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") { - atsLineIndex = index; - } - if ( - val.mod_lbr_ty !== "LA1" && - val.mod_lbr_ty !== "LA2" && - val.mod_lbr_ty !== "LA3" && - val.mod_lbr_ty !== "LA4" && - val.mod_lbr_ty !== "LAU" && - val.mod_lbr_ty !== "LAG" && - val.mod_lbr_ty !== "LAS" && - val.mod_lbr_ty !== "LAA" - ) { - acc = acc + val.mod_lb_hrs; - } + //Check if ATS should be automatically added. + if (job.auto_add_ats) { + const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]); - return acc; - }, 0); + //Get the total sum of hours that should be the ATS amount. + //Check to see if an ATS line exists. + const atsHours = job.joblines.reduce((acc, val, index) => { + if (val.line_desc?.toLowerCase() === "ats amount") { + atsLineIndex = index; + } - const atsAmount = atsHours * (job.rate_ats || 0); - //If it does, update it in place, and make sure it is updated for local calculations. + if (!excludedLaborTypes.has(val.mod_lbr_ty)) { + acc = acc + val.mod_lb_hrs; + } + + return acc; + }, 0); + + atsAmount = atsHours * (job.rate_ats || 0); + } + + //Check if a Flat Rate ATS should be added. + if (job.flat_rate_ats) { + atsLineIndex = ((i) => (i === -1 ? null : i))( + job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount") + ); + atsAmount = job.rate_ats_flat || 0; + } + + //If it does not, create one for local calculations and insert it. if (atsLineIndex === null) { const newAtsLine = { jobid: job.id, alt_partm: null, - line_no: 35, unq_seq: 0, line_ind: "E", line_desc: "ATS Amount", @@ -220,19 +228,40 @@ async function AutoAddAtsIfRequired({ job, client }) { prt_dsmk_m: 0.0 }; - const result = await client.request(queries.INSERT_NEW_JOB_LINE, { - lineInput: [newAtsLine] - }); + try { + const result = await client.request(queries.INSERT_NEW_JOB_LINE, { + lineInput: [newAtsLine] + }); - job.joblines.push(newAtsLine); + if (result) { + job.joblines.push(newAtsLine); + } + } catch (error) { + logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { + jobid: job.id, + error: error.message, + stack: error.stack + }); + } } - //If it does not, create one for local calculations and insert it. + //If it does, update it in place, and make sure it is updated for local calculations. else { - const result = await client.request(queries.UPDATE_JOB_LINE, { - line: { act_price: atsAmount }, - lineId: job.joblines[atsLineIndex].id - }); - job.joblines[atsLineIndex].act_price = atsAmount; + try { + const result = await client.request(queries.UPDATE_JOB_LINE, { + line: { act_price: atsAmount }, + lineId: job.joblines[atsLineIndex].id + }); + if (result) { + job.joblines[atsLineIndex].act_price = atsAmount; + } + } catch (error) { + logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { + jobid: job.id, + atsLineIndex: atsLineIndex, + error: error.message, + stack: error.stack + }); + } } } } @@ -314,7 +343,7 @@ async function CalculateRatesTotals({ job, client }) { let hasMashLine = false; let hasMahwLine = false; let hasCustomMahwLine; - let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode); + // let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode); let mashOpCodes = ParseCalopCode(job.materials["MASH"]?.cal_opcode); jobLines.forEach((item) => { @@ -564,7 +593,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) { } }; - default: + default: { if (!value.part_type && value.db_ref !== "900510" && value.db_ref !== "900511") return acc; const discountAmount = @@ -631,6 +660,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) { ) } }; + } } }, { @@ -652,7 +682,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) { let adjustments = {}; //Track all adjustments that need to be made. - const linesToAdjustForDiscount = []; + //const linesToAdjustForDiscount = []; Object.keys(parts_tax_rates).forEach((key) => { //Check if there's a discount or a mark up. let disc = Dinero(), @@ -1019,7 +1049,9 @@ function CalculateTaxesTotals(job, otherTotals) { } } catch (error) { logger.log("job-totals-USA Key with issue", "error", null, job.id, { - key + key: key, + error: error.message, + stack: error.stack }); } }); @@ -1158,6 +1190,8 @@ function CalculateTaxesTotals(job, otherTotals) { exports.default = Totals; function DiscountNotAlreadyCounted(jobline, joblines) { + void jobline; + void joblines; return false; } @@ -1172,27 +1206,35 @@ function IsTrueOrYes(value) { return value === true || value === "Y" || value === "y"; } -async function UpdateJobLines(joblinesToUpdate) { - if (joblinesToUpdate.length === 0) return; - const updateQueries = joblinesToUpdate.map((line, index) => - generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index) - ); - const query = ` - mutation UPDATE_EST_LINES{ - ${updateQueries} - } - `; +// Function not in use from RO to IO Merger 02/05/2024 +// async function UpdateJobLines(joblinesToUpdate) { +// if (joblinesToUpdate.length === 0) return; +// const updateQueries = joblinesToUpdate.map((line, index) => +// generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index) +// ); +// const query = ` +// mutation UPDATE_EST_LINES{ +// ${updateQueries} +// } +// `; +// try { +// const result = await adminClient.request(query); +// void result; +// } catch (error) { +// logger.log("update-job-lines", "error", null, null, { +// error: error.message, +// stack: error.stack +// }); +// } +// } - const result = await adminClient.request(query); -} - -const generateUpdateQuery = (lineToUpdate, index) => { - return ` - update_joblines${index}: update_joblines(where: { id: { _eq: "${ - lineToUpdate.id - }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) { - returning { - id - } - }`; -}; +// const generateUpdateQuery = (lineToUpdate, index) => { +// return ` +// update_joblines${index}: update_joblines(where: { id: { _eq: "${ +// lineToUpdate.id +// }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) { +// returning { +// id +// } +// }`; +// }; diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 4cd45e13c..0a160426d 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -1,7 +1,5 @@ const Dinero = require("dinero.js"); const queries = require("../graphql-client/queries"); -const adminClient = require("../graphql-client/graphql-client").client; -const _ = require("lodash"); const logger = require("../utils/logger"); //****************************************************** */ @@ -44,11 +42,16 @@ exports.totalsSsu = async function (req, res) { } }); + if (!result) { + throw new Error("Failed to update job totals"); + } + res.status(200).send(); } catch (error) { logger.log("job-totals-ssu-error", "ERROR", req.user.email, id, { jobid: id, - error + error: error.message, + stack: error.stack }); res.status(503).send(); } @@ -57,7 +60,7 @@ exports.totalsSsu = async function (req, res) { //IMPORTANT*** These two functions MUST be mirrrored. async function TotalsServerSide(req, res) { const { job, client } = req.body; - await AutoAddAtsIfRequired({ job: job, client: client }); + await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user }); try { let ret = { @@ -71,7 +74,8 @@ async function TotalsServerSide(req, res) { } catch (error) { logger.log("job-totals-ssu-error", "ERROR", req?.user?.email, job.id, { jobid: job.id, - error + error: error.message, + stack: error.stack }); res.status(400).send(JSON.stringify(error)); } @@ -83,13 +87,12 @@ async function Totals(req, res) { const logger = req.logger; const client = req.userGraphQLClient; - logger.log("job-totals", "DEBUG", req.user.email, job.id, { - jobid: job.id + logger.log("job-totals-", "DEBUG", req.user.email, job.id, { + jobid: job.id, + id: id }); - logger.log("job-totals-ssu", "DEBUG", req.user.email, id, null); - - await AutoAddAtsIfRequired({ job, client }); + await AtsAdjustmentsIfRequired({ job, client, user: req.user }); try { let ret = { @@ -103,46 +106,52 @@ async function Totals(req, res) { } catch (error) { logger.log("job-totals-error", "ERROR", req.user.email, job.id, { jobid: job.id, - error + error: error.message, + stack: error.stack }); res.status(400).send(JSON.stringify(error)); } } -async function AutoAddAtsIfRequired({ job, client }) { - //Check if ATS should be automatically added. - if (job.auto_add_ats) { - //Get the total sum of hours that should be the ATS amount. - //Check to see if an ATS line exists. +async function AtsAdjustmentsIfRequired({ job, client, user }) { + if (job.auto_add_ats || job.flat_rate_ats) { + let atsAmount = 0; let atsLineIndex = null; - const atsHours = job.joblines.reduce((acc, val, index) => { - if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") { - atsLineIndex = index; - } - if ( - val.mod_lbr_ty !== "LA1" && - val.mod_lbr_ty !== "LA2" && - val.mod_lbr_ty !== "LA3" && - val.mod_lbr_ty !== "LA4" && - val.mod_lbr_ty !== "LAU" && - val.mod_lbr_ty !== "LAG" && - val.mod_lbr_ty !== "LAS" && - val.mod_lbr_ty !== "LAA" - ) { - acc = acc + val.mod_lb_hrs; - } + //Check if ATS should be automatically added. + if (job.auto_add_ats) { + const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]); - return acc; - }, 0); + //Get the total sum of hours that should be the ATS amount. + //Check to see if an ATS line exists. + const atsHours = job.joblines.reduce((acc, val, index) => { + if (val.line_desc?.toLowerCase() === "ats amount") { + atsLineIndex = index; + } - const atsAmount = atsHours * (job.rate_ats || 0); - //If it does, update it in place, and make sure it is updated for local calculations. + if (!excludedLaborTypes.has(val.mod_lbr_ty)) { + acc = acc + val.mod_lb_hrs; + } + + return acc; + }, 0); + + atsAmount = atsHours * (job.rate_ats || 0); + } + + //Check if a Flat Rate ATS should be added. + if (job.flat_rate_ats) { + atsLineIndex = ((i) => (i === -1 ? null : i))( + job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount") + ); + atsAmount = job.rate_ats_flat || 0; + } + + //If it does not, create one for local calculations and insert it. if (atsLineIndex === null) { const newAtsLine = { jobid: job.id, alt_partm: null, - line_no: 35, unq_seq: 0, line_ind: "E", line_desc: "ATS Amount", @@ -167,22 +176,41 @@ async function AutoAddAtsIfRequired({ job, client }) { prt_dsmk_m: 0.0 }; - const result = await client.request(queries.INSERT_NEW_JOB_LINE, { - lineInput: [newAtsLine] - }); + try { + const result = await client.request(queries.INSERT_NEW_JOB_LINE, { + lineInput: [newAtsLine] + }); - job.joblines.push(newAtsLine); + if (result) { + job.joblines.push(newAtsLine); + } + } catch (error) { + logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { + jobid: job.id, + error: error.message, + stack: error.stack + }); + } } - //If it does not, create one for local calculations and insert it. + //If it does, update it in place, and make sure it is updated for local calculations. else { - const result = await client.request(queries.UPDATE_JOB_LINE, { - line: { act_price: atsAmount }, - lineId: job.joblines[atsLineIndex].id - }); - job.joblines[atsLineIndex].act_price = atsAmount; + try { + const result = await client.request(queries.UPDATE_JOB_LINE, { + line: { act_price: atsAmount }, + lineId: job.joblines[atsLineIndex].id + }); + if (result) { + job.joblines[atsLineIndex].act_price = atsAmount; + } + } catch (error) { + logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { + jobid: job.id, + atsLineIndex: atsLineIndex, + error: error.message, + stack: error.stack + }); + } } - - //console.log(job.jobLines); } } From f3b9c6399f0f66142ef6e6ed3a6efc686866d00b Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 13:10:00 -0400 Subject: [PATCH 22/45] IO-3183-Dependency-Updates-and-maintenance - UUID, Concurrently and Twilio Updates --- package-lock.json | 93 ++++----------------- package.json | 6 +- server/accounting/pbs/pbs-ap-allocations.js | 3 +- server/data/arms.js | 4 +- server/routes/miscellaneousRoutes.js | 4 +- 5 files changed, 25 insertions(+), 85 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d0fc24da..0db4ef983 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,8 +60,8 @@ "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", - "twilio": "^4.23.0", - "uuid": "^10.0.0", + "twilio": "^5.5.1", + "uuid": "^11.1.0", "winston": "^3.17.0", "winston-cloudwatch": "^6.3.0", "xml2js": "^0.6.2", @@ -70,7 +70,7 @@ "devDependencies": { "@eslint/js": "^9.23.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "concurrently": "^8.2.2", + "concurrently": "^9.1.2", "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", @@ -4549,18 +4549,16 @@ } }, "node_modules/concurrently": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", - "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", + "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", - "date-fns": "^2.30.0", "lodash": "^4.17.21", "rxjs": "^7.8.1", "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", "supports-color": "^8.1.1", "tree-kill": "^1.2.2", "yargs": "^17.7.2" @@ -4570,7 +4568,7 @@ "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": "^14.13.0 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" @@ -4829,23 +4827,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -6106,19 +6087,6 @@ "@google-cloud/storage": "^7.14.0" } }, - "node_modules/firebase-admin/node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -9136,12 +9104,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT" - }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -9312,12 +9274,6 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" - }, "node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -10132,12 +10088,6 @@ "node": ">=10" } }, - "node_modules/spawn-command": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", - "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", - "dev": true - }, "node_modules/specificity": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", @@ -10708,18 +10658,17 @@ "license": "Unlicense" }, "node_modules/twilio": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/twilio/-/twilio-4.23.0.tgz", - "integrity": "sha512-LdNBQfOe0dY2oJH2sAsrxazpgfFQo5yXGxe96QA8UWB5uu+433PrUbkv8gQ5RmrRCqUTPQ0aOrIyAdBr1aB03Q==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.1.tgz", + "integrity": "sha512-b1gLd2eMsCSCHRerp3GQUedVlz0nCTt5FbyPxDPmMvk5cm6eIPk4ZTp5JNpgucARZgpCB2uUACJbdcidEHAUBA==", "license": "MIT", "dependencies": { - "axios": "^1.6.0", + "axios": "^1.7.8", "dayjs": "^1.11.9", "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^9.0.0", + "jsonwebtoken": "^9.0.2", "qs": "^6.9.4", "scmp": "^2.1.0", - "url-parse": "^1.5.9", "xmlbuilder": "^13.0.2" }, "engines": { @@ -10911,16 +10860,6 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "license": "MIT" }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10937,16 +10876,16 @@ } }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/valid-data-url": { diff --git a/package.json b/package.json index 8245785a7..7567e361b 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,8 @@ "socket.io": "^4.8.1", "socket.io-adapter": "^2.5.5", "ssh2-sftp-client": "^11.0.0", - "twilio": "^4.23.0", - "uuid": "^10.0.0", + "twilio": "^5.5.1", + "uuid": "^11.1.0", "winston": "^3.17.0", "winston-cloudwatch": "^6.3.0", "xml2js": "^0.6.2", @@ -80,7 +80,7 @@ "devDependencies": { "@eslint/js": "^9.23.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "concurrently": "^8.2.2", + "concurrently": "^9.1.2", "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", diff --git a/server/accounting/pbs/pbs-ap-allocations.js b/server/accounting/pbs/pbs-ap-allocations.js index a969e82c8..9574b166d 100644 --- a/server/accounting/pbs/pbs-ap-allocations.js +++ b/server/accounting/pbs/pbs-ap-allocations.js @@ -12,7 +12,7 @@ const AxiosLib = require("axios").default; const axios = AxiosLib.create(); const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants"); const { CheckForErrors } = require("./pbs-job-export"); -const uuid = require("uuid").v4; + axios.interceptors.request.use((x) => { const socket = x.socket; @@ -21,6 +21,7 @@ axios.interceptors.request.use((x) => { ...x.headers[x.method], ...x.headers }; + const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${ x.url } | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`; diff --git a/server/data/arms.js b/server/data/arms.js index 70ad3be5e..6dadc9364 100644 --- a/server/data/arms.js +++ b/server/data/arms.js @@ -18,7 +18,7 @@ const entegralEndpoint = : "https://uat-ws.armsbusinesssolutions.net/RepairOrderFolderService/RepairOrderFolderService.asmx?WSDL"; const client = require("../graphql-client/graphql-client").client; -const uuid = require("uuid").v4; +const { v4 } = require("uuid"); const momentFormat = "yyyy-MM-DDTHH:mm:ss.SSS"; @@ -79,7 +79,7 @@ exports.default = async (req, res) => { } try { - const transId = uuid(); // Can this actually be the job id? + const transId = v4(); // Can this actually be the job id? let obj = { RqUID: transId, DocumentInfo: { diff --git a/server/routes/miscellaneousRoutes.js b/server/routes/miscellaneousRoutes.js index a3f3ca281..aeb59af93 100644 --- a/server/routes/miscellaneousRoutes.js +++ b/server/routes/miscellaneousRoutes.js @@ -14,7 +14,7 @@ const { taskAssignedEmail, tasksRemindEmail } = require("../email/tasksEmails"); const { canvastest } = require("../render/canvas-handler"); const { alertCheck } = require("../alerts/alertcheck"); const updateBodyshopCache = require("../web-sockets/updateBodyshopCache"); -const uuid = require("uuid").v4; +const { v4 } = require("uuid"); //Test route to ensure Express is responding. router.get("/test", eventAuthorizationMiddleware, async function (req, res) { @@ -83,7 +83,7 @@ router.get("/wstest", eventAuthorizationMiddleware, (req, res) => { // image_path: [], newMessage: { conversation: { - id: uuid(), + id: v4(), archived: false, bodyshop: { id: "bfec8c8c-b7f1-49e0-be4c-524455f4e582", From 922aaaf4b2596701b3a400af2aadb9d38940fc76 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 13:23:41 -0400 Subject: [PATCH 23/45] IO-3183-Dependency-Updates-and-maintenance - Minor front end dep bump, logging clean up on OS --- client/package-lock.json | 24 ++++++++++++------------ client/package.json | 4 ++-- server/opensearch/os-handler.js | 6 ++++++ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 8219a9e5b..e579c3317 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -28,7 +28,7 @@ "@vitejs/plugin-react": "^4.3.4", "antd": "^5.24.5", "apollo-link-logger": "^2.0.1", - "apollo-link-sentry": "^4.1.0", + "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", "axios": "^1.8.4", "classnames": "^2.5.1", @@ -113,12 +113,12 @@ "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", - "vite-plugin-pwa": "^0.21.1", + "vite-plugin-pwa": "^0.21.2", "vite-plugin-style-import": "^2.0.0", "workbox-window": "^7.3.0" }, "engines": { - "node": ">=18.18.2" + "node": ">=22.0.0" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.6.1" @@ -6180,20 +6180,20 @@ } }, "node_modules/apollo-link-sentry": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/apollo-link-sentry/-/apollo-link-sentry-4.1.0.tgz", - "integrity": "sha512-wHiJXZ9OzmRbV3famykszz0E0SZyCBpa3Rt0EVrdOKDN9qQQaE63xQB2lFa3mUkZb95GMc+6ugPt8bVIkwsRPQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/apollo-link-sentry/-/apollo-link-sentry-4.2.0.tgz", + "integrity": "sha512-w8EUM4aEw1/VxIB3KOP11T8qz44oWRcbXRd2vJq/qHnfRMKS5HkMerSIYwKN2e8k9H8ubfkwBvStH51CVf4wwg==", "license": "MIT", "dependencies": { "deepmerge": "^4.2.2", - "dot-prop": "^6.0.0", + "dot-prop": "^6", "tslib": "^2.0.3", "zen-observable-ts": "^1.2.5" }, "peerDependencies": { "@apollo/client": "^3.2.3", - "@sentry/core": "^8.33.0", - "graphql": "15 - 16" + "@sentry/core": "^8.33 || ^9", + "graphql": "^15 || ^16" } }, "node_modules/argparse": { @@ -17009,9 +17009,9 @@ } }, "node_modules/vite-plugin-pwa": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.21.1.tgz", - "integrity": "sha512-rkTbKFbd232WdiRJ9R3u+hZmf5SfQljX1b45NF6oLA6DSktEKpYllgTo1l2lkiZWMWV78pABJtFjNXfBef3/3Q==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.21.2.tgz", + "integrity": "sha512-vFhH6Waw8itNu37hWUJxL50q+CBbNcMVzsKaYHQVrfxTt3ihk3PeLO22SbiP1UNWzcEPaTQv+YVxe4G0KOjAkg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/client/package.json b/client/package.json index bd0966e2d..fbb9d218a 100644 --- a/client/package.json +++ b/client/package.json @@ -27,7 +27,7 @@ "@vitejs/plugin-react": "^4.3.4", "antd": "^5.24.5", "apollo-link-logger": "^2.0.1", - "apollo-link-sentry": "^4.1.0", + "apollo-link-sentry": "^4.2.0", "autosize": "^6.0.1", "axios": "^1.8.4", "classnames": "^2.5.1", @@ -147,7 +147,7 @@ "vite-plugin-babel": "^1.3.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-node-polyfills": "^0.23.0", - "vite-plugin-pwa": "^0.21.1", + "vite-plugin-pwa": "^0.21.2", "vite-plugin-style-import": "^2.0.0", "workbox-window": "^7.3.0" } diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index 9fd500a46..48310c4f2 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -160,6 +160,11 @@ async function OpenSearchUpdateHandler(req, res) { res.status(200).json(response.body); } } catch (error) { + // We don't want this spam message existing in development/test, + if (process.env?.NODE_ENV !== "production" && error?.message === "Invalid URL") { + return res.status(400).json(JSON.stringify(error)); + } + logger.log("os-handler-error", "ERROR", null, null, { id: req.body.event.data.new.id, index: req.body.table.name, @@ -167,6 +172,7 @@ async function OpenSearchUpdateHandler(req, res) { stack: error.stack // body: document }); + res.status(400).json(JSON.stringify(error)); } } From 4589e7fa05302a5ea4327df33d81af9213324a7e Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 13:54:18 -0400 Subject: [PATCH 24/45] IO-3183-Dependency-Updates-and-maintenance - Revert react-grid-layout --- client/package-lock.json | 39 +++++++++++++++------------------------ client/package.json | 2 +- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index e579c3317..03db0e103 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -59,7 +59,7 @@ "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", - "react-grid-layout": "^1.5.1", + "react-grid-layout": "1.3.4", "react-i18next": "^14.1.3", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", @@ -11233,6 +11233,13 @@ "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", "license": "MIT" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -13933,38 +13940,22 @@ } }, "node_modules/react-grid-layout": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.5.1.tgz", - "integrity": "sha512-4Fr+kKMk0+m1HL/BWfHxi/lRuaOmDNNKQDcu7m12+NEYcen20wIuZFo789u3qWCyvUsNUxCiyf0eKq4WiJSNYw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz", + "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0", - "fast-equals": "^4.0.3", + "clsx": "^1.1.1", + "lodash.isequal": "^4.0.0", "prop-types": "^15.8.1", - "react-draggable": "^4.4.5", - "react-resizable": "^3.0.5", - "resize-observer-polyfill": "^1.5.1" + "react-draggable": "^4.0.0", + "react-resizable": "^3.0.4" }, "peerDependencies": { "react": ">= 16.3.0", "react-dom": ">= 16.3.0" } }, - "node_modules/react-grid-layout/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/react-grid-layout/node_modules/fast-equals": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", - "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", - "license": "MIT" - }, "node_modules/react-i18next": { "version": "14.1.3", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", diff --git a/client/package.json b/client/package.json index fbb9d218a..ac6f0679c 100644 --- a/client/package.json +++ b/client/package.json @@ -58,7 +58,7 @@ "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", - "react-grid-layout": "^1.5.1", + "react-grid-layout": "1.3.4", "react-i18next": "^14.1.3", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", From c568970fd828d87234278e59d4698347454dbd8e Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 14:05:21 -0400 Subject: [PATCH 25/45] IO-3183-Dependency-Updates-and-maintenance - Refactor dashboard-grid.component.jsx to separate some of the logic into componentList.js and createDashboardQuery.js --- .../dashboard-grid/componentList.js | 132 +++++++++++ .../dashboard-grid/createDashboardQuery.js | 85 +++++++ .../dashboard-grid.component.jsx | 224 +----------------- 3 files changed, 223 insertions(+), 218 deletions(-) create mode 100644 client/src/components/dashboard-grid/componentList.js create mode 100644 client/src/components/dashboard-grid/createDashboardQuery.js diff --git a/client/src/components/dashboard-grid/componentList.js b/client/src/components/dashboard-grid/componentList.js new file mode 100644 index 000000000..015d3509e --- /dev/null +++ b/client/src/components/dashboard-grid/componentList.js @@ -0,0 +1,132 @@ +import i18next from "i18next"; +import DashboardTotalProductionDollars from "../dashboard-components/total-production-dollars/total-production-dollars.component.jsx"; +import { + DashboardTotalProductionHours, + DashboardTotalProductionHoursGql +} from "../dashboard-components/total-production-hours/total-production-hours.component.jsx"; +import DashboardProjectedMonthlySales, { + DashboardProjectedMonthlySalesGql +} from "../dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx"; +import DashboardMonthlyRevenueGraph, { + DashboardMonthlyRevenueGraphGql +} from "../dashboard-components/monthly-revenue-graph/monthly-revenue-graph.component.jsx"; +import DashboardMonthlyJobCosting from "../dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx"; +import DashboardMonthlyPartsSales from "../dashboard-components/monthly-parts-sales/monthly-parts-sales.component.jsx"; +import DashboardMonthlyLaborSales from "../dashboard-components/monthly-labor-sales/monthly-labor-sales.component.jsx"; +import DashboardMonthlyEmployeeEfficiency, { + DashboardMonthlyEmployeeEfficiencyGql +} from "../dashboard-components/monthly-employee-efficiency/monthly-employee-efficiency.component.jsx"; +import DashboardScheduledInToday, { + DashboardScheduledInTodayGql +} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component.jsx"; +import DashboardScheduledOutToday, { + DashboardScheduledOutTodayGql +} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx"; +import JobLifecycleDashboardComponent, { + JobLifecycleDashboardGQL +} from "../dashboard-components/job-lifecycle/job-lifecycle-dashboard.component.jsx"; + +const componentList = { + ProductionDollars: { + label: i18next.t("dashboard.titles.productiondollars"), + component: DashboardTotalProductionDollars, + gqlFragment: null, + w: 1, + h: 1, + minW: 2, + minH: 1 + }, + ProductionHours: { + label: i18next.t("dashboard.titles.productionhours"), + component: DashboardTotalProductionHours, + gqlFragment: DashboardTotalProductionHoursGql, + w: 3, + h: 1, + minW: 3, + minH: 1 + }, + ProjectedMonthlySales: { + label: i18next.t("dashboard.titles.projectedmonthlysales"), + component: DashboardProjectedMonthlySales, + gqlFragment: DashboardProjectedMonthlySalesGql, + w: 2, + h: 1, + minW: 2, + minH: 1 + }, + MonthlyRevenueGraph: { + label: i18next.t("dashboard.titles.monthlyrevenuegraph"), + component: DashboardMonthlyRevenueGraph, + gqlFragment: DashboardMonthlyRevenueGraphGql, + w: 4, + h: 2, + minW: 4, + minH: 2 + }, + MonthlyJobCosting: { + label: i18next.t("dashboard.titles.monthlyjobcosting"), + component: DashboardMonthlyJobCosting, + gqlFragment: null, + minW: 6, + minH: 3, + w: 6, + h: 3 + }, + MonthlyPartsSales: { + label: i18next.t("dashboard.titles.monthlypartssales"), + component: DashboardMonthlyPartsSales, + gqlFragment: null, + minW: 2, + minH: 2, + w: 2, + h: 2 + }, + MonthlyLaborSales: { + label: i18next.t("dashboard.titles.monthlylaborsales"), + component: DashboardMonthlyLaborSales, + gqlFragment: null, + minW: 2, + minH: 2, + w: 2, + h: 2 + }, + // Typo in Efficency should be Efficiency, but changing it would reset users dashboard settings + MonthlyEmployeeEfficency: { + label: i18next.t("dashboard.titles.monthlyemployeeefficiency"), + component: DashboardMonthlyEmployeeEfficiency, + gqlFragment: DashboardMonthlyEmployeeEfficiencyGql, + minW: 2, + minH: 2, + w: 2, + h: 2 + }, + ScheduleInToday: { + label: i18next.t("dashboard.titles.scheduledintoday"), + component: DashboardScheduledInToday, + gqlFragment: DashboardScheduledInTodayGql, + minW: 6, + minH: 2, + w: 10, + h: 3 + }, + ScheduleOutToday: { + label: i18next.t("dashboard.titles.scheduledouttoday"), + component: DashboardScheduledOutToday, + gqlFragment: DashboardScheduledOutTodayGql, + minW: 6, + minH: 2, + w: 10, + h: 3 + }, + JobLifecycle: { + label: i18next.t("dashboard.titles.joblifecycle"), + component: JobLifecycleDashboardComponent, + gqlFragment: JobLifecycleDashboardGQL, + minW: 6, + minH: 3, + w: 6, + h: 3 + } +}; + +export default componentList; diff --git a/client/src/components/dashboard-grid/createDashboardQuery.js b/client/src/components/dashboard-grid/createDashboardQuery.js new file mode 100644 index 000000000..a37f4aa4a --- /dev/null +++ b/client/src/components/dashboard-grid/createDashboardQuery.js @@ -0,0 +1,85 @@ +import { gql } from "@apollo/client"; +import dayjs from "../../utils/day.js"; +import componentList from "./componentList.js"; + +const createDashboardQuery = (state) => { + const componentBasedAdditions = + state && + Array.isArray(state.layout) && + state.layout.map((item, index) => componentList[item.i].gqlFragment || "").join(""); + return gql` + query QUERY_DASHBOARD_DETAILS { ${componentBasedAdditions || ""} + monthly_sales: jobs(where: {_and: [ + { voided: {_eq: false}}, + {date_invoiced: {_gte: "${dayjs() + .startOf("month") + .startOf("day") + .toISOString()}"}}, {date_invoiced: {_lte: "${dayjs().endOf("month").endOf("day").toISOString()}"}}]}) { + id + ro_number + date_invoiced + job_totals + rate_la1 + rate_la2 + rate_la3 + rate_la4 + rate_laa + rate_lab + rate_lad + rate_lae + rate_laf + rate_lag + rate_lam + rate_lar + rate_las + rate_lau + rate_ma2s + rate_ma2t + rate_ma3s + rate_mabl + rate_macs + rate_mahw + rate_mapa + rate_mash + rate_matd + joblines(where: { removed: { _eq: false } }) { + id + mod_lbr_ty + mod_lb_hrs + act_price + part_qty + part_type + } + } + production_jobs: jobs(where: { inproduction: { _eq: true } }) { + id + ro_number + ins_co_nm + job_totals + joblines(where: { removed: { _eq: false } }) { + id + mod_lbr_ty + mod_lb_hrs + act_price + part_qty + part_type + } + labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" }, removed: { _eq: false } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + } + }`; +}; + +export default createDashboardQuery; diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx index 6c3412a3d..83608e830 100644 --- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx +++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx @@ -1,10 +1,8 @@ import Icon, { SyncOutlined } from "@ant-design/icons"; -import { gql, useMutation, useQuery } from "@apollo/client"; +import { useMutation, useQuery } from "@apollo/client"; import { Button, Dropdown, Space } from "antd"; import { PageHeader } from "@ant-design/pro-layout"; -import i18next from "i18next"; import _ from "lodash"; -import dayjs from "../../utils/day"; import React, { useState } from "react"; import { Responsive, WidthProvider } from "react-grid-layout"; import { useTranslation } from "react-i18next"; @@ -15,38 +13,13 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { UPDATE_DASHBOARD_LAYOUT } from "../../graphql/user.queries"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import AlertComponent from "../alert/alert.component"; -import DashboardMonthlyEmployeeEfficiency, { - DashboardMonthlyEmployeeEfficiencyGql -} from "../dashboard-components/monthly-employee-efficiency/monthly-employee-efficiency.component"; -import DashboardMonthlyJobCosting from "../dashboard-components/monthly-job-costing/monthly-job-costing.component"; -import DashboardMonthlyLaborSales from "../dashboard-components/monthly-labor-sales/monthly-labor-sales.component"; -import DashboardMonthlyPartsSales from "../dashboard-components/monthly-parts-sales/monthly-parts-sales.component"; -import DashboardMonthlyRevenueGraph, { - DashboardMonthlyRevenueGraphGql -} from "../dashboard-components/monthly-revenue-graph/monthly-revenue-graph.component"; -import DashboardProjectedMonthlySales, { - DashboardProjectedMonthlySalesGql -} from "../dashboard-components/pojected-monthly-sales/projected-monthly-sales.component"; -import DashboardTotalProductionDollars from "../dashboard-components/total-production-dollars/total-production-dollars.component"; -import DashboardTotalProductionHours, { - DashboardTotalProductionHoursGql -} from "../dashboard-components/total-production-hours/total-production-hours.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; -//Combination of the following: -// /node_modules/react-grid-layout/css/styles.css -// /node_modules/react-resizable/css/styles.css -import DashboardScheduledInToday, { - DashboardScheduledInTodayGql -} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component"; -import DashboardScheduledOutToday, { - DashboardScheduledOutTodayGql -} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component"; -import JobLifecycleDashboardComponent, { - JobLifecycleDashboardGQL -} from "../dashboard-components/job-lifecycle/job-lifecycle-dashboard.component"; -import "./dashboard-grid.styles.scss"; import { GenerateDashboardData } from "./dashboard-grid.utils"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import componentList from "./componentList.js"; +import createDashboardQuery from "./createDashboardQuery.js"; + +import "./dashboard-grid.styles.scss"; const ResponsiveReactGridLayout = WidthProvider(Responsive); @@ -54,6 +27,7 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, bodyshop: selectBodyshop }); + const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); @@ -193,189 +167,3 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { } export default connect(mapStateToProps, mapDispatchToProps)(DashboardGridComponent); - -const componentList = { - ProductionDollars: { - label: i18next.t("dashboard.titles.productiondollars"), - component: DashboardTotalProductionDollars, - gqlFragment: null, - w: 1, - h: 1, - minW: 2, - minH: 1 - }, - ProductionHours: { - label: i18next.t("dashboard.titles.productionhours"), - component: DashboardTotalProductionHours, - gqlFragment: DashboardTotalProductionHoursGql, - w: 3, - h: 1, - minW: 3, - minH: 1 - }, - ProjectedMonthlySales: { - label: i18next.t("dashboard.titles.projectedmonthlysales"), - component: DashboardProjectedMonthlySales, - gqlFragment: DashboardProjectedMonthlySalesGql, - w: 2, - h: 1, - minW: 2, - minH: 1 - }, - MonthlyRevenueGraph: { - label: i18next.t("dashboard.titles.monthlyrevenuegraph"), - component: DashboardMonthlyRevenueGraph, - gqlFragment: DashboardMonthlyRevenueGraphGql, - w: 4, - h: 2, - minW: 4, - minH: 2 - }, - MonthlyJobCosting: { - label: i18next.t("dashboard.titles.monthlyjobcosting"), - component: DashboardMonthlyJobCosting, - gqlFragment: null, - minW: 6, - minH: 3, - w: 6, - h: 3 - }, - MonthlyPartsSales: { - label: i18next.t("dashboard.titles.monthlypartssales"), - component: DashboardMonthlyPartsSales, - gqlFragment: null, - minW: 2, - minH: 2, - w: 2, - h: 2 - }, - MonthlyLaborSales: { - label: i18next.t("dashboard.titles.monthlylaborsales"), - component: DashboardMonthlyLaborSales, - gqlFragment: null, - minW: 2, - minH: 2, - w: 2, - h: 2 - }, - // Typo in Efficency should be Efficiency, but changing it would reset users dashboard settings - MonthlyEmployeeEfficency: { - label: i18next.t("dashboard.titles.monthlyemployeeefficiency"), - component: DashboardMonthlyEmployeeEfficiency, - gqlFragment: DashboardMonthlyEmployeeEfficiencyGql, - minW: 2, - minH: 2, - w: 2, - h: 2 - }, - ScheduleInToday: { - label: i18next.t("dashboard.titles.scheduledintoday"), - component: DashboardScheduledInToday, - gqlFragment: DashboardScheduledInTodayGql, - minW: 6, - minH: 2, - w: 10, - h: 3 - }, - ScheduleOutToday: { - label: i18next.t("dashboard.titles.scheduledouttoday"), - component: DashboardScheduledOutToday, - gqlFragment: DashboardScheduledOutTodayGql, - minW: 6, - minH: 2, - w: 10, - h: 3 - }, - JobLifecycle: { - label: i18next.t("dashboard.titles.joblifecycle"), - component: JobLifecycleDashboardComponent, - gqlFragment: JobLifecycleDashboardGQL, - minW: 6, - minH: 3, - w: 6, - h: 3 - } -}; - -const createDashboardQuery = (state) => { - const componentBasedAdditions = - state && - Array.isArray(state.layout) && - state.layout.map((item, index) => componentList[item.i].gqlFragment || "").join(""); - return gql` - query QUERY_DASHBOARD_DETAILS { ${componentBasedAdditions || ""} - monthly_sales: jobs(where: {_and: [ - { voided: {_eq: false}}, - {date_invoiced: {_gte: "${dayjs() - .startOf("month") - .startOf("day") - .toISOString()}"}}, {date_invoiced: {_lte: "${dayjs() - .endOf("month") - .endOf("day") - .toISOString()}"}}]}) { - id - ro_number - date_invoiced - job_totals - rate_la1 - rate_la2 - rate_la3 - rate_la4 - rate_laa - rate_lab - rate_lad - rate_lae - rate_laf - rate_lag - rate_lam - rate_lar - rate_las - rate_lau - rate_ma2s - rate_ma2t - rate_ma3s - rate_mabl - rate_macs - rate_mahw - rate_mapa - rate_mash - rate_matd - joblines(where: { removed: { _eq: false } }) { - id - mod_lbr_ty - mod_lb_hrs - act_price - part_qty - part_type - } - } - production_jobs: jobs(where: { inproduction: { _eq: true } }) { - id - ro_number - ins_co_nm - job_totals - joblines(where: { removed: { _eq: false } }) { - id - mod_lbr_ty - mod_lb_hrs - act_price - part_qty - part_type - } - labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) { - aggregate { - sum { - mod_lb_hrs - } - } - } - larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" }, removed: { _eq: false } }) { - aggregate { - sum { - mod_lb_hrs - } - } - } - } - }`; -}; From 3b21c603f6a068661c4cb7cbf752924dd21b13e8 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 14:09:21 -0400 Subject: [PATCH 26/45] IO-3183-Dependency-Updates-and-maintenance - Cleaning dashboard-grid.component.jsx --- .../dashboard-grid/dashboard-grid.component.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx index 83608e830..1fd97ceb1 100644 --- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx +++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx @@ -2,8 +2,7 @@ import Icon, { SyncOutlined } from "@ant-design/icons"; import { useMutation, useQuery } from "@apollo/client"; import { Button, Dropdown, Space } from "antd"; import { PageHeader } from "@ant-design/pro-layout"; -import _ from "lodash"; -import React, { useState } from "react"; +import { useMemo, useState } from "react"; import { Responsive, WidthProvider } from "react-grid-layout"; import { useTranslation } from "react-i18next"; import { MdClose } from "react-icons/md"; @@ -20,6 +19,7 @@ import componentList from "./componentList.js"; import createDashboardQuery from "./createDashboardQuery.js"; import "./dashboard-grid.styles.scss"; +import cloneDeep from "lodash/cloneDeep"; const ResponsiveReactGridLayout = WidthProvider(Responsive); @@ -71,7 +71,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { logImEXEvent("dashboard_remove_component", { name: key }); const idxToRemove = state.items.findIndex((i) => i.i === key); - const items = _.cloneDeep(state.items); + const items = cloneDeep(state.items); items.splice(idxToRemove, 1); setState({ ...state, items }); @@ -94,7 +94,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { }); }; - const dashboarddata = React.useMemo(() => GenerateDashboardData(data), [data]); + const dashboardData = useMemo(() => GenerateDashboardData(data), [data]); const existingLayoutKeys = state.items.map((i) => i.i); const menuItems = Object.keys(componentList).map((key) => ({ @@ -156,7 +156,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { }} onClick={() => handleRemoveComponent(item.i)} /> - +
); From e36bb65e4c6cf661d5637dfce2713a2203fab02f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 14:14:24 -0400 Subject: [PATCH 27/45] IO-3183-Dependency-Updates-and-maintenance - Cleaning dashboard-grid.component.jsx --- .../components/dashboard-grid/dashboard-grid.component.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx index 1fd97ceb1..70800158a 100644 --- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx +++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx @@ -1,4 +1,5 @@ import Icon, { SyncOutlined } from "@ant-design/icons"; +import { isEmpty, cloneDeep } from "lodash"; import { useMutation, useQuery } from "@apollo/client"; import { Button, Dropdown, Space } from "antd"; import { PageHeader } from "@ant-design/pro-layout"; @@ -19,7 +20,6 @@ import componentList from "./componentList.js"; import createDashboardQuery from "./createDashboardQuery.js"; import "./dashboard-grid.styles.scss"; -import cloneDeep from "lodash/cloneDeep"; const ResponsiveReactGridLayout = WidthProvider(Responsive); @@ -59,8 +59,8 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { layout: { ...state, layout, layouts } } }); - if (!!result.errors) { - notification["error"]({ + if (!isEmpty(result?.errors)) { + notification.error({ message: t("dashboard.errors.updatinglayout", { message: JSON.stringify(result.errors) }) From b5611c8470f9bc66a67468e8fa725dc6e2400a51 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 14:16:25 -0400 Subject: [PATCH 28/45] IO-3183-Dependency-Updates-and-maintenance - Cleaning dashboard-grid.component.jsx --- .../components/dashboard-grid/dashboard-grid.component.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx index 70800158a..082e404ac 100644 --- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx +++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx @@ -59,6 +59,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { layout: { ...state, layout, layouts } } }); + if (!isEmpty(result?.errors)) { notification.error({ message: t("dashboard.errors.updatinglayout", { @@ -67,6 +68,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { }); } }; + const handleRemoveComponent = (key) => { logImEXEvent("dashboard_remove_component", { name: key }); const idxToRemove = state.items.findIndex((i) => i.i === key); @@ -95,6 +97,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { }; const dashboardData = useMemo(() => GenerateDashboardData(data), [data]); + const existingLayoutKeys = state.items.map((i) => i.i); const menuItems = Object.keys(componentList).map((key) => ({ @@ -130,7 +133,6 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { width="100%" layouts={state.layouts} onLayoutChange={handleLayoutChange} - // onBreakpointChange={onBreakpointChange} > {state.items.map((item, index) => { const TheComponent = componentList[item.i].component; From c9cc9d2df38d1262009cdbdc511371e85d33abfe Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 14:26:32 -0400 Subject: [PATCH 29/45] IO-3183-Dependency-Updates-and-maintenance - Cleaning dashboard-grid.component.jsx --- server/routes/smsRoutes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/routes/smsRoutes.js b/server/routes/smsRoutes.js index bb23d24e8..1b169747d 100644 --- a/server/routes/smsRoutes.js +++ b/server/routes/smsRoutes.js @@ -7,6 +7,7 @@ const { status, markConversationRead } = require("../sms/status"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); // Twilio Webhook Middleware for production +// TODO: Look into this because it technically is never validating anything const twilioWebhookMiddleware = twilio.webhook({ validate: process.env.NODE_ENV === "PRODUCTION" }); router.post("/receive", twilioWebhookMiddleware, receive); From aaf966e721bc6635a471c8f3d97843272467e3ce Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 15:01:18 -0400 Subject: [PATCH 30/45] IO-3183-Dependency-Updates-and-maintenance - remove userpilot, update i18next , logrocket, react-cookie, react-i18next, react-markdown --- client/package-lock.json | 267 ++++++++++++++++++------------- client/package.json | 13 +- client/src/App/App.container.jsx | 6 - 3 files changed, 159 insertions(+), 127 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 03db0e103..66e922267 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -40,11 +40,11 @@ "env-cmd": "^10.1.0", "exifr": "^7.1.3", "graphql": "^16.10.0", - "i18next": "^23.15.1", + "i18next": "^24.2.3", "i18next-browser-languagedetector": "^8.0.4", "immutability-helper": "^3.1.1", "libphonenumber-js": "^1.12.6", - "logrocket": "^8.1.2", + "logrocket": "^9.0.2", "markerjs2": "^2.32.4", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", @@ -55,15 +55,15 @@ "react": "^18.3.1", "react-big-calendar": "^1.18.0", "react-color": "^2.19.3", - "react-cookie": "^7.2.2", + "react-cookie": "^8.0.1", "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "1.3.4", - "react-i18next": "^14.1.3", + "react-i18next": "^15.4.1", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", - "react-markdown": "^9.0.3", + "react-markdown": "^10.1.0", "react-number-format": "^5.4.3", "react-popopo": "^2.1.9", "react-product-fruits": "^2.2.61", @@ -84,12 +84,11 @@ "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.9", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, "devDependencies": { - "@ant-design/icons": "^5.6.1", + "@ant-design/icons": "^6.0.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", "@dotenvx/dotenvx": "^1.39.0", @@ -193,16 +192,16 @@ } }, "node_modules/@ant-design/icons": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", - "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-6.0.0.tgz", + "integrity": "sha512-o0aCCAlHc1o4CQcapAwWzHeaW2x9F49g7P3IDtvtNXgHowtRWYb7kiubt8sQPFvfVIVU/jLw2hzeSlNt0FU+Uw==", + "dev": true, "license": "MIT", "dependencies": { - "@ant-design/colors": "^7.0.0", + "@ant-design/colors": "^8.0.0", "@ant-design/icons-svg": "^4.4.0", - "@babel/runtime": "^7.24.8", - "classnames": "^2.2.6", - "rc-util": "^5.31.1" + "@rc-component/util": "^1.2.1", + "classnames": "^2.2.6" }, "engines": { "node": ">=8" @@ -218,6 +217,26 @@ "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", "license": "MIT" }, + "node_modules/@ant-design/icons/node_modules/@ant-design/colors": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-8.0.0.tgz", + "integrity": "sha512-6YzkKCw30EI/E9kHOIXsQDHmMvTllT8STzjMb4K2qzit33RW2pqCJP0sk+hidBntXxE+Vz4n1+RvCTfBw6OErw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^3.0.0" + } + }, + "node_modules/@ant-design/icons/node_modules/@ant-design/fast-color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.0.tgz", + "integrity": "sha512-eqvpP7xEDm2S7dUzl5srEQCBTXZMmY3ekf97zI+M2DHOYyKdJGH0qua0JACHTqbkRnD/KHFQP9J1uMJ/XWVzzA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.x" + } + }, "node_modules/@ant-design/pro-layout": { "version": "7.22.3", "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.22.3.tgz", @@ -246,6 +265,26 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-layout/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/pro-provider": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.15.3.tgz", @@ -288,6 +327,26 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-utils/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/react-slick": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", @@ -2279,9 +2338,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -3479,36 +3538,6 @@ "integrity": "sha512-AAeTkqyVJGdWLCA60aHDrh3s8h9z8TokyoR1tCpNtYatfe2cdocVdB0AaNquWTmddRWgAklmOBrowsMFQFY8hg==", "license": "MIT" }, - "node_modules/@ndhoule/each": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@ndhoule/each/-/each-2.0.1.tgz", - "integrity": "sha512-wHuJw6x+rF6Q9Skgra++KccjBozCr9ymtna0FhxmV/8xT/hZ2ExGYR8SV8prg8x4AH/7mzDYErNGIVHuzHeybw==", - "license": "MIT", - "dependencies": { - "@ndhoule/keys": "^2.0.0" - } - }, - "node_modules/@ndhoule/includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@ndhoule/includes/-/includes-2.0.1.tgz", - "integrity": "sha512-Q8zN6f3yIhxgBwZ5ldLozHqJlc/fRQ5+hFFsPMFeC9SJvz0nq8vG9hoRXL1c1iaNFQd7yAZIy2igQpERoFqxqg==", - "license": "MIT", - "dependencies": { - "@ndhoule/each": "^2.0.1" - } - }, - "node_modules/@ndhoule/keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ndhoule/keys/-/keys-2.0.0.tgz", - "integrity": "sha512-vtCqKBC1Av6dsBA8xpAO+cgk051nfaI+PnmTZep2Px0vYrDvpUmLxv7z40COlWH5yCpu3gzNhepk+02yiQiZNw==", - "license": "MIT" - }, - "node_modules/@ndhoule/pick": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ndhoule/pick/-/pick-2.0.0.tgz", - "integrity": "sha512-xkYtpf1pRd8egwvl5tJcdGu+GBd6ZZH3S/zoIQ9txEI+pHF9oTIlxMC9G4CB3sRugAeLgu8qYJGl3tnxWq74Qw==", - "license": "MIT" - }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4142,6 +4171,27 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@rc-component/util": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.2.1.tgz", + "integrity": "sha512-AUVu6jO+lWjQnUOOECwu8iR0EdElQgWW5NBv5vP/Uf9dWbAX3udhMutRlkVXjuac2E40ghkFy+ve00mc/3Fymg==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/@redux-saga/core": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.3.0.tgz", @@ -5412,12 +5462,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", @@ -6141,6 +6185,26 @@ "react-dom": ">=16.9.0" } }, + "node_modules/antd/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -7324,11 +7388,6 @@ "node": ">=4.0.0" } }, - "node_modules/component-indexof": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz", - "integrity": "sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==" - }, "node_modules/compute-scroll-into-view": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", @@ -7388,12 +7447,12 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" } }, "node_modules/copy-to-clipboard": { @@ -10056,9 +10115,9 @@ } }, "node_modules/i18next": { - "version": "23.16.8", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", - "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", + "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", "funding": [ { "type": "individual", @@ -10075,7 +10134,15 @@ ], "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2" + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/i18next-browser-languagedetector": { @@ -10255,15 +10322,6 @@ "url": "https://opencollective.com/ioredis" } }, - "node_modules/is": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", - "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -11255,9 +11313,9 @@ "license": "MIT" }, "node_modules/logrocket": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-8.1.3.tgz", - "integrity": "sha512-lWuFhkWYMtARJ2BZUrxP54Dtn3TskpLZ0kDhp14BkrapFQihcN0GB8pvy2vP1OdRFFVh3pAG7AWo/BUbQ9SIbg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-9.0.2.tgz", + "integrity": "sha512-DscsCEi9PLEEXPXWOsf+BGsmwZGIFzn9Ixo+lTezFpR2o3xzZxD7Qz3FWecYYuci6SKvalVciy6msVvMjD16PA==", "license": "MIT" }, "node_modules/long": { @@ -12348,12 +12406,6 @@ "node": ">=8" } }, - "node_modules/obj-case": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/obj-case/-/obj-case-0.2.1.tgz", - "integrity": "sha512-PquYBBTy+Y6Ob/O2574XHhDtHJlV1cJHMCgW+rDRc9J5hhmRelJB3k5dTK/3cVmFVtzvAKuENeuLpoyTzMzkOg==", - "license": "MIT" - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -13873,14 +13925,14 @@ } }, "node_modules/react-cookie": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.2.2.tgz", - "integrity": "sha512-e+hi6axHcw9VODoeVu8WyMWyoosa1pzpyjfvrLdF7CexfU+WSGZdDuRfHa4RJgTpfv3ZjdIpHE14HpYBieHFhg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-8.0.1.tgz", + "integrity": "sha512-QNdAd0MLuAiDiLcDU/2s/eyKmmfMHtjPUKJ2dZ/5CcQ9QKUium4B3o61/haq6PQl/YWFqC5PO8GvxeHKhy3GFA==", "license": "MIT", "dependencies": { - "@types/hoist-non-react-statics": "^3.3.5", + "@types/hoist-non-react-statics": "^3.3.6", "hoist-non-react-statics": "^3.3.2", - "universal-cookie": "^7.0.0" + "universal-cookie": "^8.0.0" }, "peerDependencies": { "react": ">= 16.3.0" @@ -13957,12 +14009,12 @@ } }, "node_modules/react-i18next": { - "version": "14.1.3", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", - "integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.1.tgz", + "integrity": "sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", + "@babel/runtime": "^7.25.0", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { @@ -14015,12 +14067,13 @@ "license": "MIT" }, "node_modules/react-markdown": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.3.tgz", - "integrity": "sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", @@ -16546,13 +16599,12 @@ } }, "node_modules/universal-cookie": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.2.2.tgz", - "integrity": "sha512-fMiOcS3TmzP2x5QV26pIH3mvhexLIT0HmPa3V7Q7knRfT9HG6kTwq02HZGLPw0sAOXrAmotElGRvTLCMbJsvxQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-8.0.1.tgz", + "integrity": "sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg==", "license": "MIT", "dependencies": { - "@types/cookie": "^0.6.0", - "cookie": "^0.7.2" + "cookie": "^1.0.2" } }, "node_modules/universalify": { @@ -16757,19 +16809,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/userpilot": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.9.tgz", - "integrity": "sha512-V0QIuIlAJPB8s3j+qtv7BW7NKSXthlZWuowIu+IZOMGLgUbqQTaSW5m1Ct4wJviPKUNOi8kbhCXN4c4b3zcJzg==", - "license": "MIT", - "dependencies": { - "@ndhoule/includes": "^2.0.1", - "@ndhoule/pick": "^2.0.0", - "component-indexof": "0.0.3", - "is": "^3.1.0", - "obj-case": "^0.2.0" - } - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/client/package.json b/client/package.json index ac6f0679c..30d26ffc7 100644 --- a/client/package.json +++ b/client/package.json @@ -39,11 +39,11 @@ "env-cmd": "^10.1.0", "exifr": "^7.1.3", "graphql": "^16.10.0", - "i18next": "^23.15.1", + "i18next": "^24.2.3", "i18next-browser-languagedetector": "^8.0.4", "immutability-helper": "^3.1.1", "libphonenumber-js": "^1.12.6", - "logrocket": "^8.1.2", + "logrocket": "^9.0.2", "markerjs2": "^2.32.4", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", @@ -54,15 +54,15 @@ "react": "^18.3.1", "react-big-calendar": "^1.18.0", "react-color": "^2.19.3", - "react-cookie": "^7.2.2", + "react-cookie": "^8.0.1", "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "1.3.4", - "react-i18next": "^14.1.3", + "react-i18next": "^15.4.1", "react-icons": "^5.5.0", "react-image-lightbox": "^5.1.4", - "react-markdown": "^9.0.3", + "react-markdown": "^10.1.0", "react-number-format": "^5.4.3", "react-popopo": "^2.1.9", "react-product-fruits": "^2.2.61", @@ -83,7 +83,6 @@ "styled-components": "^6.1.16", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.9", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, @@ -123,7 +122,7 @@ "@rollup/rollup-linux-x64-gnu": "4.6.1" }, "devDependencies": { - "@ant-design/icons": "^5.6.1", + "@ant-design/icons": "^6.0.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.26.3", "@dotenvx/dotenvx": "^1.39.0", diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx index 0f3559d2c..67fd0f444 100644 --- a/client/src/App/App.container.jsx +++ b/client/src/App/App.container.jsx @@ -10,12 +10,6 @@ import client from "../utils/GraphQLClient"; import App from "./App"; import * as Sentry from "@sentry/react"; import themeProvider from "./themeProvider"; -import { Userpilot } from "userpilot"; - -// Initialize Userpilot -if (import.meta.env.DEV) { - Userpilot.initialize("NX-69145f08"); -} // Base Split configuration const config = { From 1b5ae29078c56b5cace16a3743269f7004f3cf41 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 24 Mar 2025 15:34:32 -0400 Subject: [PATCH 31/45] IO-3183-Dependency-Updates-and-maintenance - Remove concurrently, clean up scripts in both package.json`s --- client/package.json | 1 - package-lock.json | 71 +++------------------------------------------ package.json | 7 ----- 3 files changed, 4 insertions(+), 75 deletions(-) diff --git a/client/package.json b/client/package.json index 30d26ffc7..f7e354160 100644 --- a/client/package.json +++ b/client/package.json @@ -99,7 +99,6 @@ "build:test:rome": "env-cmd -f .env.test.rome npm run build", "build:production:imex": "env-cmd -f .env.production.imex npm run build", "build:production:rome": "env-cmd -f .env.production.rome npm run build", - "eject": "react-scripts eject", "madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .", "eulaize": "node src/utils/eulaize.js" }, diff --git a/package-lock.json b/package-lock.json index 0db4ef983..76296e97b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,7 +70,6 @@ "devDependencies": { "@eslint/js": "^9.23.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "concurrently": "^9.1.2", "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", @@ -4308,8 +4307,8 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "devOptional": true, "license": "ISC", + "optional": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4323,8 +4322,8 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "devOptional": true, "license": "MIT", + "optional": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4548,32 +4547,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/concurrently": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", - "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -9363,16 +9336,6 @@ "integrity": "sha512-c5ouQkOvGHF1qomUUDJGFcXsomeSO2gbEs6hVhMAtlkE1CuaZase/WzoaKFG/EZQuNmq6pw/EMCeEnDvOgCJYQ==", "license": "MIT" }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-array-concat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", @@ -10433,22 +10396,6 @@ "pick-util": "^1.1.5" } }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -10608,16 +10555,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/triple-beam": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", @@ -11526,8 +11463,8 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "devOptional": true, "license": "MIT", + "optional": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -11545,8 +11482,8 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "devOptional": true, "license": "ISC", + "optional": true, "engines": { "node": ">=12" } diff --git a/package.json b/package.json index 7567e361b..4de2904c0 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,6 @@ "scripts": { "setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i", "setup:win": "rimraf node_modules && npm i && cd client && rimraf node_modules && npm i", - "admin": "cd admin && npm start", - "client": "cd client && npm start", - "server": "nodemon server.js", - "build": "cd client && npm run build", - "dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"", - "deva": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\" \"npm run admin\"", "start": "node server.js", "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" }, @@ -80,7 +74,6 @@ "devDependencies": { "@eslint/js": "^9.23.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", - "concurrently": "^9.1.2", "eslint": "^9.23.0", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", From f485951a4c4f39043d77d47a48fa894ad943d22d Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Mon, 24 Mar 2025 12:47:51 -0700 Subject: [PATCH 32/45] IO-3178 Requested Changes for Flat Rate ATS Signed-off-by: Allan Carr --- server/job/job-totals-USA.js | 9 +++++---- server/job/job-totals.js | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index 6835dc7cb..dd850dc9b 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -139,7 +139,7 @@ async function Totals(req, res) { const logger = req.logger; const client = req.userGraphQLClient; - logger.log("job-totals-USA", "DEBUG", req.user.email, job.id, { + logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, { jobid: job.id, id: id }); @@ -156,7 +156,7 @@ async function Totals(req, res) { res.status(200).json(ret); } catch (error) { - logger.log("job-totals-USA-error", "ERROR", req.user.email, job.id, { + logger.log("job-totals-ssu-USA-error", "ERROR", req.user.email, job.id, { jobid: job.id, error: error.message, stack: error.stack @@ -258,6 +258,8 @@ async function AtsAdjustmentsIfRequired({ job, client, user }) { logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { jobid: job.id, atsLineIndex: atsLineIndex, + atsAmount: atsAmount, + jobline: job.joblines[atsLineIndex], error: error.message, stack: error.stack }); @@ -1189,9 +1191,8 @@ function CalculateTaxesTotals(job, otherTotals) { exports.default = Totals; +//eslint-disable-next-line no-unused-vars function DiscountNotAlreadyCounted(jobline, joblines) { - void jobline; - void joblines; return false; } diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 0a160426d..6182f9ced 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -87,7 +87,7 @@ async function Totals(req, res) { const logger = req.logger; const client = req.userGraphQLClient; - logger.log("job-totals-", "DEBUG", req.user.email, job.id, { + logger.log("job-totals-ssu", "DEBUG", req.user.email, job.id, { jobid: job.id, id: id }); @@ -104,7 +104,7 @@ async function Totals(req, res) { res.status(200).json(ret); } catch (error) { - logger.log("job-totals-error", "ERROR", req.user.email, job.id, { + logger.log("job-totals-ssu-error", "ERROR", req.user.email, job.id, { jobid: job.id, error: error.message, stack: error.stack @@ -206,6 +206,8 @@ async function AtsAdjustmentsIfRequired({ job, client, user }) { logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, { jobid: job.id, atsLineIndex: atsLineIndex, + atsAmount: atsAmount, + jobline: job.joblines[atsLineIndex], error: error.message, stack: error.stack }); From b88795078cc120eba94ab277b739cf418b9dd5e2 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Mon, 24 Mar 2025 18:16:31 -0700 Subject: [PATCH 33/45] IO-3185 Job Drawer Suspend Job Signed-off-by: Allan Carr --- .../job-detail-cards.component.jsx | 53 ++++++++++++++---- .../production-list-detail.component.jsx | 54 +++++++++++++++---- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/client/src/components/job-detail-cards/job-detail-cards.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.component.jsx index ea66c9112..5e5df5b58 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.component.jsx @@ -1,17 +1,21 @@ -import { PrinterFilled } from "@ant-design/icons"; -import { useQuery } from "@apollo/client"; +import { PauseCircleOutlined, PlayCircleOutlined, PrinterFilled } from "@ant-design/icons"; +import { useMutation, useQuery } from "@apollo/client"; import { Button, Card, Col, Divider, Drawer, Grid, Row, Space } from "antd"; import queryString from "query-string"; -import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries"; +import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { logImEXEvent } from "../../firebase/firebase.utils"; +import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions.js"; import { setModalContext } from "../../redux/modals/modals.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings.js"; import AlertComponent from "../alert/alert.component"; import JobSyncButton from "../job-sync-button/job-sync-button.component"; +import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx"; import JobsDetailHeader from "../jobs-detail-header/jobs-detail-header.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import JobDetailCardsDamageComponent from "./job-detail-cards.damage.component"; @@ -21,15 +25,21 @@ import JobDetailCardsInsuranceComponent from "./job-detail-cards.insurance.compo import JobDetailCardsNotesComponent from "./job-detail-cards.notes.component"; import JobDetailCardsPartsComponent from "./job-detail-cards.parts.component"; import JobDetailCardsTotalsComponent from "./job-detail-cards.totals.component"; -import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); const mapDispatchToProps = (dispatch) => ({ - setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })) + setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch( + insertAuditTrail({ + jobid, + operation, + type + }) + ) }); const span = { @@ -38,8 +48,9 @@ const span = { xxl: { span: 8 } }; -export function JobDetailCards({ bodyshop, setPrintCenterContext }) { +export function JobDetailCards({ bodyshop, setPrintCenterContext, insertAuditTrail }) { const { scenarioNotificationsOn } = useSocket(); + const [updateJob] = useMutation(UPDATE_JOB); const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) .filter((screen) => !!screen[1]) .slice(-1)[0]; @@ -91,7 +102,29 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) { extra={ - + diff --git a/client/src/components/production-list-detail/production-list-detail.component.jsx b/client/src/components/production-list-detail/production-list-detail.component.jsx index ea2d6ef67..7db55bd07 100644 --- a/client/src/components/production-list-detail/production-list-detail.component.jsx +++ b/client/src/components/production-list-detail/production-list-detail.component.jsx @@ -1,17 +1,20 @@ -import { PrinterFilled } from "@ant-design/icons"; -import { useQuery } from "@apollo/client"; -import { Button, Descriptions, Drawer, Space } from "antd"; +import { PauseCircleOutlined, PlayCircleOutlined, PrinterFilled } from "@ant-design/icons"; import { PageHeader } from "@ant-design/pro-layout"; +import { useMutation, useQuery } from "@apollo/client"; +import { Button, Descriptions, Drawer, Space } from "antd"; import queryString from "query-string"; -import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries"; +import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; +import { logImEXEvent } from "../../firebase/firebase.utils.js"; +import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions.js"; import { setModalContext } from "../../redux/modals/modals.actions"; import { selectTechnician } from "../../redux/tech/tech.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings.js"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; import PhoneNumberFormatter from "../../utils/PhoneFormatter"; @@ -24,22 +27,29 @@ import JobDetailCardsPartsComponent from "../job-detail-cards/job-detail-cards.p import CardTemplate from "../job-detail-cards/job-detail-cards.template.component"; import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container"; import ScoreboardAddButton from "../job-scoreboard-add-button/job-scoreboard-add-button.component"; +import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import ProductionRemoveButton from "../production-remove-button/production-remove-button.component"; -import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx"; -import { useSocket } from "../../contexts/SocketIO/useSocket.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, technician: selectTechnician }); const mapDispatchToProps = (dispatch) => ({ - setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })) + setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch( + insertAuditTrail({ + jobid, + operation, + type + }) + ) }); export default connect(mapStateToProps, mapDispatchToProps)(ProductionListDetail); -export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, technician }) { +export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, technician, insertAuditTrail }) { const search = queryString.parse(useLocation().search); const history = useNavigate(); const { selected } = search; @@ -58,6 +68,7 @@ export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, te fetchPolicy: "network-only", nextFetchPolicy: "network-only" }); + const [updateJob] = useMutation(UPDATE_JOB); return ( {!technician ? : null} + {!technician && ( + + )} {!technician ? : null} From 517eca0900aea5835983cf4a36f82c4e748106ea Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 25 Mar 2025 14:53:09 -0400 Subject: [PATCH 34/45] Revert "Merge remote-tracking branch 'origin/release/2025-02-28' into feature/IO-3092-imgproxy" This reverts commit ba9b248b1f46fa2a36d6f3cdf4435db77e449f81, reversing changes made to 0810798d3019afba5591d334c8d685d494c4495c. --- .../parts-order-modal.component.jsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/components/parts-order-modal/parts-order-modal.component.jsx b/client/src/components/parts-order-modal/parts-order-modal.component.jsx index 4fc3a5789..c3ade9187 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.component.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.component.jsx @@ -1,16 +1,17 @@ import { DeleteFilled, DownOutlined, WarningFilled } from "@ant-design/icons"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { Checkbox, Divider, Dropdown, Form, Input, InputNumber, Radio, Select, Space, Tag } from "antd"; +import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component"; import PartsOrderModalPriceChange from "./parts-order-modal-price-change.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -32,7 +33,7 @@ export function PartsOrderModalComponent({ bodyshop, vendorList, sendTypeState, }); const { t } = useTranslation(); - const handleClick = ({ item }) => { + const handleClick = ({ item, key, keyPath }) => { form.setFieldsValue({ comments: item.props.value }); }; @@ -97,18 +98,17 @@ export function PartsOrderModalComponent({ bodyshop, vendorList, sendTypeState, )} - {!isReturn && ( - - - {t("parts_orders.labels.parts_order")} - {t("parts_orders.labels.sublet_order")} - - - )} + + + + {t("parts_orders.labels.parts_order")} + {t("parts_orders.labels.sublet_order")} + + {t("parts_orders.labels.inthisorder")} - {(fields, { remove, move }) => { + {(fields, { add, remove, move }) => { return (
{fields.map((field, index) => ( From 02f5f1985ca089e7752c9d63a9c3d2fbc05ced3b Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 25 Mar 2025 15:01:50 -0400 Subject: [PATCH 35/45] release/2025-03-28 - Up two deps --- package-lock.json | 138 ++++++++-------------------------------------- package.json | 4 +- 2 files changed, 26 insertions(+), 116 deletions(-) diff --git a/package-lock.json b/package-lock.json index 66794a554..806ee2a13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,8 @@ "@aws-sdk/client-secrets-manager": "^3.772.0", "@aws-sdk/client-ses": "^3.772.0", "@aws-sdk/credential-provider-node": "^3.772.0", - "@aws-sdk/lib-storage": "^3.743.0", - "@aws-sdk/s3-request-presigner": "^3.731.1", + "@aws-sdk/lib-storage": "^3.774.0", + "@aws-sdk/s3-request-presigner": "^3.774.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", @@ -798,14 +798,14 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.743.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.743.0.tgz", - "integrity": "sha512-Rf/5sljlEJRVtB5C4UjLCOIcK2ODZet9rQsRtsn0bIc2byURbpOdqIGvfEcKWPayoXCS4dC/5bdjhL1zhZ0TMg==", + "version": "3.774.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.774.0.tgz", + "integrity": "sha512-xB3rD+F5pt+JLJaUt5eakCJ3+CUa8PXk9nxgN2VozfpuvuR6A/l3lnxmP5wYLhw1I9hxJLV9AD1/QYcibdBjtQ==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.2", - "@smithy/smithy-client": "^4.1.2", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/smithy-client": "^4.1.6", "buffer": "5.6.0", "events": "3.3.0", "stream-browserify": "3.0.0", @@ -815,7 +815,7 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.743.0" + "@aws-sdk/client-s3": "^3.774.0" } }, "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { @@ -1067,95 +1067,18 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.731.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.731.1.tgz", - "integrity": "sha512-GdG0pXkcTgBpenouB834FoCHyLaivV2rGQn7OEQBiT8SBaTxSackZ6tGlJQAlzZQkiQfE/NePUJU7DczJZZvrg==", + "version": "3.774.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.774.0.tgz", + "integrity": "sha512-vD37Nq7+ChUkXSoDqkNMXu37R8kRDUo13pOfYgesSI4HA970fjXP1T4Mf2131Ms/NuYbBHNn330+3MAkbbYKxg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.731.0", - "@aws-sdk/types": "3.731.0", - "@aws-sdk/util-format-url": "3.731.0", - "@smithy/middleware-endpoint": "^4.0.0", - "@smithy/protocol-http": "^5.0.0", - "@smithy/smithy-client": "^4.0.0", - "@smithy/types": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/core": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.731.0.tgz", - "integrity": "sha512-ithBN1VWASkvAIlozJmenqDvNnFddr/SZXAs58+jCnBHgy3tXLHABZGVNCjetZkHRqNdXEO1kirnoxaFeXMeDA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.731.0", - "@smithy/core": "^3.0.0", - "@smithy/node-config-provider": "^4.0.0", - "@smithy/property-provider": "^4.0.0", - "@smithy/protocol-http": "^5.0.0", - "@smithy/signature-v4": "^5.0.0", - "@smithy/smithy-client": "^4.0.0", - "@smithy/types": "^4.0.0", - "@smithy/util-middleware": "^4.0.0", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.731.0.tgz", - "integrity": "sha512-J9aKyQaVoec5eWTSDfO4h2sKHNP0wTzN15LFcHnkD+e/d0rdmOi7BTkkbJrIaynma9WShIasmrtM3HNi9GiiTA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.731.0", - "@aws-sdk/types": "3.731.0", - "@aws-sdk/util-arn-parser": "3.723.0", - "@smithy/core": "^3.0.0", - "@smithy/node-config-provider": "^4.0.0", - "@smithy/protocol-http": "^5.0.0", - "@smithy/signature-v4": "^5.0.0", - "@smithy/smithy-client": "^4.0.0", - "@smithy/types": "^4.0.0", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.0", - "@smithy/util-stream": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.731.0.tgz", - "integrity": "sha512-1r/b4Os15dR+BCVRRLVQJMF7Krq6xX6IKHxN43kuvODYWz8Nv3XDlaSpeRpAzyJuzW/fTp4JgE+z0+gmJfdEeA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.731.0", - "@aws-sdk/types": "3.731.0", - "@smithy/protocol-http": "^5.0.0", - "@smithy/signature-v4": "^5.0.0", - "@smithy/types": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/types": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.731.0.tgz", - "integrity": "sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.0.0", + "@aws-sdk/signature-v4-multi-region": "3.774.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-format-url": "3.734.0", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, "engines": { @@ -1237,27 +1160,14 @@ } }, "node_modules/@aws-sdk/util-format-url": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.731.0.tgz", - "integrity": "sha512-wZHObjnYmiz8wFlUQ4/5dHsT7k0at+GvZM02LgvshcRJLnFjYdrzjelMKuNynd/NNK3gLgTsFTGuIgPpz9r4rA==", + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.734.0.tgz", + "integrity": "sha512-TxZMVm8V4aR/QkW9/NhujvYpPZjUYqzLwSge5imKZbWFR806NP7RMwc5ilVuHF/bMOln/cVHkl42kATElWBvNw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.731.0", - "@smithy/querystring-builder": "^4.0.0", - "@smithy/types": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-format-url/node_modules/@aws-sdk/types": { - "version": "3.731.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.731.0.tgz", - "integrity": "sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.0.0", + "@aws-sdk/types": "3.734.0", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, "engines": { diff --git a/package.json b/package.json index 05a8eb327..9f2bf57f2 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "@aws-sdk/client-secrets-manager": "^3.772.0", "@aws-sdk/client-ses": "^3.772.0", "@aws-sdk/credential-provider-node": "^3.772.0", - "@aws-sdk/lib-storage": "^3.743.0", - "@aws-sdk/s3-request-presigner": "^3.731.1", + "@aws-sdk/lib-storage": "^3.774.0", + "@aws-sdk/s3-request-presigner": "^3.774.0", "@opensearch-project/opensearch": "^2.13.0", "@socket.io/admin-ui": "^0.5.1", "@socket.io/redis-adapter": "^8.3.0", From 46999145fcda90ed42b60d04d9b455277d067061 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 25 Mar 2025 16:38:03 -0400 Subject: [PATCH 36/45] release/2025-03-28 - Package locks --- client/package-lock.json | 1044 -------------------------------------- package-lock.json | 65 --- 2 files changed, 1109 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 66e922267..289873fe4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2618,414 +2618,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/win32-x64": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", @@ -3688,166 +3280,6 @@ "@parcel/watcher-win32-x64": "2.5.1" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-linux-x64-glibc": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", @@ -3888,46 +3320,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-win32-x64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", @@ -4575,202 +3967,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz", - "integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz", - "integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz", - "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz", - "integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz", - "integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz", - "integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz", - "integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz", - "integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz", - "integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz", - "integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz", - "integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz", - "integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz", - "integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz", - "integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.1.tgz", @@ -4798,34 +3994,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz", - "integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz", - "integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4963,105 +4131,6 @@ "@sentry/cli-win32-x64": "2.42.2" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-darwin": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz", - "integrity": "sha512-GtJSuxER7Vrp1IpxdUyRZzcckzMnb4N5KTW7sbTwUiwqARRo+wxS+gczYrS8tdgtmXs5XYhzhs+t4d52ITHMIg==", - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz", - "integrity": "sha512-7udCw+YL9lwq+9eL3WLspvnuG+k5Icg92YE7zsteTzWLwgPVzaxeZD2f8hwhsu+wmL+jNqbpCRmktPteh3i2mg==", - "cpu": [ - "arm" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm64": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz", - "integrity": "sha512-BOxzI7sgEU5Dhq3o4SblFXdE9zScpz6EXc5Zwr1UDZvzgXZGosUtKVc7d1LmkrHP8Q2o18HcDWtF3WvJRb5Zpw==", - "cpu": [ - "arm64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-i686": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz", - "integrity": "sha512-Sw/dQp5ZPvKnq3/y7wIJyxTUJYPGoTX/YeMbDs8BzDlu9to2LWV3K3r7hE7W1Lpbaw4tSquUHiQjP5QHCOS7aQ==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-x64": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz", - "integrity": "sha512-mU4zUspAal6TIwlNLBV5oq6yYqiENnCWSxtSQVzWs0Jyq97wtqGNG9U+QrnwjJZ+ta/hvye9fvL2X25D/RxHQw==", - "cpu": [ - "x64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-i686": { - "version": "2.42.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz", - "integrity": "sha512-iHvFHPGqgJMNqXJoQpqttfsv2GI3cGodeTq4aoVLU/BT3+hXzbV0x1VpvvEhncJkDgDicJpFLM8sEPHb3b8abw==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-x64": { "version": "2.42.2", "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz", @@ -5128,105 +4197,6 @@ "@sentry/cli-win32-x64": "2.42.4" } }, - "node_modules/@sentry/cli-darwin": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.4.tgz", - "integrity": "sha512-PZV4Y97VDWBR4rIt0HkJfXaBXlebIN2s/FDzC3iHINZE5OG62CDFsnC4/lbGlf2/UZLDaGGIK7mYwSHhTvN+HQ==", - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-arm": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.4.tgz", - "integrity": "sha512-lBn0oeeg62h68/4Eo6zbPq99Idz5t0VRV48rEU/WKeM4MtQCvG/iGGQ3lBFW2yNiUBzXZIK9poXLEcgbwmcRVw==", - "cpu": [ - "arm" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-arm64": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.4.tgz", - "integrity": "sha512-Ex8vRnryyzC/9e43daEmEqPS+9uirY/l6Hw2lAvhBblFaL7PTWNx52H+8GnYGd9Zy2H3rWNyBDYfHwnErg38zA==", - "cpu": [ - "arm64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-i686": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.4.tgz", - "integrity": "sha512-IBJg0aHjsLCL4LvcFa3cXIjA+4t5kPqBT9y+PoDu4goIFxYD8zl7mbUdGJutvJafTk8Akf4ss4JJXQBjg019zA==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-x64": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.4.tgz", - "integrity": "sha512-gXI5OEiOSNiAEz7VCE6AZcAgHJ47mlgal3+NmbE8XcHmFOnyDws9FNie6PJAy8KZjXi3nqoBP9JVAbnmOix3uA==", - "cpu": [ - "x64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-win32-i686": { - "version": "2.42.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.4.tgz", - "integrity": "sha512-vZuR3UPHKqOMniyrijrrsNwn9usaRysXq78F6WV0cL0ZyPLAmY+KBnTDSFk1Oig2pURnzaTm+RtcZu2fc8mlzg==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@sentry/cli-win32-x64": { "version": "2.42.4", "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz", @@ -9537,20 +8507,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", diff --git a/package-lock.json b/package-lock.json index 806ee2a13..3ca7998d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2151,71 +2151,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", From fb30529808b53790745d3fb64116653815e83267 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 25 Mar 2025 16:48:03 -0400 Subject: [PATCH 37/45] release/2025-03-28 - Modify vite config --- client/vite.config.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/vite.config.js b/client/vite.config.js index 6aed665ef..d53373c69 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -191,11 +191,13 @@ export default defineConfig({ "@sentry/react": ["@sentry/react"], "@splitsoftware/splitio-react": ["@splitsoftware/splitio-react"], logrocket: ["logrocket"], - "@firebase/analytics": ["@firebase/analytics"], - "@firebase/app": ["@firebase/app"], - "@firebase/firestore": ["@firebase/firestore"], - "@firebase/auth": ["@firebase/auth"], - "@firebase/messaging": ["@firebase/messaging"], + firebase: [ + "@firebase/analytics", + "@firebase/app", + "@firebase/firestore", + "@firebase/auth", + "@firebase/messaging" + ], markerjs2: ["markerjs2"], "@apollo/client": ["@apollo/client"], "libphonenumber-js": ["libphonenumber-js"] From 341fc09c22927054b1881a459bf502c44575f451 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 25 Mar 2025 16:51:33 -0400 Subject: [PATCH 38/45] release/2025-03-28 - Modify vite config --- client/vite.config.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/vite.config.js b/client/vite.config.js index d53373c69..075a410d1 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -220,7 +220,13 @@ export default defineConfig({ "react-router-dom", "dayjs", "redux", - "react-redux" + "react-redux", + "@firebase/app", + "@firebase/analytics", + "@firebase/firestore", + "@firebase/auth", + "@firebase/messaging", + "@firebase/util" ], esbuildOptions: { // Update for Vite 6: Use proper file extensions From bbf291e8f3385814ea498109befd7e8e89f3cf93 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 25 Mar 2025 20:16:34 -0700 Subject: [PATCH 39/45] IO-3176 IntelliPay Payment Mapping Signed-off-by: Allan Carr --- server/graphql-client/queries.js | 3 +++ server/intellipay/intellipay.js | 43 ++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index b0c72aa7d..f05ea7ec5 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2768,6 +2768,9 @@ exports.GET_BODYSHOP_BY_ID = ` id md_order_statuses shopname + imexshopid + intellipay_config + state } } `; diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 49d91a88c..4af4a50cc 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -52,6 +52,7 @@ const getShopCredentials = async (bodyshop) => { const decodeComment = (comment) => { try { return comment ? JSON.parse(Buffer.from(comment, "base64").toString()) : null; + // eslint-disable-next-line no-unused-vars } catch (error) { return null; // Handle malformed base64 string gracefully } @@ -361,24 +362,18 @@ exports.checkfee = async (req, res) => { exports.postback = async (req, res) => { const { body: values } = req; const decodedComment = decodeComment(values?.comment); + const logResponseMeta = { - bodyshop: { - id: req.body?.bodyshop?.id, - imexshopid: req.body?.bodyshop?.imexshopid, - name: req.body?.bodyshop?.shopname, - state: req.body?.bodyshop?.state - }, iprequest: values, decodedComment }; - const ipMapping = req.body?.bodyshop?.intellipay_config?.payment_map; - logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, logResponseMeta); + logger.log("intellipay-postback-received", "DEBUG", "api", null, logResponseMeta); try { if ((!values.invoice || values.invoice === "") && !decodedComment) { //invoice is specified through the pay link. Comment by IO. - logger.log("intellipay-postback-ignored", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-ignored", "DEBUG", "api", null, { message: "No invoice or comment provided", ...logResponseMeta }); @@ -391,7 +386,7 @@ exports.postback = async (req, res) => { //This has been triggered by IO and may have multiple jobs. const parsedComment = decodedComment; - logger.log("intellipay-postback-parsed-comment", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-parsed-comment", "DEBUG", "api", null, { parsedComment, ...logResponseMeta }); @@ -405,8 +400,12 @@ exports.postback = async (req, res) => { const jobs = await gqlClient.request(queries.GET_JOBS_BY_PKS, { ids: partialPayments.map((p) => p.jobid) }); + const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { + id: jobs.jobs[0].shopid + }); + const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; - logger.log("intellipay-postback-jobs-fetched", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-jobs-fetched", "DEBUG", "api", null, { jobs, parsedComment, ...logResponseMeta @@ -424,7 +423,7 @@ exports.postback = async (req, res) => { payment_responses: { data: { amount: values.total, - bodyshopid: jobs.jobs[0].shopid, + bodyshopid: bodyshop.bodyshops_by_pk.id, jobid: p.jobid, declinereason: "Approved", ext_paymentid: values.paymentid, @@ -435,7 +434,7 @@ exports.postback = async (req, res) => { })) }); - logger.log("intellipay-postback-payment-success", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-payment-success", "DEBUG", "api", null, { paymentResult, jobs, parsedComment, @@ -458,7 +457,7 @@ exports.postback = async (req, res) => { .join("
") }) }).catch((error) => { - logger.log("intellipay-postback-email-error", "ERROR", req.user?.email, null, { + logger.log("intellipay-postback-email-error", "ERROR", "api", null, { message: error.message, jobs, paymentResult, @@ -472,8 +471,14 @@ exports.postback = async (req, res) => { id: values.invoice }); - logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", req.user?.email, null, { + const bodyshop = await gqlClient.request(queries.GET_BODYSHOP_BY_ID, { + id: job.jobs_by_pk.shopid + }); + const ipMapping = bodyshop.bodyshops_by_pk.intellipay_config?.payment_map; + + logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", "api", null, { job, + bodyshop, ...logResponseMeta }); @@ -488,7 +493,7 @@ exports.postback = async (req, res) => { } }); - logger.log("intellipay-postback-invoice-payment-success", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-invoice-payment-success", "DEBUG", "api", null, { paymentResult, ...logResponseMeta }); @@ -496,7 +501,7 @@ exports.postback = async (req, res) => { const responseResults = await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, { paymentResponse: { amount: values.total, - bodyshopid: job.jobs_by_pk.shopid, + bodyshopid: bodyshop.bodyshops_by_pk.id, paymentid: paymentResult.id, jobid: values.invoice, declinereason: "Approved", @@ -506,14 +511,14 @@ exports.postback = async (req, res) => { } }); - logger.log("intellipay-postback-invoice-response-success", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-invoice-response-success", "DEBUG", "api", null, { responseResults, ...logResponseMeta }); res.sendStatus(200); } } catch (error) { - logger.log("intellipay-postback-error", "ERROR", req.user?.email, null, { + logger.log("intellipay-postback-error", "ERROR", "api", null, { message: error?.message, ...logResponseMeta }); From 67b6da7c31881d1494b712f1140173ade3701e0f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 26 Mar 2025 16:51:53 -0400 Subject: [PATCH 40/45] feature/IO-3181-Test-Framework-Selection - Skeletons complete --- .gitignore | 6 ++++++ client/.gitignore | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/.gitignore b/.gitignore index fc12776ac..4002717d7 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,9 @@ logs/oAuthClient-log.log /*.env.* .idea/* .idea + +# Vitest +vitest-report*/ # Test report directories (e.g., vitest-report-html) +vitest-coverage/ # Coverage reports +*.vitest.log # Vitest log files +test-output.txt # Custom test output files (if used) diff --git a/client/.gitignore b/client/.gitignore index 730a6b93c..91c59e628 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,3 +1,14 @@ +# Vitest +vitest-report*/ # Test report directories (e.g., vitest-report-html) +vitest-coverage/ # Coverage reports +*.vitest.log # Vitest log files +test-output.txt # Custom test output files (if used) + +# Playwright +playwright-report/ # Playwright test reports +test-results/ # Playwright test results (screenshots, videos, etc.) +playwright/.cache/ # Playwright cache for browser binaries +*.playwright.log # Playwright log files # Sentry Config File .sentryclirc From 146bb6c5c0f04c4fa9fe8ed6a8e83e4d274ff896 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 26 Mar 2025 16:52:59 -0400 Subject: [PATCH 41/45] feature/IO-3181-Test-Framework-Selection - Skeletons complete --- client/package-lock.json | 1468 +++++++++++++++-- client/package.json | 14 +- client/playwright.config.js | 16 + .../alert.component.test.js.snap | 3 - .../components/alert/alert.component.test.js | 19 - .../components/alert/alert.component.test.jsx | 31 + ...ocations-assignment.component.test.js.snap | 5 - .../allocations-assignment.component.test.js | 35 - client/src/setupTests.js | 4 - client/src/translations/en_us/common.json | 3 +- client/src/translations/es/common.json | 3 +- client/src/translations/fr/common.json | 3 +- client/src/utils/TestingHelpers.js | 139 -- client/tests/Button.test.jsx | 14 + client/tests/e2e/homepage.e2e.js | 6 + client/tests/e2e/signin.e2e.js | 28 + client/tests/e2e/utils/login.js | 21 + client/tests/setup.js | 5 + client/tests/setupI18n.js | 27 + client/vitest.config.js | 19 + package-lock.json | 1406 +++++++++++++++- package.json | 8 +- server/tests/api.test.js | 14 + server/tests/math.test.js | 11 + vitest.config.js | 10 + 25 files changed, 2988 insertions(+), 324 deletions(-) create mode 100644 client/playwright.config.js delete mode 100644 client/src/components/alert/__snapshots__/alert.component.test.js.snap delete mode 100644 client/src/components/alert/alert.component.test.js create mode 100644 client/src/components/alert/alert.component.test.jsx delete mode 100644 client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap delete mode 100644 client/src/components/allocations-assignment/allocations-assignment.component.test.js delete mode 100644 client/src/setupTests.js delete mode 100644 client/src/utils/TestingHelpers.js create mode 100644 client/tests/Button.test.jsx create mode 100644 client/tests/e2e/homepage.e2e.js create mode 100644 client/tests/e2e/signin.e2e.js create mode 100644 client/tests/e2e/utils/login.js create mode 100644 client/tests/setup.js create mode 100644 client/tests/setupI18n.js create mode 100644 client/vitest.config.js create mode 100644 server/tests/api.test.js create mode 100644 server/tests/math.test.js create mode 100644 vitest.config.js diff --git a/client/package-lock.json b/client/package-lock.json index 289873fe4..af00cf920 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -25,7 +25,6 @@ "@sentry/vite-plugin": "^3.2.2", "@splitsoftware/splitio-react": "^2.0.1", "@tanem/react-nprogress": "^5.0.53", - "@vitejs/plugin-react": "^4.3.4", "antd": "^5.24.5", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", @@ -95,7 +94,12 @@ "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", "@eslint/js": "^9.23.0", + "@playwright/test": "^1.51.1", "@sentry/webpack-plugin": "^3.2.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", + "@vitejs/plugin-react": "^4.3.4", "browserslist": "^4.24.4", "browserslist-to-esbuild": "^2.1.1", "chalk": "^5.4.1", @@ -103,8 +107,10 @@ "eslint-config-react-app": "^7.0.1", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", + "jsdom": "^26.0.0", "memfs": "^4.17.0", "os-browserify": "^0.3.0", + "playwright": "^1.51.1", "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", @@ -114,6 +120,7 @@ "vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-pwa": "^0.21.2", "vite-plugin-style-import": "^2.0.0", + "vitest": "^3.0.9", "workbox-window": "^7.3.0" }, "engines": { @@ -123,6 +130,13 @@ "@rollup/rollup-linux-x64-gnu": "4.6.1" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz", + "integrity": "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==", + "dev": true, + "license": "MIT" + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -423,6 +437,27 @@ } } }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", + "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.2", + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -674,6 +709,7 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1902,6 +1938,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1917,6 +1954,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2403,6 +2441,121 @@ "node": ">=6.9.0" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", + "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", + "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -3340,6 +3493,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@playwright/test": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz", + "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.51.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -4391,10 +4560,135 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", + "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz", + "integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -4408,6 +4702,7 @@ "version": "7.6.8", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" @@ -4417,6 +4712,7 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", @@ -4427,6 +4723,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" @@ -4967,6 +5264,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.26.0", @@ -4982,6 +5280,163 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, + "node_modules/@vitest/expect": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", + "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", + "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", + "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.0.9", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/snapshot": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", + "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@vitest/snapshot/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/spy": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", + "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", + "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@wry/caches": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", @@ -5090,6 +5545,21 @@ "node": ">=8" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/antd": { "version": "5.24.5", "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.5.tgz", @@ -5239,6 +5709,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -5439,6 +5919,16 @@ "util": "^0.12.5" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -6035,6 +6525,16 @@ "dev": true, "license": "MIT" }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -6157,6 +6657,23 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", @@ -6231,6 +6748,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -6635,6 +7162,27 @@ "postcss-value-parser": "^4.0.2" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", + "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.1", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -6775,6 +7323,57 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -6867,6 +7466,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, "node_modules/decimal.js-light": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", @@ -6902,6 +7508,16 @@ "dev": true, "license": "MIT" }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7078,6 +7694,13 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -7269,6 +7892,19 @@ "node": ">=10.0.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-cmd": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", @@ -7819,16 +8455,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/eslint-plugin-react": { "version": "7.37.4", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", @@ -7963,22 +8589,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/eslint/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -8032,19 +8642,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -8215,6 +8812,16 @@ "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==", "license": "MIT" }, + "node_modules/expect-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", + "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -8507,6 +9114,20 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -9011,6 +9632,19 @@ "react-is": "^16.7.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -9030,6 +9664,30 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -9110,6 +9768,19 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -9196,6 +9867,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -9691,6 +10372,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -9941,21 +10629,6 @@ "node": ">=10" } }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9972,18 +10645,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -10009,6 +10670,130 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", + "integrity": "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -10302,6 +11087,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true, + "license": "MIT" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -10330,6 +11122,16 @@ "node": ">=12" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.8", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", @@ -11112,6 +11914,16 @@ "node": ">=6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -11362,6 +12174,13 @@ "node": ">=8" } }, + "node_modules/nwsapi": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz", + "integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==", + "dev": true, + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -11754,6 +12573,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/pascal-case": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", @@ -11874,6 +12706,16 @@ "dev": true, "license": "MIT" }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/pbkdf2": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", @@ -11929,6 +12771,38 @@ "node": ">=10" } }, + "node_modules/playwright": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", + "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.51.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", + "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -11996,6 +12870,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -13153,6 +14062,7 @@ "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13342,6 +14252,20 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -13807,6 +14731,13 @@ "win32" ] }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -13916,6 +14847,13 @@ "node": ">=10" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, "node_modules/sass": { "version": "1.86.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", @@ -13936,6 +14874,19 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -14164,6 +15115,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -14299,22 +15257,6 @@ "node": ">=12" } }, - "node_modules/source-map-explorer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/source-map-explorer/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -14376,19 +15318,6 @@ "node": ">= 8" } }, - "node_modules/source-map-explorer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map-explorer/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -14484,12 +15413,26 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", "license": "MIT" }, + "node_modules/std-env": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", + "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -14751,6 +15694,19 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -14893,6 +15849,18 @@ } } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -14928,6 +15896,13 @@ "node": ">=0.10" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/temp": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", @@ -15094,12 +16069,26 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", @@ -15114,6 +16103,56 @@ "node": ">=12.0.0" } }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", + "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.85" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", + "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15132,6 +16171,19 @@ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", "license": "MIT" }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -15922,6 +16974,43 @@ } } }, + "node_modules/vite-node": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", + "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-node/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/vite-plugin-babel": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/vite-plugin-babel/-/vite-plugin-babel-1.3.0.tgz", @@ -16082,6 +17171,21 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/vite/node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -16111,6 +17215,93 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/vitest": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", + "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "3.0.9", + "@vitest/mocker": "3.0.9", + "@vitest/pretty-format": "^3.0.9", + "@vitest/runner": "3.0.9", + "@vitest/snapshot": "3.0.9", + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.9", + "@vitest/ui": "3.0.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/vitest/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -16127,6 +17318,19 @@ "node": ">=0.10.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", @@ -16163,6 +17367,29 @@ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", "license": "MIT" }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -16277,6 +17504,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -16615,21 +17859,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -16657,6 +17886,23 @@ } } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", diff --git a/client/package.json b/client/package.json index f7e354160..4f595d18c 100644 --- a/client/package.json +++ b/client/package.json @@ -24,7 +24,6 @@ "@sentry/vite-plugin": "^3.2.2", "@splitsoftware/splitio-react": "^2.0.1", "@tanem/react-nprogress": "^5.0.53", - "@vitejs/plugin-react": "^4.3.4", "antd": "^5.24.5", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^4.2.0", @@ -100,7 +99,10 @@ "build:production:imex": "env-cmd -f .env.production.imex npm run build", "build:production:rome": "env-cmd -f .env.production.rome npm run build", "madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .", - "eulaize": "node src/utils/eulaize.js" + "eulaize": "node src/utils/eulaize.js", + "test:unit": "vitest run", + "test:watch": "vitest", + "test:e2e": "playwright test" }, "browserslist": { "production": [ @@ -128,7 +130,12 @@ "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", "@eslint/js": "^9.23.0", + "@playwright/test": "^1.51.1", "@sentry/webpack-plugin": "^3.2.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", + "@vitejs/plugin-react": "^4.3.4", "browserslist": "^4.24.4", "browserslist-to-esbuild": "^2.1.1", "chalk": "^5.4.1", @@ -136,8 +143,10 @@ "eslint-config-react-app": "^7.0.1", "eslint-plugin-react": "^7.37.4", "globals": "^15.15.0", + "jsdom": "^26.0.0", "memfs": "^4.17.0", "os-browserify": "^0.3.0", + "playwright": "^1.51.1", "react-error-overlay": "^6.1.0", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", @@ -147,6 +156,7 @@ "vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-pwa": "^0.21.2", "vite-plugin-style-import": "^2.0.0", + "vitest": "^3.0.9", "workbox-window": "^7.3.0" } } diff --git a/client/playwright.config.js b/client/playwright.config.js new file mode 100644 index 000000000..5f1d1ec3b --- /dev/null +++ b/client/playwright.config.js @@ -0,0 +1,16 @@ +import { defineConfig } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests/e2e", + testMatch: "*.e2e.js", + use: { + baseURL: "https://localhost:3000", + browser: "chromium", + ignoreHTTPSErrors: true + }, + webServer: { + command: "npm run start:imex", + port: 3000, + reuseExistingServer: !process.env.CI // Reuse server locally, not in CI + } +}); diff --git a/client/src/components/alert/__snapshots__/alert.component.test.js.snap b/client/src/components/alert/__snapshots__/alert.component.test.js.snap deleted file mode 100644 index b872ff7b9..000000000 --- a/client/src/components/alert/__snapshots__/alert.component.test.js.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Alert component should render Alert component 1`] = `ShallowWrapper {}`; diff --git a/client/src/components/alert/alert.component.test.js b/client/src/components/alert/alert.component.test.js deleted file mode 100644 index b7c14b48a..000000000 --- a/client/src/components/alert/alert.component.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { shallow } from "enzyme"; -import React from "react"; -import Alert from "./alert.component"; - -describe("Alert component", () => { - let wrapper; - beforeEach(() => { - const mockProps = { - type: "error", - message: "Test error message." - }; - - wrapper = shallow(); - }); - - it("should render Alert component", () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/client/src/components/alert/alert.component.test.jsx b/client/src/components/alert/alert.component.test.jsx new file mode 100644 index 000000000..a34644a4b --- /dev/null +++ b/client/src/components/alert/alert.component.test.jsx @@ -0,0 +1,31 @@ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; +import AlertComponent from "./alert.component"; + +describe("AlertComponent", () => { + it("renders with default props", () => { + render(); + expect(screen.getByText("Default Alert")).toBeInTheDocument(); + expect(screen.getByRole("alert")).toHaveClass("ant-alert"); + }); + + it("applies type prop correctly", () => { + render(); + const alert = screen.getByRole("alert"); + expect(screen.getByText("Success Alert")).toBeInTheDocument(); + expect(alert).toHaveClass("ant-alert-success"); + }); + + it("displays description when provided", () => { + render(); + expect(screen.getByText("Error Alert")).toBeInTheDocument(); + expect(screen.getByText("Something went wrong")).toBeInTheDocument(); + expect(screen.getByRole("alert")).toHaveClass("ant-alert-error"); + }); + + it("is closable and shows icon when props are set", () => { + render(); + expect(screen.getByText("Warning Alert")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /close/i })).toBeInTheDocument(); // Close button + }); +}); diff --git a/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap b/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap deleted file mode 100644 index c0b9ed61d..000000000 --- a/client/src/components/allocations-assignment/__snapshots__/allocations-assignment.component.test.js.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AllocationsAssignmentComponent component should create an allocation on save 1`] = `ReactWrapper {}`; - -exports[`AllocationsAssignmentComponent component should render AllocationsAssignmentComponent component 1`] = `ReactWrapper {}`; diff --git a/client/src/components/allocations-assignment/allocations-assignment.component.test.js b/client/src/components/allocations-assignment/allocations-assignment.component.test.js deleted file mode 100644 index fe9c3628b..000000000 --- a/client/src/components/allocations-assignment/allocations-assignment.component.test.js +++ /dev/null @@ -1,35 +0,0 @@ -import { mount } from "enzyme"; -import React from "react"; -import { MockBodyshop } from "../../utils/TestingHelpers"; -import { AllocationsAssignmentComponent } from "./allocations-assignment.component"; - -describe("AllocationsAssignmentComponent component", () => { - let wrapper; - - beforeEach(() => { - const mockProps = { - bodyshop: MockBodyshop, - handleAssignment: jest.fn(), - assignment: {}, - setAssignment: jest.fn(), - visibilityState: [false, jest.fn()], - maxHours: 4 - }; - - wrapper = mount(); - }); - - it("should render AllocationsAssignmentComponent component", () => { - expect(wrapper).toMatchSnapshot(); - }); - - it("should render a list of employees", () => { - const empList = wrapper.find("#employeeSelector"); - expect(empList.children()).to.have.lengthOf(2); - }); - - it("should create an allocation on save", () => { - wrapper.find("Button").simulate("click"); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/client/src/setupTests.js b/client/src/setupTests.js deleted file mode 100644 index 6f413a40b..000000000 --- a/client/src/setupTests.js +++ /dev/null @@ -1,4 +0,0 @@ -import { configure } from "enzyme"; -import Adapter from "enzyme-adapter-react-16"; - -configure({ adapter: new Adapter() }); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index ccf90fc10..b2ca3146e 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -3679,7 +3679,8 @@ "signinerror": { "auth/user-disabled": "User account disabled. ", "auth/user-not-found": "A user with this email does not exist.", - "auth/wrong-password": "The email and password combination you provided is incorrect." + "auth/wrong-password": "The email and password combination you provided is incorrect.", + "auth/invalid-email": "A user with this email does not exist." } } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 2f9fa9a2b..b32bbaacc 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -3679,7 +3679,8 @@ "signinerror": { "auth/user-disabled": "", "auth/user-not-found": "", - "auth/wrong-password": "" + "auth/wrong-password": "", + "auth/invalid-email": "" } } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 888162de9..e054c842c 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -3679,7 +3679,8 @@ "signinerror": { "auth/user-disabled": "", "auth/user-not-found": "", - "auth/wrong-password": "" + "auth/wrong-password": "", + "auth/invalid-email": "" } } }, diff --git a/client/src/utils/TestingHelpers.js b/client/src/utils/TestingHelpers.js deleted file mode 100644 index 9b0ffd9b0..000000000 --- a/client/src/utils/TestingHelpers.js +++ /dev/null @@ -1,139 +0,0 @@ -export const MockBodyshop = { - address1: "123 Fake St", - address2: "Unit #100", - city: "Vancouver", - country: "Canada", - created_at: "2019-12-10T20:03:06.420853+00:00", - email: "snaptsoft@gmail.com", - federal_tax_id: "GST10150492", - id: "52b7357c-0edd-4c95-85c3-dfdbcdfad9ac", - insurance_vendor_id: "F123456", - logo_img_path: "https://www.snapt.ca/assets/logo-placeholder.png", - md_ro_statuses: { - statuses: [ - "Open", - "Scheduled", - "Arrived", - "Repair Plan", - "Parts", - "Body", - "Prep", - "Paint", - "Reassembly", - "Sublet", - "Detail", - "Completed", - "Delivered", - "Invoiced", - "Exported" - ], - open_statuses: ["Open", "Scheduled", "Arrived", "Repair Plan", "Parts", "Body", "Prep", "Paint"], - default_arrived: "Arrived", - default_exported: "Exported", - default_imported: "Open", - default_invoiced: "Invoiced", - default_completed: "Completed", - default_delivered: "Delivered", - default_scheduled: "Scheduled" - }, - md_order_statuses: { - statuses: ["Ordered", "Received", "Canceled", "Backordered"], - default_bo: "Backordered", - default_ordered: "Ordered", - default_canceled: "Canceled", - default_received: "Received" - }, - shopname: "Testing Collision", - state: "BC", - state_tax_id: "PST1000-2991", - updated_at: "2020-03-23T22:06:03.509544+00:00", - zip_post: "V6B 1M9", - region_config: "CA_BC", - md_responsibility_centers: { - costs: [ - "Aftermarket", - "ATS", - "Body", - "Detail", - "Daignostic", - "Electrical", - "Chrome", - "Frame", - "Mechanical", - "Refinish", - "Structural", - "Existing", - "Glass", - "LKQ", - "OEM", - "OEM Partial", - "Re-cored", - "Remanufactured", - "Other", - "Sublet", - "Towing" - ], - profits: [ - "Aftermarket", - "ATS", - "Body", - "Detail", - "Daignostic", - "Electrical", - "Chrome", - "Frame", - "Mechanical", - "Refinish", - "Structural", - "Existing", - "Glass", - "LKQ", - "OEM", - "OEM Partial", - "Re-cored", - "Remanufactured", - "Other", - "Sublet", - "Towing" - ], - defaults: { - ATS: "ATS", - LAB: "Body", - LAD: "Diagnostic", - LAE: "Electrical", - LAF: "Frame", - LAG: "Glass", - LAM: "Mechanical", - LAR: "Refinish", - LAS: "Structural", - LAU: "Detail", - PAA: "Aftermarket", - PAC: "Chrome", - PAL: "LKQ", - PAM: "Remanufactured", - PAN: "OEM", - PAO: "Other", - PAP: "OEM Partial", - PAR: "16", - TOW: "Towing" - } - }, - employees: [ - { - id: "075b744c-8919-49ca-abb2-ccd51040326d", - first_name: "Patrick", - last_name: "BODY123", - employee_number: "101", - cost_center: "Body", - __typename: "employees" - }, - { - id: "8cc787d3-1cfe-49d3-8a15-8469cd5c2e41", - first_name: "Patrick", - last_name: "Painter", - employee_number: "10211", - cost_center: "REFINISH", - __typename: "employees" - } - ] -}; diff --git a/client/tests/Button.test.jsx b/client/tests/Button.test.jsx new file mode 100644 index 000000000..b83bf36c3 --- /dev/null +++ b/client/tests/Button.test.jsx @@ -0,0 +1,14 @@ +// Button.test.jsx +import React from "react"; +import { render, screen } from "@testing-library/react"; +import { describe, it, expect } from "vitest"; +import { Button } from "antd"; +import "antd/dist/reset.css"; // Optional: include if needed for styling reset + +describe("AntD Button", () => { + it("renders with correct text", () => { + render(); + const button = screen.getByRole("button", { name: /click me/i }); + expect(button).toBeInTheDocument(); + }); +}); diff --git a/client/tests/e2e/homepage.e2e.js b/client/tests/e2e/homepage.e2e.js new file mode 100644 index 000000000..0cede9e0a --- /dev/null +++ b/client/tests/e2e/homepage.e2e.js @@ -0,0 +1,6 @@ +import { test, expect } from "@playwright/test"; + +test("homepage loads correctly", async ({ page }) => { + await page.goto("/"); + await expect(page.locator("h1")).toContainText("ImEX Online"); +}); diff --git a/client/tests/e2e/signin.e2e.js b/client/tests/e2e/signin.e2e.js new file mode 100644 index 000000000..4213c82ce --- /dev/null +++ b/client/tests/e2e/signin.e2e.js @@ -0,0 +1,28 @@ +import { test, expect } from "@playwright/test"; +import { login } from "./utils/login"; + +test.describe("SignInComponent", () => { + test("successfully logs in with valid credentials", async ({ page }) => { + const email = "dave@imex.dev"; + const password = "dave123"; + + await login(page, { email, password }); + + // Additional assertions after login (optional) + await expect(page).toHaveURL(/\/manage\//); + }); + + test("displays error on invalid credentials", async ({ page }) => { + await page.goto("/"); // Adjust if login route differs + + // Fill form with invalid credentials + await page.fill('input[placeholder="Username"]', "wronguser@example.com"); + await page.fill('input[placeholder="Password"]', "wrongpassword"); + await page.click("button.login-btn"); + + // Check for error alert + const alert = page.locator(".ant-alert-error"); + await expect(alert).toBeVisible(); + await expect(alert).toContainText("A user with this email does not exist."); + }); +}); diff --git a/client/tests/e2e/utils/login.js b/client/tests/e2e/utils/login.js new file mode 100644 index 000000000..8b6c2e9f8 --- /dev/null +++ b/client/tests/e2e/utils/login.js @@ -0,0 +1,21 @@ +import { expect } from "@playwright/test"; + +export async function login(page, { email, password }) { + // Navigate to the login page + await page.goto("/"); // Adjust if your login route differs (e.g., '/login') + + // Fill email field + await page.fill('input[placeholder="Username"]', email); // Matches Ant Design Input placeholder + + // Fill password field + await page.fill('input[placeholder="Password"]', password); + + // Click login button + await page.click("button.login-btn"); + + // Wait for navigation or success indicator (e.g., redirect to /manage/) + await page.waitForURL(/\/manage\//, { timeout: 10000 }); // Adjust based on redirect + + // Verify successful login (e.g., check for a dashboard element) + await expect(page.locator("text=Manage")).toBeVisible(); // Adjust to your app’s post-login UI +} diff --git a/client/tests/setup.js b/client/tests/setup.js new file mode 100644 index 000000000..8b4799a23 --- /dev/null +++ b/client/tests/setup.js @@ -0,0 +1,5 @@ +import { afterEach } from "vitest"; +import { cleanup } from "@testing-library/react"; +import "@testing-library/jest-dom"; + +afterEach(() => cleanup()); diff --git a/client/tests/setupI18n.js b/client/tests/setupI18n.js new file mode 100644 index 000000000..91ae266fe --- /dev/null +++ b/client/tests/setupI18n.js @@ -0,0 +1,27 @@ +import i18n from "i18next"; +import { initReactI18next } from "react-i18next"; +import en_Translation from "../src/translations/en_us/common.json"; +import es_Translation from "../src/translations/es/common.json"; +import fr_Translation from "../src/translations/fr/common.json"; + +const resources = { + "en-US": en_Translation, + "fr-CA": fr_Translation, + "es-MX": es_Translation +}; + +i18n.use(initReactI18next).init({ + resources, + lng: "en-US", // Default to en-US for tests (no LanguageDetector) + fallbackLng: "en-US", + debug: false, // Disable debug in tests + react: { + useSuspense: false // Disable Suspense for Vitest + }, + interpolation: { + escapeValue: false, // React handles XSS + skipOnVariables: false + } +}); + +export default i18n; diff --git a/client/vitest.config.js b/client/vitest.config.js new file mode 100644 index 000000000..f5841b1bd --- /dev/null +++ b/client/vitest.config.js @@ -0,0 +1,19 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], + test: { + environment: "jsdom", + globals: true, + setupFiles: "./tests/setup.js", + testTimeout: 10000 // 10 seconds (in milliseconds) + }, + css: { + preprocessorOptions: { + scss: { + silenceDeprecations: ["import"] // Suppress @import warnings + } + } + } +}); diff --git a/package-lock.json b/package-lock.json index 3ca7998d5..7c4c6bfe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,7 +78,9 @@ "globals": "^15.15.0", "p-limit": "^3.1.0", "prettier": "^3.5.3", - "source-map-explorer": "^2.5.2" + "source-map-explorer": "^2.5.2", + "supertest": "^7.1.0", + "vitest": "^3.0.9" }, "engines": { "node": ">=18.0.0", @@ -1483,6 +1485,431 @@ "integrity": "sha512-d5RjycE+MObE/hU+8OM5Zp4VjTwiPLRa8299fj7muOmR16fb942z8byoMbCErnGh0lBevvgkGrLclQDvINbIyg==", "license": "Apache-2.0" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -2396,6 +2823,286 @@ "@redis/client": "^1.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", + "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", + "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", + "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", + "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", + "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", + "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", + "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", + "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", + "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", + "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", + "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", + "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", + "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", + "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", + "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", + "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", + "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", + "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", + "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", + "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@smithy/abort-controller": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz", @@ -3445,6 +4152,119 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "license": "MIT" }, + "node_modules/@vitest/expect": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", + "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", + "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", + "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.0.9", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", + "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", + "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", + "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@xmldom/is-dom-node": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@xmldom/is-dom-node/-/is-dom-node-1.0.1.tgz", @@ -3943,6 +4763,16 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -4356,6 +5186,16 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -4422,6 +5262,23 @@ "cargo-cp-artifact": "bin/cargo-cp-artifact.js" } }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4462,6 +5319,16 @@ "pnpm": ">=8" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/cheerio": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", @@ -4667,6 +5534,16 @@ "node": ">=18" } }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/compress-commons": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", @@ -4857,6 +5734,13 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -5183,6 +6067,16 @@ "node": ">= 16" } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5724,6 +6618,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -5778,6 +6679,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -6020,6 +6962,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6057,6 +7009,16 @@ "node": ">=0.8.x" } }, + "node_modules/expect-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", + "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -6523,6 +7485,21 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -8311,6 +9288,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -8351,6 +9335,16 @@ "node": ">=12" } }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8631,6 +9625,25 @@ "license": "MIT", "optional": true }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -9223,6 +10236,23 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/phone": { "version": "3.1.58", "resolved": "https://registry.npmjs.org/phone/-/phone-3.1.58.tgz", @@ -9257,6 +10287,35 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/pprof-format": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.1.0.tgz", @@ -9744,6 +10803,46 @@ "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==", "license": "MIT" }, + "node_modules/rollup": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", + "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.37.0", + "@rollup/rollup-android-arm64": "4.37.0", + "@rollup/rollup-darwin-arm64": "4.37.0", + "@rollup/rollup-darwin-x64": "4.37.0", + "@rollup/rollup-freebsd-arm64": "4.37.0", + "@rollup/rollup-freebsd-x64": "4.37.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", + "@rollup/rollup-linux-arm-musleabihf": "4.37.0", + "@rollup/rollup-linux-arm64-gnu": "4.37.0", + "@rollup/rollup-linux-arm64-musl": "4.37.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", + "@rollup/rollup-linux-riscv64-gnu": "4.37.0", + "@rollup/rollup-linux-riscv64-musl": "4.37.0", + "@rollup/rollup-linux-s390x-gnu": "4.37.0", + "@rollup/rollup-linux-x64-gnu": "4.37.0", + "@rollup/rollup-linux-x64-musl": "4.37.0", + "@rollup/rollup-win32-arm64-msvc": "4.37.0", + "@rollup/rollup-win32-ia32-msvc": "4.37.0", + "@rollup/rollup-win32-x64-msvc": "4.37.0", + "fsevents": "~2.3.2" + } + }, "node_modules/rsa-pem-from-mod-exp": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/rsa-pem-from-mod-exp/-/rsa-pem-from-mod-exp-0.8.6.tgz", @@ -10123,6 +11222,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -10465,6 +11571,16 @@ "node": ">=10" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/specificity": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", @@ -10548,6 +11664,13 @@ "node": "*" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -10563,6 +11686,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", + "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -10833,6 +11963,54 @@ "pick-util": "^1.1.5" } }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.0.tgz", + "integrity": "sha512-5QeSO8hSrKghtcWEoPiO036fxH0Ii2wVQfFZSP0oqQhmjk8bOLhDFXr4JrvaFmPuEWUoq4znY3uSi8UzLKxGqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -10991,6 +12169,50 @@ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tlhunter-sorted-set": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/tlhunter-sorted-set/-/tlhunter-sorted-set-0.1.0.tgz", @@ -11300,6 +12522,171 @@ "node": ">= 0.8" } }, + "node_modules/vite": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", + "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "postcss": "^8.5.3", + "rollup": "^4.30.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", + "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", + "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "3.0.9", + "@vitest/mocker": "3.0.9", + "@vitest/pretty-format": "^3.0.9", + "@vitest/runner": "3.0.9", + "@vitest/snapshot": "3.0.9", + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.9", + "@vitest/ui": "3.0.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "node_modules/web-resource-inliner": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-7.0.0.tgz", @@ -11602,6 +12989,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", diff --git a/package.json b/package.json index 9f2bf57f2..d95e7a731 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i", "setup:win": "rimraf node_modules && npm i && cd client && rimraf node_modules && npm i", "start": "node server.js", - "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" + "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"", + "test:unit": "vitest run", + "test:watch": "vitest" }, "dependencies": { "@aws-sdk/client-cloudwatch-logs": "^3.772.0", @@ -82,6 +84,8 @@ "globals": "^15.15.0", "p-limit": "^3.1.0", "prettier": "^3.5.3", - "source-map-explorer": "^2.5.2" + "source-map-explorer": "^2.5.2", + "supertest": "^7.1.0", + "vitest": "^3.0.9" } } diff --git a/server/tests/api.test.js b/server/tests/api.test.js new file mode 100644 index 000000000..ce5ccf72f --- /dev/null +++ b/server/tests/api.test.js @@ -0,0 +1,14 @@ +import { describe, it, expect } from "vitest"; +import request from "supertest"; +import express from "express"; + +const app = express(); +app.get("/api/health", (req, res) => res.json({ status: "ok" })); + +describe("API", () => { + it("returns health status", async () => { + const response = await request(app).get("/api/health"); + expect(response.status).toBe(200); + expect(response.body).toEqual({ status: "ok" }); + }); +}); diff --git a/server/tests/math.test.js b/server/tests/math.test.js new file mode 100644 index 000000000..551b921a5 --- /dev/null +++ b/server/tests/math.test.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from "vitest"; + +function add(a, b) { + return a + b; +} + +describe("Math", () => { + it("adds two numbers correctly", () => { + expect(add(2, 3)).toBe(5); + }); +}); diff --git a/vitest.config.js b/vitest.config.js new file mode 100644 index 000000000..7757f9a7e --- /dev/null +++ b/vitest.config.js @@ -0,0 +1,10 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + globals: true, + include: ["./server/tests/**/*.{test,spec}.[jt]s"], // Only search /tests in root + exclude: ["**/client/**", "**/node_modules/**", "**/dist/**"] // Explicitly exclude /client + } +}); From 549cb56cdfd4d2ad06711f4afcc1a070a313c817 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 26 Mar 2025 16:54:05 -0400 Subject: [PATCH 42/45] feature/IO-3181-Test-Framework-Selection - Skeletons complete --- .gitignore | 9 +++++---- client/.gitignore | 16 ++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 4002717d7..bf7f3dac7 100644 --- a/.gitignore +++ b/.gitignore @@ -123,7 +123,8 @@ logs/oAuthClient-log.log .idea # Vitest -vitest-report*/ # Test report directories (e.g., vitest-report-html) -vitest-coverage/ # Coverage reports -*.vitest.log # Vitest log files -test-output.txt # Custom test output files (if used) +vitest-report*/ +vitest-coverage/ +*.vitest.log +test-output.txt + diff --git a/client/.gitignore b/client/.gitignore index 91c59e628..0d780b332 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,14 +1,14 @@ # Vitest -vitest-report*/ # Test report directories (e.g., vitest-report-html) -vitest-coverage/ # Coverage reports -*.vitest.log # Vitest log files -test-output.txt # Custom test output files (if used) +vitest-report*/ +vitest-coverage/ +*.vitest.log +test-output.txt # Playwright -playwright-report/ # Playwright test reports -test-results/ # Playwright test results (screenshots, videos, etc.) -playwright/.cache/ # Playwright cache for browser binaries -*.playwright.log # Playwright log files +playwright-report/ +test-results/ +playwright/.cache/ +*.playwright.log # Sentry Config File .sentryclirc From 2a7686ec757c24681601e0ca6d99bbf2ec2718ab Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 26 Mar 2025 15:21:42 -0700 Subject: [PATCH 43/45] IO-3187 Admin Enhancements Signed-off-by: Allan Carr --- server/admin/adminops.js | 43 +++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/server/admin/adminops.js b/server/admin/adminops.js index d134bdcba..7ff7e9ef4 100644 --- a/server/admin/adminops.js +++ b/server/admin/adminops.js @@ -39,12 +39,14 @@ exports.createShop = async (req, res) => { try { const result = await client.request( - `mutation INSERT_BODYSHOPS($bs: bodyshops_insert_input!){ - insert_bodyshops_one(object:$bs){ - id - - } -}`, + `mutation INSERT_BODYSHOPS($bs: bodyshops_insert_input!) { + insert_bodyshops_one(object: $bs) { + id + vendors { + id + } + } + }`, { bs: { ...bodyshop, @@ -54,12 +56,39 @@ exports.createShop = async (req, res) => { { countertype: "ihbnum", count: 1 }, { countertype: "paymentnum", count: 1 } ] + }, + vendors: { + data: [{ name: "In-House" }] } } } ); - res.json(result); + const bodyshopId = result.insert_bodyshops_one.id; + const vendorId = result.insert_bodyshops_one.vendors[0].id; + + if (!bodyshopId || !vendorId) { + throw new Error("Failed to create bodyshop or vendor"); + } + + const updateBodyshop = await client.request( + `mutation UPDATE_BODYSHOP($id: uuid!, $inhousevendorid: uuid!) { + update_bodyshops_by_pk(pk_columns: { id: $id }, _set: { inhousevendorid: $inhousevendorid }) { + id + } + }`, + { + id: bodyshopId, + inhousevendorid: vendorId + } + ); + res.status(200).json(updateBodyshop); } catch (error) { + logger.log("admin-create-shop-error", "error", req.user.email, null, { + message: error.message, + stack: error.stack, + request: req.body, + ioadmin: true + }); res.status(500).json(error); } }; From 8b7bb099f387e17c311d1dd36d29e8f4985fe716 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 28 Mar 2025 12:16:36 -0400 Subject: [PATCH 44/45] feature/IO-3181-Test-Framework-Selection - Skeletons complete --- client/.env.development.imex | 2 ++ client/.env.development.rome | 2 ++ client/package.json | 6 +++++- client/playwright.config.js | 11 ++++++++++- client/playwright.rome.config.js | 25 +++++++++++++++++++++++++ client/tests/e2e/signin.e2e.js | 4 ++-- 6 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 client/playwright.rome.config.js diff --git a/client/.env.development.imex b/client/.env.development.imex index ef94b0621..d1383e6ef 100644 --- a/client/.env.development.imex +++ b/client/.env.development.imex @@ -12,3 +12,5 @@ VITE_APP_AXIOS_BASE_API_URL=/api/ VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_INSTANCE=IMEX +TEST_USERNAME="test@imex.dev" +TEST_PASSWORD="test123" diff --git a/client/.env.development.rome b/client/.env.development.rome index 5d0c366fa..15408c90b 100644 --- a/client/.env.development.rome +++ b/client/.env.development.rome @@ -14,3 +14,5 @@ VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc VITE_APP_COUNTRY=USA VITE_APP_INSTANCE=ROME +TEST_USERNAME="test@imex.dev" +TEST_PASSWORD="test123" diff --git a/client/package.json b/client/package.json index 4f595d18c..db79ba1eb 100644 --- a/client/package.json +++ b/client/package.json @@ -102,7 +102,11 @@ "eulaize": "node src/utils/eulaize.js", "test:unit": "vitest run", "test:watch": "vitest", - "test:e2e": "playwright test" + "test:e2e:imex": "playwright test --config playwright.config.js", + "test:e2e:rome": "playwright test --config playwright.rome.config.js", + "test:e2e:imex:headed": "playwright test --config playwright.config.js --headed", + "test:e2e:rome:headed": "playwright test --config playwright.rome.config.js --headed", + "test:e2e:report": "playwright show-report" }, "browserslist": { "production": [ diff --git a/client/playwright.config.js b/client/playwright.config.js index 5f1d1ec3b..1ffc0d207 100644 --- a/client/playwright.config.js +++ b/client/playwright.config.js @@ -1,8 +1,16 @@ import { defineConfig } from "@playwright/test"; +import dotenv from "dotenv"; + +dotenv.config({ + path: "./.env.development.imex", + prefix: "TEST_" +}); export default defineConfig({ testDir: "./tests/e2e", testMatch: "*.e2e.js", + timeout: 60 * 1000, + reporter: [["list"], ["html"]], use: { baseURL: "https://localhost:3000", browser: "chromium", @@ -10,7 +18,8 @@ export default defineConfig({ }, webServer: { command: "npm run start:imex", - port: 3000, + ignoreHTTPSErrors: true, + url: "https://localhost:3000/health", // Health check endpoint will tell us when the server is ready reuseExistingServer: !process.env.CI // Reuse server locally, not in CI } }); diff --git a/client/playwright.rome.config.js b/client/playwright.rome.config.js new file mode 100644 index 000000000..8378df05c --- /dev/null +++ b/client/playwright.rome.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from "@playwright/test"; +import dotenv from "dotenv"; + +dotenv.config({ + path: "./.env.development.rome", + prefix: "TEST_" +}); + +export default defineConfig({ + testDir: "./tests/e2e", + testMatch: "*.e2e.js", + timeout: 60 * 1000, + reporter: [["list"], ["html"]], + use: { + baseURL: "https://localhost:3000", + browser: "chromium", + ignoreHTTPSErrors: true + }, + webServer: { + command: "npm run start:rome", + ignoreHTTPSErrors: true, + url: "https://localhost:3000/health", // Health check endpoint will tell us when the server is ready + reuseExistingServer: !process.env.CI // Reuse server locally, not in CI + } +}); diff --git a/client/tests/e2e/signin.e2e.js b/client/tests/e2e/signin.e2e.js index 4213c82ce..3ad1f874b 100644 --- a/client/tests/e2e/signin.e2e.js +++ b/client/tests/e2e/signin.e2e.js @@ -3,8 +3,8 @@ import { login } from "./utils/login"; test.describe("SignInComponent", () => { test("successfully logs in with valid credentials", async ({ page }) => { - const email = "dave@imex.dev"; - const password = "dave123"; + const email = process.env.TEST_USERNAME; + const password = process.env.TEST_PASSWORD; await login(page, { email, password }); From c8701aba638c178b49664dd0d50607961e3a60b4 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Tue, 1 Apr 2025 10:03:17 -0700 Subject: [PATCH 45/45] Add region capture to Crisp. --- client/src/redux/user/user.sagas.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 3b3a07c91..35f3d9d97 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -340,6 +340,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) { args: [], imex: () => { window.$crisp.push(["set", "user:company", [payload.shopname]]); + window.$crisp.push(["set", "session:segments", [[`region:${payload.region_config}`]]]); if (authRecord[0] && authRecord[0].user.validemail) { window.$crisp.push(["set", "user:email", [authRecord[0].user.email]]); }