mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 16:21:57 -05:00
🎉 Link files to libraries
This commit is contained in:
parent
5ff0a723d5
commit
752038039c
22 changed files with 1080 additions and 318 deletions
|
@ -0,0 +1,15 @@
|
|||
CREATE TABLE file_library_rel (
|
||||
file_id uuid NOT NULL REFERENCES file(id) ON DELETE CASCADE,
|
||||
library_file_id uuid NOT NULL REFERENCES file(id) ON DELETE RESTRICT,
|
||||
|
||||
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
||||
|
||||
PRIMARY KEY (file_id, library_file_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE file_library_rel
|
||||
IS 'Relation between files and the shared library files they use (NM)';
|
||||
|
||||
CREATE INDEX file_library_rel__file_id__idx
|
||||
ON file_library_rel(file_id);
|
||||
|
|
@ -79,7 +79,11 @@
|
|||
|
||||
{:desc "Truncate & alter tokens tables"
|
||||
:name "0016-truncate-and-alter-tokens-table"
|
||||
:fn (mg/resource "migrations/0016-truncate-and-alter-tokens-table.sql")}]})
|
||||
:fn (mg/resource "migrations/0016-truncate-and-alter-tokens-table.sql")}
|
||||
|
||||
{:desc "Link files to libraries"
|
||||
:name "0017-link-files-to-libraries"
|
||||
:fn (mg/resource "migrations/0017-link-files-to-libraries.sql")}]})
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Entry point
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
{:id id}))
|
||||
|
||||
|
||||
;; --- Mutation: Delete Project File
|
||||
;; --- Mutation: Delete File
|
||||
|
||||
(declare mark-file-deleted)
|
||||
|
||||
|
@ -149,3 +149,47 @@
|
|||
{:id id})
|
||||
nil)
|
||||
|
||||
|
||||
;; --- Mutation: Link file to library
|
||||
|
||||
(declare link-file-to-library)
|
||||
|
||||
(s/def ::link-file-to-library
|
||||
(s/keys :req-un [::profile-id ::file-id ::library-id]))
|
||||
|
||||
(sm/defmutation ::link-file-to-library
|
||||
[{:keys [profile-id file-id library-id] :as params}]
|
||||
(when (= file-id library-id)
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-library
|
||||
:hint "A file cannot be linked to itself"))
|
||||
(db/with-atomic [conn db/pool]
|
||||
(files/check-edition-permissions! conn profile-id file-id)
|
||||
(link-file-to-library conn params)))
|
||||
|
||||
(defn- link-file-to-library
|
||||
[conn {:keys [file-id library-id] :as params}]
|
||||
(db/insert! conn :file-library-rel
|
||||
{:file-id file-id
|
||||
:library-file-id library-id}))
|
||||
|
||||
|
||||
;; --- Mutation: Unlink file from library
|
||||
|
||||
(declare unlink-file-from-library)
|
||||
|
||||
(s/def ::unlink-file-from-library
|
||||
(s/keys :req-un [::profile-id ::file-id ::library-id]))
|
||||
|
||||
(sm/defmutation ::unlink-file-from-library
|
||||
[{:keys [profile-id file-id library-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(files/check-edition-permissions! conn profile-id file-id)
|
||||
(unlink-file-from-library conn params)))
|
||||
|
||||
(defn- unlink-file-from-library
|
||||
[conn {:keys [file-id library-id] :as params}]
|
||||
(db/delete! conn :file-library-rel
|
||||
{:file-id file-id
|
||||
:library-file-id library-id}))
|
||||
|
||||
|
|
|
@ -148,32 +148,6 @@
|
|||
(mapv decode-row)))
|
||||
|
||||
|
||||
;; --- Query: Shared Files
|
||||
|
||||
(def ^:private sql:shared-files
|
||||
"select distinct
|
||||
f.*,
|
||||
array_agg(pg.id) over pages_w as pages,
|
||||
first_value(pg.data) over pages_w as data
|
||||
from file as f
|
||||
left join page as pg on (f.id = pg.file_id)
|
||||
where is_shared = true
|
||||
and f.deleted_at is null
|
||||
and pg.deleted_at is null
|
||||
window pages_w as (partition by f.id order by pg.ordering
|
||||
range between unbounded preceding
|
||||
and unbounded following)
|
||||
order by f.modified_at desc")
|
||||
|
||||
(s/def ::shared-files
|
||||
(s/keys :req-un [::profile-id]))
|
||||
|
||||
(sq/defquery ::shared-files
|
||||
[{:keys [profile-id] :as params}]
|
||||
(->> (db/exec! db/pool [sql:shared-files])
|
||||
(mapv decode-row)))
|
||||
|
||||
|
||||
;; --- Query: File Permissions
|
||||
|
||||
(def ^:private sql:file-permissions
|
||||
|
@ -236,6 +210,25 @@
|
|||
range between unbounded preceding
|
||||
and unbounded following)")
|
||||
|
||||
(defn retrieve-file
|
||||
[conn id]
|
||||
(let [row (db/exec-one! conn [sql:file id])]
|
||||
(when-not row
|
||||
(ex/raise :type :not-found))
|
||||
(decode-row row)))
|
||||
|
||||
(s/def ::file
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::file
|
||||
[{:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(check-edition-permissions! conn profile-id id)
|
||||
(retrieve-file conn id)))
|
||||
|
||||
|
||||
;; --- Query: File users
|
||||
|
||||
(def ^:private sql:file-users
|
||||
"select pf.id, pf.fullname, pf.photo
|
||||
from profile as pf
|
||||
|
@ -249,13 +242,6 @@
|
|||
inner join file as f on (p.id = f.project_id)
|
||||
where f.id = ?")
|
||||
|
||||
(defn retrieve-file
|
||||
[conn id]
|
||||
(let [row (db/exec-one! conn [sql:file id])]
|
||||
(when-not row
|
||||
(ex/raise :type :not-found))
|
||||
(decode-row row)))
|
||||
|
||||
(defn retrieve-file-users
|
||||
[conn id]
|
||||
(->> (db/exec! conn [sql:file-users id id])
|
||||
|
@ -270,14 +256,93 @@
|
|||
(check-edition-permissions! conn profile-id id)
|
||||
(retrieve-file-users conn id)))
|
||||
|
||||
(s/def ::file
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::file
|
||||
[{:keys [profile-id id] :as params}]
|
||||
;; --- Query: Shared Library Files
|
||||
|
||||
(def ^:private sql:shared-files
|
||||
"select distinct
|
||||
f.*,
|
||||
array_agg(pg.id) over pages_w as pages,
|
||||
first_value(pg.data) over pages_w as data,
|
||||
(select count(*) from color as c
|
||||
where c.file_id = f.id
|
||||
and c.deleted_at is null) as colors_count,
|
||||
(select count(*) from media_object as m
|
||||
where m.file_id = f.id
|
||||
and m.is_local = false
|
||||
and m.deleted_at is null) as graphics_count
|
||||
from file as f
|
||||
left join page as pg on (f.id = pg.file_id)
|
||||
where is_shared = true
|
||||
and f.deleted_at is null
|
||||
and pg.deleted_at is null
|
||||
window pages_w as (partition by f.id order by pg.ordering
|
||||
range between unbounded preceding
|
||||
and unbounded following)
|
||||
order by f.modified_at desc")
|
||||
|
||||
(s/def ::shared-files
|
||||
(s/keys :req-un [::profile-id]))
|
||||
|
||||
(sq/defquery ::shared-files
|
||||
[{:keys [profile-id] :as params}]
|
||||
(->> (db/exec! db/pool [sql:shared-files])
|
||||
(mapv decode-row)))
|
||||
|
||||
|
||||
;; --- Query: File Libraries used by a File
|
||||
|
||||
(def ^:private sql:file-libraries
|
||||
"select fl.*,
|
||||
array_agg(pg.id) over pages_w as pages,
|
||||
first_value(pg.data) over pages_w as data
|
||||
from file as fl
|
||||
left join page as pg on (fl.id = pg.file_id)
|
||||
inner join file_library_rel as flr on (flr.library_file_id = fl.id)
|
||||
where flr.file_id = ?
|
||||
and fl.deleted_at is null
|
||||
and pg.deleted_at is null
|
||||
window pages_w as (partition by fl.id order by pg.ordering
|
||||
range between unbounded preceding
|
||||
and unbounded following)")
|
||||
|
||||
(defn retrieve-file-libraries
|
||||
[conn file-id]
|
||||
(->> (db/exec! conn [sql:file-libraries file-id])
|
||||
(mapv decode-row)))
|
||||
|
||||
(s/def ::file-libraries
|
||||
(s/keys :req-un [::profile-id ::file-id]))
|
||||
|
||||
(sq/defquery ::file-libraries
|
||||
[{:keys [profile-id file-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(check-edition-permissions! conn profile-id id)
|
||||
(retrieve-file conn id)))
|
||||
(check-edition-permissions! conn profile-id file-id)
|
||||
(retrieve-file-libraries conn file-id)))
|
||||
|
||||
|
||||
;; --- Query: Single File Library
|
||||
|
||||
(def ^:private sql:file-library
|
||||
"select fl.*
|
||||
from file as fl
|
||||
where fl.id = ?")
|
||||
|
||||
(defn retrieve-file-library
|
||||
[conn file-id]
|
||||
(let [row (db/exec-one! conn [sql:file-library file-id])]
|
||||
(when-not row
|
||||
(ex/raise :type :not-found))
|
||||
row))
|
||||
|
||||
(s/def ::file-library
|
||||
(s/keys :req-un [::profile-id ::file-id]))
|
||||
|
||||
(sq/defquery ::file-library
|
||||
[{:keys [profile-id file-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(check-edition-permissions! conn profile-id file-id) ;; TODO: this should check read permissions
|
||||
(retrieve-file-library conn file-id)))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
|
|
@ -100,6 +100,15 @@
|
|||
[coll v]
|
||||
(index-of-pred coll #(= % v)))
|
||||
|
||||
(defn replace-by-id
|
||||
([value]
|
||||
(map (fn [item]
|
||||
(if (= (:id item) (:id value))
|
||||
value
|
||||
item))))
|
||||
([coll value]
|
||||
(sequence (replace-by-id value) coll)))
|
||||
|
||||
(defn remove-nil-vals
|
||||
"Given a map, return a map removing key-value
|
||||
pairs when value is `nil`."
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg height="500" viewBox="0 0 500 500.00001" width="500" xmlns="http://www.w3.org/2000/svg"><path d="m374.18867.0267054c-35.64828-.2594519-69.82413 17.0404356-93.20368 43.4592726-15.96943 15.815633-34.18905 30.514355-45.18713 50.405678-5.1515 18.457664 15.53601 39.058944 33.81154 31.036824 12.22641-5.78727 20.9306-16.63075 30.89383-25.454779 16.22461-15.903949 31.60842-34.624491 53.26814-43.214287 30.62802-9.50856 68.02579 2.749108 83.55033 31.696765 16.13296 27.355411 11.40609 65.900651-12.9823 86.952601-33.6878 33.49189-65.99089 68.54217-101.81764 99.77497-25.67623 17.23892-62.49311 13.96445-85.18151-6.89399-9.89211-7.80227-24.66431-13.50914-36.06589-5.38341-13.15171 8.62196-16.04732 29.62343-4.15345 40.55617 15.93267 16.29843 36.91504 27.64936 59.09307 32.78437 40.13279 9.48411 85.67216-1.55446 114.36469-32.06287 33.07787-32.27923 66.63084-64.14607 97.86433-98.23413 23.04904-23.96391 33.83451-58.70201 31.15623-91.46246-2.70232-43.764061-31.22711-84.958851-71.53209-102.670553-16.87008-7.7105388-35.48438-11.6840846-53.87847-11.2901716zm-159.2861 160.6206946c-39.01926-.33444-76.68538 19.58857-100.83485 49.88477-31.172069 33.41854-67.205805 62.36033-94.800257 98.98025-26.9880443 41.08393-25.4588562 98.63597 3.545885 138.48623 27.24324 38.81883 78.068962 59.33957 124.213102 49.59632 24.72587-4.46394 47.81335-17.32539 65.23405-35.18393 17.52414-16.41671 34.99703-33.22162 49.95378-51.99502 8.83127-16.43283-6.03228-38.57632-24.49974-37.35978-12.4053.64489-20.59493 11.5371-29.6011 18.68791-19.15239 17.81799-35.79382 39.82048-60.06572 51.03535-30.55108 10.5216-68.21902-1.2911-84.667542-29.78775-16.559305-26.43812-13.141765-64.30146 9.984965-85.87978 34.067387-34.21788 67.149797-69.52054 103.267867-101.61931 26.30278-18.27341 64.67227-14.35 87.64732 7.61083 10.00553 7.94798 25.88113 12.00271 36.36258 2.66107 12.25723-9.77484 13.27481-30.9153.40352-40.68432-22.71929-22.32063-54.40976-34.65193-86.14386-34.43284z" fill="#060606"/></svg>
|
||||
<svg height="500" viewBox="0 0 500 500.00001" width="500" xmlns="http://www.w3.org/2000/svg"><path d="m374.18867.0267054c-35.64828-.2594519-69.82413 17.0404356-93.20368 43.4592726-15.96943 15.815633-34.18905 30.514355-45.18713 50.405678-5.1515 18.457664 15.53601 39.058944 33.81154 31.036824 12.22641-5.78727 20.9306-16.63075 30.89383-25.454779 16.22461-15.903949 31.60842-34.624491 53.26814-43.214287 30.62802-9.50856 68.02579 2.749108 83.55033 31.696765 16.13296 27.355411 11.40609 65.900651-12.9823 86.952601-33.6878 33.49189-65.99089 68.54217-101.81764 99.77497-25.67623 17.23892-62.49311 13.96445-85.18151-6.89399-9.89211-7.80227-24.66431-13.50914-36.06589-5.38341-13.15171 8.62196-16.04732 29.62343-4.15345 40.55617 15.93267 16.29843 36.91504 27.64936 59.09307 32.78437 40.13279 9.48411 85.67216-1.55446 114.36469-32.06287 33.07787-32.27923 66.63084-64.14607 97.86433-98.23413 23.04904-23.96391 33.83451-58.70201 31.15623-91.46246-2.70232-43.764061-31.22711-84.958851-71.53209-102.670553-16.87008-7.7105388-35.48438-11.6840846-53.87847-11.2901716zm-159.2861 160.6206946c-39.01926-.33444-76.68538 19.58857-100.83485 49.88477-31.172069 33.41854-67.205805 62.36033-94.800257 98.98025-26.9880443 41.08393-25.4588562 98.63597 3.545885 138.48623 27.24324 38.81883 78.068962 59.33957 124.213102 49.59632 24.72587-4.46394 47.81335-17.32539 65.23405-35.18393 17.52414-16.41671 34.99703-33.22162 49.95378-51.99502 8.83127-16.43283-6.03228-38.57632-24.49974-37.35978-12.4053.64489-20.59493 11.5371-29.6011 18.68791-19.15239 17.81799-35.79382 39.82048-60.06572 51.03535-30.55108 10.5216-68.21902-1.2911-84.667542-29.78775-16.559305-26.43812-13.141765-64.30146 9.984965-85.87978 34.067387-34.21788 67.149797-69.52054 103.267867-101.61931 26.30278-18.27341 64.67227-14.35 87.64732 7.61083 10.00553 7.94798 25.88113 12.00271 36.36258 2.66107 12.25723-9.77484 13.27481-30.9153.40352-40.68432-22.71929-22.32063-54.40976-34.65193-86.14386-34.43284z"/></svg>
|
||||
|
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
3
frontend/resources/images/icons/libraries.svg
Normal file
3
frontend/resources/images/icons/libraries.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
|
||||
<path d="M188 37v425h50V37zM176 0c-14 0-25 11-25 25v450c0 14 11 25 25 25h75c14 0 25-11 25-25V165l103 318c5 13 19 20 32 16l72-23c13-5 20-19 16-32L391 111c-5-13-19-20-32-16l-72 23c-4 2-8 4-11 8V25c0-14-11-25-25-25zM38 137v325h50V137zm-13-37c-14 0-25 11-25 25v350c0 14 11 25 25 25h75c14 0 25-11 25-25V125c0-14-11-25-25-25zm386 359L311 150l48-15 100 309z" clip-rule="evenodd" fill-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 466 B |
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
},
|
||||
"auth.create-demo-profile" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:116", "src/uxbox/main/ui/auth/login.cljs:115" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:116", "src/uxbox/main/ui/auth/login.cljs:121" ],
|
||||
"translations" : {
|
||||
"en" : "Create demo account",
|
||||
"fr" : "Créer un compte de démonstration",
|
||||
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
},
|
||||
"auth.create-demo-profile-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:113", "src/uxbox/main/ui/auth/login.cljs:112" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:113", "src/uxbox/main/ui/auth/login.cljs:118" ],
|
||||
"translations" : {
|
||||
"en" : "Just wanna try it?",
|
||||
"fr" : "Vous voulez juste essayer?",
|
||||
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
},
|
||||
"auth.email-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:82", "src/uxbox/main/ui/auth/recovery_request.cljs:46", "src/uxbox/main/ui/auth/login.cljs:73" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:82", "src/uxbox/main/ui/auth/recovery_request.cljs:46", "src/uxbox/main/ui/auth/login.cljs:74" ],
|
||||
"translations" : {
|
||||
"en" : "Email",
|
||||
"fr" : "Adresse email",
|
||||
|
@ -54,7 +54,7 @@
|
|||
}
|
||||
},
|
||||
"auth.forgot-password" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:97" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:103" ],
|
||||
"translations" : {
|
||||
"en" : "Forgot your password?",
|
||||
"fr" : "Mot de passe oublié?",
|
||||
|
@ -99,7 +99,7 @@
|
|||
}
|
||||
},
|
||||
"auth.login-submit-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:81" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:82" ],
|
||||
"translations" : {
|
||||
"en" : "Sign in",
|
||||
"fr" : "Se connecter",
|
||||
|
@ -107,17 +107,8 @@
|
|||
"es" : "Entrar"
|
||||
}
|
||||
},
|
||||
"auth.login-with-ldap-submit-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:108" ],
|
||||
"translations" : {
|
||||
"en" : "Sign in with LDAP",
|
||||
"fr" : "Se connecter via LDAP",
|
||||
"es" : "Entrar con LDAP",
|
||||
"ru" : "Вход через LDAP"
|
||||
}
|
||||
},
|
||||
"auth.login-subtitle" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:89" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:95" ],
|
||||
"translations" : {
|
||||
"en" : "Enter your details below",
|
||||
"fr" : "Entrez vos informations ci-dessous",
|
||||
|
@ -126,7 +117,7 @@
|
|||
}
|
||||
},
|
||||
"auth.login-title" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:88" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:94" ],
|
||||
"translations" : {
|
||||
"en" : "Great to see you again!",
|
||||
"fr" : "Ravi de vous revoir!",
|
||||
|
@ -134,6 +125,15 @@
|
|||
"es" : "Encantados de volverte a ver"
|
||||
}
|
||||
},
|
||||
"auth.login-with-ldap-submit-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:86" ],
|
||||
"translations" : {
|
||||
"en" : "Sign in with LDAP",
|
||||
"fr" : "Se connecter via LDAP",
|
||||
"ru" : "Вход через LDAP",
|
||||
"es" : "Entrar con LDAP"
|
||||
}
|
||||
},
|
||||
"auth.new-password-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/recovery.cljs:73" ],
|
||||
"translations" : {
|
||||
|
@ -171,7 +171,7 @@
|
|||
}
|
||||
},
|
||||
"auth.password-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:86", "src/uxbox/main/ui/auth/login.cljs:79" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/register.cljs:86", "src/uxbox/main/ui/auth/login.cljs:80" ],
|
||||
"translations" : {
|
||||
"en" : "Password",
|
||||
"fr" : "Mot de passe",
|
||||
|
@ -225,7 +225,7 @@
|
|||
}
|
||||
},
|
||||
"auth.register" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:103" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:109" ],
|
||||
"translations" : {
|
||||
"en" : "Sign up here",
|
||||
"fr" : "Inscrivez-vous ici",
|
||||
|
@ -234,7 +234,7 @@
|
|||
}
|
||||
},
|
||||
"auth.register-label" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:100" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:106" ],
|
||||
"translations" : {
|
||||
"en" : "No account yet?",
|
||||
"fr" : "Pas encore de compte?",
|
||||
|
@ -504,48 +504,48 @@
|
|||
"unused" : true
|
||||
},
|
||||
"dashboard.library.menu.icons" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:89" ],
|
||||
"translations" : {
|
||||
"en" : "Icons",
|
||||
"fr" : "Icônes",
|
||||
"ru" : "Иконки",
|
||||
"es" : "Iconos"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"dashboard.library.menu.images" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:93" ],
|
||||
"translations" : {
|
||||
"en" : "Images",
|
||||
"fr" : "Images",
|
||||
"ru" : "Изображения",
|
||||
"es" : "Imágenes"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"dashboard.library.menu.palettes" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:97" ],
|
||||
"translations" : {
|
||||
"en" : "Palettes",
|
||||
"fr" : "Palettes",
|
||||
"ru" : "Палитры",
|
||||
"es" : "Paletas"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"dashboard.search.no-matches-for" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/search.cljs:48" ],
|
||||
"translations" : {
|
||||
"en" : "No matches found for \"%s\"",
|
||||
"fr" : "Aucune correspondance pour \"%s\"",
|
||||
"ru" : "Совпадений для \"%s\" не найдено",
|
||||
"es" : "No se encuentra \"%s\""
|
||||
"en" : "No matches found for “%s“",
|
||||
"fr" : "Aucune correspondance pour “%s“",
|
||||
"ru" : "Совпадений для “%s“ не найдено",
|
||||
"es" : "No se encuentra “%s“"
|
||||
}
|
||||
},
|
||||
"dashboard.search.searching-for" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/search.cljs:44" ],
|
||||
"translations" : {
|
||||
"en" : "Searching for \"%s\"...",
|
||||
"fr" : "Recherche de \"%s\"...",
|
||||
"ru" : "Ищу \"%s\"...",
|
||||
"es" : "Buscando \"%s\"..."
|
||||
"en" : "Searching for “%s“...",
|
||||
"fr" : "Recherche de “%s“...",
|
||||
"ru" : "Ищу “%s“...",
|
||||
"es" : "Buscando “%s“..."
|
||||
}
|
||||
},
|
||||
"dashboard.search.type-something" : {
|
||||
|
@ -594,25 +594,25 @@
|
|||
}
|
||||
},
|
||||
"ds.button.delete" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:145", "src/uxbox/main/ui/dashboard/library.cljs:210", "src/uxbox/main/ui/dashboard/library.cljs:249", "src/uxbox/main/ui/dashboard/library.cljs:290" ],
|
||||
"translations" : {
|
||||
"en" : "Delete",
|
||||
"fr" : "Supprimer",
|
||||
"ru" : "Удалить",
|
||||
"es" : "Borrar"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"ds.button.rename" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:142" ],
|
||||
"translations" : {
|
||||
"en" : "Rename",
|
||||
"fr" : "Renommer",
|
||||
"ru" : "Переименовать",
|
||||
"es" : "Renombrar"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"ds.button.save" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:55", "src/uxbox/main/ui/workspace/sidebar/assets.cljs:69" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:62" ],
|
||||
"translations" : {
|
||||
"en" : "Save",
|
||||
"fr" : "Sauvegarder",
|
||||
|
@ -711,7 +711,7 @@
|
|||
}
|
||||
},
|
||||
"errors.auth.unauthorized" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:62" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/auth/login.cljs:63" ],
|
||||
"translations" : {
|
||||
"en" : "Username or password seems to be wrong.",
|
||||
"fr" : "Le nom d'utilisateur ou le mot de passe semble être faux.",
|
||||
|
@ -738,7 +738,7 @@
|
|||
}
|
||||
},
|
||||
"errors.generic" : {
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:204", "src/uxbox/main/ui/settings/profile.cljs:38", "src/uxbox/main/ui/auth.cljs:91" ],
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:183", "src/uxbox/main/ui/settings/profile.cljs:38", "src/uxbox/main/ui/auth.cljs:91" ],
|
||||
"translations" : {
|
||||
"en" : "Something wrong has happened.",
|
||||
"fr" : "Quelque chose c'est mal passé.",
|
||||
|
@ -747,7 +747,7 @@
|
|||
}
|
||||
},
|
||||
"errors.media-format-unsupported" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:406", "src/uxbox/main/data/users.cljs:177", "src/uxbox/main/data/images.cljs:376" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:39" ],
|
||||
"translations" : {
|
||||
"en" : "The image format is not supported (must be svg, jpg or png).",
|
||||
"fr" : "Le format d'image n'est pas supporté (doit être svg, jpg ou png).",
|
||||
|
@ -756,7 +756,7 @@
|
|||
}
|
||||
},
|
||||
"errors.media-too-large" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:404", "src/uxbox/main/data/users.cljs:175", "src/uxbox/main/data/images.cljs:374" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:37" ],
|
||||
"translations" : {
|
||||
"en" : "The image is too large to be inserted (must be under 5mb).",
|
||||
"fr" : "L'image est trop grande (doit être inférieure à 5 Mo).",
|
||||
|
@ -765,7 +765,7 @@
|
|||
}
|
||||
},
|
||||
"errors.media-type-mismatch" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:371", "src/uxbox/main/data/workspace/persistence.cljs:421", "src/uxbox/main/data/users.cljs:191", "src/uxbox/main/data/images.cljs:391" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:62" ],
|
||||
"translations" : {
|
||||
"en" : "Seems that the contents of the image does not match the file extension.",
|
||||
"fr" : "",
|
||||
|
@ -774,7 +774,7 @@
|
|||
}
|
||||
},
|
||||
"errors.media-type-not-allowed" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:368", "src/uxbox/main/data/workspace/persistence.cljs:418", "src/uxbox/main/data/users.cljs:188", "src/uxbox/main/data/images.cljs:388" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:59" ],
|
||||
"translations" : {
|
||||
"en" : "Seems that this is not a valid image.",
|
||||
"fr" : "",
|
||||
|
@ -783,7 +783,7 @@
|
|||
}
|
||||
},
|
||||
"errors.network" : {
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:198" ],
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:177" ],
|
||||
"translations" : {
|
||||
"en" : "Unable to connect to backend server.",
|
||||
"fr" : "Impossible de se connecter au serveur principal.",
|
||||
|
@ -819,7 +819,7 @@
|
|||
}
|
||||
},
|
||||
"errors.unexpected-error" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:374", "src/uxbox/main/data/workspace/persistence.cljs:424", "src/uxbox/main/data/users.cljs:194", "src/uxbox/main/data/images.cljs:394", "src/uxbox/main/ui/settings/change_email.cljs:51", "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:65", "src/uxbox/main/ui/auth/register.cljs:54" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:65", "src/uxbox/main/ui/settings/change_email.cljs:51", "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:65", "src/uxbox/main/ui/auth/register.cljs:54" ],
|
||||
"translations" : {
|
||||
"en" : "An unexpected error occurred.",
|
||||
"fr" : "Une erreur inattendue c'est produite",
|
||||
|
@ -864,7 +864,7 @@
|
|||
}
|
||||
},
|
||||
"media.loading" : {
|
||||
"used-in" : [ "src/uxbox/main/data/workspace/persistence.cljs:382", "src/uxbox/main/data/workspace/persistence.cljs:433", "src/uxbox/main/data/users.cljs:201", "src/uxbox/main/data/images.cljs:403" ],
|
||||
"used-in" : [ "src/uxbox/main/data/media.cljs:44" ],
|
||||
"translations" : {
|
||||
"en" : "Loading image...",
|
||||
"fr" : "Chargement de l'image...",
|
||||
|
@ -873,7 +873,7 @@
|
|||
}
|
||||
},
|
||||
"modal.create-color.new-color" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/library.cljs:49", "src/uxbox/main/ui/workspace/sidebar/assets.cljs:62" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:55" ],
|
||||
"translations" : {
|
||||
"en" : "New Color",
|
||||
"fr" : "Nouvelle couleur",
|
||||
|
@ -1053,7 +1053,7 @@
|
|||
}
|
||||
},
|
||||
"settings.multiple" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:132", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:117", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:126", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:227", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:240" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:137", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:117", "src/uxbox/main/ui/workspace/sidebar/options/rows/color_row.cljs:126", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:124", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:227", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:240" ],
|
||||
"translations" : {
|
||||
"en" : "Mixed",
|
||||
"fr" : null,
|
||||
|
@ -1089,7 +1089,7 @@
|
|||
}
|
||||
},
|
||||
"settings.notifications.email-not-verified" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard.cljs:118" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard.cljs:98" ],
|
||||
"translations" : {
|
||||
"en" : "Your email address has not been verified yet. Please check your inbox at “%s” for a confirmation email.",
|
||||
"fr" : "Votre adresse e-mail n'a pas encore été vérifiée. Veuillez vérifier votre boîte de réception à “%s” pour un e-mail de confirmation.",
|
||||
|
@ -1116,7 +1116,7 @@
|
|||
}
|
||||
},
|
||||
"settings.notifications.profile-deletion-not-allowed" : {
|
||||
"used-in" : [ "src/uxbox/main/data/auth.cljs:136" ],
|
||||
"used-in" : [ "src/uxbox/main/data/auth.cljs:160" ],
|
||||
"translations" : {
|
||||
"en" : "You can't delete you profile. Reasign your teams before proceed.",
|
||||
"fr" : "Vous ne pouvez pas supprimer votre profil. Réassignez vos équipes avant de continuer.",
|
||||
|
@ -1449,7 +1449,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:331" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:328" ],
|
||||
"translations" : {
|
||||
"en" : "Assets",
|
||||
"fr" : "",
|
||||
|
@ -1485,7 +1485,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.colors" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:247" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:240" ],
|
||||
"translations" : {
|
||||
"en" : "Colors",
|
||||
"fr" : "",
|
||||
|
@ -1494,7 +1494,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.delete" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:136", "src/uxbox/main/ui/workspace/sidebar/assets.cljs:231" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:129", "src/uxbox/main/ui/workspace/sidebar/assets.cljs:224" ],
|
||||
"translations" : {
|
||||
"en" : "Delete",
|
||||
"fr" : "",
|
||||
|
@ -1503,7 +1503,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.edit" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:230" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:223" ],
|
||||
"translations" : {
|
||||
"en" : "Edit",
|
||||
"fr" : "",
|
||||
|
@ -1512,7 +1512,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.file-library" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:272" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:354" ],
|
||||
"translations" : {
|
||||
"en" : "File library",
|
||||
"fr" : "",
|
||||
|
@ -1521,7 +1521,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.graphics" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:113" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:106" ],
|
||||
"translations" : {
|
||||
"en" : "Graphics",
|
||||
"fr" : "",
|
||||
|
@ -1529,8 +1529,17 @@
|
|||
"es" : "Gráficos"
|
||||
}
|
||||
},
|
||||
"workspace.assets.libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:331" ],
|
||||
"translations" : {
|
||||
"en" : "Libraries",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Bibliotecas"
|
||||
}
|
||||
},
|
||||
"workspace.assets.not-found" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:287" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:281" ],
|
||||
"translations" : {
|
||||
"en" : "No assets found",
|
||||
"fr" : "",
|
||||
|
@ -1539,7 +1548,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.rename" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:229" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:222" ],
|
||||
"translations" : {
|
||||
"en" : "Rename",
|
||||
"fr" : "",
|
||||
|
@ -1557,7 +1566,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.assets.shared" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:274" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/assets.cljs:268" ],
|
||||
"translations" : {
|
||||
"en" : "SHARED",
|
||||
"fr" : "",
|
||||
|
@ -1601,6 +1610,15 @@
|
|||
"es" : "Alinear a la rejilla"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:132" ],
|
||||
"translations" : {
|
||||
"en" : "Hide assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Ocultar recursos"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-grid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:104" ],
|
||||
"translations" : {
|
||||
|
@ -1619,15 +1637,6 @@
|
|||
"es" : "Ocultar capas"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:132" ],
|
||||
"translations" : {
|
||||
"en" : "Hide assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Ocultar recursos"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:125" ],
|
||||
"translations" : {
|
||||
|
@ -1646,6 +1655,15 @@
|
|||
"es" : "Ocultar reglas"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:133" ],
|
||||
"translations" : {
|
||||
"en" : "Show assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Mostrar recursos"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-grid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:105" ],
|
||||
"translations" : {
|
||||
|
@ -1664,15 +1682,6 @@
|
|||
"es" : "Mostrar capas"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:133" ],
|
||||
"translations" : {
|
||||
"en" : "Show assets",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Mostrar recursos"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:126" ],
|
||||
"translations" : {
|
||||
|
@ -1700,59 +1709,167 @@
|
|||
"es" : "Modo de visualización (Ctrl + P)"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.add" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:98" ],
|
||||
"translations" : {
|
||||
"en" : "Add",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Añadir"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.colors" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:55" ],
|
||||
"translations" : {
|
||||
"en" : "%s colors",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "%s colors"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.file-library" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:61" ],
|
||||
"translations" : {
|
||||
"en" : "File library",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Biblioteca de este archivo"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.graphics" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:52" ],
|
||||
"translations" : {
|
||||
"en" : "%s graphics",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "%s gráficos"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.in-this-file" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:58" ],
|
||||
"translations" : {
|
||||
"en" : "LIBRARIES IN THIS FILE",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "BIBLIOTECAS EN ESTE ARCHIVO"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:140" ],
|
||||
"translations" : {
|
||||
"en" : "LIBRARIES",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "BIBLIOTECAS"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.no-matches-for" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:104" ],
|
||||
"translations" : {
|
||||
"en" : "No matches found for “%s“",
|
||||
"fr" : "Aucune correspondance pour “%s“",
|
||||
"ru" : "Совпадений для “%s“ не найдено",
|
||||
"es" : "No se encuentra “%s“"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.no-shared-libraries-available" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:103" ],
|
||||
"translations" : {
|
||||
"en" : "There are no Shared Libraries available",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "No hay bibliotecas compartidas disponibles"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.remove" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:72" ],
|
||||
"translations" : {
|
||||
"en" : "Remove",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Quitar"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.search-shared-libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:79" ],
|
||||
"translations" : {
|
||||
"en" : "Search shared libraries",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "Buscar bibliotecas compartidas"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.shared-libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:76" ],
|
||||
"translations" : {
|
||||
"en" : "SHARED LIBRARIES",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "BIBLIOTECAS COMPARTIDAS"
|
||||
}
|
||||
},
|
||||
"workspace.libraries.updates" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/libraries.cljs:144" ],
|
||||
"translations" : {
|
||||
"en" : "UPDATES",
|
||||
"fr" : "",
|
||||
"ru" : "",
|
||||
"es" : "ACTUALIZACIONES"
|
||||
}
|
||||
},
|
||||
"workspace.library.all" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:128" ],
|
||||
"translations" : {
|
||||
"en" : "All libraries",
|
||||
"fr" : "Toutes les librairies",
|
||||
"ru" : "Все библиотеки",
|
||||
"es" : "Todas"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.library.icons" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:178" ],
|
||||
"translations" : {
|
||||
"en" : "Icons",
|
||||
"fr" : "Icônes",
|
||||
"ru" : "Иконки",
|
||||
"es" : "Iconos"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.library.images" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:183" ],
|
||||
"translations" : {
|
||||
"en" : "Images",
|
||||
"fr" : "Images",
|
||||
"ru" : "Изображения",
|
||||
"es" : "Imágenes"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.library.libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:160" ],
|
||||
"translations" : {
|
||||
"en" : "Libraries",
|
||||
"fr" : "Librairies",
|
||||
"ru" : "Библиотеки",
|
||||
"es" : "Bibliotecas"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.library.own" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:129" ],
|
||||
"translations" : {
|
||||
"en" : "My libraries",
|
||||
"fr" : "Mes librairies",
|
||||
"ru" : "Мои библиотеки",
|
||||
"es" : "Mis bibliotecas"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.library.store" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:130" ],
|
||||
"translations" : {
|
||||
"en" : "Store libraries",
|
||||
"fr" : "Prédéfinies",
|
||||
"ru" : "Сохраненные библиотеки",
|
||||
"es" : "Predefinidas"
|
||||
}
|
||||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.options.canvas-background" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:37" ],
|
||||
|
@ -1780,21 +1897,21 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.export-object" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:154" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:155" ],
|
||||
"translations" : {
|
||||
"en" : "Export shape",
|
||||
"ru" : "Экспорт фигуры"
|
||||
}
|
||||
},
|
||||
"workspace.options.exporting-object" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:153" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/exports.cljs:154" ],
|
||||
"translations" : {
|
||||
"en" : "Exporting...",
|
||||
"ru" : "Экспортирую ..."
|
||||
}
|
||||
},
|
||||
"workspace.options.fill" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:50" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:52" ],
|
||||
"translations" : {
|
||||
"en" : "Fill",
|
||||
"fr" : "Remplissage",
|
||||
|
@ -1992,7 +2109,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.group-fill" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:49" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:51" ],
|
||||
"translations" : {
|
||||
"en" : "Group fill",
|
||||
"fr" : null,
|
||||
|
@ -2001,7 +2118,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.group-stroke" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:65" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:70" ],
|
||||
"translations" : {
|
||||
"en" : "Group stroke",
|
||||
"fr" : null,
|
||||
|
@ -2082,7 +2199,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.selection-fill" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:48" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:50" ],
|
||||
"translations" : {
|
||||
"en" : "Selection fill",
|
||||
"fr" : null,
|
||||
|
@ -2091,7 +2208,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.selection-stroke" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:64" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:69" ],
|
||||
"translations" : {
|
||||
"en" : "Selection stroke",
|
||||
"fr" : null,
|
||||
|
@ -2118,7 +2235,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:66" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:71" ],
|
||||
"translations" : {
|
||||
"en" : "Stroke",
|
||||
"fr" : "Bordure",
|
||||
|
@ -2127,7 +2244,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.center" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:139" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:144" ],
|
||||
"translations" : {
|
||||
"en" : "Center",
|
||||
"fr" : "Centre",
|
||||
|
@ -2136,7 +2253,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.dashed" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:149" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:154" ],
|
||||
"translations" : {
|
||||
"en" : "Dashed",
|
||||
"fr" : "Tiré",
|
||||
|
@ -2145,7 +2262,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.dotted" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:148" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:153" ],
|
||||
"translations" : {
|
||||
"en" : "Dotted",
|
||||
"fr" : "Pointillé",
|
||||
|
@ -2154,7 +2271,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.inner" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:140" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:145" ],
|
||||
"translations" : {
|
||||
"en" : "Inside",
|
||||
"fr" : "Intérieur",
|
||||
|
@ -2163,7 +2280,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.mixed" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:150" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:155" ],
|
||||
"translations" : {
|
||||
"en" : "Mixed",
|
||||
"fr" : "Mixte",
|
||||
|
@ -2172,7 +2289,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.outer" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:141" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:146" ],
|
||||
"translations" : {
|
||||
"en" : "Outside",
|
||||
"fr" : "Extérieur",
|
||||
|
@ -2181,7 +2298,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.options.stroke.solid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:147" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:152" ],
|
||||
"translations" : {
|
||||
"en" : "Solid",
|
||||
"fr" : "Solide",
|
||||
|
@ -2404,7 +2521,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.assets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:105" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:99" ],
|
||||
"translations" : {
|
||||
"en" : "Assets (Ctrl + I)",
|
||||
"fr" : "",
|
||||
|
@ -2413,7 +2530,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.circle" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:64" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:63" ],
|
||||
"translations" : {
|
||||
"en" : "Circle (E)",
|
||||
"fr" : "Cercle (E)",
|
||||
|
@ -2422,7 +2539,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.color-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:113" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:107" ],
|
||||
"translations" : {
|
||||
"en" : "Color Palette (---)",
|
||||
"fr" : "Palette de couleurs (---)",
|
||||
|
@ -2431,7 +2548,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.curve" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:83" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:82" ],
|
||||
"translations" : {
|
||||
"en" : "Curve",
|
||||
"fr" : "Courbe",
|
||||
|
@ -2440,7 +2557,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.frame" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:54" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:53" ],
|
||||
"translations" : {
|
||||
"en" : "Artboard (A)",
|
||||
"fr" : "Plan de travail (A)",
|
||||
|
@ -2449,7 +2566,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.image" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:74" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:73" ],
|
||||
"translations" : {
|
||||
"en" : "Image (I)",
|
||||
"fr" : "Image (I)",
|
||||
|
@ -2467,7 +2584,7 @@
|
|||
"unused" : true
|
||||
},
|
||||
"workspace.toolbar.path" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:88" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:87" ],
|
||||
"translations" : {
|
||||
"en" : "Path",
|
||||
"fr" : "Chemin",
|
||||
|
@ -2476,7 +2593,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.rect" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:59" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:58" ],
|
||||
"translations" : {
|
||||
"en" : "Box (B)",
|
||||
"fr" : "Boîte (B)",
|
||||
|
@ -2485,7 +2602,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.toolbar.text" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:69" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/left_toolbar.cljs:68" ],
|
||||
"translations" : {
|
||||
"en" : "Text (T)",
|
||||
"fr" : "Texte (T)",
|
||||
|
@ -2494,7 +2611,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.viewport.click-to-close-path" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:55" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:59" ],
|
||||
"translations" : {
|
||||
"en" : "Click to close the path",
|
||||
"fr" : "Cliquez pour fermer le chemin",
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
@import 'main/layouts/main-layout';
|
||||
@import 'main/layouts/login';
|
||||
@import 'main/layouts/projects-page';
|
||||
@import 'main/layouts/libraries-page';
|
||||
@import 'main/layouts/recent-files-page';
|
||||
@import "main/layouts/not-found";
|
||||
@import "main/layouts/viewer";
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
.libraries-page {
|
||||
padding: 1rem;
|
||||
height: 100%;
|
||||
background-color: $color-white;
|
||||
}
|
|
@ -136,3 +136,156 @@
|
|||
}
|
||||
}
|
||||
|
||||
.libraries-dialog {
|
||||
width: 920px;
|
||||
height: 664px;
|
||||
|
||||
.modal-content {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.libraries-header {
|
||||
border-bottom: 1px solid $color-gray-20;
|
||||
padding: 2rem 1rem 0.5rem 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.header-item {
|
||||
cursor: pointer;
|
||||
color: $color-gray-40;
|
||||
font-size: $fs15;
|
||||
|
||||
&.active {
|
||||
color: $color-gray-60;
|
||||
border-bottom: 2px solid $color-primary;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.libraries-content {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
align-items: stretch;
|
||||
flex-grow: 1;
|
||||
padding: 0 $size-4;
|
||||
color: $color-gray-40;
|
||||
|
||||
.section {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
padding: $size-4 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-left: 1px solid $color-gray-20;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: $fs15;
|
||||
padding: 0 $size-4;
|
||||
}
|
||||
|
||||
.section-list {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
padding: 0 $size-4;
|
||||
overflow: auto;
|
||||
|
||||
.section-list-item {
|
||||
padding: $size-4 0;
|
||||
border-bottom: 1px solid $color-gray-20;
|
||||
position: relative;
|
||||
|
||||
.item-name {
|
||||
color: $color-gray-60;
|
||||
font-size: $fs14;
|
||||
}
|
||||
|
||||
.item-contents {
|
||||
color: $color-gray-40;
|
||||
font-size: $fs12;
|
||||
}
|
||||
|
||||
.item-button {
|
||||
position: absolute;
|
||||
top: $size-4;
|
||||
right: 0;
|
||||
border: 1px solid $color-primary;
|
||||
border-radius: 2px;
|
||||
width: 4.5rem;
|
||||
background: $color-primary;
|
||||
color: $color-black;
|
||||
padding: $size-2;
|
||||
|
||||
&:hover {
|
||||
color: $color-primary;
|
||||
background: $color-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-list-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 $size-4;
|
||||
flex-grow: 1;
|
||||
|
||||
& svg {
|
||||
fill: $color-gray-20;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin-bottom: $size-4;
|
||||
}
|
||||
}
|
||||
|
||||
.libraries-search {
|
||||
border: 1px solid $color-gray-30;
|
||||
margin: $size-4;
|
||||
padding: $x-small;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:focus-within {
|
||||
border-color: $color-primary;
|
||||
}
|
||||
|
||||
& .search-input {
|
||||
border: none;
|
||||
color: $color-gray-60;
|
||||
font-size: $fs12;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
& .search-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&.search-close {
|
||||
transform: rotate(45deg);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,30 @@
|
|||
color: $color-gray-10;
|
||||
font-size: $fs14;
|
||||
margin: $small $small 0 $small;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
& .libraries-button {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
padding-right: $x-small;
|
||||
}
|
||||
}
|
||||
|
||||
& .libraries-button:hover {
|
||||
color: $color-primary;
|
||||
|
||||
& svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-block {
|
||||
|
@ -22,14 +46,14 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:focus-within {
|
||||
border-color: $color-primary !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $color-gray-20;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
border-color: $color-primary;
|
||||
}
|
||||
|
||||
& .search-input {
|
||||
background-color: $color-gray-50;
|
||||
border: none;
|
||||
|
@ -50,8 +74,8 @@
|
|||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&.close {
|
||||
|
|
|
@ -99,6 +99,22 @@ $width-settings-bar: 15rem;
|
|||
margin-left: auto;
|
||||
}
|
||||
|
||||
span.tool-link {
|
||||
margin-left: auto;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool-window-icon {
|
||||
margin-right: $small;
|
||||
display: none;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-colors-library (:id color)] color)
|
||||
(update-in [:workspace-file :colors] #(conj % color))
|
||||
(assoc-in [:workspace-local :color-for-rename] (:id color))))))
|
||||
|
||||
(def clear-color-for-rename
|
||||
|
@ -67,7 +67,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-colors-library (:id color)] color)))))
|
||||
(update-in [:workspace-file :colors] #(d/replace-by-id % color))))))
|
||||
|
||||
(declare update-color-result)
|
||||
|
||||
|
@ -86,7 +86,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-colors-library (:id color)] color)))))
|
||||
(update-in [:workspace-file :colors] #(d/replace-by-id % color))))))
|
||||
|
||||
(declare delete-color-result)
|
||||
|
||||
|
@ -104,5 +104,6 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(d/dissoc-in [:workspace-colors-library color-id])))))
|
||||
(update-in [:workspace-file :colors]
|
||||
(fn [colors] (filter #(not= (:id %) color-id) colors)))))))
|
||||
|
||||
|
|
|
@ -1433,8 +1433,9 @@
|
|||
;; Persistence
|
||||
|
||||
(def set-file-shared dwp/set-file-shared)
|
||||
(def fetch-media-library dwp/fetch-media-library)
|
||||
(def fetch-colors-library dwp/fetch-colors-library)
|
||||
(def fetch-shared-files dwp/fetch-shared-files)
|
||||
(def link-file-to-library dwp/link-file-to-library)
|
||||
(def unlink-file-from-library dwp/unlink-file-from-library)
|
||||
(def add-media-object-from-url dwp/add-media-object-from-url)
|
||||
(def upload-media-objects dwp/upload-media-objects)
|
||||
(def delete-media-object dwp/delete-media-object)
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
::ordering
|
||||
::data]))
|
||||
|
||||
(declare fetch-libraries-content)
|
||||
(declare bundle-fetched)
|
||||
|
||||
(defn- fetch-bundle
|
||||
|
@ -147,10 +148,18 @@
|
|||
(->> (rx/zip (rp/query :file {:id file-id})
|
||||
(rp/query :file-users {:id file-id})
|
||||
(rp/query :project-by-id {:project-id project-id})
|
||||
(rp/query :pages {:file-id file-id}))
|
||||
(rp/query :pages {:file-id file-id})
|
||||
(rp/query :media-objects {:file-id file-id :is-local false})
|
||||
(rp/query :colors {:file-id file-id})
|
||||
(rp/query :file-libraries {:file-id file-id}))
|
||||
(rx/first)
|
||||
(rx/map (fn [[file users project pages]]
|
||||
(bundle-fetched file users project pages)))
|
||||
(rx/mapcat
|
||||
(fn [bundle]
|
||||
(->> (fetch-libraries-content (get bundle 6))
|
||||
(rx/map (fn [[lib-media-objects lib-colors]]
|
||||
(conj bundle lib-media-objects lib-colors))))))
|
||||
(rx/map (fn [bundle]
|
||||
(apply bundle-fetched bundle)))
|
||||
(rx/catch (fn [{:keys [type code] :as error}]
|
||||
(cond
|
||||
(= :not-found type)
|
||||
|
@ -163,27 +172,78 @@
|
|||
:else
|
||||
(throw error))))))))
|
||||
|
||||
(defn- fetch-libraries-content
|
||||
[libraries]
|
||||
(if (empty? libraries)
|
||||
(rx/of [{} {}])
|
||||
(rx/zip
|
||||
(->> ;; fetch media-objects list of each library, and concatenate in a sequence
|
||||
(apply rx/zip (for [library libraries]
|
||||
(->> (rp/query :media-objects {:file-id (:id library)
|
||||
:is-local false})
|
||||
(rx/map (fn [media-objects]
|
||||
[(:id library) media-objects])))))
|
||||
|
||||
;; reorganize the sequence as a map {library-id -> media-objects}
|
||||
(rx/map (fn [media-list]
|
||||
(reduce (fn [result, [library-id media-objects]]
|
||||
(assoc result library-id media-objects))
|
||||
{}
|
||||
media-list))))
|
||||
|
||||
(->> ;; fetch colorss list of each library, and concatenate in a vector
|
||||
(apply rx/zip (for [library libraries]
|
||||
(->> (rp/query :colors {:file-id (:id library)})
|
||||
(rx/map (fn [colors]
|
||||
[(:id library) colors])))))
|
||||
|
||||
;; reorganize the sequence as a map {library-id -> colors}
|
||||
(rx/map (fn [colors-list]
|
||||
(reduce (fn [result, [library-id colors]]
|
||||
(assoc result library-id colors))
|
||||
{}
|
||||
colors-list)))))))
|
||||
|
||||
(defn- bundle-fetched
|
||||
[file users project pages]
|
||||
[file users project pages media-objects colors libraries lib-media-objects lib-colors]
|
||||
(ptk/reify ::bundle-fetched
|
||||
IDeref
|
||||
(-deref [_]
|
||||
{:file file
|
||||
:users users
|
||||
:project project
|
||||
:pages pages})
|
||||
:pages pages
|
||||
:media-objects media-objects
|
||||
:colors colors
|
||||
:libraries libraries})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [assoc-page #(assoc-in %1 [:workspace-pages (:id %2)] %2)]
|
||||
(let [assoc-page
|
||||
#(assoc-in %1 [:workspace-pages (:id %2)] %2)
|
||||
|
||||
assoc-media-objects
|
||||
#(assoc-in %1 [:workspace-libraries %2 :media-objects]
|
||||
(get lib-media-objects %2))
|
||||
|
||||
assoc-colors
|
||||
#(assoc-in %1 [:workspace-libraries %2 :colors]
|
||||
(get lib-colors %2))]
|
||||
|
||||
(as-> state $$
|
||||
(assoc $$
|
||||
:workspace-file file
|
||||
:workspace-file (assoc file
|
||||
:media-objects media-objects
|
||||
:colors colors)
|
||||
:workspace-users (d/index-by :id users)
|
||||
:workspace-pages {}
|
||||
:workspace-project project)
|
||||
:workspace-project project
|
||||
:workspace-libraries (d/index-by :id libraries))
|
||||
(reduce assoc-media-objects $$ (keys lib-media-objects))
|
||||
(reduce assoc-colors $$ (keys lib-colors))
|
||||
(reduce assoc-page $$ pages))))))
|
||||
|
||||
|
||||
;; --- Set File shared
|
||||
|
||||
(defn set-file-shared
|
||||
|
@ -200,6 +260,79 @@
|
|||
(->> (rp/mutation :set-file-shared params)
|
||||
(rx/ignore))))))
|
||||
|
||||
|
||||
;; --- Fetch Shared Files
|
||||
|
||||
(declare shared-files-fetched)
|
||||
|
||||
(defn fetch-shared-files
|
||||
[]
|
||||
(ptk/reify ::fetch-shared-files
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {}]
|
||||
(->> (rp/query :shared-files params)
|
||||
(rx/map shared-files-fetched))))))
|
||||
|
||||
(defn shared-files-fetched
|
||||
[files]
|
||||
(us/verify (s/every ::file) files)
|
||||
(ptk/reify ::shared-files-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [state (dissoc state :files)]
|
||||
(assoc state :workspace-shared-files files)))))
|
||||
|
||||
|
||||
;; --- Link and unlink Files
|
||||
|
||||
(declare file-linked)
|
||||
|
||||
(defn link-file-to-library
|
||||
[file-id library-id]
|
||||
(ptk/reify ::link-file-to-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(->> (->> (rp/mutation :link-file-to-library params)
|
||||
(rx/mapcat
|
||||
#(rx/zip (rp/query :file-library {:file-id library-id})
|
||||
(rp/query :media-objects {:file-id library-id
|
||||
:is-local false})
|
||||
(rp/query :colors {:file-id library-id}))))
|
||||
(rx/map file-linked))))))
|
||||
|
||||
(defn file-linked
|
||||
[[library media-objects colors]]
|
||||
(ptk/reify ::file-linked
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-libraries (:id library)]
|
||||
(assoc library
|
||||
:media-objects media-objects
|
||||
:colors colors)))))
|
||||
|
||||
(declare file-unlinked)
|
||||
|
||||
(defn unlink-file-from-library
|
||||
[file-id library-id]
|
||||
(ptk/reify ::unlink-file-from-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(->> (rp/mutation :unlink-file-from-library params)
|
||||
(rx/map #(file-unlinked file-id library-id)))))))
|
||||
|
||||
(defn file-unlinked
|
||||
[file-id library-id]
|
||||
(ptk/reify ::file-unlinked
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(d/dissoc-in state [:workspace-libraries library-id]))))
|
||||
|
||||
|
||||
;; --- Fetch Pages
|
||||
|
||||
(declare page-fetched)
|
||||
|
@ -298,46 +431,6 @@
|
|||
(rx/of go-to-file)
|
||||
(rx/empty))))))))))
|
||||
|
||||
;; --- Fetch Workspace Media library
|
||||
|
||||
(declare media-library-fetched)
|
||||
|
||||
(defn fetch-media-library
|
||||
[file-id]
|
||||
(ptk/reify ::fetch-media-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query :media-objects {:file-id file-id :is-local false})
|
||||
(rx/map media-library-fetched)))))
|
||||
|
||||
(defn media-library-fetched
|
||||
[media-objects]
|
||||
(ptk/reify ::media-library-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [media-objects (d/index-by :id media-objects)]
|
||||
(assoc state :workspace-media-library media-objects)))))
|
||||
|
||||
;; --- Fetch Workspace Colors library
|
||||
|
||||
(declare colors-library-fetched)
|
||||
|
||||
(defn fetch-colors-library
|
||||
[file-id]
|
||||
(ptk/reify ::fetch-colors-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (rp/query :colors {:file-id file-id})
|
||||
(rx/map colors-library-fetched)))))
|
||||
|
||||
(defn colors-library-fetched
|
||||
[colors]
|
||||
(ptk/reify ::colors-library-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [colors (d/index-by :id colors)]
|
||||
(assoc state :workspace-colors-library colors)))))
|
||||
|
||||
|
||||
;; --- Upload local media objects
|
||||
|
||||
|
@ -357,6 +450,8 @@
|
|||
|
||||
on-error #(do (di/notify-finished-loading)
|
||||
(di/process-error %))
|
||||
|
||||
is-library (not= file-id (:id (:workspace-file state)))
|
||||
|
||||
prepare
|
||||
(fn [url]
|
||||
|
@ -370,7 +465,7 @@
|
|||
(rx/map prepare)
|
||||
(rx/mapcat #(rp/mutation! :add-media-object-from-url %))
|
||||
(rx/do on-success)
|
||||
(rx/map (partial upload-media-objects-result file-id is-local))
|
||||
(rx/map (partial upload-media-objects-result file-id is-local is-library))
|
||||
(rx/catch on-error)))))))
|
||||
|
||||
(defn upload-media-objects
|
||||
|
@ -389,6 +484,8 @@
|
|||
on-error #(do (di/notify-finished-loading)
|
||||
(di/process-error %))
|
||||
|
||||
is-library (not= file-id (:id (:workspace-file state)))
|
||||
|
||||
prepare
|
||||
(fn [js-file]
|
||||
{:name (.-name js-file)
|
||||
|
@ -403,32 +500,43 @@
|
|||
(rx/map prepare)
|
||||
(rx/mapcat #(rp/mutation! :upload-media-object %))
|
||||
(rx/do on-success)
|
||||
(rx/map (partial upload-media-objects-result file-id is-local))
|
||||
(rx/map (partial upload-media-objects-result file-id is-local is-library))
|
||||
(rx/catch on-error)))))))
|
||||
|
||||
(defn upload-media-objects-result
|
||||
[file-id is-local media-object]
|
||||
[file-id is-local is-library media-object]
|
||||
(us/verify ::us/uuid file-id)
|
||||
(us/verify ::us/boolean is-local)
|
||||
(us/verify ::cm/media-object media-object)
|
||||
(ptk/reify ::upload-media-objects-result
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if is-local
|
||||
(if is-local ;; the media-object is local to the file, not for its library
|
||||
state
|
||||
(assoc-in state
|
||||
[:workspace-media-library (:id media-object)]
|
||||
media-object)))))
|
||||
(if is-library ;; the file is not the currently editing one, but a linked shared file
|
||||
(update-in state
|
||||
[:workspace-libraries file-id :media-objects]
|
||||
#(conj % media-object))
|
||||
(update-in state
|
||||
[:workspace-file :media-objects]
|
||||
#(conj % media-object)))))))
|
||||
|
||||
|
||||
;; --- Delete media object
|
||||
|
||||
(defn delete-media-object
|
||||
[id]
|
||||
[file-id id]
|
||||
(ptk/reify ::delete-media-object
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-media-library dissoc id))
|
||||
(let [is-library (not= file-id (:id (:workspace-file state)))]
|
||||
(if is-library
|
||||
(update-in state
|
||||
[:workspace-libraries file-id :media-objects]
|
||||
(fn [media-objects] (filter #(not= (:id %) id) media-objects)))
|
||||
(update-in state
|
||||
[:workspace-file :media-objects]
|
||||
(fn [media-objects] (filter #(not= (:id %) id) media-objects))))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
|
|
@ -57,11 +57,11 @@
|
|||
(def workspace-project
|
||||
(l/derived :workspace-project st/state))
|
||||
|
||||
(def workspace-media-library
|
||||
(l/derived :workspace-media-library st/state))
|
||||
(def workspace-shared-files
|
||||
(l/derived :workspace-shared-files st/state))
|
||||
|
||||
(def workspace-colors-library
|
||||
(l/derived :workspace-colors-library st/state))
|
||||
(def workspace-libraries
|
||||
(l/derived :workspace-libraries st/state))
|
||||
|
||||
(def workspace-users
|
||||
(l/derived :workspace-users st/state))
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
(def layers (icon-xref :layers))
|
||||
(def letter-spacing (icon-xref :letter-spacing))
|
||||
(def library (icon-xref :library))
|
||||
(def libraries (icon-xref :libraries))
|
||||
(def line (icon-xref :line))
|
||||
(def line-height (icon-xref :line-height))
|
||||
(def loader (icon-xref :loader))
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.main.ui.confirm]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.hooks :as hooks]
|
||||
[uxbox.main.ui.workspace.viewport :refer [viewport coordinates]]
|
||||
|
|
155
frontend/src/uxbox/main/ui/workspace/libraries.cljs
Normal file
155
frontend/src/uxbox/main/ui/workspace/libraries.cljs
Normal file
|
@ -0,0 +1,155 @@
|
|||
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.libraries
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.data :refer [classnames matches-search]]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.main.ui.modal :as modal]))
|
||||
|
||||
(mf/defc libraries-tab
|
||||
[{:keys [file libraries shared-files] :as props}]
|
||||
(let [state (mf/use-state {:search-term ""})
|
||||
|
||||
sorted-libraries (->> (vals libraries)
|
||||
(sort-by #(str/lower (:name %))))
|
||||
|
||||
filtered-files (->> shared-files
|
||||
(filter #(not= (:id %) (:id file)))
|
||||
(filter #(nil? (get libraries (:id %))))
|
||||
(filter #(matches-search (:name %) (:search-term @state)))
|
||||
(sort-by #(str/lower (:name %))))
|
||||
|
||||
on-search-term-change (fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(swap! state assoc :search-term value)))
|
||||
|
||||
on-search-clear-click (fn [event]
|
||||
(swap! state assoc :search-term ""))
|
||||
|
||||
link-library (fn [library-id]
|
||||
(st/emit! (dw/link-file-to-library (:id file) library-id)))
|
||||
|
||||
unlink-library (fn [library-id]
|
||||
(st/emit! (dw/unlink-file-from-library (:id file) library-id)))
|
||||
|
||||
contents-str (fn [library graphics-count colors-count]
|
||||
(str
|
||||
(str/join " · "
|
||||
(cond-> []
|
||||
(< 0 graphics-count)
|
||||
(conj (tr "workspace.libraries.graphics" graphics-count))
|
||||
|
||||
(< 0 colors-count)
|
||||
(conj (tr "workspace.libraries.colors" colors-count))))
|
||||
"\u00A0"))] ;; Include a so this block has always some content
|
||||
[:*
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
||||
[:div.section-list
|
||||
[:div.section-list-item
|
||||
[:div.item-name (tr "workspace.libraries.file-library")]
|
||||
[:div.item-contents (contents-str file
|
||||
(count (:media-objects file))
|
||||
(count (:colors file)))]]
|
||||
(for [library sorted-libraries]
|
||||
[:div.section-list-item {:key (:id library)}
|
||||
[:div.item-name (:name library)]
|
||||
[:div.item-contents (contents-str library
|
||||
(count (:media-objects library))
|
||||
(count (:colors library)))]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.remove")
|
||||
:on-click #(unlink-library (:id library))}]])
|
||||
]]
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.shared-libraries")]
|
||||
[:div.libraries-search
|
||||
[:input.search-input
|
||||
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||
:type "text"
|
||||
:value (:search-term @state)
|
||||
:on-change on-search-term-change}]
|
||||
(if (str/empty? (:search-term @state))
|
||||
[:div.search-icon
|
||||
i/search]
|
||||
[:div.search-icon.search-close
|
||||
{:on-click on-search-clear-click}
|
||||
i/close])]
|
||||
(if (> (count filtered-files) 0)
|
||||
[:div.section-list
|
||||
(for [file filtered-files]
|
||||
[:div.section-list-item {:key (:id file)}
|
||||
[:div.item-name (:name file)]
|
||||
[:div.item-contents (contents-str file
|
||||
(:graphics-count file)
|
||||
(:colors-count file))]
|
||||
[:input.item-button {:type "button"
|
||||
:value (tr "workspace.libraries.add")
|
||||
:on-click #(link-library (:id file))}]])]
|
||||
[:div.section-list-empty
|
||||
i/library
|
||||
(if (str/empty? (:search-term @state))
|
||||
(tr "workspace.libraries.no-shared-libraries-available")
|
||||
(tr "workspace.libraries.no-matches-for" (:search-term @state)))])]]))
|
||||
|
||||
|
||||
(mf/defc updates-tab
|
||||
[]
|
||||
[:div])
|
||||
|
||||
|
||||
(mf/defc libraries-dialog
|
||||
[{:keys [] :as ctx}]
|
||||
(let [state (mf/use-state {:current-tab :libraries})
|
||||
|
||||
current-tab (:current-tab @state)
|
||||
|
||||
file (mf/deref refs/workspace-file)
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
shared-files (mf/deref refs/workspace-shared-files)
|
||||
|
||||
change-tab (fn [tab]
|
||||
(swap! state assoc :current-tab tab))
|
||||
|
||||
close (fn [event]
|
||||
(dom/prevent-default event)
|
||||
(modal/hide!))]
|
||||
|
||||
(mf/use-effect
|
||||
#(st/emit! (dw/fetch-shared-files)))
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal.libraries-dialog
|
||||
[:a.close {:on-click close} i/close]
|
||||
[:div.modal-content
|
||||
[:div.libraries-header
|
||||
[:div.header-item
|
||||
{:class (classnames :active (= current-tab :libraries))
|
||||
:on-click #(change-tab :libraries)}
|
||||
(tr "workspace.libraries.libraries")]
|
||||
[:div.header-item
|
||||
{:class (classnames :active (= current-tab :updates))
|
||||
:on-click #(change-tab :updates)}
|
||||
(tr "workspace.libraries.updates")]]
|
||||
[:div.libraries-content
|
||||
(case current-tab
|
||||
:libraries
|
||||
[:& libraries-tab {:file file
|
||||
:libraries libraries
|
||||
:shared-files shared-files}]
|
||||
:updates
|
||||
[:& updates-tab {}])]]]]))
|
||||
|
|
@ -29,20 +29,14 @@
|
|||
[uxbox.util.timers :as timers]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.data :refer [classnames matches-search]]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.main.ui.colorpicker :refer [colorpicker most-used-colors]]
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[uxbox.main.ui.components.file-uploader :refer [file-uploader]]
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
||||
|
||||
(defn matches-search
|
||||
[name search-term]
|
||||
(if (str/empty? search-term)
|
||||
true
|
||||
(let [st (str/trim (str/lower search-term))
|
||||
nm (str/trim (str/lower name))]
|
||||
(str/includes? nm st))))
|
||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]
|
||||
[uxbox.main.ui.workspace.libraries :refer [libraries-dialog]]))
|
||||
|
||||
(mf/defc modal-edit-color
|
||||
[{:keys [color-value on-accept on-cancel] :as ctx}]
|
||||
|
@ -72,7 +66,7 @@
|
|||
[:a.close {:href "#" :on-click cancel} i/close]]])))
|
||||
|
||||
(mf/defc graphics-box
|
||||
[{:keys [file-id media-objects] :as props}]
|
||||
[{:keys [file-id local-library? media-objects] :as props}]
|
||||
(let [state (mf/use-state {:menu-open false
|
||||
:top nil
|
||||
:left nil
|
||||
|
@ -84,7 +78,7 @@
|
|||
#(dom/click (mf/ref-val file-input))
|
||||
|
||||
delete-graphic
|
||||
#(st/emit! (dw/delete-media-object (:object-id @state)))
|
||||
#(st/emit! (dw/delete-media-object file-id (:object-id @state)))
|
||||
|
||||
on-files-selected
|
||||
(fn [js-files]
|
||||
|
@ -93,14 +87,15 @@
|
|||
on-context-menu
|
||||
(fn [object-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
|
||||
:object-id object-id))))
|
||||
(when local-library?
|
||||
(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
|
||||
:object-id object-id)))))
|
||||
|
||||
on-drag-start
|
||||
(fn [uri]
|
||||
|
@ -112,14 +107,15 @@
|
|||
[:div.group-title
|
||||
(tr "workspace.assets.graphics")
|
||||
[:span (str "\u00A0(") (count media-objects) ")"] ;; Unicode 00A0 is non-breaking space
|
||||
[:div.group-button {:on-click add-graphic}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-media-types
|
||||
:multi true
|
||||
:input-ref file-input
|
||||
:on-selected on-files-selected}]]]
|
||||
(when local-library?
|
||||
[:div.group-button {:on-click add-graphic}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-media-types
|
||||
:multi true
|
||||
:input-ref file-input
|
||||
:on-selected on-files-selected}]])]
|
||||
[:div.group-grid
|
||||
(for [object (sort-by :name media-objects)]
|
||||
(for [object media-objects]
|
||||
[:div.grid-cell {:key (:id object)
|
||||
:draggable true
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
|
@ -127,17 +123,18 @@
|
|||
[:img {:src (:thumb-uri object)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
[:div.cell-name (:name object)]])
|
||||
[:& 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]]}]]]))
|
||||
(when local-library?
|
||||
[:& 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 color-item
|
||||
[{:keys [color file-id] :as props}]
|
||||
[{:keys [color file-id local-library?] :as props}]
|
||||
(let [workspace-local @refs/workspace-local
|
||||
color-for-rename (:color-for-rename workspace-local)
|
||||
|
||||
|
@ -189,14 +186,15 @@
|
|||
|
||||
on-context-menu
|
||||
(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)))]
|
||||
(when local-library?
|
||||
(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))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps (:editing @state))
|
||||
|
@ -220,18 +218,19 @@
|
|||
(:name color)
|
||||
(when-not (= (:name color) (:content color))
|
||||
[:span (:content color)])])
|
||||
[:& 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.rename") rename-color-clicked]
|
||||
[(tr "workspace.assets.edit") edit-color-clicked]
|
||||
[(tr "workspace.assets.delete") delete-color]]}]]))
|
||||
(when local-library?
|
||||
[:& 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.rename") rename-color-clicked]
|
||||
[(tr "workspace.assets.edit") edit-color-clicked]
|
||||
[(tr "workspace.assets.delete") delete-color]]}])]))
|
||||
|
||||
(mf/defc colors-box
|
||||
[{:keys [file-id colors] :as props}]
|
||||
[{:keys [file-id local-library? colors] :as props}]
|
||||
(let [add-color
|
||||
(fn [value opacity]
|
||||
(st/emit! (dcol/create-color file-id value)))
|
||||
|
@ -246,15 +245,18 @@
|
|||
[:div.group-title
|
||||
(tr "workspace.assets.colors")
|
||||
[:span (str "\u00A0(") (count colors) ")"] ;; Unicode 00A0 is non-breaking space
|
||||
[:div.group-button {:on-click add-color-clicked} i/plus]]
|
||||
(when local-library?
|
||||
[:div.group-button {:on-click add-color-clicked} i/plus])]
|
||||
[:div.group-list
|
||||
(for [color (sort-by :name colors)]
|
||||
(for [color colors]
|
||||
[:& color-item {:key (:id color)
|
||||
:color color
|
||||
:file-id file-id}])]]))
|
||||
:file-id file-id
|
||||
:local-library? local-library?}])]]))
|
||||
|
||||
(mf/defc file-library-toolbox
|
||||
[{:keys [file-id
|
||||
[{:keys [library
|
||||
local-library?
|
||||
shared?
|
||||
media-objects
|
||||
colors
|
||||
|
@ -262,26 +264,41 @@
|
|||
search-term
|
||||
box-filter] :as props}]
|
||||
(let [open? (mf/use-state initial-open?)
|
||||
toggle-open #(swap! open? not)]
|
||||
toggle-open #(swap! open? not)
|
||||
router (mf/deref refs/router)
|
||||
library-url (rt/resolve router :workspace
|
||||
{:project-id (:project-id library)
|
||||
:file-id (:id library)}
|
||||
{:page-id (first (:pages library))})]
|
||||
[: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 shared?
|
||||
[:span.tool-badge (tr "workspace.assets.shared")])]
|
||||
(if local-library?
|
||||
[:*
|
||||
[:span (tr "workspace.assets.file-library")]
|
||||
(when shared?
|
||||
[:span.tool-badge (tr "workspace.assets.shared")])]
|
||||
[:*
|
||||
[:span (:name library)]
|
||||
[:span.tool-link
|
||||
[:a {:href (str "#" library-url) :target "_blank"} i/chain]]])]
|
||||
(when @open?
|
||||
(let [show-graphics (and (or (= box-filter :all) (= box-filter :graphics))
|
||||
(or (> (count media-objects) 0) (str/empty? search-term)))
|
||||
show-colors (and (or (= box-filter :all) (= box-filter :colors))
|
||||
(or (> (count colors) 0) (str/empty? search-term)))]
|
||||
(or (> (count media-objects) 0) (str/empty? search-term)))
|
||||
show-colors (and (or (= box-filter :all) (= box-filter :colors))
|
||||
(or (> (count colors) 0) (str/empty? search-term)))]
|
||||
[:div.tool-window-content
|
||||
(when show-graphics
|
||||
[:& graphics-box {:file-id file-id :media-objects media-objects}])
|
||||
[:& graphics-box {:file-id (:id library)
|
||||
:local-library? local-library?
|
||||
:media-objects media-objects}])
|
||||
(when show-colors
|
||||
[:& colors-box {:file-id file-id :colors colors}])
|
||||
[:& colors-box {:file-id (:id library)
|
||||
:local-library? local-library?
|
||||
:colors colors}])
|
||||
(when (and (not show-graphics) (not show-colors))
|
||||
[:div.asset-group
|
||||
[:div.group-title (tr "workspace.assets.not-found")]])]))]))
|
||||
|
@ -290,19 +307,27 @@
|
|||
[]
|
||||
(let [team-id (-> refs/workspace-project mf/deref :team-id)
|
||||
file (mf/deref refs/workspace-file)
|
||||
file-id (:id file)
|
||||
file-media (mf/deref refs/workspace-media-library)
|
||||
file-colors (mf/deref refs/workspace-colors-library)
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
sorted-libraries (->> (vals libraries)
|
||||
(sort-by #(str/lower (:name %))))
|
||||
|
||||
state (mf/use-state {:search-term ""
|
||||
:box-filter :all})
|
||||
|
||||
filtered-media-objects (filter #(matches-search (:name %) (:search-term @state))
|
||||
(vals file-media))
|
||||
filtered-media-objects (fn [library-id]
|
||||
(as-> libraries $$
|
||||
(assoc $$ (:id file) file)
|
||||
(get-in $$ [library-id :media-objects])
|
||||
(filter #(matches-search (:name %) (:search-term @state)) $$)
|
||||
(sort-by #(str/lower (:name %)) $$)))
|
||||
|
||||
filtered-colors (filter #(or (matches-search (:name %) (:search-term @state))
|
||||
(matches-search (:content %) (:search-term @state)))
|
||||
(vals file-colors))
|
||||
filtered-colors (fn [library-id]
|
||||
(as-> libraries $$
|
||||
(assoc $$ (:id file) file)
|
||||
(get-in $$ [library-id :colors])
|
||||
(filter #(or (matches-search (:name %) (:search-term @state))
|
||||
(matches-search (:content %) (:search-term @state))) $$)
|
||||
(sort-by #(str/lower (:name %)) $$)))
|
||||
|
||||
on-search-term-change (fn [event]
|
||||
(let [value (-> (dom/get-target event)
|
||||
|
@ -318,17 +343,15 @@
|
|||
(d/read-string))]
|
||||
(swap! state assoc :box-filter value)))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps file-id)
|
||||
#(when file-id
|
||||
(st/emit! (dw/fetch-media-library file-id))
|
||||
(st/emit! (dw/fetch-colors-library file-id))))
|
||||
|
||||
[:div.assets-bar
|
||||
|
||||
[:div.tool-window
|
||||
[:div.tool-window-content
|
||||
[:div.assets-bar-title (tr "workspace.assets.assets")]
|
||||
[:div.assets-bar-title
|
||||
(tr "workspace.assets.assets")
|
||||
[:div.libraries-button {:on-click #(modal/show! libraries-dialog {})}
|
||||
i/libraries
|
||||
(tr "workspace.assets.libraries")]]
|
||||
|
||||
[:div.search-block
|
||||
[:input.search-input
|
||||
|
@ -347,14 +370,25 @@
|
|||
: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")]]
|
||||
]]
|
||||
[:option {:value ":colors"} (tr "workspace.assets.box-filter-colors")]]]]
|
||||
|
||||
[:& file-library-toolbox {:file-id file-id
|
||||
[:& file-library-toolbox {:key (:id file)
|
||||
:library file
|
||||
:local-library? true
|
||||
:shared? (:is-shared file)
|
||||
:media-objects filtered-media-objects
|
||||
:colors filtered-colors
|
||||
:media-objects (filtered-media-objects (:id file))
|
||||
:colors (filtered-colors (:id file))
|
||||
:initial-open? true
|
||||
:search-term (:search-term @state)
|
||||
:box-filter (:box-filter @state)}]]))
|
||||
:box-filter (:box-filter @state)}]
|
||||
(for [library sorted-libraries]
|
||||
[:& file-library-toolbox {:key (:id library)
|
||||
:library library
|
||||
:local-library? false
|
||||
:shared? (:is-shared library)
|
||||
:media-objects (filtered-media-objects (:id library))
|
||||
:colors (filtered-colors (:id library))
|
||||
:initial-open? false
|
||||
:search-term (:search-term @state)
|
||||
:box-filter (:box-filter @state)}])]))
|
||||
|
||||
|
|
|
@ -180,6 +180,13 @@
|
|||
"className"
|
||||
(str/camel (name key))))))
|
||||
|
||||
(defn matches-search
|
||||
[name search-term]
|
||||
(if (str/empty? search-term)
|
||||
true
|
||||
(let [st (str/trim (str/lower search-term))
|
||||
nm (str/trim (str/lower name))]
|
||||
(str/includes? nm st))))
|
||||
|
||||
;; (defn coalesce
|
||||
;; [^number v ^number n]
|
||||
|
|
Loading…
Add table
Reference in a new issue