Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-01-16 00:12:55 +01:00
commit aa33bb1ebf
41 changed files with 219 additions and 127 deletions

View File

@ -357,7 +357,9 @@
f.is_shared,
ft.media_id
from file as f
left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn)
left join file_thumbnail as ft on (ft.file_id = f.id
and ft.revn = f.revn
and ft.deleted_at is null)
where f.project_id = ?
and f.deleted_at is null
order by f.modified_at desc")
@ -660,7 +662,9 @@
row_number() over w as row_num
from file as f
inner join project as p on (p.id = f.project_id)
left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn)
left join file_thumbnail as ft on (ft.file_id = f.id
and ft.revn = f.revn
and ft.deleted_at is null)
where p.team_id = ?
and p.deleted_at is null
and f.deleted_at is null

View File

@ -6,4 +6,4 @@
(ns app.common.files.defaults)
(def version 37)
(def version 38)

View File

@ -671,3 +671,31 @@
(defmethod migrate 37
[data]
(d/without-nils data))
(defmethod migrate 38
[data]
(letfn [(fix-gradient [{:keys [type] :as gradient}]
(if (string? type)
(assoc gradient :type (keyword type))
gradient))
(update-fill [fill]
(d/update-when fill :fill-color-gradient fix-gradient))
(update-object [object]
(d/update-when object :fills #(mapv update-fill %)))
(update-shape [shape]
(let [shape (update-object shape)]
(if (cfh/text-shape? shape)
(-> shape
(update :content (partial txt/transform-nodes identity update-fill))
(d/update-when :position-data #(mapv update-object %)))
shape)))
(update-container [container]
(update container :objects update-vals update-shape))]
(-> data
(update :pages-index update-vals update-container)
(update :components update-vals update-container))))

View File

@ -7,6 +7,7 @@
(ns app.common.geom.shapes.bool
(:require
[app.common.data :as d]
[app.common.files.helpers :as cpf]
[app.common.svg.path.bool :as pb]
[app.common.svg.path.shapes-to-path :as stp]))
@ -16,6 +17,7 @@
(let [extract-content-xf
(comp (map (d/getf objects))
(filter (comp not :hidden))
(remove cpf/svg-raw-shape?)
(map #(stp/convert-to-path % objects))
(map :content))

View File

@ -56,7 +56,7 @@
(sm/define! ::gradient
[:map {:title "Gradient"}
[:type [::sm/one-of #{:linear :radial "linear" "radial"}]]
[:type [::sm/one-of #{:linear :radial}]]
[:start-x ::sm/safe-number]
[:start-y ::sm/safe-number]
[:end-x ::sm/safe-number]

View File

@ -301,6 +301,9 @@
(gpt/add orig-pos delta)
{:skip-components? true
:bottom-frames? true}))
frame (get-shape container frame-id)
component-frame (get-component-shape (:objects container) frame {:allow-main? true})
ids-map (volatile! {})
update-new-shape
@ -339,7 +342,8 @@
:component-root true
:name new-name)
(some? (:parent-id original-shape)) ;; On v2 we have removed the parent-id for component roots (see above)
(or (some? (:parent-id original-shape)) ; On v2 we have removed the parent-id for component roots (see above)
(some? component-frame))
(dissoc :component-root))))
[new-shape new-shapes _]

View File

@ -375,8 +375,8 @@
{:frame-id uuid/zero
:fills [{:fill-color clr/white
:fill-opacity 1}]
:name "Board"
:strokes []
:name "Board"
:shapes []
:hide-fill-on-export false})
@ -390,11 +390,15 @@
(def ^:private minimal-group-attrs
{:type :group
:name "Group"
:fills []
:strokes []
:shapes []})
(def ^:private minimal-bool-attrs
{:type :bool
:name "Bool"
:fills []
:strokes []
:shapes []})
(def ^:private minimal-text-attrs

View File

@ -769,10 +769,6 @@
@include titleTipography;
color: var(--color-foreground-primary);
text-align: left;
display: grid;
grid-template-columns: 1fr 22px;
grid-template-areas: "name button";
width: 100%;
margin: 0;
padding: 0;
height: fit-content;

View File

@ -97,8 +97,7 @@
color: var(--menu-foreground-color);
}
@mixin copyWrapper {
@include flexColumn;
@mixin copyWrapperBase {
position: relative;
min-height: $s-32;
width: $s-156;

View File

@ -944,7 +944,7 @@
(let [shape (get objects id)
parent (get objects parent-id)
component-shape (ctn/get-component-shape objects shape)
component-shape-parent (ctn/get-component-shape objects parent)
component-shape-parent (ctn/get-component-shape objects parent {:allow-main? true})
root-parent (ctn/get-instance-root objects parent)
detach? (and (ctk/in-component-copy-not-head? shape)

View File

@ -827,7 +827,7 @@
0)))))
(defn- add-component-for-swap
[shape file-id id-new-component target-cell]
[shape file-id id-new-component index target-cell]
(dm/assert! (uuid? id-new-component))
(dm/assert! (uuid? file-id))
(ptk/reify ::add-component-for-swap
@ -837,7 +837,6 @@
libraries (wsh/get-libraries state)
objects (:objects page)
index (find-shape-index objects (:parent-id shape) (:id shape))
position (gpt/point (:x shape) (:y shape))
changes (-> (pcb/empty-changes it (:id page))
(pcb/with-objects objects))
@ -877,9 +876,11 @@
;; If the target parent is a grid layout we need to pass the target cell
target-cell (when (ctl/grid-layout? parent)
(ctl/get-cell-by-shape-id parent (:id shape)))]
(ctl/get-cell-by-shape-id parent (:id shape)))
index (find-shape-index objects (:parent-id shape) (:id shape))]
(rx/of (dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true})
(add-component-for-swap shape file-id id-new-component target-cell)
(add-component-for-swap shape file-id id-new-component index target-cell)
(ptk/data-event :layout/update [(:parent-id shape)]))))))
(defn component-multi-swap

View File

@ -210,8 +210,9 @@
(defn search-snap-distance [selrect coord shapes-lt shapes-gt zoom]
(->> (rx/combine-latest shapes-lt shapes-gt)
(rx/map (fn [[shapes-lt shapes-gt]]
(calculate-snap coord selrect shapes-lt shapes-gt zoom)))))
(rx/map
(fn [[shapes-lt shapes-gt]]
(calculate-snap coord selrect shapes-lt shapes-gt zoom)))))
(defn select-shapes-area
[page-id frame-id selected objects area]
@ -233,12 +234,12 @@
(rx/merge-map
(fn [[frame selrect]]
(let [vbox (deref refs/vbox)
frame-id (->> shapes first :frame-id)
frame-sr (when-not (cfh/root? frame) (dm/get-prop frame :selrect))
bounds (d/nilv (grc/clip-rect frame-sr vbox) vbox)
selected (into #{} (map :id shapes))
areas (->> (gsh/get-areas
(or (grc/clip-rect (dm/get-prop frame :selrect) vbox)
vbox)
selrect)
areas (->> (gsh/get-areas bounds selrect)
(d/mapm #(select-shapes-area page-id frame-id selected objects %2)))
snap-x (search-snap-distance selrect :x (:left areas) (:right areas) zoom)
snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas) zoom)]

View File

@ -73,6 +73,9 @@
text-transform: uppercase;
font-size: $fs-11;
}
&.register a {
@extend .button-primary;
}
}
.forgot-password {

View File

@ -275,10 +275,6 @@
(mf/use-fn
#(st/emit! (rt/nav :auth-register {} params)))
on-pass-recovery
(mf/use-fn
#(st/emit! (rt/nav :auth-recovery-request)))
on-create-demo-profile
(mf/use-fn
#(st/emit! (du/create-demo-profile)))]
@ -292,13 +288,6 @@
[:& login-methods {:params params}]
[:div {:class (stl/css :links)}
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:div {:class (stl/css :link-entry :register)}
[:& lk/link {:action on-pass-recovery
:data-test "forgot-password"}
(tr "auth.forgot-password")]])
(when (contains? cf/flags :registration)
[:div {:class (stl/css :link-entry :register)}
[:span (tr "auth.register") " "]

View File

@ -25,7 +25,7 @@
(let [sub (timers/schedule 1000 #(reset! just-copied false))]
;; On unmount we dispose the timer
#(rx/-dispose sub)))))
[:button {:class (dm/str class " " (stl/css-case :copy-button true
[:button {:class (dm/str class " " (stl/css-case :copy-button (not (some? children))
:copy-wrapper (some? children)))
:on-click #(when-not @just-copied
(reset! just-copied true)

View File

@ -10,7 +10,7 @@
@include buttonStyle;
@include flexCenter;
height: $s-32;
width: $s-28;
width: $s-32;
border: $s-1 solid transparent;
border-radius: $br-8;
background-color: transparent;
@ -46,32 +46,50 @@
stroke: var(--button-tertiary-foreground-color-active);
}
}
}
&.copy-wrapper {
@include copyWrapper;
height: fit-content;
text-align: left;
.icon-btn {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
right: 0;
height: 32px;
width: 28px;
svg {
@extend .button-icon-small;
display: none;
}
.copy-wrapper {
@include buttonStyle;
@include copyWrapperBase;
display: grid;
grid-template-columns: 1fr $s-24;
grid-template-areas: "name button";
width: 100%;
height: fit-content;
text-align: left;
.icon-btn {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
right: 0;
height: $s-32;
width: $s-32;
svg {
@extend .button-icon-small;
display: none;
}
&:hover {
.icon-btn {
svg {
display: flex;
stroke: var(--button-tertiary-foreground-color-active);
}
}
&:hover {
.icon-btn {
svg {
display: flex;
stroke: var(--button-tertiary-foreground-color-active);
}
}
}
&:hover {
background-color: var(--color-background-tertiary);
color: var(--color-foreground-primary);
border: $s-1 solid var(--color-background-tertiary);
}
&:focus,
&:focus-visible {
outline: none;
border: $s-1 solid var(--button-tertiary-border-color-focus);
background-color: transparent;
color: var(--button-tertiary-foreground-color-focus);
}
}

View File

@ -87,7 +87,7 @@
(swap! form assoc-in [:touched input-name] true)))
props (-> props
(dissoc :help-icon :form :trim :children :show-success?)
(dissoc :help-icon :form :trim :children :show-success? :auto-focus?)
(assoc :id (name input-name)
:value value
:auto-focus auto-focus?

View File

@ -362,6 +362,7 @@
min-height: $s-32;
border-radius: $br-8;
padding: $s-0 $s-2;
color: var(--input-foreground-color);
&:focus,
&:focus-within {
outline: none;

View File

@ -359,7 +359,7 @@
:background-color (dm/get-in file [:data :options :background])}])
(when (and (:is-shared file) (not library-view?))
[:div {:class (stl/css :item-badge)} i/library])
[:div {:class (stl/css :item-badge)} i/library-refactor])
[:div {:class (stl/css :info-wrapper)}
[:div {:class (stl/css :item-info)}

View File

@ -144,7 +144,8 @@ $thumbnail-default-height: $s-168; // Default width
justify-content: center;
svg {
fill: $db-secondary;
stroke: $db-secondary;
fill: none;
height: $s-16;
width: $s-16;
}

View File

@ -203,7 +203,6 @@
display: flex;
flex-direction: column;
align-items: flex-start;
flex-grow: 1;
padding: $s-20 $s-20;
}
@ -222,7 +221,7 @@
a {
color: $da-primary;
}
padding-top: $s-8;
padding: $s-8 0;
}
.close {
position: absolute;
@ -249,8 +248,11 @@
height: $s-200;
overflow: hidden;
border-radius: $br-4;
@media (max-width: 1200px) {
display: none;
width: 0;
}
}
img {
border-radius: $br-4;
height: $s-200;

View File

@ -14,7 +14,9 @@
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[app.util.router :as rt]
[beicon.v2.core :as rx]
[cljs.spec.alpha :as s]
@ -74,6 +76,15 @@
: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)
handle-keydown
(mf/use-callback
(mf/deps)
(fn [e]
(when (kbd/enter? e)
(dom/prevent-default e)
(dom/stop-propagation e)
(on-submit form e))))
on-close #(st/emit! (modal/hide))]
[:div {:class (stl/css :modal-overlay)}
@ -97,7 +108,8 @@
:form form
:name :name
:placeholder "E.g. Design"
:label (tr "labels.create-team.placeholder")}]]
:label (tr "labels.create-team.placeholder")
:on-key-down handle-keydown}]]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}

View File

@ -126,7 +126,7 @@
}
.selection-title {
@include titleTipography;
color: $df-primary;
color: var(--modal-text-foreground-color);
}
}
.selection-wrapper {

View File

@ -64,6 +64,7 @@
.modal-text {
@include titleTipography;
color: var(--modal-text-foreground-color);
}
.property-block {

View File

@ -114,6 +114,13 @@
(s/keys :req-un [::experience-design-tool]
:opt-un [::experience-design-tool-other]))
(defn- step-1-form-validator
[errors data]
(let [planning (-> (:planning data) (str/trim))]
(cond-> errors
(= planning "")
(assoc :planning {:code "missing"}))))
(defn- step-3-form-validator
[errors data]
(let [experience-design-tool (:experience-design-tool data)
@ -209,6 +216,7 @@
;; and we want to keep the filled info
step-1-form (fm/use-form
:initial {}
:validators [step-1-form-validator]
:spec ::questions-form-step-1)
step-2-form (fm/use-form
:initial {}

View File

@ -15,6 +15,7 @@
}
.viewer-content {
overflow: hidden;
grid-row: 2 / span 1;
display: grid;
grid-template-rows: $s-252 auto;

View File

@ -89,12 +89,13 @@
.color-info,
.color-row-copy-btn {
@include copyWrapper;
display: flex;
max-width: $s-144;
}
.first-row {
display: grid;
grid-template-columns: 1fr $s-20;
grid-template-columns: 1fr $s-24;
grid-template-areas: "name button";
height: fit-content;
width: 100%;

View File

@ -80,7 +80,8 @@
[:div {:class (stl/css :global/attr-label)}
(tr "inspect.attributes.typography")]
[:div {:class (stl/css :global/attr-value)}
[:& copy-button {:data (copy-style-data typography :font-family :font-weight :font-style)}
[:& copy-button {:data (copy-style-data typography :font-family :font-weight :font-style)
:class (stl/css :copy-btn-wrapper)}
[:div {:class (stl/css :button-children)} (:name typography)]]]])
(when (:font-id style)

View File

@ -120,10 +120,10 @@
{:value "1.5" :label "1.5x"}
{:value "2" :label "2x"}
{:value "4" :label "4x"}
{:value "6" :label "6"}]
{:value "6" :label "6x"}]
format-options [{:value "png" :label "PNG"}
{:value "jpeg" :label "JPE"}
{:value "jpeg" :label "JPEG"}
{:value "svg" :label "SVG"}
{:value "pdf" :label "PDF"}]]

View File

@ -46,43 +46,50 @@
@include flexRow;
}
.action-btn {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
svg {
@extend .button-icon;
.element-group {
display: grid;
grid-template-columns: repeat(8, 1fr);
column-gap: $s-4;
.action-btn {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
svg {
@extend .button-icon;
}
}
}
.element-group {
@include flexRow;
}
.input-wrapper {
@include flexRow;
grid-column: span 7;
display: grid;
grid-template-columns: subgrid;
}
.format-select {
width: $s-60;
grid-column: span 2;
padding: 0;
}
.dropdown-upwards {
bottom: $s-36;
width: $s-80;
top: unset;
.dropdown-upwards {
bottom: $s-36;
width: $s-80;
top: unset;
}
}
.size-select {
width: $s-60;
grid-column: span 2;
padding: 0;
.dropdown-upwards {
bottom: $s-36;
top: unset;
width: $s-80;
}
}
.suffix-input {
@extend .input-element;
min-width: $s-92;
flex-grow: 1;
grid-column: span 3;
}
.export-btn {

View File

@ -14,6 +14,7 @@
left: calc(100vw - $s-512);
z-index: $z-index-modal;
}
.share-link-dialog {
@extend .modal-container-base;
min-height: unset;
@ -86,6 +87,7 @@
.description {
@include titleTipography;
color: var(--modal-text-foreground-color);
margin-bottom: $s-24;
}
@ -141,7 +143,7 @@
}
.view-mode {
max-height: $s-248;
max-height: $s-216;
overflow: hidden auto;
scrollbar-gutter: stable;
}

View File

@ -341,8 +341,8 @@
:id "file-menu-text-palette"}
[:span {:class (stl/css :item-name)}
(if (contains? layout :textpalette)
(tr "workspace.header.menu.hide-palette")
(tr "workspace.header.menu.show-palette"))]
(tr "workspace.header.menu.hide-textpalette")
(tr "workspace.header.menu.show-textpalette"))]
[:span {:class (stl/css :shortcut)}
(for [sc (scd/split-sc (sc/get-tooltip :toggle-textpalette))]
[:span {:class (stl/css :shortcut-key) :key sc} sc])]]])

View File

@ -64,7 +64,7 @@
}
.history-entries {
height: 100%;
height: calc(100vh - $s-100);
padding: $s-12;
overflow-x: hidden;
overflow-y: auto;

View File

@ -100,7 +100,7 @@
padding: 0;
}
.back-button-icon {
.back-button {
@include flexCenter;
height: $s-32;
width: $s-24;

View File

@ -162,10 +162,10 @@
{:value "1.5" :label "1.5x"}
{:value "2" :label "2x"}
{:value "4" :label "4x"}
{:value "6" :label "6"}]
{:value "6" :label "6x"}]
format-options [{:value "png" :label "PNG"}
{:value "jpeg" :label "JPE"}
{:value "jpeg" :label "JPEG"}
{:value "svg" :label "SVG"}
{:value "pdf" :label "PDF"}]]

View File

@ -611,7 +611,7 @@
:options animation-opts
:on-change change-animation-type}]]]
;; Direction
;; Direction
(when (ctsi/has-way? interaction)
[:div {:class (stl/css :property-row)}
[:div {:class (stl/css :inputs-wrapper)}
@ -624,7 +624,7 @@
[:& radio-button {:id "animation-way-out"
:value "out"}]]]])
;; Direction
;; Direction
(when (ctsi/has-direction? interaction)
[:div {:class (stl/css :property-row)}
[:div {:class (stl/css :buttons-wrapper)}
@ -648,7 +648,7 @@
:id "animation-up"
:value "up"}]]]])
;; Duration
;; Duration
(when (ctsi/has-duration? interaction)
[:div {:class (stl/css :property-row)}
[:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-duration")]
@ -661,7 +661,7 @@
:value (-> interaction :animation :duration)
:title (tr "workspace.options.interaction-ms")}]]])
;; Easing
;; Easing
(when (ctsi/has-easing? interaction)
[:div {:class (stl/css :property-row)}
[:span {:class (stl/css :interaction-name)} (tr "workspace.options.interaction-easing")]
@ -672,7 +672,7 @@
:options easing-options
:on-change change-easing}]]])
;; Offset effect
;; Offset effect
(when (ctsi/has-offset-effect? interaction)
[:div {:class (stl/css :property-row)}
[:div {:class (stl/css :checkbox-option)}

View File

@ -913,9 +913,10 @@
[:button {:class (stl/css :layout-option) :on-click set-flex} "Flex layout"]
[:button {:class (stl/css :layout-option) :on-click set-grid} "Grid layout"]]]])
[:button {:class (stl/css :remove-layout)
:on-click on-remove-layout}
i/remove-refactor]]
(when has-layout?
[:button {:class (stl/css :remove-layout)
:on-click on-remove-layout}
i/remove-refactor])]
[:div {:class (stl/css :title-actions)}
(if ^boolean grid-enabled?
@ -933,9 +934,10 @@
:data-value "flex"
:on-click on-set-layout}
i/add-refactor])
[:button {:class (stl/css :remove-layout)
:on-click on-remove-layout}
i/remove-refactor]])]]
(when has-layout?
[:button {:class (stl/css :remove-layout)
:on-click on-remove-layout}
i/remove-refactor])])]]
(when (and open? has-layout?)
(when (not= :multiple layout-type)

View File

@ -407,7 +407,7 @@
[:div {:class (stl/css :row)}
[:& align-self-row {:is-col? is-col?
:align-self align-self
:on-changer set-align-self}]])
:on-change set-align-self}]])
(when is-layout-child?
[:div {:class (stl/css :row)}

View File

@ -195,6 +195,7 @@
}
.not-found {
@include titleTipography;
color: var(--empty-message-foreground-color);
margin: $s-12;
}
}

View File

@ -118,7 +118,7 @@
:on-pointer-up on-pointer-up}]])
(mf/defc gradient-handler-transformed
[{:keys [from-p to-p width-p from-color to-color zoom editing
[{:keys [from-p to-p width-p from-color to-color zoom editing transform
on-change-start on-change-finish on-change-width]}]
(let [moving-point (mf/use-var nil)
angle (+ 90 (gpt/angle from-p to-p))
@ -151,7 +151,7 @@
(reset! moving-point nil))]
(mf/use-effect
(mf/deps @moving-point from-p to-p width-p)
(mf/deps @moving-point from-p to-p width-p transform)
(fn []
(let [subs (->> st/stream
(rx/filter mse/pointer-event?)
@ -159,17 +159,18 @@
(rx/map mse/get-pointer-position)
(rx/subs!
(fn [pt]
(case @moving-point
:from-p (when on-change-start (on-change-start pt))
:to-p (when on-change-finish (on-change-finish pt))
:width-p (when on-change-width
(let [width-v (gpt/unit (gpt/to-vec from-p width-p))
distance (gpt/point-line-distance pt from-p to-p)
new-width-p (gpt/add
from-p
(gpt/multiply width-v (gpt/point distance)))]
(on-change-width new-width-p)))
nil))))]
(let [pt (gpt/transform pt transform)]
(case @moving-point
:from-p (when on-change-start (on-change-start pt))
:to-p (when on-change-finish (on-change-finish pt))
:width-p (when on-change-width
(let [width-v (gpt/unit (gpt/to-vec from-p width-p))
distance (gpt/point-line-distance pt from-p to-p)
new-width-p (gpt/add
from-p
(gpt/multiply width-v (gpt/point distance)))]
(on-change-width new-width-p)))
nil)))))]
(fn [] (rx/dispose! subs)))))
[:g.gradient-handlers
[:defs
@ -295,6 +296,7 @@
:width-p (when (= :radial (:type gradient)) width-p)
:from-color {:value start-color :opacity start-opacity}
:to-color {:value end-color :opacity end-opacity}
:transform transform
:zoom zoom
:on-change-start on-change-start
:on-change-finish on-change-finish

View File

@ -8,6 +8,7 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cph]
[app.common.geom.rect :as grc]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
@ -212,9 +213,9 @@
gt-side (if (= coord :x) :right :bottom)
vbox (deref refs/vbox)
areas (gsh/get-areas
(or (grc/clip-rect (dm/get-prop frame :selrect) vbox) vbox)
selrect)
frame-sr (when-not (cph/root? frame) (dm/get-prop frame :selrect))
bounds (d/nilv (grc/clip-rect frame-sr vbox) vbox)
areas (gsh/get-areas bounds selrect)
query-side
(fn [side]