0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-28 07:31:25 -05:00

Merge remote-tracking branch 'origin/staging'

This commit is contained in:
Alejandro Alonso 2024-05-07 12:47:17 +02:00
commit bbb64b8be9
9 changed files with 41 additions and 218 deletions

View file

@ -16,6 +16,7 @@
[app.db.sql :as sql]
[app.features.components-v2 :as feat.compv2]
[app.features.fdata :as fdata]
[app.loggers.audit :as audit]
[app.rpc :as-alias rpc]
[app.rpc.commands.files :as files]
[app.rpc.commands.files-create :as files.create]
@ -23,6 +24,7 @@
[app.rpc.commands.projects :as projects]
[app.rpc.commands.teams :as teams]
[app.rpc.doc :as-alias doc]
[app.rpc.helpers :as rph]
[app.util.blob :as blob]
[app.util.pointer-map :as pmap]
[app.util.services :as sv]
@ -100,7 +102,9 @@
:revn revn
:data nil
:changes (blob/encode changes)})
nil)))
(rph/with-meta (rph/wrap nil)
{::audit/replace-props {:file-id id
:revn revn}}))))
;; --- MUTATION COMMAND: persist-temp-file

View file

@ -143,18 +143,12 @@
(map-indexed vector)
(filter #(#{(:id group)} (second %)))
(ffirst)
inc)
;; Shapes that are in a component (including root) must be detached,
;; because cannot be easyly synchronized back to the main component.
shapes-to-detach (filter ctk/in-component-copy?
(cfh/get-children-with-self objects (:id group)))]
inc)]
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
(pcb/change-parent parent-id children index-in-parent)
(pcb/remove-objects [(:id group)])
(pcb/update-shapes (map :id shapes-to-detach) ctk/detach-shape))))
(pcb/remove-objects [(:id group)]))))
(defn remove-frame-changes
[it page-id frame objects]

View file

@ -133,7 +133,10 @@
(defn- fetch-gfont-css
[url]
(->> (http/send! {:method :get :uri url :mode :cors :response-type :text})
(rx/map :body)))
(rx/map :body)
(rx/catch (fn [err]
(.warn js/console "Cannot find the font" (obj/get err "message"))
(rx/empty)))))
(defmethod load-font :google
[{:keys [id ::on-loaded] :as font}]

View file

@ -7,15 +7,11 @@
(ns app.main.ui.dashboard.projects
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.config :as cf]
[app.main.data.dashboard :as dd]
[app.main.data.events :as ev]
[app.main.data.messages :as msg]
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.errors :as errors]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.dashboard.grid :refer [line-grid]]
@ -100,80 +96,6 @@
(def builtin-templates
(l/derived :builtin-templates st/state))
(mf/defc tutorial-project
[{:keys [close-tutorial default-project-id] :as props}]
(let [state (mf/use-state {:status :waiting
:file nil})
templates (mf/deref builtin-templates)
template (d/seek #(= (:id %) "tutorial-for-beginners") templates)
on-template-cloned-success
(mf/use-fn
(mf/deps default-project-id)
(fn [response]
(swap! state #(assoc % :status :success :file (:first response)))
(st/emit! (dd/go-to-workspace {:id (first response) :project-id default-project-id :name "tutorial"})
(du/update-profile-props {:viewed-tutorial? true}))))
on-template-cloned-error
(mf/use-fn
(fn [cause]
(swap! state assoc :status :error)
(errors/print-error! cause)
(st/emit! (msg/error (tr "dashboard.libraries-and-templates.import-error")))))
download-tutorial
(mf/use-fn
(mf/deps template default-project-id)
(fn []
(let [mdata {:on-success on-template-cloned-success
:on-error on-template-cloned-error}
params {:project-id default-project-id
:template-id (:id template)}]
(swap! state #(assoc % :status :importing))
(st/emit! (with-meta (dd/clone-template (with-meta params mdata))
{::ev/origin "get-started-hero-block"})))))]
[:article {:class (stl/css :tutorial)}
[:div {:class (stl/css :thumbnail)}]
[:div {:class (stl/css :text)}
[:h2 {:class (stl/css :title)} (tr "dasboard.tutorial-hero.title")]
[:p {:class (stl/css :info)} (tr "dasboard.tutorial-hero.info")]
[:button {:class (stl/css :btn-primary :action)
:on-click download-tutorial}
(case (:status @state)
:waiting (tr "dasboard.tutorial-hero.start")
:importing [:span.loader i/loader-pencil]
:success "")]]
[:button {:class (stl/css :close)
:on-click close-tutorial
:aria-label (tr "labels.close")}
close-icon]]))
(mf/defc interface-walkthrough
{::mf/wrap [mf/memo]}
[{:keys [close-walkthrough] :as props}]
(let [handle-walkthrough-link
(fn []
(st/emit! (ptk/event ::ev/event {::ev/name "show-walkthrough"
::ev/origin "get-started-hero-block"
:section "dashboard"})))]
[:article {:class (stl/css :walkthrough)}
[:div {:class (stl/css :thumbnail)}]
[:div {:class (stl/css :text)}
[:h2 {:class (stl/css :title)} (tr "dasboard.walkthrough-hero.title")]
[:p {:class (stl/css :info)} (tr "dasboard.walkthrough-hero.info")]
[:a {:class (stl/css :btn-primary :action)
:href " https://design.penpot.app/walkthrough"
:target "_blank"
:on-click handle-walkthrough-link}
(tr "dasboard.walkthrough-hero.start")]]
[:button {:class (stl/css :close)
:on-click close-walkthrough
:aria-label (tr "labels.close")}
close-icon]]))
(mf/defc project-item
[{:keys [project first? team files] :as props}]
(let [locale (mf/deref i18n/locale)
@ -365,7 +287,7 @@
(l/derived :dashboard-recent-files st/state))
(mf/defc projects-section
[{:keys [team projects profile default-project-id] :as props}]
[{:keys [team projects profile] :as props}]
(let [projects (->> (vals projects)
(sort-by :modified-at)
(reverse))
@ -378,8 +300,6 @@
(:team-hero? props true)
(not (:is-default team)))
tutorial-viewed? (:viewed-tutorial? props true)
walkthrough-viewed? (:viewed-walkthrough? props true)
is-my-penpot (= (:default-team-id profile) (:id team))
team-id (:id team)
@ -391,28 +311,6 @@
(ptk/data-event ::ev/event {::ev/name "dont-show-team-up-hero"
::ev/origin "dashboard"}))))
close-tutorial
(mf/use-fn
(fn []
(st/emit! (du/update-profile-props {:viewed-tutorial? true})
(ptk/data-event ::ev/event {::ev/name "dont-show-tutorial"
::ev/origin "get-started-hero"
:type "tutorial"
:section "dashboard"}))))
close-walkthrough
(mf/use-fn
(fn []
(st/emit! (du/update-profile-props {:viewed-walkthrough? true})
(ptk/data-event ::ev/event {::ev/name "dont-show-walkthrough"
::ev/origin "get-started-hero"
:type "walkthrough"
:section "dashboard"}))))
show-hero? (and is-my-penpot
(or (not tutorial-viewed?)
(not walkthrough-viewed?)))
show-team-hero? (and (not is-my-penpot) team-hero?)]
(mf/with-effect [team]
@ -433,22 +331,9 @@
(when team-hero?
[:& team-hero {:team team :close-fn close-banner}])
(when (and (contains? cf/flags :dashboard-templates-section)
show-hero?)
[:div {:class (stl/css :hero-projects)}
(when (and (not tutorial-viewed?) (:is-default team))
[:& tutorial-project
{:close-tutorial close-tutorial
:default-project-id default-project-id}])
(when (and (not walkthrough-viewed?) (:is-default team))
[:& interface-walkthrough
{:close-walkthrough close-walkthrough}])])
[:div {:class (stl/css-case :dashboard-container true
:no-bg true
:dashboard-projects true
:with-hero show-hero?
:with-team-hero show-team-hero?)}
(for [{:keys [id] :as project} projects]
(let [files (when recent-map

View file

@ -20,7 +20,6 @@
height: calc(100vh - $s-64);
}
.with-hero,
.with-team-hero {
height: calc(100vh - $s-280);
}
@ -242,88 +241,3 @@
width: 0;
}
}
.hero-projects {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: $s-32;
margin: 0 $s-16 $s-16 $s-20;
@media (max-width: 1366px) {
grid-template-columns: 1fr;
}
.tutorial,
.walkthrough {
display: grid;
grid-template-columns: auto 1fr;
position: relative;
border-radius: $br-8;
min-height: $s-216;
background-color: $db-tertiary;
padding: $s-8;
.thumbnail {
width: $s-200;
height: $s-200;
border-radius: $br-6;
padding: $s-32;
display: block;
background-color: var(--color-canvas);
}
img {
border-radius: $br-4;
margin-bottom: 0;
width: $s-232;
}
.text {
padding: $s-32;
display: flex;
flex-direction: column;
}
.title {
color: $df-primary;
font-size: $fs-24;
font-weight: $fw400;
margin-bottom: $s-8;
}
.info {
flex: 1;
color: $df-secondary;
margin-bottom: $s-20;
font-size: $fs-16;
}
.invite {
height: $s-32;
}
.action {
width: $s-180;
height: $s-40;
}
}
.walkthrough {
.thumbnail {
background-image: url("/images/walkthrough-cover.png");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
}
.tutorial {
.thumbnail {
background-image: url("/images/hands-on-tutorial.png");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.loader {
display: flex;
svg#loader-pencil {
width: $s-32;
}
}
}
}

View file

@ -122,7 +122,11 @@
(add! :stroke-cap-end)))
(cond-> text?
(-> (add! :grow-type)
(-> (add! :x)
(add! :y)
(add! :width)
(add! :height)
(add! :grow-type)
(add! :content (comp json/encode uuid->string))
(add! :position-data (comp json/encode uuid->string))))

View file

@ -94,6 +94,13 @@
(obj/unset! "disable-shadows?")
(obj/set! "ref" ref)
(obj/set! "id" (dm/fmt "shape-%" shape-id))
;; TODO: This is added for backward compatibility.
(cond-> (and (cfh/text-shape? shape) (empty? (:position-data shape)))
(-> (obj/set! "x" (:x shape))
(obj/set! "y" (:y shape))
(obj/set! "width" (:width shape))
(obj/set! "height" (:height shape))))
(obj/set! "style" styles))
wrapper-props

View file

@ -332,7 +332,7 @@
:title (tr "viewer.header.comments-section" (sc/get-tooltip :open-comments))}
i/comments])
(when (or (= (:type permissions) :membership)
(when (or (:in-team permissions)
(and (= (:type permissions) :share-link)
(= (:who-inspect permissions) "all")))
[:button {:on-click go-to-inspect

View file

@ -272,9 +272,21 @@
(def has-position? #{:frame :rect :image :text})
(defn parse-position
[props svg-data]
(let [values (->> (select-keys svg-data [:x :y :width :height])
(d/mapm (fn [_ val] (d/parse-double val))))]
[props node svg-data]
(let [x (get-meta node :x d/parse-double)
y (get-meta node :y d/parse-double)
width (get-meta node :width d/parse-double)
height (get-meta node :height d/parse-double)
values (->> (select-keys svg-data [:x :y :width :height])
(d/mapm (fn [_ val] (d/parse-double val))))
values
(cond-> values
(some? x) (assoc :x x)
(some? y) (assoc :y y)
(some? width) (assoc :width width)
(some? height) (assoc :height height))]
(d/merge props values)))
(defn parse-circle
@ -392,7 +404,7 @@
center (gpt/point center-x center-y)]
(cond-> props
(has-position? type)
(parse-position svg-data)
(parse-position node svg-data)
(= type :svg-raw)
(add-svg-position node)