mirror of
https://github.com/penpot/penpot.git
synced 2025-08-04 05:28:19 +02:00
WIP
This commit is contained in:
parent
7b8f241d41
commit
2663acf224
6 changed files with 281 additions and 120 deletions
|
@ -13,15 +13,18 @@
|
|||
(defn app-render
|
||||
[own]
|
||||
(let [{:keys [location location-params] :as state} (rum/react state)]
|
||||
(case location
|
||||
:auth/login (ui.u/login)
|
||||
;; :auth/register (u/register)
|
||||
;; :auth/recover (u/recover-password)
|
||||
:main/dashboard (ui.d/dashboard)
|
||||
;; :main/project (w/workspace conn location-params)
|
||||
;; :main/page (w/workspace conn location-params))))
|
||||
nil
|
||||
)))
|
||||
(html
|
||||
[:section
|
||||
(lb/lightb
|
||||
(case location
|
||||
:auth/login (ui.u/login)
|
||||
;; :auth/register (u/register)
|
||||
;; :auth/recover (u/recover-password)
|
||||
:main/dashboard (ui.d/dashboard)
|
||||
;; :main/project (w/workspace conn location-params)
|
||||
;; :main/page (w/workspace conn location-params))))
|
||||
nil
|
||||
)))
|
||||
|
||||
(def app
|
||||
(util/component {:render app-render
|
||||
|
|
|
@ -4,25 +4,16 @@
|
|||
[cuerdas.core :refer [trim]]
|
||||
[uxbox.util :as util]
|
||||
[uxbox.router :as r]
|
||||
[uxbox.ui.navigation :as nav]
|
||||
;; [uxbox.ui.mixins :as mx]
|
||||
[uxbox.ui.icons :as i]
|
||||
[uxbox.ui.users :as ui.u]
|
||||
;; [uxbox.ui.lightbox :refer [lightbox
|
||||
;; render-lightbox
|
||||
;; set-lightbox!
|
||||
;; close-lightbox!]]
|
||||
[uxbox.ui.dom :as dom]
|
||||
[uxbox.ui.header :as ui.h]
|
||||
[uxbox.ui.lightbox :as lightbox]
|
||||
;; [uxbox.ui.activity :refer [timeline]]
|
||||
[uxbox.ui.icons.dashboard :as icons]
|
||||
;; [uxbox.projects.queries :as q]
|
||||
;; [uxbox.projects.actions :as actions]
|
||||
[uxbox.time :refer [ago]]))
|
||||
|
||||
(def lightbox (constantly nil))
|
||||
(def render-lightbox (constantly nil))
|
||||
(def set-lightbox! (constantly nil))
|
||||
(def close-lightbox! (constantly nil))
|
||||
|
||||
;; Config
|
||||
;; TODO: i18nized names
|
||||
(def project-orderings {:project/name "name"
|
||||
|
@ -55,51 +46,52 @@
|
|||
|
||||
;; Views
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Lightbox
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn layout-input
|
||||
[layout new-project]
|
||||
[layout local]
|
||||
(let [human-name (get-in project-layouts [layout :name])
|
||||
id (str "project-" (get-in project-layouts [layout :id]))
|
||||
tag (str "input#" id)
|
||||
tag (keyword tag)]
|
||||
[[tag
|
||||
{:type "radio"
|
||||
:key id
|
||||
:name "project-layout"
|
||||
:value human-name
|
||||
:checked (= layout (:layout @new-project))
|
||||
:on-change #(swap! new-project merge {:layout layout
|
||||
:width (get-in project-layouts [layout :width])
|
||||
:height (get-in project-layouts [layout :height])})}]
|
||||
[:label
|
||||
{:value name
|
||||
:for id}
|
||||
human-name]]))
|
||||
{:type "radio"
|
||||
:key id
|
||||
:name "project-layout"
|
||||
:value human-name
|
||||
:checked (= layout (:layout @local))
|
||||
:on-change #(swap! local merge {:layout layout
|
||||
:width (get-in project-layouts [layout :width])
|
||||
:height (get-in project-layouts [layout :height])})}]
|
||||
[:label
|
||||
{:value name
|
||||
:for id}
|
||||
human-name]]))
|
||||
|
||||
(rum/defc layout-selector
|
||||
[new-project]
|
||||
(vec (cons :div.input-radio.radio-primary
|
||||
(mapcat #(layout-input % new-project) (keys project-layouts)))))
|
||||
(defn- layout-selector
|
||||
[local]
|
||||
(html
|
||||
[:div.input-radio.radio-primary
|
||||
(vec (cons :div.input-radio.radio-primary
|
||||
(mapcat #(layout-input % local) (keys project-layouts))))]))
|
||||
|
||||
(rum/defcs new-project-lightbox < (rum/local new-project-defaults :new-project)
|
||||
[{:keys [new-project]} conn]
|
||||
(let [{:keys [name width height layout]} @new-project]
|
||||
(defn- new-project-lightbox-render
|
||||
[own]
|
||||
(let [local (:rum/local own)
|
||||
width (:width @local)
|
||||
height (:height @local)]
|
||||
(html
|
||||
[:div.lightbox-body
|
||||
[:h3 "New project"]
|
||||
[:form
|
||||
{:on-submit (fn [e]
|
||||
(.preventDefault e)
|
||||
(let [new-project-attributes {:name (trim name)
|
||||
:width (int width)
|
||||
:height (int height)
|
||||
:layout layout}]
|
||||
;; (actions/create-project conn new-project-attributes)
|
||||
(close-lightbox!)))}
|
||||
[:form {:on-submit (constantly nil)}
|
||||
[:input#project-name.input-text
|
||||
{:placeholder "New project name"
|
||||
:type "text"
|
||||
:value name
|
||||
:auto-focus true
|
||||
:on-change #(swap! new-project assoc :name (.-value (.-target %)))}]
|
||||
{:placeholder "New project name"
|
||||
:type "text"
|
||||
:value name
|
||||
:auto-focus true
|
||||
:on-change #(swap! local assoc :name (.-value (.-target %)))}]
|
||||
[:div.project-size
|
||||
[:input#project-witdh.input-text
|
||||
{:placeholder "Width"
|
||||
|
@ -107,10 +99,10 @@
|
|||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value width
|
||||
:on-change #(swap! new-project assoc :width (.-value (.-target %)))}]
|
||||
:on-change #(swap! local assoc :width (.-value (.-target %)))}]
|
||||
[:a.toggle-layout
|
||||
{:href "#"
|
||||
:on-click #(swap! new-project assoc :width height :height width)}
|
||||
:on-click #(swap! local assoc :width width :height height)}
|
||||
i/toggle]
|
||||
[:input#project-height.input-text
|
||||
{:placeholder "Height"
|
||||
|
@ -118,9 +110,9 @@
|
|||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value height
|
||||
:on-change #(swap! new-project assoc :height (.-value (.-target %)))}]]
|
||||
:on-change #(swap! local assoc :height (.-value (.-target %)))}]]
|
||||
;; Layout selector
|
||||
(layout-selector new-project)
|
||||
(layout-selector local)
|
||||
;; Submit
|
||||
(when-not (empty? (trim name))
|
||||
[:input#project-btn.btn-primary
|
||||
|
@ -128,23 +120,30 @@
|
|||
:type "submit"}])]
|
||||
[:a.close
|
||||
{:href "#"
|
||||
:on-click #(close-lightbox!)}
|
||||
i/close]]))
|
||||
:on-click #(lightbox/close!)}
|
||||
i/close]])))
|
||||
|
||||
;; (defmethod render-lightbox :new-project
|
||||
;; [_ conn]
|
||||
;; (new-project-lightbox conn))
|
||||
;; (.preventDefault e)
|
||||
;; (let [new-project-attributes {:name (trim name)
|
||||
;; :width (int width)
|
||||
;; :height (int height)
|
||||
;; :layout layout}]
|
||||
;; ;; (actions/create-project conn new-project-attributes)
|
||||
;; (close-lightbox!)))}
|
||||
|
||||
(rum/defc header
|
||||
[]
|
||||
[:header#main-bar.main-bar
|
||||
[:div.main-logo
|
||||
(nav/link "/" i/logo)]
|
||||
(ui.u/user)])
|
||||
(def new-project-lightbox
|
||||
(util/component
|
||||
{:render new-project-lightbox-render
|
||||
:name "new-project-lightbox"
|
||||
:mixins [(rum/local new-project-defaults)]}))
|
||||
|
||||
(rum/defc project-count < rum/static
|
||||
[n]
|
||||
[:span.dashboard-projects n " projects"])
|
||||
(defmethod lightbox/render-lightbox :new-project
|
||||
[_]
|
||||
(new-project-lightbox))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Menu
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rum/defc project-sort-selector < rum/reactive
|
||||
[sort-order]
|
||||
|
@ -156,47 +155,57 @@
|
|||
:let [name (get project-orderings order)]]
|
||||
[:option {:key name} name])]))
|
||||
|
||||
(rum/defc dashboard-bar
|
||||
(rum/defc project-count < rum/static
|
||||
[n]
|
||||
[:span.dashboard-projects n " projects"])
|
||||
|
||||
(defn menu-render
|
||||
[]
|
||||
[:section#dashboard-bar.dashboard-bar
|
||||
(html
|
||||
[:section#dashboard-bar.dashboard-bar
|
||||
[:div.dashboard-info
|
||||
(project-count 0)
|
||||
[:span "Sort by"]
|
||||
(project-sort-selector (atom :name))]
|
||||
[:div.dashboard-search
|
||||
icons/search]])
|
||||
icons/search]]))
|
||||
|
||||
(rum/defc project-card < rum/static
|
||||
[conn
|
||||
{uuid :project/uuid
|
||||
last-update :project/last-updated
|
||||
name :project/name
|
||||
pages :project/pages
|
||||
comment-count :project/comment-count}]
|
||||
[:div.grid-item.project-th
|
||||
{:on-click #(r/go :project {:project-uuid uuid})
|
||||
:key uuid}
|
||||
[:h3
|
||||
name]
|
||||
[:span.project-th-update "Updated " (ago last-update)]
|
||||
[:div.project-th-actions
|
||||
[:div.project-th-icon.pages
|
||||
icons/page
|
||||
[:span pages]]
|
||||
[:div.project-th-icon.comments
|
||||
i/chat
|
||||
[:span comment-count]]
|
||||
[:div.project-th-icon.delete
|
||||
{:on-click #(do (.stopPropagation %)
|
||||
;; (actions/delete-project conn uuid)
|
||||
%)}
|
||||
icons/trash]]])
|
||||
(def menu
|
||||
(util/component
|
||||
{:render menu-render
|
||||
:name "dashboard-menu"}))
|
||||
|
||||
(rum/defc new-project < rum/static
|
||||
[]
|
||||
[:div.grid-item.add-project
|
||||
{:on-click #(set-lightbox! :new-project)}
|
||||
[:span "+ New project"]])
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Project Item
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn project-render
|
||||
[own project]
|
||||
(html
|
||||
[:div.grid-item.project-th {:on-click (constantly nil)
|
||||
:key (:uuid project)}
|
||||
[:h3 (:name project)]
|
||||
[:span.project-th-update
|
||||
(str "Updated " (ago (:last-update project)))]
|
||||
[:div.project-th-actions
|
||||
[:div.project-th-icon.pages
|
||||
icons/page
|
||||
[:span 0]]
|
||||
[:div.project-th-icon.comments
|
||||
i/chat
|
||||
[:span 0]]
|
||||
[:div.project-th-icon.delete
|
||||
{:on-click #(do
|
||||
(dom/stop-propagation %)
|
||||
;; (actions/delete-project conn uuid)
|
||||
%)}
|
||||
icons/trash]]]))
|
||||
|
||||
(def project
|
||||
(util/component
|
||||
{:render project-render
|
||||
:name "project"
|
||||
:mixins [rum/static]}))
|
||||
|
||||
;; (defn sorted-projects
|
||||
;; [projects sort-order]
|
||||
|
@ -205,26 +214,41 @@
|
|||
;; project-cards
|
||||
;; (reverse project-cards))))
|
||||
|
||||
(rum/defc dashboard-grid < rum/reactive
|
||||
[projects sort-order]
|
||||
[:section.dashboard-grid
|
||||
[:h2 "Your projects"]
|
||||
[:div.dashboard-grid-content
|
||||
(vec
|
||||
(concat [:div.dashboard-grid-content
|
||||
(new-project)]
|
||||
#_(sorted-projects projects
|
||||
(rum/react sort-order))))]])
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Grid
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn grid-render
|
||||
[own]
|
||||
(letfn [(on-click [e]
|
||||
(dom/prevent-default e)
|
||||
(lightbox/set! :new-project))]
|
||||
(html
|
||||
[:section.dashboard-grid
|
||||
[:h2 "Your projects"]
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-content
|
||||
[:div.grid-item.add-project {:on-click on-click}
|
||||
[:span "+ New project"]]]]])))
|
||||
|
||||
(def grid
|
||||
(util/component
|
||||
{:render grid-render
|
||||
:name "grid"
|
||||
:mixins [rum/reactive]}))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Main
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn dashboard-render
|
||||
[own]
|
||||
(html
|
||||
[:main.dashboard-main
|
||||
(header)
|
||||
(ui.h/header)
|
||||
[:section.dashboard-content
|
||||
#_(dashboard-bar sort-order @project-count)
|
||||
(dashboard-bar)
|
||||
(dashboard-grid [] (atom :name))]
|
||||
(menu)
|
||||
(grid)]
|
||||
#_(timeline conn)]))
|
||||
|
||||
|
||||
|
|
9
frontend/uxbox/ui/dom.cljs
Normal file
9
frontend/uxbox/ui/dom.cljs
Normal file
|
@ -0,0 +1,9 @@
|
|||
(ns uxbox.ui.dom)
|
||||
|
||||
(defn stop-propagation
|
||||
[e]
|
||||
(.stopPropagation e))
|
||||
|
||||
(defn prevent-default
|
||||
[e]
|
||||
(.preventDefault e))
|
25
frontend/uxbox/ui/header.cljs
Normal file
25
frontend/uxbox/ui/header.cljs
Normal file
|
@ -0,0 +1,25 @@
|
|||
(ns uxbox.ui.header
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[uxbox.util :as util]
|
||||
[uxbox.router :as r]
|
||||
[uxbox.ui.navigation :as nav]
|
||||
[uxbox.ui.icons :as i]
|
||||
[uxbox.ui.users :as ui.u]))
|
||||
|
||||
(defn header-render
|
||||
[own]
|
||||
(html
|
||||
[:header#main-bar.main-bar
|
||||
[:div.main-logo
|
||||
(nav/link "/" i/logo)]
|
||||
(ui.u/user)]))
|
||||
|
||||
(def ^:static header
|
||||
(util/component
|
||||
{:render header-render
|
||||
:name "header"
|
||||
:mixins [rum/static]}))
|
||||
|
||||
|
||||
|
39
frontend/uxbox/ui/keyboard.cljs
Normal file
39
frontend/uxbox/ui/keyboard.cljs
Normal file
|
@ -0,0 +1,39 @@
|
|||
(ns uxbox.ui.keyboard
|
||||
(:require [goog.events :as events])
|
||||
(:import [goog.events EventType KeyCodes]
|
||||
[goog.ui KeyboardShortcutHandler]))
|
||||
|
||||
|
||||
(defn is-keycode?
|
||||
[keycode]
|
||||
(fn [e]
|
||||
(= (.-keyCode e) keycode)))
|
||||
|
||||
(def esc? (is-keycode? 27))
|
||||
(def enter? (is-keycode? 13))
|
||||
|
||||
;; (def workspace-event-keys
|
||||
;; ["DELETE" "ESC" "CTRL+C" "CTRL+V" "CTRL+B" "CTRL+E" "CTRL+L" "SHIFT+Q"
|
||||
;; "SHIFT+W" "SHIFT+E" "CTRL+SHIFT+I" "CTRL+SHIFT+F" "CTRL+SHIFT+C"
|
||||
;; "CTRL+SHIFT+L" "CTRL+G" "CTRL+UP" "CTRL+DOWN" "CTRL+SHIFT+UP"
|
||||
;; "CTRL+SHIFT+DOWN" "SHIFT+I" "SHIFT+0" "SHIFT+O"])
|
||||
|
||||
;; ;; Mixins
|
||||
|
||||
;; (defn keyboard-keypress
|
||||
;; "A mixin for capture keyboard events."
|
||||
;; [event-keys]
|
||||
;; (let [handler (KeyboardShortcutHandler. js/document)]
|
||||
;; (doseq [shortcut event-keys]
|
||||
;; (.registerShortcut handler shortcut shortcut))
|
||||
|
||||
;; {:will-mount (fn [state]
|
||||
;; (events/listen handler
|
||||
;; KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED
|
||||
;; ws/on-workspace-keypress)
|
||||
;; state)
|
||||
;; :will-unmount (fn [state]
|
||||
;; (events/unlisten js/document
|
||||
;; EventType.KEYDOWN
|
||||
;; ws/on-workspace-keypress)
|
||||
;; state)}))
|
61
frontend/uxbox/ui/lightbox.cljs
Normal file
61
frontend/uxbox/ui/lightbox.cljs
Normal file
|
@ -0,0 +1,61 @@
|
|||
(ns uxbox.ui.lightbox
|
||||
(:require [rum.core :as rum]
|
||||
[uxbox.util :as util]
|
||||
[uxbox.ui.keyboard :as k]
|
||||
[goog.events :as events])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; State Management
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defonce +current+ (atom nil))
|
||||
|
||||
(defn set!
|
||||
[kind]
|
||||
(println "lightbox$set!" kind)
|
||||
(reset! +current+ kind))
|
||||
|
||||
(defn close!
|
||||
[]
|
||||
(reset! +current+ nil))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; UI
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defmulti render-lightbox identity)
|
||||
(defmethod render-lightbox :default [_] nil)
|
||||
|
||||
(defn- on-esc-clicked
|
||||
[e]
|
||||
(when (k/esc? e)
|
||||
(close!)))
|
||||
|
||||
(defn- lightbox-will-mount
|
||||
[state]
|
||||
(events/listen js/document
|
||||
EventType.KEYDOWN
|
||||
on-esc-clicked)
|
||||
state)
|
||||
|
||||
(defn- lightbox-will-umount
|
||||
[state]
|
||||
(events/unlisten js/document
|
||||
EventType.KEYDOWN
|
||||
on-esc-clicked)
|
||||
state)
|
||||
|
||||
(defn- lightbox-render
|
||||
[own]
|
||||
(let [name (rum/react +current+)]
|
||||
[:div.lightbox {:class (when (nil? name) "hide")}
|
||||
(render-lightbox name)]))
|
||||
|
||||
(def lightbox
|
||||
(util/component
|
||||
{:name "lightbox"
|
||||
:render lightbox-render
|
||||
:will-mount lightbox-will-mount
|
||||
:will-unmount lightbox-will-umount
|
||||
:mixins [rum/reactive]}))
|
Loading…
Add table
Add a link
Reference in a new issue