0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-19 11:11:21 -05:00

♻️ Remove new-css-system from modals

This commit is contained in:
Eva 2024-01-03 13:23:06 +01:00
parent 7a3525febc
commit 3f151f16ce
41 changed files with 2359 additions and 4385 deletions

View file

@ -9,7 +9,6 @@
(:require
[app.main.data.modal :as modal]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,8 @@
hint
accept-label
accept-style] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
on-accept (or on-accept identity)
(let [on-accept (or on-accept identity)
message (or message (tr "ds.alert-title"))
accept-label (or accept-label (tr "ds.alert-ok"))
accept-style (or accept-style :danger)
@ -50,54 +49,26 @@
(on-accept props)))]
(->> (events/listen js/document "keydown" on-keydown)
(partial events/unlistenByKey))))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click accept-fn} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click accept-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])]
[:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]
[:div.modal-overlay
[:div.modal-container.alert-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 title]]
[:div.modal-close-button
{:on-click accept-fn} i/close]]
[:div.modal-content
(when (and (string? message) (not= message ""))
[:h3 message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 scd-message])
(when (string? hint)
[:p hint])]
[:div.modal-footer
[:div.action-buttons
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]])))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]))

View file

@ -11,39 +11,45 @@
&.transparent {
background-color: transparent;
}
.modal-container {
@extend .modal-container-base;
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.modal-hint {
@include titleTipography;
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
}
.modal-container {
@extend .modal-container-base;
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.modal-hint {
@include titleTipography;
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}

View file

@ -12,7 +12,6 @@
[app.main.ui.auth.recovery :refer [recovery-page]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-page register-success-page register-validate-page]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -20,102 +19,57 @@
(mf/defc terms-login
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
(let [show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
show-terms? (some? cf/terms-of-service-uri)
show-privacy? (some? cf/privacy-policy-uri)]
(if new-css-system
(when show-all?
[:div {:class (stl/css :terms-login)}
(when show-terms?
[:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
(when show-all?
[:div {:class (stl/css :terms-login)}
(when show-terms?
[:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
(when show-all?
[:span (tr "labels.and")])
(when show-all?
[:span (tr "labels.and")])
(when show-privacy?
[:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])])
(when show-all?
[:div.terms-login
(when show-terms?
[:a {:href cf/terms-of-service-uri :target "_blank"} (tr "auth.terms-of-service")])
(when show-all?
[:span (tr "labels.and")])
(when show-privacy?
[:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])]))))
(when show-privacy?
[:a {:href cf/privacy-policy-uri :target "_blank"} (tr "auth.privacy-policy")])])))
(mf/defc auth
[{:keys [route] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
section (get-in route [:data :name])
(let [section (get-in route [:data :name])
params (:query-params route)
show-illustration? (contains? cf/flags :login-illustration)]
(mf/use-effect
#(dom/set-html-title (tr "title.default")))
(if new-css-system
[:main {:class (stl/css-case :auth-section true
:no-illustration (not show-illustration?))}
(when show-illustration?
[:div {:class (stl/css :login-illustration)}
i/login-illustration])
[:main {:class (stl/css-case :auth-section true
:no-illustration (not show-illustration?))}
(when show-illustration?
[:div {:class (stl/css :login-illustration)}
i/login-illustration])
[:section {:class (stl/css :auth-content)}
[:*
[:a {:href "#/" :class (stl/css :logo-btn)}i/logo]
(case section
:auth-register
[:& register-page {:params params}]
[:section {:class (stl/css :auth-content)}
[:*
[:a {:href "#/" :class (stl/css :logo-btn)} i/logo]
(case section
:auth-register
[:& register-page {:params params}]
:auth-register-validate
[:& register-validate-page {:params params}]
:auth-register-validate
[:& register-validate-page {:params params}]
:auth-register-success
[:& register-success-page {:params params}]
:auth-register-success
[:& register-success-page {:params params}]
:auth-login
[:& login-page {:params params}]
:auth-login
[:& login-page {:params params}]
:auth-recovery-request
[:& recovery-request-page]
:auth-recovery-request
[:& recovery-request-page]
:auth-recovery
[:& recovery-page {:params params}])]
:auth-recovery
[:& recovery-page {:params params}])]
(when (contains? #{:auth-login :auth-register} section)
[:& terms-login])]]
;; OLD
[:main.auth
[:section.auth-sidebar
[:a.logo {:href "#/"}
[:span {:aria-hidden true} i/logo]
[:span.hidden-name "Home"]]
[:span.tagline (tr "auth.sidebar-tagline")]]
[:section.auth-content
(case section
:auth-register
[:& register-page {:params params}]
:auth-register-validate
[:& register-validate-page {:params params}]
:auth-register-success
[:& register-success-page {:params params}]
:auth-login
[:& login-page {:params params}]
:auth-recovery-request
[:& recovery-request-page]
:auth-recovery
[:& recovery-page {:params params}])
[:& terms-login {}]]])))
(when (contains? #{:auth-login :auth-register} section)
[:& terms-login])]]))

View file

@ -18,7 +18,6 @@
[app.main.ui.components.button-link :as bl]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.dom :as dom]
@ -94,8 +93,7 @@
(mf/defc login-form
[{:keys [params on-success-callback origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
initial (mf/use-memo (mf/deps params) (constantly params))
(let [initial (mf/use-memo (mf/deps params) (constantly params))
error (mf/use-state false)
form (fm/use-form :spec ::login-form
:validators [handle-error-messages]
@ -157,156 +155,86 @@
(mf/use-fn
#(st/emit! (rt/nav :auth-recovery-request)))]
(if new-css-system
[:*
(when-let [message @error]
[:& msgs/inline-banner
{:type :warning
:content message
:on-close #(reset! error nil)
:data-test "login-banner"
:role "alert"}])
[:*
(when-let [message @error]
[:& msgs/inline-banner
{:type :warning
:content message
:on-close #(reset! error nil)
:data-test "login-banner"
:role "alert"}])
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input
{:name :email
:type "email"
:label (tr "auth.email")
:class (stl/css :form-field)}]]
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input
{:name :email
:type "email"
:label (tr "auth.email")
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input
{:type "password"
:name :password
:label (tr "auth.password")
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input
{:type "password"
:name :password
:label (tr "auth.password")
:class (stl/css :form-field)}]]
(when (and (not= origin :viewer)
(or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)))
[:div {:class (stl/css :fields-row :forgot-password)}
[:& lk/link {:action on-recovery-request
:data-test "forgot-password"}
(tr "auth.forgot-password")]])
(when (and (not= origin :viewer)
(or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)))
[:div {:class (stl/css :fields-row :forgot-password)}
[:& lk/link {:action on-recovery-request
:data-test "forgot-password"}
(tr "auth.forgot-password")]])
[:div {:class (stl/css :buttons-stack)}
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:> fm/submit-button*
{:label (tr "auth.login-submit")
:data-test "login-submit"
:class (stl/css :login-button)}])
[:div {:class (stl/css :buttons-stack)}
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:> fm/submit-button*
{:label (tr "auth.login-submit")
:data-test "login-submit"
:class (stl/css :login-button)}])
(when (contains? cf/flags :login-with-ldap)
[:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]]
;; OLD
[:*
(when-let [message @error]
[:& msgs/inline-banner
{:type :warning
:content message
:on-close #(reset! error nil)
:data-test "login-banner"
:role "alert"}])
[:& fm/form {:on-submit on-submit :form form}
[:div.fields-row
[:& fm/input
{:name :email
:type "email"
:help-icon i/at
:label (tr "auth.email")
:class (stl/css :form-field)}]]
[:div.fields-row
[:& fm/input
{:type "password"
:name :password
:help-icon i/eye
:label (tr "auth.password")
:class (stl/css :form-field)}]]
[:div.buttons-stack
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:> fm/submit-button*
{:label (tr "auth.login-submit")
:data-test "login-submit"}])
(when (contains? cf/flags :login-with-ldap)
[:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]])))
(when (contains? cf/flags :login-with-ldap)
[:> fm/submit-button*
{:label (tr "auth.login-with-ldap-submit")
:on-click on-submit-ldap}])]]]))
(mf/defc login-buttons
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
(let [login-with-google (mf/use-fn (mf/deps params) #(login-with-oidc % :google params))
login-with-github (mf/use-fn (mf/deps params) #(login-with-oidc % :github params))
login-with-gitlab (mf/use-fn (mf/deps params) #(login-with-oidc % :gitlab params))
login-with-oidc (mf/use-fn (mf/deps params) #(login-with-oidc % :oidc params))]
(if new-css-system
[:div {:class (stl/css :auth-buttons)}
(when (contains? cf/flags :login-with-google)
[:& bl/button-link {:on-click login-with-google
:icon i/brand-google
:label (tr "auth.login-with-google-submit")
:class (stl/css :login-btn :btn-google-auth)}])
[:div {:class (stl/css :auth-buttons)}
(when (contains? cf/flags :login-with-google)
[:& bl/button-link {:on-click login-with-google
:icon i/brand-google
:label (tr "auth.login-with-google-submit")
:class (stl/css :login-btn :btn-google-auth)}])
(when (contains? cf/flags :login-with-github)
[:& bl/button-link {:on-click login-with-github
:icon i/brand-github
:label (tr "auth.login-with-github-submit")
:class (stl/css :login-btn :btn-github-auth)}])
(when (contains? cf/flags :login-with-github)
[:& bl/button-link {:on-click login-with-github
:icon i/brand-github
:label (tr "auth.login-with-github-submit")
:class (stl/css :login-btn :btn-github-auth)}])
(when (contains? cf/flags :login-with-gitlab)
[:& bl/button-link {:on-click login-with-gitlab
:icon i/brand-gitlab
:label (tr "auth.login-with-gitlab-submit")
:class (stl/css :login-btn :btn-gitlab-auth)}])
(when (contains? cf/flags :login-with-gitlab)
[:& bl/button-link {:on-click login-with-gitlab
:icon i/brand-gitlab
:label (tr "auth.login-with-gitlab-submit")
:class (stl/css :login-btn :btn-gitlab-auth)}])
(when (contains? cf/flags :login-with-oidc)
[:& bl/button-link {:on-click login-with-oidc
:icon i/brand-openid
:label (tr "auth.login-with-oidc-submit")
:class (stl/css :login-btn :btn-oidc-auth)}])]
[:div.auth-buttons
(when (contains? cf/flags :login-with-google)
[:& bl/button-link {:on-click login-with-google
:icon i/brand-google
:label (tr "auth.login-with-google-submit")
:class "btn-google-auth"}])
(when (contains? cf/flags :login-with-github)
[:& bl/button-link {:on-click login-with-github
:icon i/brand-github
:label (tr "auth.login-with-github-submit")
:class "btn-github-auth"}])
(when (contains? cf/flags :login-with-gitlab)
[:& bl/button-link {:on-click login-with-gitlab
:icon i/brand-gitlab
:label (tr "auth.login-with-gitlab-submit")
:class "btn-gitlab-auth"}])
(when (contains? cf/flags :login-with-oidc)
[:& bl/button-link {:on-click login-with-oidc
:icon i/brand-openid
:label (tr "auth.login-with-oidc-submit")
:class "btn-github-auth"}])])))
(when (contains? cf/flags :login-with-oidc)
[:& bl/button-link {:on-click login-with-oidc
:icon i/brand-openid
:label (tr "auth.login-with-oidc-submit")
:class (stl/css :login-btn :btn-oidc-auth)}])]))
(mf/defc login-button-oidc
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
login-oidc
(let [login-oidc
(mf/use-fn
(mf/deps params)
(fn [event]
@ -317,69 +245,33 @@
(fn [event]
(when (k/enter? event)
(login-oidc event))))]
(if new-css-system
(when (contains? cf/flags :login-with-oidc)
[:div {:class (stl/css :link-entry :link-oidc)}
[:a {:tab-index "0"
:on-key-down handle-key-down
:on-click login-oidc}
(tr "auth.login-with-oidc-submit")]])
;; OLD
(when (contains? cf/flags :login-with-oidc)
[:div.link-entry.link-oidc
[:a {:tab-index "0"
:on-key-down handle-key-down
:on-click login-oidc}
(tr "auth.login-with-oidc-submit")]]))))
(when (contains? cf/flags :login-with-oidc)
[:div {:class (stl/css :link-entry :link-oidc)}
[:a {:tab-index "0"
:on-key-down handle-key-down
:on-click login-oidc}
(tr "auth.login-with-oidc-submit")]])))
(mf/defc login-methods
[{:keys [params on-success-callback origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:*
(when show-alt-login-buttons?
[:*
[:& login-buttons {:params params}]
[:*
(when show-alt-login-buttons?
[:*
[:& login-buttons {:params params}]
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:hr {:class (stl/css :separator)}])])
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:hr {:class (stl/css :separator)}])])
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:& login-form {:params params :on-success-callback on-success-callback :origin origin}])]
;; OLD
[:*
(when show-alt-login-buttons?
[:*
[:span.separator
[:span.line]
[:span.text (tr "labels.continue-with")]
[:span.line]]
[:& login-buttons {:params params}]
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:span.separator
[:span.line]
[:span.text (tr "labels.or")]
[:span.line]])])
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:& login-form {:params params :on-success-callback on-success-callback}])])))
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)
(contains? cf/flags :login-with-ldap))
[:& login-form {:params params :on-success-callback on-success-callback :origin origin}])])
(mf/defc login-page
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
go-register
(let [go-register
(mf/use-fn
#(st/emit! (rt/nav :auth-register {} params)))
@ -391,64 +283,33 @@
(mf/use-fn
#(st/emit! (du/create-demo-profile)))]
(if new-css-system
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "login-title"} (tr "auth.login-title")]
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "login-title"} (tr "auth.login-title")]
[:hr {:class (stl/css :separator)}]
[:hr {:class (stl/css :separator)}]
[:& login-methods {:params params}]
[:& 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")]])
[: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") " "]
[:& lk/link {:action go-register
:data-test "register-submit"}
(tr "auth.register-submit")]])]
(when (contains? cf/flags :registration)
[:div {:class (stl/css :link-entry :register)}
[:span (tr "auth.register") " "]
[:& lk/link {:action go-register
:data-test "register-submit"}
(tr "auth.register-submit")]])]
(when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-account)}
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action on-create-demo-profile
:data-test "demo-account-link"}
(tr "auth.create-demo-account")]])]
;; OLD
[:div.generic-form.login-form
[:div.form-container
[:h1 {:data-test "login-title"} (tr "auth.login-title")]
[:& login-methods {:params params}]
[:div.links
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password))
[:div.link-entry
[:& lk/link {:action on-pass-recovery
:data-test "forgot-password"}
(tr "auth.forgot-password")]])
(when (contains? cf/flags :registration)
[:div.link-entry
[:span (tr "auth.register") " "]
[:& lk/link {:action go-register
:data-test "register-submit"}
(tr "auth.register-submit")]])]
(when (contains? cf/flags :demo-users)
[:div.links.demo
[:div.link-entry
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action on-create-demo-profile
:data-test "demo-account-link"}
(tr "auth.create-demo-account")]]])]])))
(when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-account)}
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action on-create-demo-profile
:data-test "demo-account-link"}
(tr "auth.create-demo-account")]])]))

View file

@ -14,8 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[beicon.v2.core :as rx]
@ -34,8 +32,7 @@
(mf/defc recovery-form
[{:keys [on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
form (fm/use-form :spec ::recovery-request-form
(let [form (fm/use-form :spec ::recovery-request-form
:validators [handle-error-messages]
:initial {})
submitted (mf/use-state false)
@ -77,62 +74,34 @@
(reset! form nil)
(st/emit! (du/request-profile-recovery params)))))]
(if new-css-system
[:& fm/form {:on-submit on-submit
:form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :email
:label (tr "auth.email")
:type "text"
:class (stl/css :form-field)}]]
[:& fm/form {:on-submit on-submit
:form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :email
:label (tr "auth.email")
:type "text"
:class (stl/css :form-field)}]]
[:> fm/submit-button*
{:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit"
:class (stl/css :recover-btn)}]]
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:name :email
:label (tr "auth.email")
:help-icon i/at
:type "text"}]]
[:> fm/submit-button*
{:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit"}]])))
[:> fm/submit-button*
{:label (tr "auth.recovery-request-submit")
:data-test "recovery-resquest-submit"
:class (stl/css :recover-btn)}]]))
;; --- Recovery Request Page
(mf/defc recovery-request-page
[{:keys [params on-success-callback go-back-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
default-go-back #(st/emit! (rt/nav :auth-login))
(let [default-go-back #(st/emit! (rt/nav :auth-login))
go-back (or go-back-callback default-go-back)]
(if new-css-system
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")]
[:hr {:class (stl/css :separator)}]
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)} (tr "auth.recovery-request-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.recovery-request-subtitle")]
[:hr {:class (stl/css :separator)}]
[:& recovery-form {:params params :on-success-callback on-success-callback}]
[:& recovery-form {:params params :on-success-callback on-success-callback}]
[:div {:class (stl/css :link-entry)}
[:& lk/link {:action go-back
:data-test "go-back-link"}
(tr "labels.go-back")]]]
;; old
[:section.generic-form
[:div.form-container
[:h1 (tr "auth.recovery-request-title")]
[:div.subtitle (tr "auth.recovery-request-subtitle")]
[:& recovery-form {:params params :on-success-callback on-success-callback}]
[:div.links
[:div.link-entry
[:& lk/link {:action go-back
:data-test "go-back-link"}
(tr "labels.go-back")]]]]])))
[:div {:class (stl/css :link-entry)}
[:& lk/link {:action go-back
:data-test "go-back-link"}
(tr "labels.go-back")]]]))

View file

@ -17,7 +17,6 @@
[app.main.ui.auth.login :as login]
[app.main.ui.components.forms :as fm]
[app.main.ui.components.link :as lk]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :refer [tr tr-html]]
@ -88,8 +87,7 @@
(mf/defc register-form
[{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
initial (mf/use-memo (mf/deps params) (constantly params))
(let [initial (mf/use-memo (mf/deps params) (constantly params))
form (fm/use-form :spec ::register-form
:validators [validate
(fm/validate-not-empty :password (tr "auth.password-not-empty"))]
@ -114,133 +112,64 @@
(partial handle-prepare-register-error form))))))]
(if new-css-system
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email
:label (tr "auth.email")
:data-test "email-input"
:show-success? true
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :password
:hint (tr "auth.password-length-hint")
:label (tr "auth.password")
:show-success? true
:type "password"
:class (stl/css :form-field)}]]
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email
:label (tr "auth.email")
:data-test "email-input"
:show-success? true
:class (stl/css :form-field)}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :password
:hint (tr "auth.password-length-hint")
:label (tr "auth.password")
:show-success? true
:type "password"
:class (stl/css :form-field)}]]
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:data-test "register-form-submit"
:class (stl/css :register-btn)}]]
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:type "email"
:name :email
:help-icon i/at
:label (tr "auth.email")
:data-test "email-input"}]]
[:div.fields-row
[:& fm/input {:name :password
:hint (tr "auth.password-length-hint")
:label (tr "auth.password")
:type "password"}]]
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:data-test "register-form-submit"}]])))
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:data-test "register-form-submit"
:class (stl/css :register-btn)}]]))
(mf/defc register-methods
[{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:*
(when login/show-alt-login-buttons?
[:*
[:hr {:class (stl/css :separator)}]
[:& login/login-buttons {:params params}]])
[:hr {:class (stl/css :separator)}]
[:& register-form {:params params :on-success-callback on-success-callback}]]
;; OLD
[:*
(when login/show-alt-login-buttons?
[:*
[:span.separator
[:span.line]
[:span.text (tr "labels.continue-with")]
[:span.line]]
[:& login/login-buttons {:params params}]
(when (or (contains? cf/flags :login)
(contains? cf/flags :login-with-ldap))
[:span.separator
[:span.line]
[:span.text (tr "labels.or")]
[:span.line]])])
[:& register-form {:params params :on-success-callback on-success-callback}]])))
[:*
(when login/show-alt-login-buttons?
[:*
[:hr {:class (stl/css :separator)}]
[:& login/login-buttons {:params params}]])
[:hr {:class (stl/css :separator)}]
[:& register-form {:params params :on-success-callback on-success-callback}]])
(mf/defc register-page
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "registration-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "registration-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
(when (contains? cf/flags :demo-warning)
[:& demo-warning])
(when (contains? cf/flags :demo-warning)
[:& demo-warning])
[:& register-methods {:params params}]
[:& register-methods {:params params}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :account)}
[:span (tr "auth.already-have-account") " "]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :account)}
[:span (tr "auth.already-have-account") " "]
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
:data-test "login-here-link"}
(tr "auth.login-here")]]
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
:data-test "login-here-link"}
(tr "auth.login-here")]]
(when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-users)}
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action #(st/emit! (du/create-demo-profile))}
(tr "auth.create-demo-account")]])]]
;; OLD
[:div.form-container
[:h1 {:data-test "registration-title"} (tr "auth.register-title")]
[:div.subtitle (tr "auth.register-subtitle")]
(when (contains? cf/flags :demo-warning)
[:& demo-warning])
[:& register-methods {:params params}]
[:div.links
[:div.link-entry
[:span (tr "auth.already-have-account") " "]
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
:data-test "login-here-link"}
(tr "auth.login-here")]]
(when (contains? cf/flags :demo-users)
[:div.link-entry
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action #(st/emit! (du/create-demo-profile))}
(tr "auth.create-demo-account")]])]])))
(when (contains? cf/flags :demo-users)
[:div {:class (stl/css :link-entry :demo-users)}
[:span (tr "auth.create-demo-profile") " "]
[:& lk/link {:action #(st/emit! (du/create-demo-profile))}
(tr "auth.create-demo-account")]])]])
;; --- PAGE: register validation
@ -284,8 +213,7 @@
(mf/defc register-validate-form
[{:keys [params on-success-callback] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
form (fm/use-form :spec ::register-validate-form
(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)
@ -306,103 +234,55 @@
(rx/subs! on-success
(partial handle-register-error form))))))]
(if new-css-system
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :fullname
:label (tr "auth.fullname")
:type "text"
:show-success? true
:class (stl/css :form-field)}]]
[:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :fullname
:label (tr "auth.fullname")
:type "text"
:show-success? true
:class (stl/css :form-field)}]]
(when (contains? cf/flags :terms-and-privacy-checkbox)
(let [terms-label
(mf/html
[:& tr-html
{:tag-name "div"
:label "auth.terms-privacy-agreement-md"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class "check-primary"
:type "checkbox"
:label terms-label}]]))
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:class (stl/css :register-btn)}]]
;; OLD
[:& fm/form {:on-submit on-submit
:form form}
[:div.fields-row
[:& fm/input {:name :fullname
:label (tr "auth.fullname")
:type "text"}]]
(when (contains? cf/flags :terms-and-privacy-checkbox)
[:div.fields-row.input-visible.accept-terms-and-privacy-wrapper
(when (contains? cf/flags :terms-and-privacy-checkbox)
(let [terms-label
(mf/html
[:& tr-html
{:tag-name "div"
:label "auth.terms-privacy-agreement-md"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class "check-primary"
:type "checkbox"}
[:span
(tr "auth.terms-privacy-agreement")]]
[:div.auth-links
[:a {:href "https://penpot.app/terms" :target "_blank"} (tr "auth.terms-of-service")]
[:span ",\u00A0"]
[:a {:href "https://penpot.app/privacy" :target "_blank"} (tr "auth.privacy-policy")]]])
:type "checkbox"
:label terms-label}]]))
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?}]])))
[:> fm/submit-button*
{:label (tr "auth.register-submit")
:disabled @submitted?
:class (stl/css :register-btn)}]]))
(mf/defc register-validate-page
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "register-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
[:div {:class (stl/css :auth-form)}
[:h1 {:class (stl/css :auth-title)
:data-test "register-title"} (tr "auth.register-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-subtitle")]
[:hr {:class (stl/css :separator)}]
[:hr {:class (stl/css :separator)}]
[:& register-validate-form {:params params}]
[:& register-validate-form {:params params}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :go-back)}
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
(tr "labels.go-back")]]]]
;; OLD
[:div.form-container
[:h1 {:data-test "register-title"} (tr "auth.register-title")]
[:div.subtitle (tr "auth.register-subtitle")]
[:& register-validate-form {:params params}]
[:div.links
[:div.link-entry
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
(tr "labels.go-back")]]]])))
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry :go-back)}
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))}
(tr "labels.go-back")]]]])
(mf/defc register-success-page
[{:keys [params] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :auth-form :register-success)}
[:div {:class (stl/css :notification-icon)} i/icon-verify]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
[:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]]
;; OLD
[:div.form-container
[:div.notification-icon i/icon-verify]
[:div.notification-text (tr "auth.verification-email-sent")]
[:div.notification-text-email (:email params "")]
[:div.notification-text (tr "auth.check-your-email")]])))
[:div {:class (stl/css :auth-form :register-success)}
[:div {:class (stl/css :notification-icon)} i/icon-verify]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]
[:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])

View file

@ -18,7 +18,6 @@
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -81,20 +80,18 @@
(set! (.-height (.-style node)) "0")
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px")))))
[:textarea
{:ref local-ref
:auto-focus autofocus?
:on-key-down on-key-down
:on-focus on-focus*
:on-blur on-blur
:value value
:placeholder placeholder
:on-change on-change*}]))
[:textarea {:ref local-ref
:auto-focus autofocus?
:on-key-down on-key-down
:on-focus on-focus*
:on-blur on-blur
:value value
:placeholder placeholder
:on-change on-change*}]))
(mf/defc reply-form
[{:keys [thread] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
show-buttons? (mf/use-state false)
(let [show-buttons? (mf/use-state false)
content (mf/use-state "")
disabled? (or (fm/all-spaces? @content)
@ -123,54 +120,32 @@
(fn []
(st/emit! (dcm/add-comment thread @content))
(on-cancel)))]
(if new-css-system
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:value @content
:placeholder "Reply"
:on-blur on-blur
:on-focus on-focus
:select-on-focus? false
:on-ctrl-enter on-submit
:on-change on-change}]
(when (or @show-buttons? (seq @content))
[:div {:class (stl/css :buttons-wrapper)}
[:input.btn-secondary
{:type "button"
:class (stl/css :cancel-btn)
:value "Cancel"
:on-click on-cancel}]
[:input
{:type "button"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:value "Post"
:on-click on-submit
:disabled disabled?}]])]
[:div.reply-form
[:& resizing-textarea {:value @content
:placeholder "Reply"
:on-blur on-blur
:on-focus on-focus
:on-ctrl-enter on-submit
:on-change on-change}]
(when (or @show-buttons? (seq @content))
[:div.buttons
[:input.btn-primary
{:type "button"
:value "Post"
:on-click on-submit
:disabled disabled?}]
[:input.btn-secondary
{:type "button"
:value "Cancel"
:on-click on-cancel}]])])))
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:value @content
:placeholder "Reply"
:on-blur on-blur
:on-focus on-focus
:select-on-focus? false
:on-ctrl-enter on-submit
:on-change on-change}]
(when (or @show-buttons? (seq @content))
[:div {:class (stl/css :buttons-wrapper)}
[:input.btn-secondary
{:type "button"
:class (stl/css :cancel-btn)
:value "Cancel"
:on-click on-cancel}]
[:input
{:type "button"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:value "Post"
:on-click on-submit
:disabled disabled?}]])]))
(mf/defc draft-thread
[{:keys [draft zoom on-cancel on-submit position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
position (cond-> (:position draft)
(let [position (cond-> (:position draft)
(some? position-modifier)
(gpt/transform position-modifier))
content (:content draft)
@ -201,73 +176,42 @@
(mf/deps draft)
(partial on-submit draft))]
[:*
[:div
{:class (stl/css :floating-thread-bubble)
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
"?"]
[:div {:class (stl/css :thread-content)
:style {:top (str (- pos-y 24) "px")
:left (str (+ pos-x 28) "px")}
:on-click dom/stop-propagation}
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:select-on-focus? false
:on-esc on-esc
:on-change on-change
:on-ctrl-enter on-submit}]
[:div {:class (stl/css :buttons-wrapper)}
(if new-css-system
[:*
[:div
{:class (stl/css :floating-thread-bubble)
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
"?"]
[:div {:class (stl/css :thread-content)
:style {:top (str (- pos-y 24) "px")
:left (str (+ pos-x 28) "px")}
:on-click dom/stop-propagation}
[:div {:class (stl/css :reply-form)}
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:select-on-focus? false
:on-esc on-esc
:on-change on-change
:on-ctrl-enter on-submit}]
[:div {:class (stl/css :buttons-wrapper)}
[:input {:on-click on-esc
:class (stl/css :cancel-btn)
:type "button"
:value "Cancel"}]
[:input {:on-click on-esc
:class (stl/css :cancel-btn)
:type "button"
:value "Cancel"}]
[:input {:on-click on-submit
:type "button"
:value "Post"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:disabled disabled?}]]]]]
[:*
[:div.thread-bubble
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
[:span "?"]]
[:div.thread-content
{:style {:top (str (- pos-y 14) "px")
:left (str (+ pos-x 14) "px")}
:on-click dom/stop-propagation}
[:div.reply-form
[:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:autofocus true
:on-esc on-esc
:on-ctrl-enter on-submit
:on-change on-change}]
[:div.buttons
[:input.btn-primary
{:on-click on-submit
:type "button"
:value "Post"
:disabled disabled?}]
[:input.btn-secondary
{:on-click on-esc
:type "button"
:value "Cancel"}]]]]])))
[:input {:on-click on-submit
:type "button"
:value "Post"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:disabled disabled?}]]]]]))
(mf/defc edit-form
[{:keys [content on-submit on-cancel] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
content (mf/use-state content)
(let [content (mf/use-state content)
on-change
(mf/use-fn
@ -281,44 +225,28 @@
disabled? (or (fm/all-spaces? @content)
(str/empty-or-nil? @content))]
(if new-css-system
[:div {:class (stl/css :edit-form)}
[:& resizing-textarea {:value @content
:autofocus true
:select-on-focus true
:select-on-focus? false
:on-ctrl-enter on-submit*
:on-change on-change}]
[:div {:class (stl/css :buttons-wrapper)}
[:input {:type "button"
:value "Cancel"
:class (stl/css :cancel-btn)
:on-click on-cancel}]
[:input {:type "button"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:value "Post"
:on-click on-submit*
:disabled disabled?}]]]
[:div.reply-form.edit-form
[:& resizing-textarea {:value @content
:autofocus true
:select-on-focus true
:on-ctrl-enter on-submit*
:on-change on-change}]
[:div.buttons
[:input.btn-primary {:type "button"
:value "Post"
:on-click on-submit*
:disabled disabled?}]
[:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]]])))
[:div {:class (stl/css :edit-form)}
[:& resizing-textarea {:value @content
:autofocus true
:select-on-focus true
:select-on-focus? false
:on-ctrl-enter on-submit*
:on-change on-change}]
[:div {:class (stl/css :buttons-wrapper)}
[:input {:type "button"
:value "Cancel"
:class (stl/css :cancel-btn)
:on-click on-cancel}]
[:input {:type "button"
:class (stl/css-case :post-btn true
:global/disabled disabled?)
:value "Post"
:on-click on-submit*
:disabled disabled?}]]]))
(mf/defc comment-item
[{:keys [comment thread users origin] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
owner (get users (:owner-id comment))
(let [owner (get users (:owner-id comment))
profile (mf/deref refs/profile)
options (mf/use-state false)
edition? (mf/use-state false)
@ -382,82 +310,46 @@
(dom/stop-propagation event)
(st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))]
(if new-css-system
[:div {:class (stl/css :comment-container)}
[:div {:class (stl/css :comment)}
[:div {:class (stl/css :author)}
[:div {:class (stl/css :avatar)}
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div {:class (stl/css :name)}
[:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
[:div {:class (stl/css :comment-container)}
[:div {:class (stl/css :comment)}
[:div {:class (stl/css :author)}
[:div {:class (stl/css :avatar)}
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div {:class (stl/css :name)}
[:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]]
(when (some? thread)
[:div {:class (stl/css :options-resolve-wrapper)
:on-click toggle-resolved}
[:span {:class (stl/css-case :options-resolve true
:global/checked (:is-resolved thread))} i/tick-refactor]])
(when (some? thread)
[:div {:class (stl/css :options-resolve-wrapper)
:on-click toggle-resolved}
[:span {:class (stl/css-case :options-resolve true
:global/checked (:is-resolved thread))} i/tick-refactor]])
(when (= (:id profile) (:id owner))
[:div {:class (stl/css :options)
:on-click on-toggle-options}
i/menu-refactor])]
(when (= (:id profile) (:id owner))
[:div {:class (stl/css :options)
:on-click on-toggle-options}
i/menu-refactor])]
[:div {:class (stl/css :content)}
(if @edition?
[:& edit-form {:content (:content comment)
:on-submit on-submit
:on-cancel on-cancel}]
[:span {:class (stl/css :text)} (:content comment)])]]
[:div {:class (stl/css :content)}
(if @edition?
[:& edit-form {:content (:content comment)
:on-submit on-submit
:on-cancel on-cancel}]
[:span {:class (stl/css :text)} (:content comment)])]]
[:& dropdown {:show @options
:on-close on-hide-options}
[:ul {:class (stl/css :comment-options-dropdown)}
[:& dropdown {:show @options
:on-close on-hide-options}
[:ul {:class (stl/css :comment-options-dropdown)}
[:li {:class (stl/css :context-menu-option)
:on-click on-edit-clicked}
(tr "labels.edit")]
(if thread
[:li {:class (stl/css :context-menu-option)
:on-click on-edit-clicked}
(tr "labels.edit")]
(if thread
[:li {:class (stl/css :context-menu-option)
:on-click on-delete-thread}
(tr "labels.delete-comment-thread")]
[:li {:class (stl/css :context-menu-option)
:on-click on-delete-comment}
(tr "labels.delete-comment")])]]]
[:div.comment-container
[:div.comment
[:div.author
[:div.avatar
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div.name
[:div.fullname (:fullname owner)]
[:div.timeago (dt/timeago (:modified-at comment))]]
(when (some? thread)
[:div.options-resolve {:on-click toggle-resolved}
(if (:is-resolved thread)
[:span i/checkbox-checked]
[:span i/checkbox-unchecked])])
(when (= (:id profile) (:id owner))
[:div.options
[:div.options-icon {:on-click on-toggle-options} i/actions]])]
[:div.content
(if @edition?
[:& edit-form {:content (:content comment)
:on-submit on-submit
:on-cancel on-cancel}]
[:span.text (:content comment)])]]
[:& dropdown {:show @options
:on-close on-hide-options}
[:ul.dropdown.comment-options-dropdown
[:li {:on-click on-edit-clicked} (tr "labels.edit")]
(if thread
[:li {:on-click on-delete-thread} (tr "labels.delete-comment-thread")]
[:li {:on-click on-delete-comment} (tr "labels.delete-comment")])]]])))
:on-click on-delete-thread}
(tr "labels.delete-comment-thread")]
[:li {:class (stl/css :context-menu-option)
:on-click on-delete-comment}
(tr "labels.delete-comment")])]]]))
(defn make-comments-ref
[thread-id]
@ -466,8 +358,7 @@
(mf/defc thread-comments
{::mf/wrap [mf/memo]}
[{:keys [thread zoom users origin position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
ref (mf/use-ref)
(let [ref (mf/use-ref)
thread-id (:id thread)
@ -477,12 +368,8 @@
(some? position-modifier)
(gpt/transform position-modifier))
pos-x (if new-css-system
(+ (* (:x pos) zoom) 24)
(+ (* (:x pos) zoom) 14))
pos-y (if new-css-system
(- (* (:y pos) zoom) 28)
(- (* (:y pos) zoom) 14))
pos-x (+ (* (:x pos) zoom) 24)
pos-y (- (* (:y pos) zoom) 28)
comments-ref (mf/with-memo [thread-id]
@ -504,46 +391,24 @@
(mf/with-layout-effect [thread-pos comments-map]
(when-let [node (mf/ref-val ref)]
(dom/scroll-into-view-if-needed! node)))
(if new-css-system
(when (some? comment)
[:div {:class (stl/css :thread-content)
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
(when (some? comment)
[:div {:class (stl/css :thread-content)
:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
[:div {:class (stl/css :comments)}
[:& comment-item {:comment comment
:users users
:thread thread
:origin origin}]
(for [item (rest comments)]
[:* {:key (dm/str (:id item))}
[:& comment-item {:comment item
:users users
:origin origin}]])
[:div {:ref ref}]]
[:& reply-form {:thread thread}]])
(when (some? comment)
[:div.thread-content
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-click dom/stop-propagation}
[:div.comments
[:& comment-item {:comment comment
:users users
:thread thread
:origin origin}]
(for [item (rest comments)]
[:* {:key (dm/str (:id item))}
[:hr]
[:& comment-item {:comment item
:users users
:origin origin}]])
[:div {:ref ref}]]
[:& reply-form {:thread thread}]]))))
[:div {:class (stl/css :comments)}
[:& comment-item {:comment comment
:users users
:thread thread
:origin origin}]
(for [item (rest comments)]
[:* {:key (dm/str (:id item))}
[:& comment-item {:comment item
:users users
:origin origin}]])
[:div {:ref ref}]]
[:& reply-form {:thread thread}]])))
(defn use-buble
[zoom {:keys [position frame-id]}]
@ -602,8 +467,7 @@
(mf/defc thread-bubble
{::mf/wrap [mf/memo]}
[{:keys [thread zoom open? on-click origin position-modifier]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
pos (cond-> (:position thread)
(let [pos (cond-> (:position thread)
(some? position-modifier)
(gpt/transform position-modifier))
@ -658,37 +522,22 @@
(dom/stop-propagation event)
(when (= origin :viewer)
(on-click thread))))]
(if new-css-system
[:div {:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-pointer-down on-pointer-down*
:on-pointer-up on-pointer-up*
:on-pointer-move on-pointer-move*
:on-click on-click*
:on-lost-pointer-capture on-lost-pointer-capture
:class (stl/css-case
:floating-thread-bubble true
:resolved (:is-resolved thread)
:unread (pos? (:count-unread-comments thread)))}
[:span (:seqn thread)]]
[:div.thread-bubble
{:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-pointer-down on-pointer-down*
:on-pointer-up on-pointer-up*
:on-pointer-move on-pointer-move*
:on-click on-click*
:on-lost-pointer-capture on-lost-pointer-capture
:class (dom/classnames
:resolved (:is-resolved thread)
:unread (pos? (:count-unread-comments thread)))}
[:span (:seqn thread)]])))
[:div {:style {:top (str pos-y "px")
:left (str pos-x "px")}
:on-pointer-down on-pointer-down*
:on-pointer-up on-pointer-up*
:on-pointer-move on-pointer-move*
:on-click on-click*
:on-lost-pointer-capture on-lost-pointer-capture
:class (stl/css-case
:floating-thread-bubble true
:resolved (:is-resolved thread)
:unread (pos? (:count-unread-comments thread)))}
[:span (:seqn thread)]]))
(mf/defc comment-thread
[{:keys [item users on-click]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
owner (get users (:owner-id item))
(let [owner (get users (:owner-id item))
on-click*
(mf/use-fn
(mf/deps item)
@ -698,99 +547,50 @@
(when (fn? on-click)
(on-click item))))]
(if new-css-system
[:div {:class (stl/css :comment)
:on-click on-click*}
[:div {:class (stl/css :author)}
[:div {:class (stl/css-case :thread-bubble true
:resolved (:is-resolved item)
:unread (pos? (:count-unread-comments item)))}
(:seqn item)]
[:div {:class (stl/css :avatar)}
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div {:class (stl/css :name)}
[:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]]
[:div {:class (stl/css :content)}
(:content item)]
[:div {:class (stl/css :replies)}
(let [unread (:count-unread-comments item ::none)
total (:count-comments item 1)]
[:*
(when (> total 1)
(if (= total 2)
[:span {:class (stl/css :total-replies)} "1 reply"]
[:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
[:div {:class (stl/css :comment)
:on-click on-click*}
[:div {:class (stl/css :author)}
[:div {:class (stl/css-case :thread-bubble true
:resolved (:is-resolved item)
:unread (pos? (:count-unread-comments item)))}
(:seqn item)]
[:div {:class (stl/css :avatar)}
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div {:class (stl/css :name)}
[:div {:class (stl/css :fullname)} (:fullname owner)]
[:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]]
[:div {:class (stl/css :content)}
(:content item)]
[:div {:class (stl/css :replies)}
(let [unread (:count-unread-comments item ::none)
total (:count-comments item 1)]
[:*
(when (> total 1)
(if (= total 2)
[:span {:class (stl/css :total-replies)} "1 reply"]
[:span {:class (stl/css :total-replies)} (str (dec total) " replies")]))
(when (and (> total 1) (> unread 0))
(if (= unread 1)
[:span {:class (stl/css :new-replies)} "1 new reply"]
[:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]
[:div.comment {:on-click on-click*}
[:div.author
[:div.thread-bubble
{:class (dom/classnames
:resolved (:is-resolved item)
:unread (pos? (:count-unread-comments item)))}
(:seqn item)]
[:div.avatar
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
[:div.name
[:div.fullname (:fullname owner) ", "]
[:div.timeago (dt/timeago (:modified-at item))]]]
[:div.content
[:span.text (:content item)]]
[:div.content.replies
(let [unread (:count-unread-comments item ::none)
total (:count-comments item 1)]
[:*
(when (> total 1)
(if (= total 2)
[:span.total-replies "1 reply"]
[:span.total-replies (str (dec total) " replies")]))
(when (and (> total 1) (> unread 0))
(if (= unread 1)
[:span.new-replies "1 new reply"]
[:span.new-replies (str unread " new replies")]))])]])))
(when (and (> total 1) (> unread 0))
(if (= unread 1)
[:span {:class (stl/css :new-replies)} "1 new reply"]
[:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]))
(mf/defc comment-thread-group
[{:keys [group users on-thread-click]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :thread-group)}
(if (:file-name group)
[:div {:class (stl/css :section-title)}
[:span {:class (stl/css :file-name)} (:file-name group) ", "]
[:span {:class (stl/css :page-name)} (:page-name group)]]
[:div {:class (stl/css :thread-group)}
(if (:file-name group)
[:div {:class (stl/css :section-title)}
[:span {:class (stl/css :file-name)} (:file-name group) ", "]
[:span {:class (stl/css :page-name)} (:page-name group)]]
[:div {:class (stl/css :section-title)}
[:span {:class (stl/css :icon)} i/document-refactor]
[:span {:class (stl/css :page-name)} (:page-name group)]])
[:div {:class (stl/css :section-title)}
[:span {:class (stl/css :icon)} i/document-refactor]
[:span {:class (stl/css :page-name)} (:page-name group)]])
[:div {:class (stl/css :threads)}
(for [item (:items group)]
[:& comment-thread
{:item item
:on-click on-thread-click
:users users
:key (:id item)}])]]
[:div.thread-group
(if (:file-name group)
[:div.section-title
[:span.label.filename (:file-name group) ", "]
[:span.label (:page-name group)]]
[:div.section-title
[:span.icon i/file-html]
[:span.label (:page-name group)]])
[:div.threads
(for [item (:items group)]
[:& comment-thread
{:item item
:on-click on-thread-click
:users users
:key (:id item)}])]])))
[:div {:class (stl/css :threads)}
(for [item (:items group)]
[:& comment-thread
{:item item
:on-click on-thread-click
:users users
:key (:id item)}])]])

View file

@ -13,96 +13,106 @@
border-radius: $br-8;
padding: $s-8 $s-16;
.section-title {
@include titleTipography;
height: $s-32;
display: flex;
align-items: center;
margin-bottom: $s-8;
.file-name {
color: var(--comment-subtitle-color);
}
.page-name {
color: var(--comment-subtitle-color);
}
.icon {
display: flex;
align-items: center;
padding: 0 $s-6 0 $s-4;
width: $s-24;
height: $s-32;
margin-left: $s-6;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
}
.threads {
display: flex;
flex-direction: column;
gap: $s-24;
}
&:hover {
background: $db-primary;
}
}
.section-title {
@include titleTipography;
height: $s-32;
display: flex;
align-items: center;
margin-bottom: $s-8;
}
.file-name {
color: var(--comment-subtitle-color);
}
.page-name {
color: var(--comment-subtitle-color);
}
.icon {
display: flex;
align-items: center;
padding: 0 $s-6 0 $s-4;
width: $s-24;
height: $s-32;
margin-left: $s-6;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
}
.threads {
display: flex;
flex-direction: column;
gap: $s-24;
}
// Comment-thread
.comment {
@include titleTipography;
display: flex;
flex-direction: column;
gap: $s-12;
.author {
display: flex;
gap: $s-8;
.thread-bubble {
@extend .comment-bubbles;
&.resolved {
@extend .resolved-comment-bubble;
}
&.unread {
@extend .unread-comment-bubble;
}
}
.avatar {
height: $s-32;
width: $s-32;
border-radius: $br-circle;
img {
border-radius: $br-circle;
}
}
.name {
flex-grow: 1;
.fullname {
@include textEllipsis;
color: var(--comment-title-color);
}
.timeago {
@include textEllipsis;
color: var(--comment-subtitle-color);
}
}
}
.author {
display: flex;
gap: $s-8;
}
.thread-bubble {
@extend .comment-bubbles;
&.resolved {
@extend .resolved-comment-bubble;
}
.content {
@include titleTipography;
color: var(--color-foreground-primary);
}
.replies {
display: flex;
gap: $s-8;
.total-replies {
color: var(--color-foreground-secondary);
}
.new-replies {
color: var(--color-accent-primary);
}
&.unread {
@extend .unread-comment-bubble;
}
}
.avatar {
height: $s-32;
width: $s-32;
border-radius: $br-circle;
img {
border-radius: $br-circle;
}
}
.name {
flex-grow: 1;
.fullname {
@include textEllipsis;
color: var(--comment-title-color);
}
.timeago {
@include textEllipsis;
color: var(--comment-subtitle-color);
}
}
.content {
@include titleTipography;
color: var(--color-foreground-primary);
}
.replies {
display: flex;
gap: $s-8;
}
.total-replies {
color: var(--color-foreground-secondary);
}
.new-replies {
color: var(--color-accent-primary);
}
// Thread-bubble
.floating-thread-bubble {

View file

@ -30,15 +30,14 @@
(when label-text
[:label {:for input-id :class-name label-class} label-text])
[:input
{:style {:display "none"
:width 0}
:id input-id
:multiple multi
:accept accept
:type "file"
:ref input-ref
:on-change on-files-selected
:data-test data-test
:aria-label "uploader"}]]))
[:input {:style {:display "none"
:width 0}
:id input-id
:multiple multi
:accept accept
:type "file"
:ref input-ref
:on-change on-files-selected
:data-test data-test
:aria-label "uploader"}]]))

View file

@ -9,7 +9,6 @@
(:require
[app.main.data.modal :as modal]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr t]]
@ -31,8 +30,7 @@
cancel-label
accept-label
accept-style] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
locale (mf/deref i18n/locale)
(let [locale (mf/deref i18n/locale)
on-accept (or on-accept identity)
on-cancel (or on-cancel identity)
@ -67,87 +65,45 @@
(partial events/unlistenByKey))))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])
(when (> (count items) 0)
[:*
[:p {:class (stl/css :modal-subtitle)}
(tr "ds.component-subtitle")]
[:ul {:class (stl/css :component-list)}
(for [item items]
[:li {:class (stl/css :modal-item-element)}
[:span {:class (stl/css :modal-component-icon)}
i/component-refactor]
[:span {:class (stl/css :modal-component-name)}
(:name item)]])]])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input
{:class (stl/css :cancel-button)
:type "button"
:value cancel-label
:on-click cancel-fn}])
[:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])
(when (> (count items) 0)
[:*
[:p {:class (stl/css :modal-subtitle)}
(tr "ds.component-subtitle")]
[:ul {:class (stl/css :component-list)}
(for [item items]
[:li {:class (stl/css :modal-item-element)}
[:span {:class (stl/css :modal-component-icon)}
i/component-refactor]
[:span {:class (stl/css :modal-component-name)}
(:name item)]])]])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input
{:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
{:class (stl/css :cancel-button)
:type "button"
:value accept-label
:on-click accept-fn}]]]]]
:value cancel-label
:on-click cancel-fn}])
[:div.modal-overlay
[:div.modal-container.confirm-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 title]]
[:div.modal-close-button
{:on-click cancel-fn} i/close]]
[:div.modal-content
(when (and (string? message) (not= message ""))
[:h3 message])
(when (and (string? scd-message) (not= scd-message ""))
[:h3 scd-message])
(when (string? hint)
[:p hint])
(when (> (count items) 0)
[:*
[:p (tr "ds.component-subtitle")]
[:ul.component-list
(for [item items]
[:li.modal-item-element
[:span.modal-component-icon i/component]
[:span (:name item)]])]])]
[:div.modal-footer
[:div.action-buttons
(when-not (= cancel-label :omit)
[:input.cancel-button
{:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]])))
[:input
{:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]))

View file

@ -11,56 +11,63 @@
&.transparent {
background-color: transparent;
}
.modal-container {
@extend .modal-container-base;
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.component-list {
.modal-item-element {
@include flexRow;
.modal-component-icon {
@include flexCenter;
height: $s-16;
width: $s-16;
svg {
@extend .button-icon-small;
stroke: var(--color);
}
}
.modal-component-name {
@include titleTipography;
}
}
}
.modal-hint {
@extend .modal-hint-base;
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
}
.modal-container {
@extend .modal-container-base;
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.modal-item-element {
@include flexRow;
}
.modal-component-icon {
@include flexCenter;
height: $s-16;
width: $s-16;
svg {
@extend .button-icon-small;
stroke: var(--color);
}
}
.modal-component-name {
@include titleTipography;
}
.modal-hint {
@extend .modal-hint-base;
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}

View file

@ -12,7 +12,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[cljs.spec.alpha :as s]
@ -26,8 +25,7 @@
{::mf/register modal/components
::mf/register-as :leave-and-reassign}
[{:keys [profile team accept]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
form (fm/use-form :spec ::leave-modal-form :initial {})
(let [form (fm/use-form :spec ::leave-modal-form :initial {})
members-map (mf/deref refs/dashboard-team-members)
members (vals members-map)
@ -42,71 +40,37 @@
(let [member-id (get-in @form [:clean-data :member-id])]
(accept member-id)))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.leave-and-reassign.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)}
[:p {:class (stl/css :modal-msg)}
(tr "modals.leave-and-reassign.hint1" (:name team))]
(if (empty? members)
[:p {:class (stl/css :modal-msg)}
(tr "modals.leave-and-reassign.hint1" (:name team))]
(tr "modals.leave-and-reassign.forbidden")]
[:*
[:& fm/form {:form form}
[:& fm/select {:name :member-id
:options options}]]])]
(if (empty? members)
[:p {:class (stl/css :modal-msg)}
(tr "modals.leave-and-reassign.forbidden")]
[:*
[:& fm/form {:form form}
[:& fm/select {:name :member-id
:options options}]]])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input.accept-button
{:type "button"
:class (stl/css-case :accept-btn true
:danger (:valid @form)
:global/disabled (not (:valid @form)))
:disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
:on-click on-accept}]]]]]
[:div.modal-overlay
[:div.modal-container.confirm-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.leave-and-reassign.title")]]
[:div.modal-close-button
{:on-click on-cancel} i/close]]
[:div.modal-content.generic-form
[:p (tr "modals.leave-and-reassign.hint1" (:name team))]
(if (empty? members)
[:p (tr "modals.leave-and-reassign.forbidden")]
[:*
[:& fm/form {:form form}
[:& fm/select {:name :member-id
:options options}]]])]
[:div.modal-footer
[:div.action-buttons
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input.accept-button
{:type "button"
:class (if (:valid @form) "danger" "btn-disabled")
:disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
:on-click on-accept}]]]]])))
[:input.accept-button
{:type "button"
:class (stl/css-case :accept-btn true
:danger (:valid @form)
:global/disabled (not (:valid @form)))
:disabled (not (:valid @form))
:value (tr "modals.leave-and-reassign.promote-and-leave")
:on-click on-accept}]]]]]))

View file

@ -8,39 +8,46 @@
.modal-overlay {
@extend .modal-overlay-base;
.modal-container {
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.input-wrapper {
@extend .input-with-label;
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
}
.modal-container {
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color);
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.input-wrapper {
@extend .input-with-label;
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}

View file

@ -11,7 +11,6 @@
[app.common.data.macros :as dm]
[app.main.data.modal :as modal]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.worker :as uw]
[app.util.dom :as dom]
@ -24,36 +23,19 @@
(mf/defc export-entry
{::mf/wrap-props false}
[{:keys [file]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
[:div {:class (stl/css-case :file-entry true
:loading (:loading? file)
:success (:export-success? file)
:error (:export-error? file))}
(if new-css-system
[:div {:class (stl/css-case :file-entry true
:loading (:loading? file)
:success (:export-success? file)
:error (:export-error? file))}
[:div {:class (stl/css :file-name)}
[:span {:class (stl/css :file-icon)}
(cond (:export-success? file) i/tick-refactor
(:export-error? file) i/close-refactor
(:loading? file) i/loader-pencil)]
[:div {:class (stl/css :file-name)}
[:span {:class (stl/css :file-icon)}
(cond (:export-success? file) i/tick-refactor
(:export-error? file) i/close-refactor
(:loading? file) i/loader-pencil)]
[:div {:class (stl/css :file-name-label)}
(:name file)]]]
[:div.file-entry
{:class (dom/classnames
:loading (:loading? file)
:success (:export-success? file)
:error (:export-error? file))}
[:div.file-name
[:div.file-icon
(cond (:export-success? file) i/tick
(:export-error? file) i/close
(:loading? file) i/loader-pencil)]
[:div.file-name-label (:name file)]]])))
[:div {:class (stl/css :file-name-label)}
(:name file)]]])
(defn- mark-file-error
[files file-id]
@ -79,8 +61,7 @@
::mf/register-as :export
::mf/wrap-props false}
[{:keys [team-id files has-libraries? binary? features]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
state* (mf/use-state
(let [state* (mf/use-state
#(let [files (mapv (fn [file] (assoc file :loading? true)) files)]
{:status :prepare
:selected :all
@ -140,136 +121,70 @@
(when-not has-libraries?
(start-export)))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)}
(tr "dashboard.export.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)}
(tr "dashboard.export.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-cancel} i/close-refactor]]
(cond
(= status :prepare)
[:*
[:div {:class (stl/css :modal-content)}
[:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")]
[:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")]
(cond
(= status :prepare)
[:*
[:div {:class (stl/css :modal-content)}
[:p {:class (stl/css :modal-msg)} (tr "dashboard.export.explain")]
[:p {:class (stl/css :modal-scd-msg)} (tr "dashboard.export.detail")]
(for [type export-types]
[:div {:class (stl/css :export-option true)
:key (name type)}
[:label {:for (str "export-" type)
:class (stl/css-case :global/checked (= selected type))}
;; Execution time translation strings:
;; dashboard.export.options.all.message
;; dashboard.export.options.all.title
;; dashboard.export.options.detach.message
;; dashboard.export.options.detach.title
;; dashboard.export.options.merge.message
;; dashboard.export.options.merge.title
[:span {:class (stl/css-case :global/checked (= selected type))}
(when (= selected type)
i/status-tick-refactor)]
[:div {:class (stl/css :option-content)}
[:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
[:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]]
(for [type export-types]
[:div {:class (stl/css :export-option true)
:key (name type)}
[:label {:for (str "export-" type)
:class (stl/css-case :global/checked (= selected type))}
;; Execution time translation strings:
;; dashboard.export.options.all.message
;; dashboard.export.options.all.title
;; dashboard.export.options.detach.message
;; dashboard.export.options.detach.title
;; dashboard.export.options.merge.message
;; dashboard.export.options.merge.title
[:span {:class (stl/css-case :global/checked (= selected type))}
(when (= selected type)
i/status-tick-refactor)]
[:div {:class (stl/css :option-content)}
[:h3 {:class (stl/css :modal-subtitle)} (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
[:p {:class (stl/css :modal-msg)} (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]]
[:input {:type "radio"
:class (stl/css :option-input)
:id (str "export-" type)
:checked (= selected type)
:name "export-option"
:data-type (name type)
:on-change on-change}]]])]
[:input {:type "radio"
:class (stl/css :option-input)
:id (str "export-" type)
:checked (= selected type)
:name "export-option"
:data-type (name type)
:on-change on-change}]]])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.continue")
:on-click on-accept}]]]]
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.continue")
:on-click on-accept}]]]]
(= status :exporting)
[:*
[:div {:class (stl/css :modal-content)}
(for [file (:files state)]
[:& export-entry {:file file :key (dm/str (:id file))}])]
(= status :exporting)
[:*
[:div {:class (stl/css :modal-content)}
(for [file (:files state)]
[:& export-entry {:file file :key (dm/str (:id file))}])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.close")
:disabled (->> state :files (some :loading?))
:on-click on-cancel}]]]])]]
[:div.modal-overlay
[:div.modal-container.export-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "dashboard.export.title")]]
[:div.modal-close-button
{:on-click on-cancel} i/close]]
(cond
(= status :prepare)
[:*
[:div.modal-content
[:p.explain (tr "dashboard.export.explain")]
[:p.detail (tr "dashboard.export.detail")]
(for [type export-types]
[:div.export-option {:class (when (= selected type) "selected")
:key (name type)}
[:label.option-container
;; Execution time translation strings:
;; dashboard.export.options.all.message
;; dashboard.export.options.all.title
;; dashboard.export.options.detach.message
;; dashboard.export.options.detach.title
;; dashboard.export.options.merge.message
;; dashboard.export.options.merge.title
[:h3 (tr (dm/str "dashboard.export.options." (d/name type) ".title"))]
[:p (tr (dm/str "dashboard.export.options." (d/name type) ".message"))]
[:input {:type "radio"
:checked (= selected type)
:data-type (name type)
:on-change on-change
:name "export-option"}]
[:span {:class "option-radio-check"}]]])]
[:div.modal-footer
[:div.action-buttons
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click on-cancel}]
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.continue")
:on-click on-accept}]]]]
(= status :exporting)
[:*
[:div.modal-content
(for [file (:files state)]
[:& export-entry {:file file :key (dm/str (:id file))}])]
[:div.modal-footer
[:div.action-buttons
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.close")
:disabled (->> state :files (some :loading?))
:on-click on-cancel}]]]])]])))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.close")
:disabled (->> state :files (some :loading?))
:on-click on-cancel}]]]])]]))

View file

@ -8,59 +8,64 @@
.modal-overlay {
@extend .modal-overlay-base;
}
.modal-container {
@extend .modal-container-base;
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-container {
@extend .modal-container-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.export-option {
@extend .input-checkbox;
width: 100%;
align-items: flex-start;
label {
align-items: flex-start;
.modal-subtitle {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
}
span {
margin-top: $s-8;
}
.option-content {
@include flexColumn;
@include titleTipography;
}
}
}
.modal-header {
margin-bottom: $s-24;
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.export-option {
@extend .input-checkbox;
width: 100%;
align-items: flex-start;
label {
align-items: flex-start;
.modal-subtitle {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
}
span {
margin-top: $s-8;
}
}
.option-content {
@include flexColumn;
@include titleTipography;
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
.modal-scd-msg,

View file

@ -18,7 +18,6 @@
[app.main.features :as features]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.worker :as uw]
[app.util.dom :as dom]
@ -152,8 +151,7 @@
(mf/defc import-entry
[{:keys [state file editing? can-be-deleted?]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
loading? (or (= :analyzing (:status file))
(let [loading? (or (= :analyzing (:status file))
(= :importing (:status file)))
analyze-error? (= :analyze-error (:status file))
import-finish? (= :import-finish (:status file))
@ -191,122 +189,66 @@
(fn []
(swap! state update :files remove-file (:file-id file))))]
(if new-css-system
[:div {:class (stl/css-case :file-entry true
:loading loading?
:success (and import-finish? (not import-warn?) (not import-error?))
:warning (and import-finish? import-warn? (not import-error?))
:error (or import-error? analyze-error?)
:editable (and ready? (not editing?)))}
[:div {:class (stl/css-case :file-entry true
:loading loading?
:success (and import-finish? (not import-warn?) (not import-error?))
:warning (and import-finish? import-warn? (not import-error?))
:error (or import-error? analyze-error?)
:editable (and ready? (not editing?)))}
[:div {:class (stl/css :file-name)}
[:div {:class (stl/css-case :file-icon true
:icon-fill ready?)}
(cond loading? i/loader-pencil
ready? i/logo-icon
import-warn? i/msg-warning
import-error? i/close-refactor
import-finish? i/tick-refactor
analyze-error? i/close-refactor)]
[:div {:class (stl/css :file-name)}
[:div {:class (stl/css-case :file-icon true
:icon-fill ready?)}
(cond loading? i/loader-pencil
ready? i/logo-icon
import-warn? i/msg-warning
import-error? i/close-refactor
import-finish? i/tick-refactor
analyze-error? i/close-refactor)]
(if editing?
[:div {:class (stl/css :file-name-edit)}
[:input {:type "text"
:auto-focus true
:default-value (:name file)
:on-key-press handle-edit-key-press
:on-blur handle-edit-blur}]]
(if editing?
[:div {:class (stl/css :file-name-edit)}
[:input {:type "text"
:auto-focus true
:default-value (:name file)
:on-key-press handle-edit-key-press
:on-blur handle-edit-blur}]]
[:div {:class (stl/css :file-name-label)}
(:name file)
(when is-shared? i/library-refactor)])
[:div {:class (stl/css :file-name-label)}
(:name file)
(when is-shared? i/library-refactor)])
[:div {:class (stl/css :edit-entry-buttons)}
(when (= "application/zip" (:type file))
[:button {:on-click handle-edit-entry} i/curve-refactor])
(when can-be-deleted?
[:button {:on-click handle-remove-entry} i/delete-refactor])]]
(cond
analyze-error?
[:div {:class (stl/css :error-message)}
(tr "dashboard.import.analyze-error")]
[:div {:class (stl/css :edit-entry-buttons)}
(when (= "application/zip" (:type file))
[:button {:on-click handle-edit-entry} i/curve-refactor])
(when can-be-deleted?
[:button {:on-click handle-remove-entry} i/delete-refactor])]]
(cond
analyze-error?
[:div {:class (stl/css :error-message)}
(tr "dashboard.import.analyze-error")]
import-error?
[:div {:class (stl/css :error-message)}
(tr "dashboard.import.import-error")]
import-error?
[:div {:class (stl/css :error-message)}
(tr "dashboard.import.import-error")]
(and (not import-finish?) (some? progress))
[:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
(and (not import-finish?) (some? progress))
[:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
[:div {:class (stl/css :linked-libraries)}
(for [library-id (:libraries file)]
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
error? (or (:deleted? library-data) (:import-error library-data))]
(when (some? library-data)
[:div {:class (stl/css-case :linked-library-tag true
:error error?)}
i/detach-refactor (:name library-data)])))]]
[:div.file-entry
{:class (dom/classnames
:loading loading?
:success (and import-finish? (not import-warn?) (not import-error?))
:warning (and import-finish? import-warn? (not import-error?))
:error (or import-error? analyze-error?)
:editable (and ready? (not editing?)))}
[:div.file-name
[:div.file-icon
(cond loading? i/loader-pencil
ready? i/logo-icon
import-warn? i/msg-warning
import-error? i/close
import-finish? i/tick
analyze-error? i/close)]
(if editing?
[:div.file-name-edit
[:input {:type "text"
:auto-focus true
:default-value (:name file)
:on-key-press handle-edit-key-press
:on-blur handle-edit-blur}]]
[:div.file-name-label (:name file) (when is-shared? i/library)])
[:div.edit-entry-buttons
(when (= "application/zip" (:type file))
[:button {:on-click handle-edit-entry} i/pencil])
(when can-be-deleted?
[:button {:on-click handle-remove-entry} i/trash])]]
(cond
analyze-error?
[:div.error-message
(tr "dashboard.import.analyze-error")]
import-error?
[:div.error-message
(tr "dashboard.import.import-error")]
(and (not import-finish?) (some? progress))
[:div.progress-message (parse-progress-message progress)])
[:div.linked-libraries
(for [library-id (:libraries file)]
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
error? (or (:deleted? library-data) (:import-error library-data))]
(when (some? library-data)
[:div.linked-library-tag {:class (when error? "error")}
(if error? i/unchain i/chain) (:name library-data)])))]])))
[:div {:class (stl/css :linked-libraries)}
(for [library-id (:libraries file)]
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
error? (or (:deleted? library-data) (:import-error library-data))]
(when (some? library-data)
[:div {:class (stl/css-case :linked-library-tag true
:error error?)}
i/detach-refactor (:name library-data)])))]]))
(mf/defc import-dialog
{::mf/register modal/components
::mf/register-as :import}
[{:keys [project-id files template on-finish-import]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
state (mf/use-state
(let [state (mf/use-state
{:status :analyzing
:editing nil
:importing-templates 0
@ -425,122 +367,60 @@
#(doseq [file files]
(wapi/revoke-uri (:uri file)))))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
[:button {:class (stl/css :modal-close-btn)
:on-click handle-cancel} i/close-refactor]]
[:button {:class (stl/css :modal-close-btn)
:on-click handle-cancel} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)}
(when (and (= :importing (:status @state)) (not pending-import?))
(if (> warning-files 0)
[:div {:class (stl/css-case :feedback-banner true
:warning true)}
[:div {:class (stl/css :icon)} i/msg-warning-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]]
(when (and (= :importing (:status @state)) (not pending-import?))
(if (> warning-files 0)
[:div {:class (stl/css-case :feedback-banner true
:warning true)}
[:div {:class (stl/css :icon)} i/msg-warning-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-warning" warning-files success-files)]]
[:div {:class (stl/css :feedback-banner)}
[:div {:class (stl/css :icon)} i/msg-success-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
[:div {:class (stl/css :feedback-banner)}
[:div {:class (stl/css :icon)} i/msg-success-refactor]
[:div {:class (stl/css :message)} (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
(for [file files]
(let [editing? (and (some? (:file-id file))
(= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
:key (dm/str (:uri file))
:file file
:editing? editing?
:can-be-deleted? (> (count files) 1)}]))
(when (some? template)
(for [file files]
(let [editing? (and (some? (:file-id file))
(= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
:editing? false
:can-be-deleted? false}])]
:key (dm/str (:uri file))
:file file
:editing? editing?
:can-be-deleted? (> (count files) 1)}]))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when (= :analyzing (:status @state))
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click handle-cancel}])
(when (some? template)
[:& import-entry {:state state
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
:editing? false
:can-be-deleted? false}])]
(when (= :analyzing (:status @state))
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.continue")
:disabled (or pending-analysis? (not valid-files?))
:on-click handle-continue}])
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when (= :analyzing (:status @state))
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click handle-cancel}])
(when (= :importing (:status @state))
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.accept")
:disabled (or pending-import? (not valid-files?))
:on-click handle-accept}])]]]]
(when (= :analyzing (:status @state))
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.continue")
:disabled (or pending-analysis? (not valid-files?))
:on-click handle-continue}])
[:div.modal-overlay
[:div.modal-container.import-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "dashboard.import")]]
[:div.modal-close-button
{:on-click handle-cancel} i/close]]
[:div.modal-content
(when (and (= :importing (:status @state)) (not pending-import?))
(if (> warning-files 0)
[:div.feedback-banner.warning
[:div.icon i/msg-warning]
[:div.message (tr "dashboard.import.import-warning" warning-files success-files)]]
[:div.feedback-banner
[:div.icon i/checkbox-checked]
[:div.message (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))]]))
(for [file files]
(let [editing? (and (some? (:file-id file))
(= (:file-id file) (:editing @state)))]
[:& import-entry {:state state
:key (dm/str (:uri file))
:file file
:editing? editing?
:can-be-deleted? (> (count files) 1)}]))
(when (some? template)
[:& import-entry {:state state
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
:editing? false
:can-be-deleted? false}])]
[:div.modal-footer
[:div.action-buttons
(when (= :analyzing (:status @state))
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click handle-cancel}])
(when (= :analyzing (:status @state))
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.continue")
:disabled (or pending-analysis? (not valid-files?))
:on-click handle-continue}])
(when (= :importing (:status @state))
[:input.accept-button
{:class "primary"
:type "button"
:value (tr "labels.accept")
:disabled (or pending-import? (not valid-files?))
:on-click handle-accept}])]]]])))
(when (= :importing (:status @state))
[:input {:class (stl/css :accept-btn)
:type "button"
:value (tr "labels.accept")
:disabled (or pending-import? (not valid-files?))
:on-click handle-accept}])]]]]))

View file

@ -8,69 +8,72 @@
.modal-overlay {
@extend .modal-overlay-base;
}
.modal-container {
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-container {
@extend .modal-container-base;
border: $s-1 solid var(--modal-border-color);
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.feedback-banner {
@include flexRow;
height: $s-32;
width: 100%;
margin-bottom: $s-24;
border-radius: $br-8;
background-color: var(--alert-background-color-ok);
color: var(--alert-foreground-color-ok);
.icon {
@include flexCenter;
height: $s-24;
width: $s-24;
svg {
@extend .button-icon;
stroke: var(--alert-foreground-color-ok);
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.feedback-banner {
@include flexRow;
height: $s-32;
width: 100%;
margin-bottom: $s-24;
border-radius: $br-8;
background-color: var(--alert-background-color-ok);
color: var(--alert-foreground-color-ok);
.icon {
@include flexCenter;
height: $s-24;
width: $s-24;
svg {
@extend .button-icon;
stroke: var(--alert-foreground-color-ok);
}
}
.message {
@include titleTipography;
}
&.warning {
background-color: var(--alert-background-color-warning);
color: var(--alert-foreground-color-warning);
.icon svg {
stroke: var(--alert-foreground-color-warning);
}
}
}
}
.message {
@include titleTipography;
}
&.warning {
background-color: var(--alert-background-color-warning);
color: var(--alert-foreground-color-warning);
.icon svg {
stroke: var(--alert-foreground-color-warning);
}
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
@ -122,6 +125,7 @@
.error-message,
.progress-message {
height: $s-32;
color: var(--modal-text-foreground-color);
}
.linked-libraries {

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,6 @@
[app.main.data.modal :as modal]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
@ -70,73 +69,42 @@
(mf/defc team-form-modal {::mf/register modal/components
::mf/register-as :team-form}
[{:keys [team] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
initial (mf/use-memo (fn [] (or team {})))
(let [initial (mf/use-memo (fn [] (or team {})))
form (fm/use-form :spec ::team-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)
on-close #(st/emit! (modal/hide))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-header)}
(if team
[:h2 {:class (stl/css :modal-title)}
(tr "labels.rename-team")]
[:h2 {:class (stl/css :modal-title)}
(tr "labels.create-team")])
[:div {:class (stl/css :modal-header)}
(if team
[:h2 {:class (stl/css :modal-title)}
(tr "labels.rename-team")]
[:h2 {:class (stl/css :modal-title)}
(tr "labels.create-team")])
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:& fm/input {:type "text"
:auto-focus? true
:class (stl/css :group-name-input)
:form form
:name :name
:placeholder "E.g. Design"
:label (tr "labels.create-team.placeholder")}]]
[:div {:class (stl/css :modal-content)}
[:& fm/input {:type "text"
:auto-focus? true
:class (stl/css :group-name-input)
:form form
:name :name
:placeholder "E.g. Design"
:label (tr "labels.create-team.placeholder")}]]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:> fm/submit-button*
{:label (if team
(tr "labels.update-team")
(tr "labels.create-team"))
:className (stl/css :accept-btn)}]]]]]]
[:div.modal-overlay
[:div.modal-container.team-form-modal
[:& fm/form {:form form :on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
(if team
[:h2 (tr "labels.rename-team")]
[:h2 (tr "labels.create-team")])]
[:div.modal-close-button
{:on-click #(st/emit! (modal/hide))} i/close]]
[:div.modal-content.generic-form
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:label (tr "labels.create-team.placeholder")}]]
[:div.modal-footer
[:div.action-buttons
[:> fm/submit-button*
{:label (if team
(tr "labels.update-team")
(tr "labels.create-team"))}]]]]]])))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:> fm/submit-button*
{:label (if team
(tr "labels.update-team")
(tr "labels.create-team"))
:className (stl/css :accept-btn)}]]]]]]))

View file

@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,7 @@
::mf/register-as :delete-shared-libraries
::mf/wrap-props false}
[{:keys [ids on-accept on-cancel accept-style origin count-libraries]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
references* (mf/use-state {})
(let [references* (mf/use-state {})
references (deref references*)
on-accept (or on-accept noop)
@ -96,91 +94,43 @@
(let [key (events/listen js/document "keydown" on-keydown)]
(partial events/unlistenByKey key))))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:button {:class (stl/css :modal-close-btn)
:on-click cancel-fn} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
(when (and (string? subtitle) (not= subtitle ""))
[:h3 {:class (stl/css :modal-subtitle)} subtitle])
(when (not= 0 count-libraries)
(if (pos? (count references))
[:*
[:div
(when (and (string? scd-msg) (not= scd-msg ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-msg])
[:ul {:class (stl/css :element-list)}
(for [[file-id file-name] references]
[:li {:class (stl/css :list-item)
:key (dm/str file-id)}
[:span "- " file-name]])]]
(when (and (string? hint) (not= hint ""))
[:h3 {:class (stl/css :modal-hint)}hint])]
[:*
[:h3 {:class (stl/css :modal-msg)} no-files-msg]]))]
[:div {:class (stl/css :modal-content)}
(when (and (string? subtitle) (not= subtitle ""))
[:h3 {:class (stl/css :modal-subtitle)} subtitle])
(when (not= 0 count-libraries)
(if (pos? (count references))
[:*
[:div
(when (and (string? scd-msg) (not= scd-msg ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-msg])
[:ul {:class (stl/css :element-list)}
(for [[file-id file-name] references]
[:li {:class (stl/css :list-item)
:key (dm/str file-id)}
[:span "- " file-name]])]]
(when (and (string? hint) (not= hint ""))
[:h3 {:class (stl/css :modal-hint)} hint])]
[:*
[:h3 {:class (stl/css :modal-msg)} no-files-msg]]))]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input {:class (stl/css :cancel-button)
:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:input {:class (stl/css :cancel-button)
:type "button"
:value accept-label
:on-click accept-fn}]]]]]
:value cancel-label
:on-click cancel-fn}])
[:div.modal-overlay
[:div.modal-container.confirm-dialog
[:div.modal-header
[:div.modal-header-title
[:h2 title]]
[:div.modal-close-button
{:on-click cancel-fn} i/close]]
[:div.modal-content.delete-shared
(when (and (string? subtitle) (not= subtitle ""))
[:h3 subtitle])
(when (not= 0 count-libraries)
(if (pos? (count references))
[:*
[:div
(when (and (string? scd-msg) (not= scd-msg ""))
[:h3 scd-msg])
[:ul.file-list
(for [[file-id file-name] references]
[:li.modal-item-element
{:key (dm/str file-id)}
[:span "- " file-name]])]]
(when (and (string? hint) (not= hint ""))
[:h3 hint])]
[:*
[:h3 no-files-msg]]))]
[:div.modal-footer
[:div.action-buttons
(when-not (= cancel-label :omit)
[:input.cancel-button
{:type "button"
:value cancel-label
:on-click cancel-fn}])
[:input.accept-button
{:class (dom/classnames
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]
)
))
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]))

View file

@ -11,45 +11,53 @@
&.transparent {
background-color: transparent;
}
.modal-container {
@extend .modal-container-base;
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
.modal-hint {
@extend .modal-hint-base;
}
.element-list {
@include titleTipography;
.list-item {
@include titleTipography;
}
}
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
}
.modal-container {
@extend .modal-container-base;
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include titleTipography;
margin-bottom: $s-24;
}
.modal-hint {
@extend .modal-hint-base;
}
.element-list {
@include titleTipography;
.list-item {
@include titleTipography;
}
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}

View file

@ -14,96 +14,52 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.link-button :as lb]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc banner
[{:keys [type position status controls content links actions on-close data-test role] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css-case :banner true
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
:info (= type :info)
:fixed (= position :fixed)
:floating (= position :floating)
:inline (= position :inline)
:hide (= status :hide))}
[:div {:class (stl/css :wrapper)}
[:div {:class (stl/css :icon)}
(case type
:warning i/msg-warning-refactor
:error i/msg-error-refactor
:success i/msg-success-refactor
:info i/msg-neutral-refactor
i/msg-error-refactor)]
[:div {:class (stl/css-case :banner true
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
:info (= type :info)
:fixed (= position :fixed)
:floating (= position :floating)
:inline (= position :inline)
:hide (= status :hide))}
[:div {:class (stl/css :wrapper)}
[:div {:class (stl/css :icon)}
(case type
:warning i/msg-warning-refactor
:error i/msg-error-refactor
:success i/msg-success-refactor
:info i/msg-neutral-refactor
i/msg-error-refactor)]
[:div {:class (stl/css-case :content true
:inline-actions (= controls :inline-actions)
:bottom-actions (= controls :bottom-actions))
:data-test data-test
:role role}
[:span {:class (stl/css :text)}
content
(for [[index link] (d/enumerate links)]
[:* {:key (dm/str "link-" index)}
" " [:& lb/link-button {:class "link"
:on-click (:callback link)
:value (:label link)}]])]
[:div {:class (stl/css-case :content true
:inline-actions (= controls :inline-actions)
:bottom-actions (= controls :bottom-actions))
:data-test data-test
:role role}
[:span {:class (stl/css :text)}
content
(for [[index link] (d/enumerate links)]
[:* {:key (dm/str "link-" index)}
" " [:& lb/link-button {:class "link"
:on-click (:callback link)
:value (:label link)}]])]
(when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div {:class (stl/css :actions)}
(for [action actions]
[:button {:key (uuid/next)
:class (stl/css :action-bnt)
:on-click (:callback action)}
(:label action)])])]
(when (= controls :close)
[:button {:class (stl/css :btn-close)
:on-click on-close} i/close-refactor])]]
[:div.banner {:class (dom/classnames
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
:info (= type :info)
:fixed (= position :fixed)
:floating (= position :floating)
:inline (= position :inline)
:hide (= status :hide))}
[:div.wrapper
[:div.icon (case type
:warning i/msg-warning
:error i/msg-error
:success i/msg-success
:info i/msg-info
i/msg-error)]
[:div.content {:class (dom/classnames
:inline-actions (= controls :inline-actions)
:bottom-actions (= controls :bottom-actions))
:data-test data-test
:role role}
[:span
content
(for [[index link] (d/enumerate links)]
[:* {:key (dm/str "link-" index)}
" " [:& lb/link-button {:class "link"
:on-click (:callback link)
:value (:label link)}]])]
(when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div.actions
(for [action actions]
[:div.btn-secondary.btn-small {:key (uuid/next)
:on-click (:callback action)}
(:label action)])])]
(when (= controls :close)
[:div.btn-close {:on-click on-close} i/close])]])))
(when (or (= controls :bottom-actions) (= controls :inline-actions))
[:div {:class (stl/css :actions)}
(for [action actions]
[:button {:key (uuid/next)
:class (stl/css :action-bnt)
:on-click (:callback action)}
(:label action)])])]
(when (= controls :close)
[:button {:class (stl/css :btn-close)
:on-click on-close} i/close-refactor])]])
(mf/defc notifications
[]

View file

@ -100,15 +100,6 @@
@include titleTipography;
}
.inline-actions {
}
.bottom-actions {
}
.actions {
}
.action-btn {
@extend .button-tertiary;
height: $s-32;

View file

@ -51,7 +51,6 @@
(let [data (unchecked-get props "data")
wrapper-ref (mf/use-ref nil)
components (mf/deref dm/components)
new-css-system (mf/use-ctx ctx/new-css-system)
allow-click-outside (:allow-click-outside data)
@ -78,9 +77,7 @@
(when-let [component (get components (:type data))]
[:div {:ref wrapper-ref
:class (stl/css-case
:modal-wrapper new-css-system
:global/modal-wrapper (not new-css-system))}
:class (stl/css :modal-wrapper)}
(mf/element component (:props data))])))
(def modal-ref

View file

@ -13,7 +13,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.onboarding.newsletter]
[app.main.ui.onboarding.questions]
[app.main.ui.onboarding.team-choice]
@ -33,178 +32,113 @@
(mf/defc onboarding-welcome
[{:keys [next] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
go-next
(let [go-next
(fn []
(send-event "onboarding-step1-continue")
(next))]
(if new-css-system
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/onboarding-welcome.png"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.welcome.title")]]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/onboarding-welcome.png"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.welcome.title")]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.welcome.desc1")]
[:div {:class (stl/css :property-block)}
[:img {:src "images/community.svg"
:border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://community.penpot.app/"
:target "_blank"
:on-click #(send-event "onboarding-community-link")}
(tr "onboarding-v2.welcome.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc2")]]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.welcome.desc1")]
[:div {:class (stl/css :property-block)}
[:img {:src "images/community.svg"
:border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://community.penpot.app/"
:target "_blank"
:on-click #(send-event "onboarding-community-link")}
(tr "onboarding-v2.welcome.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc2")]]]
[:div {:class (stl/css :property-block)}
[:img {:src "images/contributing.svg"
:border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://help.penpot.app/contributing-guide/"
:target "_blank" :on-click #(send-event "onboarding-contributing-link")}
(tr "onboarding-v2.welcome.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc3")]]]]]
[:div {:class (stl/css :property-block)}
[:img {:src "images/contributing.svg"
:border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:href "https://help.penpot.app/contributing-guide/"
:target "_blank" :on-click #(send-event "onboarding-contributing-link")}
(tr "onboarding-v2.welcome.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.welcome.desc3")]]]]]
[:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]]
[:div.modal-container.onboarding.onboarding-v2
[:div.modal-left.welcome
[:img {:src "images/onboarding-welcome.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
[:div.modal-right
[:div.release-container [:span.release "Version " (:main cf/version)]]
[:div.right-content
[:div.modal-title
[:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.welcome.title")]]
[:div.modal-content
[:p (tr "onboarding-v2.welcome.desc1")]
[:div.welcome-card
[:img {:src "images/community.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://community.penpot.app/" :target "_blank" :on-click #(send-event "onboarding-community-link")} (tr "onboarding-v2.welcome.desc2.title")]]
[:div.description (tr "onboarding-v2.welcome.desc2")]]]
[:div.welcome-card
[:img {:src "images/contributing.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://help.penpot.app/contributing-guide/" :target "_blank" :on-click #(send-event "onboarding-contributing-link")} (tr "onboarding-v2.welcome.desc3.title")]]
[:div.description (tr "onboarding-v2.welcome.desc3")]]]]]
[:div.modal-navigation
[:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
[:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]]))
(mf/defc onboarding-before-start
[{:keys [next] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
go-next
(let [go-next
(fn []
(send-event "onboarding-step2-continue")
(next))]
(if new-css-system
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/onboarding-people.png"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.before-start.title")]]
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/onboarding-people.png"
:border "0"
:alt (tr "onboarding.welcome.alt")}]]
[:div {:class (stl/css :modal-right)}
[:div {:class (stl/css :release)}
"Version " (:main cf/version)]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-welcome"}
(tr "onboarding-v2.before-start.title")]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.before-start.desc1")]
[:div {:class (stl/css :property-block)}
[:img {:src "images/user-guide.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://help.penpot.app/user-guide/"
:target "_blank"
:on-click #(send-event "onboarding-user-guide-link")}
(tr "onboarding-v2.before-start.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc2")]]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.before-start.desc1")]
[:div {:class (stl/css :property-block)}
[:img {:src "images/user-guide.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://help.penpot.app/user-guide/"
:target "_blank"
:on-click #(send-event "onboarding-user-guide-link")}
(tr "onboarding-v2.before-start.desc2.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc2")]]]
[:div {:class (stl/css :property-block)}
[:img {:src "images/video-tutorials.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://www.youtube.com/c/Penpot"
:target "_blank"
:on-click #(send-event "onboarding-video-tutorials-link")}
(tr "onboarding-v2.before-start.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc3")]]]]]
[:div {:class (stl/css :property-block)}
[:img {:src "images/video-tutorials.svg" :border "0"}]
[:div {:class (stl/css :text-wrapper)}
[:div {:class (stl/css :property-title)}
[:a {:class (stl/css :modal-link)
:href "https://www.youtube.com/c/Penpot"
:target "_blank"
:on-click #(send-event "onboarding-video-tutorials-link")}
(tr "onboarding-v2.before-start.desc3.title")]]
[:div {:class (stl/css :property-description)}
(tr "onboarding-v2.before-start.desc3")]]]]]
[:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]]
[:div.modal-container.onboarding.onboarding-v2
[:div.modal-left.welcome
[:img {:src "images/onboarding-people.png" :border "0" :alt (tr "onboarding.welcome.alt")}]]
[:div.modal-right
[:div.release-container [:span.release "Version " (:main cf/version)]]
[:div.right-content
[:div.modal-title
[:h2 {:data-test "onboarding-welcome"} (tr "onboarding-v2.before-start.title")]]
[:div.modal-content
[:p (tr "onboarding-v2.before-start.desc1")]
[:div.welcome-card
[:img {:src "images/user-guide.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://help.penpot.app/user-guide/" :target "_blank" :on-click #(send-event "onboarding-user-guide-link")} (tr "onboarding-v2.before-start.desc2.title")]]
[:div.description (tr "onboarding-v2.before-start.desc2")]]]
[:div.welcome-card
[:img {:src "images/video-tutorials.svg" :border "0"}]
[:div
[:div.title [:a {:href "https://www.youtube.com/c/Penpot" :target "_blank" :on-click #(send-event "onboarding-video-tutorials-link")} (tr "onboarding-v2.before-start.desc3.title")]]
[:div.description (tr "onboarding-v2.before-start.desc3")]]]]]
[:div.modal-navigation
[:button.btn-secondary {:on-click go-next :data-test "onboarding-next-btn"} (tr "labels.continue")]]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
[:div {:class (stl/css :modal-footer)}
[:button {:on-click go-next
:data-test "onboarding-next-btn"}
(tr "labels.continue")]]]]))
(mf/defc onboarding-modal
{::mf/register modal/components
::mf/register-as :onboarding}
[_]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
slide (mf/use-state :start)
(let [slide (mf/use-state :start)
klass (mf/use-state "fadeInDown")
navigate
@ -230,15 +164,8 @@
(reset! klass nil)
(tm/dispose! sem))))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div.animated {:class(dm/str @klass " " (stl/css :animated))}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]]
[:div.modal-overlay
[:div.animated {:class @klass}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]])))
[:div {:class (stl/css :modal-overlay)}
[:div.animated {:class (dm/str @klass " " (stl/css :animated))}
(case @slide
:start [:& onboarding-welcome {:next #(navigate :opensource)}]
:opensource [:& onboarding-before-start {:next skip}])]]))

View file

@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@ -20,8 +19,7 @@
{::mf/register modal/components
::mf/register-as :onboarding-newsletter-modal}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
message (tr "onboarding.newsletter.acceptance-message")
(let [message (tr "onboarding.newsletter.acceptance-message")
newsletter-updates (mf/use-state false)
newsletter-news (mf/use-state false)
toggle
@ -39,78 +37,49 @@
(modal/show {:type :onboarding-team})
(du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeInDown {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-newsletter-title"}
(tr "onboarding.newsletter.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.desc")]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :newsletter-options)}
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-updates"}
[:span {:class (stl/css-case :global/checked @newsletter-updates)}
(when @newsletter-updates
i/status-tick-refactor)]
(tr "onboarding-v2.newsletter.updates")
[:input {:type "checkbox"
:id "newsletter-updates"
:on-change #(toggle newsletter-updates)}]]]
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeInDown {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "onboarding-newsletter-title"}
(tr "onboarding.newsletter.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.desc")]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :newsletter-options)}
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-updates"}
[:span {:class (stl/css-case :global/checked @newsletter-updates)}
(when @newsletter-updates
i/status-tick-refactor)]
(tr "onboarding-v2.newsletter.updates")
[:input {:type "checkbox"
:id "newsletter-updates"
:on-change #(toggle newsletter-updates)}]]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-news"}
[:span {:class (stl/css-case :global/checked @newsletter-news)}
(when @newsletter-news
i/status-tick-refactor)]
(tr "onboarding-v2.newsletter.news")
[:input {:type "checkbox"
:id "newsletter-news"
:on-change #(toggle newsletter-news)}]]]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-news"}
[:span {:class (stl/css-case :global/checked @newsletter-news)}
(when @newsletter-news
i/status-tick-refactor)]
(tr "onboarding-v2.newsletter.news")
[:input {:type "checkbox"
:id "newsletter-news"
:on-change #(toggle newsletter-news)}]]]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy1")
[:a {:class (stl/css :modal-link)
:target "_blank"
:href "https://penpot.app/privacy"}
(tr "onboarding.newsletter.policy")]]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy2")]]]
[:div {:class (stl/css :modal-info)}
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy1")
[:a {:class (stl/css :modal-link)
:target "_blank"
:href "https://penpot.app/privacy"}
(tr "onboarding.newsletter.policy")]]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy2")]]]
[:div {:class (stl/css :modal-footer)}
[:button {:on-click accept} (tr "labels.continue")]]
[:div {:class (stl/css :modal-footer)}
[:button {:on-click accept} (tr "labels.continue")]]
[:img {:class (stl/css-case :deco true
:top true)
:src "images/deco-newsletter.png" :border "0"}]]]
[:div.modal-overlay
[:div.modal-container.onboarding.newsletter.animated.fadeInDown
[:div.modal-top
[:h1.newsletter-title {:data-test "onboarding-newsletter-title"} (tr "onboarding.newsletter.title")]
[:p (tr "onboarding-v2.newsletter.desc")]]
[:div.modal-bottom
[:div.newsletter-options
[:div.input-checkbox.check-primary
[:input {:type "checkbox"
:id "newsletter-updates"
:on-change #(toggle newsletter-updates)}]
[:label {:for "newsletter-updates"} (tr "onboarding-v2.newsletter.updates")]]
[:div.input-checkbox.check-primary
[:input {:type "checkbox"
:id "newsletter-news"
:on-change #(toggle newsletter-news)}]
[:label {:for "newsletter-news"} (tr "onboarding-v2.newsletter.news")]]]
[:p (tr "onboarding-v2.newsletter.privacy1") [:a {:target "_blank" :href "https://penpot.app/privacy"} (tr "onboarding.newsletter.policy")]]
[:p (tr "onboarding-v2.newsletter.privacy2")]]
[:div.modal-footer
[:button.btn-primary {:on-click accept} (tr "labels.continue")]]
[:img.deco.top {:src "images/deco-newsletter.png" :border "0"}]
[:img.deco.newsletter-left {:src "images/deco-news-left.png" :border "0"}]
[:img.deco.newsletter-right {:src "images/deco-news-right.png" :border "0"}]]])
))
[:img {:class (stl/css-case :deco true
:top true)
:src "images/deco-newsletter.png" :border "0"}]]]))

View file

@ -15,7 +15,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
@ -30,64 +29,38 @@
(mf/defc team-modal-right
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
(if new-css-system
[:div {:class (stl/css :modal-right)}
[:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-desc")]
[:ul {:class (stl/css :team-features)}
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/document-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-1")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/move-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-2")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/tree-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-3")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/user-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-4")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/tick-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-5")]]]]
[:div.team-right
[:h2.subtitle (tr "onboarding.team-modal.create-team")]
[:p.info (tr "onboarding.team-modal.create-team-desc")]
[:ul.team-features
[:li.feature
[:span.icon i/file-html]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-1")]]
[:li.feature
[:span.icon i/pointer-inner]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-2")]]
[:li.feature
[:span.icon i/tree]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-3")]]
[:li.feature
[:span.icon i/user]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-4")]]
[:li.feature
[:span.icon i/tick]
[:p.feature-txt (tr "onboarding.team-modal.create-team-feature-5")]]]])))
[:div {:class (stl/css :modal-right)}
[:h2 {:class (stl/css :modal-subtitle)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-desc")]
[:ul {:class (stl/css :team-features)}
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/document-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-1")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/move-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-2")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/tree-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-3")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/user-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-4")]]
[:li {:class (stl/css :feature)}
[:span {:class (stl/css :icon)} i/tick-refactor]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.team-modal.create-team-feature-5")]]]])
(mf/defc onboarding-team-modal
{::mf/register modal/components
::mf/register-as :onboarding-team}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
form (fm/use-form :spec ::team-form
(let [form (fm/use-form :spec ::team-form
: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"))])
@ -109,76 +82,43 @@
teams (mf/deref refs/teams)]
(if new-css-system
(if (< (count teams) 2)
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :first-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form
:class (stl/css :modal-form)
:on-submit on-submit}
(if (< (count teams) 2)
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:div {:class (stl/css :first-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.team-modal.create-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form
:class (stl/css :modal-form)
:on-submit on-submit}
[:& fm/input {:type "text"
:class (stl/css :team-name-input)
:name :name
:placeholder "Team name"
:label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:div {:class (stl/css :action-buttons)}
[:& fm/submit-button*
{:className (stl/css :accept-button)
:label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
[:div {:class (stl/css :second-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.choice.team-up.start-without-a-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.start-without-a-team-description")]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :accept-button)
:on-click on-skip}
(tr "onboarding.choice.team-up.continue-without-a-team")]]]]
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "1/2"]]]
(st/emit! (modal/hide)))
(if (< (count teams) 2)
[:div.modal-overlay
[:div.modal-container.onboarding-team.animated.fadeIn
[:div.team-left
[:h2.title (tr "onboarding.team-modal.create-team")]
[:p.info (tr "onboarding.choice.team-up.create-team-desc")]
[:& fm/form {:form form
:on-submit on-submit}
[:& fm/input {:type "text"
:name :name
:label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:& fm/input {:type "text"
:class (stl/css :team-name-input)
:name :name
:placeholder "Team name"
:label (tr "onboarding.choice.team-up.create-team-placeholder")}]
[:div {:class (stl/css :action-buttons)}
[:& fm/submit-button*
{:label (tr "onboarding.choice.team-up.continue-creating-team")}]]
{:className (stl/css :accept-button)
:label (tr "onboarding.choice.team-up.continue-creating-team")}]]]]
[:div {:class (stl/css :second-block)}
[:h2 {:class (stl/css :modal-title)}
(tr "onboarding.choice.team-up.start-without-a-team")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding.choice.team-up.start-without-a-team-description")]
[:h2.title (tr "onboarding.choice.team-up.start-without-a-team")]
[:p.info (tr "onboarding.choice.team-up.start-without-a-team-description")]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :accept-button)
:on-click on-skip}
(tr "onboarding.choice.team-up.continue-without-a-team")]]]]
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "1/2"]]]
[:div
[:button.btn-primary.btn-large {:on-click on-skip} (tr "onboarding.choice.team-up.continue-without-a-team")]]]
[:& team-modal-right]
[:div.paginator "1/2"]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]]
(st/emit! (modal/hide))))))
(st/emit! (modal/hide)))))
(defn get-available-roles
[]
@ -197,8 +137,7 @@
{::mf/register modal/components
::mf/register-as :onboarding-team-invitations}
[{:keys [name] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
initial (mf/use-memo (constantly
(let [initial (mf/use-memo (constantly
{:role "editor"
:name name}))
form (fm/use-form :spec ::invite-form
@ -265,96 +204,48 @@
(on-invite-now form)
(on-invite-later form)))))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")]
[:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
[:div {:class (stl/css :modal-overlay)}
[:div.animated.fadeIn {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:h2 {:class (stl/css :modal-title)} (tr "onboarding.choice.team-up.invite-members")]
[:p {:class (stl/css :modal-text)} (tr "onboarding.choice.team-up.invite-members-info")]
[:div {:class (stl/css :modal-form)}
[:& fm/form {:form form
:on-submit on-submit}
[:div {:class (stl/css :role-select)}
[:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:div {:class (stl/css :modal-form)}
[:& fm/form {:form form
:on-submit on-submit}
[:div {:class (stl/css :role-select)}
[:p {:class (stl/css :role-title)} (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:div {:class (stl/css :invitation-row)}
[:& fm/multi-input {:type "email"
:name :emails
:auto-focus? true
:trim true
:valid-item-fn us/parse-email
:caution-item-fn #{}
:label (tr "modals.invite-member.emails")
:on-submit on-submit}]]]
[:div {:class (stl/css :invitation-row)}
[:& fm/multi-input {:type "email"
:name :emails
:auto-focus? true
:trim true
:valid-item-fn us/parse-email
:caution-item-fn #{}
:label (tr "modals.invite-member.emails")
:on-submit on-submit}]]]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :back-button)
:on-click #(st/emit! (modal/show {:type :onboarding-team})
(ptk/event ::ev/event {::ev/name "invite-members-back"
::ev/origin "onboarding"
:name name
:step 2}))}
(tr "labels.back")]
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :back-button)
:on-click #(st/emit! (modal/show {:type :onboarding-team})
(ptk/event ::ev/event {::ev/name "invite-members-back"
::ev/origin "onboarding"
:name name
:step 2}))}
(tr "labels.back")]
[:& fm/submit-button*
{:className (stl/css :accept-button)
:label
(if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-invite")
(tr "onboarding.choice.team-up.create-team-without-invite"))}]]
[:div {:class (stl/css :modal-hint)}
(tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
[:& fm/submit-button*
{:className (stl/css :accept-button)
:label
(if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-invite")
(tr "onboarding.choice.team-up.create-team-without-invite"))}]]
[:div {:class (stl/css :modal-hint)}
(tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "2/2"]]]
[:div.modal-overlay
[:div.modal-container.onboarding-team-members.animated.fadeIn
[:div.team-left
[:h2.title (tr "onboarding.choice.team-up.invite-members")]
[:p.info (tr "onboarding.choice.team-up.invite-members-info")]
[:& fm/form {:form form
:on-submit on-submit}
[:div.invite-row
[:div.role-wrapper
[:span.rol (tr "onboarding.choice.team-up.roles")]
[:& fm/select {:name :role :options roles}]]
[:& fm/multi-input {:type "email"
:name :emails
:auto-focus? true
:trim true
:valid-item-fn us/parse-email
:caution-item-fn #{}
:on-submit on-submit
:label (tr "modals.invite-member.emails")}]]
[:div.buttons
[:button.btn-secondary.btn-large
{:on-click #(st/emit! (modal/show {:type :onboarding-team})
(ptk/event ::ev/event {::ev/name "invite-members-back"
::ev/origin "onboarding"
:name name
:step 2}))}
(tr "labels.back")]
[:& fm/submit-button*
{:label
(if (> (count emails) 0)
(tr "onboarding.choice.team-up.create-team-and-send-invites")
(tr "onboarding.choice.team-up.create-team-without-inviting"))}]]
[:div.skip-action
(tr "onboarding.choice.team-up.create-team-and-send-invites-description")]]]
[:& team-modal-right]
[:div.paginator "2/2"]
[:img.deco.square {:src "images/deco-square.svg" :border "0"}]
[:img.deco.circle {:src "images/deco-circle.svg" :border "0"}]
[:img.deco.line1 {:src "images/deco-line1.svg" :border "0"}]
[:img.deco.line2 {:src "images/deco-line2.svg" :border "0"}]]])))
[:& team-modal-right]
[:div {:class (stl/css :paginator)} "2/2"]]]))

View file

@ -14,7 +14,6 @@
[app.main.store :as st]
[app.main.ui.components.context-menu-a11y :refer [context-menu-a11y]]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -51,8 +50,7 @@
{::mf/register modal/components
::mf/register-as :access-token}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
form (fm/use-form
(let [form (fm/use-form
:initial initial-data
:spec ::access-token-form
:validators [name-validator
@ -107,176 +105,96 @@
:content (tr "dashboard.access-tokens.copied-success")
:timeout 1000}))))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form :on-submit on-submit}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")]
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.create-access-token.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:disabled @created?
:label (tr "modals.create-access-token.name.label")
:show-success? true
:placeholder (tr "modals.create-access-token.name.placeholder")}]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:disabled @created?
:label (tr "modals.create-access-token.name.label")
:show-success? true
:placeholder (tr "modals.create-access-token.name.placeholder")}]]
[:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")]
[:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
{:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
{:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
{:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
{:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
:default "never"
:disabled @created?
:name :expiration-date}]
(when @created?
[:span.token-created-info
(if (:expires-at created)
(tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
(tr "dashboard.access-tokens.token-will-not-expire"))])]
[:div {:class (stl/css :fields-row)}
[:div {:class (stl/css :select-title)} (tr "modals.create-access-token.expiration-date.label")]
[:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
{:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
{:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
{:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
{:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
:default "never"
:disabled @created?
:name :expiration-date}]
(when @created?
[:span.token-created-info
(if (:expires-at created)
(tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
(tr "dashboard.access-tokens.token-will-not-expire"))])]
[:div {:class (stl/css :fields-row)}
(when @created?
[:div {:class (stl/css :custon-input-wrapper)}
[:input {:type "text"
:value (:token created "")
:class (stl/css :custom-input-token)
:placeholder (tr "modals.create-access-token.token")
:read-only true}]
[:button {:title (tr "modals.create-access-token.copy-token")
:class (stl/css :copy-btn)
:on-click copy-token}
i/clipboard-refactor]])
#_(when @created?
[:div {:class (stl/css :fields-row)}
(when @created?
[:div {:class (stl/css :custon-input-wrapper)}
[:input {:type "text"
:value (:token created "")
:class (stl/css :custom-input-token)
:placeholder (tr "modals.create-access-token.token")
:read-only true}]
[:button {:title (tr "modals.create-access-token.copy-token")
:class (stl/css :copy-btn)
:on-click copy-token}
i/clipboard-refactor]])
#_(when @created?
[:button {:class (stl/css :copy-btn)
:title (tr "modals.create-access-token.copy-token")
:on-click copy-token}
[:span {:class (stl/css :token-value)}(:token created "")]
[:span {:class (stl/css :token-value)} (:token created "")]
[:span {:class (stl/css :icon)}
i/clipboard-refactor]])]]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(if @created?
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.close")
:on-click #(modal/hide!)}]
[:*
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click #(modal/hide!)}]
[:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]]
[:div.modal-overlay
[:div.modal-container.access-tokens-modal
[:& fm/form {:form form :on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.create-access-token.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content.generic-form
[:div.fields-container
[:div.fields-row
[:& fm/input {:type "text"
:auto-focus? true
:form form
:name :name
:disabled @created?
:label (tr "modals.create-access-token.name.label")
:placeholder (tr "modals.create-access-token.name.placeholder")}]]
[:div.fields-row
[:& fm/select {:options [{:label (tr "dashboard.access-tokens.expiration-never") :value "never" :key "never"}
{:label (tr "dashboard.access-tokens.expiration-30-days") :value "720h" :key "720h"}
{:label (tr "dashboard.access-tokens.expiration-60-days") :value "1440h" :key "1440h"}
{:label (tr "dashboard.access-tokens.expiration-90-days") :value "2160h" :key "2160h"}
{:label (tr "dashboard.access-tokens.expiration-180-days") :value "4320h" :key "4320h"}]
:label (tr "modals.create-access-token.expiration-date.label")
:default "never"
:disabled @created?
:name :expiration-date}]
(when @created?
[:span.token-created-info
(if (:expires-at created)
(tr "dashboard.access-tokens.token-will-expire" (dt/format-date-locale (:expires-at created) {:locale locale}))
(tr "dashboard.access-tokens.token-will-not-expire"))])]
[:div.fields-row.access-token-created
(when @created?
[:div.custom-input.with-icon
[:input {:type "text"
:value (:token created "")
:placeholder (tr "modals.create-access-token.token")
:read-only true}]
[:button.help-icon {:title (tr "modals.create-access-token.copy-token")
:on-click copy-token}
i/copy]])]]]
[:div.modal-footer
[:div.action-buttons
(if @created?
[:input.cancel-button
{:type "button"
:value (tr "labels.close")
:on-click #(modal/hide!)}]
[:*
[:input.cancel-button
{:type "button"
:value (tr "labels.cancel")
:on-click #(modal/hide!)}]
[:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]])))
(if @created?
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.close")
:on-click #(modal/hide!)}]
[:*
[:input {:class (stl/css :cancel-button)
:type "button"
:value (tr "labels.cancel")
:on-click #(modal/hide!)}]
[:> fm/submit-button*
{:label (tr "modals.create-access-token.submit-label")}]])]]]]]))
(mf/defc access-tokens-hero
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))]
(if new-css-system
[:div {:class (stl/css :access-tokens-hero-container)}
[:div {:class (stl/css :access-tokens-hero)}
[:div {:class (stl/css :desc)}
[:h2 (tr "dashboard.access-tokens.personal")]
[:p (tr "dashboard.access-tokens.personal.description")]]
(let [on-click (mf/use-fn #(st/emit! (modal/show :access-token {})))]
[:div {:class (stl/css :access-tokens-hero-container)}
[:div {:class (stl/css :access-tokens-hero)}
[:div {:class (stl/css :desc)}
[:h2 (tr "dashboard.access-tokens.personal")]
[:p (tr "dashboard.access-tokens.personal.description")]]
[:button
{:class (stl/css :btn-primary)
:on-click on-click}
[:span (tr "dashboard.access-tokens.create")]]]]
;; OLD
[:div.access-tokens-hero-container
[:div.access-tokens-hero
[:div.desc
[:h2 (tr "dashboard.access-tokens.personal")]
[:p (tr "dashboard.access-tokens.personal.description")]]
[:button.btn-primary
{:on-click on-click}
[:span (tr "dashboard.access-tokens.create")]]]])))
[:button
{:class (stl/css :btn-primary)
:on-click on-click}
[:span (tr "dashboard.access-tokens.create")]]]]))
(mf/defc access-token-actions
[{:keys [on-delete]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
local (mf/use-state {:menu-open false})
(let [local (mf/use-state {:menu-open false})
show? (:menu-open @local)
options (mf/with-memo [on-delete]
[{:option-name (tr "labels.delete")
@ -302,47 +220,25 @@
(dom/stop-propagation event)
(on-menu-click event))))]
(if new-css-system
[:div
{:class (stl/css :icon)
:tab-index "0"
:ref menu-ref
:on-click on-menu-click
:on-key-down on-keydown}
i/actions
[:& context-menu-a11y
{:on-close on-menu-close
:show show?
:fixed? true
:min-width? true
:top "auto"
:left "auto"
:options options}]]
;; OLD
[:div.icon
{:tab-index "0"
:ref menu-ref
:on-click on-menu-click
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions
[:& context-menu-a11y
{:on-close on-menu-close
:show show?
:fixed? true
:min-width? true
:top "auto"
:left "auto"
:options options}]])))
[:div {:class (stl/css :icon)
:tab-index "0"
:ref menu-ref
:on-click on-menu-click
:on-key-down on-keydown}
i/actions
[:& context-menu-a11y
{:on-close on-menu-close
:show show?
:fixed? true
:min-width? true
:top "auto"
:left "auto"
:options options}]]))
(mf/defc access-token-item
{::mf/wrap [mf/memo]}
[{:keys [token] :as props}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
locale (mf/deref i18n/locale)
(let [locale (mf/deref i18n/locale)
expires-at (:expires-at token)
expires-txt (some-> expires-at (dt/format-date-locale {:locale locale}))
expired? (and (some? expires-at) (> (dt/now) expires-at))
@ -366,66 +262,36 @@
:accept-label (tr "modals.delete-acces-token.accept")
:on-accept delete-fn}))))]
(if new-css-system
[:div {:class (stl/css :table-row)}
[:div {:class (stl/css :table-field :name)}
(str (:name token))]
[:div {:class (stl/css :table-row)}
[:div {:class (stl/css :table-field :name)}
(str (:name token))]
[:div {:class (stl/css :table-field :expiration-date)}
[:span {:class (stl/css-case :expired expired? :content true)}
(cond
(nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
:else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
[:div {:class (stl/css :table-field :actions)}
[:& access-token-actions
{:on-delete on-delete}]]]
;; OLD
[:div.table-row
[:div.table-field.name
(str (:name token))]
[:div.table-field.expiration-date
[:span.content {:class (when expired? "expired")}
(cond
(nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
:else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
[:div.table-field.actions
[:& access-token-actions
{:on-delete on-delete}]]])))
[:div {:class (stl/css :table-field :expiration-date)}
[:span {:class (stl/css-case :expired expired? :content true)}
(cond
(nil? expires-at) (tr "dashboard.access-tokens.no-expiration")
expired? (tr "dashboard.access-tokens.expired-on" expires-txt)
:else (tr "dashboard.access-tokens.expires-on" expires-txt))]]
[:div {:class (stl/css :table-field :actions)}
[:& access-token-actions
{:on-delete on-delete}]]]))
(mf/defc access-tokens-page
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
tokens (mf/deref tokens-ref)]
(let [tokens (mf/deref tokens-ref)]
(mf/with-effect []
(dom/set-html-title (tr "title.settings.access-tokens"))
(st/emit! (du/fetch-access-tokens)))
(if new-css-system
[:div {:class (stl/css :dashboard-access-tokens)}
[:div
[:& access-tokens-hero]
(if (empty? tokens)
[:div {:class (stl/css :access-tokens-empty)}
[:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
[:div (tr "dashboard.access-tokens.empty.add-one")]]
[:div {:class (stl/css :dashboard-table)}
[:div {:class (stl/css :table-rows)}
(for [token tokens]
[:& access-token-item {:token token :key (:id token)}])]])]]
;; OLD
[:div.dashboard-access-tokens
[:div
[:& access-tokens-hero]
(if (empty? tokens)
[:div.access-tokens-empty
[:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
[:div (tr "dashboard.access-tokens.empty.add-one")]]
[:div.dashboard-table
[:div.table-rows
(for [token tokens]
[:& access-token-item {:token token :key (:id token)}])]])]])))
[:div {:class (stl/css :dashboard-access-tokens)}
[:div
[:& access-tokens-hero]
(if (empty? tokens)
[:div {:class (stl/css :access-tokens-empty)}
[:div (tr "dashboard.access-tokens.empty.no-access-tokens")]
[:div (tr "dashboard.access-tokens.empty.add-one")]]
[:div {:class (stl/css :dashboard-table)}
[:div {:class (stl/css :table-rows)}
(for [token tokens]
[:& access-token-item {:token token :key (:id token)}])]])]]))

View file

@ -12,95 +12,95 @@
font-size: $fs-16;
margin-top: $s-20;
width: $s-800;
}
.table-header {
color: $df-secondary;
display: grid;
font-size: $fs-12;
grid-template-columns: 43% 1fr $s-108 $s-12;
height: $s-40;
max-width: $s-1000;
padding: 0 $s-16;
text-transform: uppercase;
width: 100%;
.table-header {
color: $df-secondary;
display: grid;
font-size: $fs-12;
grid-template-columns: 43% 1fr $s-108 $s-12;
height: $s-40;
max-width: $s-1000;
padding: 0 $s-16;
text-transform: uppercase;
width: 100%;
}
.table-rows {
color: $db-secondary;
display: flex;
flex-direction: column;
margin-top: $s-16;
max-width: $s-1000;
padding-top: 0;
width: 100%;
}
.table-row {
align-items: center;
background-color: $db-tertiary;
border-radius: $br-8;
color: $df-primary;
display: grid;
font-size: $fs-14;
grid-template-columns: 1fr 43% $s-12;
height: fit-content;
min-height: $s-40;
padding: 0 $s-16;
width: 100%;
&:not(:first-child) {
margin-top: $s-8;
}
}
.table-field {
display: flex;
align-items: center;
.icon {
padding-left: $s-12;
cursor: pointer;
}
.table-rows {
color: $db-secondary;
display: flex;
flex-direction: column;
margin-top: $s-16;
max-width: $s-1000;
padding-top: 0;
width: 100%;
}
.table-row {
align-items: center;
background-color: $db-tertiary;
border-radius: $br-8;
&.name {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: $df-primary;
display: grid;
font-size: $fs-14;
grid-template-columns: 1fr 43% $s-12;
height: fit-content;
min-height: $s-40;
padding: 0 $s-16;
width: 100%;
&:not(:first-child) {
margin-top: $s-8;
}
display: -webkit-box;
max-width: $s-480;
overflow: hidden;
text-overflow: ellipsis;
}
.table-field {
display: flex;
align-items: center;
&.expiration-date {
color: $df-secondary;
font-size: $fs-14;
.icon {
padding-left: $s-12;
cursor: pointer;
}
&.name {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: $df-primary;
display: -webkit-box;
max-width: $s-480;
overflow: hidden;
text-overflow: ellipsis;
}
&.expiration-date {
color: $df-secondary;
font-size: $fs-14;
.content {
padding: $s-2 $s-6;
&.expired {
background-color: var(--warning-color);
border-radius: $br-4;
color: $db-secondary;
}
.content {
padding: $s-2 $s-6;
&.expired {
background-color: var(--warning-color);
border-radius: $br-4;
color: $db-secondary;
}
}
&.access-token-created {
word-break: break-all;
}
&.actions {
position: relative;
}
}
&.access-token-created {
word-break: break-all;
}
svg {
width: $s-12;
height: $s-12;
fill: $df-primary;
&.actions {
position: relative;
}
}
svg {
width: $s-12;
height: $s-12;
fill: $df-primary;
}
.dashboard-access-tokens {
display: flex;
flex-direction: column;

View file

@ -16,7 +16,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]]
@ -76,8 +75,7 @@
{::mf/register modal/components
::mf/register-as :change-email}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
profile (mf/deref refs/profile)
(let [profile (mf/deref refs/profile)
form (fm/use-form :spec ::email-change-form
:validators [email-equality]
:initial profile)
@ -99,82 +97,44 @@
(when (and different-emails-error? (= email-1 email-2))
(swap! form d/dissoc-in [:errors :email-2])))))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form
:on-submit on-submit}
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:& fm/form {:form form
:on-submit on-submit}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "change-email-title"}
(tr "modals.change-email.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)
:data-test "change-email-title"}
(tr "modals.change-email.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner
{:type :info
:content (tr "modals.change-email.info" (:email profile))}]
[:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner
{:type :info
:content (tr "modals.change-email.info" (:email profile))}]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email-1
:label (tr "modals.change-email.new-email")
:trim true
:show-success? true
:on-change-value on-email-change}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email-1
:label (tr "modals.change-email.new-email")
:trim true
:show-success? true
:on-change-value on-email-change}]]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email-2
:label (tr "modals.change-email.confirm-email")
:trim true
:show-success? true
:on-change-value on-email-change}]]]
[:div {:class (stl/css :fields-row)}
[:& fm/input {:type "email"
:name :email-2
:label (tr "modals.change-email.confirm-email")
:trim true
:show-success? true
:on-change-value on-email-change}]]]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)
:data-test "change-email-submit"}
[:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]]
[:div.modal-overlay
[:div.modal-container.change-email-modal.form-container
[:& fm/form {:form form
:on-submit on-submit}
[:div.modal-header
[:div.modal-header-title
[:h2 {:data-test "change-email-title"}
(tr "modals.change-email.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content
[:& msgs/inline-banner
{:type :info
:content (tr "modals.change-email.info" (:email profile))}]
[:div.fields-container
[:div.fields-row
[:& fm/input {:type "email"
:name :email-1
:label (tr "modals.change-email.new-email")
: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
:on-change-value on-email-change}]]]]
[:div.modal-footer
[:div.action-buttons {:data-test "change-email-submit"}
[:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]])
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)
:data-test "change-email-submit"}
[:> fm/submit-button*
{:label (tr "modals.change-email.submit")}]]]]]]
))

View file

@ -8,46 +8,50 @@
.modal-overlay {
@extend .modal-overlay-base;
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
}
.modal-content {
@include flexColumn;
@include titleTipography;
gap: $s-24;
margin-bottom: $s-24;
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
}
.fields-row {
@include flexColumn;
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
}
}
.modal-header {
margin-bottom: $s-24;
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
}
.cancel-button {
@extend .modal-cancel-btn;
}
}
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include flexColumn;
@include titleTipography;
gap: $s-24;
margin-bottom: $s-24;
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
button {
@extend .modal-accept-btn;
}
}
.cancel-button {
@extend .modal-cancel-btn;
}

View file

@ -11,7 +11,6 @@
[app.main.data.modal :as modal]
[app.main.data.users :as du]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr]]
@ -29,8 +28,7 @@
{::mf/register modal/components
::mf/register-as :delete-account}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
on-close
(let [on-close
(mf/use-callback #(st/emit! (modal/hide)))
on-accept
@ -39,52 +37,28 @@
(du/request-account-deletion
(with-meta {} {:on-error on-error}))))]
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:h2 {:class (stl/css :modal-title)} (tr "modals.delete-account.title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner
{:type :warning
:content (tr "modals.delete-account.info")}]]
[:div {:class (stl/css :modal-content)}
[:& msgs/inline-banner
{:type :warning
:content (tr "modals.delete-account.info")}]]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :cancel-button)
:on-click on-close}
(tr "modals.delete-account.cancel")]
[:button {:class (stl/css-case :accept-button true
:danger true)
:on-click on-accept
:data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")]]]]]
[:div.modal-overlay
[:div.modal-container.change-email-modal
[:div.modal-header
[:div.modal-header-title
[:h2 (tr "modals.delete-account.title")]]
[:div.modal-close-button
{:on-click on-close} i/close]]
[:div.modal-content
[:& msgs/inline-banner
{:type :warning
:content (tr "modals.delete-account.info")}]]
[:div.modal-footer
[:div.action-buttons
[:button.btn-danger.btn-large {:on-click on-accept
:data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")]
[:button.btn-secondary.btn-large {:on-click on-close}
(tr "modals.delete-account.cancel")]]]]])))
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
[:button {:class (stl/css :cancel-button)
:on-click on-close}
(tr "modals.delete-account.cancel")]
[:button {:class (stl/css-case :accept-button true
:danger true)
:on-click on-accept
:data-test "delete-account-btn"}
(tr "modals.delete-account.confirm")]]]]]))

View file

@ -8,50 +8,54 @@
.modal-overlay {
@extend .modal-overlay-base;
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
}
.modal-content {
@include flexColumn;
@include titleTipography;
gap: $s-24;
margin-bottom: $s-24;
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
}
.fields-row {
@include flexColumn;
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
}
}
.modal-header {
margin-bottom: $s-24;
}
.modal-footer {
.action-buttons {
@extend .modal-action-btns;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-button {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
}
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include flexColumn;
@include titleTipography;
gap: $s-24;
margin-bottom: $s-24;
}
.fields-row {
@include flexColumn;
}
.select-title {
@include titleTipography;
color: var(--modal-title-foreground-color);
}
.action-buttons {
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-button {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}

View file

@ -14,7 +14,6 @@
[app.main.ui.auth.login :refer [login-methods]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-methods register-validate-form register-success-page]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -27,8 +26,7 @@
{::mf/register modal/components
::mf/register-as :login-register}
[_]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
uri (. (. js/document -location) -href)
(let [uri (. (. js/document -location) -href)
user-email (mf/use-state "")
register-token (mf/use-state "")
@ -71,114 +69,58 @@
(mf/with-effect []
(swap! storage assoc :redirect-url uri))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")]
[:button {:class (stl/css :modal-close-btn)
:title (tr "labels.close")
:on-click close} i/close-refactor]]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "labels.continue-with-penpot")]
[:button {:class (stl/css :modal-close-btn)
:title (tr "labels.close")
:on-click close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :modal-content)}
(case current-section
:login
[:div {:class (stl/css :form-container)}
[:& login-methods {:on-success-callback success-login :origin :viewer}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:a {:on-click set-section
:data-value :recovery-request}
(tr "auth.forgot-password")]]
[:div {:class (stl/css :link-entry)}
[:span (tr "auth.register") " "]
[:a {:on-click set-section
:data-value :register}
(tr "auth.register-submit")]]]]
(case current-section
:login
[:div {:class (stl/css :form-container)}
[:& login-methods {:on-success-callback success-login :origin :viewer}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:a {:on-click set-section
:data-value :recovery-request}
(tr "auth.forgot-password")]]
[:div {:class (stl/css :link-entry)}
[:span (tr "auth.register") " "]
[:a {:on-click set-section
:data-value :register}
(tr "auth.register-submit")]]]]
:register
[:div {:class (stl/css :form-container)}
[:& register-methods {:on-success-callback success-register}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:span (tr "auth.already-have-account") " "]
[:a {:on-click set-section
:data-value :login}
(tr "auth.login-here")]]]]
:register
[:div {:class (stl/css :form-container)}
[:& register-methods {:on-success-callback success-register}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:span (tr "auth.already-have-account") " "]
[:a {:on-click set-section
:data-value :login}
(tr "auth.login-here")]]]]
:register-validate
[:div {:class (stl/css :form-container)}
[:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:a {:on-click set-section
:data-value :register}
(tr "labels.go-back")]]]]
:recovery-request
[:& recovery-request-page {:go-back-callback go-back-to-login
:register-validate
[:div {:class (stl/css :form-container)}
[:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
:email-sent
[:div {:class (stl/css :form-container)}
[:& register-success-page {:params {:email @user-email}}]])
[:div {:class (stl/css :links)}
[:div {:class (stl/css :link-entry)}
[:a {:on-click set-section
:data-value :register}
(tr "labels.go-back")]]]]
(when main-section
[:div {:class (stl/css :links)}
[:& terms-login]])]]]
:recovery-request
[:& recovery-request-page {:go-back-callback go-back-to-login
:on-success-callback success-email-sent}]
:email-sent
[:div {:class (stl/css :form-container)}
[:& register-success-page {:params {:email @user-email}}]])
;;OLD
[:div.modal-overlay
[:div.modal-container.login-register
[:div.title
[:div.modal-close-button {:on-click close :title (tr "labels.close")}
i/close]
(when main-section
[:h2 (tr "labels.continue-with-penpot")])]
[:div.modal-bottom.auth-content
(case current-section
:login
[:div.generic-form.login-form
[:div.form-container
[:& login-methods {:on-success-callback success-login}]
[:div.links
[:div.link-entry
[:a {:on-click #(set-current-section :recovery-request)}
(tr "auth.forgot-password")]]
[:div.link-entry
[:span (tr "auth.register") " "]
[:a {:on-click #(set-current-section :register)}
(tr "auth.register-submit")]]]]]
:register
[:div.form-container
[:& register-methods {:on-success-callback success-register}]
[:div.links
[:div.link-entry
[:span (tr "auth.already-have-account") " "]
[:a {:on-click #(set-current-section :login)}
(tr "auth.login-here")]]]]
:register-validate
[:div.form-container
[:& register-validate-form {:params {:token @register-token}
:on-success-callback success-email-sent}]
[:div.links
[:div.link-entry
[:a {:on-click #(set-current-section :register)}
(tr "labels.go-back")]]]]
:recovery-request
[:& recovery-request-page {:go-back-callback #(set-current-section :login)
:on-success-callback success-email-sent}]
:email-sent
[:div.form-container
[:& register-success-page {:params {:email @user-email}}]])]
(when main-section
[:div.modal-footer.links
[:& terms-login]])]])))
(when main-section
[:div {:class (stl/css :links)}
[:& terms-login]])]]]))

View file

@ -18,7 +18,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -40,8 +39,7 @@
::mf/register-as :share-link
::mf/wrap-props false}
[{:keys [file page]}]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
current-page page
(let [current-page page
current-page-id (:id page)
slinks (mf/deref refs/share-links)
router (mf/deref refs/router)
@ -165,274 +163,151 @@
(reset! confirm* false)
(swap! options* assoc :who-comment value))]
(if new-css-system
[:div {:class (stl/css :share-modal)}
[:div {:class (stl/css :share-link-dialog)}
[:div {:class (stl/css :share-link-header)}
[:h2 {:class (stl/css :share-link-title)}
(tr "common.share-link.title")]
[:button {:class (stl/css :modal-close-button)
:on-click on-close
:title (tr "labels.close")}
i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :share-link-section)}
(when (and (not confirm?) (some? current-link))
[:div {:class (stl/css :custon-input-wrapper)}
[:input {:class (stl/css :input-text)
:type "text"
:value (or current-link "")
:placeholder (tr "common.share-link.placeholder")
:read-only true}]
[:button {:class (stl/css :copy-button)
:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/clipboard-refactor]])
[:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?)
[:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
(cond
(true? confirm?)
[:div {:class (stl/css :confirm-dialog)}
[:div {:class (stl/css :description)}
(tr "common.share-link.confirm-deletion-link-description")]
[:div {:class (stl/css :actions)}
[:input {:type "button"
:class (stl/css :button-cancel)
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input {:type "button"
:class (stl/css :button-danger)
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(some? current-link)
[:input
{:type "button"
:class (stl/css :button-danger)
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
:else
[:input
{:type "button"
:class (stl/css :button-active)
:on-click create-link
:value (tr "common.share-link.get-link")}])]]
[:div {:class (stl/css :share-modal)}
[:div {:class (stl/css :share-link-dialog)}
[:div {:class (stl/css :share-link-header)}
[:h2 {:class (stl/css :share-link-title)}
(tr "common.share-link.title")]
[:button {:class (stl/css :modal-close-button)
:on-click on-close
:title (tr "labels.close")}
i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :share-link-section)}
(when (and (not confirm?) (some? current-link))
[:div {:class (stl/css :custon-input-wrapper)}
[:input {:class (stl/css :input-text)
:type "text"
:value (or current-link "")
:placeholder (tr "common.share-link.placeholder")
:read-only true}]
[:button {:class (stl/css :copy-button)
:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/clipboard-refactor]])
[:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?)
[:div {:class (stl/css :permissions-section)}
[:button {:class (stl/css :manage-permissions)
:on-click toggle-perms-visibility}
[:span {:class (stl/css-case :icon true
:rotated perms-visible?)}
i/arrow-refactor]
(tr "common.share-link.manage-ops")]
[:div {:class (stl/css :hint)} (tr "common.share-link.permissions-hint")])
(cond
(true? confirm?)
[:div {:class (stl/css :confirm-dialog)}
[:div {:class (stl/css :description)}
(tr "common.share-link.confirm-deletion-link-description")]
[:div {:class (stl/css :actions)}
[:input {:type "button"
:class (stl/css :button-cancel)
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input {:type "button"
:class (stl/css :button-danger)
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(when ^boolean perms-visible?
[:*
(let [all-selected? (:all-pages options)
pages (->> (get-in file [:data :pages])
(map #(get-in file [:data :pages-index %])))
selected (:pages options)]
[:div {:class (stl/css :view-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-pages")]
[:div {:class (stl/css :items)}
(if (= 1 (count pages))
(some? current-link)
[:input
{:type "button"
:class (stl/css :button-danger)
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
[:div {:class (stl/css :checkbox-wrapper)}
[:input {:type "checkbox"
:id (dm/str "page-" current-page-id)
:data-page-id (dm/str current-page-id)
:on-change on-mark-checked-page
:checked true}]
[:label {:for (str "page-" current-page-id)} (:name current-page)]
[:span {:class (stl/css-case :checkobox-tick true
:global/checked true)}
i/status-tick-refactor]
[:span (str " " (tr "common.share-link.current-tag"))]]
:else
[:input
{:type "button"
:class (stl/css :button-active)
:on-click create-link
:value (tr "common.share-link.get-link")}])]]
[:*
[:div {:class (stl/css :select-all-row)}
[:div {:class (stl/css :checkbox-wrapper)}
[:label {:for "view-all"
:class (stl/css :select-all-label)}
[:span {:class (stl/css-case :global/checked all-selected?)}
(when all-selected?
i/status-tick-refactor)]
(tr "common.share-link.view-all")
[:input {:type "checkbox"
:id "view-all"
:checked all-selected?
:name "pages-mode"
:on-change on-toggle-all}]]]
[:span {:class (stl/css :count-pages)}
(tr "common.share-link.page-shared" (i18n/c (count selected)))]]
(when (not ^boolean confirm?)
[:div {:class (stl/css :permissions-section)}
[:button {:class (stl/css :manage-permissions)
:on-click toggle-perms-visibility}
[:span {:class (stl/css-case :icon true
:rotated perms-visible?)}
i/arrow-refactor]
(tr "common.share-link.manage-ops")]
[:ul {:class (stl/css :pages-selection)}
(for [{:keys [id name]} pages]
[:li {:class (stl/css :checkbox-wrapper)
:key (dm/str id)}
[:label {:for (dm/str "page-" id)}
[:span {:class (stl/css-case :global/checked (contains? selected id))}
(when (contains? selected id)
i/status-tick-refactor)]
name
(when (= current-page-id id)
[:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
[:input {:type "checkbox"
:id (dm/str "page-" id)
:data-page-id (dm/str id)
:on-change on-mark-checked-page
:checked (contains? selected id)}]]])]])]])
[:div {:class (stl/css :access-mode)}
(when ^boolean perms-visible?
[:*
(let [all-selected? (:all-pages options)
pages (->> (get-in file [:data :pages])
(map #(get-in file [:data :pages-index %])))
selected (:pages options)]
[:div {:class (stl/css :view-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-comment")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-comment-select)
:default-value (dm/str (:who-comment options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-comment-change}]]]
[:div {:class (stl/css :inspect-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-inspect")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-inspect-select)
:default-value (dm/str (:who-inspect options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-inspect-change}]]]])])]]]
;;OLD
[:div.modal-overlay.transparent.share-modal
[:div.modal-container.share-link-dialog
[:div.modal-content.initial
[:div.title
[:h2 (tr "common.share-link.title")]
[:div.modal-close-button
{:on-click on-close
:title (tr "labels.close")}
i/close]]]
[:div.modal-content
[:div.share-link-section
(when (and (not confirm?) (some? current-link))
[:div.custom-input.with-icon
[:input {:type "text"
:value (or current-link "")
:placeholder (tr "common.share-link.placeholder")
:read-only true}]
[:div.help-icon {:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
i/copy]])
[:div.hint-wrapper
(when (not ^boolean confirm?)
[:div.hint (tr "common.share-link.permissions-hint")])
(cond
(true? confirm?)
[:div.confirm-dialog
[:div.description (tr "common.share-link.confirm-deletion-link-description")]
[:div.actions
[:input.btn-secondary
{:type "button"
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input.btn-danger
{:type "button"
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(some? current-link)
[:input.btn-secondary
{:type "button"
:class "primary"
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
:else
[:input.btn-primary
{:type "button"
:class "primary"
:on-click create-link
:value (tr "common.share-link.get-link")}])]]]
[:div.modal-content.ops-section
[:div.manage-permissions
{:on-click toggle-perms-visibility}
[:span.icon i/picker-hsv]
[:div.title (tr "common.share-link.manage-ops")]]
(when ^boolean perms-visible?
[:*
(let [all-selected? (:all-pages options)
pages (->> (get-in file [:data :pages])
(map #(get-in file [:data :pages-index %])))
selected (:pages options)]
[:*
[:div.view-mode
[:div.subtitle
[:span.icon i/play]
(tr "common.share-link.permissions-pages")]
[:div.items
[:div {:class (stl/css :items)}
(if (= 1 (count pages))
[:div.input-checkbox.check-primary
[:div {:class (stl/css :checkbox-wrapper)}
[:input {:type "checkbox"
:id (dm/str "page-" current-page-id)
:data-page-id (dm/str current-page-id)
:on-change on-mark-checked-page
:checked true}]
[:label {:for (str "page-" current-page-id)} (:name current-page)]
[:span {:class (stl/css-case :checkobox-tick true
:global/checked true)}
i/status-tick-refactor]
[:span (str " " (tr "common.share-link.current-tag"))]]
[:*
[:div.row
[:div.input-checkbox.check-primary
[:input {:type "checkbox"
:id "view-all"
:checked all-selected?
:name "pages-mode"
:on-change on-toggle-all}]
[:label {:for "view-all"} (tr "common.share-link.view-all")]]
[:span.count-pages (tr "common.share-link.page-shared" (i18n/c (count selected)))]]
[:div {:class (stl/css :select-all-row)}
[:div {:class (stl/css :checkbox-wrapper)}
[:label {:for "view-all"
:class (stl/css :select-all-label)}
[:span {:class (stl/css-case :global/checked all-selected?)}
(when all-selected?
i/status-tick-refactor)]
(tr "common.share-link.view-all")
[:input {:type "checkbox"
:id "view-all"
:checked all-selected?
:name "pages-mode"
:on-change on-toggle-all}]]]
[:ul.pages-selection
[:span {:class (stl/css :count-pages)}
(tr "common.share-link.page-shared" (i18n/c (count selected)))]]
[:ul {:class (stl/css :pages-selection)}
(for [{:keys [id name]} pages]
[:li.input-checkbox.check-primary {:key (dm/str id)}
[:input {:type "checkbox"
:id (dm/str "page-" id)
:data-page-id (dm/str id)
:on-change on-mark-checked-page
:checked (contains? selected id)}]
(if (= current-page-id id)
[:*
[:label {:for (dm/str "page-" id)} name]
[:span.current-tag (dm/str " " (tr "common.share-link.current-tag"))]]
[:label {:for (dm/str "page-" id)} name])])]])]]])
[:div.access-mode
[:div.subtitle
[:span.icon i/chat]
(tr "common.share-link.permissions-can-comment")]
[:div.items
[:select.input-select {:on-change on-comment-change
:value (:who-comment options)}
[:option {:value "team"} (tr "common.share-link.team-members")]
[:option {:value "all"} (tr "common.share-link.all-users")]]]]
[:div.inspect-mode
[:div.subtitle
[:span.icon i/code]
(tr "common.share-link.permissions-can-inspect")]
[:div.items
[:select.input-select {:on-change on-inspect-change
:value (:who-inspect options)}
[:option {:value "team"} (tr "common.share-link.team-members")]
[:option {:value "all"} (tr "common.share-link.all-users")]]]]])]]])))
[:li {:class (stl/css :checkbox-wrapper)
:key (dm/str id)}
[:label {:for (dm/str "page-" id)}
[:span {:class (stl/css-case :global/checked (contains? selected id))}
(when (contains? selected id)
i/status-tick-refactor)]
name
(when (= current-page-id id)
[:div {:class (stl/css :current-tag)} (dm/str " " (tr "common.share-link.current-tag"))])
[:input {:type "checkbox"
:id (dm/str "page-" id)
:data-page-id (dm/str id)
:on-change on-mark-checked-page
:checked (contains? selected id)}]]])]])]])
[:div {:class (stl/css :access-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-comment")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-comment-select)
:default-value (dm/str (:who-comment options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-comment-change}]]]
[:div {:class (stl/css :inspect-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-inspect")]
[:div {:class (stl/css :items)}
[:& select
{:class (stl/css :who-inspect-select)
:default-value (dm/str (:who-inspect options))
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-inspect-change}]]]])])]]]))

View file

@ -19,7 +19,8 @@
height: $s-32;
margin-right: $s-4;
svg {
height: $s-32;
min-height: $s-32;
width: $s-32;
fill: var(--icon-foreground-hover);
}
}

View file

@ -39,9 +39,11 @@
stroke: var(--icon-foreground);
}
}
.modal-title {
@include tabTitleTipography;
margin-bottom: $s-16;
color: var(--modal-title-foreground-color);
}
.modal-content {
@ -161,6 +163,7 @@
.section-list-empty {
@include titleTipography;
@include flexCenter;
color: var(--empty-message-foreground-color);
svg {
@extend .button-icon-small;

View file

@ -12,7 +12,6 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.context :as ctx]
[app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -32,8 +31,7 @@
{::mf/register modal/components
::mf/register-as :nudge-option}
[]
(let [new-css-system (mf/use-ctx ctx/new-css-system)
profile (mf/deref refs/profile)
(let [profile (mf/deref refs/profile)
nudge (or (get-in profile [:props :nudge]) {:big 10 :small 1})
update-big (mf/use-fn #(st/emit! (dw/update-nudge {:big %})))
update-small (mf/use-fn #(st/emit! (dw/update-nudge {:small %})))
@ -43,45 +41,24 @@
(->> (events/listen js/document EventType.KEYDOWN on-keydown)
(partial events/unlistenByKey)))
(if new-css-system
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :input-wrapper)}
[:label {:class (stl/css :modal-msg)
:for "nudge-small"} (tr "modals.small-nudge")]
[:> numeric-input* {:min 0.01
:id "nudge-small"
:value (:small nudge)
:on-change update-small}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:class (stl/css :modal-msg)
:for "nudge-big"} (tr "modals.big-nudge")]
[:> numeric-input* {:min 0.01
:id "nudge-big"
:value (:big nudge)
:on-change update-big}]]]]]
[:div.nudge-modal-overlay
[:div.nudge-modal-container
[:div.nudge-modal-header
[:p.nudge-modal-title (tr "modals.nudge-title")]
[:button.modal-close-button {:on-click on-close} i/close]]
[:div.nudge-modal-body
[:div.input-wrapper
[:span
[:p.nudge-subtitle (tr "modals.small-nudge")]
[:> numeric-input* {:min 0.01
:value (:small nudge)
:on-change update-small}]]]
[:div.input-wrapper
[:span
[:p.nudge-subtitle (tr "modals.big-nudge")]
[:> numeric-input* {:min 0.01
:value (:big nudge)
:on-change update-big}]]]]]])))
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} (tr "modals.nudge-title")]
[:button {:class (stl/css :modal-close-btn)
:on-click on-close} i/close-refactor]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :input-wrapper)}
[:label {:class (stl/css :modal-msg)
:for "nudge-small"} (tr "modals.small-nudge")]
[:> numeric-input* {:min 0.01
:id "nudge-small"
:value (:small nudge)
:on-change update-small}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:class (stl/css :modal-msg)
:for "nudge-big"} (tr "modals.big-nudge")]
[:> numeric-input* {:min 0.01
:id "nudge-big"
:value (:big nudge)
:on-change update-big}]]]]]))

View file

@ -8,33 +8,37 @@
.modal-overlay {
@extend .modal-overlay-base;
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
.modal-header {
margin-bottom: $s-24;
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
}
}
.modal-content {
@include flexColumn;
gap: $s-24;
@include titleTipography;
margin-bottom: $s-24;
.input-wrapper {
@extend .input-with-label;
label {
text-transform: none;
}
}
}
.modal-container {
@extend .modal-container-base;
min-width: $s-408;
border: $s-1 solid var(--modal-border-color);
}
.modal-header {
margin-bottom: $s-24;
}
.modal-title {
@include tabTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.modal-content {
@include flexColumn;
gap: $s-24;
@include titleTipography;
margin-bottom: $s-24;
}
.input-wrapper {
@extend .input-with-label;
label {
text-transform: none;
}
}

View file

@ -12,10 +12,7 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.components.tabs-container :refer [tabs-container tabs-element]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.comments :refer [comments-sidebar]]
[app.main.ui.workspace.left-header :refer [left-header]]
[app.main.ui.workspace.right-header :refer [right-header]]
@ -26,7 +23,6 @@
[app.main.ui.workspace.sidebar.options :refer [options-toolbox]]
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.object :as obj]
[rumext.v2 :as mf]))
@ -47,7 +43,6 @@
(contains? layout :assets) :assets)
shortcuts? (contains? layout :shortcuts)
show-debug? (contains? layout :debug-panel)
new-css-system (mf/use-ctx ctx/new-css-system)
{on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size}
(use-resize-hook :left-sidebar 275 275 500 :x false :left)
@ -65,25 +60,17 @@
[:aside {:ref parent-ref
:id "left-sidebar-aside"
:data-size size
:class (stl/css-case new-css-system
:global/settings-bar (not new-css-system)
:global/settings-bar-left (not new-css-system)
:left-settings-bar true
:class (stl/css-case :left-settings-bar true
:global/two-row (<= size 300)
:global/three-row (and (> size 300) (<= size 400))
:global/four-row (> size 400))
:style #js {"--width" (dm/str size "px")}}
(when new-css-system
[:& left-header {:file file :layout layout :project project :page-id page-id}])
[:& left-header {:file file :layout layout :project project :page-id page-id}]
[:div {:on-pointer-down on-pointer-down
:on-lost-pointer-capture on-lost-pointer-capture
:on-pointer-move on-pointer-move
:class (if ^boolean new-css-system
(stl/css :resize-area)
(dom/classnames :resize-area true))}]
[:div {:class (if ^boolean new-css-system
(stl/css :settings-bar-inside)
(dom/classnames :settings-bar-inside true))}
:class (stl/css :resize-area)}]
[:div {:class (stl/css :settings-bar-inside)}
(cond
(true? shortcuts?)
[:& shortcuts-container]
@ -92,64 +79,32 @@
[:& debug-panel]
:else
(if ^boolean new-css-system
[:div {:class (stl/css :tabs-wrapper)}
[:& tab-container
{:on-change-tab on-tab-change
:selected section
:shortcuts? shortcuts?
:collapsable? true
:handle-collapse handle-collapse
:class (stl/css :tab-spacing)}
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:div {:class (stl/css :layers-tab)
:style #js {"--height" (str size-pages "px")}}
[:& sitemap {:layout layout
:toggle-pages toggle-pages
:show-pages? @show-pages?
:size size-pages}]
(when @show-pages?
[:div {:class (stl/css :resize-area-horiz)
:on-pointer-down on-pointer-down-pages
:on-lost-pointer-capture on-lost-pointer-capture-pages
:on-pointer-move on-pointer-move-pages}])
[:& layers-toolbox {:size-parent size
:size size-pages}]]]
[:div {:class (stl/css :tabs-wrapper)}
[:& tab-container
{:on-change-tab on-tab-change
:selected section
:shortcuts? shortcuts?
:collapsable? true
:handle-collapse handle-collapse
:class (stl/css :tab-spacing)}
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:div {:class (stl/css :layers-tab)
:style #js {"--height" (str size-pages "px")}}
[:& sitemap {:layout layout
:toggle-pages toggle-pages
:show-pages? @show-pages?
:size size-pages}]
(when @show-pages?
[:div {:class (stl/css :resize-area-horiz)
:on-pointer-down on-pointer-down-pages
:on-lost-pointer-capture on-lost-pointer-capture-pages
:on-pointer-move on-pointer-move-pages}])
[:& layers-toolbox {:size-parent size
:size size-pages}]]]
(when-not ^boolean mode-inspect?
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
[:& assets-toolbox]])]]
[:*
[:button.collapse-sidebar
{:on-click handle-collapse
:aria-label (tr "workspace.sidebar.collapse")}
i/arrow-slide]
[:& tabs-container
{:on-change-tab on-tab-change
:selected section
:shortcuts? shortcuts?
:collapsable? true
:handle-collapse handle-collapse}
[:& tabs-element {:id :layers :title (tr "workspace.sidebar.layers")}
[:div {:class :layers-tab
:style #js {"--height" (str size-pages "px")}}
[:& sitemap {:layout layout
:toggle-pages toggle-pages
:show-pages? @show-pages?
:size size-pages}]
(when @show-pages?
[:div.resize-area-horiz
{:on-pointer-down on-pointer-down-pages
:on-lost-pointer-capture on-lost-pointer-capture-pages
:on-pointer-move on-pointer-move-pages}])
[:& layers-toolbox {:size-parent size}]]]
(when-not ^boolean mode-inspect?
[:& tabs-element {:id :assets :title (tr "workspace.toolbar.assets")}
[:& assets-toolbox]])]]))]]))
(when-not ^boolean mode-inspect?
[:& tab-element {:id :assets :title (tr "workspace.toolbar.assets")}
[:& assets-toolbox]])]])]]))
;; --- Right Sidebar (Component)

View file

@ -64,8 +64,8 @@
(mf/html [:div {:class (stl/css :special-title)}
file-name]))}
(when-not local?
[:span.tool-link.tooltip.tooltip-left {:alt "Open library file"}
[:a {:class (dom/classnames true)
[:span {:title "Open library file"}
[:a {:class (stl/css :file-link)
:href (str "#" url)
:target "_blank"
:on-click dom/stop-propagation}