Merge pull request #2 from uxbox/sort-and-filter-projects

Sort and filter projects
This commit is contained in:
2016-02-18 20:19:42 +01:00
commit bb1222116d
7 changed files with 171 additions and 35 deletions

View File

@ -28,22 +28,44 @@
} }
.dashboard-search { .dashboard-search {
cursor: pointer; align-items: center;
margin-left: $big; display: flex;
margin-left: $small;
svg { .input-text {
fill: $color-gray-dark; background: rgba(255,255,255,.4);
height: 20px; border: 0;
width: 20px; color: $dark-ui-text;
padding: 4px 8px;
margin: 0;
max-width: 160px;
}
.clear-search {
align-items: center;
background: rgba(255,255,255,.4);
cursor: pointer;
display: flex;
height: 28px;
padding: 0 5px;
svg {
fill: $light-ui-icons;
height: 15px;
transform: rotate(45deg);
width: 15px;
&:hover {
fill: $color-danger;
}
&:hover {
fill: $color-gray-darker;
} }
} }
} }
&.library-gap { &.library-gap {
padding: $small $medium $small 270px; padding: $small $medium $small 270px;
} }

View File

@ -62,6 +62,39 @@
(-pr-writer [mv writer _] (-pr-writer [mv writer _]
(-write writer "#<event:u.d.d/initialize>")))) (-write writer "#<event:u.d.d/initialize>"))))
(defn set-project-ordering
[order]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(assoc-in state [:dashboard :project-order] order))
IPrintWithWriter
(-pr-writer [mv writer _]
(-write writer "#<event:u.d.d/set-project-ordering>"))))
(defn set-project-filtering
[term]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(assoc-in state [:dashboard :project-filter] term))
IPrintWithWriter
(-pr-writer [mv writer _]
(-write writer "#<event:u.d.d/set-project-filtering>"))))
(defn clear-project-filtering
[]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(assoc-in state [:dashboard :project-filter] ""))
IPrintWithWriter
(-pr-writer [mv writer _]
(-write writer "#<event:u.d.d/clear-project-filtering>"))))
(defn set-collection-type (defn set-collection-type
[type] [type]
{:pre [(contains? #{:builtin :own} type)]} {:pre [(contains? #{:builtin :own} type)]}

View File

@ -1,5 +1,6 @@
(ns uxbox.data.projects (ns uxbox.data.projects
(:require [bouncer.validators :as v] (:require [bouncer.validators :as v]
[cuerdas.core :as str]
[uxbox.rstore :as rs] [uxbox.rstore :as rs]
[uxbox.router :as r] [uxbox.router :as r]
[uxbox.state :as st] [uxbox.state :as st]
@ -57,6 +58,23 @@
(sort-by :created) (sort-by :created)
(into []))) (into [])))
(defn sort-projects-by
[ordering projs]
(case ordering
:name (sort-by :name projs)
:created (reverse (sort-by :created projs))
projs))
(defn contains-term?
[phrase term]
(str/contains? (str/lower phrase) (str/trim (str/lower term))))
(defn filter-projects-by
[term projs]
(if (str/blank? term)
projs
(filter #(contains-term? (:name %) term) projs)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Events ;; Events
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -34,7 +34,14 @@
(let [value (get-in +locales+ [+locale+ t] (name t)) (let [value (get-in +locales+ [+locale+ t] (name t))
plural (first (filter c? args)) plural (first (filter c? args))
args (mapv #(if (c? %) @% %) args) args (mapv #(if (c? %) @% %) args)
value (if vector? value (cond
(and (vector? value)
(= 3 (count value)))
(nth value (min 2 @plural))
(vector? value)
(if (= @plural 1) (first value) (second value)) (if (= @plural 1) (first value) (second value))
:else
value)] value)]
(apply str/format value args)))) (apply str/format value args))))

View File

@ -2,6 +2,15 @@
(defonce +locales+ (defonce +locales+
{"ds.projects" "PROJECTS" {"ds.projects" "PROJECTS"
"ds.num-projects" ["No projects"
"%s project"
"%s projects"]
"ds.project-ordering" "Sort by"
"ds.project-ordering.by-name" "name"
"ds.project-ordering.by-last-update" "last update"
"ds.project-ordering.by-creation-date" "creation date"
"ds.project-search.placeholder" "Search..."
"ds.elements" "ELEMENTS" "ds.elements" "ELEMENTS"
"ds.icons" "ICONS" "ds.icons" "ICONS"
"ds.colors" "COLORS" "ds.colors" "COLORS"

View File

@ -7,7 +7,8 @@
(defonce stream (defonce stream
(rs/init {:user {:fullname "Cirilla Fiona" (rs/init {:user {:fullname "Cirilla Fiona"
:avatar "http://lorempixel.com/50/50/"} :avatar "http://lorempixel.com/50/50/"}
:dashboard {} :dashboard {:project-order :name
:project-filter ""}
:workspace {} :workspace {}
:shapes-by-id {} :shapes-by-id {}
:elements-by-id {} :elements-by-id {}

View File

@ -3,10 +3,12 @@
[rum.core :as rum] [rum.core :as rum]
[cats.labs.lens :as l] [cats.labs.lens :as l]
[cuerdas.core :as str] [cuerdas.core :as str]
[uxbox.locales :as t :refer (tr)]
[uxbox.router :as r] [uxbox.router :as r]
[uxbox.rstore :as rs] [uxbox.rstore :as rs]
[uxbox.state :as s] [uxbox.state :as s]
[uxbox.time :as time] [uxbox.time :as time]
[uxbox.data.dashboard :as dd]
[uxbox.data.projects :as dp] [uxbox.data.projects :as dp]
[uxbox.data.workspace :as dw] [uxbox.data.workspace :as dw]
[uxbox.ui.icons :as i] [uxbox.ui.icons :as i]
@ -20,9 +22,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FIXME rename ;; FIXME rename
(def +ordering-options+ {:name "name" (def +ordering-options+ {:name "ds.project-ordering.by-name"
:last-updated "date updated" :created "ds.project-ordering.by-creation-date"})
:created "date created"})
(def +layouts+ {:mobile {:name "Mobile" (def +layouts+ {:mobile {:name "Mobile"
:id "mobile" :id "mobile"
@ -149,32 +150,75 @@
;; Menu ;; Menu
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (def ^:static menu-l (def ^:static menu-l
;; (as-> (l/select-keys [:projects]) $ (as-> (l/select-keys [:projects-by-id]) $
;; (l/focus-atom $ s/state))) (l/focus-atom $ s/state)))
(rum/defc project-sort-selector < rum/reactive (def ^:static project-ordering-l
[sort-order] (as-> (l/in [:dashboard :project-order]) $
nil) (l/focus-atom $ s/state)))
;; (let [sort-name (get project-orderings (rum/react sort-order))]
;; [:select.input-select (def ^:static project-filtering-l
;; {:on-change #(reset! sort-order (name->order (.-value (.-target %)))) (as-> (l/in [:dashboard :project-filter]) $
;; :value sort-name} (l/focus-atom $ s/state)))
;; (for [order (keys project-orderings)
;; :let [name (get project-orderings order)]] (defn project-sort-render
;; [:option {:key name} name])])) []
(let [ordering (rum/react project-ordering-l)
change-order #(rs/emit! (dd/set-project-ordering (keyword (.-value (.-target %)))))]
(html
[:div
[:span (tr "ds.project-ordering")]
[:select.input-select
{:on-change change-order
:value (name ordering)}
(for [option (keys +ordering-options+)
:let [option-id (get +ordering-options+ option)
option-value (name option)
option-text (tr option-id)]]
[:option
{:key option-id
:value option-value}
option-text])]])))
(def project-sorting
(mx/component
{:render project-sort-render
:name "project-sort-order"
:mixins [rum/reactive]}))
(defn project-search-render
[]
(let [change-term #(rs/emit! (dd/set-project-filtering (.-value (.-target %))))
clear-term #(rs/emit! (dd/clear-project-filtering))]
(html
[:form.dashboard-search
[:input.input-text
{:type "text"
:on-change change-term
:auto-focus true
:placeholder (tr "ds.project-search.placeholder")
:value (rum/react project-filtering-l)}]
[:div.clear-search
{:on-click clear-term}
i/close]])))
(def project-search
(mx/component
{:render project-search-render
:name "project-search"
:mixins [rum/reactive]}))
(defn menu-render (defn menu-render
[] []
(let [state {:projects []} #_(rum/react menu-l) (let [projects (rum/react menu-l)
pcount (count (:projects state))] pcount (count (:projects-by-id projects))] ;; FIXME: redundant project-by-id key
(html (html
[:section#dashboard-bar.dashboard-bar [:section#dashboard-bar.dashboard-bar
[:div.dashboard-info [:div.dashboard-info
[:span.dashboard-projects pcount " projects"] [:span.dashboard-projects (tr "ds.num-projects" (t/c pcount))]
[:span "Sort by"]] (project-sorting)
[:div.dashboard-search (project-search)]])))
i/search]])))
(def menu (def menu
(mx/component (mx/component
@ -235,14 +279,17 @@
(letfn [(on-click [e] (letfn [(on-click [e]
(dom/prevent-default e) (dom/prevent-default e)
(lightbox/open! :new-project))] (lightbox/open! :new-project))]
(let [state (rum/react grid-l)] (let [state (rum/react grid-l)
ordering (rum/react project-ordering-l)
filtering (rum/react project-filtering-l)
projects (dp/filter-projects-by filtering (vals (:projects-by-id state)))]
(html (html
[:section.dashboard-grid [:section.dashboard-grid
[:h2 "Your projects"] [:h2 "Your projects"]
[:div.dashboard-grid-content [:div.dashboard-grid-content
[:div.grid-item.add-project {:on-click on-click} [:div.grid-item.add-project {:on-click on-click}
[:span "+ New project"]] [:span "+ New project"]]
(for [item (vals (:projects-by-id state))] (for [item (dp/sort-projects-by ordering projects)]
(rum/with-key (project-item item) (:id item)))]])))) (rum/with-key (project-item item) (:id item)))]]))))
(def grid (def grid
@ -250,4 +297,3 @@
{:render grid-render {:render grid-render
:name "grid" :name "grid"
:mixins [rum/reactive]})) :mixins [rum/reactive]}))