diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ff3f95e0..df139e3e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [[0.12.2]](https://github.com/thoth-pub/thoth/releases/tag/v0.12.2) - 2024-04-16 +### Added + - [581](https://github.com/thoth-pub/thoth/issues/581) - Add crossmark policy DOI to imprint record + +### Changed + - [591](https://github.com/thoth-pub/thoth/pull/591) - Upgrade rust to `1.77.2` in production and development `Dockerfile` + - [591](https://github.com/thoth-pub/thoth/pull/591) - Added favicons to export API and GraphQL API docs + - [591](https://github.com/thoth-pub/thoth/pull/591) - Replaced static logo files with CDN paths + - [591](https://github.com/thoth-pub/thoth/pull/591) - Moved thoth CSS to root directory in thoth-app + - [591](https://github.com/thoth-pub/thoth/pull/591) - Replace unnecessary pageloader CSS with an actual loader + - [591](https://github.com/thoth-pub/thoth/pull/591) - Apply Thoth theming to rapidocs + - [591](https://github.com/thoth-pub/thoth/pull/591) - Upgrade `graphiql` to v3.2 + - [591](https://github.com/thoth-pub/thoth/pull/591) - Upgrade `trunk` to v0.19.2 + - [591](https://github.com/thoth-pub/thoth/pull/591) - Upgrade `wasm-bindgen` to v0.2.92 + +### Fixed + - [591](https://github.com/thoth-pub/thoth/pull/591) - Replaced broken logo URL in export API docs + ## [[0.12.1]](https://github.com/thoth-pub/thoth/releases/tag/v0.12.1) - 2024-04-8 ### Fixed - [589](https://github.com/thoth-pub/thoth/issues/589) - Truncation of `short_abstract` in Thoth ONIX results in Invalid UTF-8 sequences diff --git a/Cargo.lock b/Cargo.lock index 6293da86e..41df70c87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3087,7 +3087,7 @@ dependencies = [ [[package]] name = "thoth" -version = "0.12.1" +version = "0.12.2" dependencies = [ "cargo-husky", "clap", @@ -3102,7 +3102,7 @@ dependencies = [ [[package]] name = "thoth-api" -version = "0.12.1" +version = "0.12.2" dependencies = [ "actix-web", "argon2rs", @@ -3131,7 +3131,7 @@ dependencies = [ [[package]] name = "thoth-api-server" -version = "0.12.1" +version = "0.12.2" dependencies = [ "actix-cors", "actix-identity", @@ -3147,7 +3147,7 @@ dependencies = [ [[package]] name = "thoth-app" -version = "0.12.1" +version = "0.12.2" dependencies = [ "anyhow", "chrono", @@ -3176,7 +3176,7 @@ dependencies = [ [[package]] name = "thoth-app-server" -version = "0.12.1" +version = "0.12.2" dependencies = [ "actix-cors", "actix-web", @@ -3186,7 +3186,7 @@ dependencies = [ [[package]] name = "thoth-client" -version = "0.12.1" +version = "0.12.2" dependencies = [ "chrono", "graphql_client", @@ -3202,7 +3202,7 @@ dependencies = [ [[package]] name = "thoth-errors" -version = "0.12.1" +version = "0.12.2" dependencies = [ "actix-web", "csv", @@ -3223,7 +3223,7 @@ dependencies = [ [[package]] name = "thoth-export-server" -version = "0.12.1" +version = "0.12.2" dependencies = [ "actix-cors", "actix-web", @@ -3540,9 +3540,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", "serde", @@ -3552,9 +3552,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -3579,9 +3579,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3589,9 +3589,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -3602,9 +3602,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-logger" diff --git a/Cargo.toml b/Cargo.toml index 20f65dd89..69add2f8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth" -version = "0.12.1" +version = "0.12.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2021" license = "Apache-2.0" @@ -16,11 +16,11 @@ maintenance = { status = "actively-developed" } members = ["thoth-api", "thoth-api-server", "thoth-app", "thoth-app-server", "thoth-client", "thoth-errors", "thoth-export-server"] [dependencies] -thoth-api = { version = "=0.12.1", path = "thoth-api", features = ["backend"] } -thoth-api-server = { version = "=0.12.1", path = "thoth-api-server" } -thoth-app-server = { version = "=0.12.1", path = "thoth-app-server" } -thoth-errors = { version = "=0.12.1", path = "thoth-errors" } -thoth-export-server = { version = "=0.12.1", path = "thoth-export-server" } +thoth-api = { version = "0.12.2", path = "thoth-api", features = ["backend"] } +thoth-api-server = { version = "0.12.2", path = "thoth-api-server" } +thoth-app-server = { version = "0.12.2", path = "thoth-app-server" } +thoth-errors = { version = "0.12.2", path = "thoth-errors" } +thoth-export-server = { version = "0.12.2", path = "thoth-export-server" } clap = { version = "4.4.7", features = ["cargo", "env"] } dialoguer = { version = "0.11.0", features = ["password"] } dotenv = "0.15.0" diff --git a/Dockerfile b/Dockerfile index 08921587d..5fabc028b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG MUSL_IMAGE=clux/muslrust:1.76.0 +ARG MUSL_IMAGE=clux/muslrust:1.77.2-stable FROM ${MUSL_IMAGE} as build diff --git a/Dockerfile.dev b/Dockerfile.dev index 139cee26d..9f2ac2d13 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,4 +1,4 @@ -ARG RUST_VERSION=1.76.0 +ARG RUST_VERSION=1.77.2 FROM rust:${RUST_VERSION} diff --git a/thoth-api-server/Cargo.toml b/thoth-api-server/Cargo.toml index a748c3fa2..65b089a8b 100644 --- a/thoth-api-server/Cargo.toml +++ b/thoth-api-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-api-server" -version = "0.12.1" +version = "0.12.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2021" license = "Apache-2.0" @@ -9,8 +9,8 @@ repository = "https://github.com/thoth-pub/thoth" readme = "README.md" [dependencies] -thoth-api = { version = "0.12.1", path = "../thoth-api", features = ["backend"] } -thoth-errors = { version = "0.12.1", path = "../thoth-errors" } +thoth-api = { version = "0.12.2", path = "../thoth-api", features = ["backend"] } +thoth-errors = { version = "0.12.2", path = "../thoth-errors" } actix-web = "4.5.1" actix-cors = "0.7.0" actix-identity = "0.7.1" diff --git a/thoth-api-server/src/graphiql.rs b/thoth-api-server/src/graphiql.rs index 326571f53..b4f77587f 100644 --- a/thoth-api-server/src/graphiql.rs +++ b/thoth-api-server/src/graphiql.rs @@ -2,40 +2,28 @@ /// Generate the HTML source to show a GraphiQL interface pub fn graphiql_source(graphql_endpoint_url: &str) -> String { - let default_query = r#"# Welcome to Thoth's GraphQL API explorer (GraphiQL). + let version = env!("CARGO_PKG_VERSION"); + let default_query = r##"# Welcome to Thoth's GraphQL API explorer (GraphiQL). # # GraphiQL is an in-browser tool for writing, validating, and # testing GraphQL queries. # -# Type queries into this side of the screen, and you will see intelligent -# typeaheads aware of the current GraphQL type schema and live syntax and -# validation errors highlighted within the text. +# Type queries into this side of the screen, and you will see +# intelligent typeaheads aware of the current GraphQL type +# schema and live syntax and validation errors highlighted +# within the text. # -# Click on the QueryRoot in the Documentation Explorer ( < Docs ) on the -# right hand side of the screen to navigate the API schema. +# Click on the QueryRoot in the Documentation Explorer +# (first icon) on the top left of the screen to navigate +# the API schema. # -# GraphQL queries typically start with a "{" character. Lines that starts -# with a # are ignored. +# GraphQL queries typically start with a "{" character. +# Lines that starts with a "#" are ignored. # -# An example Thoth GraphQL query might look like: -# -# { -# books(workStatuses: [ACTIVE]) { -# fullTitle -# doi -# } -# } -# -# Keyboard shortcuts: +# Run the following example Thoth GraphQL query: # # Run Query: Ctrl-Enter (or press the play button above) # -# Auto Complete: Ctrl-Space (or just start typing) -# -# -# Run the following query (Ctrl-Enter): -# - { books(order: {field: PUBLICATION_DATE, direction: ASC}) { fullTitle @@ -50,62 +38,142 @@ pub fn graphiql_source(graphql_endpoint_url: &str) -> String { } } } -"#; +"##; format!( - r#" + r##" - - - - - Thoth GraphQL API Documentation - - - - - -
- - - - - - - + + + + + Thoth GraphQL API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loading...
+ + -"#, + +"##, ) } diff --git a/thoth-api/Cargo.toml b/thoth-api/Cargo.toml index 7672caf8f..02ba1078a 100644 --- a/thoth-api/Cargo.toml +++ b/thoth-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-api" -version = "0.12.1" +version = "0.12.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2021" license = "Apache-2.0" @@ -16,7 +16,7 @@ maintenance = { status = "actively-developed" } backend = ["diesel", "diesel-derive-enum", "diesel_migrations", "futures", "actix-web", "jsonwebtoken"] [dependencies] -thoth-errors = { version = "0.12.1", path = "../thoth-errors" } +thoth-errors = { version = "0.12.2", path = "../thoth-errors" } actix-web = { version = "4.5.1", optional = true } argon2rs = "0.2.5" isbn2 = "0.4.0" diff --git a/thoth-api/migrations/v0.12.2/down.sql b/thoth-api/migrations/v0.12.2/down.sql new file mode 100644 index 000000000..f21aa271a --- /dev/null +++ b/thoth-api/migrations/v0.12.2/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE imprint + DROP COLUMN crossmark_doi; diff --git a/thoth-api/migrations/v0.12.2/up.sql b/thoth-api/migrations/v0.12.2/up.sql new file mode 100644 index 000000000..9f2f56d91 --- /dev/null +++ b/thoth-api/migrations/v0.12.2/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE imprint + ADD COLUMN crossmark_doi TEXT CHECK (crossmark_doi ~* 'https:\/\/doi.org\/10.\d{4,9}\/[-._\;\(\)\/:a-zA-Z0-9]+$'); diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 6f608b9ca..5afc51f1d 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -3035,10 +3035,19 @@ impl Imprint { &self.imprint_name } + #[graphql(description = "URL of the imprint's landing page")] pub fn imprint_url(&self) -> Option<&String> { self.imprint_url.as_ref() } + #[graphql( + description = "DOI of the imprint's Crossmark policy page, if publisher participates. Crossmark 'gives readers quick and easy access to the + current status of an item of content, including any corrections, retractions, or updates'. More: https://www.crossref.org/services/crossmark/" + )] + pub fn crossmark_doi(&self) -> Option<&Doi> { + self.crossmark_doi.as_ref() + } + pub fn created_at(&self) -> Timestamp { self.created_at.clone() } diff --git a/thoth-api/src/model/imprint/crud.rs b/thoth-api/src/model/imprint/crud.rs index 6feea42c7..7f127576c 100644 --- a/thoth-api/src/model/imprint/crud.rs +++ b/thoth-api/src/model/imprint/crud.rs @@ -54,6 +54,10 @@ impl Crud for Imprint { Direction::Asc => query.order(imprint_url.asc()), Direction::Desc => query.order(imprint_url.desc()), }, + ImprintField::CrossmarkDoi => match order.direction { + Direction::Asc => query.order(crossmark_doi.asc()), + Direction::Desc => query.order(crossmark_doi.desc()), + }, ImprintField::CreatedAt => match order.direction { Direction::Asc => query.order(created_at.asc()), Direction::Desc => query.order(created_at.desc()), diff --git a/thoth-api/src/model/imprint/mod.rs b/thoth-api/src/model/imprint/mod.rs index a87b965f8..ceb1ad4db 100644 --- a/thoth-api/src/model/imprint/mod.rs +++ b/thoth-api/src/model/imprint/mod.rs @@ -1,3 +1,4 @@ +use crate::model::Doi; use serde::Deserialize; use serde::Serialize; use strum::Display; @@ -27,6 +28,8 @@ pub enum ImprintField { ImprintName, #[strum(serialize = "ImprintURL")] ImprintUrl, + #[strum(serialize = "CrossmarkDOI")] + CrossmarkDoi, CreatedAt, UpdatedAt, } @@ -39,6 +42,7 @@ pub struct Imprint { pub publisher_id: Uuid, pub imprint_name: String, pub imprint_url: Option, + pub crossmark_doi: Option, pub created_at: Timestamp, pub updated_at: Timestamp, } @@ -49,6 +53,7 @@ pub struct ImprintWithPublisher { pub imprint_id: Uuid, pub imprint_name: String, pub imprint_url: Option, + pub crossmark_doi: Option, pub updated_at: Timestamp, pub publisher: Publisher, } @@ -62,6 +67,7 @@ pub struct NewImprint { pub publisher_id: Uuid, pub imprint_name: String, pub imprint_url: Option, + pub crossmark_doi: Option, } #[cfg_attr( @@ -74,6 +80,7 @@ pub struct PatchImprint { pub publisher_id: Uuid, pub imprint_name: String, pub imprint_url: Option, + pub crossmark_doi: Option, } #[cfg_attr(feature = "backend", derive(Queryable))] @@ -118,6 +125,7 @@ fn test_imprintfield_display() { assert_eq!(format!("{}", ImprintField::ImprintId), "ID"); assert_eq!(format!("{}", ImprintField::ImprintName), "Imprint"); assert_eq!(format!("{}", ImprintField::ImprintUrl), "ImprintURL"); + assert_eq!(format!("{}", ImprintField::CrossmarkDoi), "CrossmarkDOI"); assert_eq!(format!("{}", ImprintField::CreatedAt), "CreatedAt"); assert_eq!(format!("{}", ImprintField::UpdatedAt), "UpdatedAt"); } @@ -137,6 +145,10 @@ fn test_imprintfield_fromstr() { ImprintField::from_str("ImprintURL").unwrap(), ImprintField::ImprintUrl ); + assert_eq!( + ImprintField::from_str("CrossmarkDOI").unwrap(), + ImprintField::CrossmarkDoi + ); assert_eq!( ImprintField::from_str("CreatedAt").unwrap(), ImprintField::CreatedAt diff --git a/thoth-api/src/schema.rs b/thoth-api/src/schema.rs index cada1078b..795ffa493 100644 --- a/thoth-api/src/schema.rs +++ b/thoth-api/src/schema.rs @@ -189,6 +189,7 @@ table! { publisher_id -> Uuid, imprint_name -> Text, imprint_url -> Nullable, + crossmark_doi -> Nullable, created_at -> Timestamptz, updated_at -> Timestamptz, } diff --git a/thoth-app-server/Cargo.toml b/thoth-app-server/Cargo.toml index 00d6fd500..0c281becb 100644 --- a/thoth-app-server/Cargo.toml +++ b/thoth-app-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-app-server" -version = "0.12.1" +version = "0.12.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2021" license = "Apache-2.0" diff --git a/thoth-app-server/build.rs b/thoth-app-server/build.rs index 0ddd2e2b9..84d963acf 100644 --- a/thoth-app-server/build.rs +++ b/thoth-app-server/build.rs @@ -2,7 +2,7 @@ use dotenv::dotenv; use std::env; use std::process::{exit, Command}; -const TRUNK_VERSION: &str = "0.18.8"; +const TRUNK_VERSION: &str = "0.19.2"; fn is_wasm_target_installed() -> bool { let output = Command::new("rustup") diff --git a/thoth-app-server/src/lib.rs b/thoth-app-server/src/lib.rs index 56165713e..4682f2871 100644 --- a/thoth-app-server/src/lib.rs +++ b/thoth-app-server/src/lib.rs @@ -4,6 +4,9 @@ use std::time::Duration; use actix_cors::Cors; use actix_web::{get, middleware::Logger, web, App, HttpResponse, HttpServer}; +mod manifest; +use crate::manifest::manifest_source; + const NO_CACHE: &str = "no-cache"; const LOG_FORMAT: &str = r#"%{r}a %a "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T"#; @@ -28,36 +31,7 @@ macro_rules! static_files { static_files! { (JS, js_file) => ("../static/pkg/thoth-app.js", "/admin/thoth-app.js", "application/javascript"), (WASM, wasm_file) => ("../static/pkg/thoth-app_bg.wasm", "/admin/thoth-app_bg.wasm", "application/wasm"), - (BULMA, bulma_file) => ("../static/pkg/bulma-pageloader.min.css", "/admin/bulma-pageloader.min.css", "text/css; charset=utf-8"), (CSS, css_file) => ("../static/pkg/thoth.css", "/admin/thoth.css", "text/css; charset=utf-8"), - (LOGO, logo_file) => ("../static/img/thoth-logo.png", "/admin/img/thoth-logo.png", "image/png"), - (XML, xml_file) => ("../static/browserconfig.xml", "/admin/browserconfig.xml", "application/xml"), - (JSON, json_file) => ("../static/manifest.json", "/admin/manifest.json", "application/json"), - (ICON, icon_file) => ("../static/img/favicon.ico", "/admin/favicon.ico", "image/x-icon"), - (ICON1, icon_file1) => ("../static/img/android-icon-144x144.png", "/admin/android-icon-144x144.png", "image/png"), - (ICON2, icon_file2) => ("../static/img/android-icon-192x192.png", "/admin/android-icon-192x192.png", "image/png"), - (ICON3, icon_file3) => ("../static/img/android-icon-36x36.png", "/admin/android-icon-36x36.png", "image/png"), - (ICON4, icon_file4) => ("../static/img/android-icon-48x48.png", "/admin/android-icon-48x48.png", "image/png"), - (ICON5, icon_file5) => ("../static/img/android-icon-72x72.png", "/admin/android-icon-72x72.png", "image/png"), - (ICON6, icon_file6) => ("../static/img/android-icon-96x96.png", "/admin/android-icon-96x96.png", "image/png"), - (ICON7, icon_file7) => ("../static/img/apple-icon-114x114.png", "/admin/apple-icon-114x114.png", "image/png"), - (ICON8, icon_file8) => ("../static/img/apple-icon-120x120.png", "/admin/apple-icon-120x120.png", "image/png"), - (ICON9, icon_file9) => ("../static/img/apple-icon-144x144.png", "/admin/apple-icon-144x144.png", "image/png"), - (ICON10, icon_file10) => ("../static/img/apple-icon-152x152.png", "/admin/apple-icon-152x152.png", "image/png"), - (ICON11, icon_file11) => ("../static/img/apple-icon-180x180.png", "/admin/apple-icon-180x180.png", "image/png"), - (ICON12, icon_file12) => ("../static/img/apple-icon-57x57.png", "/admin/apple-icon-57x57.png", "image/png"), - (ICON13, icon_file13) => ("../static/img/apple-icon-60x60.png", "/admin/apple-icon-60x60.png", "image/png"), - (ICON14, icon_file14) => ("../static/img/apple-icon-72x72.png", "/admin/apple-icon-72x72.png", "image/png"), - (ICON15, icon_file15) => ("../static/img/apple-icon-76x76.png", "/admin/apple-icon-76x76.png", "image/png"), - (ICON16, icon_file16) => ("../static/img/apple-icon-precomposed.png", "/admin/apple-icon-precomposed.png", "image/png"), - (ICON17, icon_file17) => ("../static/img/apple-icon.png", "/admin/apple-icon.png", "image/png"), - (ICON18, icon_file18) => ("../static/img/favicon-16x16.png", "/admin/favicon-16x16.png", "image/png"), - (ICON19, icon_file19) => ("../static/img/favicon-32x32.png", "/admin/favicon-32x32.png", "image/png"), - (ICON20, icon_file20) => ("../static/img/favicon-96x96.png", "/admin/favicon-96x96.png", "image/png"), - (ICON21, icon_file21) => ("../static/img/ms-icon-144x144.png", "/admin/ms-icon-144x144.png", "image/png"), - (ICON22, icon_file22) => ("../static/img/ms-icon-150x150.png", "/admin/ms-icon-150x150.png", "image/png"), - (ICON23, icon_file23) => ("../static/img/ms-icon-310x310.png", "/admin/ms-icon-310x310.png", "image/png"), - (ICON24, icon_file24) => ("../static/img/ms-icon-70x70.png", "/admin/ms-icon-70x70.png", "image/png"), } const INDEX_FILE: &[u8] = include_bytes!("../static/pkg/index.html"); @@ -69,6 +43,13 @@ async fn index() -> HttpResponse { .body(INDEX_FILE) } +#[get("/admin/manifest.json")] +async fn app_manifest() -> HttpResponse { + HttpResponse::Ok() + .content_type("application/json") + .body(manifest_source()) +} + #[actix_web::main] pub async fn start_server( host: String, @@ -84,6 +65,7 @@ pub async fn start_server( .wrap(Cors::default().allowed_methods(vec!["GET", "POST", "OPTIONS"])) .configure(config) .default_service(web::route().to(index)) + .service(app_manifest) }) .workers(threads) .keep_alive(Duration::from_secs(keep_alive)) diff --git a/thoth-app-server/src/manifest.rs b/thoth-app-server/src/manifest.rs new file mode 100644 index 000000000..6a7ff814d --- /dev/null +++ b/thoth-app-server/src/manifest.rs @@ -0,0 +1,58 @@ +//! Utility module to generate the manifest.json file + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub fn manifest_source() -> String { + format!( + r##" +{{ + "name": "Thoth", + "version": "{VERSION}", + "description": "Bibliographical metadata management system.", + "display": "standalone", + "scope": "/admin", + "start_url": ".", + "background_color": "#FFDD57", + "theme_color": "#FFDD57", + "icons": [ + {{ + "src": "https://cdn.thoth.pub/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }}, + {{ + "src": "https://cdn.thoth.pub/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }}, + {{ + "src": "https://cdn.thoth.pub/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }}, + {{ + "src": "https://cdn.thoth.pub/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }}, + {{ + "src": "https://cdn.thoth.pub/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }}, + {{ + "src": "https://cdn.thoth.pub/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + }} + ] +}} +"## + ) +} diff --git a/thoth-app/Cargo.toml b/thoth-app/Cargo.toml index 33eaf9958..843f17628 100644 --- a/thoth-app/Cargo.toml +++ b/thoth-app/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-app" -version = "0.12.1" +version = "0.12.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2021" license = "Apache-2.0" @@ -36,8 +36,8 @@ uuid = { version = "0.8.2", features = ["serde", "v4"] } # `getrandom` is a dependency of `uuid`, we need to explicitly import and include the `js` feature to enable wasm # https://docs.rs/getrandom/latest/getrandom/#webassembly-support getrandom = { version = "0.2", features = ["js"] } -thoth-api = { version = "0.12.1", path = "../thoth-api" } -thoth-errors = { version = "0.12.1", path = "../thoth-errors" } +thoth-api = { version = "0.12.2", path = "../thoth-api" } +thoth-errors = { version = "0.12.2", path = "../thoth-errors" } [build-dependencies] dotenv = "0.15.0" diff --git a/thoth-app/Trunk.toml b/thoth-app/Trunk.toml index 2a31d91eb..f5c75869e 100644 --- a/thoth-app/Trunk.toml +++ b/thoth-app/Trunk.toml @@ -12,5 +12,5 @@ dist = "pkg" [tools] # Default wasm-bindgen version to download. -wasm_bindgen = "0.2.89" +wasm_bindgen = "0.2.92" diff --git a/thoth-app/browserconfig.xml b/thoth-app/browserconfig.xml deleted file mode 100644 index 28b1c0e42..000000000 --- a/thoth-app/browserconfig.xml +++ /dev/null @@ -1,2 +0,0 @@ - -#ffdd57 diff --git a/thoth-app/css/bulma-pageloader.min.css b/thoth-app/css/bulma-pageloader.min.css deleted file mode 100644 index 72334bf86..000000000 --- a/thoth-app/css/bulma-pageloader.min.css +++ /dev/null @@ -1 +0,0 @@ -@-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.pageloader{bottom:0;left:0;position:absolute;right:0;top:0}.pageloader{position:fixed;padding-top:2em;background:#00d1b2;background:#00d1b2;z-index:999998;transition:transform .35s ease-out,-webkit-transform .35s ease-out;will-change:transform}.pageloader.is-white{background-color:#fff;background:#fff}.pageloader.is-white::after{border-color:#0a0a0a;-webkit-animation:loader-figure-white 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-white 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-white .title{color:#0a0a0a}.pageloader.is-black{background-color:#0a0a0a;background:#0a0a0a}.pageloader.is-black::after{border-color:#fff;-webkit-animation:loader-figure-black 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-black 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-black .title{color:#fff}.pageloader.is-light{background-color:#f5f5f5;background:#f5f5f5}.pageloader.is-light::after{border-color:#363636;-webkit-animation:loader-figure-light 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-light 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-light .title{color:#363636}.pageloader.is-dark{background-color:#363636;background:#363636}.pageloader.is-dark::after{border-color:#f5f5f5;-webkit-animation:loader-figure-dark 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-dark 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-dark .title{color:#f5f5f5}.pageloader.is-primary{background-color:#00d1b2;background:#00d1b2}.pageloader.is-primary::after{border-color:#fff;-webkit-animation:loader-figure-primary 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-primary 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-primary .title{color:#fff}.pageloader.is-link{background-color:#3273dc;background:#3273dc}.pageloader.is-link::after{border-color:#fff;-webkit-animation:loader-figure-link 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-link 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-link .title{color:#fff}.pageloader.is-info{background-color:#209cee;background:#209cee}.pageloader.is-info::after{border-color:#fff;-webkit-animation:loader-figure-info 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-info 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-info .title{color:#fff}.pageloader.is-success{background-color:#23d160;background:#23d160}.pageloader.is-success::after{border-color:#fff;-webkit-animation:loader-figure-success 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-success 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-success .title{color:#fff}.pageloader.is-warning{background-color:#ffdd57;background:#ffdd57}.pageloader.is-warning::after{border-color:rgba(0,0,0,.7);-webkit-animation:loader-figure-warning 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-warning 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-warning .title{color:rgba(0,0,0,.7)}.pageloader.is-danger{background-color:#ff3860;background:#ff3860}.pageloader.is-danger::after{border-color:#fff;-webkit-animation:loader-figure-danger 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure-danger 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader.is-danger .title{color:#fff}.pageloader:not(.is-bottom-to-top){-webkit-transform:translateY(-100%);transform:translateY(-100%)}.pageloader.is-bottom-to-top{-webkit-transform:translateY(100%);transform:translateY(100%)}.pageloader.is-left-to-right{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.pageloader.is-right-to-left{-webkit-transform:translateX(100%);transform:translateX(100%)}.pageloader.is-active:not(.is-left-to-right),.pageloader.is-active:not(.is-right-to-left){-webkit-transform:translateY(0);transform:translateY(0)}.pageloader.is-active.is-left-to-right,.pageloader.is-active.is-right-to-left{-webkit-transform:translateX(0);transform:translateX(0)}.pageloader::after{position:absolute;top:50%;left:50%;display:block;border-radius:100%;content:'';z-index:9999;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:0;height:0;box-sizing:border-box;border:0 solid #fff;-webkit-animation:loader-figure 1.15s infinite cubic-bezier(.215,.61,.355,1);animation:loader-figure 1.15s infinite cubic-bezier(.215,.61,.355,1)}.pageloader .title{position:absolute;top:50%;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);margin:2em 0 0 0;font-size:.875em;letter-spacing:.1em;line-height:1.5em;color:#fff;white-space:nowrap}@-webkit-keyframes loader-figure{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-white{0%{height:0;width:0;background-color:#0a0a0a}29%{background-color:#0a0a0a}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-white{0%{height:0;width:0;background-color:#0a0a0a}29%{background-color:#0a0a0a}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-black{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-black{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-light{0%{height:0;width:0;background-color:#363636}29%{background-color:#363636}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-light{0%{height:0;width:0;background-color:#363636}29%{background-color:#363636}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-dark{0%{height:0;width:0;background-color:#f5f5f5}29%{background-color:#f5f5f5}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-dark{0%{height:0;width:0;background-color:#f5f5f5}29%{background-color:#f5f5f5}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-primary{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-primary{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-link{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-link{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-info{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-info{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-success{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-success{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-warning{0%{height:0;width:0;background-color:rgba(0,0,0,.7)}29%{background-color:rgba(0,0,0,.7)}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-warning{0%{height:0;width:0;background-color:rgba(0,0,0,.7)}29%{background-color:rgba(0,0,0,.7)}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@-webkit-keyframes loader-figure-danger{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}}@keyframes loader-figure-danger{0%{height:0;width:0;background-color:#fff}29%{background-color:#fff}30%{height:2em;width:2em;background-color:transparent;border-width:1em;opacity:1}100%{height:2em;width:2em;border-width:0;opacity:0;background-color:transparent}} diff --git a/thoth-app/css/thoth.css b/thoth-app/css/thoth.css deleted file mode 100644 index eb821bc13..000000000 --- a/thoth-app/css/thoth.css +++ /dev/null @@ -1,120 +0,0 @@ -.contributor:last-child > span { - display: none; -} - -.license { - width: 100% !important; - margin-top: 0.5em; -} - -.license > svg { - margin-left: 0.2em; -} - -.row { - cursor: pointer; -} - -.fixed-right { - float: right; - position: fixed; - right: 0; - z-index: 1; -} - -.dropdown-item { - cursor: pointer; -} - - -.field.is-horizontal > .field:not(:last-child) { - margin-right: .75em; -} - -.home-banner { - max-height: 350px; -} - -.home-icons { - margin: 6rem auto 0; - max-width: 1080px; -} - -.home-icons-item .item { - transition-duration: 172ms; - transition-property: color; -} - -.home-icons-item .subtitle { - color: #000000B0; -} - -.home-icons-item:nth-child(1):hover .title { - color: #53C2E6; -} - -.home-icons-item:nth-child(2):hover .title { - color: #FF8D41; -} - -.home-icons-item:nth-child(3):hover .title { - color: #00A15B; -} - -.home-icons-item:nth-child(4):hover .title { - color: #D04F54; -} - -.home-icons-item:nth-child(5):hover .title { - color: #7E308E; -} - -.home-icons-item:nth-child(1) figure { - color: #53C2E6; -} - -.home-icons-item:nth-child(2) figure { - color: #FF8D41; -} - -.home-icons-item:nth-child(3) figure { - color: #00A15B; -} - -.home-icons-item:nth-child(4) figure { - color: #D04F54; -} - -.home-icons-item:nth-child(5) figure { - color: #7E308E; -} - -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - display: block; -} - -.button.primary { - color: #ffffff; - background-color: #8c3f8d; - border-width: 2px; - border-radius: .375rem; - border-color: #8c3f8d; - font-weight: bold; -} -.button.primary:hover { - background-color: #af4fb0; -} -.version { - color: #f14668; - padding-left: 1em; - padding-right: 1em; - padding-bottom: calc(.5em - 1px); - font-weight: bold; -} -.version:hover { - text-decoration: underline; - color: #f14668; -} \ No newline at end of file diff --git a/thoth-app/img/android-icon-144x144.png b/thoth-app/img/android-icon-144x144.png deleted file mode 100644 index d2ac151d0..000000000 Binary files a/thoth-app/img/android-icon-144x144.png and /dev/null differ diff --git a/thoth-app/img/android-icon-192x192.png b/thoth-app/img/android-icon-192x192.png deleted file mode 100644 index 83fe4eecf..000000000 Binary files a/thoth-app/img/android-icon-192x192.png and /dev/null differ diff --git a/thoth-app/img/android-icon-36x36.png b/thoth-app/img/android-icon-36x36.png deleted file mode 100644 index fbea7e33a..000000000 Binary files a/thoth-app/img/android-icon-36x36.png and /dev/null differ diff --git a/thoth-app/img/android-icon-48x48.png b/thoth-app/img/android-icon-48x48.png deleted file mode 100644 index d1fe9cbee..000000000 Binary files a/thoth-app/img/android-icon-48x48.png and /dev/null differ diff --git a/thoth-app/img/android-icon-72x72.png b/thoth-app/img/android-icon-72x72.png deleted file mode 100644 index 4b01334c5..000000000 Binary files a/thoth-app/img/android-icon-72x72.png and /dev/null differ diff --git a/thoth-app/img/android-icon-96x96.png b/thoth-app/img/android-icon-96x96.png deleted file mode 100644 index c6229d7c6..000000000 Binary files a/thoth-app/img/android-icon-96x96.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-114x114.png b/thoth-app/img/apple-icon-114x114.png deleted file mode 100644 index 0d953a77a..000000000 Binary files a/thoth-app/img/apple-icon-114x114.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-120x120.png b/thoth-app/img/apple-icon-120x120.png deleted file mode 100644 index 3f921dc99..000000000 Binary files a/thoth-app/img/apple-icon-120x120.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-144x144.png b/thoth-app/img/apple-icon-144x144.png deleted file mode 100644 index d2ac151d0..000000000 Binary files a/thoth-app/img/apple-icon-144x144.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-152x152.png b/thoth-app/img/apple-icon-152x152.png deleted file mode 100644 index b6ae7714a..000000000 Binary files a/thoth-app/img/apple-icon-152x152.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-180x180.png b/thoth-app/img/apple-icon-180x180.png deleted file mode 100644 index 83bfeb120..000000000 Binary files a/thoth-app/img/apple-icon-180x180.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-57x57.png b/thoth-app/img/apple-icon-57x57.png deleted file mode 100644 index b8b2f85b8..000000000 Binary files a/thoth-app/img/apple-icon-57x57.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-60x60.png b/thoth-app/img/apple-icon-60x60.png deleted file mode 100644 index c3d05825a..000000000 Binary files a/thoth-app/img/apple-icon-60x60.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-72x72.png b/thoth-app/img/apple-icon-72x72.png deleted file mode 100644 index 4b01334c5..000000000 Binary files a/thoth-app/img/apple-icon-72x72.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-76x76.png b/thoth-app/img/apple-icon-76x76.png deleted file mode 100644 index 4ab2ea5a1..000000000 Binary files a/thoth-app/img/apple-icon-76x76.png and /dev/null differ diff --git a/thoth-app/img/apple-icon-precomposed.png b/thoth-app/img/apple-icon-precomposed.png deleted file mode 100644 index 5fef37e97..000000000 Binary files a/thoth-app/img/apple-icon-precomposed.png and /dev/null differ diff --git a/thoth-app/img/apple-icon.png b/thoth-app/img/apple-icon.png deleted file mode 100644 index 5fef37e97..000000000 Binary files a/thoth-app/img/apple-icon.png and /dev/null differ diff --git a/thoth-app/img/favicon-16x16.png b/thoth-app/img/favicon-16x16.png deleted file mode 100644 index 740812383..000000000 Binary files a/thoth-app/img/favicon-16x16.png and /dev/null differ diff --git a/thoth-app/img/favicon-32x32.png b/thoth-app/img/favicon-32x32.png deleted file mode 100644 index 2a5a7bb85..000000000 Binary files a/thoth-app/img/favicon-32x32.png and /dev/null differ diff --git a/thoth-app/img/favicon-96x96.png b/thoth-app/img/favicon-96x96.png deleted file mode 100644 index c6229d7c6..000000000 Binary files a/thoth-app/img/favicon-96x96.png and /dev/null differ diff --git a/thoth-app/img/favicon.ico b/thoth-app/img/favicon.ico deleted file mode 100644 index a7ee22dde..000000000 Binary files a/thoth-app/img/favicon.ico and /dev/null differ diff --git a/thoth-app/img/ms-icon-144x144.png b/thoth-app/img/ms-icon-144x144.png deleted file mode 100644 index d2ac151d0..000000000 Binary files a/thoth-app/img/ms-icon-144x144.png and /dev/null differ diff --git a/thoth-app/img/ms-icon-150x150.png b/thoth-app/img/ms-icon-150x150.png deleted file mode 100644 index 4f20ef8b3..000000000 Binary files a/thoth-app/img/ms-icon-150x150.png and /dev/null differ diff --git a/thoth-app/img/ms-icon-310x310.png b/thoth-app/img/ms-icon-310x310.png deleted file mode 100644 index 1fc0fea22..000000000 Binary files a/thoth-app/img/ms-icon-310x310.png and /dev/null differ diff --git a/thoth-app/img/ms-icon-70x70.png b/thoth-app/img/ms-icon-70x70.png deleted file mode 100644 index f6276fad0..000000000 Binary files a/thoth-app/img/ms-icon-70x70.png and /dev/null differ diff --git a/thoth-app/img/thoth-logo.png b/thoth-app/img/thoth-logo.png deleted file mode 100644 index f80aeaf71..000000000 Binary files a/thoth-app/img/thoth-logo.png and /dev/null differ diff --git a/thoth-app/index.html b/thoth-app/index.html index ac653d1ee..557d0a5ff 100644 --- a/thoth-app/index.html +++ b/thoth-app/index.html @@ -7,31 +7,51 @@ Thoth - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + + - - - - + + - + +
+
+
+
+
+
+
+
+
+
+ + + + + + + +
+
+ diff --git a/thoth-app/manifest.json b/thoth-app/manifest.json deleted file mode 100644 index b95de0043..000000000 --- a/thoth-app/manifest.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "Thoth", - "description": "Bibliographical metadata management system.", - "dir": "auto", - "lang": "en-GB", - "display": "standalone", - "orientation": "portrait", - "scope": "/", - "start_url": "/?homescreen=1", - "background_color": "#ffffff", - "theme_color": "#ffdd57", - "version": "0.12.1", - "icons": [ - { - "src": "\/admin\/android-icon-36x36.png", - "sizes": "36x36", - "type": "image\/png", - "density": "0.75" - }, - { - "src": "\/admin\/android-icon-48x48.png", - "sizes": "48x48", - "type": "image\/png", - "density": "1.0" - }, - { - "src": "\/admin\/android-icon-72x72.png", - "sizes": "72x72", - "type": "image\/png", - "density": "1.5" - }, - { - "src": "\/admin\/android-icon-96x96.png", - "sizes": "96x96", - "type": "image\/png", - "density": "2.0" - }, - { - "src": "\/admin\/android-icon-144x144.png", - "sizes": "144x144", - "type": "image\/png", - "density": "3.0" - }, - { - "src": "\/admin\/android-icon-192x192.png", - "sizes": "192x192", - "type": "image\/png", - "density": "4.0" - } - ] -} diff --git a/thoth-app/src/component/imprint.rs b/thoth-app/src/component/imprint.rs index 247b23ebc..7ee396651 100644 --- a/thoth-app/src/component/imprint.rs +++ b/thoth-app/src/component/imprint.rs @@ -2,6 +2,7 @@ use thoth_api::account::model::AccountAccess; use thoth_api::account::model::AccountDetails; use thoth_api::model::imprint::ImprintWithPublisher; use thoth_api::model::publisher::Publisher; +use thoth_api::model::{Doi, DOI_DOMAIN}; use thoth_errors::ThothError; use uuid::Uuid; use yew::html; @@ -21,6 +22,7 @@ use crate::agent::notification_bus::Request; use crate::component::delete_dialogue::ConfirmDeleteComponent; use crate::component::utils::FormPublisherSelect; use crate::component::utils::FormTextInput; +use crate::component::utils::FormTextInputExtended; use crate::component::utils::FormUrlInput; use crate::component::utils::Loader; use crate::models::imprint::delete_imprint_mutation::DeleteImprintRequest; @@ -59,6 +61,9 @@ pub struct ImprintComponent { notification_bus: NotificationDispatcher, // Store props value locally in order to test whether it has been updated on props change resource_access: AccountAccess, + // Track the user-entered DOI string, which may not be validly formatted + crossmark_doi: String, + crossmark_doi_warning: String, } #[derive(Default)] @@ -78,6 +83,7 @@ pub enum Msg { ChangePublisher(Uuid), ChangeImprintName(String), ChangeImprintUrl(String), + ChangeCrossmarkDoi(String), } #[derive(PartialEq, Eq, Properties)] @@ -99,6 +105,8 @@ impl Component for ImprintComponent { let notification_bus = NotificationBus::dispatcher(); let imprint: ImprintWithPublisher = Default::default(); let resource_access = ctx.props().current_user.resource_access.clone(); + let crossmark_doi = Default::default(); + let crossmark_doi_warning = Default::default(); ctx.link().send_message(Msg::GetImprint); ctx.link().send_message(Msg::GetPublishers); @@ -112,6 +120,8 @@ impl Component for ImprintComponent { fetch_publishers, notification_bus, resource_access, + crossmark_doi, + crossmark_doi_warning, } } @@ -154,6 +164,13 @@ impl Component for ImprintComponent { Some(c) => c.to_owned(), None => Default::default(), }; + // Initialise user-entered DOI variable to match DOI in database + self.crossmark_doi = self + .imprint + .crossmark_doi + .clone() + .unwrap_or_default() + .to_string(); // If user doesn't have permission to edit this object, redirect to dashboard if let Some(publishers) = ctx.props().current_user.resource_access.restricted_to() @@ -192,6 +209,13 @@ impl Component for ImprintComponent { FetchState::Fetching(_) => false, FetchState::Fetched(body) => match &body.data.update_imprint { Some(i) => { + self.crossmark_doi = self + .imprint + .crossmark_doi + .clone() + .unwrap_or_default() + .to_string(); + self.crossmark_doi_warning.clear(); self.notification_bus.send(Request::NotificationBusMsg(( format!("Saved {}", i.imprint_name), NotificationStatus::Success, @@ -216,11 +240,20 @@ impl Component for ImprintComponent { } } Msg::UpdateImprint => { + // Only update the DOI value with the current user-entered string + // if it is validly formatted - otherwise keep the default. + // If no DOI was provided, no format check is required. + if self.crossmark_doi.is_empty() { + self.imprint.crossmark_doi.neq_assign(None); + } else if let Ok(result) = self.crossmark_doi.parse::() { + self.imprint.crossmark_doi.neq_assign(Some(result)); + } let body = UpdateImprintRequestBody { variables: UpdateVariables { imprint_id: self.imprint.imprint_id, imprint_name: self.imprint.imprint_name.clone(), imprint_url: self.imprint.imprint_url.clone(), + crossmark_doi: self.imprint.crossmark_doi.clone(), publisher_id: self.imprint.publisher.publisher_id, }, ..Default::default() @@ -299,6 +332,27 @@ impl Component for ImprintComponent { Msg::ChangeImprintUrl(value) => { self.imprint.imprint_url.neq_assign(value.to_opt_string()) } + Msg::ChangeCrossmarkDoi(value) => { + if self.crossmark_doi.neq_assign(value.trim().to_owned()) { + // If DOI is not correctly formatted, display a warning. + // Don't update self.imprint.crossmark_doi yet, as user may later + // overwrite a new valid value with an invalid one. + self.crossmark_doi_warning.clear(); + match self.crossmark_doi.parse::() { + Err(e) => { + match e { + // If no DOI was provided, no warning is required. + ThothError::DoiEmptyError => {} + _ => self.crossmark_doi_warning = e.to_string(), + } + } + Ok(value) => self.crossmark_doi = value.to_string(), + } + true + } else { + false + } + } } } @@ -360,6 +414,13 @@ impl Component for ImprintComponent { value={ self.imprint.imprint_url.clone() } oninput={ ctx.link().callback(|e: InputEvent| Msg::ChangeImprintUrl(e.to_value())) } /> +
diff --git a/thoth-app/src/component/navbar.rs b/thoth-app/src/component/navbar.rs index 6210ecda9..05b6454ff 100644 --- a/thoth-app/src/component/navbar.rs +++ b/thoth-app/src/component/navbar.rs @@ -44,7 +44,8 @@ impl Component for NavbarComponent {