mirror of
https://github.com/penpot/penpot.git
synced 2025-01-06 14:50:20 -05:00
🎉 Manage file images as assets
This commit is contained in:
parent
8f8dc80cad
commit
8c8b5887d6
14 changed files with 482 additions and 18 deletions
2
backend/scripts/psql.sh
Executable file
2
backend/scripts/psql.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
PGPASSWORD=$UXBOX_DATABASE_PASSWORD psql $UXBOX_DATABASE_URI -U $UXBOX_DATABASE_USERNAME
|
|
@ -133,6 +133,7 @@
|
|||
(declare create-file-image)
|
||||
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::image-id ::us/uuid)
|
||||
(s/def ::content ::imgs/upload)
|
||||
|
||||
(s/def ::add-file-image-from-url
|
||||
|
@ -189,6 +190,33 @@
|
|||
(images/resolve-urls :thumb-path :thumb-uri))))
|
||||
|
||||
|
||||
;; --- Mutation: Delete File Image
|
||||
|
||||
(declare mark-file-image-deleted)
|
||||
|
||||
(s/def ::delete-file-image
|
||||
(s/keys :req-un [::file-id ::image-id ::profile-id]))
|
||||
|
||||
(sm/defmutation ::delete-file-image
|
||||
[{:keys [file-id image-id profile-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(files/check-edition-permissions! conn profile-id file-id)
|
||||
|
||||
;; Schedule object deletion
|
||||
(tasks/submit! conn {:name "delete-object"
|
||||
:delay cfg/default-deletion-delay
|
||||
:props {:id image-id :type :file-image}})
|
||||
|
||||
(mark-file-image-deleted conn params)))
|
||||
|
||||
(defn mark-file-image-deleted
|
||||
[conn {:keys [image-id] :as params}]
|
||||
(db/update! conn :file-image
|
||||
{:deleted-at (dt/now)}
|
||||
{:id image-id})
|
||||
nil)
|
||||
|
||||
|
||||
;; --- Mutation: Import from collection
|
||||
|
||||
(declare copy-image)
|
||||
|
|
|
@ -169,7 +169,8 @@
|
|||
(def ^:private sql:file-images
|
||||
"select fi.*
|
||||
from file_image as fi
|
||||
where fi.file_id = ?")
|
||||
where fi.file_id = ?
|
||||
and fi.deleted_at is null")
|
||||
|
||||
(defn retrieve-file-images
|
||||
[conn {:keys [file-id] :as params}]
|
||||
|
|
|
@ -1358,6 +1358,87 @@
|
|||
"es" : "Alinear arriba"
|
||||
}
|
||||
},
|
||||
"workspace.assets.assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:144" ],
|
||||
"translations" : {
|
||||
"en" : "Assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Recursos"
|
||||
}
|
||||
},
|
||||
"workspace.assets.box-filter-all" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:154" ],
|
||||
"translations" : {
|
||||
"en" : "All assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Todos"
|
||||
}
|
||||
},
|
||||
"workspace.assets.box-filter-colors" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:156" ],
|
||||
"translations" : {
|
||||
"en" : "Colors",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Colores"
|
||||
}
|
||||
},
|
||||
"workspace.assets.box-filter-graphics" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:155" ],
|
||||
"translations" : {
|
||||
"en" : "Graphics",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Gráficos"
|
||||
}
|
||||
},
|
||||
"workspace.assets.colors" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:91" ],
|
||||
"translations" : {
|
||||
"en" : "Colors",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Colores"
|
||||
}
|
||||
},
|
||||
"workspace.assets.delete" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:83" ],
|
||||
"translations" : {
|
||||
"en" : "Delete",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Borrar"
|
||||
}
|
||||
},
|
||||
"workspace.assets.file-library" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:104" ],
|
||||
"translations" : {
|
||||
"en" : "File library",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Bilioteca del archivo"
|
||||
}
|
||||
},
|
||||
"workspace.assets.graphics" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:68" ],
|
||||
"translations" : {
|
||||
"en" : "Graphics",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Gráficos"
|
||||
}
|
||||
},
|
||||
"workspace.assets.search" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:147" ],
|
||||
"translations" : {
|
||||
"en" : "Search assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Buscar recursos"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.disable-dynamic-alignment" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:117" ],
|
||||
"translations" : {
|
||||
|
@ -2179,13 +2260,13 @@
|
|||
}
|
||||
},
|
||||
"workspace.sidebar.icons" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/icons.cljs:89" ],
|
||||
"translations" : {
|
||||
"en" : "Icons",
|
||||
"fr" : "Icône",
|
||||
"ru" : "Иконки",
|
||||
"es" : "Iconos"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.sidebar.sitemap" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:150" ],
|
||||
|
@ -2196,6 +2277,15 @@
|
|||
"es" : "Páginas"
|
||||
}
|
||||
},
|
||||
"workspace.toolbar.assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:105" ],
|
||||
"translations" : {
|
||||
"en" : "Assets (Ctrl + I)",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Recursos (Ctrl + I)"
|
||||
}
|
||||
},
|
||||
"workspace.toolbar.circle" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:64" ],
|
||||
"translations" : {
|
||||
|
@ -2206,7 +2296,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.color-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:108" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:113" ],
|
||||
"translations" : {
|
||||
"en" : "Color Palette (---)",
|
||||
"fr" : "Palette de couleurs (---)",
|
||||
|
@ -2242,13 +2332,13 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:100" ],
|
||||
"translations" : {
|
||||
"en" : "Libraries (Ctrl + Shift + L)",
|
||||
"fr" : "Librairies (Ctrl + Shift + L)",
|
||||
"ru" : "Библиотеки (Ctrl + Shift + L)",
|
||||
"es" : "Bibliotecas (Ctrl + Mays + L)"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.toolbar.path" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:88" ],
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
@import 'main/partials/sidebar-layers';
|
||||
@import 'main/partials/sidebar-sitemap';
|
||||
@import 'main/partials/sidebar-tools';
|
||||
@import 'main/partials/sidebar-assets';
|
||||
@import 'main/partials/tab-container';
|
||||
@import 'main/partials/tool-bar';
|
||||
@import 'main/partials/user-settings';
|
||||
|
|
143
frontend/resources/styles/main/partials/sidebar-assets.scss
Normal file
143
frontend/resources/styles/main/partials/sidebar-assets.scss
Normal file
|
@ -0,0 +1,143 @@
|
|||
// 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>
|
||||
|
||||
.assets-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.assets-bar-title {
|
||||
color: $color-gray-10;
|
||||
font-size: $fs14;
|
||||
margin: $small $small 0 $small;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
background-color: $color-gray-50;
|
||||
border: 1px solid $color-gray-30;
|
||||
color: $color-gray-10;
|
||||
font-size: $fs12;
|
||||
margin: $small $small 0 $small;
|
||||
padding: $x-small;
|
||||
|
||||
&:focus {
|
||||
color: lighten($color-gray-10, 8%);
|
||||
border-color: $color-primary !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $color-gray-20;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.input-select {
|
||||
background-color: $color-gray-50;
|
||||
color: $color-gray-10;
|
||||
border: 1px solid transparent;
|
||||
border-bottom-color: $color-gray-40;
|
||||
padding: $x-small $x-small 0 $x-small;
|
||||
margin: $small $small $medium $small;
|
||||
|
||||
&:focus {
|
||||
color: lighten($color-gray-10, 8%);
|
||||
}
|
||||
|
||||
option {
|
||||
color: $color-gray-60;
|
||||
background: $color-white;
|
||||
font-size: $fs11;
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-library {
|
||||
margin-right: $small;
|
||||
cursor: pointer;
|
||||
|
||||
&.open svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.asset-group {
|
||||
background-color: $color-gray-60;
|
||||
padding: $small;
|
||||
font-size: $fs11;
|
||||
color: $color-gray-20;
|
||||
|
||||
.group-title {
|
||||
display: flex;
|
||||
|
||||
& span {
|
||||
color: $color-gray-30;
|
||||
}
|
||||
}
|
||||
|
||||
.group-button {
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
|
||||
& svg {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
fill: #F0F0F0;
|
||||
}
|
||||
}
|
||||
|
||||
.group-grid {
|
||||
margin-top: $small;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: 7vh;
|
||||
column-gap: 0.5rem;
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.grid-cell {
|
||||
background-color: $color-white;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
& img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
background-color: $color-gray-60;
|
||||
font-size: $fs9;
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.grid-cell:hover {
|
||||
border: 1px solid $color-primary;
|
||||
|
||||
& .cell-name {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ $width-settings-bar: 15rem;
|
|||
}
|
||||
|
||||
.settings-bar-inside {
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
display: grid;
|
||||
grid-template-columns: 100%;
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
:sitemap-pages
|
||||
:layers
|
||||
:libraries
|
||||
:assets
|
||||
:document-history
|
||||
:colorpalette
|
||||
:element-options
|
||||
|
@ -74,9 +75,10 @@
|
|||
(s/def ::layout-flags (s/coll-of ::layout-flag))
|
||||
|
||||
(def default-layout
|
||||
#{:sitemap
|
||||
:sitemap-pages
|
||||
:layers
|
||||
#{;; :sitemap
|
||||
;; :sitemap-pages
|
||||
;; :layers
|
||||
:assets
|
||||
:element-options
|
||||
:rules
|
||||
:display-grid
|
||||
|
@ -305,7 +307,8 @@
|
|||
left-sidebar? (not (empty? (keep layout [:layers
|
||||
:sitemap
|
||||
:document-history
|
||||
:libraries])))
|
||||
:libraries
|
||||
:assets])))
|
||||
right-sidebar? (not (empty? (keep layout [:element-options])))]
|
||||
(update-in state [:workspace-local]
|
||||
assoc :left-sidebar? left-sidebar?
|
||||
|
@ -1434,8 +1437,10 @@
|
|||
|
||||
;; Persistence
|
||||
|
||||
(def fetch-images dwp/fetch-images)
|
||||
(def add-image-from-url dwp/add-image-from-url)
|
||||
(def upload-image dwp/upload-image)
|
||||
(def delete-file-image dwp/delete-file-image)
|
||||
(def rename-page dwp/rename-page)
|
||||
(def delete-page dwp/delete-page)
|
||||
(def create-empty-page dwp/create-empty-page)
|
||||
|
|
|
@ -430,6 +430,23 @@
|
|||
(update [_ state]
|
||||
(update state :workspace-images assoc (:id item) item))))
|
||||
|
||||
|
||||
;; --- Delete image
|
||||
|
||||
(defn delete-file-image
|
||||
[file-id image-id]
|
||||
(ptk/reify ::delete-file-image
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-images dissoc image-id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {:file-id file-id
|
||||
:image-id image-id}]
|
||||
(rp/mutation :delete-file-image params)))))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn purge-page
|
||||
|
|
|
@ -25,11 +25,15 @@
|
|||
(let [open? (gobj/get props "show")
|
||||
options (gobj/get props "options")
|
||||
is-selectable (gobj/get props "selectable")
|
||||
selected (gobj/get props "selected")]
|
||||
selected (gobj/get props "selected")
|
||||
top (gobj/get props "top")
|
||||
left (gobj/get props "left")]
|
||||
(when open?
|
||||
[:> dropdown' props
|
||||
[:div.context-menu {:class (classnames :is-open open?
|
||||
:is-selectable is-selectable)}
|
||||
:is-selectable is-selectable)
|
||||
:style {:top top
|
||||
:left left}}
|
||||
[:ul.context-menu-items
|
||||
(for [[action-name action-handler] options]
|
||||
[:li.context-menu-item {:class (classnames :is-selected (and selected (= action-name selected)))
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
(def picker (icon-xref :picker))
|
||||
(def pin (icon-xref :pin))
|
||||
(def play (icon-xref :play))
|
||||
(def plus (icon-xref :plus))
|
||||
(def radius (icon-xref :radius))
|
||||
(def recent (icon-xref :recent))
|
||||
(def redo (icon-xref :redo))
|
||||
|
|
|
@ -96,10 +96,15 @@
|
|||
:class (when (contains? layout :layers) "selected")
|
||||
:on-click #(st/emit! (dw/toggle-layout-flags :sitemap :layers))}
|
||||
i/layers]
|
||||
;; [:li.tooltip.tooltip-right
|
||||
;; {:alt (t locale "workspace.toolbar.libraries")
|
||||
;; :class (when (contains? layout :libraries) "selected")
|
||||
;; :on-click #(st/emit! (dw/toggle-layout-flags :libraries))}
|
||||
;; i/icon-set]
|
||||
[:li.tooltip.tooltip-right
|
||||
{:alt (t locale "workspace.toolbar.libraries")
|
||||
:class (when (contains? layout :libraries) "selected")
|
||||
:on-click #(st/emit! (dw/toggle-layout-flags :libraries))}
|
||||
{:alt (t locale "workspace.toolbar.assets")
|
||||
:class (when (contains? layout :assets) "selected")
|
||||
:on-click #(st/emit! (dw/toggle-layout-flags :assets))}
|
||||
i/icon-set]
|
||||
[:li.tooltip.tooltip-right
|
||||
{:alt "History"}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
[uxbox.main.ui.workspace.sidebar.layers :refer [layers-toolbox]]
|
||||
[uxbox.main.ui.workspace.sidebar.options :refer [options-toolbox]]
|
||||
[uxbox.main.ui.workspace.sidebar.sitemap :refer [sitemap-toolbox]]
|
||||
[uxbox.main.ui.workspace.sidebar.libraries :refer [libraries-toolbox]]))
|
||||
[uxbox.main.ui.workspace.sidebar.libraries :refer [libraries-toolbox]]
|
||||
[uxbox.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]))
|
||||
|
||||
;; --- Left Sidebar (Component)
|
||||
|
||||
|
@ -34,7 +35,9 @@
|
|||
(when (contains? layout :layers)
|
||||
[:& layers-toolbox {:page page}])
|
||||
(when (contains? layout :libraries)
|
||||
[:& libraries-toolbox])]])
|
||||
[:& libraries-toolbox])
|
||||
(when (contains? layout :assets)
|
||||
[:& assets-toolbox])]])
|
||||
|
||||
;; --- Right Sidebar (Component)
|
||||
|
||||
|
|
164
frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs
Normal file
164
frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs
Normal file
|
@ -0,0 +1,164 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.assets
|
||||
(:require
|
||||
[okulary.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.dom.dnd :as dnd]
|
||||
[uxbox.util.timers :as timers]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[uxbox.main.data.library :as dlib]
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
||||
|
||||
(defn matches-search
|
||||
[name search-term]
|
||||
(if (empty? search-term)
|
||||
true
|
||||
(let [st (str/trim (str/lower search-term))
|
||||
nm (str/trim (str/lower name))]
|
||||
(str/includes? nm st))))
|
||||
|
||||
(mf/defc graphics-box
|
||||
[{:keys [library-id images] :as props}]
|
||||
(let [state (mf/use-state {:menu-open false
|
||||
:top nil
|
||||
:left nil
|
||||
:image-id nil})
|
||||
|
||||
add-graphic #(println "añadir gráfico")
|
||||
|
||||
delete-graphic
|
||||
#(st/emit! (dw/delete-file-image library-id (:image-id @state)))
|
||||
|
||||
on-context-menu (fn [image-id]
|
||||
(fn [event]
|
||||
(let [pos (dom/get-client-position event)
|
||||
top (:y pos)
|
||||
left (- (:x pos) 20)]
|
||||
(dom/prevent-default event)
|
||||
(swap! state assoc :menu-open true
|
||||
:top top
|
||||
:left left
|
||||
:image-id image-id))))]
|
||||
|
||||
[:div.asset-group
|
||||
[:div.group-title
|
||||
(tr "workspace.assets.graphics")
|
||||
[:span (str "\u00A0(") (count images) ")"] ;; Unicode 00A0 is non-breaking space
|
||||
[:div.group-button {:on-click add-graphic} i/plus]]
|
||||
[:div.group-grid
|
||||
(for [image (sort-by :name images)]
|
||||
[:div.grid-cell {:key (:id image)
|
||||
:on-context-menu (on-context-menu (:id image))}
|
||||
[:img {:src (:thumb-uri image)}]
|
||||
[:div.cell-name (:name image)]])
|
||||
[:& context-menu
|
||||
{:selectable false
|
||||
:show (:menu-open @state)
|
||||
:on-close #(swap! state assoc :menu-open false)
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:options [[(tr "workspace.assets.delete") delete-graphic]]}]]
|
||||
]))
|
||||
|
||||
(mf/defc colors-box
|
||||
[{:keys [colors] :as props}]
|
||||
(let [add-color #(println "añadir color")]
|
||||
[:div.asset-group
|
||||
[:div.group-title
|
||||
(tr "workspace.assets.colors")
|
||||
[:div.group-button {:on-click add-color} i/plus]]]))
|
||||
|
||||
(mf/defc library-toolbox
|
||||
[{:keys [library-id images initial-open? search-term box-filter] :as props}]
|
||||
(let [open? (mf/use-state initial-open?)
|
||||
toggle-open #(swap! open? not)]
|
||||
[:div.tool-window
|
||||
[:div.tool-window-bar
|
||||
[:div.collapse-library
|
||||
{:class (classnames :open @open?)
|
||||
:on-click toggle-open}
|
||||
i/arrow-slide]
|
||||
[:span (tr "workspace.assets.file-library")]]
|
||||
(when @open?
|
||||
[:div.tool-window-content
|
||||
(when (or (= box-filter :all) (= box-filter :graphics))
|
||||
[:& graphics-box {:library-id library-id :images images}])
|
||||
(when (or (= box-filter :all) (= box-filter :colors))
|
||||
[:& colors-box {:colors {}}])])]))
|
||||
|
||||
(mf/defc assets-toolbox
|
||||
[]
|
||||
(let [team-id (-> refs/workspace-project mf/deref :team-id)
|
||||
file-id (-> refs/workspace-file mf/deref :id)
|
||||
file-images (mf/deref refs/workspace-images)
|
||||
|
||||
state (mf/use-state {:search-term ""
|
||||
:box-filter :all})
|
||||
|
||||
filtered-images (filter #(matches-search (:name %) (:search-term @state))
|
||||
(vals file-images))
|
||||
|
||||
on-search-term-change (fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(swap! state assoc :search-term value)))
|
||||
|
||||
on-box-filter-change (fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(d/read-string))]
|
||||
(swap! state assoc :box-filter value)))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps file-id)
|
||||
#(when file-id
|
||||
(st/emit! (dw/fetch-images file-id))))
|
||||
|
||||
[:div.assets-bar
|
||||
|
||||
[:div.tool-window
|
||||
[:div.tool-window-content
|
||||
[:div.assets-bar-title (tr "workspace.assets.assets")]
|
||||
|
||||
[:input.search-input
|
||||
{:placeholder (tr "workspace.assets.search")
|
||||
:type "text"
|
||||
:value (:search-term @state)
|
||||
:on-change on-search-term-change}]
|
||||
|
||||
[:select.input-select {:value (:box-filter @state)
|
||||
:on-change on-box-filter-change}
|
||||
[:option {:value ":all"} (tr "workspace.assets.box-filter-all")]
|
||||
[:option {:value ":graphics"} (tr "workspace.assets.box-filter-graphics")]
|
||||
[:option {:value ":colors"} (tr "workspace.assets.box-filter-colors")]]
|
||||
]]
|
||||
|
||||
[:& library-toolbox {:library-id file-id
|
||||
:images filtered-images
|
||||
:initial-open? true
|
||||
:search-term (:search-term @state)
|
||||
:box-filter (:box-filter @state)}]]))
|
||||
|
Loading…
Reference in a new issue