0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 00:58:26 -05:00

Merge branch '20/view-application' into develop

This commit is contained in:
Andrey Antukh 2020-04-08 13:05:35 +02:00
commit a9b2951d8b
20 changed files with 522 additions and 650 deletions

View file

@ -17,26 +17,25 @@
[vertx.web :as vw]
[vertx.eventbus :as ve]))
(def mutation-types-hierarchy
(-> (make-hierarchy)
(derive :login ::unauthenticated)
(derive :logout ::unauthenticated)
(derive :register-profile ::unauthenticated)
(derive :request-profile-recovery ::unauthenticated)
(derive :recover-profile ::unauthenticated)
(derive :create-demo-profile ::unauthenticated)))
(def query-types-hierarchy
(make-hierarchy))
(def unauthorized-services
#{:create-demo-profile
:logout
:profile
:recover-profile
:register-profile
:request-profile-recovery
:viewer-bundle
:login})
(defn query-handler
[req]
(let [type (keyword (get-in req [:path-params :type]))
data (merge (:params req)
{::sq/type type
:profile-id (:profile-id req)})]
{::sq/type type})
data (cond-> data
(:profile-id req) (assoc :profile-id (: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}))
(p/then' (fn [result]
{:status 200
@ -51,10 +50,11 @@
data (merge (:params req)
(:body-params req)
(:uploads req)
{::sm/type type
:profile-id (:profile-id req)})]
{::sm/type type})
data (cond-> data
(:profile-id req) (assoc :profile-id (: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}))
(p/then' (fn [result]
{:status 200 :body result})))

View file

@ -91,15 +91,6 @@
(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)
(def ^:private sql:update-profile
@ -158,6 +149,7 @@
(update-password conn params)))
;; --- Mutation: Update Photo
(declare upload-photo)

View file

@ -15,6 +15,7 @@
[uxbox.images :as images]
[uxbox.services.queries :as sq]
[uxbox.services.util :as su]
[uxbox.util.uuid :as uuid]
[uxbox.util.blob :as blob]))
;; --- Helpers & Specs
@ -32,11 +33,19 @@
;; --- Query: Profile (own)
(defn retrieve-profile
[conn id]
(let [sql "select * from profile where id=$1 and deleted_at is null"]
(db/query-one db/pool [sql id])))
(declare retrieve-profile)
(declare retrieve-additional-data)
(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
;; 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-project-id (:id project)}))))
(s/def ::profile
(s/keys :req-un [::profile-id]))
(defn retrieve-profile-data
[conn id]
(let [sql "select * from profile where id=$1 and deleted_at is null"]
(db/query-one conn [sql id])))
(sq/defquery ::profile
[{:keys [profile-id] :as params}]
(db/with-atomic [conn db/pool]
(p/let [prof (-> (retrieve-profile conn profile-id)
(p/then' su/raise-not-found-if-nil)
(p/then' strip-private-attrs)
(p/then' #(images/resolve-media-uris % [:photo :photo-uri])))
addt (retrieve-additional-data conn profile-id)]
(merge prof addt))))
(defn retrieve-profile
[conn id]
(p/let [prof (-> (retrieve-profile-data conn id)
(p/then' su/raise-not-found-if-nil)
(p/then' strip-private-attrs)
(p/then' #(images/resolve-media-uris % [:photo :photo-uri])))
addt (retrieve-additional-data conn id)]
(merge prof addt)))
;; --- Attrs Helpers

View 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

View file

@ -1,3 +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"/>
<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>

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 936 B

View file

@ -25,7 +25,7 @@
flex-shrink: 0;
}
&.btn-small {
font-size: $fs12;
font-size: $fs13;
padding: .7rem 1rem;
line-height: 1.15;
}

View file

@ -45,7 +45,7 @@
@import 'main/partials/main-bar';
@import 'main/partials/workspace';
@import 'main/partials/workspace-bar';
@import 'main/partials/workspace-header';
@import 'main/partials/workspace-libraries';
@import 'main/partials/tool-bar';
@import 'main/partials/project-bar';
@ -71,6 +71,7 @@
@import 'main/partials/debug-icons-preview';
@import 'main/partials/editable-label';
@import 'main/partials/tab-container';
@import "main/partials/zoom-widget";
@import "main/partials/viewer-header";
@import "main/partials/viewer-thumbnails";
@import "main/partials/viewer";

View file

@ -9,6 +9,10 @@
z-index: 12;
justify-content: space-between;
a {
font-size: $fs13;
}
.main-icon {
align-items: center;
background-color: $color-gray-60;
@ -85,9 +89,13 @@
align-items: center;
display: flex;
width: 300px;
justify-content: space-between;
justify-content: flex-end;
position: relative;
> * {
margin-left: $big;
}
.btn-share {
display: flex;
align-items: center;
@ -107,6 +115,10 @@
padding: 0.4rem 1rem;
}
.btn-primary.btn-small {
height: 25px;
}
.btn-fullscreen {
align-items: center;
background-color: $color-gray-60;
@ -134,23 +146,25 @@
}
.share-link-dropdown {
position: absolute;
left: -180px;
top: 45px;
background-color: $color-gray-50;
background-color: $color-white;
border-radius: $br-small;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
display: flex;
flex-direction: column;
left: -180px;
position: absolute;
padding: 1rem;
top: 45px;
width: 400px;
.share-link-title {
font-size: 18px;
color: $color-black;
font-size: $fs15;
padding-bottom: 1rem;
}
.share-link-subtitle {
color: $color-gray-40;
padding-bottom: 1rem;
}
@ -168,111 +182,50 @@
}
.share-link-input {
display: flex;
justify-content: space-between;
padding: $small;
align-items: center;
border: 1px solid $color-gray-30;
border: 1px solid $color-gray-20;
border-radius: 3px;
display: flex;
height: 40px;
justify-content: space-between;
margin-bottom: 1rem;
padding: 9px $small;
overflow: hidden;
.link {
color: $color-gray-50;
line-height: 1.5;
user-select: all;
overflow: hidden;
}
svg {
width: 20px;
height: 20px;
fill: $color-gray-20;
stroke: $color-gray-20;
.link-button {
color: $color-primary-dark;
cursor: pointer;
flex-shrink: 0;
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 {
cursor: pointer;
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%;
}
}
.zoom-dropdown {
left : 150px;
top: 45px;
}
.users-zone {

View file

@ -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;
}
}

View 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;
}
}
}
}

View file

@ -183,3 +183,28 @@
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;
}
}

View 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;
}
}
}
}

View file

@ -39,6 +39,7 @@
(def folder (icon-xref :folder))
(def folder-zip (icon-xref :folder-zip))
(def full-screen (icon-xref :full-screen))
(def full-screen-off (icon-xref :full-screen-off))
(def grid (icon-xref :grid))
(def grid-snap (icon-xref :grid-snap))
(def icon-set (icon-xref :icon-set))
@ -103,7 +104,7 @@
{::mf/wrap-props false}
[props]
[: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)
[:div.icon-item {:key key}
(deref val)

View file

@ -18,23 +18,25 @@
;; --- Common Specs
(s/def ::id uuid?)
(s/def ::fullname string?)
(s/def ::id ::us/uuid)
(s/def ::fullname ::us/string)
(s/def ::email ::us/email)
(s/def ::password string?)
(s/def ::language string?)
(s/def ::photo string?)
(s/def ::created-at inst?)
(s/def ::password-1 string?)
(s/def ::password-2 string?)
(s/def ::password-old string?)
(s/def ::password ::us/string)
(s/def ::language ::us/string)
(s/def ::photo ::us/string)
(s/def ::created-at ::us/inst)
(s/def ::password-1 ::us/string)
(s/def ::password-2 ::us/string)
(s/def ::password-old ::us/string)
(s/def ::lang (s/nilable ::us/string))
(s/def ::profile
(s/keys :req-un [::id
(s/keys :req-un [::id]
:opt-un [::created-at
::fullname
::photo
::email
::created-at
::photo]))
::lang]))
;; --- Profile Fetched

View file

@ -41,7 +41,7 @@
(declare bundle-fetched)
(defn initialize
[page-id]
[page-id share-token]
(ptk/reify ::initialize
ptk/UpdateEvent
(update [_ state]
@ -49,18 +49,21 @@
ptk/WatchEvent
(watch [_ state stream]
(rx/of (fetch-bundle page-id)))))
(rx/of (fetch-bundle page-id share-token)))))
;; --- Data Fetching
(defn fetch-bundle
[page-id]
[page-id share-token]
(ptk/reify ::fetch-file
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :viewer-bundle {:page-id page-id})
(rx/map bundle-fetched)))))
(let [params (cond-> {:page-id page-id}
(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
[page]

View file

@ -5,7 +5,7 @@
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; 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
"A collection of derived refs."

View file

@ -101,12 +101,6 @@
:profile-recovery
[:& 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-password)
[:& settings/settings {:route route}]
@ -126,6 +120,14 @@
:dashboard-library-palettes-index)
[:& 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
(let [project-id (uuid (get-in route [:params :path :project-id]))
file-id (uuid (get-in route [:params :path :file-id]))

View file

@ -96,8 +96,11 @@
(l/derive st/state)))
(mf/defc viewer-page
[{:keys [page-id index] :as props}]
(mf/use-effect (mf/deps page-id) #(st/emit! (dv/initialize page-id)))
[{:keys [page-id index token] :as props}]
(mf/use-effect
(mf/deps page-id token)
#(st/emit! (dv/initialize page-id token)))
(let [data (mf/deref viewer-data-ref)
local (mf/deref viewer-local-ref)]
(when data

View file

@ -17,43 +17,18 @@
[uxbox.builtins.icons :as i]
[uxbox.main.store :as st]
[uxbox.main.ui.components.dropdown :refer [dropdown]]
[uxbox.main.ui.workspace.header :refer [zoom-widget]]
[uxbox.main.data.viewer :as dv]
[uxbox.main.refs :as refs]
[uxbox.util.data :refer [classnames]]
[uxbox.util.dom :as dom]
[uxbox.util.uuid :as uuid]
[uxbox.util.i18n :as i18n :refer [t tr]]
[uxbox.util.math :as mth]
[uxbox.util.router :as rt])
(:import goog.events.EventType
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
[{:keys [page] :as props}]
@ -64,12 +39,11 @@
create #(st/emit! dv/create-share-link)
delete #(st/emit! dv/delete-share-link)
href (.-href js/location)]
[:*
[:span.btn-share.tooltip.tooltip-bottom
[:span.btn-primary.btn-small
{:alt "Share link"
:on-click #(swap! show-dropdown? not)}
i/exit]
"Share link"]
[:& dropdown {:show @show-dropdown?
:on-close #(swap! show-dropdown? not)
@ -78,28 +52,35 @@
[:span.share-link-title "Share link"]
[:div.share-link-input
(if (string? token)
[:span.link (str href "&" token)]
[:span "Share link will apear here"])
i/chain]
[:span.link (str href "&token=" token)]
[:span.link-placeholder "Share link will apear here"])
[:span.link-button "Copy link"]]
[:span.share-link-subtitle "Anyone with the link will have access"]
[:div.share-link-buttons
(if (string? token)
[:button.btn-delete {:on-click delete} "Remove link"]
[:button.btn-primary {:on-click create} "Create link"])]]]]))
(mf/defc header
[{:keys [data index local fullscreen? toggle-fullscreen] :as props}]
(let [{:keys [project file page frames]} data
total (count frames)
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
{:project-id (get-in data [:project :id])
:file-id (get-in data [:file :id])}
{:page-id (get-in data [:page :id])}))]
{:project-id project-id
:file-id file-id}
{:page-id page-id}))]
[:header.viewer-header
[:div.main-icon
[:a i/logo-icon]]
[:a {:on-click on-edit} i/logo-icon]]
[:div.sitemap-zone {:alt (tr "header.sitemap")
:on-click on-click}
@ -112,13 +93,25 @@
[:span.counters (str (inc index) " / " total)]]
[:div.options-zone
[:& share-link {:page (:page data)}]
[:span.btn-primary {:on-click on-edit} "Edit page"]
[:& zoom-widget {:zoom (:zoom local)}]
(when-not anonymous?
[:& share-link {:page (:page data)}])
(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
{:alt "Full screen"
{:alt "Full Screen"
:on-click toggle-fullscreen}
i/full-screen]
(if fullscreen?
i/full-screen-off
i/full-screen)]
]]))

View file

@ -30,33 +30,38 @@
(mf/defc zoom-widget
{:wrap [mf/memo]}
[props]
(let [zoom (mf/deref refs/selected-zoom)
show-dropdown? (mf/use-state false)
increase #(st/emit! dw/increase-zoom)
decrease #(st/emit! dw/decrease-zoom)
zoom-to-50 #(st/emit! dw/zoom-to-50)
zoom-to-100 #(st/emit! dw/reset-zoom)
zoom-to-200 #(st/emit! dw/zoom-to-200)]
[:div.zoom-input
[:span.add-zoom {:on-click decrease} "-"]
[:div {: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%" [:span "Shift + 0"]]
[:li {:on-click zoom-to-100}
"Zoom to 100%" [:span "Shift + 1"]]
[:li {:on-click zoom-to-200}
"Zoom to 200%" [:span "Shift + 2"]]]]]
[:span.remove-zoom {:on-click increase} "+"]]))
[{:keys [zoom
on-increase
on-decrease
on-zoom-to-50
on-zoom-to-100
on-zoom-to-200]
: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 {: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 on-increase}
"Zoom in" [:span "+"]]
[:li {:on-click on-decrease}
"Zoom out" [:span "-"]]
[:li {:on-click on-zoom-to-50}
"Zoom to 50%"]
[: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
@ -77,7 +82,7 @@
[props]
(let [profile (mf/deref refs/profile)
users (mf/deref refs/workspace-users)]
[:ul.user-multi
[:ul.active-users
[:& user-widget {:user profile :self? true}]
(for [id (->> (:active users)
(remove #(= % (:id profile))))]
@ -85,16 +90,22 @@
:key id}])]))
(mf/defc menu
[{:keys [layout] :as props}]
[{:keys [layout project file] :as props}]
(let [show-menu? (mf/use-state false)
toggle-sitemap #(st/emit! (dw/toggle-layout-flag :sitemap))
locale (i18n/use-locale)]
[:*
[:div.menu-btn {:on-click #(reset! show-menu? true)} i/actions]
[:div.menu-section
[: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?
:on-close #(reset! show-menu? false)}
[:ul.workspace-menu
[:ul.menu
[:li {:on-click #(st/emit! (dw/toggle-layout-flag :rules))}
[:span i/ruler]
[:span
@ -139,28 +150,33 @@
(mf/defc header
[{:keys [page file layout project] :as props}]
(let [go-to-dashboard #(st/emit! (rt/nav :dashboard-team {:team-id "self"}))
toggle-sitemap #(st/emit! (dw/toggle-layout-flag :sitemap))
(let [locale (i18n/use-locale)
go-to-dashboard #(st/emit! (rt/nav :dashboard-team {:team-id "self"}))
zoom (mf/deref refs/selected-zoom)
locale (i18n/use-locale)
router (mf/deref router-ref)
view-url (rt/resolve router :viewer {:page-id (:id page)} {:index 0})]
[:header.workspace-bar
[:header.workspace-header
[:div.main-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")
:class (classnames :selected (contains? layout :sitemap))
:on-click toggle-sitemap}
[:span.project-name (:name project) " /"]
[:span (:name file)]]
[:div.workspace-options
[:div.users-section
[:& 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]]))