mirror of
https://github.com/penpot/penpot.git
synced 2025-05-11 14:46:37 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
806dc78d2b
22 changed files with 672 additions and 330 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
export PENPOT_ASSERTS_ENABLED=true
|
export PENPOT_ASSERTS_ENABLED=true
|
||||||
|
|
||||||
export OPTIONS="-A:jmx-remote:dev -J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -J-Xms512m -J-Xmx512m -J-Dlog4j2.configurationFile=log4j2-devenv.xml";
|
export OPTIONS="-A:jmx-remote:dev -J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -J-Dlog4j2.configurationFile=log4j2-devenv.xml -J-XX:+UseZGC -J-XX:ConcGCThreads=1 -J-XX:-OmitStackTraceInFastThrow -J-Xms50m -J-Xmx512m";
|
||||||
# export OPTIONS="$OPTIONS -J-XX:+UnlockDiagnosticVMOptions";
|
# export OPTIONS="$OPTIONS -J-XX:+UnlockDiagnosticVMOptions";
|
||||||
# export OPTIONS="$OPTIONS -J-XX:-TieredCompilation -J-XX:CompileThreshold=10000";
|
# export OPTIONS="$OPTIONS -J-XX:-TieredCompilation -J-XX:CompileThreshold=10000";
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,43 @@
|
||||||
CREATE TABLE team_font_variant (
|
CREATE TABLE team_font_variant (
|
||||||
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
|
||||||
team_id uuid NOT NULL REFERENCES team(id) ON DELETE CASCADE,
|
team_id uuid NOT NULL REFERENCES team(id) ON DELETE CASCADE DEFERRABLE,
|
||||||
profile_id uuid NULL REFERENCES profile(id) ON DELETE SET NULL,
|
profile_id uuid NULL REFERENCES profile(id) ON DELETE SET NULL DEFERRABLE,
|
||||||
|
|
||||||
created_at timestamptz NOT NULL DEFAULT now(),
|
created_at timestamptz NOT NULL DEFAULT now(),
|
||||||
modified_at timestamptz NOT NULL DEFAULT now(),
|
modified_at timestamptz NOT NULL DEFAULT now(),
|
||||||
deleted_at timestamptz NULL DEFAULT NULL,
|
deleted_at timestamptz NULL DEFAULT NULL,
|
||||||
|
|
||||||
font_id text NOT NULL,
|
font_id uuid NOT NULL,
|
||||||
font_family text NOT NULL,
|
font_family text NOT NULL,
|
||||||
font_weight smallint NOT NULL,
|
font_weight smallint NOT NULL,
|
||||||
font_style text NOT NULL,
|
font_style text NOT NULL,
|
||||||
|
|
||||||
otf_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL,
|
otf_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL DEFERRABLE,
|
||||||
ttf_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL,
|
ttf_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL DEFERRABLE,
|
||||||
woff1_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL,
|
woff1_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL DEFERRABLE,
|
||||||
woff2_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL
|
woff2_file_id uuid NULL REFERENCES storage_object(id) ON DELETE SET NULL DEFERRABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_team_id_font_id_idx
|
||||||
|
ON team_font_variant (team_id, font_id);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_profile_id_idx
|
||||||
|
ON team_font_variant (profile_id);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_otf_file_id_idx
|
||||||
|
ON team_font_variant (otf_file_id);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_ttf_file_id_idx
|
||||||
|
ON team_font_variant (ttf_file_id);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_woff1_file_id_idx
|
||||||
|
ON team_font_variant (woff1_file_id);
|
||||||
|
|
||||||
|
CREATE INDEX team_font_variant_woff2_file_id_idx
|
||||||
|
ON team_font_variant (woff2_file_id);
|
||||||
|
|
||||||
|
ALTER TABLE team_font_variant
|
||||||
|
ALTER COLUMN font_family SET STORAGE external,
|
||||||
|
ALTER COLUMN font_style SET STORAGE external;
|
||||||
|
|
||||||
|
|
|
@ -16,20 +16,20 @@
|
||||||
[app.util.services :as sv]
|
[app.util.services :as sv]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[app.worker :as wrk]
|
[app.worker :as wrk]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]))
|
||||||
[cuerdas.core :as str]))
|
|
||||||
|
|
||||||
(declare create-font-variant)
|
(declare create-font-variant)
|
||||||
|
|
||||||
(def valid-weight #{100 200 300 400 500 600 700 800 900 950})
|
(def valid-weight #{100 200 300 400 500 600 700 800 900 950})
|
||||||
(def valid-style #{"normal" "italic"})
|
(def valid-style #{"normal" "italic"})
|
||||||
|
|
||||||
|
(s/def ::id ::us/uuid)
|
||||||
(s/def ::profile-id ::us/uuid)
|
(s/def ::profile-id ::us/uuid)
|
||||||
(s/def ::team-id ::us/uuid)
|
(s/def ::team-id ::us/uuid)
|
||||||
(s/def ::name ::us/not-empty-string)
|
(s/def ::name ::us/not-empty-string)
|
||||||
(s/def ::weight valid-weight)
|
(s/def ::weight valid-weight)
|
||||||
(s/def ::style valid-style)
|
(s/def ::style valid-style)
|
||||||
(s/def ::font-id (s/and ::us/string #(str/starts-with? % "custom-")))
|
(s/def ::font-id ::us/uuid)
|
||||||
(s/def ::content-type ::media/font-content-type)
|
(s/def ::content-type ::media/font-content-type)
|
||||||
(s/def ::data (s/map-of ::us/string any?))
|
(s/def ::data (s/map-of ::us/string any?))
|
||||||
|
|
||||||
|
@ -76,29 +76,57 @@
|
||||||
:otf-file-id (:id otf)
|
:otf-file-id (:id otf)
|
||||||
:ttf-file-id (:id ttf)})))
|
:ttf-file-id (:id ttf)})))
|
||||||
|
|
||||||
;; --- UPDATE FONT VARIANT
|
;; --- UPDATE FONT FAMILY
|
||||||
|
|
||||||
(s/def ::update-font-variant
|
(s/def ::update-font
|
||||||
(s/keys :req-un [::profile-id ::team-id ::id ::font-family ::font-id]))
|
(s/keys :req-un [::profile-id ::team-id ::id ::name]))
|
||||||
|
|
||||||
(sv/defmethod ::update-font-variant
|
(def sql:update-font
|
||||||
[{:keys [pool] :as cfg} {:keys [id team-id profile-id font-family font-id] :as params}]
|
"update team_font_variant
|
||||||
|
set font_family = ?
|
||||||
|
where team_id = ?
|
||||||
|
and font_id = ?")
|
||||||
|
|
||||||
|
(sv/defmethod ::update-font
|
||||||
|
[{:keys [pool] :as cfg} {:keys [team-id profile-id id name] :as params}]
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(teams/check-edition-permissions! conn profile-id team-id)
|
(teams/check-edition-permissions! conn profile-id team-id)
|
||||||
(db/update! conn :team-font-variant
|
(db/exec-one! conn [sql:update-font name team-id id])
|
||||||
{:font-family font-family
|
|
||||||
:font-id font-id}
|
|
||||||
{:id id
|
|
||||||
:team-id team-id})
|
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
|
;; --- DELETE FONT
|
||||||
|
|
||||||
|
(s/def ::delete-font
|
||||||
|
(s/keys :req-un [::profile-id ::team-id ::id]))
|
||||||
|
|
||||||
|
(sv/defmethod ::delete-font
|
||||||
|
[{:keys [pool] :as cfg} {:keys [id team-id profile-id] :as params}]
|
||||||
|
(db/with-atomic [conn pool]
|
||||||
|
(teams/check-edition-permissions! conn profile-id team-id)
|
||||||
|
|
||||||
|
(let [items (db/query conn :team-font-variant
|
||||||
|
{:font-id id :team-id team-id}
|
||||||
|
{:for-update true})]
|
||||||
|
(doseq [item items]
|
||||||
|
;; Schedule object deletion
|
||||||
|
(wrk/submit! {::wrk/task :delete-object
|
||||||
|
::wrk/delay cf/deletion-delay
|
||||||
|
::wrk/conn conn
|
||||||
|
:id (:id item)
|
||||||
|
:type :team-font-variant}))
|
||||||
|
|
||||||
|
(db/update! conn :team-font-variant
|
||||||
|
{:deleted-at (dt/now)}
|
||||||
|
{:font-id id :team-id team-id})
|
||||||
|
nil)))
|
||||||
|
|
||||||
;; --- DELETE FONT VARIANT
|
;; --- DELETE FONT VARIANT
|
||||||
|
|
||||||
(s/def ::delete-font-variant
|
(s/def ::delete-font-variant
|
||||||
(s/keys :req-un [::profile-id ::team-id ::id]))
|
(s/keys :req-un [::profile-id ::team-id ::id]))
|
||||||
|
|
||||||
(sv/defmethod ::delete-font-variant
|
(sv/defmethod ::delete-font-variant
|
||||||
[{:keys [pool] :as cfg} {:keys [id team-id profile-id font-family font-id] :as params}]
|
[{:keys [pool] :as cfg} {:keys [id team-id profile-id] :as params}]
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(teams/check-edition-permissions! conn profile-id team-id)
|
(teams/check-edition-permissions! conn profile-id team-id)
|
||||||
|
|
||||||
|
@ -111,6 +139,5 @@
|
||||||
|
|
||||||
(db/update! conn :team-font-variant
|
(db/update! conn :team-font-variant
|
||||||
{:deleted-at (dt/now)}
|
{:deleted-at (dt/now)}
|
||||||
{:id id
|
{:id id :team-id team-id})
|
||||||
:team-id team-id})
|
|
||||||
nil))
|
nil))
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
(let [prof (th/create-profile* 1 {:is-active true})
|
(let [prof (th/create-profile* 1 {:is-active true})
|
||||||
team-id (:default-team-id prof)
|
team-id (:default-team-id prof)
|
||||||
proj-id (:default-project-id prof)
|
proj-id (:default-project-id prof)
|
||||||
|
font-id (uuid/custom 10 1)
|
||||||
|
|
||||||
ttfdata (-> (io/resource "app/tests/_files/font-1.ttf")
|
ttfdata (-> (io/resource "app/tests/_files/font-1.ttf")
|
||||||
(fs/slurp-bytes))
|
(fs/slurp-bytes))
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
params {::th/type :create-font-variant
|
params {::th/type :create-font-variant
|
||||||
:profile-id (:id prof)
|
:profile-id (:id prof)
|
||||||
:team-id team-id
|
:team-id team-id
|
||||||
:font-id "custom-somefont"
|
:font-id font-id
|
||||||
:font-family "somefont"
|
:font-family "somefont"
|
||||||
:font-weight 400
|
:font-weight 400
|
||||||
:font-style "normal"
|
:font-style "normal"
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
(let [prof (th/create-profile* 1 {:is-active true})
|
(let [prof (th/create-profile* 1 {:is-active true})
|
||||||
team-id (:default-team-id prof)
|
team-id (:default-team-id prof)
|
||||||
proj-id (:default-project-id prof)
|
proj-id (:default-project-id prof)
|
||||||
|
font-id (uuid/custom 10 1)
|
||||||
|
|
||||||
data (-> (io/resource "app/tests/_files/font-1.woff")
|
data (-> (io/resource "app/tests/_files/font-1.woff")
|
||||||
(fs/slurp-bytes))
|
(fs/slurp-bytes))
|
||||||
|
@ -63,7 +65,7 @@
|
||||||
params {::th/type :create-font-variant
|
params {::th/type :create-font-variant
|
||||||
:profile-id (:id prof)
|
:profile-id (:id prof)
|
||||||
:team-id team-id
|
:team-id team-id
|
||||||
:font-id "custom-somefont"
|
:font-id font-id
|
||||||
:font-family "somefont"
|
:font-family "somefont"
|
||||||
:font-weight 400
|
:font-weight 400
|
||||||
:font-style "normal"
|
:font-style "normal"
|
||||||
|
|
|
@ -69,17 +69,17 @@
|
||||||
(defn parse-font-weight
|
(defn parse-font-weight
|
||||||
[variant]
|
[variant]
|
||||||
(cond
|
(cond
|
||||||
(re-seq #"(?i)(?:hairline|thin)" variant) 100
|
(re-seq #"(?i)(?:hairline|thin)" variant) 100
|
||||||
(re-seq #"(?i)(?:extra light|ultra light)" variant) 200
|
(re-seq #"(?i)(?:extra\s*light|ultra\s*light)" variant) 200
|
||||||
(re-seq #"(?i)(?:light)" variant) 300
|
(re-seq #"(?i)(?:light)" variant) 300
|
||||||
(re-seq #"(?i)(?:normal|regular)" variant) 400
|
(re-seq #"(?i)(?:normal|regular)" variant) 400
|
||||||
(re-seq #"(?i)(?:medium)" variant) 500
|
(re-seq #"(?i)(?:medium)" variant) 500
|
||||||
(re-seq #"(?i)(?:semi bold|demi bold)" variant) 600
|
(re-seq #"(?i)(?:semi\s*bold|demi\s*bold)" variant) 600
|
||||||
(re-seq #"(?i)(?:bold)" variant) 700
|
(re-seq #"(?i)(?:extra\s*bold|ultra\s*bold)" variant) 800
|
||||||
(re-seq #"(?i)(?:extra bold|ultra bold)" variant) 800
|
(re-seq #"(?i)(?:bold)" variant) 700
|
||||||
(re-seq #"(?i)(?:black|heavy)" variant) 900
|
(re-seq #"(?i)(?:extra\s*black|ultra\s*black)" variant) 950
|
||||||
(re-seq #"(?i)(?:extra black|ultra black)" variant) 950
|
(re-seq #"(?i)(?:black|heavy)" variant) 900
|
||||||
:else 400))
|
:else 400))
|
||||||
|
|
||||||
(defn parse-font-style
|
(defn parse-font-style
|
||||||
[variant]
|
[variant]
|
||||||
|
|
BIN
frontend/resources/images/features/custom-fonts.gif
Normal file
BIN
frontend/resources/images/features/custom-fonts.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/resources/images/features/performance.gif
Normal file
BIN
frontend/resources/images/features/performance.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 679 KiB |
BIN
frontend/resources/images/features/scale-text.gif
Normal file
BIN
frontend/resources/images/features/scale-text.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 472 KiB |
BIN
frontend/resources/images/features/shapes-to-path.gif
Normal file
BIN
frontend/resources/images/features/shapes-to-path.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 310 KiB |
|
@ -23,6 +23,7 @@ $color-info: #59b9e2;
|
||||||
$color-ocean: #4285f4;
|
$color-ocean: #4285f4;
|
||||||
$color-component: #76B0B8;
|
$color-component: #76B0B8;
|
||||||
$color-component-highlight: #00E0FF;
|
$color-component-highlight: #00E0FF;
|
||||||
|
$color-pink: #feecfc;
|
||||||
|
|
||||||
// Gray scale
|
// Gray scale
|
||||||
$color-gray-10: #E3E3E3;
|
$color-gray-10: #E3E3E3;
|
||||||
|
|
|
@ -30,8 +30,13 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0px $big;
|
padding: 0px $big;
|
||||||
|
|
||||||
> div {
|
> .family {
|
||||||
width: 30%;
|
min-width: 200px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .variants {
|
||||||
|
padding-left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
|
@ -50,20 +55,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fonts-group {
|
|
||||||
margin-top: $big;
|
|
||||||
}
|
|
||||||
|
|
||||||
.font-item {
|
.font-item {
|
||||||
|
margin-top: $big;
|
||||||
color: $color-gray-40;
|
color: $color-gray-40;
|
||||||
font-size: $fs14;
|
font-size: $fs14;
|
||||||
background-color: $color-white;
|
background-color: $color-white;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: 1000px;
|
min-width: 1000px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 97px;
|
min-height: 97px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: $big;
|
padding: $big;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
border-top: 1px solid $color-gray-10;
|
border-top: 1px solid $color-gray-10;
|
||||||
|
@ -77,14 +80,52 @@
|
||||||
font-size: $fs12;
|
font-size: $fs12;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .family {
|
||||||
width: 30%;
|
min-width: 200px;
|
||||||
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variant {
|
> .filenames {
|
||||||
font-size: $fs14;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .variants {
|
||||||
|
font-size: $fs14;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.variant {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: flex;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
margin-left: 6px;
|
||||||
|
align-items: center;
|
||||||
|
svg {
|
||||||
|
fill: transparent;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.icon svg {
|
||||||
|
fill: $color-gray-30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.filenames {
|
.filenames {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -117,7 +158,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.dashboard-fonts-upload {
|
.dashboard-fonts-upload {
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -164,4 +204,31 @@
|
||||||
color: $color-gray-40;
|
color: $color-gray-40;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fonts-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 1000px;
|
||||||
|
width: 100%;
|
||||||
|
height: 161px;
|
||||||
|
|
||||||
|
border: 1px dashed $color-gray-20;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
svg {
|
||||||
|
fill: $color-gray-40;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: $color-gray-40;
|
||||||
|
font-size: $fs14;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,7 +382,7 @@
|
||||||
|
|
||||||
.modal-left {
|
.modal-left {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: $color-primary;
|
background-color: $color-pink;
|
||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
border-bottom-left-radius: 5px;
|
border-bottom-left-radius: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -391,6 +391,10 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: $x-big;
|
padding: $x-big;
|
||||||
width: 230px;
|
width: 230px;
|
||||||
|
|
||||||
|
&.welcome {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-right {
|
.modal-right {
|
||||||
|
@ -498,6 +502,7 @@
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
overflow: visible;
|
||||||
padding: $x-big 40px;
|
padding: $x-big 40px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{:http {:port 3448}
|
{:http {:port 3448}
|
||||||
:nrepl {:port 3447}
|
:nrepl {:port 3447}
|
||||||
:jvm-opts ["-Xmx600m" "-Xms50m" "-XX:+UseSerialGC"]
|
:jvm-opts ["-Xmx700m" "-Xms100m" "-XX:+UseSerialGC" "-XX:-OmitStackTraceInFastThrow"]
|
||||||
:dev-http {8888 "classpath:public"}
|
:dev-http {8888 "classpath:public"}
|
||||||
|
|
||||||
:source-paths ["src", "vendor", "resources", "../common", "tests", "dev"]
|
:source-paths ["src", "vendor", "resources", "../common", "tests", "dev"]
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
;; 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) UXBOX Labs SL
|
|
||||||
|
|
||||||
(ns app.main.data.dashboard.fonts
|
|
||||||
(:require
|
|
||||||
[app.common.exceptions :as ex]
|
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.media :as cm]
|
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.uuid :as uuid]
|
|
||||||
[app.main.repo :as rp]
|
|
||||||
[app.util.time :as dt]
|
|
||||||
[app.util.timers :as ts]
|
|
||||||
[app.main.data.messages :as dm]
|
|
||||||
[app.util.webapi :as wa]
|
|
||||||
[app.util.object :as obj]
|
|
||||||
[app.util.transit :as t]
|
|
||||||
[beicon.core :as rx]
|
|
||||||
[cljs.spec.alpha :as s]
|
|
||||||
[cuerdas.core :as str]
|
|
||||||
[potok.core :as ptk]))
|
|
||||||
|
|
||||||
(defn fetch-fonts
|
|
||||||
[{:keys [id] :as team}]
|
|
||||||
(ptk/reify ::fetch-fonts
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(->> (rp/query! :team-font-variants {:team-id id})
|
|
||||||
(rx/map (fn [items]
|
|
||||||
#(assoc % :dashboard-fonts (d/index-by :id items))))))))
|
|
||||||
|
|
||||||
(defn add-font
|
|
||||||
[font]
|
|
||||||
(ptk/reify ::add-font
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update state :dashboard-fonts assoc (:id font) font))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn update-font
|
|
||||||
[{:keys [id font-family] :as font}]
|
|
||||||
(ptk/reify ::update-font
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [font (assoc font :font-id (str "custom-" (str/slug font-family)))]
|
|
||||||
(update state :dashboard-fonts assoc id font)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [font (get-in state [:dashboard-fonts id])]
|
|
||||||
(->> (rp/mutation! :update-font-variant font)
|
|
||||||
(rx/ignore))))))
|
|
||||||
|
|
||||||
(defn delete-font
|
|
||||||
[{:keys [id] :as font}]
|
|
||||||
(ptk/reify ::delete-font
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update state :dashboard-fonts dissoc id))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [params (select-keys font [:id :team-id])]
|
|
||||||
(->> (rp/mutation! :delete-font-variant params)
|
|
||||||
(rx/ignore))))))
|
|
||||||
|
|
||||||
;; (defn upload-font
|
|
||||||
;; [{:keys [id] :as font}]
|
|
||||||
;; (ptk/reify ::upload-font
|
|
||||||
;; ptk/WatchEvent
|
|
||||||
;; (watch [_ state stream]
|
|
||||||
;; (let [{:keys [on-success on-error]
|
|
||||||
;; :or {on-success identity
|
|
||||||
;; on-error rx/throw}} (meta params)]
|
|
||||||
;; (->> (rp/mutation! :create-font-variant font)
|
|
||||||
;; (rx/tap on-success)
|
|
||||||
;; (rx/catch on-error))))))
|
|
||||||
|
|
||||||
;; (defn add-font
|
|
||||||
;; "Add fonts to the state in a pending to upload state."
|
|
||||||
;; [font]
|
|
||||||
;; (ptk/reify ::add-font
|
|
||||||
;; ptk/UpdateEvent
|
|
||||||
;; (update [_ state]
|
|
||||||
;; (let [id (uuid/next)
|
|
||||||
;; font (-> font
|
|
||||||
;; (assoc :created-at (dt/now))
|
|
||||||
;; (assoc :id id)
|
|
||||||
;; (assoc :status :draft))]
|
|
||||||
;; (js/console.log (clj->js font))
|
|
||||||
;; (assoc-in state [:dashboard-fonts id] font)))))
|
|
|
@ -6,42 +6,68 @@
|
||||||
|
|
||||||
(ns app.main.data.fonts
|
(ns app.main.data.fonts
|
||||||
(:require
|
(:require
|
||||||
|
["opentype.js" :as ot]
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.spec :as us]
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[app.util.logging :as log]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
|
[app.util.webapi :as wa]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]))
|
[potok.core :as ptk]))
|
||||||
|
|
||||||
(defn prepare-font-variant
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
[item]
|
;; General purpose events & IMPL
|
||||||
{:id (str (:font-style item) "-" (:font-weight item))
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
:name (str (cm/font-weight->name (:font-weight item)) " "
|
|
||||||
(str/capital (:font-style item)))
|
|
||||||
:style (:font-style item)
|
|
||||||
:weight (str (:font-weight item))
|
|
||||||
::fonts/woff1-file-id (:woff1-file-id item)
|
|
||||||
::fonts/woff2-file-id (:woff2-file-id item)
|
|
||||||
::fonts/ttf-file-id (:ttf-file-id item)
|
|
||||||
::fonts/otf-file-id (:otf-file-id item)})
|
|
||||||
|
|
||||||
(defn prepare-font
|
|
||||||
[[id [item :as items]]]
|
|
||||||
{:id id
|
|
||||||
:name (:font-family item)
|
|
||||||
:family (:font-family item)
|
|
||||||
:variants (mapv prepare-font-variant items)})
|
|
||||||
|
|
||||||
(defn team-fonts-loaded
|
(defn team-fonts-loaded
|
||||||
[fonts]
|
[fonts]
|
||||||
(ptk/reify ::team-fonts-loaded
|
(letfn [;; Prepare font to the internal font database format.
|
||||||
ptk/EffectEvent
|
(prepare-font [[id [item :as items]]]
|
||||||
(effect [_ state stream]
|
{:id id
|
||||||
(let [fonts (->> (group-by :font-id fonts)
|
:name (:font-family item)
|
||||||
(mapv prepare-font))]
|
:family (:font-family item)
|
||||||
(fonts/register! :custom fonts)))))
|
:variants (->> items
|
||||||
|
(map prepare-font-variant)
|
||||||
|
(sort-by variant-sort-fn)
|
||||||
|
(vec))})
|
||||||
|
|
||||||
|
(variant-sort-fn [item]
|
||||||
|
[(:weight item)
|
||||||
|
(if (= "normal" (:style item)) 1 2)])
|
||||||
|
|
||||||
|
(prepare-font-variant [item]
|
||||||
|
{:id (str (:font-style item) "-" (:font-weight item))
|
||||||
|
:name (str (cm/font-weight->name (:font-weight item))
|
||||||
|
(when (not= "normal" (:font-style item))
|
||||||
|
(str " " (str/capital (:font-style item)))))
|
||||||
|
:style (:font-style item)
|
||||||
|
:weight (str (:font-weight item))
|
||||||
|
::fonts/woff1-file-id (:woff1-file-id item)
|
||||||
|
::fonts/woff2-file-id (:woff2-file-id item)
|
||||||
|
::fonts/ttf-file-id (:ttf-file-id item)
|
||||||
|
::fonts/otf-file-id (:otf-file-id item)})
|
||||||
|
|
||||||
|
(adapt-font-id [variant]
|
||||||
|
(update variant :font-id #(str "custom-" %)))]
|
||||||
|
|
||||||
|
(ptk/reify ::team-fonts-loaded
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc state :dashboard-fonts (d/index-by :id fonts)))
|
||||||
|
|
||||||
|
ptk/EffectEvent
|
||||||
|
(effect [_ state stream]
|
||||||
|
(let [fonts (->> fonts
|
||||||
|
(map adapt-font-id)
|
||||||
|
(group-by :font-id)
|
||||||
|
(mapv prepare-font))]
|
||||||
|
(fonts/register! :custom fonts))))))
|
||||||
|
|
||||||
(defn load-team-fonts
|
(defn load-team-fonts
|
||||||
[team-id]
|
[team-id]
|
||||||
|
@ -51,7 +77,168 @@
|
||||||
(->> (rp/query :team-font-variants {:team-id team-id})
|
(->> (rp/query :team-font-variants {:team-id team-id})
|
||||||
(rx/map team-fonts-loaded)))))
|
(rx/map team-fonts-loaded)))))
|
||||||
|
|
||||||
|
(defn process-upload
|
||||||
|
"Given a seq of blobs and the team id, creates a ready-to-use fonts
|
||||||
|
map with temporal ID's associated to each font entry."
|
||||||
|
[blobs team-id]
|
||||||
|
(letfn [(prepare [{:keys [font type name data] :as params}]
|
||||||
|
(let [family (or (.getEnglishName ^js font "preferredFamily")
|
||||||
|
(.getEnglishName ^js font "fontFamily"))
|
||||||
|
variant (or (.getEnglishName ^js font "preferredSubfamily")
|
||||||
|
(.getEnglishName ^js font "fontSubfamily"))]
|
||||||
|
{:content {:data (js/Uint8Array. data)
|
||||||
|
:name name
|
||||||
|
:type type}
|
||||||
|
:font-family family
|
||||||
|
:font-weight (cm/parse-font-weight variant)
|
||||||
|
:font-style (cm/parse-font-style variant)}))
|
||||||
|
|
||||||
(defn get-fonts
|
(join [res {:keys [content] :as font}]
|
||||||
[backend]
|
(let [key-fn (juxt :font-family :font-weight :font-style)
|
||||||
(get @fonts/fonts backend []))
|
existing (d/seek #(= (key-fn font) (key-fn %)) (vals res))]
|
||||||
|
(if existing
|
||||||
|
(update res
|
||||||
|
(:id existing)
|
||||||
|
(fn [existing]
|
||||||
|
(-> existing
|
||||||
|
(update :data assoc (:type content) (:data content))
|
||||||
|
(update :names conj (:name content)))))
|
||||||
|
(let [tmp-id (uuid/next)]
|
||||||
|
(assoc res tmp-id
|
||||||
|
(-> font
|
||||||
|
(assoc :id tmp-id)
|
||||||
|
(assoc :team-id team-id)
|
||||||
|
(assoc :names #{(:name content)})
|
||||||
|
(assoc :data {(:type content)
|
||||||
|
(:data content)})
|
||||||
|
(dissoc :content)))))))
|
||||||
|
|
||||||
|
(parse-mtype [mtype]
|
||||||
|
(case mtype
|
||||||
|
"application/vnd.oasis.opendocument.formula-template" "font/otf"
|
||||||
|
mtype))
|
||||||
|
|
||||||
|
(parse-font [{:keys [data] :as params}]
|
||||||
|
(try
|
||||||
|
(assoc params :font (ot/parse data))
|
||||||
|
(catch :default e
|
||||||
|
(log/warn :msg (str/fmt "skiping file %s, unsupported format" (:name params)))
|
||||||
|
nil)))
|
||||||
|
|
||||||
|
(read-blob [blob]
|
||||||
|
(->> (wa/read-file-as-array-buffer blob)
|
||||||
|
(rx/map (fn [data]
|
||||||
|
{:data data
|
||||||
|
:name (.-name blob)
|
||||||
|
:type (parse-mtype (.-type blob))}))))]
|
||||||
|
|
||||||
|
(->> (rx/from blobs)
|
||||||
|
(rx/mapcat read-blob)
|
||||||
|
(rx/map parse-font)
|
||||||
|
(rx/filter some?)
|
||||||
|
(rx/map prepare)
|
||||||
|
(rx/reduce join {}))))
|
||||||
|
|
||||||
|
(defn- calculate-family-to-id-mapping
|
||||||
|
[existing]
|
||||||
|
(reduce #(assoc %1 (:font-family %2) (:font-id %2)) {} (vals existing)))
|
||||||
|
|
||||||
|
(defn merge-and-group-fonts
|
||||||
|
"Function responsible to merge (and apropriatelly group) incoming
|
||||||
|
fonts (processed by `process-upload`) into existing fonts
|
||||||
|
in local state, preserving correct font-id references."
|
||||||
|
[current-fonts installed-fonts incoming-fonts]
|
||||||
|
(loop [famdb (-> (merge current-fonts installed-fonts)
|
||||||
|
(calculate-family-to-id-mapping))
|
||||||
|
items (vals incoming-fonts)
|
||||||
|
result current-fonts]
|
||||||
|
(if-let [{:keys [id font-family] :as item} (first items)]
|
||||||
|
(let [font-id (or (get famdb font-family)
|
||||||
|
(uuid/next))
|
||||||
|
font (assoc item :font-id font-id)]
|
||||||
|
(recur (assoc famdb font-family font-id)
|
||||||
|
(rest items)
|
||||||
|
(assoc result id font)))
|
||||||
|
result)))
|
||||||
|
|
||||||
|
(defn rename-and-regroup
|
||||||
|
"Function responsible to rename a font in a local state and properly
|
||||||
|
regroup it to the apropriate `font-id` having in account current
|
||||||
|
fonts and installed fonts."
|
||||||
|
[current-fonts id name installed-fonts]
|
||||||
|
(let [famdb (-> (merge current-fonts installed-fonts)
|
||||||
|
(calculate-family-to-id-mapping))
|
||||||
|
font-id (or (get famdb name)
|
||||||
|
(uuid/next))]
|
||||||
|
(update current-fonts id (fn [font]
|
||||||
|
(-> font
|
||||||
|
(assoc :name name)
|
||||||
|
(assoc :font-id font-id))))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Dashboard related events
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn add-font
|
||||||
|
[font]
|
||||||
|
(ptk/reify ::add-font
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :dashboard-fonts assoc (:id font) font))))
|
||||||
|
|
||||||
|
(defn update-font
|
||||||
|
[{:keys [id name] :as params}]
|
||||||
|
(us/assert ::us/uuid id)
|
||||||
|
(us/assert ::us/not-empty-string name)
|
||||||
|
(ptk/reify ::update-font
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
;; Update all variants that has the same font-id with the new
|
||||||
|
;; name in the local state.
|
||||||
|
(update state :dashboard-fonts
|
||||||
|
(fn [fonts]
|
||||||
|
(d/mapm (fn [_ font]
|
||||||
|
(cond-> font
|
||||||
|
(= id (:font-id font))
|
||||||
|
(assoc :font-family name)))
|
||||||
|
fonts))))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(->> (rp/mutation! :update-font {:id id :name name :team-id team-id})
|
||||||
|
(rx/ignore))))))
|
||||||
|
|
||||||
|
(defn delete-font
|
||||||
|
"Delete all variants related to the provided `font-id`."
|
||||||
|
[font-id]
|
||||||
|
(us/assert ::us/uuid font-id)
|
||||||
|
(ptk/reify ::delete-font
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :dashboard-fonts
|
||||||
|
(fn [variants]
|
||||||
|
(d/removem (fn [[id variant]]
|
||||||
|
(= (:font-id variant) font-id)) variants))))
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(->> (rp/mutation! :delete-font {:id font-id :team-id team-id})
|
||||||
|
(rx/ignore))))))
|
||||||
|
|
||||||
|
(defn delete-font-variant
|
||||||
|
[id]
|
||||||
|
(us/assert ::us/uuid id)
|
||||||
|
(ptk/reify ::delete-font-variants
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :dashboard-fonts
|
||||||
|
(fn [variants]
|
||||||
|
(d/removem (fn [[_ variant]]
|
||||||
|
(= (:id variant) id))
|
||||||
|
variants))))
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(->> (rp/mutation! :delete-font-variant {:id id :team-id team-id})
|
||||||
|
(rx/ignore))))))
|
||||||
|
|
|
@ -56,10 +56,6 @@
|
||||||
(vec)
|
(vec)
|
||||||
(reset! fonts))))
|
(reset! fonts))))
|
||||||
|
|
||||||
(defn- remove-fonts
|
|
||||||
[db backend]
|
|
||||||
(reduce-kv #(cond-> %1 (= backend (:backend %3)) (dissoc %2)) db db))
|
|
||||||
|
|
||||||
(defn register!
|
(defn register!
|
||||||
[backend fonts]
|
[backend fonts]
|
||||||
(swap! fontsdb
|
(swap! fontsdb
|
||||||
|
@ -96,7 +92,6 @@
|
||||||
(unchecked-set node "type" "text/css")
|
(unchecked-set node "type" "text/css")
|
||||||
node))
|
node))
|
||||||
|
|
||||||
|
|
||||||
(defn- create-style-element
|
(defn- create-style-element
|
||||||
[css]
|
[css]
|
||||||
(let [node (.createElement js/document "style")]
|
(let [node (.createElement js/document "style")]
|
||||||
|
@ -166,9 +161,9 @@
|
||||||
url(%(otf-uri)s) format('otf');
|
url(%(otf-uri)s) format('otf');
|
||||||
}")
|
}")
|
||||||
|
|
||||||
(defn- font-id->uri
|
(defn- asset-id->uri
|
||||||
[font-id]
|
[asset-id]
|
||||||
(str (u/join cf/public-uri "assets/by-id/" font-id)))
|
(str (u/join cf/public-uri "assets/by-id/" asset-id)))
|
||||||
|
|
||||||
(defn generate-custom-font-variant-css
|
(defn generate-custom-font-variant-css
|
||||||
[family variant]
|
[family variant]
|
||||||
|
@ -176,10 +171,10 @@
|
||||||
{:family family
|
{:family family
|
||||||
:style (:style variant)
|
:style (:style variant)
|
||||||
:weight (:weight variant)
|
:weight (:weight variant)
|
||||||
:woff2-uri (font-id->uri (::woff2-file-id variant))
|
:woff2-uri (asset-id->uri (::woff2-file-id variant))
|
||||||
:woff1-uri (font-id->uri (::woff1-file-id variant))
|
:woff1-uri (asset-id->uri (::woff1-file-id variant))
|
||||||
:ttf-uri (font-id->uri (::ttf-file-id variant))
|
:ttf-uri (asset-id->uri (::ttf-file-id variant))
|
||||||
:otf-uri (font-id->uri (::otf-file-id variant))}))
|
:otf-uri (asset-id->uri (::otf-file-id variant))}))
|
||||||
|
|
||||||
(defn- generate-custom-font-css
|
(defn- generate-custom-font-css
|
||||||
[{:keys [family variants] :as font}]
|
[{:keys [family variants] :as font}]
|
||||||
|
@ -190,7 +185,7 @@
|
||||||
(defmethod load-font :custom
|
(defmethod load-font :custom
|
||||||
[{:keys [id family variants ::on-loaded] :as font}]
|
[{:keys [id family variants ::on-loaded] :as font}]
|
||||||
(when (exists? js/window)
|
(when (exists? js/window)
|
||||||
(js/console.log "[debug:fonts]: loading google font" id)
|
(js/console.log "[debug:fonts]: loading custom font" id)
|
||||||
(let [css (generate-custom-font-css font)]
|
(let [css (generate-custom-font-css font)]
|
||||||
(add-font-css! css))))
|
(add-font-css! css))))
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
:dashboard-team-settings)
|
:dashboard-team-settings)
|
||||||
[:*
|
[:*
|
||||||
#_[:div.modal-wrapper
|
#_[:div.modal-wrapper
|
||||||
[:& app.main.ui.onboarding/release-notes-modal {:version "1.5"}]]
|
[:& app.main.ui.onboarding/release-notes-modal {:version "1.6"}]]
|
||||||
[:& dashboard {:route route}]]
|
[:& dashboard {:route route}]]
|
||||||
|
|
||||||
:viewer
|
:viewer
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
(ns app.main.ui.dashboard.fonts
|
(ns app.main.ui.dashboard.fonts
|
||||||
(:require
|
(:require
|
||||||
["opentype.js" :as ot]
|
[app.common.data :as d]
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.dashboard.fonts :as df]
|
[app.main.data.fonts :as df]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
[app.main.ui.components.file-uploader :refer [file-uploader]]
|
||||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
|
@ -64,56 +64,23 @@
|
||||||
[:h1 (tr "labels.fonts")]]
|
[:h1 (tr "labels.fonts")]]
|
||||||
[:nav
|
[:nav
|
||||||
#_[:ul
|
#_[:ul
|
||||||
[:li {:class (when (= section :fonts) "active")}
|
[:li {:class (when (= section :fonts) "active")}
|
||||||
[:a {:on-click go-fonts} (tr "labels.custom-fonts")]]
|
[:a {:on-click go-fonts} (tr "labels.custom-fonts")]]
|
||||||
[:li {:class (when (= section :providers) "active")}
|
[:li {:class (when (= section :providers) "active")}
|
||||||
[:a {:on-click go-providers} (tr "labels.font-providers")]]]]
|
[:a {:on-click go-providers} (tr "labels.font-providers")]]]]
|
||||||
|
|
||||||
[:div]]))
|
[:div]]))
|
||||||
|
|
||||||
(defn- prepare-fonts
|
(mf/defc font-variant-display-name
|
||||||
[blobs]
|
[{:keys [variant]}]
|
||||||
(letfn [(prepare [{:keys [font type name data] :as params}]
|
[:*
|
||||||
(let [family (or (.getEnglishName ^js font "preferredFamily")
|
[:span (cm/font-weight->name (:font-weight variant))]
|
||||||
(.getEnglishName ^js font "fontFamily"))
|
(when (not= "normal" (:font-style variant))
|
||||||
variant (or (.getEnglishName ^js font "preferredSubfamily")
|
[:span " " (str/capital (:font-style variant))])])
|
||||||
(.getEnglishName ^js font "fontSubfamily"))]
|
|
||||||
{:content {:data (js/Uint8Array. data)
|
|
||||||
:name name
|
|
||||||
:type type}
|
|
||||||
:font-id (str "custom-" (str/slug family))
|
|
||||||
:font-family family
|
|
||||||
:font-weight (cm/parse-font-weight variant)
|
|
||||||
:font-style (cm/parse-font-style variant)}))
|
|
||||||
|
|
||||||
(parse-mtype [mtype]
|
|
||||||
(case mtype
|
|
||||||
"application/vnd.oasis.opendocument.formula-template" "font/otf"
|
|
||||||
mtype))
|
|
||||||
|
|
||||||
(parse-font [{:keys [data] :as params}]
|
|
||||||
(try
|
|
||||||
(assoc params :font (ot/parse data))
|
|
||||||
(catch :default e
|
|
||||||
(log/warn :msg (str/fmt "skiping file %s, unsupported format" (:name params)))
|
|
||||||
nil)))
|
|
||||||
|
|
||||||
(read-blob [blob]
|
|
||||||
(->> (wa/read-file-as-array-buffer blob)
|
|
||||||
(rx/map (fn [data]
|
|
||||||
{:data data
|
|
||||||
:name (.-name blob)
|
|
||||||
:type (parse-mtype (.-type blob))}))))]
|
|
||||||
|
|
||||||
(->> (rx/from blobs)
|
|
||||||
(rx/mapcat read-blob)
|
|
||||||
(rx/map parse-font)
|
|
||||||
(rx/filter some?)
|
|
||||||
(rx/map prepare))))
|
|
||||||
|
|
||||||
(mf/defc fonts-upload
|
(mf/defc fonts-upload
|
||||||
[{:keys [team] :as props}]
|
[{:keys [team installed-fonts] :as props}]
|
||||||
(let [fonts (mf/use-state {})
|
(let [fonts (mf/use-state {})
|
||||||
input-ref (mf/use-ref)
|
input-ref (mf/use-ref)
|
||||||
|
|
||||||
uploading (mf/use-state #{})
|
uploading (mf/use-state #{})
|
||||||
|
@ -126,19 +93,11 @@
|
||||||
|
|
||||||
on-selected
|
on-selected
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps team)
|
(mf/deps team installed-fonts)
|
||||||
(fn [blobs]
|
(fn [blobs]
|
||||||
(->> (prepare-fonts blobs)
|
(->> (df/process-upload blobs (:id team))
|
||||||
(rx/subs (fn [{:keys [content] :as font}]
|
(rx/subs (fn [result]
|
||||||
(let [key (font-key-fn font)]
|
(swap! fonts df/merge-and-group-fonts installed-fonts result))
|
||||||
(swap! fonts update key
|
|
||||||
(fn [val]
|
|
||||||
(-> (or val font)
|
|
||||||
(assoc :team-id (:id team))
|
|
||||||
(update :id #(or % (uuid/next)))
|
|
||||||
(update :data assoc (:type content) (:data content))
|
|
||||||
(update :names (fnil conj #{}) (:name content))
|
|
||||||
(dissoc :content))))))
|
|
||||||
(fn [error]
|
(fn [error]
|
||||||
(js/console.error "error" error))))))
|
(js/console.error "error" error))))))
|
||||||
|
|
||||||
|
@ -146,22 +105,26 @@
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
(fn [item]
|
(fn [item]
|
||||||
(let [key (font-key-fn item)]
|
(swap! uploading conj (:id item))
|
||||||
(swap! uploading conj (:id item))
|
(->> (rp/mutation! :create-font-variant item)
|
||||||
(->> (rp/mutation! :create-font-variant item)
|
(rx/delay-at-least 2000)
|
||||||
(rx/delay-at-least 2000)
|
(rx/subs (fn [font]
|
||||||
(rx/subs (fn [font]
|
(swap! fonts dissoc (:id item))
|
||||||
(swap! fonts dissoc key)
|
(swap! uploading disj (:id item))
|
||||||
(swap! uploading disj (:id item))
|
(st/emit! (df/add-font font)))
|
||||||
(st/emit! (df/add-font font)))
|
(fn [error]
|
||||||
(fn [error]
|
(js/console.log "error" error))))))
|
||||||
(js/console.log "error" error)))))))
|
|
||||||
|
on-blur-name
|
||||||
|
(fn [id event]
|
||||||
|
(let [name (dom/get-target-val event)]
|
||||||
|
(swap! fonts df/rename-and-regroup id name installed-fonts)))
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
(fn [item]
|
(fn [{:keys [id] :as item}]
|
||||||
(swap! fonts dissoc (font-key-fn item))))]
|
(swap! fonts dissoc id)))]
|
||||||
|
|
||||||
[:div.dashboard-fonts-upload
|
[:div.dashboard-fonts-upload
|
||||||
[:div.dashboard-fonts-hero
|
[:div.dashboard-fonts-hero
|
||||||
|
@ -177,7 +140,7 @@
|
||||||
|
|
||||||
[:div.btn-primary
|
[:div.btn-primary
|
||||||
{:on-click on-click}
|
{:on-click on-click}
|
||||||
[:span "Add custom font"]
|
[:span (tr "labels.add-custom-font")]
|
||||||
[:& file-uploader {:input-id "font-upload"
|
[:& file-uploader {:input-id "font-upload"
|
||||||
:accept cm/str-font-types
|
:accept cm/str-font-types
|
||||||
:multi true
|
:multi true
|
||||||
|
@ -190,11 +153,11 @@
|
||||||
[:div.font-item.table-row {:key (:id item)}
|
[:div.font-item.table-row {:key (:id item)}
|
||||||
[:div.table-field.family
|
[:div.table-field.family
|
||||||
[:input {:type "text"
|
[:input {:type "text"
|
||||||
|
:on-blur #(on-blur-name (:id item) %)
|
||||||
:default-value (:font-family item)}]]
|
:default-value (:font-family item)}]]
|
||||||
[:div.table-field.variant
|
[:div.table-field.variants
|
||||||
[:span (cm/font-weight->name (:font-weight item))]
|
[:span.label
|
||||||
(when (not= "normal" (:font-style item))
|
[:& font-variant-display-name {:variant item}]]]
|
||||||
[:span " " (str/capital (:font-style item))])]
|
|
||||||
[:div.table-field.filenames
|
[:div.table-field.filenames
|
||||||
(for [item (:names item)]
|
(for [item (:names item)]
|
||||||
[:span item])]
|
[:span item])]
|
||||||
|
@ -210,56 +173,67 @@
|
||||||
[:span.icon.close {:on-click #(on-delete item)} i/close]]]))]]))
|
[:span.icon.close {:on-click #(on-delete item)} i/close]]]))]]))
|
||||||
|
|
||||||
(mf/defc installed-font
|
(mf/defc installed-font
|
||||||
[{:keys [font] :as props}]
|
[{:keys [font-id variants] :as props}]
|
||||||
(let [open-menu? (mf/use-state false)
|
(let [font (first variants)
|
||||||
|
|
||||||
|
variants (sort-by (fn [item]
|
||||||
|
[(:font-weight item)
|
||||||
|
(if (= "normal" (:font-style item)) 1 2)])
|
||||||
|
variants)
|
||||||
|
|
||||||
|
open-menu? (mf/use-state false)
|
||||||
edit? (mf/use-state false)
|
edit? (mf/use-state false)
|
||||||
state (mf/use-var (:font-family font))
|
state (mf/use-var (:font-family font))
|
||||||
|
|
||||||
on-change
|
on-change
|
||||||
(mf/use-callback
|
(fn [event]
|
||||||
(mf/deps font)
|
(reset! state (dom/get-target-val event)))
|
||||||
(fn [event]
|
|
||||||
(reset! state (dom/get-target-val event))))
|
|
||||||
|
|
||||||
on-save
|
on-save
|
||||||
(mf/use-callback
|
(fn [event]
|
||||||
(mf/deps font)
|
(let [font-family @state]
|
||||||
(fn [event]
|
(st/emit! (df/update-font
|
||||||
(let [font (assoc font :font-family @state)]
|
{:id font-id
|
||||||
(st/emit! (df/update-font font))
|
:name font-family}))
|
||||||
(reset! edit? false))))
|
(reset! edit? false)))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-callback
|
(fn [event]
|
||||||
(mf/deps font)
|
(when (kbd/enter? event)
|
||||||
(fn [event]
|
(on-save event)))
|
||||||
(when (kbd/enter? event)
|
|
||||||
(on-save event))))
|
|
||||||
|
|
||||||
on-cancel
|
on-cancel
|
||||||
(mf/use-callback
|
(fn [event]
|
||||||
(mf/deps font)
|
(reset! edit? false)
|
||||||
(fn [event]
|
(reset! state (:font-family font)))
|
||||||
(reset! edit? false)
|
|
||||||
(reset! state (:font-family font))))
|
|
||||||
|
|
||||||
delete-fn
|
delete-font-fn
|
||||||
(mf/use-callback
|
(fn [] (st/emit! (df/delete-font font-id)))
|
||||||
(mf/deps font)
|
|
||||||
(st/emitf (df/delete-font font)))
|
delete-variant-fn
|
||||||
|
(fn [id] (st/emit! (df/delete-font-variant id)))
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
(mf/use-callback
|
(fn []
|
||||||
(mf/deps font)
|
(st/emit! (modal/show
|
||||||
(st/emitf (modal/show
|
{:type :confirm
|
||||||
{:type :confirm
|
:title (tr "modals.delete-font.title")
|
||||||
:title (tr "modals.delete-font.title")
|
:message (tr "modals.delete-font.message")
|
||||||
:message (tr "modals.delete-font.message")
|
:accept-label (tr "labels.delete")
|
||||||
:accept-label (tr "labels.delete")
|
:on-accept (fn [props]
|
||||||
:on-accept delete-fn})))]
|
(delete-font-fn))})))
|
||||||
|
|
||||||
|
on-delete-variant
|
||||||
|
(fn [id]
|
||||||
|
(st/emit! (modal/show
|
||||||
|
{:type :confirm
|
||||||
|
:title (tr "modals.delete-font-variant.title")
|
||||||
|
:message (tr "modals.delete-font-variant.message")
|
||||||
|
:accept-label (tr "labels.delete")
|
||||||
|
:on-accept (fn [props]
|
||||||
|
(delete-variant-fn id))})))]
|
||||||
|
|
||||||
[:div.font-item.table-row {:key (:id font)}
|
[:div.font-item.table-row
|
||||||
[:div.table-field.family
|
[:div.table-field.family
|
||||||
(if @edit?
|
(if @edit?
|
||||||
[:input {:type "text"
|
[:input {:type "text"
|
||||||
|
@ -268,10 +242,14 @@
|
||||||
:on-change on-change}]
|
:on-change on-change}]
|
||||||
[:span (:font-family font)])]
|
[:span (:font-family font)])]
|
||||||
|
|
||||||
[:div.table-field.variant
|
[:div.table-field.variants
|
||||||
[:span (cm/font-weight->name (:font-weight font))]
|
(for [item variants]
|
||||||
(when (not= "normal" (:font-style font))
|
[:div.variant
|
||||||
[:span " " (str/capital (:font-style font))])]
|
[:span.label
|
||||||
|
[:& font-variant-display-name {:variant item}]]
|
||||||
|
[:span.icon.close
|
||||||
|
{:on-click #(on-delete-variant (:id item))}
|
||||||
|
i/plus]])]
|
||||||
|
|
||||||
[:div]
|
[:div]
|
||||||
|
|
||||||
|
@ -281,7 +259,7 @@
|
||||||
{:disabled (str/blank? @state)
|
{:disabled (str/blank? @state)
|
||||||
:on-click on-save
|
:on-click on-save
|
||||||
:class (dom/classnames :btn-disabled (str/blank? @state))}
|
:class (dom/classnames :btn-disabled (str/blank? @state))}
|
||||||
"Save"]
|
(tr "labels.save")]
|
||||||
[:span.icon.close {:on-click on-cancel} i/close]]
|
[:span.icon.close {:on-click on-cancel} i/close]]
|
||||||
|
|
||||||
[:div.table-field.options
|
[:div.table-field.options
|
||||||
|
@ -313,41 +291,45 @@
|
||||||
[:h3 (tr "labels.installed-fonts")]
|
[:h3 (tr "labels.installed-fonts")]
|
||||||
[:div.installed-fonts-header
|
[:div.installed-fonts-header
|
||||||
[:div.table-field.family (tr "labels.font-family")]
|
[:div.table-field.family (tr "labels.font-family")]
|
||||||
[:div.table-field.variant (tr "labels.font-variant")]
|
[:div.table-field.variants (tr "labels.font-variants")]
|
||||||
[:div]
|
[:div]
|
||||||
[:div.table-field.search-input
|
[:div.table-field.search-input
|
||||||
[:input {:placeholder (tr "labels.search-font")
|
[:input {:placeholder (tr "labels.search-font")
|
||||||
:default-value ""
|
:default-value ""
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
}]]]
|
}]]]
|
||||||
(for [[font-id fonts] (->> fonts
|
|
||||||
(filter matches?)
|
|
||||||
(group-by :font-id))]
|
|
||||||
[:div.fonts-group
|
|
||||||
(for [font (sort-by (juxt :font-weight :font-style) fonts)]
|
|
||||||
[:& installed-font {:key (:id font) :font font}])])]))
|
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(seq fonts)
|
||||||
|
(for [[font-id variants] (->> (vals fonts)
|
||||||
|
(filter matches?)
|
||||||
|
(group-by :font-id))]
|
||||||
|
[:& installed-font {:key (str font-id)
|
||||||
|
:font-id font-id
|
||||||
|
:variants variants}])
|
||||||
|
|
||||||
|
(nil? fonts)
|
||||||
|
[:div.fonts-placeholder
|
||||||
|
[:div.icon i/loader]
|
||||||
|
[:div.label (tr "dashboard.loading-fonts")]]
|
||||||
|
|
||||||
|
:else
|
||||||
|
[:div.fonts-placeholder
|
||||||
|
[:div.icon i/text]
|
||||||
|
[:div.label (tr "dashboard.fonts.empty-placeholder")]])]))
|
||||||
|
|
||||||
(mf/defc fonts-page
|
(mf/defc fonts-page
|
||||||
[{:keys [team] :as props}]
|
[{:keys [team] :as props}]
|
||||||
(let [fonts-map (mf/deref refs/dashboard-fonts)
|
(let [fonts (mf/deref refs/dashboard-fonts)]
|
||||||
fonts (vals fonts-map)]
|
|
||||||
|
|
||||||
(mf/use-effect
|
|
||||||
(mf/deps team)
|
|
||||||
(st/emitf (df/fetch-fonts team)))
|
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:& header {:team team :section :fonts}]
|
[:& header {:team team :section :fonts}]
|
||||||
[:section.dashboard-container.dashboard-fonts
|
[:section.dashboard-container.dashboard-fonts
|
||||||
[:& fonts-upload {:team team}]
|
[:& fonts-upload {:team team :installed-fonts fonts}]
|
||||||
|
[:& installed-fonts {:team team :fonts fonts}]]]))
|
||||||
|
|
||||||
(when fonts
|
|
||||||
[:& installed-fonts {:team team
|
|
||||||
:fonts fonts}])]]))
|
|
||||||
(mf/defc font-providers-page
|
(mf/defc font-providers-page
|
||||||
[{:keys [team] :as props}]
|
[{:keys [team] :as props}]
|
||||||
[:*
|
[:*
|
||||||
[:& header {:team team :section :providers}]
|
[:& header {:team team :section :providers}]
|
||||||
[:section.dashboard-container
|
[:section.dashboard-container
|
||||||
[:span "hello world font providers"]]])
|
[:span "font providers"]]])
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
(mf/defc onboarding-start
|
(mf/defc onboarding-start
|
||||||
[{:keys [next] :as props}]
|
[{:keys [next] :as props}]
|
||||||
[:div.modal-container.onboarding
|
[:div.modal-container.onboarding
|
||||||
[:div.modal-left
|
[:div.modal-left.welcome
|
||||||
[:img {:src "images/login-on.jpg" :border "0" :alt "Penpot"}]]
|
[:img {:src "images/login-on.jpg" :border "0" :alt "Penpot"}]]
|
||||||
[:div.modal-right
|
[:div.modal-right
|
||||||
[:div.modal-title
|
[:div.modal-title
|
||||||
|
@ -296,7 +296,7 @@
|
||||||
|
|
||||||
(defmethod render-release-notes "0.0"
|
(defmethod render-release-notes "0.0"
|
||||||
[params]
|
[params]
|
||||||
(render-release-notes (assoc params :version "1.5")))
|
(render-release-notes (assoc params :version "1.6")))
|
||||||
|
|
||||||
(defmethod render-release-notes "1.4"
|
(defmethod render-release-notes "1.4"
|
||||||
[{:keys [slide klass next finish navigate version]}]
|
[{:keys [slide klass next finish navigate version]}]
|
||||||
|
@ -474,3 +474,101 @@
|
||||||
{:slide @slide
|
{:slide @slide
|
||||||
:navigate navigate
|
:navigate navigate
|
||||||
:total 3}]]]]]])))
|
:total 3}]]]]]])))
|
||||||
|
|
||||||
|
(defmethod render-release-notes "1.6"
|
||||||
|
[{:keys [slide klass next finish navigate version]}]
|
||||||
|
(mf/html
|
||||||
|
(case @slide
|
||||||
|
:start
|
||||||
|
[:div.modal-overlay
|
||||||
|
[:div.animated {:class @klass}
|
||||||
|
[:div.modal-container.onboarding.feature
|
||||||
|
[:div.modal-left
|
||||||
|
[:img {:src "images/login-on.jpg" :border "0" :alt "What's new Alpha release 1.6.0"}]]
|
||||||
|
[:div.modal-right
|
||||||
|
[:div.modal-title
|
||||||
|
[:h2 "What's new?"]]
|
||||||
|
[:span.release "Alpha version " version]
|
||||||
|
[:div.modal-content
|
||||||
|
[:p "Penpot continues growing with new features that improve performance, user experience and visual design."]
|
||||||
|
[:p "We are happy to show you a sneak peak of the most important stuff that the Alpha 1.6.0 version brings."]]
|
||||||
|
[:div.modal-navigation
|
||||||
|
[:button.btn-secondary {:on-click next} "Continue"]]]
|
||||||
|
[:img.deco {:src "images/deco-left.png" :border "0"}]
|
||||||
|
[:img.deco.right {:src "images/deco-right.png" :border "0"}]]]]
|
||||||
|
|
||||||
|
0
|
||||||
|
[:div.modal-overlay
|
||||||
|
[:div.animated {:class @klass}
|
||||||
|
[:div.modal-container.onboarding.feature
|
||||||
|
[:div.modal-left
|
||||||
|
[:img {:src "images/features/custom-fonts.gif" :border "0" :alt "Upload/use custom fonts"}]]
|
||||||
|
[:div.modal-right
|
||||||
|
[:div.modal-title
|
||||||
|
[:h2 "Upload/use custom fonts"]]
|
||||||
|
[:div.modal-content
|
||||||
|
[:p "From now on you can upload fonts to a Penpot team and use them across its files. This is one of the most requested features since our first release (we listen!)"]
|
||||||
|
[:p "We hope you enjoy having more typography options and our brand new font selector."]]
|
||||||
|
[:div.modal-navigation
|
||||||
|
[:button.btn-secondary {:on-click next} "Continue"]
|
||||||
|
[:& navigation-bullets
|
||||||
|
{:slide @slide
|
||||||
|
:navigate navigate
|
||||||
|
:total 4}]]]]]]
|
||||||
|
|
||||||
|
1
|
||||||
|
[:div.modal-overlay
|
||||||
|
[:div.animated {:class @klass}
|
||||||
|
[:div.modal-container.onboarding.feature
|
||||||
|
[:div.modal-left
|
||||||
|
[:img {:src "images/features/scale-text.gif" :border "0" :alt "Interactively scale text"}]]
|
||||||
|
[:div.modal-right
|
||||||
|
[:div.modal-title
|
||||||
|
[:h2 "Scale text layers at resizing"]]
|
||||||
|
[:div.modal-content
|
||||||
|
[:p "New main menu option “Scale text (K)” to enable scale text mode."]
|
||||||
|
[:p "Disabled by default, this tool is disabled back after being used."]]
|
||||||
|
[:div.modal-navigation
|
||||||
|
[:button.btn-secondary {:on-click next} "Continue"]
|
||||||
|
[:& navigation-bullets
|
||||||
|
{:slide @slide
|
||||||
|
:navigate navigate
|
||||||
|
:total 4}]]]]]]
|
||||||
|
|
||||||
|
2
|
||||||
|
[:div.modal-overlay
|
||||||
|
[:div.animated {:class @klass}
|
||||||
|
[:div.modal-container.onboarding.feature
|
||||||
|
[:div.modal-left
|
||||||
|
[:img {:src "images/features/performance.gif" :border "0" :alt "Performance improvements"}]]
|
||||||
|
[:div.modal-right
|
||||||
|
[:div.modal-title
|
||||||
|
[:h2 "Performance improvements"]]
|
||||||
|
[:div.modal-content
|
||||||
|
[:p "Penpot brings important improvements handling large files. The performance in managing files in the dashboard has also been improved."]
|
||||||
|
[:p "You should have the feeling that files and layers show up a bit faster :)"]]
|
||||||
|
[:div.modal-navigation
|
||||||
|
[:button.btn-secondary {:on-click next} "Continue"]
|
||||||
|
[:& navigation-bullets
|
||||||
|
{:slide @slide
|
||||||
|
:navigate navigate
|
||||||
|
:total 4}]]]]]]
|
||||||
|
|
||||||
|
3
|
||||||
|
[:div.modal-overlay
|
||||||
|
[:div.animated {:class @klass}
|
||||||
|
[:div.modal-container.onboarding.feature
|
||||||
|
[:div.modal-left
|
||||||
|
[:img {:src "images/features/shapes-to-path.gif" :border "0" :alt "Shapes to path"}]]
|
||||||
|
[:div.modal-right
|
||||||
|
[:div.modal-title
|
||||||
|
[:h2 "Shapes to path"]]
|
||||||
|
[:div.modal-content
|
||||||
|
[:p "Now you can edit basic shapes like rectangles, circles and image containers by double clicking."]
|
||||||
|
[:p "An easy way to increase speed by working with vectors!"]]
|
||||||
|
[:div.modal-navigation
|
||||||
|
[:button.btn-secondary {:on-click finish} "Start!"]
|
||||||
|
[:& navigation-bullets
|
||||||
|
{:slide @slide
|
||||||
|
:navigate navigate
|
||||||
|
:total 4}]]]]]])))
|
||||||
|
|
|
@ -310,7 +310,16 @@
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:div.input-select.font-option
|
[:div.input-select.font-option
|
||||||
{:on-click #(reset! open-selector? true)}
|
{:on-click #(reset! open-selector? true)}
|
||||||
(:name font)]]
|
(cond
|
||||||
|
(= :multiple font-id)
|
||||||
|
"--"
|
||||||
|
|
||||||
|
(some? font)
|
||||||
|
(:name font)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(tr "dashboard.fonts.deleted-placeholder"))]]
|
||||||
|
|
||||||
|
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
(let [size-options [8 9 10 11 12 14 18 24 36 48 72]
|
(let [size-options [8 9 10 11 12 14 18 24 36 48 72]
|
||||||
|
|
|
@ -206,6 +206,12 @@ msgstr "Duplicate %s files"
|
||||||
msgid "dashboard.empty-files"
|
msgid "dashboard.empty-files"
|
||||||
msgstr "You still have no files here"
|
msgstr "You still have no files here"
|
||||||
|
|
||||||
|
msgid "dashboard.fonts.deleted-placeholder"
|
||||||
|
msgstr "Font deleted"
|
||||||
|
|
||||||
|
msgid "dashboard.fonts.empty-placeholder"
|
||||||
|
msgstr "You still have no custom fonts installed."
|
||||||
|
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "dashboard.fonts.hero-text1"
|
msgid "dashboard.fonts.hero-text1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -239,6 +245,9 @@ msgstr "Shared Libraries"
|
||||||
msgid "dashboard.loading-files"
|
msgid "dashboard.loading-files"
|
||||||
msgstr "loading your files …"
|
msgstr "loading your files …"
|
||||||
|
|
||||||
|
msgid "dashboard.loading-fonts"
|
||||||
|
msgstr "loading your fonts …"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/project_menu.cljs, src/app/main/ui/dashboard/file_menu.cljs
|
#: src/app/main/ui/dashboard/project_menu.cljs, src/app/main/ui/dashboard/file_menu.cljs
|
||||||
msgid "dashboard.move-to"
|
msgid "dashboard.move-to"
|
||||||
msgstr "Move to"
|
msgstr "Move to"
|
||||||
|
@ -790,6 +799,9 @@ msgstr "You are seeing version %s"
|
||||||
msgid "labels.accept"
|
msgid "labels.accept"
|
||||||
msgstr "Accept"
|
msgstr "Accept"
|
||||||
|
|
||||||
|
msgid "labels.add-custom-font"
|
||||||
|
msgstr "Add custom font"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs
|
#: src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs
|
||||||
msgid "labels.admin"
|
msgid "labels.admin"
|
||||||
msgstr "Admin"
|
msgstr "Admin"
|
||||||
|
@ -891,8 +903,8 @@ msgstr "Font Family"
|
||||||
msgid "labels.font-providers"
|
msgid "labels.font-providers"
|
||||||
msgstr "Font providers"
|
msgstr "Font providers"
|
||||||
|
|
||||||
msgid "labels.font-variant"
|
msgid "labels.font-variants"
|
||||||
msgstr "Style"
|
msgstr "Styles"
|
||||||
|
|
||||||
msgid "labels.fonts"
|
msgid "labels.fonts"
|
||||||
msgstr "Fonts"
|
msgstr "Fonts"
|
||||||
|
@ -1189,6 +1201,14 @@ msgstr "Are you sure you want to delete %s files?"
|
||||||
msgid "modals.delete-file-multi-confirm.title"
|
msgid "modals.delete-file-multi-confirm.title"
|
||||||
msgstr "Deleting %s files"
|
msgstr "Deleting %s files"
|
||||||
|
|
||||||
|
msgid "modals.delete-font-variant.message"
|
||||||
|
msgstr ""
|
||||||
|
"Are you sure you want to delete this font style? It will not load if is "
|
||||||
|
"used in a file."
|
||||||
|
|
||||||
|
msgid "modals.delete-font-variant.title"
|
||||||
|
msgstr "Deleting font style"
|
||||||
|
|
||||||
msgid "modals.delete-font.message"
|
msgid "modals.delete-font.message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Are you sure you want to delete this font? It will not load if is used in a "
|
"Are you sure you want to delete this font? It will not load if is used in a "
|
||||||
|
|
|
@ -210,6 +210,12 @@ msgstr "Duplicar %s archivos"
|
||||||
msgid "dashboard.empty-files"
|
msgid "dashboard.empty-files"
|
||||||
msgstr "Todavía no hay ningún archivo aquí"
|
msgstr "Todavía no hay ningún archivo aquí"
|
||||||
|
|
||||||
|
msgid "dashboard.fonts.deleted-placeholder"
|
||||||
|
msgstr "Fuente eliminada."
|
||||||
|
|
||||||
|
msgid "dashboard.fonts.empty-placeholder"
|
||||||
|
msgstr "Aun no tienes fuentes personalizadas."
|
||||||
|
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "dashboard.fonts.hero-text1"
|
msgid "dashboard.fonts.hero-text1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -243,6 +249,9 @@ msgstr "Bibliotecas Compartidas"
|
||||||
msgid "dashboard.loading-files"
|
msgid "dashboard.loading-files"
|
||||||
msgstr "cargando tus ficheros …"
|
msgstr "cargando tus ficheros …"
|
||||||
|
|
||||||
|
msgid "dashboard.loading-fonts"
|
||||||
|
msgstr "cargando tus fuentes …"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/project_menu.cljs, src/app/main/ui/dashboard/file_menu.cljs
|
#: src/app/main/ui/dashboard/project_menu.cljs, src/app/main/ui/dashboard/file_menu.cljs
|
||||||
msgid "dashboard.move-to"
|
msgid "dashboard.move-to"
|
||||||
msgstr "Mover a"
|
msgstr "Mover a"
|
||||||
|
@ -796,6 +805,9 @@ msgstr "Estás viendo la versión %s"
|
||||||
msgid "labels.accept"
|
msgid "labels.accept"
|
||||||
msgstr "Aceptar"
|
msgstr "Aceptar"
|
||||||
|
|
||||||
|
msgid "labels.add-custom-font"
|
||||||
|
msgstr "Añadir fuentes personalizada"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs
|
#: src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs, src/app/main/ui/dashboard/team.cljs
|
||||||
msgid "labels.admin"
|
msgid "labels.admin"
|
||||||
msgstr "Administración"
|
msgstr "Administración"
|
||||||
|
@ -893,8 +905,8 @@ msgstr "Familia de fuente"
|
||||||
msgid "labels.font-providers"
|
msgid "labels.font-providers"
|
||||||
msgstr "Proveedores de fuentes"
|
msgstr "Proveedores de fuentes"
|
||||||
|
|
||||||
msgid "labels.font-variant"
|
msgid "labels.font-variants"
|
||||||
msgstr "Estilo"
|
msgstr "Estilos"
|
||||||
|
|
||||||
msgid "labels.fonts"
|
msgid "labels.fonts"
|
||||||
msgstr "Fuentes"
|
msgstr "Fuentes"
|
||||||
|
@ -1191,10 +1203,18 @@ msgstr "¿Seguro que quieres eliminar %s archivos?"
|
||||||
msgid "modals.delete-file-multi-confirm.title"
|
msgid "modals.delete-file-multi-confirm.title"
|
||||||
msgstr "Eliminando %s archivos"
|
msgstr "Eliminando %s archivos"
|
||||||
|
|
||||||
|
msgid "modals.delete-font-variant.message"
|
||||||
|
msgstr ""
|
||||||
|
"Estas seguro de querer eliminar esta estilo de fuente? Dejara de cargar si "
|
||||||
|
"es usada en algun fichero."
|
||||||
|
|
||||||
|
msgid "modals.delete-font-variant.title"
|
||||||
|
msgstr "Eliminando estilo de fuente"
|
||||||
|
|
||||||
msgid "modals.delete-font.message"
|
msgid "modals.delete-font.message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Are you sure you want to delete this font? It will not load if is used in a "
|
"Estas seguro de querer eliminar esta fuente? Dejara de cargar si es usada "
|
||||||
"file."
|
"en algun fichero."
|
||||||
|
|
||||||
msgid "modals.delete-font.title"
|
msgid "modals.delete-font.title"
|
||||||
msgstr "Eliminando fuente"
|
msgstr "Eliminando fuente"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue