From 63c8798264fd0237d4f8ce08484802f5f80decf9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 30 Jun 2023 12:03:22 +0200 Subject: [PATCH 01/35] :arrow_up: Update backend and common dependencies --- backend/deps.edn | 20 ++++++++++---------- common/deps.edn | 29 +++++++++++++---------------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/backend/deps.edn b/backend/deps.edn index 742a29217a..0b4e5180a4 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -6,7 +6,7 @@ org.clojure/clojure {:mvn/version "1.11.1"} org.clojure/core.async {:mvn/version "1.6.673"} - com.github.luben/zstd-jni {:mvn/version "1.5.2-5"} + com.github.luben/zstd-jni {:mvn/version "1.5.5-4"} io.prometheus/simpleclient {:mvn/version "0.16.0"} io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"} @@ -17,7 +17,7 @@ io.prometheus/simpleclient_httpserver {:mvn/version "0.16.0"} - io.lettuce/lettuce-core {:mvn/version "6.2.2.RELEASE"} + io.lettuce/lettuce-core {:mvn/version "6.2.4.RELEASE"} java-http-clj/java-http-clj {:mvn/version "0.4.3"} funcool/yetti @@ -26,8 +26,8 @@ :git/url "https://github.com/funcool/yetti.git" :exclusions [org.slf4j/slf4j-api]} - com.github.seancorfield/next.jdbc {:mvn/version "1.3.847"} - metosin/reitit-core {:mvn/version "0.5.18"} + com.github.seancorfield/next.jdbc {:mvn/version "1.3.883"} + metosin/reitit-core {:mvn/version "0.6.0"} org.postgresql/postgresql {:mvn/version "42.6.0"} @@ -35,12 +35,12 @@ io.whitfin/siphash {:mvn/version "2.0.0"} - buddy/buddy-hashers {:mvn/version "1.8.158"} - buddy/buddy-sign {:mvn/version "3.4.333"} + buddy/buddy-hashers {:mvn/version "2.0.167"} + buddy/buddy-sign {:mvn/version "3.5.351"} - com.github.ben-manes.caffeine/caffeine {:mvn/version "3.1.5"} + com.github.ben-manes.caffeine/caffeine {:mvn/version "3.1.6"} - org.jsoup/jsoup {:mvn/version "1.15.3"} + org.jsoup/jsoup {:mvn/version "1.16.1"} org.im4java/im4java {:git/tag "1.4.0-penpot-2" :git/sha "e2b3e16" @@ -49,14 +49,14 @@ org.lz4/lz4-java {:mvn/version "1.8.0"} org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"} - integrant/integrant {:mvn/version "0.8.0"} + integrant/integrant {:mvn/version "0.8.1"} dawran6/emoji {:mvn/version "0.1.5"} markdown-clj/markdown-clj {:mvn/version "1.11.4"} ;; Pretty Print specs pretty-spec/pretty-spec {:mvn/version "0.1.4"} - software.amazon.awssdk/s3 {:mvn/version "2.19.29"} + software.amazon.awssdk/s3 {:mvn/version "2.20.96"} } :paths ["src" "resources" "target/classes"] diff --git a/common/deps.edn b/common/deps.edn index 5ff183c57a..28c4b5b9c6 100644 --- a/common/deps.edn +++ b/common/deps.edn @@ -1,40 +1,37 @@ {:deps {org.clojure/clojure {:mvn/version "1.11.1"} org.clojure/data.json {:mvn/version "2.4.0"} - org.clojure/tools.cli {:mvn/version "1.0.214"} + org.clojure/tools.cli {:mvn/version "1.0.219"} org.clojure/clojurescript {:mvn/version "1.11.60"} org.clojure/test.check {:mvn/version "1.1.1"} org.clojure/data.fressian {:mvn/version "1.0.0"} ;; Logging - org.apache.logging.log4j/log4j-api {:mvn/version "2.19.0"} - org.apache.logging.log4j/log4j-core {:mvn/version "2.19.0"} - org.apache.logging.log4j/log4j-web {:mvn/version "2.19.0"} - org.apache.logging.log4j/log4j-jul {:mvn/version "2.19.0"} - org.apache.logging.log4j/log4j-slf4j2-impl {:mvn/version "2.19.0"} - org.slf4j/slf4j-api {:mvn/version "2.0.6"} - pl.tkowalcz.tjahzi/log4j2-appender {:mvn/version "0.9.26"} + org.apache.logging.log4j/log4j-api {:mvn/version "2.20.0"} + org.apache.logging.log4j/log4j-core {:mvn/version "2.20.0"} + org.apache.logging.log4j/log4j-web {:mvn/version "2.20.0"} + org.apache.logging.log4j/log4j-jul {:mvn/version "2.20.0"} + org.apache.logging.log4j/log4j-slf4j2-impl {:mvn/version "2.20.0"} + org.slf4j/slf4j-api {:mvn/version "2.0.7"} + pl.tkowalcz.tjahzi/log4j2-appender {:mvn/version "0.9.30"} - selmer/selmer {:mvn/version "1.12.55"} + selmer/selmer {:mvn/version "1.12.58"} criterium/criterium {:mvn/version "0.4.6"} metosin/jsonista {:mvn/version "0.3.7"} metosin/malli {:mvn/version "0.11.0"} expound/expound {:mvn/version "0.9.0"} - com.cognitect/transit-clj {:mvn/version "1.0.329"} + com.cognitect/transit-clj {:mvn/version "1.0.333"} com.cognitect/transit-cljs {:mvn/version "0.8.280"} java-http-clj/java-http-clj {:mvn/version "0.4.3"} funcool/cuerdas {:mvn/version "2022.06.16-403"} - funcool/promesa - {:git/tag "11.0-alpha13" - :git/sha "f6cab38" - :git/url "https://github.com/funcool/promesa.git"} + funcool/promesa {:mvn/version "11.0.671"} funcool/datoteka {:mvn/version "3.0.66" :exclusions [funcool/promesa]} - lambdaisland/uri {:mvn/version "1.13.95" + lambdaisland/uri {:mvn/version "1.15.125" :exclusions [org.clojure/data.json]} frankiesardo/linked {:mvn/version "1.3.0"} @@ -44,7 +41,7 @@ ;; exception printing fipp/fipp {:mvn/version "0.6.26"} - io.aviso/pretty {:mvn/version "1.3"} + io.aviso/pretty {:mvn/version "1.4.4"} environ/environ {:mvn/version "1.2.0"}} :paths ["src" "target/classes"] :aliases From cadcc1607d2930de4d6b63ac159f5fada807a7f8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 30 Jun 2023 12:03:40 +0200 Subject: [PATCH 02/35] :sparkles: Increase default argon2id iterations --- backend/src/app/auth.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/app/auth.clj b/backend/src/app/auth.clj index 500f07916f..0037e69001 100644 --- a/backend/src/app/auth.clj +++ b/backend/src/app/auth.clj @@ -13,8 +13,8 @@ (def default-params {:alg :argon2id - :memory (* 32768 2) - :iterations 5 + :memory (* 32768 2) ;; 64 MiB + :iterations 7 :parallelism (px/get-available-processors)}) (defn derive-password From dda67af5cce467fa797c52708f544d44325b857d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 30 Jun 2023 12:04:03 +0200 Subject: [PATCH 03/35] :sparkles: Update oidc impl with latest buddy-sign improvements --- backend/src/app/auth/oidc.clj | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 36cf0afe9d..41e3c6355e 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -25,8 +25,7 @@ [app.tokens :as tokens] [app.util.json :as json] [app.util.time :as dt] - [buddy.core.keys :as keys] - [buddy.sign.jws :as jws] + [buddy.sign.jwk :as jwk] [buddy.sign.jwt :as jwt] [clojure.set :as set] [clojure.spec.alpha :as s] @@ -109,7 +108,7 @@ (defn- process-oidc-jwks [keys] (reduce (fn [result {:keys [kid] :as kdata}] - (let [pkey (ex/try! (keys/jwk->public-key kdata))] + (let [pkey (ex/try! (jwk/public-key kdata))] (if (ex/exception? pkey) (do (l/warn :hint "unable to create public key" @@ -392,7 +391,7 @@ (defn- get-user-info [{:keys [provider]} tdata] (try - (let [{:keys [kid alg] :as theader} (jws/decode-header (:token/id tdata))] + (let [{:keys [kid alg] :as theader} (jwt/decode-header (:token/id tdata))] (when-let [key (if (str/starts-with? (name alg) "hs") (:client-secret provider) (get-in provider [:jwks kid]))] From 8cda8924df2fc2bf3abc2a50bb703c39eecd1ee6 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 3 Jul 2023 10:43:35 +0200 Subject: [PATCH 04/35] :sparkles: Add the ability to select user info source using the PENPOT_OIDC_USER_INFO_SOURCE environment variable with two possible values: token and userinfo --- backend/src/app/auth/oidc.clj | 8 ++++++-- backend/src/app/config.clj | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 41e3c6355e..5330efc098 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -424,8 +424,12 @@ code (get params :code) state (tokens/verify props {:token state :iss :oauth}) tdata (fetch-access-token cfg code) - info (or (get-user-info cfg tdata) - (fetch-user-info cfg tdata)) + info (case (cf/get :oidc-user-info-source) + :token (get-user-info cfg tdata) + :userinfo (fetch-user-info cfg tdata) + (or (get-user-info cfg tdata) + (fetch-user-info cfg tdata))) + info (process-user-info provider tdata info)] (l/trace :hint "user info" :info info) diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index d2cfc2cfb8..ed98060d2b 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -146,6 +146,7 @@ (s/def ::google-client-id ::us/string) (s/def ::google-client-secret ::us/string) (s/def ::oidc-client-id ::us/string) +(s/def ::oidc-user-info-source ::us/keyword) (s/def ::oidc-client-secret ::us/string) (s/def ::oidc-base-uri ::us/string) (s/def ::oidc-token-uri ::us/string) @@ -242,6 +243,7 @@ ::google-client-secret ::oidc-client-id ::oidc-client-secret + ::oidc-user-info-source ::oidc-base-uri ::oidc-token-uri ::oidc-auth-uri From a737c125d5a49724d933d817fc656e3cf4a7b488 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 10:46:38 +0200 Subject: [PATCH 05/35] :bug: Fix unpublish more than one library at the same time --- CHANGES.md | 1 + .../src/app/main/ui/dashboard/file_menu.cljs | 40 ++++++++++--------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 88a5ef6707..ad3a2f5693 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,7 @@ - Fix files can be opened from multiple urls [Taiga #5310](https://tree.taiga.io/project/penpot/issue/5310) - Fix asset color item was created from the selected layer [Taiga #5180](https://tree.taiga.io/project/penpot/issue/5180) +- Fix unpublish more than one library at the same time [Taiga #5532](https://tree.taiga.io/project/penpot/issue/5532) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/dashboard/file_menu.cljs b/frontend/src/app/main/ui/dashboard/file_menu.cljs index cea4baf067..23726875ea 100644 --- a/frontend/src/app/main/ui/dashboard/file_menu.cljs +++ b/frontend/src/app/main/ui/dashboard/file_menu.cljs @@ -142,7 +142,11 @@ #(st/emit! (dd/set-file-shared (assoc file :is-shared true))) del-shared - #(st/emit! (dd/set-file-shared (assoc file :is-shared false))) + (mf/use-fn + (mf/deps files) + (fn [_] + (run! #(st/emit! (dd/set-file-shared (assoc % :is-shared false))) files))) + on-add-shared (fn [event] @@ -216,23 +220,23 @@ (when current-team (let [sub-options (concat (vec (for [project current-projects] - {:option-name (get-project-name project) - :id (get-project-id project) - :option-handler (on-move (:id current-team) - (:id project))})) - (when (seq other-teams) - [{:option-name (tr "dashboard.move-to-other-team") - :id "move-to-other-team" - :sub-options - (for [team other-teams] - {:option-name (get-team-name team) - :id (get-project-id team) - :sub-options - (for [sub-project (:projects team)] - {:option-name (get-project-name sub-project) - :id (get-project-id sub-project) - :option-handler (on-move (:id team) - (:id sub-project))})})}])) + {:option-name (get-project-name project) + :id (get-project-id project) + :option-handler (on-move (:id current-team) + (:id project))})) + (when (seq other-teams) + [{:option-name (tr "dashboard.move-to-other-team") + :id "move-to-other-team" + :sub-options + (for [team other-teams] + {:option-name (get-team-name team) + :id (get-project-id team) + :sub-options + (for [sub-project (:projects team)] + {:option-name (get-project-name sub-project) + :id (get-project-id sub-project) + :option-handler (on-move (:id team) + (:id sub-project))})})}])) options (if multi? [{:option-name (tr "dashboard.duplicate-multi" file-count) From 4d4e9703ccf26eae911c3af6ac04edd79f8347da Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:50:08 +0200 Subject: [PATCH 06/35] :bug: Fix drag projects on dahsboard --- CHANGES.md | 2 ++ .../resources/styles/main/partials/dashboard.scss | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ad3a2f5693..5004cfe722 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,8 @@ - Fix files can be opened from multiple urls [Taiga #5310](https://tree.taiga.io/project/penpot/issue/5310) - Fix asset color item was created from the selected layer [Taiga #5180](https://tree.taiga.io/project/penpot/issue/5180) - Fix unpublish more than one library at the same time [Taiga #5532](https://tree.taiga.io/project/penpot/issue/5532) +- Fix drag projects on dahsboard [Taiga #5531](https://tree.taiga.io/project/penpot/issue/5531) + ### :arrow_up: Deps updates diff --git a/frontend/resources/styles/main/partials/dashboard.scss b/frontend/resources/styles/main/partials/dashboard.scss index 5efa8efb3b..f48e89e57d 100644 --- a/frontend/resources/styles/main/partials/dashboard.scss +++ b/frontend/resources/styles/main/partials/dashboard.scss @@ -466,20 +466,27 @@ .dashboard-templates-section { position: absolute; + display: flex; + flex-direction: column; + justify-content: flex-end; bottom: 0; width: 100%; - height: 285px; + height: 228px; transition: bottom 300ms; - + pointer-events: none; &.collapsed { bottom: -228px; transition: bottom 300ms; } .title { - width: 100%; + pointer-events: all; + width: fit-content; + top: -56px; + right: -28px; text-align: right; height: 56px; + position: absolute; button { border: none; cursor: pointer; @@ -529,6 +536,7 @@ display: flex; align-items: center; justify-content: center; + pointer-events: all; svg { width: 12px; height: 12px; @@ -550,6 +558,7 @@ } .content { + pointer-events: all; background-color: $color-white; width: 200%; height: 229px; From 02466d603c4ae0912e02ae9be8dde6e123afc306 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:51:34 +0200 Subject: [PATCH 07/35] :bug: Fix allow team name to be all blank --- CHANGES.md | 2 +- frontend/src/app/main/ui/dashboard/team_form.cljs | 11 ++++++++++- frontend/translations/en.po | 8 ++++++++ frontend/translations/es.po | 8 ++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5004cfe722..c2c4f1f4d3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,7 +26,7 @@ - Fix asset color item was created from the selected layer [Taiga #5180](https://tree.taiga.io/project/penpot/issue/5180) - Fix unpublish more than one library at the same time [Taiga #5532](https://tree.taiga.io/project/penpot/issue/5532) - Fix drag projects on dahsboard [Taiga #5531](https://tree.taiga.io/project/penpot/issue/5531) - +- Fix allow team name to be all blank [Taiga #5527](https://tree.taiga.io/project/penpot/issue/5527) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/dashboard/team_form.cljs b/frontend/src/app/main/ui/dashboard/team_form.cljs index 673343fcf9..81579044cf 100644 --- a/frontend/src/app/main/ui/dashboard/team_form.cljs +++ b/frontend/src/app/main/ui/dashboard/team_form.cljs @@ -17,12 +17,20 @@ [app.util.router :as rt] [beicon.core :as rx] [cljs.spec.alpha :as s] + [cuerdas.core :as str] [rumext.v2 :as mf])) (s/def ::name ::us/not-empty-string) (s/def ::team-form (s/keys :req-un [::name])) +(defn- validate-name + [errors data] + (let [name (-> data :name str/trim)] + (cond-> errors + (str/empty? name) + (assoc :name {:message (tr "dashboard.team-name.not-empty-name")})))) + (defn- on-create-success [_form response] (let [msg "Team created successfully"] @@ -66,10 +74,11 @@ (on-create-submit form)))) (mf/defc team-form-modal {::mf/register modal/components - ::mf/register-as :team-form} + ::mf/register-as :team-form} [{:keys [team] :as props}] (let [initial (mf/use-memo (fn [] (or team {}))) form (fm/use-form :spec ::team-form + :validators [validate-name] :initial initial)] [:div.modal-overlay [:div.modal-container.team-form-modal diff --git a/frontend/translations/en.po b/frontend/translations/en.po index e8dd59406d..d1c88fc3b2 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -113,6 +113,10 @@ msgstr "Password" msgid "auth.password-length-hint" msgstr "At least 8 characters" +#: src/app/main/ui/auth/register.cljs +msgid "auth.password-not-empty" +msgstr "Password must contain some character other than space." + msgid "auth.privacy-policy" msgstr "Privacy policy" @@ -371,6 +375,10 @@ msgstr "180 days" msgid "dashboard.access-tokens.errors-required-name" msgstr "The name is required" +#: src/app/main/ui/settings/team-form.cljs +msgid "dashboard.team-name.not-empty-name" +msgstr "The name must contain some character other than space." + #: src/app/main/ui/settings/access-tokens.cljs msgid "dashboard.access-tokens.token-will-expire" msgstr "The token will expire on %s" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 42f40e5fcc..9cadae14db 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -118,6 +118,10 @@ msgstr "Contraseña" msgid "auth.password-length-hint" msgstr "8 caracteres como mínimo" +#: src/app/main/ui/auth/register.cljs +msgid "auth.password-not-empty" +msgstr "La contraseña debe contener algún caracter diferente de espacio" + msgid "auth.privacy-policy" msgstr "Política de privacidad" @@ -378,6 +382,10 @@ msgstr "180 días" msgid "dashboard.access-tokens.errors-required-name" msgstr "El nombre es obligatorio" +#: src/app/main/ui/settings/team-form.cljs +msgid "dashboard.team-name.not-empty-name" +msgstr "El nombre debe contener algún carácter diferente de espacio" + #: src/app/main/ui/settings/access-tokens.cljs msgid "dashboard.access-tokens.token-will-expire" msgstr "El token expirará el %s" From 9a880f007c96b59553adfe31e91d694c37c77669 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:52:08 +0200 Subject: [PATCH 08/35] :bug: Fix focus title on layers sidebar --- .../styles/main/partials/sidebar-layers.scss | 67 ++++++++++++++++++- .../styles/main/partials/sidebar.scss | 47 +------------ 2 files changed, 66 insertions(+), 48 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-layers.scss b/frontend/resources/styles/main/partials/sidebar-layers.scss index 79ad3b4aff..e9d3256b5c 100644 --- a/frontend/resources/styles/main/partials/sidebar-layers.scss +++ b/frontend/resources/styles/main/partials/sidebar-layers.scss @@ -355,10 +355,12 @@ span.element-name { .pages-tool-bar { display: flex; justify-content: space-between; - height: 32px; - margin-top: 8px; + height: 40px; + padding: 0; &.search { + margin-top: 8px; + padding: 8px; .search-box { border: 1px solid $color-gray-20; border-radius: $br4; @@ -403,6 +405,67 @@ span.element-name { margin: 0 2px 0 5px; cursor: pointer; } + .page-name { + padding: 8px; + margin-top: 8px; + } + .icon-search { + margin-top: 8px; + } + .focus-title { + width: 100%; + height: 100%; + display: grid; + align-items: center; + grid-template-columns: 16px 1fr auto; + grid-column-gap: 8px; + cursor: pointer; + + .back-button { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + background: none; + border: none; + padding: 0; + margin: 0; + + svg { + width: 12px; + height: 12px; + fill: $color-gray-20; + transform: rotate(180deg); + } + + &:hover { + svg { + fill: $color-primary; + } + } + } + + .focus-name { + height: 100%; + display: flex; + justify-content: flex-start; + align-items: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .focus-mode { + color: $color-primary; + border: 1px solid $color-primary; + border-radius: $br3; + font-size: $fs10; + text-transform: uppercase; + padding: 0px 4px; + display: flex; + align-items: center; + } + } } } .active-filters { diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index 09ac24e249..d8498fa7b3 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -40,6 +40,7 @@ flex-shrink: 0; padding: $size-2; overflow: hidden; + margin: 0; svg { fill: $color-gray-20; @@ -136,52 +137,6 @@ padding: 0.25rem; } } - - & .focus-title { - width: 100%; - height: 100%; - display: grid; - align-items: center; - grid-template-columns: auto 1fr auto; - grid-column-gap: 8px; - cursor: pointer; - - & .back-button { - background: none; - border: none; - padding: 0; - margin: 0; - - & svg { - fill: $color-white; - transform: rotate(180deg); - margin-top: 3px; - } - - &:hover { - svg { - fill: $color-primary; - } - } - } - - & .focus-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - & .focus-mode { - color: $color-primary; - border: 1px solid $color-primary; - border-radius: $br3; - font-size: $fs10; - text-transform: uppercase; - padding: 0px 4px; - display: flex; - align-items: center; - } - } } .assets-bar .tool-window { From e75b53ff8d0fc7fd10d068e54b906dc30ca9de52 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:53:14 +0200 Subject: [PATCH 09/35] :bug: Fix search font visualitation --- CHANGES.md | 2 ++ frontend/resources/styles/main/partials/dashboard-fonts.scss | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index c2c4f1f4d3..a584c90003 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,8 @@ - Fix unpublish more than one library at the same time [Taiga #5532](https://tree.taiga.io/project/penpot/issue/5532) - Fix drag projects on dahsboard [Taiga #5531](https://tree.taiga.io/project/penpot/issue/5531) - Fix allow team name to be all blank [Taiga #5527](https://tree.taiga.io/project/penpot/issue/5527) +- Fix search font visualitation [Taiga #5523](https://tree.taiga.io/project/penpot/issue/5523) + ### :arrow_up: Deps updates diff --git a/frontend/resources/styles/main/partials/dashboard-fonts.scss b/frontend/resources/styles/main/partials/dashboard-fonts.scss index bd93dca5f3..544e50341e 100644 --- a/frontend/resources/styles/main/partials/dashboard-fonts.scss +++ b/frontend/resources/styles/main/partials/dashboard-fonts.scss @@ -60,7 +60,7 @@ font-size: $fs14; background-color: $color-white; display: flex; - min-width: 1000px; + max-width: 1000px; width: 100%; min-height: 97px; align-items: center; From 82183ec71a4298688344253c11e18297ff7e3c28 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:54:40 +0200 Subject: [PATCH 10/35] :bug: Fix create and account only with spaces --- CHANGES.md | 2 +- frontend/src/app/main/ui/auth/register.cljs | 10 +++++++++- .../src/app/main/ui/settings/password.cljs | 20 +++++++++++++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a584c90003..d3eefa8cb0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,7 +28,7 @@ - Fix drag projects on dahsboard [Taiga #5531](https://tree.taiga.io/project/penpot/issue/5531) - Fix allow team name to be all blank [Taiga #5527](https://tree.taiga.io/project/penpot/issue/5527) - Fix search font visualitation [Taiga #5523](https://tree.taiga.io/project/penpot/issue/5523) - +- Fix create and account only with spaces [Taiga #5518](https://tree.taiga.io/project/penpot/issue/5518) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index 76ce3a1ac7..37314093b4 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -22,6 +22,7 @@ [app.util.router :as rt] [beicon.core :as rx] [cljs.spec.alpha :as s] + [cuerdas.core :as str] [rumext.v2 :as mf])) (mf/defc demo-warning @@ -45,6 +46,13 @@ (= code ::us/email) (assoc :message (tr "errors.email-invalid")))))))) +(defn- validate-password + [errors data] + (let [password (-> data :password str/trim)] + (cond-> errors + (str/empty? password) + (assoc :password {:message (tr "auth.password-not-empty")})))) + (s/def ::fullname ::us/not-empty-string) (s/def ::password ::us/not-empty-string) (s/def ::email ::us/email) @@ -87,7 +95,7 @@ [{:keys [params on-success-callback] :as props}] (let [initial (mf/use-memo (mf/deps params) (constantly params)) form (fm/use-form :spec ::register-form - :validators [validate] + :validators [validate validate-password] :initial initial) submitted? (mf/use-state false) diff --git a/frontend/src/app/main/ui/settings/password.cljs b/frontend/src/app/main/ui/settings/password.cljs index 9e792d5458..f9ab2a915c 100644 --- a/frontend/src/app/main/ui/settings/password.cljs +++ b/frontend/src/app/main/ui/settings/password.cljs @@ -14,6 +14,7 @@ [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t tr]] [cljs.spec.alpha :as s] + [cuerdas.core :as str] [rumext.v2 :as mf])) (defn- on-error @@ -24,7 +25,7 @@ {:message (tr "errors.wrong-old-password")}) :email-as-password (swap! form assoc-in [:errors :password-1] - {:message (tr "errors.email-as-password")}) + {:message (tr "errors.email-as-password")}) (let [msg (tr "generic.error")] (st/emit! (dm/error msg))))) @@ -62,6 +63,17 @@ (and password-1 (> 8 (count password-1))) (assoc :password-1 {:message (tr "errors.password-too-short")})))) +(defn- validate-password + [errors data] + (let [password-1 (-> data :password-1 str/trim) + password-2 (-> data :password-2 str/trim)] + (cond-> errors + (str/empty? password-1) + (assoc :password-1 {:message (tr "auth.password-not-empty")}) + + (str/empty? password-2) + (assoc :password-2 {:message (tr "auth.password-not-empty")})))) + (s/def ::password-form (s/keys :req-un [::password-1 ::password-2 @@ -71,8 +83,8 @@ [{:keys [locale] :as props}] (let [initial (mf/use-memo (constantly {:password-old nil})) form (fm/use-form :spec ::password-form - :validators [password-equality] - :initial initial)] + :validators [validate-password password-equality] + :initial initial)] [:& fm/form {:class "password-form" :on-submit on-submit :form form} @@ -105,7 +117,7 @@ (mf/defc password-page [{:keys [locale]}] (mf/use-effect - #(dom/set-html-title (tr "title.settings.password"))) + #(dom/set-html-title (tr "title.settings.password"))) [:section.dashboard-settings.form-container [:div.form-container From 94b5c980429e845c9bf1c4da1be3f8534b902bae Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:56:35 +0200 Subject: [PATCH 11/35] :bug: Fix context menu outside screen --- CHANGES.md | 1 + frontend/resources/styles/main/partials/dashboard-team.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d3eefa8cb0..c978bec229 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ - Fix allow team name to be all blank [Taiga #5527](https://tree.taiga.io/project/penpot/issue/5527) - Fix search font visualitation [Taiga #5523](https://tree.taiga.io/project/penpot/issue/5523) - Fix create and account only with spaces [Taiga #5518](https://tree.taiga.io/project/penpot/issue/5518) +- Fix context menu outside screen [Taiga #5524](https://tree.taiga.io/project/penpot/issue/5524) ### :arrow_up: Deps updates diff --git a/frontend/resources/styles/main/partials/dashboard-team.scss b/frontend/resources/styles/main/partials/dashboard-team.scss index 384b748edc..45ee9d6ecb 100644 --- a/frontend/resources/styles/main/partials/dashboard-team.scss +++ b/frontend/resources/styles/main/partials/dashboard-team.scss @@ -324,7 +324,7 @@ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25); z-index: 12; top: 30px; - left: 6px; + left: -151px; width: 155px; hr { From 8955f87d5afb1c372cee8fc6fbbaebc3322bf403 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:57:45 +0200 Subject: [PATCH 12/35] :bug: Fix z-index nillable input when static position --- .../ui/workspace/sidebar/options/menus/layout_item.cljs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs index af92826ee1..e4885697ad 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs @@ -192,6 +192,8 @@ (if (= align-self value) (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil})) (st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value})))) + + is-absolute? (:layout-item-absolute values) is-col? (every? ctl/col? selection-parents) @@ -219,6 +221,8 @@ on-change-position (fn [value] + (when (= value :static) + (st/emit! (dwsl/update-layout-child ids {:layout-item-z-index nil}))) (st/emit! (dwsl/update-layout-child ids {:layout-item-absolute (= value :absolute)}))) on-change-z-index @@ -254,6 +258,8 @@ {:placeholder "--" :on-focus #(dom/select-target %) :on-change #(on-change-z-index %) + :nillable true + :disabled (not is-absolute?) :value (:layout-item-z-index values)}]]]]) (when (not (:layout-item-absolute values)) From ef3fedee59e71398214a8d52811c5ab615415954 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 12:57:59 +0200 Subject: [PATCH 13/35] :bug: Fix some warnings and format some files --- .../app/main/ui/components/dropdown_menu.cljs | 2 +- .../src/app/main/ui/dashboard/sidebar.cljs | 35 ++++++++++--------- .../options/menus/layout_container.cljs | 32 ++++++++--------- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/frontend/src/app/main/ui/components/dropdown_menu.cljs b/frontend/src/app/main/ui/components/dropdown_menu.cljs index c397b5c26f..75e32b60b1 100644 --- a/frontend/src/app/main/ui/components/dropdown_menu.cljs +++ b/frontend/src/app/main/ui/components/dropdown_menu.cljs @@ -25,7 +25,7 @@ on-key-down (gobj/get props "on-key-down") id (gobj/get props "id") klass (gobj/get props "klass") - key (gobj/get props "key") + key (gobj/get props "unique-key") data-test (gobj/get props "data-test")] [:li {:id id :class klass diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index a494b1b36f..571b97fca8 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -243,6 +243,7 @@ (when (kbd/enter? event) (team-selected (:default-team-id profile) event))) :id "teams-selector-default-team" + :unique-key "default-team" :klass "team-name"} [:span.team-icon i/logo-icon] [:span.team-text (tr "dashboard.your-penpot")] @@ -256,7 +257,7 @@ (team-selected (:id team-item) event))) :id (str "teams-selector-" (:id team-item)) :klass "team-name" - :key (dm/str (:id team-item))} + :unique-key (dm/str (:id team-item))} [:span.team-icon [:img {:src (cf/resolve-team-photo-url team-item) :alt (:name team-item)}]] @@ -270,7 +271,7 @@ (on-create-clicked event))) :id "teams-selector-create-team" :klass "team-name action" - :key "teams-selector-create-team"} + :unique-key "teams-selector-create-team"} [:span.team-icon.new-team i/close] [:span.team-text (tr "dashboard.create-new-team")]]])) @@ -364,16 +365,16 @@ (when (kbd/enter? event) (go-members))) :id "teams-options-members" - :key "teams-options-members" - :data-test "team-members"} + :unique-key "teams-options-members" + :data-test "team-members"} (tr "labels.members")] [:& dropdown-menu-item {:on-click go-invitations :on-key-down (fn [event] (when (kbd/enter? event) (go-invitations))) :id "teams-options-invitations" - :key "teams-options-invitations" - :data-test "team-invitations"} + :unique-key "teams-options-invitations" + :data-test "team-invitations"} (tr "labels.invitations")] (when (contains? cf/flags :webhooks) @@ -382,7 +383,7 @@ (when (kbd/enter? event) (go-webhooks))) :id "teams-options-webhooks" - :key "teams-options-webhooks"} + :unique-key "teams-options-webhooks"} (tr "labels.webhooks")]) [:& dropdown-menu-item {:on-click go-settings @@ -390,8 +391,8 @@ (when (kbd/enter? event) (go-settings))) :id "teams-options-settings" - :key "teams-options-settings" - :data-test "team-settings"} + :unique-key "teams-options-settings" + :data-test "team-settings"} (tr "labels.settings")] [:hr] @@ -401,8 +402,8 @@ (when (kbd/enter? event) (on-rename-clicked))) :id "teams-options-rename" - :key "teams-options-rename" - :data-test "rename-team"} + :unique-key "teams-options-rename" + :data-test "rename-team"} (tr "labels.rename")]) (cond @@ -412,7 +413,7 @@ (when (kbd/enter? event) (leave-and-close))) :id "teams-options-leave-team" - :key "teams-options-leave-team"} + :unique-key "teams-options-leave-team"} (tr "dashboard.leave-team")] @@ -422,8 +423,8 @@ (when (kbd/enter? event) (on-leave-as-owner-clicked))) :id "teams-options-leave-team" - :key "teams-options-leave-team" - :data-test "leave-team"} + :unique-key "teams-options-leave-team" + :data-test "leave-team"} (tr "dashboard.leave-team")] (> (count members) 1) @@ -432,7 +433,7 @@ (when (kbd/enter? event) (on-leave-clicked))) :id "teams-options-leave-team" - :key "teams-options-leave-team"} + :unique-key "teams-options-leave-team"} (tr "dashboard.leave-team")]) @@ -442,9 +443,9 @@ (when (kbd/enter? event) (on-delete-clicked))) :id "teams-options-delete-team" - :key "teams-options-delete-team" + :unique-key "teams-options-delete-team" :klass "warning" - :data-test "delete-team"} + :data-test "delete-team"} (tr "dashboard.delete-team")])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index a3a3883936..1e987b4884 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -93,13 +93,13 @@ :space-between i/align-content-row-between :stretch nil)) - (case val - :start i/align-content-row-start - :end i/align-content-row-end - :center i/align-content-row-center - :space-around i/align-content-row-around - :space-between i/align-content-row-between - :stretch nil) + (case val + :start i/align-content-row-start + :end i/align-content-row-end + :center i/align-content-row-center + :space-around i/align-content-row-around + :space-between i/align-content-row-between + :stretch nil) :align-self (if is-col? @@ -275,8 +275,8 @@ {:placeholder "--" :on-change (partial on-change :simple :p1) :on-focus #(do - (dom/select-target %) - (select-paddings true false true false)) + (dom/select-target %) + (select-paddings true false true false)) :value p1}]] [:div.padding-item.tooltip.tooltip-bottom-left @@ -354,7 +354,7 @@ i/auto-gap] [:> numeric-input {:no-validate true :placeholder "--" - :on-focus (fn [event] + :on-focus (fn [event] (select-gap :row-gap) (reset! gap-selected? :row-gap) (dom/select-target event)) @@ -638,12 +638,12 @@ (if (and (not multiple) (:layout values)) [:div.title-actions #_[:div.layout-btns - [:button {:on-click set-flex - :class (dom/classnames - :active (= :flex layout-type))} "Flex"] - [:button {:on-click set-grid - :class (dom/classnames - :active (= :grid layout-type))} "Grid"]] + [:button {:on-click set-flex + :class (dom/classnames + :active (= :flex layout-type))} "Flex"] + [:button {:on-click set-grid + :class (dom/classnames + :active (= :grid layout-type))} "Grid"]] [:button.remove-layout {:on-click on-remove-layout} i/minus]] [:button.add-page {:on-click #(on-add-layout :flex)} i/close])]] From dcc15e485d7de1179e41fff38e3415668bd53846 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 3 Jul 2023 17:03:18 +0200 Subject: [PATCH 14/35] :bug: Don't allow empty or whitespace-only names on components --- .../app/main/data/workspace/libraries.cljs | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index c6901212a1..32f69ec022 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -40,6 +40,7 @@ [app.util.router :as rt] [app.util.time :as dt] [beicon.core :as rx] + [cuerdas.core :as str] [potok.core :as ptk])) ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default @@ -340,24 +341,20 @@ (defn rename-component "Rename the component with the given id, in the current file library." [id new-name] - (dm/assert! (uuid? id)) - (dm/assert! (string? new-name)) + (dm/verify! (uuid? id)) + (dm/verify! (string? new-name)) (ptk/reify ::rename-component ptk/WatchEvent (watch [it state _] - (when (and (some? new-name) (not= "" new-name)) - (let [data (get state :workspace-data) - [path name] (cph/parse-path-name new-name) - components-v2 (features/active-feature? state :components-v2) + (let [new-name (str/trim new-name)] + (if (str/empty? new-name) + (rx/empty) + (let [data (get state :workspace-data) + [path name] (cph/parse-path-name new-name) + components-v2 (features/active-feature? state :components-v2) - update-fn - (fn [component] - ;; NOTE: we need to ensure the component exists, - ;; because there are small possibilities of race - ;; conditions with component deletion. - ;; - ;; FIXME: this race conditon should be handled in pcb/update-component - (when component + update-fn + (fn [component] (cond-> component :always (assoc :path path @@ -366,13 +363,13 @@ (not components-v2) (update :objects ;; Give the same name to the root shape - #(assoc-in % [id :name] name))))) + #(assoc-in % [id :name] name)))) - changes (-> (pcb/empty-changes it) - (pcb/with-library-data data) - (pcb/update-component id update-fn))] + changes (-> (pcb/empty-changes it) + (pcb/with-library-data data) + (pcb/update-component id update-fn))] - (rx/of (dch/commit-changes changes))))))) + (rx/of (dch/commit-changes changes)))))))) (defn rename-component-and-main-instance [component-id name] From b64a9f0cf4a36c5802bceb02556c3607177d58ba Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 11:10:09 +0200 Subject: [PATCH 15/35] :bug: Fix graphic item rename on assets pannel --- CHANGES.md | 3 +-- frontend/src/app/main/ui/workspace/sidebar/assets.cljs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c978bec229..41a2497600 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,8 +30,7 @@ - Fix search font visualitation [Taiga #5523](https://tree.taiga.io/project/penpot/issue/5523) - Fix create and account only with spaces [Taiga #5518](https://tree.taiga.io/project/penpot/issue/5518) - Fix context menu outside screen [Taiga #5524](https://tree.taiga.io/project/penpot/issue/5524) - -### :arrow_up: Deps updates +- Fix graphic item rename on assets pannel [Taiga #5556](https://tree.taiga.io/project/penpot/issue/5556) ### :heart: Community contributions by (Thank you!) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 339aa0bf6e..0f8ff338f3 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -1078,7 +1078,8 @@ (mf/use-fn (fn [] (swap! state (fn [state] - (assoc state :renaming (:component-id state)))))) + (assoc state :renaming (:object-id state)))))) + cancel-rename (mf/use-fn (fn [] From a868dcf8e642ef80b8ad3ac20f22482cddf9df9e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 11:14:49 +0200 Subject: [PATCH 16/35] :bug: Don't allow empty strings and whitespace-only strings on media name --- CHANGES.md | 1 + .../app/main/data/workspace/libraries.cljs | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 41a2497600..5c178ec7a8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,7 @@ - Fix create and account only with spaces [Taiga #5518](https://tree.taiga.io/project/penpot/issue/5518) - Fix context menu outside screen [Taiga #5524](https://tree.taiga.io/project/penpot/issue/5524) - Fix graphic item rename on assets pannel [Taiga #5556](https://tree.taiga.io/project/penpot/issue/5556) +- Fix component and media name validation on assets panel [Taiga #5555](https://tree.taiga.io/project/penpot/issue/5555) ### :heart: Community contributions by (Thank you!) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 32f69ec022..d27d5794f1 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -185,21 +185,22 @@ (defn rename-media [id new-name] - (dm/assert! (uuid? id)) - (dm/assert! (string? new-name)) + (dm/verify! (uuid? id)) + (dm/verify! (string? new-name)) (ptk/reify ::rename-media ptk/WatchEvent (watch [it state _] - (when (and (some? new-name) (not= "" new-name)) - (let [data (get state :workspace-data) - [path name] (cph/parse-path-name new-name) - object (get-in data [:media id]) - new-object (assoc object :path path :name name) - changes (-> (pcb/empty-changes it) - (pcb/with-library-data data) - (pcb/update-media new-object))] - (rx/of (dch/commit-changes changes))))))) - + (let [new-name (str/trim new-name)] + (if (str/empty? new-name) + (rx/empty) + (let [[path name] (cph/parse-path-name new-name) + data (get state :workspace-data) + object (get-in data [:media id]) + new-object (assoc object :path path :name name) + changes (-> (pcb/empty-changes it) + (pcb/with-library-data data) + (pcb/update-media new-object))] + (rx/of (dch/commit-changes changes)))))))) (defn delete-media [{:keys [id] :as params}] From e0c0b251a92fd0eabc544c08c88e9608d280db6c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 11:16:33 +0200 Subject: [PATCH 17/35] :lipstick: Add minor cosmetic change to CHANGES.md file --- CHANGES.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5c178ec7a8..8234a616c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,9 +16,8 @@ - Add the ability to disable google fonts provider with the `disable-google-fonts-provider` flag - Add the ability to disable dashboard templates section with the `disable-dashboard-templates-section` flag - Add the ability to use the registration whitelist with OICD [Github #3348](https://github.com/penpot/penpot/issues/3348) -- Add support for local caching of google fonts (this avoids exposing - the final user IP to goolge and reduces the amount of request sent - to google) +- Add support for local caching of google fonts (this avoids exposing the final user IP to + goolge and reduces the amount of request sent to google) ### :bug: Bugs fixed From 7b0d3bdcabd977b9a7eb158a1cdf87536d3c6a66 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 12:59:59 +0200 Subject: [PATCH 18/35] :sparkles: Add stricter validation on events endpoint --- backend/src/app/rpc/commands/audit.clj | 34 ++++++++++++-------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/backend/src/app/rpc/commands/audit.clj b/backend/src/app/rpc/commands/audit.clj index 4578a74b3c..6e0762d0ef 100644 --- a/backend/src/app/rpc/commands/audit.clj +++ b/backend/src/app/rpc/commands/audit.clj @@ -9,7 +9,7 @@ (:require [app.common.data :as d] [app.common.logging :as l] - [app.common.spec :as us] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -19,9 +19,7 @@ [app.rpc.climit :as-alias climit] [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] - [app.util.services :as sv] - [app.util.time :as dt] - [clojure.spec.alpha :as s])) + [app.util.services :as sv])) (defn- event->row [event] [(uuid/next) @@ -52,25 +50,25 @@ (when (seq events) (db/insert-multi! pool :audit-log event-columns events)))) -(s/def ::name ::us/string) -(s/def ::type ::us/string) -(s/def ::props (s/map-of ::us/keyword any?)) -(s/def ::timestamp dt/instant?) -(s/def ::context (s/map-of ::us/keyword any?)) +(def schema:event + [:schema {:registry + {::valid-any [:or ::sm/inst :int :double [:string {:max 250}]]}} + [:map {:title "Event"} + [:name [:string {:max 250}]] + [:type [:string {:max 250}]] + [:props + [:map-of :keyword ::valid-any]] + [:context {:optional true} + [:map-of :keyword ::valid-any]]]]) -(s/def ::event - (s/keys :req-un [::type ::name ::props ::timestamp] - :opt-un [::context])) - -(s/def ::events (s/every ::event)) - -(s/def ::push-audit-events - (s/keys :req [::rpc/profile-id] - :req-un [::events])) +(def schema:push-audit-events + [:map {:title "push-audit-events"} + [:events [:vector schema:event]]]) (sv/defmethod ::push-audit-events {::climit/id :submit-audit-events-by-profile ::climit/key-fn ::rpc/profile-id + ::sm/params schema:push-audit-events ::audit/skip true ::doc/added "1.17"} [{:keys [::db/pool] :as cfg} params] From 1464f5da90429bdc2b38f73888f153c7dc184809 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 13:21:05 +0200 Subject: [PATCH 19/35] :sparkles: Ensure that all emails are under 250chars --- common/src/app/common/schema.cljc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index 8a62947dfb..92ce756e72 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -282,7 +282,9 @@ (def! ::email {:type ::email :pred (fn [s] - (and (string? s) (re-seq email-re s))) + (and (string? s) + (< (count s) 250) + (re-seq email-re s))) :type-properties {:title "email" :description "string with valid email address" From 068d2f13f48874c59b36523c975ba2e46206e041 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 13:35:54 +0200 Subject: [PATCH 20/35] :sparkles: Add min-max validation to word-string schema --- common/src/app/common/schema.cljc | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index 92ce756e72..19e3046f88 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -466,6 +466,7 @@ (def! ::word-string {:type ::word-string :pred #(and (string? %) (not (str/blank? %))) + :property-pred (m/-min-max-pred count) :type-properties {:title "string" :description "string" From be652b909eeb7736cc660cccbe15ecc2be083e0b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 13:36:14 +0200 Subject: [PATCH 21/35] :sparkles: Add stronger validationt to auth/register rpc methods --- backend/src/app/rpc/commands/auth.clj | 74 ++++++++++--------- backend/test/backend_tests/helpers.clj | 9 +++ backend/test/backend_tests/rpc_audit_test.clj | 12 +-- backend/test/backend_tests/rpc_file_test.clj | 5 +- .../test/backend_tests/rpc_profile_test.clj | 2 +- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index cbd8394a56..7281cfed25 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -8,9 +8,10 @@ (:require [app.auth :as auth] [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.exceptions :as ex] [app.common.logging :as l] - [app.common.spec :as us] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -26,18 +27,13 @@ [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] - [clojure.spec.alpha :as s] [cuerdas.core :as str])) -(s/def ::email ::us/email) -(s/def ::fullname ::us/not-empty-string) -(s/def ::lang ::us/string) -(s/def ::path ::us/string) -(s/def ::password ::us/not-empty-string) -(s/def ::old-password ::us/not-empty-string) -(s/def ::theme ::us/string) -(s/def ::invitation-token ::us/not-empty-string) -(s/def ::token ::us/not-empty-string) +(def schema:password + [::sm/word-string {:max 500}]) + +(def schema:token + [::sm/word-string {:max 1000}]) ;; ---- COMMAND: login with password @@ -101,22 +97,22 @@ (rph/with-meta {::audit/props (audit/profile->props profile) ::audit/profile-id (:id profile)})))))) -(s/def ::login-with-password - (s/keys :req-un [::email ::password] - :opt-un [::invitation-token])) +(def schema:login-with-password + [:map {:title "login-with-password"} + [:email ::sm/email] + [:password schema:password] + [:invitation-token {:optional true} schema:token]]) (sv/defmethod ::login-with-password "Performs authentication using penpot password." {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:login-with-password} [cfg params] (login-with-password cfg params)) ;; ---- COMMAND: Logout -(s/def ::logout - (s/keys :opt [::rpc/profile-id])) - (sv/defmethod ::logout "Clears the authentication cookie and logout the current session." {::rpc/auth false @@ -141,13 +137,15 @@ (update-password conn)) nil))) -(s/def ::token ::us/not-empty-string) -(s/def ::recover-profile - (s/keys :req-un [::token ::password])) +(def schema:recover-profile + [:map {:title "recover-profile"} + [:token schema:token] + [:password schema:password]]) (sv/defmethod ::recover-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:recover-profile} [cfg params] (recover-profile cfg params)) @@ -228,13 +226,16 @@ (with-meta {:token token} {::audit/profile-id uuid/zero}))) -(s/def ::prepare-register-profile - (s/keys :req-un [::email ::password] - :opt-un [::invitation-token])) +(def schema:prepare-register-profile + [:map {:title "prepare-register-profile"} + [:email ::sm/email] + [:password schema:password] + [:invitation-token {:optional true} schema:token]]) (sv/defmethod ::prepare-register-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:prepare-register-profile} [cfg params] (prepare-register cfg params)) @@ -244,7 +245,7 @@ "Create the profile entry on the database with limited set of input attrs (all the other attrs are filled with default values)." [conn {:keys [email] :as params}] - (us/assert! ::us/email email) + (dm/assert! ::sm/email email) (let [id (or (:id params) (uuid/next)) props (-> (audit/extract-utm-params params) (merge (:props params)) @@ -391,12 +392,16 @@ {::audit/replace-props (audit/profile->props profile) ::audit/profile-id (:id profile)}))))) -(s/def ::register-profile - (s/keys :req-un [::token ::fullname])) + +(def schema:register-profile + [:map {:title "register-profile"} + [:token schema:token] + [:fullname [::sm/word-string {:max 100}]]]) (sv/defmethod ::register-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:register-profile} [{:keys [::db/pool] :as cfg} params] (db/with-atomic [conn pool] (-> (assoc cfg ::db/conn conn) @@ -448,12 +453,15 @@ (create-recovery-token) (send-email-notification conn)))))) -(s/def ::request-profile-recovery - (s/keys :req-un [::email])) + +(def schema:request-profile-recovery + [:map {:title "request-profile-recovery"} + [:email ::sm/email]]) (sv/defmethod ::request-profile-recovery {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:request-profile-recovery} [cfg params] (request-profile-recovery cfg params)) diff --git a/backend/test/backend_tests/helpers.clj b/backend/test/backend_tests/helpers.clj index ac8b0ce45e..d2edaeec98 100644 --- a/backend/test/backend_tests/helpers.clj +++ b/backend/test/backend_tests/helpers.clj @@ -14,6 +14,7 @@ [app.common.pages :as cp] [app.common.pprint :as pp] [app.common.spec :as us] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -414,6 +415,14 @@ (println (us/pretty-explain data)) + (= :params-validation (:code data)) + (app.common.pprint/pprint + (sm/humanize-data (::sm/explain data))) + + (= :data-validation (:code data)) + (app.common.pprint/pprint + (sm/humanize-data (::sm/explain data))) + (= :service-error (:type data)) (print-error! (.getCause ^Throwable error)) diff --git a/backend/test/backend_tests/rpc_audit_test.clj b/backend/test/backend_tests/rpc_audit_test.clj index df860ca037..233728dac3 100644 --- a/backend/test/backend_tests/rpc_audit_test.clj +++ b/backend/test/backend_tests/rpc_audit_test.clj @@ -39,8 +39,8 @@ params {::th/type :push-audit-events ::rpc/profile-id (:id prof) :events [{:name "navigate" - :props {:project-id proj-id - :team-id team-id + :props {:project-id (str proj-id) + :team-id (str team-id) :route "dashboard-files"} :context {:engine "blink"} :profile-id (:id prof) @@ -71,8 +71,8 @@ params {::th/type :push-audit-events ::rpc/profile-id (:id prof) :events [{:name "navigate" - :props {:project-id proj-id - :team-id team-id + :props {:project-id (str proj-id) + :team-id (str team-id) :route "dashboard-files"} :context {:engine "blink"} :profile-id uuid/zero @@ -91,6 +91,8 @@ (t/is (= 1 (count rows))) (t/is (= (:id prof) (:profile-id row))) (t/is (= "navigate" (:name row))) - (t/is (= "frontend" (:source row))))))) + (t/is (= "frontend" (:source row)))) + + ))) diff --git a/backend/test/backend_tests/rpc_file_test.clj b/backend/test/backend_tests/rpc_file_test.clj index 743bbdb406..d39fd2d393 100644 --- a/backend/test/backend_tests/rpc_file_test.clj +++ b/backend/test/backend_tests/rpc_file_test.clj @@ -252,6 +252,7 @@ :components-v2 true :changes changes} out (th/command! params)] + ;; (th/print-result! out) (t/is (nil? (:error out))) (:result out)))] @@ -278,7 +279,7 @@ [{:type :add-obj :page-id page-id :id shid - :parent-id uuid/zero + :parent-id uuid/zero :frame-id uuid/zero :components-v2 true :obj {:id shid @@ -286,7 +287,7 @@ :frame-id uuid/zero :parent-id uuid/zero :type :image - :metadata {:id (:id fmo1)}}}]) + :metadata {:id (:id fmo1) :width 200 :height 200 :mtype "image/jpeg"}}}]) ;; Check that reference storage objects on filemediaobjects ;; are the same because of deduplication feature. diff --git a/backend/test/backend_tests/rpc_profile_test.clj b/backend/test/backend_tests/rpc_profile_test.clj index 846c5e1e93..a28f186c81 100644 --- a/backend/test/backend_tests/rpc_profile_test.clj +++ b/backend/test/backend_tests/rpc_profile_test.clj @@ -278,7 +278,7 @@ (let [error (:error out)] (t/is (th/ex-info? error)) (t/is (th/ex-of-type? error :validation)) - (t/is (th/ex-of-code? error :spec-validation)))) + (t/is (th/ex-of-code? error :params-validation)))) ;; try correct register (let [data {::th/type :register-profile From 8f8d90abbcaa9963cfcdddc2d5847be1ffc54fc9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 19:27:24 +0200 Subject: [PATCH 22/35] :rewind: Revert some changes to the audit validation --- backend/src/app/rpc/commands/audit.clj | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/app/rpc/commands/audit.clj b/backend/src/app/rpc/commands/audit.clj index 6e0762d0ef..9475a5a041 100644 --- a/backend/src/app/rpc/commands/audit.clj +++ b/backend/src/app/rpc/commands/audit.clj @@ -51,15 +51,13 @@ (db/insert-multi! pool :audit-log event-columns events)))) (def schema:event - [:schema {:registry - {::valid-any [:or ::sm/inst :int :double [:string {:max 250}]]}} - [:map {:title "Event"} - [:name [:string {:max 250}]] - [:type [:string {:max 250}]] - [:props - [:map-of :keyword ::valid-any]] - [:context {:optional true} - [:map-of :keyword ::valid-any]]]]) + [:map {:title "Event"} + [:name [:string {:max 250}]] + [:type [:string {:max 250}]] + [:props + [:map-of :keyword :any]] + [:context {:optional true} + [:map-of :keyword :any]]]) (def schema:push-audit-events [:map {:title "push-audit-events"} From 5a8df0dfae76ff23fc163761bacfecdd0dfe5b5c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 19:27:49 +0200 Subject: [PATCH 23/35] :sparkles: Add better validation of profile rpc methods --- backend/src/app/rpc/commands/profile.clj | 52 ++++++++++++++---------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 0a44998ed4..56b352ffcd 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -27,7 +27,6 @@ [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] - [clojure.spec.alpha :as s] [cuerdas.core :as str])) (declare check-profile-existence!) @@ -41,7 +40,7 @@ (def schema:profile [:map {:title "Profile"} [:id ::sm/uuid] - [:fullname :string] + [:fullname [::sm/word-string {:max 250}]] [:email ::sm/email] [:is-active {:optional true} :boolean] [:is-blocked {:optional true} :boolean] @@ -82,12 +81,15 @@ ;; --- MUTATION: Update Profile (own) +(def schema:update-profile + [:map {:title "update-profile"} + [:fullname [::sm/word-string {:max 250}]] + [:lang {:optional true} [:string {:max 5}]] + [:theme {:optional true} [:string {:max 250}]]]) + (sv/defmethod ::update-profile {::doc/added "1.0" - ::sm/params [:map {:title "UpdateProfileParams"} - [:fullname {:min 1} :string] - [:lang {:optional true} :string] - [:theme {:optional true} :string]] + ::sm/params schema:update-profile ::sm/result schema:profile} [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id fullname lang theme] :as params}] @@ -128,11 +130,14 @@ (declare update-profile-password!) (declare invalidate-profile-session!) +(def schema:update-profile-password + [:map {:title "update-profile-password"} + [:password [::sm/word-string {:max 500}]] + [:old-password [::sm/word-string {:max 500}]]]) + (sv/defmethod ::update-profile-password {:doc/added "1.0" - ::sm/params [:map {:title "UpdateProfilePasswordParams"} - [:password :string] - [:old-password :string]] + ::sm/params schema:update-profile-password ::sm/result :nil} [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id password] :as params}] @@ -178,10 +183,13 @@ (declare upload-photo) (declare update-profile-photo) +(def schema:update-profile-photo + [:map {:title "update-profile-photo"} + [:file ::media/upload]]) + (sv/defmethod ::update-profile-photo {:doc/added "1.1" - ::sm/params [:map {:title "UpdateProfilePhotoParams"} - [:file ::media/upload]] + ::sm/params schema:update-profile-photo ::sm/result :nil} [cfg {:keys [::rpc/profile-id file] :as params}] ;; Validate incoming mime type @@ -239,11 +247,13 @@ (declare ^:private request-email-change!) (declare ^:private change-email-immediately!) -(s/def ::request-email-change - (s/keys :req [::rpc/profile-id] - :req-un [::email])) +(def schema:request-email-change + [:map {:title "request-email-change"} + [:email ::sm/email]]) (sv/defmethod ::request-email-change + {::doc/added "1.0" + ::sm/params schema:request-email-change} [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id email] :as params}] (db/with-atomic [conn pool] (let [profile (db/get-by-id conn :profile profile-id) @@ -304,12 +314,13 @@ ;; --- MUTATION: Update Profile Props -(s/def ::props map?) -(s/def ::update-profile-props - (s/keys :req [::rpc/profile-id] - :req-un [::props])) +(def schema:update-profile-props + [:map {:title "update-profile-props"} + [:props [:map-of :keyword :any]]]) (sv/defmethod ::update-profile-props + {::doc/added "1.0" + ::sm/params schema:update-profile-props} [{:keys [::db/pool]} {:keys [::rpc/profile-id props]}] (db/with-atomic [conn pool] (let [profile (get-profile conn profile-id ::db/for-update? true) @@ -329,15 +340,12 @@ (filter-props props)))) - ;; --- MUTATION: Delete Profile (declare ^:private get-owned-teams-with-participants) -(s/def ::delete-profile - (s/keys :req [::rpc/profile-id])) - (sv/defmethod ::delete-profile + {::doc/added "1.0"} [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id] :as params}] (db/with-atomic [conn pool] (let [teams (get-owned-teams-with-participants conn profile-id) From e40245e18723964b5a00ffd32794f1c624bcceaa Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 3 Jul 2023 13:08:08 +0200 Subject: [PATCH 24/35] :bug: Fixed problem with styles inside def for svg import --- frontend/src/app/main/data/workspace/svg_upload.cljs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 7e9d99d670..dda47f024d 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -206,7 +206,6 @@ :height height :x x :y y - :hidden (= tag :defs) :content (cond-> data (map? data) (update :attrs usvg/clean-attrs))} (assoc :svg-attrs attrs) @@ -437,6 +436,7 @@ children (cond->> (:content element-data) (contains? usvg/parent-tags tag) (mapv #(usvg/inherit-attributes attrs %)))] + [shape children])))))) (defn create-svg-children @@ -537,7 +537,8 @@ root-shape (create-svg-root frame-id parent-id svg-data) root-id (:id root-shape) - ;; In penpot groups have the size of their children. To respect the imported svg size and empty space let's create a transparent shape as background to respect the imported size + ;; In penpot groups have the size of their children. To respect the imported + ;; svg size and empty space let's create a transparent shape as background to respect the imported size base-background-shape {:tag :rect :attrs {:x (str vb-x) :y (str vb-y) @@ -588,6 +589,7 @@ [new-shape new-children] (create-svg-shapes svg-data position objects frame-id parent-id selected true) + changes (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) (pcb/add-object new-shape)) From 66e32e9cbd5bbdf1f5f684340c3ce471fe906f98 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 3 Jul 2023 13:54:39 +0200 Subject: [PATCH 25/35] :bug: Fix problem with selection shortcuts --- CHANGES.md | 1 + frontend/src/app/main/data/workspace.cljs | 5 ++++- frontend/src/app/main/data/workspace/selection.cljs | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8234a616c0..c1917880f1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,7 @@ - Fix context menu outside screen [Taiga #5524](https://tree.taiga.io/project/penpot/issue/5524) - Fix graphic item rename on assets pannel [Taiga #5556](https://tree.taiga.io/project/penpot/issue/5556) - Fix component and media name validation on assets panel [Taiga #5555](https://tree.taiga.io/project/penpot/issue/5555) +- Fix problem with selection shortcuts [Taiga #5492](https://tree.taiga.io/project/penpot/issue/5492) ### :heart: Community contributions by (Thank you!) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 966af4fdd2..7043327671 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -938,7 +938,10 @@ (rx/of (dwe/start-edition-mode id)) (:group :bool :frame) - (rx/of (dws/select-shapes (into (d/ordered-set) shapes))) + (let [shapes-ids (into (d/ordered-set) + (remove #(dm/get-in objects [% :hidden])) + shapes)] + (rx/of (dws/select-shapes shapes-ids))) :svg-raw nil diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index db4dfee10a..9bab204bf7 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -249,7 +249,7 @@ (lookup uuid/zero)) toselect (->> (cph/get-immediate-children objects (:id parent)) - (into (d/ordered-set) (comp (remove :blocked) (map :id))))] + (into (d/ordered-set) (comp (remove :hidden) (remove :blocked) (map :id))))] (rx/of (select-shapes toselect)))))) From 302750bd7e614e72aabfc3fb2a910661ebb81dc3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 4 Jul 2023 10:48:28 +0200 Subject: [PATCH 26/35] :bug: Fix issue with paths line to curve and concurrent editing --- CHANGES.md | 1 + common/src/app/common/path/commands.cljc | 15 +++++++++------ frontend/src/app/util/path/format.cljs | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c1917880f1..4e7d3a38d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -32,6 +32,7 @@ - Fix graphic item rename on assets pannel [Taiga #5556](https://tree.taiga.io/project/penpot/issue/5556) - Fix component and media name validation on assets panel [Taiga #5555](https://tree.taiga.io/project/penpot/issue/5555) - Fix problem with selection shortcuts [Taiga #5492](https://tree.taiga.io/project/penpot/issue/5492) +- Fix issue with paths line to curve and concurrent editing [Taiga #5191](https://tree.taiga.io/project/penpot/issue/5191) ### :heart: Community contributions by (Thank you!) diff --git a/common/src/app/common/path/commands.cljc b/common/src/app/common/path/commands.cljc index 7a02f6ec4d..a434cb09e4 100644 --- a/common/src/app/common/path/commands.cljc +++ b/common/src/app/common/path/commands.cljc @@ -50,12 +50,15 @@ (defn update-curve-to [command h1 h2] - (-> command - (assoc :command :curve-to) - (assoc-in [:params :c1x] (:x h1)) - (assoc-in [:params :c1y] (:y h1)) - (assoc-in [:params :c2x] (:x h2)) - (assoc-in [:params :c2y] (:y h2)))) + (let [params {:x (-> command :params :x) + :y (-> command :params :y) + :c1x (:x h1) + :c1y (:y h1) + :c2x (:x h2) + :c2y (:y h2)}] + (-> command + (assoc :command :curve-to) + (assoc :params params)))) (defn make-curve-to [to h1 h2] diff --git a/frontend/src/app/util/path/format.cljs b/frontend/src/app/util/path/format.cljs index f7628bc33a..c0d38829db 100644 --- a/frontend/src/app/util/path/format.cljs +++ b/frontend/src/app/util/path/format.cljs @@ -72,7 +72,7 @@ :curve-to (let [{:keys [c1x c1y c2x c2y]} params] - (join-params c1x c1y c2x c2y x y)) + (join-params (or c1x x) (or c1y y) (or c2x x) (or c2y y) x y)) (:smooth-curve-to :quadratic-bezier-curve-to) (let [{:keys [cx cy]} params] From 302bfd30074cd1ee8c28949cc39f307cbe0ba33e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 3 Jul 2023 15:10:49 +0200 Subject: [PATCH 27/35] :bug: Fix problems with locked frames --- CHANGES.md | 1 + common/src/app/common/types/shape_tree.cljc | 11 +++++++++-- .../main/data/workspace/drawing/common.cljs | 18 ++++++++++-------- .../src/app/main/data/workspace/shapes.cljs | 4 +++- .../app/main/data/workspace/svg_upload.cljs | 2 +- .../app/main/ui/workspace/viewport/hooks.cljs | 1 + .../main/ui/workspace/viewport/widgets.cljs | 4 +++- 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4e7d3a38d7..9de31fbe15 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,7 @@ - Fix component and media name validation on assets panel [Taiga #5555](https://tree.taiga.io/project/penpot/issue/5555) - Fix problem with selection shortcuts [Taiga #5492](https://tree.taiga.io/project/penpot/issue/5492) - Fix issue with paths line to curve and concurrent editing [Taiga #5191](https://tree.taiga.io/project/penpot/issue/5191) +- Fix problems with locked layers [Taiga #5139](https://tree.taiga.io/project/penpot/issue/5139) ### :heart: Community contributions by (Thank you!) diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index 731f31de27..f84db3e4d2 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -260,7 +260,11 @@ (let [frame-ids (cond->> (all-frames-by-position objects position) (some? excluded) - (remove excluded)) + (remove excluded) + + :always + (remove #(or (dm/get-in objects [% :hidden]) + (dm/get-in objects [% :blocked])))) frame-set (set frame-ids)] @@ -276,7 +280,10 @@ "Search the top nested frame in a list of ids" [objects ids] - (let [frame-ids (->> ids (filter #(cph/frame-shape? objects %))) + (let [frame-ids (->> ids + (filter #(cph/frame-shape? objects %)) + (remove #(or (dm/get-in objects [% :hidden]) + (dm/get-in objects [% :blocked])))) frame-set (set frame-ids)] (loop [current-id (first frame-ids)] (let [current-shape (get objects current-id) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 796fe86203..ed9790e248 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -63,20 +63,22 @@ ;; Add & select the created shape to the workspace (rx/concat - (if (= :text (:type shape)) + (if (or (= :text (:type shape)) (= :frame (:type shape))) (rx/of (dwu/start-undo-transaction (:id shape))) (rx/empty)) (rx/of (dwsh/add-shape shape {:no-select? (= tool :curve)})) (if (= :frame (:type shape)) - (->> (uw/ask! {:cmd :selection/query - :page-id page-id - :rect (:selrect shape) - :include-frames? true - :full-frame? true}) - (rx/map #(cph/clean-loops objects %)) - (rx/map #(dwsh/move-shapes-into-frame (:id shape) %))) + (rx/concat + (->> (uw/ask! {:cmd :selection/query + :page-id page-id + :rect (:selrect shape) + :include-frames? true + :full-frame? true}) + (rx/map #(cph/clean-loops objects %)) + (rx/map #(dwsh/move-shapes-into-frame (:id shape) %))) + (rx/of (dwu/commit-undo-transaction (:id shape)))) (rx/empty))))) ;; Delay so the mouse event can read the drawing state diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index 295e880a9a..0ef0f39a28 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -143,12 +143,14 @@ (cond-> (ctl/grid-layout? objects frame-id) (pcb/update-shapes [frame-id] ctl/assign-cells)))))) -(defn move-shapes-into-frame [frame-id shapes] +(defn move-shapes-into-frame + [frame-id shapes] (ptk/reify ::move-shapes-into-frame ptk/WatchEvent (watch [it state _] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) + shapes (->> shapes (remove #(dm/get-in objects [% :blocked]))) changes (-> (pcb/empty-changes it page-id) (pcb/with-objects objects)) changes (prepare-move-shapes-into-frame changes diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index dda47f024d..53fbbbafb1 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -196,7 +196,7 @@ (-> (update-in [:svg-attrs :style] dissoc :mix-blend-mode) (assoc :blend-mode (-> (get-in shape [:svg-attrs :style :mix-blend-mode]) assert-valid-blend-mode))))) -(defn create-raw-svg [name frame-id svg-data {:keys [tag attrs] :as data}] +(defn create-raw-svg [name frame-id svg-data {:keys [attrs] :as data}] (let [{:keys [x y width height offset-x offset-y]} svg-data] (-> {:id (uuid/next) :type :svg-raw diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index e4787f4ec5..0a12452391 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -203,6 +203,7 @@ ids (into (d/ordered-set) + (remove #(dm/get-in objects [% :blocked])) (ctt/sort-z-index objects ids {:bottom-frames? mod?})) grouped? (fn [id] (contains? #{:group :bool} (get-in objects [id :type]))) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index 74dd73d2fe..7755d080ae 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -149,7 +149,9 @@ text-pos-x (if (:use-for-thumbnail? frame) 15 0)] (when (not (:hidden frame)) - [:g.frame-title {:id (dm/str "frame-title-" (:id frame)) :transform (vwu/title-transform frame zoom)} + [:g.frame-title {:id (dm/str "frame-title-" (:id frame)) + :transform (vwu/title-transform frame zoom) + :pointer-events (when (:blocked frame) "none")} (when (:use-for-thumbnail? frame) [:svg {:x 0 :y -9 From 0d87dc56804a13e7fe10265136f302049a54ca82 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 4 Jul 2023 07:17:13 +0200 Subject: [PATCH 28/35] :bug: Fix drag and drop in the dashboard generates import file error message --- frontend/src/app/main/ui/dashboard/grid.cljs | 48 +++++++++++--------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 05d852b304..10e3d2646a 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -495,17 +495,20 @@ (mf/use-fn (mf/deps selected-project) (fn [e] - (when (dnd/has-type? e "penpot/files") - (dom/prevent-default e) - (when-not (or (dnd/from-child? e) + (cond + (dnd/has-type? e "penpot/files") + (do + (dom/prevent-default e) + (when-not (or (dnd/from-child? e) (dnd/broken-event? e)) - (when (not= selected-project project-id) - (reset! dragging? true)))) + (when (not= selected-project project-id) + (reset! dragging? true)))) - (when (or (dnd/has-type? e "Files") - (dnd/has-type? e "application/x-moz-file")) - (dom/prevent-default e) - (reset! dragging? true)))) + (or (dnd/has-type? e "Files") + (dnd/has-type? e "application/x-moz-file")) + (do + (dom/prevent-default e) + (reset! dragging? true))))) on-drag-over (mf/use-fn @@ -531,19 +534,22 @@ (mf/use-fn (mf/deps files selected-files) (fn [e] - (when (or (dnd/has-type? e "Files") - (dnd/has-type? e "application/x-moz-file")) - (dom/prevent-default e) - (reset! dragging? false) - (import-files (.-files (.-dataTransfer e)))) + (cond + (dnd/has-type? e "penpot/files") + (do + (reset! dragging? false) + (when (not= selected-project project-id) + (let [data {:ids (into #{} (keys selected-files)) + :project-id project-id} + mdata {:on-success on-drop-success}] + (st/emit! (dd/move-files (with-meta data mdata)))))) - (when (dnd/has-type? e "penpot/files") - (reset! dragging? false) - (when (not= selected-project project-id) - (let [data {:ids (into #{} (keys selected-files)) - :project-id project-id} - mdata {:on-success on-drop-success}] - (st/emit! (dd/move-files (with-meta data mdata))))))))] + (or (dnd/has-type? e "Files") + (dnd/has-type? e "application/x-moz-file")) + (do + (dom/prevent-default e) + (reset! dragging? false) + (import-files (.-files (.-dataTransfer e)))))))] [:div.dashboard-grid {:on-drag-enter on-drag-enter :on-drag-over on-drag-over From 009236bbe33fc6c3d08c5056545fbea29bc86cdc Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 4 Jul 2023 11:25:10 +0200 Subject: [PATCH 29/35] :bug: Fix export from shared prototype --- CHANGES.md | 3 +++ backend/src/app/rpc/commands/files.clj | 13 +++++------ backend/src/app/rpc/commands/fonts.clj | 15 +++++++----- exporter/src/app/handlers/export_shapes.cljs | 6 +++-- exporter/src/app/renderer.cljs | 4 +++- exporter/src/app/renderer/bitmap.cljs | 4 ++-- exporter/src/app/renderer/pdf.cljs | 3 ++- exporter/src/app/renderer/svg.cljs | 4 ++-- frontend/src/app/main/data/exports.cljs | 7 +++--- frontend/src/app/main/ui/viewer.cljs | 5 ++-- frontend/src/app/main/ui/viewer/inspect.cljs | 5 ++-- .../main/ui/viewer/inspect/attributes.cljs | 5 ++-- .../app/main/ui/viewer/inspect/exports.cljs | 14 ++++++----- .../main/ui/viewer/inspect/right_sidebar.cljs | 5 ++-- frontend/src/app/render.cljs | 23 +++++++++++-------- 15 files changed, 69 insertions(+), 47 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9de31fbe15..a0c6cf6a59 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -34,6 +34,9 @@ - Fix problem with selection shortcuts [Taiga #5492](https://tree.taiga.io/project/penpot/issue/5492) - Fix issue with paths line to curve and concurrent editing [Taiga #5191](https://tree.taiga.io/project/penpot/issue/5191) - Fix problems with locked layers [Taiga #5139](https://tree.taiga.io/project/penpot/issue/5139) +- Fix export from shared prototype [Taiga #5565](https://tree.taiga.io/project/penpot/issue/5565) + +### :arrow_up: Deps updates ### :heart: Community contributions by (Thank you!) diff --git a/backend/src/app/rpc/commands/files.clj b/backend/src/app/rpc/commands/files.clj index e3b88a8bcb..c44c13aa46 100644 --- a/backend/src/app/rpc/commands/files.clj +++ b/backend/src/app/rpc/commands/files.clj @@ -512,6 +512,7 @@ [:map {:title "GetPage"} [:file-id ::sm/uuid] [:page-id {:optional true} ::sm/uuid] + [:share-id {:optional true} ::sm/uuid] [:object-id {:optional true} ::sm/uuid] [:features {:optional true} ::features]]) @@ -527,14 +528,12 @@ Mainly used for rendering purposes." {::doc/added "1.17" ::sm/params ::get-page} - [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}] + [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id share-id] :as params}] (dm/with-open [conn (db/open pool)] - (check-read-permissions! conn profile-id file-id) - - (binding [pmap/*load-fn* (partial load-pointer conn file-id)] - (get-page conn params)))) - - + (let [perms (get-permissions conn profile-id file-id share-id)] + (check-read-permissions! perms) + (binding [pmap/*load-fn* (partial load-pointer conn file-id)] + (get-page conn params))))) ;; --- COMMAND QUERY: get-team-shared-files diff --git a/backend/src/app/rpc/commands/fonts.clj b/backend/src/app/rpc/commands/fonts.clj index 5aab17fde3..256132e847 100644 --- a/backend/src/app/rpc/commands/fonts.clj +++ b/backend/src/app/rpc/commands/fonts.clj @@ -36,6 +36,7 @@ (s/def ::id ::us/uuid) (s/def ::name ::us/not-empty-string) (s/def ::project-id ::us/uuid) +(s/def ::share-id ::us/uuid) (s/def ::style valid-style) (s/def ::team-id ::us/uuid) (s/def ::weight valid-weight) @@ -47,7 +48,8 @@ (s/keys :req [::rpc/profile-id] :opt-un [::team-id ::file-id - ::project-id]) + ::project-id + ::share-id]) (fn [o] (or (contains? o :team-id) (contains? o :file-id) @@ -55,7 +57,7 @@ (sv/defmethod ::get-font-variants {::doc/added "1.18"} - [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id file-id project-id] :as params}] + [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id file-id project-id share-id] :as params}] (dm/with-open [conn (db/open pool)] (cond (uuid? team-id) @@ -74,11 +76,12 @@ (uuid? file-id) (let [file (db/get-by-id conn :file file-id {:columns [:id :project-id]}) - project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]})] - (files/check-read-permissions! conn profile-id file-id) + project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]}) + perms (files/get-permissions conn profile-id file-id share-id)] + (files/check-read-permissions! perms) (db/query conn :team-font-variant - {:team-id (:team-id project) - :deleted-at nil}))))) + {:team-id (:team-id project) + :deleted-at nil}))))) (declare create-font-variant) diff --git a/exporter/src/app/handlers/export_shapes.cljs b/exporter/src/app/handlers/export_shapes.cljs index 4a8e53dab9..a8e108ae46 100644 --- a/exporter/src/app/handlers/export_shapes.cljs +++ b/exporter/src/app/handlers/export_shapes.cljs @@ -28,6 +28,7 @@ (s/def ::name ::us/string) (s/def ::object-id ::us/uuid) (s/def ::page-id ::us/uuid) +(s/def ::share-id ::us/uuid) (s/def ::profile-id ::us/uuid) (s/def ::scale ::us/number) (s/def ::suffix ::us/string) @@ -35,7 +36,8 @@ (s/def ::wait ::us/boolean) (s/def ::export - (s/keys :req-un [::page-id ::file-id ::object-id ::type ::suffix ::scale ::name])) + (s/keys :req-un [::page-id ::file-id ::object-id ::type ::suffix ::scale ::name] + :opt-un [::share-id])) (s/def ::exports (s/coll-of ::export :kind vector? :min-count 1)) @@ -89,7 +91,6 @@ proc (-> (rd/render export on-progress) (p/then (constantly resource)) (p/catch on-error))] - (if wait (p/then proc #(assoc exchange :response/body (dissoc % :path))) (assoc exchange :response/body (dissoc resource :path))))) @@ -188,6 +189,7 @@ (process-partition [[part1 :as part]] {:file-id (:file-id part1) :page-id (:page-id part1) + :share-id (:share-id part1) :name (:name part1) :token token :type (:type part1) diff --git a/exporter/src/app/renderer.cljs b/exporter/src/app/renderer.cljs index 25d462a6cd..b4abaca4bc 100644 --- a/exporter/src/app/renderer.cljs +++ b/exporter/src/app/renderer.cljs @@ -18,12 +18,14 @@ (s/def ::type #{:jpeg :png :pdf :svg}) (s/def ::page-id ::us/uuid) (s/def ::file-id ::us/uuid) +(s/def ::share-id ::us/uuid) (s/def ::scale ::us/number) (s/def ::token ::us/string) (s/def ::filename ::us/string) (s/def ::object - (s/keys :req-un [::id ::name ::suffix ::filename])) + (s/keys :req-un [::id ::name ::suffix ::filename] + :opt-un [::share-id])) (s/def ::objects (s/coll-of ::object :min-count 1)) diff --git a/exporter/src/app/renderer/bitmap.cljs b/exporter/src/app/renderer/bitmap.cljs index 074a826a70..38022db739 100644 --- a/exporter/src/app/renderer/bitmap.cljs +++ b/exporter/src/app/renderer/bitmap.cljs @@ -17,7 +17,7 @@ [promesa.core :as p])) (defn render - [{:keys [file-id page-id token scale type objects] :as params} on-object] + [{:keys [file-id page-id share-id token scale type objects] :as params} on-object] (letfn [(prepare-options [uri] #js {:screen #js {:width bw/default-viewport-width :height bw/default-viewport-height} @@ -48,9 +48,9 @@ ;; take the screnshot of requested objects, one by one (p/run! (partial render-object page) objects) nil))] - (p/let [params {:file-id file-id :page-id page-id + :share-id share-id :object-id (mapv :id objects) :route "objects"} uri (-> (cf/get :public-uri) diff --git a/exporter/src/app/renderer/pdf.cljs b/exporter/src/app/renderer/pdf.cljs index a4f442c9f5..1464f62f3c 100644 --- a/exporter/src/app/renderer/pdf.cljs +++ b/exporter/src/app/renderer/pdf.cljs @@ -17,7 +17,7 @@ [promesa.core :as p])) (defn render - [{:keys [file-id page-id token scale type objects] :as params} on-object] + [{:keys [file-id page-id share-id token scale type objects] :as params} on-object] (letfn [(prepare-options [uri] #js {:screen #js {:width bw/default-viewport-width :height bw/default-viewport-height} @@ -31,6 +31,7 @@ (prepare-uri [base-uri object-id] (let [params {:file-id file-id :page-id page-id + :share-id share-id :object-id object-id :route "objects"}] (-> base-uri diff --git a/exporter/src/app/renderer/svg.cljs b/exporter/src/app/renderer/svg.cljs index 277dac18d1..ba3287a644 100644 --- a/exporter/src/app/renderer/svg.cljs +++ b/exporter/src/app/renderer/svg.cljs @@ -108,7 +108,7 @@ :height height})) (defn render - [{:keys [page-id file-id objects token scale type]} on-object] + [{:keys [page-id file-id share-id objects token scale type]} on-object] (letfn [(convert-to-ppm [pngpath] (let [ppmpath (str/concat pngpath "origin.ppm")] (l/trace :fn :convert-to-ppm :path ppmpath) @@ -338,9 +338,9 @@ ;; take the screnshot of requested objects, one by one (p/run! (partial render-object page) objects) nil))] - (p/let [params {:file-id file-id :page-id page-id + :share-id share-id :render-embed true :object-id (mapv :id objects) :route "objects"} diff --git a/frontend/src/app/main/data/exports.cljs b/frontend/src/app/main/data/exports.cljs index 1ad280babb..729d5d74f7 100644 --- a/frontend/src/app/main/data/exports.cljs +++ b/frontend/src/app/main/data/exports.cljs @@ -75,7 +75,7 @@ {:exports (vec exports)}))))))) (defn show-viewer-export-dialog - [{:keys [shapes page-id file-id exports]}] + [{:keys [shapes page-id file-id share-id exports]}] (ptk/reify ::show-viewer-export-dialog ptk/WatchEvent (watch [_ _ _] @@ -87,8 +87,9 @@ (assoc :file-id file-id) (assoc :object-id (:id shape)) (assoc :shape (dissoc shape :exports)) - (assoc :name (:name shape))))] - (rx/of (modal/show :export-shapes {:exports (vec exports)})))))) + (assoc :name (:name shape)) + (cond-> share-id (assoc :share-id share-id))))] + (rx/of (modal/show :export-shapes {:exports (vec exports)})))))) #_TODO (defn show-workspace-export-frames-dialog [frames] diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index a9823e0259..6df9120f19 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -215,7 +215,7 @@ (mf/defc viewer [{:keys [params data]}] - (let [{:keys [page-id section index interactions-mode]} params + (let [{:keys [page-id share-id section index interactions-mode]} params {:keys [file users project permissions]} data allowed (or @@ -519,7 +519,8 @@ :size size :index index :viewer-pagination viewer-pagination - :interactions-mode interactions-mode}] + :interactions-mode interactions-mode + :share-id share-id}] [:& (mf/provider ctx/current-zoom) {:value zoom} diff --git a/frontend/src/app/main/ui/viewer/inspect.cljs b/frontend/src/app/main/ui/viewer/inspect.cljs index f1e901ad00..4faa901099 100644 --- a/frontend/src/app/main/ui/viewer/inspect.cljs +++ b/frontend/src/app/main/ui/viewer/inspect.cljs @@ -35,7 +35,7 @@ (dom/add-class! layout "force-visible")))))) (mf/defc viewport - [{:keys [local file page frame index viewer-pagination size]}] + [{:keys [local file page frame index viewer-pagination size share-id]}] (let [inspect-svg-container-ref (mf/use-ref nil) on-mouse-wheel (fn [event] @@ -76,4 +76,5 @@ [:& right-sidebar {:frame frame :selected (:selected local) :page page - :file file}]])) + :file file + :share-id share-id}]])) diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes.cljs index 997b83a6c0..19fc153112 100644 --- a/frontend/src/app/main/ui/viewer/inspect/attributes.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/attributes.cljs @@ -34,7 +34,7 @@ :text [:layout :text :shadow :blur :stroke :layout-flex-item]}) (mf/defc attributes - [{:keys [page-id file-id shapes frame from libraries]}] + [{:keys [page-id file-id shapes frame from libraries share-id]}] (let [shapes (hooks/use-equal-memo shapes) shapes (mf/with-memo [shapes] (mapv #(gsh/translate-to-frame % frame) shapes)) @@ -66,4 +66,5 @@ {:shapes shapes :type type :page-id page-id - :file-id file-id}]])) + :file-id file-id + :share-id share-id}]])) diff --git a/frontend/src/app/main/ui/viewer/inspect/exports.cljs b/frontend/src/app/main/ui/viewer/inspect/exports.cljs index 55f3a83972..fc8422f816 100644 --- a/frontend/src/app/main/ui/viewer/inspect/exports.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/exports.cljs @@ -17,7 +17,7 @@ (mf/defc exports {::mf/wrap [#(mf/memo % =)]} - [{:keys [shapes page-id file-id type] :as props}] + [{:keys [shapes page-id file-id share-id type] :as props}] (let [exports (mf/use-state []) xstate (mf/deref refs/export) vstate (mf/deref refs/viewer-data) @@ -40,15 +40,17 @@ :exports @exports :filename filename :page-id page-id - :file-id file-id})) + :file-id file-id + :share-id share-id})) ;; In other all cases we only allowed to have a single ;; shape-id because multiple shape-ids are handled ;; separately by the export-modal. - (let [defaults {:page-id page-id - :file-id file-id - :name filename - :object-id (-> shapes first :id)} + (let [defaults (-> {:page-id page-id + :file-id file-id + :name filename + :object-id (-> shapes first :id)} + (cond-> share-id (assoc :share-id share-id))) exports (mapv #(merge % defaults) @exports)] (if (= 1 (count exports)) (st/emit! (de/request-simple-export {:export (first exports)})) diff --git a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs index c581232842..e3d03bc3f4 100644 --- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.cljs @@ -38,7 +38,7 @@ :data local}))))) (mf/defc right-sidebar - [{:keys [frame page file selected shapes page-id file-id from] + [{:keys [frame page file selected shapes page-id file-id share-id from] :or {from :inspect}}] (let [expanded (mf/use-state false) section (mf/use-state :info #_:code) @@ -89,7 +89,8 @@ :frame frame :shapes shapes :from from - :libraries libraries}]] + :libraries libraries + :share-id share-id}]] [:& tabs-element {:id :code :title (tr "inspect.tabs.code")} [:& code {:frame frame diff --git a/frontend/src/app/render.cljs b/frontend/src/app/render.cljs index 9f3db68afe..20f6e0906d 100644 --- a/frontend/src/app/render.cljs +++ b/frontend/src/app/render.cljs @@ -95,16 +95,17 @@ state)) (mf/defc object-svg - [{:keys [page-id file-id object-id render-embed?]}] + [{:keys [page-id file-id share-id object-id render-embed?]}] (let [components-v2 (feat/use-feature :components-v2) fetch-state (mf/use-fn - (mf/deps file-id page-id object-id components-v2) + (mf/deps file-id page-id share-id object-id components-v2) (fn [] (let [features (cond-> #{} components-v2 (conj "components/v2"))] (->> (rx/zip - (repo/cmd! :get-font-variants {:file-id file-id}) + (repo/cmd! :get-font-variants {:file-id file-id :share-id share-id}) (repo/cmd! :get-page {:file-id file-id :page-id page-id + :share-id share-id :object-id object-id :features features})) (rx/tap (fn [[fonts]] @@ -135,16 +136,17 @@ :render-embed? render-embed?}]))) (mf/defc objects-svg - [{:keys [page-id file-id object-ids render-embed?]}] + [{:keys [page-id file-id share-id object-ids render-embed?]}] (let [components-v2 (feat/use-feature :components-v2) fetch-state (mf/use-fn - (mf/deps file-id page-id components-v2) + (mf/deps file-id page-id share-id components-v2) (fn [] (let [features (cond-> #{} components-v2 (conj "components/v2"))] (->> (rx/zip - (repo/cmd! :get-font-variants {:file-id file-id}) + (repo/cmd! :get-font-variants {:file-id file-id :share-id share-id}) (repo/cmd! :get-page {:file-id file-id :page-id page-id + :share-id share-id :features features})) (rx/tap (fn [[fonts]] (when (seq fonts) @@ -164,6 +166,7 @@ (s/def ::page-id ::us/uuid) (s/def ::file-id ::us/uuid) +(s/def ::share-id ::us/uuid) (s/def ::object-id (s/or :single ::us/uuid :multiple (s/coll-of ::us/uuid))) @@ -171,24 +174,25 @@ (s/def ::render-objects (s/keys :req-un [::file-id ::page-id ::object-id] - :opt-un [::render-embed])) + :opt-un [::render-embed ::share-id])) (defn- render-objects [params] (let [{:keys [file-id page-id - render-embed] + render-embed + share-id] :as params} (us/conform ::render-objects params) [type object-id] (:object-id params)] - (case type :single (mf/html [:& object-svg {:file-id file-id :page-id page-id + :share-id share-id :object-id object-id :render-embed? render-embed}]) @@ -197,6 +201,7 @@ [:& objects-svg {:file-id file-id :page-id page-id + :share-id share-id :object-ids (into #{} object-id) :render-embed? render-embed}])))) From b43d09e5cee5f788100889584c20a28bd4f54f5f Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 4 Jul 2023 12:33:25 +0200 Subject: [PATCH 30/35] :bug: Fix email change validation --- CHANGES.md | 1 + .../src/app/main/ui/components/forms.cljs | 7 ++++-- .../app/main/ui/settings/change_email.cljs | 23 +++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a0c6cf6a59..593baaf3d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,6 +35,7 @@ - Fix issue with paths line to curve and concurrent editing [Taiga #5191](https://tree.taiga.io/project/penpot/issue/5191) - Fix problems with locked layers [Taiga #5139](https://tree.taiga.io/project/penpot/issue/5139) - Fix export from shared prototype [Taiga #5565](https://tree.taiga.io/project/penpot/issue/5565) +- Fix email change: validation error displaying even after both fields are identical [Taiga #5514](https://tree.taiga.io/project/penpot/issue/5514) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index f753038175..f8441061e4 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -24,7 +24,7 @@ (def use-form fm/use-form) (mf/defc input - [{:keys [label help-icon disabled form hint trim children data-test] :as props}] + [{:keys [label help-icon disabled form hint trim children data-test on-change-value] :as props}] (let [input-type (get props :type "text") input-name (get props :name) more-classes (get props :class) @@ -57,6 +57,8 @@ :else help-icon) + on-change-value (or on-change-value (constantly nil)) + klass (str more-classes " " (dom/classnames :focus @focus? @@ -80,7 +82,8 @@ on-change (fn [event] (let [value (-> event dom/get-target dom/get-input-value)] (swap! form assoc-in [:touched input-name] true) - (fm/on-input-change form input-name value trim))) + (fm/on-input-change form input-name value trim) + (on-change-value name value))) on-blur (fn [_] diff --git a/frontend/src/app/main/ui/settings/change_email.cljs b/frontend/src/app/main/ui/settings/change_email.cljs index 3bca85224f..26521ed784 100644 --- a/frontend/src/app/main/ui/settings/change_email.cljs +++ b/frontend/src/app/main/ui/settings/change_email.cljs @@ -6,6 +6,8 @@ (ns app.main.ui.settings.change-email (:require + [app.common.data :as d] + [app.common.data.macros :as dma] [app.common.spec :as us] [app.main.data.messages :as dm] [app.main.data.modal :as modal] @@ -29,7 +31,8 @@ email-2 (:email-2 data)] (cond-> errors (and email-1 email-2 (not= email-1 email-2)) - (assoc :email-2 {:message (tr "errors.email-invalid-confirmation")})))) + (assoc :email-2 {:message (tr "errors.email-invalid-confirmation") + :code :different-emails})))) (s/def ::email-change-form (s/keys :req-un [::email-1 ::email-2])) @@ -81,7 +84,17 @@ on-submit (mf/use-callback (mf/deps profile) - (partial on-submit profile))] + (partial on-submit profile)) + + on-email-change + (mf/use-callback + (fn [_ _] + (let [different-emails-error? (= (dma/get-in @form [:errors :email-2 :code]) :different-emails) + email-1 (dma/get-in @form [:clean-data :email-1]) + email-2 (dma/get-in @form [:clean-data :email-2])] + (println "different-emails-error?" (and different-emails-error? (= email-1 email-2))) + (when (and different-emails-error? (= email-1 email-2)) + (swap! form d/dissoc-in [:errors :email-2])))))] [:div.modal-overlay [:div.modal-container.change-email-modal.form-container @@ -105,12 +118,14 @@ [:& fm/input {:type "email" :name :email-1 :label (tr "modals.change-email.new-email") - :trim true}]] + :trim true + :on-change-value on-email-change}]] [:div.fields-row [:& fm/input {:type "email" :name :email-2 :label (tr "modals.change-email.confirm-email") - :trim true}]]]] + :trim true + :on-change-value on-email-change}]]]] [:div.modal-footer [:div.action-buttons {:data-test "change-email-submit"} From 01ec22d662646be9e4a4501852b939547e1ce2b0 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 4 Jul 2023 15:52:33 +0200 Subject: [PATCH 31/35] :bug: Fix finalize text editor state when blur --- frontend/src/app/main/ui/workspace/shapes/text/editor.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index ae28789f61..64805ef19e 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -133,6 +133,8 @@ (fn [event] (dom/stop-propagation event) (dom/prevent-default event) + (st/emit! ::dwt/finalize-editor-state) + (st/emit! (dwt/initialize-editor-state shape default-decorator)) (reset! blurred true))) on-focus From 48d9541d46b02020d1ce58ca374c58afc1276b47 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 13:05:12 +0200 Subject: [PATCH 32/35] :bug: Fix scroll of comment list on viewer --- CHANGES.md | 1 + frontend/resources/styles/main/partials/comments.scss | 2 +- frontend/resources/styles/main/partials/viewer.scss | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 593baaf3d5..6b313a2cf8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -36,6 +36,7 @@ - Fix problems with locked layers [Taiga #5139](https://tree.taiga.io/project/penpot/issue/5139) - Fix export from shared prototype [Taiga #5565](https://tree.taiga.io/project/penpot/issue/5565) - Fix email change: validation error displaying even after both fields are identical [Taiga #5514](https://tree.taiga.io/project/penpot/issue/5514) +- Fix scroll on viewer comment list [Taiga #5563](https://tree.taiga.io/project/penpot/issue/5563) ### :arrow_up: Deps updates diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss index b2d89ce3f9..7c2d4bf002 100644 --- a/frontend/resources/styles/main/partials/comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -246,7 +246,7 @@ pointer-events: auto; .thread-groups { - height: 100%; + height: calc(100% - 34px); overflow-y: scroll; hr { border: 0; diff --git a/frontend/resources/styles/main/partials/viewer.scss b/frontend/resources/styles/main/partials/viewer.scss index 1ed55ff1c4..7f26f42060 100644 --- a/frontend/resources/styles/main/partials/viewer.scss +++ b/frontend/resources/styles/main/partials/viewer.scss @@ -182,7 +182,7 @@ right: 0; top: 50px; width: 256px; - height: 100%; + height: calc(100vh - 48px); z-index: 10; } From 7216a514e615717135c6da81be557edbdb765dc6 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 3 Jul 2023 13:06:31 +0200 Subject: [PATCH 33/35] :bug: Fix context menu z-index --- CHANGES.md | 1 + frontend/resources/styles/main/partials/viewer.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 6b313a2cf8..64fccbfce2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ - Fix export from shared prototype [Taiga #5565](https://tree.taiga.io/project/penpot/issue/5565) - Fix email change: validation error displaying even after both fields are identical [Taiga #5514](https://tree.taiga.io/project/penpot/issue/5514) - Fix scroll on viewer comment list [Taiga #5563](https://tree.taiga.io/project/penpot/issue/5563) +- Fix context menu z-index [Taiga #5561](https://tree.taiga.io/project/penpot/issue/5561) ### :arrow_up: Deps updates diff --git a/frontend/resources/styles/main/partials/viewer.scss b/frontend/resources/styles/main/partials/viewer.scss index 7f26f42060..3a52326a7a 100644 --- a/frontend/resources/styles/main/partials/viewer.scss +++ b/frontend/resources/styles/main/partials/viewer.scss @@ -183,7 +183,7 @@ top: 50px; width: 256px; height: calc(100vh - 48px); - z-index: 10; + z-index: 9; } .empty-state { From acfeae8638545ffec43664cb7c9a8f433c5a369c Mon Sep 17 00:00:00 2001 From: Eva Date: Tue, 4 Jul 2023 07:47:12 +0200 Subject: [PATCH 34/35] :bug: Fix select all checkbox on shared link config --- CHANGES.md | 1 + .../src/app/main/ui/viewer/share_link.cljs | 85 +++++++++++-------- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 64fccbfce2..486266b23e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,6 +38,7 @@ - Fix email change: validation error displaying even after both fields are identical [Taiga #5514](https://tree.taiga.io/project/penpot/issue/5514) - Fix scroll on viewer comment list [Taiga #5563](https://tree.taiga.io/project/penpot/issue/5563) - Fix context menu z-index [Taiga #5561](https://tree.taiga.io/project/penpot/issue/5561) +- Fix select all checkbox on shared link config [Taiga #5566](https://tree.taiga.io/project/penpot/issue/5566) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/viewer/share_link.cljs b/frontend/src/app/main/ui/viewer/share_link.cljs index 8b0e69685d..3d45606c44 100644 --- a/frontend/src/app/main/ui/viewer/share_link.cljs +++ b/frontend/src/app/main/ui/viewer/share_link.cljs @@ -28,31 +28,36 @@ (defn prepare-params [{:keys [pages who-comment who-inspect]}] - {:pages pages - :who-comment who-comment - :who-inspect who-inspect}) + {:pages pages + :who-comment who-comment + :who-inspect who-inspect}) (mf/defc share-link-dialog {::mf/register modal/components ::mf/register-as :share-link} [{:keys [file page]}] (let [current-page page - slinks (mf/deref refs/share-links) - router (mf/deref refs/router) - route (mf/deref refs/route) - zoom-type (mf/deref refs/viewer-zoom-type) + slinks (mf/deref refs/share-links) + router (mf/deref refs/router) + route (mf/deref refs/route) + zoom-type (mf/deref refs/viewer-zoom-type) - link (mf/use-state nil) - confirm (mf/use-state false) - open-ops (mf/use-state false) + link (mf/use-state nil) + confirm (mf/use-state false) + open-ops (mf/use-state false) - opts (mf/use-state - {:pages-mode "current" - :all-pages false - :pages #{(:id page)} - :who-comment "team" - :who-inspect "team"}) + opts* (mf/use-state + {:pages-mode "current" + :all-pages false + :pages #{(:id page)} + :who-comment "team" + :who-inspect "team"}) + opts (deref opts*) + + selected-pages (:pages opts) + file-pages (->> (get-in file [:data :pages]) + (map #(get-in file [:data :pages-index %]))) close (fn [event] @@ -63,7 +68,7 @@ toggle-all (fn [] (reset! confirm false) - (swap! opts + (swap! opts* (fn [state] (if (= true (:all-pages state)) (-> state @@ -74,23 +79,29 @@ (assoc :pages (into #{} (get-in file [:data :pages])))))))) mark-checked-page - (fn [event id] - (let [target (dom/get-target event) - checked? (.-checked ^js target) - dif-pages? (not= id (first (:pages @opts))) - no-one-page (< 1 (count (:pages @opts))) + (mf/use-fn + (mf/deps selected-pages) + (fn [event id] + (let [target (dom/get-target event) + not-checked? (.-checked ^js target) + dif-pages? (not= id (first selected-pages)) + no-one-page (< 1 (count selected-pages)) should-change (or no-one-page dif-pages?)] (when should-change (reset! confirm false) - (swap! opts update :pages - (fn [pages] - (if checked? - (conj pages id) - (disj pages id))))))) + (swap! opts* + (fn [state] + (let [actual-pages (:pages state) + updated-pages (if not-checked? + (conj actual-pages id) + (disj actual-pages id))] + (-> state + (assoc :pages updated-pages) + (assoc :all-pages (= (count updated-pages) (count file-pages))))))))))) create-link (fn [_] - (let [params (prepare-params @opts) + (let [params (prepare-params opts) params (assoc params :file-id (:id file))] (st/emit! (dc/create-share-link params) (ptk/event ::ev/event {::ev/name "create-shared-link" @@ -111,7 +122,7 @@ delete-link (fn [_] - (let [params (prepare-params @opts) + (let [params (prepare-params opts) slink (d/seek #(= (:flags %) (:flags params)) slinks)] (reset! confirm false) (st/emit! (dc/delete-share-link slink)))) @@ -127,13 +138,13 @@ value (keyword value)] (reset! confirm false) (if (= type :comment) - (swap! opts assoc :who-comment (d/name value)) - (swap! opts assoc :who-inspect (d/name value)))))] + (swap! opts* assoc :who-comment (d/name value)) + (swap! opts* assoc :who-inspect (d/name value)))))] (mf/use-effect - (mf/deps file slinks @opts) + (mf/deps file slinks opts) (fn [] - (let [{:keys [pages who-comment who-inspect] :as params} (prepare-params @opts) + (let [{:keys [pages who-comment who-inspect] :as params} (prepare-params opts) slink (d/seek #(and (= (:who-inspect %) who-inspect) (= (:who-comment %) who-comment) (= (:pages %) pages)) slinks) href (when slink (let [pparams (:path-params route) @@ -204,10 +215,10 @@ [:div.title (tr "common.share-link.manage-ops")]] (when @open-ops [:* - (let [all-selected? (:all-pages @opts) + (let [all-selected? (:all-pages opts) pages (->> (get-in file [:data :pages]) (map #(get-in file [:data :pages-index %]))) - selected (:pages @opts)] + selected selected-pages] [:* [:div.view-mode @@ -253,7 +264,7 @@ (tr "common.share-link.permissions-can-comment")] [:div.items [:select.input-select {:on-change (partial on-who-change :comment) - :value (:who-comment @opts)} + :value (:who-comment opts)} [:option {:value "team"} (tr "common.share-link.team-members")] [:option {:value "all"} (tr "common.share-link.all-users")]]]] [:div.inspect-mode @@ -262,7 +273,7 @@ (tr "common.share-link.permissions-can-inspect")] [:div.items [:select.input-select {:on-change (partial on-who-change :inspect) - :value (:who-inspect @opts)} + :value (:who-inspect opts)} [:option {:value "team"} (tr "common.share-link.team-members")] [:option {:value "all"} (tr "common.share-link.all-users")]]]]])]]])) From 49df4a9404a0ea5ada44d51fbc32ffbd14d04b61 Mon Sep 17 00:00:00 2001 From: Eva Date: Wed, 5 Jul 2023 13:20:41 +0200 Subject: [PATCH 35/35] :bug: Fix several frontend validations --- CHANGES.md | 3 ++ frontend/src/app/main/ui/auth/recovery.cljs | 4 ++- frontend/src/app/main/ui/auth/register.cljs | 13 +++---- .../src/app/main/ui/components/forms.cljs | 35 ++++++++++++++++--- frontend/src/app/main/ui/dashboard/team.cljs | 6 ++-- .../src/app/main/ui/dashboard/team_form.cljs | 11 ++---- .../app/main/ui/onboarding/team_choice.cljs | 4 ++- .../app/main/ui/settings/access_tokens.cljs | 5 +-- .../src/app/main/ui/settings/feedback.cljs | 5 +-- .../src/app/main/ui/settings/password.cljs | 16 ++------- .../src/app/main/ui/settings/profile.cljs | 5 ++- .../app/main/ui/workspace/sidebar/assets.cljs | 2 ++ frontend/translations/en.po | 16 ++++++--- frontend/translations/es.po | 16 ++++++--- 14 files changed, 88 insertions(+), 53 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 486266b23e..280690f319 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,9 @@ - Fix scroll on viewer comment list [Taiga #5563](https://tree.taiga.io/project/penpot/issue/5563) - Fix context menu z-index [Taiga #5561](https://tree.taiga.io/project/penpot/issue/5561) - Fix select all checkbox on shared link config [Taiga #5566](https://tree.taiga.io/project/penpot/issue/5566) +- Fix validation on full name input on account creation [Taiga #5516](https://tree.taiga.io/project/penpot/issue/5516) +- Fix validation on team name input [Taiga #5510](https://tree.taiga.io/project/penpot/issue/5510) + ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/auth/recovery.cljs b/frontend/src/app/main/ui/auth/recovery.cljs index 3f752f7f62..397edc4d9a 100644 --- a/frontend/src/app/main/ui/auth/recovery.cljs +++ b/frontend/src/app/main/ui/auth/recovery.cljs @@ -56,7 +56,9 @@ (mf/defc recovery-form [{:keys [params] :as props}] (let [form (fm/use-form :spec ::recovery-form - :validators [password-equality] + :validators [password-equality + (fm/validate-not-empty :password-1 (tr "auth.password-not-empty")) + (fm/validate-not-empty :password-2 (tr "auth.password-not-empty"))] :initial params)] [:& fm/form {:on-submit on-submit :form form} diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index 37314093b4..01986eccbd 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -22,7 +22,6 @@ [app.util.router :as rt] [beicon.core :as rx] [cljs.spec.alpha :as s] - [cuerdas.core :as str] [rumext.v2 :as mf])) (mf/defc demo-warning @@ -46,13 +45,6 @@ (= code ::us/email) (assoc :message (tr "errors.email-invalid")))))))) -(defn- validate-password - [errors data] - (let [password (-> data :password str/trim)] - (cond-> errors - (str/empty? password) - (assoc :password {:message (tr "auth.password-not-empty")})))) - (s/def ::fullname ::us/not-empty-string) (s/def ::password ::us/not-empty-string) (s/def ::email ::us/email) @@ -95,7 +87,8 @@ [{:keys [params on-success-callback] :as props}] (let [initial (mf/use-memo (mf/deps params) (constantly params)) form (fm/use-form :spec ::register-form - :validators [validate validate-password] + :validators [validate + (fm/validate-not-empty :password (tr "auth.password-not-empty"))] :initial initial) submitted? (mf/use-state false) @@ -227,6 +220,8 @@ (mf/defc register-validate-form [{:keys [params on-success-callback] :as props}] (let [form (fm/use-form :spec ::register-validate-form + :validators [(fm/validate-not-empty :fullname (tr "auth.name.not-all-space")) + (fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))] :initial params) submitted? (mf/use-state false) diff --git a/frontend/src/app/main/ui/components/forms.cljs b/frontend/src/app/main/ui/components/forms.cljs index f8441061e4..deb8f6a46f 100644 --- a/frontend/src/app/main/ui/components/forms.cljs +++ b/frontend/src/app/main/ui/components/forms.cljs @@ -58,7 +58,7 @@ help-icon) on-change-value (or on-change-value (constantly nil)) - + klass (str more-classes " " (dom/classnames :focus @focus? @@ -138,7 +138,6 @@ (string? hint) [:span.hint hint])]])) - (mf/defc textarea [{:keys [label disabled form hint trim] :as props}] (let [input-name (get props :name) @@ -225,7 +224,7 @@ (for [item options] [:> :option (clj->js (cond-> {:key (:value item) :value (:value item)} (:disabled item) (assoc :disabled "disabled") - (:hidden item) (assoc :style {:display "none"}))) + (:hidden item) (assoc :style {:display "none"}))) (:label item)])] [:div.input-container {:class (dom/classnames :disabled disabled :focus @focus?)} @@ -240,7 +239,7 @@ [{:keys [name options form trim on-change-value] :as props}] (let [form (or form (mf/use-ctx form-ctx)) value (get-in @form [:data name] "") - on-change-value (or on-change-value (constantly nil)) + on-change-value (or on-change-value (constantly nil)) on-change (fn [event] (let [value (-> event dom/get-target dom/get-value)] (swap! form assoc-in [:touched name] true) @@ -412,3 +411,31 @@ "caution" (:caution item))} [:span.text (:text item)] [:span.icon {:on-click #(remove-item! item)} i/cross]]])])])) + +;; --- Validators + +(defn all-spaces? + [value] + (let [trimmed (str/trim value)] + (str/empty? trimmed))) + +(def max-length-allowed 250) +(def max-uri-length-allowed 2048) + +(defn max-length? + [value length] + (> (count value) length)) + +(defn validate-length + [field length errors-msg ] + (fn [errors data] + (cond-> errors + (max-length? (get data field) length) + (assoc field {:message errors-msg})))) + +(defn validate-not-empty + [field error-msg] + (fn [errors data] + (cond-> errors + (all-spaces? (get data field)) + (assoc field {:message error-msg})))) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index dcd4ef8675..f2a6625c4d 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -658,7 +658,8 @@ (let [initial (mf/use-memo (fn [] (or (some-> webhook (update :uri str)) {:is-active false :mtype "application/json"}))) form (fm/use-form :spec ::webhook-form - :initial initial) + :initial initial + :validators [(fm/validate-length :uri fm/max-uri-length-allowed (tr "team.webhooks.max-length"))]) on-success (mf/use-fn (fn [_] @@ -750,8 +751,7 @@ [:& fm/input {:type "checkbox" :form form :name :is-active - :label (tr "dashboard.webhooks.active")}] - ] + :label (tr "dashboard.webhooks.active")}]] [:div.explain (tr "dashboard.webhooks.active.explain")]]] [:div.modal-footer diff --git a/frontend/src/app/main/ui/dashboard/team_form.cljs b/frontend/src/app/main/ui/dashboard/team_form.cljs index 81579044cf..e09501b60b 100644 --- a/frontend/src/app/main/ui/dashboard/team_form.cljs +++ b/frontend/src/app/main/ui/dashboard/team_form.cljs @@ -17,20 +17,12 @@ [app.util.router :as rt] [beicon.core :as rx] [cljs.spec.alpha :as s] - [cuerdas.core :as str] [rumext.v2 :as mf])) (s/def ::name ::us/not-empty-string) (s/def ::team-form (s/keys :req-un [::name])) -(defn- validate-name - [errors data] - (let [name (-> data :name str/trim)] - (cond-> errors - (str/empty? name) - (assoc :name {:message (tr "dashboard.team-name.not-empty-name")})))) - (defn- on-create-success [_form response] (let [msg "Team created successfully"] @@ -78,7 +70,8 @@ [{:keys [team] :as props}] (let [initial (mf/use-memo (fn [] (or team {}))) form (fm/use-form :spec ::team-form - :validators [validate-name] + :validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space")) + (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))] :initial initial)] [:div.modal-overlay [:div.modal-container.team-form-modal diff --git a/frontend/src/app/main/ui/onboarding/team_choice.cljs b/frontend/src/app/main/ui/onboarding/team_choice.cljs index f34fab29b8..2dd7ee3de8 100644 --- a/frontend/src/app/main/ui/onboarding/team_choice.cljs +++ b/frontend/src/app/main/ui/onboarding/team_choice.cljs @@ -54,7 +54,9 @@ ::mf/register-as :onboarding-team} [] (let [form (fm/use-form :spec ::team-form - :initial {}) + :initial {} + :validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space")) + (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))]) on-submit (mf/use-callback (fn [form _] diff --git a/frontend/src/app/main/ui/settings/access_tokens.cljs b/frontend/src/app/main/ui/settings/access_tokens.cljs index 66606b7531..2444324edf 100644 --- a/frontend/src/app/main/ui/settings/access_tokens.cljs +++ b/frontend/src/app/main/ui/settings/access_tokens.cljs @@ -42,7 +42,6 @@ (str/blank? name) (assoc :name {:message (tr "dashboard.access-tokens.errors-required-name")})))) - (def initial-data {:name "" :expiration-date "never"}) @@ -53,7 +52,9 @@ (let [form (fm/use-form :initial initial-data :spec ::access-token-form - :validators [name-validator]) + :validators [name-validator + (fm/validate-not-empty :name (tr "auth.name.not-all-space")) + (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))]) created (mf/deref token-created-ref) created? (mf/use-state false) locale (mf/deref i18n/locale) diff --git a/frontend/src/app/main/ui/settings/feedback.cljs b/frontend/src/app/main/ui/settings/feedback.cljs index fd3d9eedbc..d510ef7c5b 100644 --- a/frontend/src/app/main/ui/settings/feedback.cljs +++ b/frontend/src/app/main/ui/settings/feedback.cljs @@ -28,8 +28,9 @@ (mf/defc feedback-form [] (let [profile (mf/deref refs/profile) - form (fm/use-form :spec ::feedback-form) - + form (fm/use-form :spec ::feedback-form + :validators [(fm/validate-length :subject fm/max-length-allowed (tr "auth.name.too-long")) + (fm/validate-not-empty :subject (tr "auth.name.not-all-space"))]) loading (mf/use-state false) on-succes diff --git a/frontend/src/app/main/ui/settings/password.cljs b/frontend/src/app/main/ui/settings/password.cljs index f9ab2a915c..48f15b00ba 100644 --- a/frontend/src/app/main/ui/settings/password.cljs +++ b/frontend/src/app/main/ui/settings/password.cljs @@ -14,7 +14,6 @@ [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t tr]] [cljs.spec.alpha :as s] - [cuerdas.core :as str] [rumext.v2 :as mf])) (defn- on-error @@ -63,17 +62,6 @@ (and password-1 (> 8 (count password-1))) (assoc :password-1 {:message (tr "errors.password-too-short")})))) -(defn- validate-password - [errors data] - (let [password-1 (-> data :password-1 str/trim) - password-2 (-> data :password-2 str/trim)] - (cond-> errors - (str/empty? password-1) - (assoc :password-1 {:message (tr "auth.password-not-empty")}) - - (str/empty? password-2) - (assoc :password-2 {:message (tr "auth.password-not-empty")})))) - (s/def ::password-form (s/keys :req-un [::password-1 ::password-2 @@ -83,7 +71,9 @@ [{:keys [locale] :as props}] (let [initial (mf/use-memo (constantly {:password-old nil})) form (fm/use-form :spec ::password-form - :validators [validate-password password-equality] + :validators [(fm/validate-not-empty :password-1 (tr "auth.password-not-empty")) + (fm/validate-not-empty :password-2 (tr "auth.password-not-empty")) + password-equality] :initial initial)] [:& fm/form {:class "password-form" :on-submit on-submit diff --git a/frontend/src/app/main/ui/settings/profile.cljs b/frontend/src/app/main/ui/settings/profile.cljs index 9a13dbaedd..cbb302b709 100644 --- a/frontend/src/app/main/ui/settings/profile.cljs +++ b/frontend/src/app/main/ui/settings/profile.cljs @@ -42,7 +42,10 @@ (mf/defc profile-form [] (let [profile (mf/deref refs/profile) - form (fm/use-form :spec ::profile-form :initial profile)] + form (fm/use-form :spec ::profile-form + :initial profile + :validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long")) + (fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))])] [:& fm/form {:on-submit on-submit :form form diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 0f8ff338f3..82cbe41f95 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -134,6 +134,8 @@ (mf/deps last-path) (constantly {:asset-name last-path})) form (fm/use-form :spec ::name-group-form + :validators [(fm/validate-not-empty :name (tr "auth.name.not-all-space")) + (fm/validate-length :name fm/max-length-allowed (tr "auth.name.too-long"))] :initial initial) create? (empty? path) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index d1c88fc3b2..bfefc32b13 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -53,6 +53,14 @@ msgstr "Full Name" msgid "auth.login-here" msgstr "Login here" +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +msgid "auth.name.too-long" +msgstr "The name must contain at most 250 characters." + +#: src/app/main/ui/settings/team-form.cljs, src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +msgid "auth.name.not-all-space" +msgstr "The name must contain some character other than space." + #: src/app/main/ui/auth/login.cljs msgid "auth.login-submit" msgstr "Login" @@ -375,10 +383,6 @@ msgstr "180 days" msgid "dashboard.access-tokens.errors-required-name" msgstr "The name is required" -#: src/app/main/ui/settings/team-form.cljs -msgid "dashboard.team-name.not-empty-name" -msgstr "The name must contain some character other than space." - #: src/app/main/ui/settings/access-tokens.cljs msgid "dashboard.access-tokens.token-will-expire" msgstr "The token will expire on %s" @@ -812,6 +816,10 @@ msgstr "No webhooks created so far." msgid "dashboard.webhooks.update.success" msgstr "Webhook updated successfully." +#: src/app/main/ui/dashboard/team.cljs +msgid "team.webhooks.max-length" +msgstr "The webhook name must contain at most 2048 characters." + #: src/app/main/ui/settings.cljs msgid "dashboard.your-account-title" msgstr "Your account" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 9cadae14db..dcdd6727b9 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -56,6 +56,14 @@ msgstr "Nombre completo" msgid "auth.login-here" msgstr "Inicia sesión aquí" +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +msgid "auth.name.too-long" +msgstr "El nombre debe contener como máximo 250 caracteres." + +#: src/app/main/ui/settings/team-form.cljs, src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +msgid "auth.name.not-all-space" +msgstr "El nombre debe contener algún carácter diferente de espacio" + #: src/app/main/ui/auth/login.cljs msgid "auth.login-submit" msgstr "Entrar" @@ -382,10 +390,6 @@ msgstr "180 días" msgid "dashboard.access-tokens.errors-required-name" msgstr "El nombre es obligatorio" -#: src/app/main/ui/settings/team-form.cljs -msgid "dashboard.team-name.not-empty-name" -msgstr "El nombre debe contener algún carácter diferente de espacio" - #: src/app/main/ui/settings/access-tokens.cljs msgid "dashboard.access-tokens.token-will-expire" msgstr "El token expirará el %s" @@ -828,6 +832,10 @@ msgstr "No hay ningún webhook aún." msgid "dashboard.webhooks.update.success" msgstr "Webhook modificado con éxito." +#: src/app/main/ui/dashboard/team.cljs +msgid "team.webhooks.max-length" +msgstr "El nombre del webhook debe contener como máximo 2048 caracteres." + #: src/app/main/ui/settings.cljs msgid "dashboard.your-account-title" msgstr "Tu cuenta"