diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index c741ee6829..493311af2c 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -476,7 +476,7 @@ ::oapi/type "string" ::oapi/format "email"}}) -(def non-empty-strings-xf +(def xf:filter-word-strings (comp (filter string?) (remove str/empty?) @@ -489,11 +489,8 @@ :min 0 :max 1 :compile - (fn [{:keys [coerce kind max min] :as props} children _] - (let [xform (if coerce - (comp non-empty-strings-xf (map coerce)) - non-empty-strings-xf) - kind (or (last children) kind) + (fn [{:keys [kind max min] :as props} children _] + (let [kind (or (last children) kind) pred (cond @@ -501,9 +498,6 @@ (nil? kind) any? :else (validator kind)) - encode-child - (encoder kind string-transformer) - pred (cond (and max min) @@ -531,31 +525,49 @@ (fn [value] (every? pred value))) - decode + + decode-string-child + (decoder kind string-transformer) + + decode-string (fn [v] - (let [v (if (string? v) (str/split v #"[\s,]+") v)] - (into #{} xform v))) + (let [v (if (string? v) (str/split v #"[\s,]+") v) + x (comp xf:filter-word-strings (map decode-string-child))] + (into #{} x v))) + + decode-json-child + (decoder kind json-transformer) + + decode-json + (fn [v] + (let [v (if (string? v) (str/split v #"[\s,]+") v) + x (comp xf:filter-word-strings (map decode-json-child))] + (into #{} x v))) + + encode-string-child + (encoder kind string-transformer) + + encode-string + (fn [o] + (if (set? o) + (str/join ", " (map encode-string-child o)) + o)) encode-json (fn [o] (if (set? o) (vec o) - o)) - - encode-string - (fn [o] - (if (set? o) - (str/join ", " (map encode-child o)) o))] + {:pred pred :type-properties {:title "set" :description "Set of Strings" :error/message "should be a set of strings" :gen/gen (-> kind sg/generator sg/set) - :decode/string decode - :decode/json decode + :decode/string decode-string + :decode/json decode-json :encode/string encode-string :encode/json encode-json ::oapi/type "array" @@ -569,21 +581,14 @@ :min 0 :max 1 :compile - (fn [{:keys [coerce kind max min] :as props} children _] - (let [xform (if coerce - (comp non-empty-strings-xf (map coerce)) - non-empty-strings-xf) - - kind (or (last children) kind) + (fn [{:keys [kind max min] :as props} children _] + (let [kind (or (last children) kind) pred (cond (fn? kind) kind (nil? kind) any? :else (validator kind)) - encode-child - (encoder kind string-transformer) - pred (cond (and max min) @@ -611,15 +616,31 @@ (fn [value] (every? pred value))) - decode + decode-string-child + (decoder kind string-transformer) + + decode-json-child + (decoder kind json-transformer) + + decode-string (fn [v] - (let [v (if (string? v) (str/split v #"[\s,]+") v)] - (into [] xform v))) + (let [v (if (string? v) (str/split v #"[\s,]+") v) + x (comp xf:filter-word-strings (map decode-string-child))] + (into #{} x v))) + + decode-json + (fn [v] + (let [v (if (string? v) (str/split v #"[\s,]+") v) + x (comp xf:filter-word-strings (map decode-json-child))] + (into #{} x v))) + + encode-string-child + (encoder kind string-transformer) encode-string (fn [o] (if (vector? o) - (str/join ", " (map encode-child o)) + (str/join ", " (map encode-string-child o)) o))] {:pred pred @@ -628,8 +649,8 @@ :description "Set of Strings" :error/message "should be a set of strings" :gen/gen (-> kind sg/generator sg/set) - :decode/string decode - :decode/json decode + :decode/string decode-string + :decode/json decode-json :encode/string encode-string ::oapi/type "array" ::oapi/format "set" @@ -646,7 +667,7 @@ :gen/gen (-> :string sg/generator sg/set) :decode/string (fn [v] (let [v (if (string? v) (str/split v #"[\s,]+") v)] - (into #{} non-empty-strings-xf v))) + (into #{} xf:filter-word-strings v))) ::oapi/type "array" ::oapi/format "set" ::oapi/items {:type "string"} @@ -662,7 +683,7 @@ :gen/gen (-> :keyword sg/generator sg/set) :decode/string (fn [v] (let [v (if (string? v) (str/split v #"[\s,]+") v)] - (into #{} (comp non-empty-strings-xf (map keyword)) v))) + (into #{} (comp xf:filter-word-strings (map keyword)) v))) ::oapi/type "array" ::oapi/format "set" ::oapi/items {:type "string" :format "keyword"} diff --git a/exporter/src/app/config.cljs b/exporter/src/app/config.cljs index 4c00880776..6ca84f584c 100644 --- a/exporter/src/app/config.cljs +++ b/exporter/src/app/config.cljs @@ -26,16 +26,24 @@ (def ^:private schema:config - (sm/define - [:map {:title "config"} - [:public-uri {:optional true} ::sm/uri] - [:host {:optional true} :string] - [:tenant {:optional true} :string] - [:flags {:optional true} ::sm/set-of-keywords] - [:redis-uri {:optional true} :string] - [:tempdir {:optional true} :string] - [:browser-pool-max {:optional true} :int] - [:browser-pool-min {:optional true} :int]])) + [:map {:title "config"} + [:public-uri {:optional true} ::sm/uri] + [:host {:optional true} :string] + [:tenant {:optional true} :string] + [:flags {:optional true} [::sm/set :keyword]] + [:redis-uri {:optional true} :string] + [:tempdir {:optional true} :string] + [:browser-pool-max {:optional true} ::sm/int] + [:browser-pool-min {:optional true} ::sm/int]]) + +(def ^:private decode-config + (sm/decoder schema:config sm/string-transformer)) + +(def ^:private explain-config + (sm/explainer schema:config)) + +(def ^:private valid-config? + (sm/validator schema:config)) (defn- parse-flags [config] @@ -60,15 +68,15 @@ [] (let [env (read-env "penpot") env (d/without-nils env) - data (merge defaults env)] + data (merge defaults env) + data (decode-config data)] - (try - (sm/conform! schema:config data) - (catch :default cause - (if-let [explain (some->> cause ex-data ::sm/explain)] - (println (sm/humanize-explain explain)) - (js/console.error cause)) - (process/exit -1))))) + (when-not (valid-config? data) + (let [explain (explain-config data)] + (println (sm/humanize-explain explain)) + (process/exit -1))) + + data)) (def config (prepare-config)) diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index a9e62c9650..5e223f69f6 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -217,9 +217,9 @@ [:team-size [:enum "more-than-50" "31-50" "11-30" "2-10" "freelancer" "personal-project"]] [:role - [:enum "designer" "developer" "student-teacher" "graphic-design" "marketing" "manager" "other"]] + [:enum "ux" "developer" "student-teacher" "designer" "marketing" "manager" "other"]] [:responsability - [:enum "team-leader" "team-member" "freelancer" "ceo-founder" "director" "student-teacher" "other"]] + [:enum "team-leader" "team-member" "freelancer" "ceo-founder" "director" "other"]] [:role-other {:optional true} [::sm/text {:max 512}]] [:responsability-other {:optional true} [::sm/text {:max 512}]]] diff --git a/frontend/src/app/main/ui/releases.cljs b/frontend/src/app/main/ui/releases.cljs index 6dd39b14f8..3337e468db 100644 --- a/frontend/src/app/main/ui/releases.cljs +++ b/frontend/src/app/main/ui/releases.cljs @@ -28,6 +28,7 @@ [app.main.ui.releases.v1-9] [app.main.ui.releases.v2-0] [app.main.ui.releases.v2-1] + [app.main.ui.releases.v2-2] [app.util.object :as obj] [app.util.timers :as tm] [rumext.v2 :as mf])) @@ -92,4 +93,4 @@ (defmethod rc/render-release-notes "0.0" [params] - (rc/render-release-notes (assoc params :version "2.1"))) + (rc/render-release-notes (assoc params :version "2.2"))) diff --git a/frontend/src/app/main/ui/releases/v2_2.cljs b/frontend/src/app/main/ui/releases/v2_2.cljs new file mode 100644 index 0000000000..2707f94d37 --- /dev/null +++ b/frontend/src/app/main/ui/releases/v2_2.cljs @@ -0,0 +1,51 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.main.ui.releases.v2-2 + (:require-macros [app.main.style :as stl]) + (:require + [app.common.data.macros :as dm] + [app.main.ui.releases.common :as c] + [rumext.v2 :as mf])) + +(defmethod c/render-release-notes "2.2" + [{:keys [slide klass finish version]}] + (mf/html + (case slide + :start + [:div {:class (stl/css-case :modal-overlay true)} + [:div.animated {:class klass} + [:div {:class (stl/css :modal-container)} + [:img {:src "images/features/2.0-intro-image.png" + :class (stl/css :start-image) + :border "0" + :alt "A graphic illustration with Penpot style"}] + + [:div {:class (stl/css :modal-content)} + [:div {:class (stl/css :modal-header)} + [:h1 {:class (stl/css :modal-title)} + "What's new in Penpot? "] + + [:div {:class (stl/css :version-tag)} + (dm/str "Version " version)]] + + [:div {:class (stl/css :features-block)} + [:p {:class (stl/css :feature-content)} + "This Penpot 2.2 release focuses on internal changes that are laying out the ground for the upcoming plugin system and substantial performance improvements."] + + [:p {:class (stl/css :feature-content)} + "This version also adds full JSON API interoperability and the brand-new Penpot’s Storybook!"] + + [:p {:class (stl/css :feature-content)} + "Self-hosted Penpot installations will benefit from better file data storage and Penpot admins can now use the improved automatic snapshotting process when recovering old files."] + + [:p {:class (stl/css :feature-content)} + "Thanks again to our awesome community for their amazing contributions to this release!"]] + + [:div {:class (stl/css :navigation)} + [:button {:class (stl/css :next-btn) + :on-click finish} "Let's go"]]]]]]))) + diff --git a/frontend/src/app/main/ui/releases/v2_2.scss b/frontend/src/app/main/ui/releases/v2_2.scss new file mode 100644 index 0000000000..dd6adbd8a0 --- /dev/null +++ b/frontend/src/app/main/ui/releases/v2_2.scss @@ -0,0 +1,79 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) KALEIDOS INC + +@import "refactor/common-refactor.scss"; + +.modal-overlay { + @extend .modal-overlay-base; +} + +.modal-container { + display: grid; + grid-template-columns: $s-324 1fr; + height: $s-480; + width: $s-888; + border-radius: $br-8; + background-color: var(--modal-background-color); + border: $s-2 solid var(--modal-border-color); +} + +.start-image { + width: $s-324; + border-radius: $br-8 0 0 $br-8; +} + +.modal-content { + padding: $s-40; + display: grid; + grid-template-rows: auto 1fr $s-32; + gap: $s-24; +} + +.modal-header { + display: grid; + gap: $s-8; +} + +.version-tag { + @include flexCenter; + @include headlineSmallTypography; + height: $s-32; + width: $s-96; + background-color: var(--communication-tag-background-color); + color: var(--communication-tag-foreground-color); + border-radius: $br-8; +} + +.modal-title { + @include headlineLargeTypography; + color: var(--modal-title-foreground-color); +} + +.features-block { + display: flex; + flex-direction: column; + gap: $s-16; + width: $s-440; +} + +.feature-content { + @include bodyMediumTypography; + margin: 0; + color: var(--modal-text-foreground-color); +} + +.navigation { + width: 100%; + display: grid; + grid-template-areas: "bullets button"; +} + +.next-btn { + @extend .button-primary; + width: $s-100; + justify-self: flex-end; + grid-area: button; +} diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss index c4be7026a4..bb4bf23661 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.scss @@ -199,7 +199,6 @@ .height { @extend .input-element; @include bodySmallTypography; - width: $s-108; .icon-text { padding-top: $s-1; } @@ -208,7 +207,6 @@ .margin { @extend .input-element; @include bodySmallTypography; - width: $s-108; .icon { &.rotated svg { transform: rotate(90deg);