🎉 Add new hero projects

This commit is contained in:
Eva 2022-08-11 14:48:15 +02:00 committed by Andrés Moya
parent 61cb43f2f0
commit bf63e9da95
12 changed files with 301 additions and 30 deletions

View file

@ -1,4 +1,8 @@
[{:id "penpot-design-system" [{:id "tutorial-for-beginners"
:name "Tutorial for beginners"
:thumbnail-uri "https://penpot.app/images/libraries/tutorial-for-beginners.jpg"
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/tutorial-for-beginners.penpot"}
{:id "penpot-design-system"
:name "Penpot Design System" :name "Penpot Design System"
:thumbnail-uri "https://penpot.app/images/libraries/cover-ds-penpot.jpg" :thumbnail-uri "https://penpot.app/images/libraries/cover-ds-penpot.jpg"
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Penpot-Design-system.penpot"} :file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Penpot-Design-system.penpot"}

View file

@ -246,6 +246,8 @@
props (-> (audit/extract-utm-params params) props (-> (audit/extract-utm-params params)
(merge (:props params)) (merge (:props params))
(merge {:viewed-tutorial? false
:viewed-walkthrough? false})
(db/tjson)) (db/tjson))
password (if-let [password (:password params)] password (if-let [password (:password params)]

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View file

@ -43,13 +43,9 @@
} }
} }
.invite { .invite {
background-color: $color-primary;
color: $color-black;
width: 180px; width: 180px;
height: 40px; height: 40px;
border: none;
align-self: flex-end; align-self: flex-end;
cursor: pointer;
} }
img { img {
width: 274px; width: 274px;
@ -61,6 +57,112 @@
} }
} }
.hero-projects {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 30px;
margin: 0 1rem 1rem 1.2rem;
.tutorial,
.walkthrough {
display: grid;
grid-template-columns: 1fr 1fr;
position: relative;
border: 2px solid $color-gray-10;
border-radius: 8px;
min-height: 211px;
.img {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
padding: 30px;
display: block;
background-color: #e0e4e9;
}
.text {
padding: 30px;
.title {
color: $color-black;
font-size: $fs24;
font-weight: bold;
margin-bottom: 8px;
}
.info {
color: $color-gray-30;
margin-bottom: 20px;
font-size: $fs16;
}
}
.action {
font-family: "worksans", sans-serif;
width: 180px;
height: 40px;
}
.close {
position: absolute;
top: 0;
right: 0;
width: $size-5;
cursor: pointer;
display: flex;
margin: 20px;
justify-content: center;
align-items: center;
background-color: transparent;
border: none;
.icon {
svg {
fill: $color-gray-30;
height: 16px;
width: 16px;
transform: rotate(45deg);
&:hover {
fill: $color-primary;
}
}
}
}
@media (max-width: 1846px) {
grid-template-columns: 190px 1fr;
}
@media (max-width: 1526px) {
grid-template-columns: 1fr;
.img {
display: none;
width: 0;
}
.text {
.info {
// font-size: $fs12;
}
}
}
}
.walkthrough {
.img {
background-image: url("/images/walkthrough-cover.png");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
}
.tutorial {
.img {
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: 31px;
}
}
}
}
.dashboard-container { .dashboard-container {
background-color: $color-dashboard; background-color: $color-dashboard;
flex: 1 0 0; flex: 1 0 0;
@ -328,8 +430,8 @@
width: 100%; width: 100%;
text-align: right; text-align: right;
height: 56px; height: 56px;
cursor: pointer;
div { div {
cursor: pointer;
height: 58px; height: 58px;
display: inline-block; display: inline-block;
line-height: 58px; line-height: 58px;

View file

@ -296,7 +296,7 @@
(rx/map recent-files-fetched))))))) (rx/map recent-files-fetched)))))))
;; --- EVENT: fetch-team-invitations ;; --- EVENT: fetch-template-files
(defn builtin-templates-fetched (defn builtin-templates-fetched
[libraries] [libraries]

View file

@ -323,7 +323,6 @@
(dcm/close-thread) (dcm/close-thread)
(rt/nav :viewer pparams (assoc qparams :index (inc index))))))))) (rt/nav :viewer pparams (assoc qparams :index (inc index)))))))))
(def select-first-frame (def select-first-frame
(ptk/reify ::select-first-frame (ptk/reify ::select-first-frame
ptk/WatchEvent ptk/WatchEvent

View file

@ -64,7 +64,9 @@
(mf/defc templates-section (mf/defc templates-section
[{:keys [default-project-id profile project team content-width] :as props}] [{:keys [default-project-id profile project team content-width] :as props}]
(let [templates (mf/deref builtin-templates) (let [templates (->> (mf/deref builtin-templates)
(filter #(not= (:id %) "tutorial-for-beginners")))
route (mf/deref refs/route) route (mf/deref refs/route)
route-name (get-in route [:data :name]) route-name (get-in route [:data :name])
section (if (= route-name :dashboard-files) section (if (= route-name :dashboard-files)
@ -141,8 +143,8 @@
:section section})))] :section section})))]
[:div.dashboard-templates-section {:class (when collapsed "collapsed")} [:div.dashboard-templates-section {:class (when collapsed "collapsed")}
[:div.title {:on-click toggle-collapse} [:div.title
[:div [:div {:on-click toggle-collapse}
[:span (tr "dashboard.libraries-and-templates")] [:span (tr "dashboard.libraries-and-templates")]
[:span.icon (if collapsed i/arrow-up i/arrow-down)]]] [:span.icon (if collapsed i/arrow-up i/arrow-down)]]]
[:div.content {:ref content-ref [:div.content {:ref content-ref
@ -192,7 +194,10 @@
(case section (case section
:dashboard-projects :dashboard-projects
[:* [:*
[:& projects-section {:team team :projects projects :profile profile}] [:& projects-section {:team team
:projects projects
:profile profile
:default-project-id default-project-id}]
[:& templates-section {:profile profile [:& templates-section {:profile profile
:project project :project project
:default-project-id default-project-id :default-project-id default-project-id

View file

@ -9,6 +9,7 @@
[app.common.math :as mth] [app.common.math :as mth]
[app.main.data.dashboard :as dd] [app.main.data.dashboard :as dd]
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.data.messages :as dm]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
[app.main.refs :as refs] [app.main.refs :as refs]
@ -51,10 +52,78 @@
[:div.info [:div.info
[:span (tr "dasboard.team-hero.text")] [:span (tr "dasboard.team-hero.text")]
[:a {:on-click go-members} (tr "dasboard.team-hero.management")]]] [:a {:on-click go-members} (tr "dasboard.team-hero.management")]]]
[:button.invite {:on-click invite-member} (tr "onboarding.choice.team-up.invite-members")] [:button.btn-primary.invite {:on-click invite-member} (tr "onboarding.choice.team-up.invite-members")]
[:button.close {:on-click close-banner} [:button.close {:on-click close-banner}
[:span i/close]]])) [:span i/close]]]))
(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})
template (->> (mf/deref builtin-templates)
(filter #(= (:id %) "tutorial-for-beginners"))
first)
on-template-cloned-success
(mf/use-callback
(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
(fn []
(swap! state #(assoc % :status :waiting))
(st/emit!
(dm/error (tr "dashboard.libraries-and-templates.import-error"))))
download-tutorial
(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"}))))]
[:div.tutorial
[:div.img]
[:div.text
[:div.title (tr "dasboard.tutorial-hero.title")]
[:div.info (tr "dasboard.tutorial-hero.info")]
[:button.btn-primary.action {:on-click download-tutorial}
(case (:status @state)
:waiting (tr "dasboard.tutorial-hero.start")
:importing [:span.loader i/loader-pencil]
:success ""
)
]]
[:button.close
{:on-click close-tutorial}
[:span.icon i/close]]]))
(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"})))]
[:div.walkthrough
[:div.img]
[:div.text
[:div.title (tr "dasboard.walkthrough-hero.title")]
[:div.info (tr "dasboard.walkthrough-hero.info")]
[:a.btn-primary.action {:href " https://design.penpot.app/walkthrough" :target "_blank" :on-click handle-walkthrough-link}
(tr "dasboard.walkthrough-hero.start")]]
[:button.close
{:on-click close-walkthrough}
[:span.icon i/close]]]))
(mf/defc project-item (mf/defc project-item
[{:keys [project first? team files] :as props}] [{:keys [project first? team files] :as props}]
(let [locale (mf/deref i18n/locale) (let [locale (mf/deref i18n/locale)
@ -215,19 +284,37 @@
(l/derived :dashboard-recent-files st/state)) (l/derived :dashboard-recent-files st/state))
(mf/defc projects-section (mf/defc projects-section
[{:keys [team projects profile] :as props}] [{:keys [team projects profile default-project-id] :as props}]
(let [projects (->> (vals projects) (let [projects (->> (vals projects)
(sort-by :modified-at) (sort-by :modified-at)
(reverse)) (reverse))
recent-map (mf/deref recent-files-ref) recent-map (mf/deref recent-files-ref)
props (some-> profile (get :props {})) props (some-> profile (get :props {}))
team-hero? (:team-hero? props true) team-hero? (:team-hero? props true)
tutorial-viewed? (:viewed-tutorial? props true)
walkthrough-viewed? (:viewed-walkthrough? props true)
close-banner (fn [] close-banner (fn []
(st/emit! (st/emit!
(du/update-profile-props {:team-hero? false}) (du/update-profile-props {:team-hero? false})
(ptk/event ::ev/event {::ev/name "dont-show-team-up-hero" (ptk/event ::ev/event {::ev/name "dont-show-team-up-hero"
::ev/origin "dashboard"})))] ::ev/origin "dashboard"})))
close-tutorial (fn []
(st/emit!
(du/update-profile-props {:viewed-tutorial? true})
(ptk/event ::ev/event {::ev/name "dont-show"
::ev/origin "get-started-hero-block"
:type "tutorial"
:section "dashboard"})))
close-walkthrough (fn []
(st/emit!
(du/update-profile-props {:viewed-walkthrough? true})
(ptk/event ::ev/event {::ev/name "dont-show"
::ev/origin "get-started-hero-block"
:type "walkthrough"
:section "dashboard"})))]
(mf/use-effect (mf/use-effect
(mf/deps team) (mf/deps team)
@ -247,9 +334,19 @@
[:* [:*
[:& header] [:& header]
(when (and team-hero? (not (:is-default team))) (when (and team-hero? (not (:is-default team)))
[:& team-hero [:& team-hero
{:team team {:team team
:close-banner close-banner}]) :close-banner close-banner}])
(when (or (not tutorial-viewed?) (not walkthrough-viewed?))
[:div.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}])])
[:section.dashboard-container.no-bg [:section.dashboard-container.no-bg
(for [{:keys [id] :as project} projects] (for [{:keys [id] :as project} projects]

View file

@ -202,9 +202,11 @@
(vals) (vals)
(filter cph/text-shape?))) (filter cph/text-shape?)))
zoom (:zoom local) zoom (:zoom local)
frames (:frames page) zoom-type (:zoom-type local)
frame (get frames index)
frames (:frames page)
frame (get frames index)
fullscreen? (mf/deref refs/viewer-fullscreen?) fullscreen? (mf/deref refs/viewer-fullscreen?)
overlays (:overlays local) overlays (:overlays local)
@ -262,7 +264,6 @@
(reset! scroll (dom/get-target-scroll event)))] (reset! scroll (dom/get-target-scroll event)))]
(hooks/use-shortcuts ::viewer sc/shortcuts) (hooks/use-shortcuts ::viewer sc/shortcuts)
(when (nil? page) (when (nil? page)
(ex/raise :type :not-found)) (ex/raise :type :not-found))
@ -313,9 +314,21 @@
(wapi/request-fullscreen wrapper) (wapi/request-fullscreen wrapper)
(wapi/exit-fullscreen)))))) (wapi/exit-fullscreen))))))
(mf/use-layout-effect
(mf/deps page)
(fn []
(case zoom-type
:fit (st/emit! dv/zoom-to-fit)
:fill (st/emit! dv/zoom-to-fill)
nil)))
(mf/use-layout-effect (mf/use-layout-effect
(mf/deps index) (mf/deps index)
(fn [] (fn []
(case zoom-type
:fit (st/emit! dv/zoom-to-fit)
:fill (st/emit! dv/zoom-to-fill)
nil)
;; Navigate animation needs to be started after navigation ;; Navigate animation needs to be started after navigation
;; is complete, and we have the next page index. ;; is complete, and we have the next page index.
(when (and current-animation (when (and current-animation

View file

@ -476,6 +476,30 @@ msgstr "Penpot is meant for teams. Invite members to work together on projects a
msgid "dasboard.team-hero.management" msgid "dasboard.team-hero.management"
msgstr "Team management" msgstr "Team management"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.title"
msgstr "Hands on Tutorial"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.info"
msgstr "Learn the basics at Penpot while having some fun with this hands on tutorial."
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.start"
msgstr "Start the tutorial"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.title"
msgstr "Interface Walkthrough"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.info"
msgstr "Take a walk through Penpot and get to know its main features."
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.start"
msgstr "Start the tour"
#: src/app/main/data/dashboard.cljs #: src/app/main/data/dashboard.cljs
msgid "dashboard.new-file-prefix" msgid "dashboard.new-file-prefix"
msgstr "New File" msgstr "New File"

View file

@ -496,6 +496,31 @@ msgstr " Penpot está dirigido a equipos. Invita a personas para trabajar conjun
msgid "dasboard.team-hero.management" msgid "dasboard.team-hero.management"
msgstr "Gestión del equipo" msgstr "Gestión del equipo"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.title"
msgstr "Tutorial práctico"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.info"
msgstr "Aprende los básicos de Penpot mientras pasas un buen rato con este tutorial práctico."
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.tutorial-hero.start"
msgstr "Comenzar tutorial"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.title"
msgstr "Recorrido por el interfaz"
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.info"
msgstr " Da un paseo por Penpot para conocer sus principales funcionalidades."
#: src/app/main/ui/dashboard/projects.cljs
msgid "dasboard.walkthrough-hero.start"
msgstr "Comenzar"
#: src/app/main/data/dashboard.cljs #: src/app/main/data/dashboard.cljs
msgid "dashboard.new-project-prefix" msgid "dashboard.new-project-prefix"
msgstr "Nuevo Proyecto" msgstr "Nuevo Proyecto"