diff --git a/.editorconfig b/.editorconfig index 1fd3f983e..770deb350 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ root = true charset=utf-8 end_of_line = lf -[*.{ts,tsx}] +[*.{ts,tsx,css}] indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true diff --git a/crates/handlers/src/upstream_oauth2/link.rs b/crates/handlers/src/upstream_oauth2/link.rs index 364694dd8..6e430e0f5 100644 --- a/crates/handlers/src/upstream_oauth2/link.rs +++ b/crates/handlers/src/upstream_oauth2/link.rs @@ -111,8 +111,8 @@ impl IntoResponse for RouteError { .with_details(details); FancyError::new(ctx).into_response() } - Self::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - e => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), + Self::Internal(e) => FancyError::from(e).into_response(), + e => FancyError::from(e).into_response(), }; (SentryEventID::from(event_id), response).into_response() diff --git a/crates/templates/src/functions.rs b/crates/templates/src/functions.rs index cb81f75dd..eac977975 100644 --- a/crates/templates/src/functions.rs +++ b/crates/templates/src/functions.rs @@ -21,7 +21,7 @@ use std::{ collections::{BTreeSet, HashMap}, fmt::Formatter, str::FromStr, - sync::Arc, + sync::{atomic::AtomicUsize, Arc}, }; use camino::Utf8Path; @@ -49,6 +49,7 @@ pub fn register( env.add_filter("add_slashes", filter_add_slashes); env.add_filter("split", filter_split); env.add_function("add_params_to_url", function_add_params_to_url); + env.add_function("counter", || Ok(Value::from_object(Counter::default()))); env.add_global( "include_asset", Value::from_object(IncludeAsset { @@ -377,3 +378,45 @@ impl Object for IncludeAsset { Ok(Value::from_safe_string(tags.join("\n"))) } } + +#[derive(Debug, Default)] +struct Counter { + count: AtomicUsize, +} + +impl std::fmt::Display for Counter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + self.count.load(std::sync::atomic::Ordering::Relaxed) + ) + } +} + +impl Object for Counter { + fn call_method(&self, _state: &State, name: &str, args: &[Value]) -> Result { + // None of the methods take any arguments + from_args::<()>(args)?; + + match name { + "reset" => { + self.count.store(0, std::sync::atomic::Ordering::Relaxed); + Ok(Value::UNDEFINED) + } + "next" => { + let old = self + .count + .fetch_add(1, std::sync::atomic::Ordering::Relaxed); + Ok(Value::from(old)) + } + "peek" => Ok(Value::from( + self.count.load(std::sync::atomic::Ordering::Relaxed), + )), + _ => Err(Error::new( + ErrorKind::InvalidOperation, + "Invalid method on counter", + )), + } + } +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 90cf287df..6630b2918 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@emotion/react": "^11.11.1", + "@fontsource/inconsolata": "^5.0.15", "@fontsource/inter": "^5.0.15", "@radix-ui/react-alert-dialog": "^1.0.5", "@types/ua-parser-js": "^0.7.38", @@ -18,7 +19,7 @@ "@urql/exchange-refocus": "^1.0.2", "@urql/exchange-request-policy": "^1.0.2", "@vector-im/compound-design-tokens": "^0.0.6", - "@vector-im/compound-web": "^0.5.4", + "@vector-im/compound-web": "^0.6.0", "classnames": "^2.3.2", "date-fns": "^2.30.0", "graphql": "^16.8.1", @@ -61,6 +62,7 @@ "happy-dom": "^12.9.1", "i18next-parser": "^8.9.0", "postcss": "^8.4.31", + "postcss-modules": "^6.0.0", "prettier": "3.0.3", "react-test-renderer": "^18.2.0", "rimraf": "^5.0.5", @@ -3179,6 +3181,11 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, + "node_modules/@fontsource/inconsolata": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@fontsource/inconsolata/-/inconsolata-5.0.15.tgz", + "integrity": "sha512-xqFvxBMaYvRSwam5oc7ofc80yvEMkYgrPOpqS9WL+FKTp0jEHCwYaWxHmyJyFcuDcKwo3EnrsAm000L3vS+vMw==" + }, "node_modules/@fontsource/inter": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.0.15.tgz", @@ -9448,9 +9455,9 @@ } }, "node_modules/@vector-im/compound-web": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@vector-im/compound-web/-/compound-web-0.5.4.tgz", - "integrity": "sha512-w4Nwzid5Y89Dt9GaxKO+kWPTjSitLpkmoAjMYHVUajNMCfUxluzu4eOgjPRCpubPH5lZUB6/95y43wOI+pEC1Q==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@vector-im/compound-web/-/compound-web-0.6.0.tgz", + "integrity": "sha512-eGbl3FofxR9hC2dCs531o/5DleKyh0ANY1v1C9cuF5kfBaQHwwt+e9tJoTqiVRDwH4widJ+o4tluDYEGIDGaHg==", "dependencies": { "@radix-ui/react-form": "^0.0.3", "@radix-ui/react-tooltip": "^1.0.6", @@ -9458,6 +9465,7 @@ "graphemer": "^1.4.0" }, "peerDependencies": { + "@fontsource/inconsolata": "^5", "@fontsource/inter": "^5", "@types/react": "*", "@types/react-dom": "*", @@ -15083,6 +15091,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "dependencies": { + "loader-utils": "^3.2.0" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -16355,6 +16372,18 @@ "node": ">=0.10.0" } }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -18169,6 +18198,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/local-pkg": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", @@ -18202,6 +18240,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, "node_modules/lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -19775,6 +19819,84 @@ } } }, + "node_modules/postcss-modules": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", + "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==", + "dev": true, + "dependencies": { + "generic-names": "^4.0.0", + "icss-utils": "^5.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/postcss-nested": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", @@ -21805,6 +21927,12 @@ "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", "dev": true }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, "node_modules/string-natural-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 319a59068..165c07cb9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@emotion/react": "^11.11.1", + "@fontsource/inconsolata": "^5.0.15", "@fontsource/inter": "^5.0.15", "@radix-ui/react-alert-dialog": "^1.0.5", "@types/ua-parser-js": "^0.7.38", @@ -26,7 +27,7 @@ "@urql/exchange-refocus": "^1.0.2", "@urql/exchange-request-policy": "^1.0.2", "@vector-im/compound-design-tokens": "^0.0.6", - "@vector-im/compound-web": "^0.5.4", + "@vector-im/compound-web": "^0.6.0", "classnames": "^2.3.2", "date-fns": "^2.30.0", "graphql": "^16.8.1", @@ -69,6 +70,7 @@ "happy-dom": "^12.9.1", "i18next-parser": "^8.9.0", "postcss": "^8.4.31", + "postcss-modules": "^6.0.0", "prettier": "3.0.3", "react-test-renderer": "^18.2.0", "rimraf": "^5.0.5", diff --git a/frontend/src/components/ConfirmationModal/__snapshots__/ConfirmationModal.test.tsx.snap b/frontend/src/components/ConfirmationModal/__snapshots__/ConfirmationModal.test.tsx.snap index 85751654a..5b387fcbd 100644 --- a/frontend/src/components/ConfirmationModal/__snapshots__/ConfirmationModal.test.tsx.snap +++ b/frontend/src/components/ConfirmationModal/__snapshots__/ConfirmationModal.test.tsx.snap @@ -25,7 +25,7 @@ exports[` > opens modal on clicking trigger 1`] = ` class="_buttons_6bc2cb" >