diff --git a/frontend/resources/styles/main/partials/viewer-header.scss b/frontend/resources/styles/main/partials/viewer-header.scss index 210d244d7..130274e78 100644 --- a/frontend/resources/styles/main/partials/viewer-header.scss +++ b/frontend/resources/styles/main/partials/viewer-header.scss @@ -84,8 +84,24 @@ .options-zone { align-items: center; display: flex; - width: 250px; + width: 300px; justify-content: space-between; + position: relative; + + .btn-share { + display: flex; + align-items: center; + justify-content: center; + width: 25px; + height: 25px; + cursor: pointer; + + svg { + fill: $color-gray-20; + width: 20px; + height: 20px; + } + } .btn-primary { padding: 0.4rem 1rem; @@ -117,6 +133,63 @@ } } + .share-link-dropdown { + position: absolute; + left: -180px; + top: 45px; + + background-color: $color-gray-50; + display: flex; + flex-direction: column; + + padding: 1rem; + width: 400px; + + .share-link-title { + font-size: 18px; + padding-bottom: 1rem; + } + + .share-link-subtitle { + padding-bottom: 1rem; + } + + .share-link-buttons { + display: flex; + justify-content: center; + align-items: center; + + .btn-delete, + .btn-primary { + width: 50%; + padding: $small; + } + + } + + .share-link-input { + display: flex; + justify-content: space-between; + padding: $small; + align-items: center; + border: 1px solid $color-gray-30; + border-radius: 3px; + margin-bottom: 1rem; + + .link { + user-select: all; + } + + svg { + width: 20px; + height: 20px; + fill: $color-gray-20; + stroke: $color-gray-20; + } + } + + } + .zoom-widget { cursor: pointer; diff --git a/frontend/src/uxbox/main/data/viewer.cljs b/frontend/src/uxbox/main/data/viewer.cljs index aba8ed40e..26fe30479 100644 --- a/frontend/src/uxbox/main/data/viewer.cljs +++ b/frontend/src/uxbox/main/data/viewer.cljs @@ -19,6 +19,7 @@ [uxbox.common.pages :as cp] [uxbox.common.data :as d] [uxbox.common.exceptions :as ex] + [uxbox.util.router :as rt] [uxbox.util.uuid :as uuid])) ;; --- Specs @@ -44,7 +45,7 @@ (ptk/reify ::initialize ptk/UpdateEvent (update [_ state] - (assoc state :viewer-local {:zoom 1})) + (assoc state :viewer-local {:zoom 1 :page-id page-id})) ptk/WatchEvent (watch [_ state stream] @@ -57,7 +58,7 @@ (ptk/reify ::fetch-file ptk/WatchEvent (watch [_ state stream] - (->> (rp/query :viewer-bundle-by-page-id {:page-id page-id}) + (->> (rp/query :viewer-bundle {:page-id page-id}) (rx/map bundle-fetched))))) @@ -85,6 +86,26 @@ :images images :frames frames}))))) +(def create-share-link + (ptk/reify ::create-share-link + ptk/WatchEvent + (watch [_ state stream] + (prn "create-share-link") + (let [id (get-in state [:viewer-local :page-id])] + (->> (rp/mutation :generate-page-share-token {:id id}) + (rx/map (fn [{:keys [share-token]}] + #(assoc-in % [:viewer-data :page :share-token] share-token)))))))) + +(def delete-share-link + (ptk/reify ::delete-share-link + ptk/WatchEvent + (watch [_ state stream] + (prn "delete-share-link") + (let [id (get-in state [:viewer-local :page-id])] + (->> (rp/mutation :clear-page-share-token {:id id}) + (rx/map (fn [_] + #(assoc-in % [:viewer-data :page :share-token] nil)))))))) + ;; --- Zoom Management (def increase-zoom @@ -131,6 +152,31 @@ (update [_ state] (update-in state [:viewer-local :show-thumbnails] not)))) +(def select-prev-frame + (ptk/reify ::select-prev-frame + ptk/WatchEvent + (watch [_ state stream] + (let [route (:route state) + qparams (get-in route [:params :query]) + pparams (get-in route [:params :path]) + index (d/parse-integer (:index qparams))] + (when (pos? index) + (rx/of (rt/nav :viewer pparams (assoc qparams :index (dec index))))))))) + +(def select-next-frame + (ptk/reify ::select-prev-frame + ptk/WatchEvent + (watch [_ state stream] + (let [route (:route state) + qparams (get-in route [:params :query]) + pparams (get-in route [:params :path]) + index (d/parse-integer (:index qparams)) + + total (count (get-in state [:viewer-data :frames]))] + (when (< index (dec total)) + (rx/of (rt/nav :viewer pparams (assoc qparams :index (inc index))))))))) + + ;; --- Shortcuts (def shortcuts @@ -138,4 +184,6 @@ "-" #(st/emit! decrease-zoom) "shift+0" #(st/emit! zoom-to-50) "shift+1" #(st/emit! reset-zoom) - "shift+2" #(st/emit! zoom-to-200)}) + "shift+2" #(st/emit! zoom-to-200) + "left" #(st/emit! select-prev-frame) + "right" #(st/emit! select-next-frame)}) diff --git a/frontend/src/uxbox/main/ui.cljs b/frontend/src/uxbox/main/ui.cljs index 2d6304b3a..8eb0cb911 100644 --- a/frontend/src/uxbox/main/ui.cljs +++ b/frontend/src/uxbox/main/ui.cljs @@ -50,7 +50,7 @@ ["/profile" :settings-profile] ["/password" :settings-password]] - ["/view/:page-id/:index" :viewer] + ["/view/:page-id" :viewer] ["/not-found" :not-found] (when *assert* @@ -102,7 +102,7 @@ [:& profile-recovery-page] :viewer - (let [index (d/parse-integer (get-in route [:params :path :index])) + (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}]) diff --git a/frontend/src/uxbox/main/ui/viewer/header.cljs b/frontend/src/uxbox/main/ui/viewer/header.cljs index 9cd273cb8..4964ed707 100644 --- a/frontend/src/uxbox/main/ui/viewer/header.cljs +++ b/frontend/src/uxbox/main/ui/viewer/header.cljs @@ -55,6 +55,39 @@ "Zoom to 200%"]]]] [:span.remove-zoom {:on-click increase} "+"]])) +(mf/defc share-link + [{:keys [page] :as props}] + (let [show-dropdown? (mf/use-state false) + dropdown-ref (mf/use-ref) + token (:share-token page) + + create #(st/emit! dv/create-share-link) + delete #(st/emit! dv/delete-share-link) + href (.-href js/location)] + + [:* + [:span.btn-share.tooltip.tooltip-bottom + {:alt "Share link" + :on-click #(swap! show-dropdown? not)} + i/exit] + + [:& dropdown {:show @show-dropdown? + :on-close #(swap! show-dropdown? not) + :container dropdown-ref} + [:div.share-link-dropdown {:ref dropdown-ref} + [: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.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 @@ -79,10 +112,13 @@ [: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)}] [:span.btn-fullscreen.tooltip.tooltip-bottom {:alt "Full screen" :on-click toggle-fullscreen} - i/full-screen]]])) + i/full-screen] + ]])) + diff --git a/frontend/src/uxbox/main/ui/viewer/thumbnails.cljs b/frontend/src/uxbox/main/ui/viewer/thumbnails.cljs index b21fea9bc..84443cae1 100644 --- a/frontend/src/uxbox/main/ui/viewer/thumbnails.cljs +++ b/frontend/src/uxbox/main/ui/viewer/thumbnails.cljs @@ -133,8 +133,7 @@ on-item-click (fn [event index] (compare-and-set! selected false true) - (st/emit! (rt/nav :viewer {:page-id page-id - :index index})) + (st/emit! (rt/nav :viewer {:page-id page-id} {:index index})) (when @expanded? (on-close)))] [:& dropdown' {:on-close on-close diff --git a/frontend/src/uxbox/main/ui/workspace/header.cljs b/frontend/src/uxbox/main/ui/workspace/header.cljs index 311a04be3..10bd1dc65 100644 --- a/frontend/src/uxbox/main/ui/workspace/header.cljs +++ b/frontend/src/uxbox/main/ui/workspace/header.cljs @@ -143,7 +143,7 @@ toggle-sitemap #(st/emit! (dw/toggle-layout-flag :sitemap)) locale (i18n/use-locale) 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 [:div.main-icon [:a {:on-click go-to-dashboard} i/logo-icon]]