mirror of
https://github.com/penpot/penpot.git
synced 2025-05-10 07:56:38 +02:00
Merge branch '20/view-application' into develop
This commit is contained in:
commit
a9b2951d8b
20 changed files with 522 additions and 650 deletions
|
@ -17,26 +17,25 @@
|
||||||
[vertx.web :as vw]
|
[vertx.web :as vw]
|
||||||
[vertx.eventbus :as ve]))
|
[vertx.eventbus :as ve]))
|
||||||
|
|
||||||
(def mutation-types-hierarchy
|
(def unauthorized-services
|
||||||
(-> (make-hierarchy)
|
#{:create-demo-profile
|
||||||
(derive :login ::unauthenticated)
|
:logout
|
||||||
(derive :logout ::unauthenticated)
|
:profile
|
||||||
(derive :register-profile ::unauthenticated)
|
:recover-profile
|
||||||
(derive :request-profile-recovery ::unauthenticated)
|
:register-profile
|
||||||
(derive :recover-profile ::unauthenticated)
|
:request-profile-recovery
|
||||||
(derive :create-demo-profile ::unauthenticated)))
|
:viewer-bundle
|
||||||
|
:login})
|
||||||
(def query-types-hierarchy
|
|
||||||
(make-hierarchy))
|
|
||||||
|
|
||||||
(defn query-handler
|
(defn query-handler
|
||||||
[req]
|
[req]
|
||||||
(let [type (keyword (get-in req [:path-params :type]))
|
(let [type (keyword (get-in req [:path-params :type]))
|
||||||
data (merge (:params req)
|
data (merge (:params req)
|
||||||
{::sq/type type
|
{::sq/type type})
|
||||||
:profile-id (:profile-id req)})]
|
data (cond-> data
|
||||||
|
(:profile-id req) (assoc :profile-id (:profile-id req)))]
|
||||||
(if (or (:profile-id req)
|
(if (or (:profile-id req)
|
||||||
(isa? query-types-hierarchy type ::unauthenticated))
|
(contains? unauthorized-services type))
|
||||||
(-> (sq/handle (with-meta data {:req req}))
|
(-> (sq/handle (with-meta data {:req req}))
|
||||||
(p/then' (fn [result]
|
(p/then' (fn [result]
|
||||||
{:status 200
|
{:status 200
|
||||||
|
@ -51,10 +50,11 @@
|
||||||
data (merge (:params req)
|
data (merge (:params req)
|
||||||
(:body-params req)
|
(:body-params req)
|
||||||
(:uploads req)
|
(:uploads req)
|
||||||
{::sm/type type
|
{::sm/type type})
|
||||||
:profile-id (:profile-id req)})]
|
data (cond-> data
|
||||||
|
(:profile-id req) (assoc :profile-id (:profile-id req)))]
|
||||||
(if (or (:profile-id req)
|
(if (or (:profile-id req)
|
||||||
(isa? mutation-types-hierarchy type ::unauthenticated))
|
(contains? unauthorized-services type))
|
||||||
(-> (sm/handle (with-meta data {:req req}))
|
(-> (sm/handle (with-meta data {:req req}))
|
||||||
(p/then' (fn [result]
|
(p/then' (fn [result]
|
||||||
{:status 200 :body result})))
|
{:status 200 :body result})))
|
||||||
|
|
|
@ -91,15 +91,6 @@
|
||||||
(db/query-one conn [sql:profile-by-email email]))
|
(db/query-one conn [sql:profile-by-email email]))
|
||||||
|
|
||||||
|
|
||||||
;; --- Mutation: Add additional email
|
|
||||||
;; TODO
|
|
||||||
|
|
||||||
;; --- Mutation: Mark email as main email
|
|
||||||
;; TODO
|
|
||||||
|
|
||||||
;; --- Mutation: Verify email (or maybe query?)
|
|
||||||
;; TODO
|
|
||||||
|
|
||||||
;; --- Mutation: Update Profile (own)
|
;; --- Mutation: Update Profile (own)
|
||||||
|
|
||||||
(def ^:private sql:update-profile
|
(def ^:private sql:update-profile
|
||||||
|
@ -158,6 +149,7 @@
|
||||||
(update-password conn params)))
|
(update-password conn params)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Mutation: Update Photo
|
;; --- Mutation: Update Photo
|
||||||
|
|
||||||
(declare upload-photo)
|
(declare upload-photo)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[uxbox.images :as images]
|
[uxbox.images :as images]
|
||||||
[uxbox.services.queries :as sq]
|
[uxbox.services.queries :as sq]
|
||||||
[uxbox.services.util :as su]
|
[uxbox.services.util :as su]
|
||||||
|
[uxbox.util.uuid :as uuid]
|
||||||
[uxbox.util.blob :as blob]))
|
[uxbox.util.blob :as blob]))
|
||||||
|
|
||||||
;; --- Helpers & Specs
|
;; --- Helpers & Specs
|
||||||
|
@ -32,11 +33,19 @@
|
||||||
|
|
||||||
;; --- Query: Profile (own)
|
;; --- Query: Profile (own)
|
||||||
|
|
||||||
(defn retrieve-profile
|
(declare retrieve-profile)
|
||||||
[conn id]
|
(declare retrieve-additional-data)
|
||||||
(let [sql "select * from profile where id=$1 and deleted_at is null"]
|
|
||||||
(db/query-one db/pool [sql id])))
|
|
||||||
|
|
||||||
|
(s/def ::profile
|
||||||
|
(s/keys :opt-un [::profile-id]))
|
||||||
|
|
||||||
|
(sq/defquery ::profile
|
||||||
|
[{:keys [profile-id] :as params}]
|
||||||
|
(if profile-id
|
||||||
|
(db/with-atomic [conn db/pool]
|
||||||
|
(retrieve-profile conn profile-id))
|
||||||
|
{:id uuid/zero
|
||||||
|
:fullname "Anonymous User"}))
|
||||||
|
|
||||||
;; NOTE: this query make the assumption that union all preserves the
|
;; NOTE: this query make the assumption that union all preserves the
|
||||||
;; order so the first id will always be the team id and the second the
|
;; order so the first id will always be the team id and the second the
|
||||||
|
@ -65,18 +74,19 @@
|
||||||
{:default-team-id (:id team)
|
{:default-team-id (:id team)
|
||||||
:default-project-id (:id project)}))))
|
:default-project-id (:id project)}))))
|
||||||
|
|
||||||
(s/def ::profile
|
(defn retrieve-profile-data
|
||||||
(s/keys :req-un [::profile-id]))
|
[conn id]
|
||||||
|
(let [sql "select * from profile where id=$1 and deleted_at is null"]
|
||||||
|
(db/query-one conn [sql id])))
|
||||||
|
|
||||||
(sq/defquery ::profile
|
(defn retrieve-profile
|
||||||
[{:keys [profile-id] :as params}]
|
[conn id]
|
||||||
(db/with-atomic [conn db/pool]
|
(p/let [prof (-> (retrieve-profile-data conn id)
|
||||||
(p/let [prof (-> (retrieve-profile conn profile-id)
|
(p/then' su/raise-not-found-if-nil)
|
||||||
(p/then' su/raise-not-found-if-nil)
|
(p/then' strip-private-attrs)
|
||||||
(p/then' strip-private-attrs)
|
(p/then' #(images/resolve-media-uris % [:photo :photo-uri])))
|
||||||
(p/then' #(images/resolve-media-uris % [:photo :photo-uri])))
|
addt (retrieve-additional-data conn id)]
|
||||||
addt (retrieve-additional-data conn profile-id)]
|
(merge prof addt)))
|
||||||
(merge prof addt))))
|
|
||||||
|
|
||||||
;; --- Attrs Helpers
|
;; --- Attrs Helpers
|
||||||
|
|
||||||
|
|
3
frontend/resources/images/icons/full-screen-off.svg
Normal file
3
frontend/resources/images/icons/full-screen-off.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500.00001" width="500" height="500">
|
||||||
|
<path d="M449.67773 20c-9.59809 3.53351-14.43153 13.472828-22.44921 19.304688-36.68366 35.782049-72.17331 72.786642-109.5879 107.818362-.76612-28.84172-.67096-57.696805-.96874-86.544925h-47.55274V231.42383h170.84375v-47.55664c-28.84878-.29635-57.70268-.19723-86.54492-.97071 41.14084-44.14516 85.49381-85.257142 126.57031-129.404292.3673-8.154531-8.63701-11.847784-12.75195-17.839844-5.42547-5.6539-10.9029-11.427284-17.5586-15.652344zM60.037109 268.57617v47.55664c28.84878.29635 57.702691.19723 86.544921.97071-41.14082 44.14516-85.493811 85.25714-126.570311 129.40429-.3673 8.15453 8.637013 11.84779 12.751953 17.83985 5.42547 5.6539 10.902894 11.42728 17.558594 15.65234 9.59809-3.53351 14.431538-13.47283 22.449218-19.30469 36.683666-35.78205 72.173316-72.78663 109.587896-107.81836.76612 28.84173.67096 57.6968.96874 86.54493h47.55274V268.57617H60.037109z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 966 B |
|
@ -1,3 +1,3 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500.00001" width="500" height="500">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500.00001" width="500" height="500">
|
||||||
<path d="M449.67773 20c-9.59809 3.53351-14.43153 13.472828-22.44921 19.304688-36.68366 35.782049-72.17331 72.786642-109.5879 107.818362-.76612-28.84172-.67096-57.696805-.96874-86.544925h-47.55274V231.42383h170.84375v-47.55664c-28.84878-.29635-57.70268-.19723-86.54492-.97071 41.14084-44.14516 85.49381-85.257142 126.57031-129.404292.3673-8.154531-8.63701-11.847784-12.75195-17.839844-5.42547-5.6539-10.9029-11.427284-17.5586-15.652344zM60.037109 268.57617v47.55664c28.84878.29635 57.702691.19723 86.544921.97071-41.14082 44.14516-85.493811 85.25714-126.570311 129.40429-.3673 8.15453 8.637013 11.84779 12.751953 17.83985 5.42547 5.6539 10.902894 11.42728 17.558594 15.65234 9.59809-3.53351 14.431538-13.47283 22.449218-19.30469 36.683666-35.78205 72.173316-72.78663 109.587896-107.81836.76612 28.84173.67096 57.6968.96874 86.54493h47.55274V268.57617H60.037109z"/>
|
<path d="M302.03711 26.576172v47.55664c28.84878.296351 57.70269.197224 86.54492.970704-41.14082 44.145164-85.49381 85.257144-126.57031 129.404294-.3673 8.15453 8.63701 11.84779 12.75195 17.83985 5.42547 5.6539 10.9029 11.42728 17.5586 15.65234 9.59809-3.53351 14.43153-13.47283 22.44921-19.30469 36.68367-35.78205 72.17331-72.78663 109.5879-107.81836.76612 28.84173.67097 57.6968.96874 86.54493h47.55274V26.576172H302.03711zM204.55859 262.57617c-9.59809 3.53351-14.43154 13.47283-22.44921 19.30469-36.68368 35.78205-72.17332 72.78663-109.587896 107.81836-.76612-28.84173-.67097-57.69679-.96875-86.54492H24V474h170.84375v-47.55664c-28.84878-.29635-57.70269-.19722-86.54492-.9707 41.14082-44.14516 85.49381-85.25715 126.57031-129.4043.3673-8.15453-8.63701-11.84778-12.75195-17.83984-5.42547-5.6539-10.9029-11.42729-17.5586-15.65235z"/>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 966 B After Width: | Height: | Size: 936 B |
|
@ -25,7 +25,7 @@
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
&.btn-small {
|
&.btn-small {
|
||||||
font-size: $fs12;
|
font-size: $fs13;
|
||||||
padding: .7rem 1rem;
|
padding: .7rem 1rem;
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
@import 'main/partials/main-bar';
|
@import 'main/partials/main-bar';
|
||||||
@import 'main/partials/workspace';
|
@import 'main/partials/workspace';
|
||||||
@import 'main/partials/workspace-bar';
|
@import 'main/partials/workspace-header';
|
||||||
@import 'main/partials/workspace-libraries';
|
@import 'main/partials/workspace-libraries';
|
||||||
@import 'main/partials/tool-bar';
|
@import 'main/partials/tool-bar';
|
||||||
@import 'main/partials/project-bar';
|
@import 'main/partials/project-bar';
|
||||||
|
@ -71,6 +71,7 @@
|
||||||
@import 'main/partials/debug-icons-preview';
|
@import 'main/partials/debug-icons-preview';
|
||||||
@import 'main/partials/editable-label';
|
@import 'main/partials/editable-label';
|
||||||
@import 'main/partials/tab-container';
|
@import 'main/partials/tab-container';
|
||||||
|
@import "main/partials/zoom-widget";
|
||||||
@import "main/partials/viewer-header";
|
@import "main/partials/viewer-header";
|
||||||
@import "main/partials/viewer-thumbnails";
|
@import "main/partials/viewer-thumbnails";
|
||||||
@import "main/partials/viewer";
|
@import "main/partials/viewer";
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
z-index: 12;
|
z-index: 12;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: $fs13;
|
||||||
|
}
|
||||||
|
|
||||||
.main-icon {
|
.main-icon {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: $color-gray-60;
|
background-color: $color-gray-60;
|
||||||
|
@ -85,9 +89,13 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
justify-content: space-between;
|
justify-content: flex-end;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
margin-left: $big;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-share {
|
.btn-share {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -107,6 +115,10 @@
|
||||||
padding: 0.4rem 1rem;
|
padding: 0.4rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-primary.btn-small {
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-fullscreen {
|
.btn-fullscreen {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: $color-gray-60;
|
background-color: $color-gray-60;
|
||||||
|
@ -134,23 +146,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-link-dropdown {
|
.share-link-dropdown {
|
||||||
position: absolute;
|
background-color: $color-white;
|
||||||
left: -180px;
|
border-radius: $br-small;
|
||||||
top: 45px;
|
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
background-color: $color-gray-50;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
left: -180px;
|
||||||
|
position: absolute;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
top: 45px;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
|
||||||
.share-link-title {
|
.share-link-title {
|
||||||
font-size: 18px;
|
color: $color-black;
|
||||||
|
font-size: $fs15;
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-link-subtitle {
|
.share-link-subtitle {
|
||||||
|
color: $color-gray-40;
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,111 +182,50 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-link-input {
|
.share-link-input {
|
||||||
display: flex;
|
border: 1px solid $color-gray-20;
|
||||||
justify-content: space-between;
|
|
||||||
padding: $small;
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid $color-gray-30;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
height: 40px;
|
||||||
|
justify-content: space-between;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
padding: 9px $small;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
|
color: $color-gray-50;
|
||||||
|
line-height: 1.5;
|
||||||
user-select: all;
|
user-select: all;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
.link-button {
|
||||||
width: 20px;
|
color: $color-primary-dark;
|
||||||
height: 20px;
|
cursor: pointer;
|
||||||
fill: $color-gray-20;
|
flex-shrink: 0;
|
||||||
stroke: $color-gray-20;
|
font-size: $fs15;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $color-black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background-color: $color-white;
|
||||||
|
content: "";
|
||||||
|
height: 16px;
|
||||||
|
left: 53%;
|
||||||
|
position: absolute;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
top: -5px;
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom-widget {
|
.zoom-dropdown {
|
||||||
cursor: pointer;
|
left : 150px;
|
||||||
|
top: 45px;
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.input-container {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-gray-10;
|
|
||||||
font-size: $fs15;
|
|
||||||
margin-left: $x-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-button svg {
|
|
||||||
fill: $color-gray-10;
|
|
||||||
height: 10px;
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
right: -25px;
|
|
||||||
top: 45px;
|
|
||||||
z-index: 12;
|
|
||||||
width: 150px;
|
|
||||||
|
|
||||||
background-color: $color-white;
|
|
||||||
border-radius: $br-small;
|
|
||||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
|
||||||
|
|
||||||
li {
|
|
||||||
color: $color-gray-60;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: $fs12;
|
|
||||||
display: flex;
|
|
||||||
padding: $small;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-gray-40;
|
|
||||||
font-size: $fs12;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary-lighter;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-zoom,
|
|
||||||
.remove-zoom {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
border-radius: $br-small;
|
|
||||||
cursor: pointer;
|
|
||||||
color: $color-gray-20;
|
|
||||||
display: flex;
|
|
||||||
opacity: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
font-size: $fs20;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 20px;
|
|
||||||
justify-content: center;
|
|
||||||
width: 20px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $color-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.add-zoom,
|
|
||||||
.remove-zoom {
|
|
||||||
opacity: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.users-zone {
|
.users-zone {
|
||||||
|
|
|
@ -1,386 +0,0 @@
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
|
||||||
// Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
|
||||||
|
|
||||||
.workspace-bar {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-50;
|
|
||||||
border-bottom: 1px solid $color-gray-60;
|
|
||||||
display: flex;
|
|
||||||
height: 40px;
|
|
||||||
padding: $x-small $medium $x-small 55px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 12;
|
|
||||||
|
|
||||||
.preview {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
border-radius: $br-small;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
height: 25px;
|
|
||||||
justify-content: center;
|
|
||||||
width: 25px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-20;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-menu {
|
|
||||||
position: absolute;
|
|
||||||
top: 40px;
|
|
||||||
left: 40px;
|
|
||||||
width: 230px;
|
|
||||||
z-index: 12;
|
|
||||||
@include animation(0,.2s,fadeInDown);
|
|
||||||
|
|
||||||
background-color: $color-white;
|
|
||||||
border-radius: $br-small;
|
|
||||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
|
||||||
|
|
||||||
li {
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: $fs12;
|
|
||||||
padding: $small $x-small;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-60;
|
|
||||||
height: 12px;
|
|
||||||
width: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-gray-60;
|
|
||||||
margin: 0 $x-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary-lighter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.main-icon {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 40px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
height: 30px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-30;
|
|
||||||
height: 30px;
|
|
||||||
width: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-btn {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: $br-small;
|
|
||||||
display: flex;
|
|
||||||
margin-right: $x-small;
|
|
||||||
padding: $x-small;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: 15px;
|
|
||||||
fill: $color-gray-20;
|
|
||||||
width: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-tree-btn {
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
padding: $x-small;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-20;
|
|
||||||
height: 20px;
|
|
||||||
margin-right: $small;
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-white;
|
|
||||||
font-size: $fs14;
|
|
||||||
overflow-x: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
&.project-name {
|
|
||||||
color: $color-gray-20;
|
|
||||||
margin-right: $x-small;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-options {
|
|
||||||
display: flex;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-input {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-gray-10;
|
|
||||||
font-size: $fs15;
|
|
||||||
margin-left: $x-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-button {
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-10;
|
|
||||||
height: 10px;
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
z-index: 12;
|
|
||||||
width: 150px;
|
|
||||||
@include animation(0,.2s,fadeInDown);
|
|
||||||
|
|
||||||
background-color: $color-white;
|
|
||||||
border-radius: $br-small;
|
|
||||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
|
||||||
|
|
||||||
li {
|
|
||||||
color: $color-gray-60;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: $fs12;
|
|
||||||
display: flex;
|
|
||||||
padding: $small;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $color-gray-40;
|
|
||||||
font-size: $fs12;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary-lighter;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-zoom,
|
|
||||||
.remove-zoom {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
border-radius: $br-small;
|
|
||||||
cursor: pointer;
|
|
||||||
color: $color-gray-20;
|
|
||||||
display: flex;
|
|
||||||
opacity: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
font-size: $fs20;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 20px;
|
|
||||||
justify-content: center;
|
|
||||||
width: 20px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $color-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.add-zoom,
|
|
||||||
.remove-zoom {
|
|
||||||
opacity: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.options-btn {
|
|
||||||
align-items: center;
|
|
||||||
border-right: 4px double $color-gray-60;
|
|
||||||
display: flex;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
align-items: center;
|
|
||||||
background-color: $color-gray-60;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: $br-small;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 30px;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 0 $small;
|
|
||||||
position: relative;
|
|
||||||
width: 30px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-20;
|
|
||||||
height: 18px;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-gray-10;
|
|
||||||
border-color: $color-gray-60;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: $color-primary;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary-options {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.view-mode {
|
|
||||||
background-color: $color-gray-20;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: $br-small;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 30px;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 0 $small;
|
|
||||||
position: relative;
|
|
||||||
width: 30px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-60;
|
|
||||||
height: 18px;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-primary;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: $color-gray-60;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-multi {
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
li {
|
|
||||||
margin-left: $small;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 3px solid #f3dd14;
|
|
||||||
border-radius: 50%;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 25px;
|
|
||||||
width: 25px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiuser-cursor {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
z-index: 10000;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: 15px;
|
|
||||||
fill: #f3dd14;
|
|
||||||
width: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
background-color: #f3dd14;
|
|
||||||
border-radius: $br-small;
|
|
||||||
color: $color-black;
|
|
||||||
font-size: $fs12;
|
|
||||||
margin-left: $small;
|
|
||||||
padding: $x-small;
|
|
||||||
}
|
|
||||||
}
|
|
209
frontend/resources/styles/main/partials/workspace-header.scss
Normal file
209
frontend/resources/styles/main/partials/workspace-header.scss
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
// Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
|
.workspace-header {
|
||||||
|
align-items: center;
|
||||||
|
background-color: $color-gray-50;
|
||||||
|
border-bottom: 1px solid $color-gray-60;
|
||||||
|
display: flex;
|
||||||
|
height: 40px;
|
||||||
|
padding: $x-small $medium $x-small 55px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 12;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.main-icon {
|
||||||
|
align-items: center;
|
||||||
|
background-color: $color-gray-60;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 40px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-30;
|
||||||
|
height: 30px;
|
||||||
|
width: 28px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.users-section {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
margin-left: $big;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-dropdown {
|
||||||
|
top: 45px;
|
||||||
|
left: -30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-button {
|
||||||
|
align-items: center;
|
||||||
|
background-color: $color-gray-60;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: $br-small;
|
||||||
|
display: flex;
|
||||||
|
margin-right: $x-small;
|
||||||
|
padding: $x-small;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 15px;
|
||||||
|
fill: $color-gray-20;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-primary;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-tree {
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
padding: $x-small;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-20;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: $small;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $color-white;
|
||||||
|
font-size: $fs14;
|
||||||
|
overflow-x: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.project-name {
|
||||||
|
color: $color-gray-20;
|
||||||
|
margin-right: $x-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-button {
|
||||||
|
align-items: center;
|
||||||
|
background-color: $color-gray-60;
|
||||||
|
border-radius: $br-small;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
height: 25px;
|
||||||
|
justify-content: center;
|
||||||
|
width: 25px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-20;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-primary;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 40px;
|
||||||
|
left: 40px;
|
||||||
|
width: 230px;
|
||||||
|
z-index: 12;
|
||||||
|
@include animation(0,.2s,fadeInDown);
|
||||||
|
|
||||||
|
background-color: $color-white;
|
||||||
|
border-radius: $br-small;
|
||||||
|
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
|
li {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: $fs12;
|
||||||
|
padding: $small $x-small;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-60;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $color-gray-60;
|
||||||
|
margin: 0 $x-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-primary-lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-users {
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-left: $small;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 3px solid #f3dd14;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 25px;
|
||||||
|
width: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -183,3 +183,28 @@
|
||||||
fill: $color-primary-dark;
|
fill: $color-primary-dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.multiuser-cursor {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10000;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 15px;
|
||||||
|
fill: #f3dd14;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
background-color: #f3dd14;
|
||||||
|
border-radius: $br-small;
|
||||||
|
color: $color-black;
|
||||||
|
font-size: $fs12;
|
||||||
|
margin-left: $small;
|
||||||
|
padding: $x-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
45
frontend/resources/styles/main/partials/zoom-widget.scss
Normal file
45
frontend/resources/styles/main/partials/zoom-widget.scss
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
.zoom-widget {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $color-gray-10;
|
||||||
|
font-size: $fs14;
|
||||||
|
margin-left: $x-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-button svg {
|
||||||
|
fill: $color-gray-10;
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 12;
|
||||||
|
width: 150px;
|
||||||
|
|
||||||
|
background-color: $color-white;
|
||||||
|
border-radius: $br-small;
|
||||||
|
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: $color-gray-60;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: $fs12;
|
||||||
|
display: flex;
|
||||||
|
padding: $small;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $color-gray-40;
|
||||||
|
font-size: $fs12;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-primary-lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@
|
||||||
(def folder (icon-xref :folder))
|
(def folder (icon-xref :folder))
|
||||||
(def folder-zip (icon-xref :folder-zip))
|
(def folder-zip (icon-xref :folder-zip))
|
||||||
(def full-screen (icon-xref :full-screen))
|
(def full-screen (icon-xref :full-screen))
|
||||||
|
(def full-screen-off (icon-xref :full-screen-off))
|
||||||
(def grid (icon-xref :grid))
|
(def grid (icon-xref :grid))
|
||||||
(def grid-snap (icon-xref :grid-snap))
|
(def grid-snap (icon-xref :grid-snap))
|
||||||
(def icon-set (icon-xref :icon-set))
|
(def icon-set (icon-xref :icon-set))
|
||||||
|
@ -103,7 +104,7 @@
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
[:section.debug-icons-preview
|
[:section.debug-icons-preview
|
||||||
(for [[key val] (ns-publics 'uxbox.builtins.icons)]
|
(for [[key val] (sort-by first (ns-publics 'uxbox.builtins.icons))]
|
||||||
(when (not= key 'debug-icons-preview)
|
(when (not= key 'debug-icons-preview)
|
||||||
[:div.icon-item {:key key}
|
[:div.icon-item {:key key}
|
||||||
(deref val)
|
(deref val)
|
||||||
|
|
|
@ -18,23 +18,25 @@
|
||||||
|
|
||||||
;; --- Common Specs
|
;; --- Common Specs
|
||||||
|
|
||||||
(s/def ::id uuid?)
|
(s/def ::id ::us/uuid)
|
||||||
(s/def ::fullname string?)
|
(s/def ::fullname ::us/string)
|
||||||
(s/def ::email ::us/email)
|
(s/def ::email ::us/email)
|
||||||
(s/def ::password string?)
|
(s/def ::password ::us/string)
|
||||||
(s/def ::language string?)
|
(s/def ::language ::us/string)
|
||||||
(s/def ::photo string?)
|
(s/def ::photo ::us/string)
|
||||||
(s/def ::created-at inst?)
|
(s/def ::created-at ::us/inst)
|
||||||
(s/def ::password-1 string?)
|
(s/def ::password-1 ::us/string)
|
||||||
(s/def ::password-2 string?)
|
(s/def ::password-2 ::us/string)
|
||||||
(s/def ::password-old string?)
|
(s/def ::password-old ::us/string)
|
||||||
|
(s/def ::lang (s/nilable ::us/string))
|
||||||
|
|
||||||
(s/def ::profile
|
(s/def ::profile
|
||||||
(s/keys :req-un [::id
|
(s/keys :req-un [::id]
|
||||||
|
:opt-un [::created-at
|
||||||
::fullname
|
::fullname
|
||||||
|
::photo
|
||||||
::email
|
::email
|
||||||
::created-at
|
::lang]))
|
||||||
::photo]))
|
|
||||||
|
|
||||||
;; --- Profile Fetched
|
;; --- Profile Fetched
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
(declare bundle-fetched)
|
(declare bundle-fetched)
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
[page-id]
|
[page-id share-token]
|
||||||
(ptk/reify ::initialize
|
(ptk/reify ::initialize
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -49,18 +49,21 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (fetch-bundle page-id)))))
|
(rx/of (fetch-bundle page-id share-token)))))
|
||||||
|
|
||||||
;; --- Data Fetching
|
;; --- Data Fetching
|
||||||
|
|
||||||
(defn fetch-bundle
|
(defn fetch-bundle
|
||||||
[page-id]
|
[page-id share-token]
|
||||||
(ptk/reify ::fetch-file
|
(ptk/reify ::fetch-file
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(->> (rp/query :viewer-bundle {:page-id page-id})
|
(let [params (cond-> {:page-id page-id}
|
||||||
(rx/map bundle-fetched)))))
|
(string? share-token) (assoc :share-token share-token))]
|
||||||
|
(->> (rp/query :viewer-bundle params)
|
||||||
|
(rx/map bundle-fetched)
|
||||||
|
(rx/catch (fn [error-data]
|
||||||
|
(rx/of (rt/nav :not-found)))))))))
|
||||||
|
|
||||||
(defn- extract-frames
|
(defn- extract-frames
|
||||||
[page]
|
[page]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
;; defined by the Mozilla Public License, v. 2.0.
|
;; defined by the Mozilla Public License, v. 2.0.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2017-2019 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2020 UXBOX Labs SL
|
||||||
|
|
||||||
(ns uxbox.main.refs
|
(ns uxbox.main.refs
|
||||||
"A collection of derived refs."
|
"A collection of derived refs."
|
||||||
|
|
|
@ -101,12 +101,6 @@
|
||||||
:profile-recovery
|
:profile-recovery
|
||||||
[:& profile-recovery-page]
|
[:& profile-recovery-page]
|
||||||
|
|
||||||
:viewer
|
|
||||||
(let [index (d/parse-integer (get-in route [:params :query :index]))
|
|
||||||
page-id (uuid (get-in route [:params :path :page-id]))]
|
|
||||||
[:& viewer-page {:page-id page-id
|
|
||||||
:index index}])
|
|
||||||
|
|
||||||
(:settings-profile
|
(:settings-profile
|
||||||
:settings-password)
|
:settings-password)
|
||||||
[:& settings/settings {:route route}]
|
[:& settings/settings {:route route}]
|
||||||
|
@ -126,6 +120,14 @@
|
||||||
:dashboard-library-palettes-index)
|
:dashboard-library-palettes-index)
|
||||||
[:& dashboard {:route route}]
|
[:& dashboard {:route route}]
|
||||||
|
|
||||||
|
:viewer
|
||||||
|
(let [index (d/parse-integer (get-in route [:params :query :index]))
|
||||||
|
token (get-in route [:params :query :token])
|
||||||
|
page-id (uuid (get-in route [:params :path :page-id]))]
|
||||||
|
[:& viewer-page {:page-id page-id
|
||||||
|
:index index
|
||||||
|
:token token}])
|
||||||
|
|
||||||
:workspace
|
:workspace
|
||||||
(let [project-id (uuid (get-in route [:params :path :project-id]))
|
(let [project-id (uuid (get-in route [:params :path :project-id]))
|
||||||
file-id (uuid (get-in route [:params :path :file-id]))
|
file-id (uuid (get-in route [:params :path :file-id]))
|
||||||
|
|
|
@ -96,8 +96,11 @@
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
(mf/defc viewer-page
|
(mf/defc viewer-page
|
||||||
[{:keys [page-id index] :as props}]
|
[{:keys [page-id index token] :as props}]
|
||||||
(mf/use-effect (mf/deps page-id) #(st/emit! (dv/initialize page-id)))
|
(mf/use-effect
|
||||||
|
(mf/deps page-id token)
|
||||||
|
#(st/emit! (dv/initialize page-id token)))
|
||||||
|
|
||||||
(let [data (mf/deref viewer-data-ref)
|
(let [data (mf/deref viewer-data-ref)
|
||||||
local (mf/deref viewer-local-ref)]
|
local (mf/deref viewer-local-ref)]
|
||||||
(when data
|
(when data
|
||||||
|
|
|
@ -17,43 +17,18 @@
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.builtins.icons :as i]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.ui.components.dropdown :refer [dropdown]]
|
[uxbox.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
[uxbox.main.ui.workspace.header :refer [zoom-widget]]
|
||||||
[uxbox.main.data.viewer :as dv]
|
[uxbox.main.data.viewer :as dv]
|
||||||
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.util.data :refer [classnames]]
|
[uxbox.util.data :refer [classnames]]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.uuid :as uuid]
|
||||||
[uxbox.util.i18n :as i18n :refer [t tr]]
|
[uxbox.util.i18n :as i18n :refer [t tr]]
|
||||||
[uxbox.util.math :as mth]
|
[uxbox.util.math :as mth]
|
||||||
[uxbox.util.router :as rt])
|
[uxbox.util.router :as rt])
|
||||||
(:import goog.events.EventType
|
(:import goog.events.EventType
|
||||||
goog.events.KeyCodes))
|
goog.events.KeyCodes))
|
||||||
|
|
||||||
(mf/defc zoom-widget
|
|
||||||
{:wrap [mf/memo]}
|
|
||||||
[{:keys [zoom] :as props}]
|
|
||||||
(let [show-dropdown? (mf/use-state false)
|
|
||||||
increase #(st/emit! dv/increase-zoom)
|
|
||||||
decrease #(st/emit! dv/decrease-zoom)
|
|
||||||
zoom-to-50 #(st/emit! dv/zoom-to-50)
|
|
||||||
zoom-to-100 #(st/emit! dv/reset-zoom)
|
|
||||||
zoom-to-200 #(st/emit! dv/zoom-to-200)]
|
|
||||||
[:div.zoom-widget
|
|
||||||
[:span.add-zoom {:on-click decrease} "-"]
|
|
||||||
[:div.input-container {:on-click #(reset! show-dropdown? true)}
|
|
||||||
[:span {} (str (mth/round (* 100 zoom)) "%")]
|
|
||||||
[:span.dropdown-button i/arrow-down]
|
|
||||||
[:& dropdown {:show @show-dropdown?
|
|
||||||
:on-close #(reset! show-dropdown? false)}
|
|
||||||
[:ul.zoom-dropdown
|
|
||||||
[:li {:on-click increase}
|
|
||||||
"Zoom in" [:span "+"]]
|
|
||||||
[:li {:on-click decrease}
|
|
||||||
"Zoom out" [:span "-"]]
|
|
||||||
[:li {:on-click zoom-to-50}
|
|
||||||
"Zoom to 50%"]
|
|
||||||
[:li {:on-click zoom-to-100}
|
|
||||||
"Zoom to 100%" [:span "Shift + 0"]]
|
|
||||||
[:li {:on-click zoom-to-200}
|
|
||||||
"Zoom to 200%"]]]]
|
|
||||||
[:span.remove-zoom {:on-click increase} "+"]]))
|
|
||||||
|
|
||||||
(mf/defc share-link
|
(mf/defc share-link
|
||||||
[{:keys [page] :as props}]
|
[{:keys [page] :as props}]
|
||||||
|
@ -64,12 +39,11 @@
|
||||||
create #(st/emit! dv/create-share-link)
|
create #(st/emit! dv/create-share-link)
|
||||||
delete #(st/emit! dv/delete-share-link)
|
delete #(st/emit! dv/delete-share-link)
|
||||||
href (.-href js/location)]
|
href (.-href js/location)]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:span.btn-share.tooltip.tooltip-bottom
|
[:span.btn-primary.btn-small
|
||||||
{:alt "Share link"
|
{:alt "Share link"
|
||||||
:on-click #(swap! show-dropdown? not)}
|
:on-click #(swap! show-dropdown? not)}
|
||||||
i/exit]
|
"Share link"]
|
||||||
|
|
||||||
[:& dropdown {:show @show-dropdown?
|
[:& dropdown {:show @show-dropdown?
|
||||||
:on-close #(swap! show-dropdown? not)
|
:on-close #(swap! show-dropdown? not)
|
||||||
|
@ -78,28 +52,35 @@
|
||||||
[:span.share-link-title "Share link"]
|
[:span.share-link-title "Share link"]
|
||||||
[:div.share-link-input
|
[:div.share-link-input
|
||||||
(if (string? token)
|
(if (string? token)
|
||||||
[:span.link (str href "&" token)]
|
[:span.link (str href "&token=" token)]
|
||||||
[:span "Share link will apear here"])
|
[:span.link-placeholder "Share link will apear here"])
|
||||||
i/chain]
|
[:span.link-button "Copy link"]]
|
||||||
[:span.share-link-subtitle "Anyone with the link will have access"]
|
[:span.share-link-subtitle "Anyone with the link will have access"]
|
||||||
[:div.share-link-buttons
|
[:div.share-link-buttons
|
||||||
(if (string? token)
|
(if (string? token)
|
||||||
[:button.btn-delete {:on-click delete} "Remove link"]
|
[:button.btn-delete {:on-click delete} "Remove link"]
|
||||||
[:button.btn-primary {:on-click create} "Create link"])]]]]))
|
[:button.btn-primary {:on-click create} "Create link"])]]]]))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc header
|
(mf/defc header
|
||||||
[{:keys [data index local fullscreen? toggle-fullscreen] :as props}]
|
[{:keys [data index local fullscreen? toggle-fullscreen] :as props}]
|
||||||
(let [{:keys [project file page frames]} data
|
(let [{:keys [project file page frames]} data
|
||||||
total (count frames)
|
total (count frames)
|
||||||
on-click #(st/emit! dv/toggle-thumbnails-panel)
|
on-click #(st/emit! dv/toggle-thumbnails-panel)
|
||||||
|
|
||||||
|
profile (mf/deref refs/profile)
|
||||||
|
anonymous? (= uuid/zero (:id profile))
|
||||||
|
|
||||||
|
project-id (get-in data [:project :id])
|
||||||
|
file-id (get-in data [:file :id])
|
||||||
|
page-id (get-in data [:page :id])
|
||||||
|
|
||||||
on-edit #(st/emit! (rt/nav :workspace
|
on-edit #(st/emit! (rt/nav :workspace
|
||||||
{:project-id (get-in data [:project :id])
|
{:project-id project-id
|
||||||
:file-id (get-in data [:file :id])}
|
:file-id file-id}
|
||||||
{:page-id (get-in data [:page :id])}))]
|
{:page-id page-id}))]
|
||||||
[:header.viewer-header
|
[:header.viewer-header
|
||||||
[:div.main-icon
|
[:div.main-icon
|
||||||
[:a i/logo-icon]]
|
[:a {:on-click on-edit} i/logo-icon]]
|
||||||
|
|
||||||
[:div.sitemap-zone {:alt (tr "header.sitemap")
|
[:div.sitemap-zone {:alt (tr "header.sitemap")
|
||||||
:on-click on-click}
|
:on-click on-click}
|
||||||
|
@ -112,13 +93,25 @@
|
||||||
[:span.counters (str (inc index) " / " total)]]
|
[:span.counters (str (inc index) " / " total)]]
|
||||||
|
|
||||||
[:div.options-zone
|
[:div.options-zone
|
||||||
[:& share-link {:page (:page data)}]
|
(when-not anonymous?
|
||||||
[:span.btn-primary {:on-click on-edit} "Edit page"]
|
[:& share-link {:page (:page data)}])
|
||||||
[:& zoom-widget {:zoom (:zoom local)}]
|
(when-not anonymous?
|
||||||
|
[:a {:on-click on-edit} "Edit page"])
|
||||||
|
|
||||||
|
[:& zoom-widget
|
||||||
|
{:zoom (:zoom local)
|
||||||
|
:on-increase #(st/emit! dv/increase-zoom)
|
||||||
|
:on-decrease #(st/emit! dv/decrease-zoom)
|
||||||
|
:on-zoom-to-50 #(st/emit! dv/zoom-to-50)
|
||||||
|
:on-zoom-to-100 #(st/emit! dv/reset-zoom)
|
||||||
|
:on-zoom-to-200 #(st/emit! dv/zoom-to-200)}]
|
||||||
|
|
||||||
[:span.btn-fullscreen.tooltip.tooltip-bottom
|
[:span.btn-fullscreen.tooltip.tooltip-bottom
|
||||||
{:alt "Full screen"
|
{:alt "Full Screen"
|
||||||
:on-click toggle-fullscreen}
|
:on-click toggle-fullscreen}
|
||||||
i/full-screen]
|
(if fullscreen?
|
||||||
|
i/full-screen-off
|
||||||
|
i/full-screen)]
|
||||||
]]))
|
]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,33 +30,38 @@
|
||||||
|
|
||||||
(mf/defc zoom-widget
|
(mf/defc zoom-widget
|
||||||
{:wrap [mf/memo]}
|
{:wrap [mf/memo]}
|
||||||
[props]
|
[{:keys [zoom
|
||||||
(let [zoom (mf/deref refs/selected-zoom)
|
on-increase
|
||||||
show-dropdown? (mf/use-state false)
|
on-decrease
|
||||||
increase #(st/emit! dw/increase-zoom)
|
on-zoom-to-50
|
||||||
decrease #(st/emit! dw/decrease-zoom)
|
on-zoom-to-100
|
||||||
zoom-to-50 #(st/emit! dw/zoom-to-50)
|
on-zoom-to-200]
|
||||||
zoom-to-100 #(st/emit! dw/reset-zoom)
|
:as props}]
|
||||||
zoom-to-200 #(st/emit! dw/zoom-to-200)]
|
(let [show-dropdown? (mf/use-state false)
|
||||||
[:div.zoom-input
|
;; increase #(st/emit! dv/increase-zoom)
|
||||||
[:span.add-zoom {:on-click decrease} "-"]
|
;; decrease #(st/emit! dv/decrease-zoom)
|
||||||
[:div {:on-click #(reset! show-dropdown? true)}
|
;; zoom-to-50 #(st/emit! dv/zoom-to-50)
|
||||||
[:span {} (str (mth/round (* 100 zoom)) "%")]
|
;; zoom-to-100 #(st/emit! dv/reset-zoom)
|
||||||
[:span.dropdown-button i/arrow-down]
|
;; zoom-to-200 #(st/emit! dv/zoom-to-200)
|
||||||
[:& dropdown {:show @show-dropdown?
|
]
|
||||||
:on-close #(reset! show-dropdown? false)}
|
[:div.zoom-widget {:on-click #(reset! show-dropdown? true)}
|
||||||
[:ul.zoom-dropdown
|
[:span {} (str (mth/round (* 100 zoom)) "%")]
|
||||||
[:li {:on-click increase}
|
[:span.dropdown-button i/arrow-down]
|
||||||
"Zoom in" [:span "+"]]
|
[:& dropdown {:show @show-dropdown?
|
||||||
[:li {:on-click decrease}
|
:on-close #(reset! show-dropdown? false)}
|
||||||
"Zoom out" [:span "-"]]
|
[:ul.zoom-dropdown
|
||||||
[:li {:on-click zoom-to-50}
|
[:li {:on-click on-increase}
|
||||||
"Zoom to 50%" [:span "Shift + 0"]]
|
"Zoom in" [:span "+"]]
|
||||||
[:li {:on-click zoom-to-100}
|
[:li {:on-click on-decrease}
|
||||||
"Zoom to 100%" [:span "Shift + 1"]]
|
"Zoom out" [:span "-"]]
|
||||||
[:li {:on-click zoom-to-200}
|
[:li {:on-click on-zoom-to-50}
|
||||||
"Zoom to 200%" [:span "Shift + 2"]]]]]
|
"Zoom to 50%"]
|
||||||
[:span.remove-zoom {:on-click increase} "+"]]))
|
[:li {:on-click on-zoom-to-100}
|
||||||
|
"Zoom to 100%" [:span "Shift + 0"]]
|
||||||
|
[:li {:on-click on-zoom-to-200}
|
||||||
|
"Zoom to 200%"]]]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Header Users
|
;; --- Header Users
|
||||||
|
|
||||||
|
@ -77,7 +82,7 @@
|
||||||
[props]
|
[props]
|
||||||
(let [profile (mf/deref refs/profile)
|
(let [profile (mf/deref refs/profile)
|
||||||
users (mf/deref refs/workspace-users)]
|
users (mf/deref refs/workspace-users)]
|
||||||
[:ul.user-multi
|
[:ul.active-users
|
||||||
[:& user-widget {:user profile :self? true}]
|
[:& user-widget {:user profile :self? true}]
|
||||||
(for [id (->> (:active users)
|
(for [id (->> (:active users)
|
||||||
(remove #(= % (:id profile))))]
|
(remove #(= % (:id profile))))]
|
||||||
|
@ -85,16 +90,22 @@
|
||||||
:key id}])]))
|
:key id}])]))
|
||||||
|
|
||||||
(mf/defc menu
|
(mf/defc menu
|
||||||
[{:keys [layout] :as props}]
|
[{:keys [layout project file] :as props}]
|
||||||
(let [show-menu? (mf/use-state false)
|
(let [show-menu? (mf/use-state false)
|
||||||
|
toggle-sitemap #(st/emit! (dw/toggle-layout-flag :sitemap))
|
||||||
locale (i18n/use-locale)]
|
locale (i18n/use-locale)]
|
||||||
|
|
||||||
[:*
|
[:div.menu-section
|
||||||
[:div.menu-btn {:on-click #(reset! show-menu? true)} i/actions]
|
[:div.menu-button {:on-click #(reset! show-menu? true)} i/actions]
|
||||||
|
[:div.project-tree {:alt (t locale "header.sitemap")
|
||||||
|
:class (classnames :selected (contains? layout :sitemap))
|
||||||
|
:on-click toggle-sitemap}
|
||||||
|
[:span.project-name (:name project) " /"]
|
||||||
|
[:span (:name file)]]
|
||||||
|
|
||||||
[:& dropdown {:show @show-menu?
|
[:& dropdown {:show @show-menu?
|
||||||
:on-close #(reset! show-menu? false)}
|
:on-close #(reset! show-menu? false)}
|
||||||
[:ul.workspace-menu
|
[:ul.menu
|
||||||
[:li {:on-click #(st/emit! (dw/toggle-layout-flag :rules))}
|
[:li {:on-click #(st/emit! (dw/toggle-layout-flag :rules))}
|
||||||
[:span i/ruler]
|
[:span i/ruler]
|
||||||
[:span
|
[:span
|
||||||
|
@ -139,28 +150,33 @@
|
||||||
|
|
||||||
(mf/defc header
|
(mf/defc header
|
||||||
[{:keys [page file layout project] :as props}]
|
[{:keys [page file layout project] :as props}]
|
||||||
(let [go-to-dashboard #(st/emit! (rt/nav :dashboard-team {:team-id "self"}))
|
(let [locale (i18n/use-locale)
|
||||||
toggle-sitemap #(st/emit! (dw/toggle-layout-flag :sitemap))
|
go-to-dashboard #(st/emit! (rt/nav :dashboard-team {:team-id "self"}))
|
||||||
|
zoom (mf/deref refs/selected-zoom)
|
||||||
locale (i18n/use-locale)
|
locale (i18n/use-locale)
|
||||||
router (mf/deref router-ref)
|
router (mf/deref router-ref)
|
||||||
view-url (rt/resolve router :viewer {:page-id (:id page)} {:index 0})]
|
view-url (rt/resolve router :viewer {:page-id (:id page)} {:index 0})]
|
||||||
[:header.workspace-bar
|
[:header.workspace-header
|
||||||
[:div.main-icon
|
[:div.main-icon
|
||||||
[:a {:on-click go-to-dashboard} i/logo-icon]]
|
[:a {:on-click go-to-dashboard} i/logo-icon]]
|
||||||
|
|
||||||
[:& menu {:layout layout}]
|
[:& menu {:layout layout
|
||||||
|
:project project
|
||||||
|
:file file}]
|
||||||
|
|
||||||
[:div.project-tree-btn {:alt (tr "header.sitemap")
|
[:div.users-section
|
||||||
:class (classnames :selected (contains? layout :sitemap))
|
|
||||||
:on-click toggle-sitemap}
|
|
||||||
[:span.project-name (:name project) " /"]
|
|
||||||
[:span (:name file)]]
|
|
||||||
|
|
||||||
[:div.workspace-options
|
|
||||||
[:& active-users]]
|
[:& active-users]]
|
||||||
|
|
||||||
[:& zoom-widget]
|
[:div.options-section
|
||||||
|
[:& zoom-widget
|
||||||
|
{:zoom zoom
|
||||||
|
:on-increase #(st/emit! dw/increase-zoom)
|
||||||
|
:on-decrease #(st/emit! dw/decrease-zoom)
|
||||||
|
:on-zoom-to-50 #(st/emit! dw/zoom-to-50)
|
||||||
|
:on-zoom-to-100 #(st/emit! dw/reset-zoom)
|
||||||
|
:on-zoom-to-200 #(st/emit! dw/zoom-to-200)}]
|
||||||
|
|
||||||
|
[:a.preview-button
|
||||||
|
{;; :target "__blank"
|
||||||
|
:href (str "#" view-url)} i/play]]]))
|
||||||
|
|
||||||
[:a.preview {
|
|
||||||
;; :target "__blank"
|
|
||||||
:href (str "#" view-url)} i/play]]))
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue