0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

🎉 Allow to ignore updates, and do it later in libraries dialog

This commit is contained in:
Andrés Moya 2020-09-22 12:00:48 +02:00 committed by Andrey Antukh
parent ae61ce05c9
commit 9873ac9104
11 changed files with 277 additions and 100 deletions

View file

@ -93,6 +93,11 @@
{:name "0025-del-generic-tokens-table"
:fn (mg/resource "app/migrations/sql/0025-del-generic-tokens-table.sql")}
{:name "0026-mod-file-library-rel-table-synced-date"
:fn (mg/resource "app/migrations/sql/0026-mod-file-library-rel-table-synced-date.sql")}
{:name "0027-mod-file-table-ignore-sync"
:fn (mg/resource "app/migrations/sql/0027-mod-file-table-ignore-sync.sql")}
]})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -0,0 +1,3 @@
ALTER TABLE file_library_rel
ADD COLUMN synced_at timestamptz NOT NULL DEFAULT clock_timestamp();

View file

@ -0,0 +1,3 @@
ALTER TABLE file
ADD COLUMN ignore_sync_until timestamptz NULL;

View file

@ -188,6 +188,47 @@
:library-file-id library-id}))
;; --- Mutation: Update syncrhonization status of a link
(declare update-sync)
(s/def ::update-sync
(s/keys :req-un [::profile-id ::file-id ::library-id]))
(sm/defmutation ::update-sync
[{:keys [profile-id file-id library-id] :as params}]
(db/with-atomic [conn db/pool]
(files/check-edition-permissions! conn profile-id file-id)
(update-sync conn params)))
(defn- update-sync
[conn {:keys [file-id library-id] :as params}]
(db/update! conn :file-library-rel
{:synced-at (dt/now)}
{:file-id file-id
:library-file-id library-id}))
;; --- Mutation: Ignore updates in linked files
(declare ignore-sync)
(s/def ::ignore-sync
(s/keys :req-un [::profile-id ::file-id ::date]))
(sm/defmutation ::ignore-sync
[{:keys [profile-id file-id date] :as params}]
(db/with-atomic [conn db/pool]
(files/check-edition-permissions! conn profile-id file-id)
(ignore-sync conn params)))
(defn- ignore-sync
[conn {:keys [file-id date] :as params}]
(db/update! conn :file
{:ignore-sync-until date}
{:id file-id}))
;; A generic, Changes based (granular) file update method.
(s/def ::changes
@ -258,6 +299,7 @@
:file-id (:id file)
:session-id sid
:revn (:revn file)
:modified-at (:modified-at file)
:changes library-changes}]
@(redis/run! :publish {:channel (str team-id)

View file

@ -235,7 +235,8 @@
;; --- Query: File Libraries used by a File
(def ^:private sql:file-libraries
"select fl.*
"select fl.*,
flr.synced_at as synced_at
from file as fl
inner join file_library_rel as flr on (flr.library_file_id = fl.id)
where flr.file_id = ?

View file

@ -182,6 +182,13 @@
(assoc m key (apply f found args))
m)))
(defn assoc-in-when
[m key-seq v]
(let [found (get-in m key-seq sentinel)]
(if-not (identical? sentinel found)
(assoc-in m key-seq v)
m)))
(defn assoc-when
[m key v]
(let [found (get m key sentinel)]

View file

@ -1,6 +1,6 @@
{
"auth.already-have-account" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:115" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:114" ],
"translations" : {
"en" : "Already have an account?",
"fr" : "Vous avez déjà un compte?",
@ -18,7 +18,7 @@
}
},
"auth.create-demo-profile" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:124", "src/app/main/ui/auth/login.cljs:135" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:123", "src/app/main/ui/auth/login.cljs:135" ],
"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/app/main/ui/auth/register.cljs:121", "src/app/main/ui/auth/login.cljs:132" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:120", "src/app/main/ui/auth/login.cljs:132" ],
"translations" : {
"en" : "Just wanna try it?",
"fr" : "Vous voulez juste essayer?",
@ -45,7 +45,7 @@
}
},
"auth.email-label" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:90", "src/app/main/ui/auth/recovery_request.cljs:45", "src/app/main/ui/auth/login.cljs:81" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:89", "src/app/main/ui/auth/recovery_request.cljs:45", "src/app/main/ui/auth/login.cljs:81" ],
"translations" : {
"en" : "Email",
"fr" : "Adresse email",
@ -63,7 +63,7 @@
}
},
"auth.fullname-label" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:84" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:83" ],
"translations" : {
"en" : "Full Name",
"fr" : "Nom complet",
@ -90,7 +90,7 @@
}
},
"auth.login-here" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:118" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:117" ],
"translations" : {
"en" : "Login here",
"fr" : "Se connecter ici",
@ -180,13 +180,13 @@
}
},
"auth.notifications.validation-email-sent" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:59", "src/app/main/ui/settings/change_email.cljs:55" ],
"used-in" : [ "src/app/main/ui/settings/change_email.cljs:55", "src/app/main/ui/auth/register.cljs:58" ],
"translations" : {
"en" : "Verification email sent to %s; check your email!"
}
},
"auth.password-label" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:94", "src/app/main/ui/auth/login.cljs:87" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:93", "src/app/main/ui/auth/login.cljs:87" ],
"translations" : {
"en" : "Password",
"fr" : "Mot de passe",
@ -195,7 +195,7 @@
}
},
"auth.password-length-hint" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:93" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:92" ],
"translations" : {
"en" : "At least 8 characters",
"fr" : "Au moins 8 caractères",
@ -258,7 +258,7 @@
}
},
"auth.register-submit-label" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:98" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:97" ],
"translations" : {
"en" : "Create an account",
"fr" : "Créer un compte",
@ -267,7 +267,7 @@
}
},
"auth.register-subtitle" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:107" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:106" ],
"translations" : {
"en" : "It's free, it's Open Source",
"fr" : "C'est gratuit, c'est Open Source",
@ -276,7 +276,7 @@
}
},
"auth.register-title" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:106" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:105" ],
"translations" : {
"en" : "Create an account",
"fr" : "Créer un compte",
@ -294,7 +294,7 @@
}
},
"dashboard.grid.add-shared" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:175", "src/app/main/ui/dashboard/grid.cljs:165" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:165", "src/app/main/ui/workspace/header.cljs:175" ],
"translations" : {
"en" : "Add as Shared Library",
"fr" : "",
@ -303,7 +303,7 @@
}
},
"dashboard.grid.add-shared-accept" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:98", "src/app/main/ui/dashboard/grid.cljs:94" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:94", "src/app/main/ui/workspace/header.cljs:98" ],
"translations" : {
"en" : "Add as Shared Library",
"fr" : "",
@ -312,7 +312,7 @@
}
},
"dashboard.grid.add-shared-hint" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:97", "src/app/main/ui/dashboard/grid.cljs:93" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:93", "src/app/main/ui/workspace/header.cljs:97" ],
"translations" : {
"en" : "Once added as Shared Library, the assets of this file library will be available to be used among the rest of your files.",
"fr" : "",
@ -321,7 +321,7 @@
}
},
"dashboard.grid.add-shared-message" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:96", "src/app/main/ui/dashboard/grid.cljs:92" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:92", "src/app/main/ui/workspace/header.cljs:96" ],
"translations" : {
"en" : "Add “%s” as Shared Library",
"fr" : "",
@ -348,7 +348,7 @@
}
},
"dashboard.grid.remove-shared" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:173", "src/app/main/ui/dashboard/grid.cljs:164" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:164", "src/app/main/ui/workspace/header.cljs:173" ],
"translations" : {
"en" : "Remove as Shared Library",
"fr" : "",
@ -357,7 +357,7 @@
}
},
"dashboard.grid.remove-shared-accept" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:107", "src/app/main/ui/dashboard/grid.cljs:113" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:113", "src/app/main/ui/workspace/header.cljs:107" ],
"translations" : {
"en" : "Remove as Shared Library",
"fr" : "",
@ -366,7 +366,7 @@
}
},
"dashboard.grid.remove-shared-hint" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:106", "src/app/main/ui/dashboard/grid.cljs:112" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:112", "src/app/main/ui/workspace/header.cljs:106" ],
"translations" : {
"en" : "Once removed as Shared Library, the File Library of this file will stop being available to be used among the rest of your files.",
"fr" : "",
@ -375,7 +375,7 @@
}
},
"dashboard.grid.remove-shared-message" : {
"used-in" : [ "src/app/main/ui/workspace/header.cljs:105", "src/app/main/ui/dashboard/grid.cljs:111" ],
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:111", "src/app/main/ui/workspace/header.cljs:105" ],
"translations" : {
"en" : "Remove “%s” as Shared Library",
"fr" : "",
@ -735,7 +735,7 @@
}
},
"errors.email-already-exists" : {
"used-in" : [ "src/app/main/ui/auth.cljs:90", "src/app/main/ui/settings/change_email.cljs:46" ],
"used-in" : [ "src/app/main/ui/settings/change_email.cljs:46", "src/app/main/ui/auth.cljs:89" ],
"translations" : {
"en" : "Email already used",
"fr" : "Adresse e-mail déjà utilisée",
@ -744,7 +744,7 @@
}
},
"errors.email-already-validated" : {
"used-in" : [ "src/app/main/ui/auth.cljs:95" ],
"used-in" : [ "src/app/main/ui/auth.cljs:94" ],
"translations" : {
"en" : "Email already validated.",
"fr" : "Adresse e-mail déjà validé.",
@ -762,7 +762,7 @@
}
},
"errors.generic" : {
"used-in" : [ "src/app/main/ui/auth.cljs:99", "src/app/main/ui/settings/profile.cljs:36" ],
"used-in" : [ "src/app/main/ui/settings/profile.cljs:36", "src/app/main/ui/auth.cljs:98" ],
"translations" : {
"en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé.",
@ -834,7 +834,7 @@
}
},
"errors.registration-disabled" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:49" ],
"used-in" : [ "src/app/main/ui/auth/register.cljs:48" ],
"translations" : {
"en" : "The registration is currently disabled.",
"fr" : "L'enregistrement est actuellement désactivé.",
@ -843,7 +843,7 @@
}
},
"errors.unexpected-error" : {
"used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/auth/register.cljs:55", "src/app/main/ui/settings/change_email.cljs:50" ],
"used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/settings/change_email.cljs:50", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/auth/register.cljs:54" ],
"translations" : {
"en" : "An unexpected error occurred.",
"fr" : "Une erreur inattendue c'est produite",
@ -924,7 +924,7 @@
}
},
"settings.cancel-email-change" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:81" ],
"used-in" : [ "src/app/main/ui/settings/profile.cljs:79" ],
"translations" : {
"en" : "Cancel",
"fr" : "Annuler",
@ -942,13 +942,13 @@
}
},
"settings.change-email-info3" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:78" ],
"translations" : {
"en" : null,
"fr" : null,
"es" : null,
"ru" : null
},
"used-in" : [ "src/app/main/ui/settings/profile.cljs:78" ]
"ru" : null,
"es" : null
}
},
"settings.change-email-label" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:73" ],
@ -1023,7 +1023,7 @@
}
},
"settings.email-verification-pending" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:86" ],
"used-in" : [ "src/app/main/ui/settings/profile.cljs:88" ],
"translations" : {
"en" : "There is a pending email validation.",
"fr" : "Une validation par e-mail est en attente.",
@ -1098,10 +1098,10 @@
"translations" : {
"en" : null,
"fr" : null,
"es" : null,
"ru" : null
"ru" : null,
"es" : null
},
"used-in" : [ "src/app/main/ui/dashboard.cljs:100" ]
"unused" : true
},
"settings.notifications.email-verified-successfully" : {
"used-in" : [ "src/app/main/ui/auth.cljs:57" ],
@ -1131,7 +1131,7 @@
}
},
"settings.notifications.profile-saved" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:41", "src/app/main/ui/settings/options.cljs:37" ],
"used-in" : [ "src/app/main/ui/settings/options.cljs:37", "src/app/main/ui/settings/profile.cljs:41" ],
"translations" : {
"en" : "Profile saved successfully!",
"fr" : "Profil enregistré avec succès!",
@ -1185,7 +1185,7 @@
}
},
"settings.profile-submit-label" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:89", "src/app/main/ui/settings/password.cljs:93", "src/app/main/ui/settings/options.cljs:67" ],
"used-in" : [ "src/app/main/ui/settings/password.cljs:93", "src/app/main/ui/settings/options.cljs:67", "src/app/main/ui/settings/profile.cljs:91" ],
"translations" : {
"en" : "Update settings",
"fr" : "Mettre à jour les paramètres",
@ -1194,7 +1194,7 @@
}
},
"settings.remove-account-label" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:94" ],
"used-in" : [ "src/app/main/ui/settings/profile.cljs:96" ],
"translations" : {
"en" : "Want to remove your account?",
"fr" : "Vous souhaitez supprimer votre compte?",
@ -1230,7 +1230,7 @@
}
},
"settings.update-photo-label" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:115" ],
"used-in" : [ "src/app/main/ui/settings/profile.cljs:117" ],
"translations" : {
"en" : "UPDATE",
"fr" : "METTRE A JOUR",
@ -1740,7 +1740,7 @@
}
},
"workspace.libraries.add" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:106" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:111" ],
"translations" : {
"en" : "Add",
"fr" : "",
@ -1749,7 +1749,7 @@
}
},
"workspace.libraries.colors" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:68" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:42" ],
"translations" : {
"en" : "%s colors",
"fr" : "",
@ -1764,13 +1764,13 @@
}
},
"workspace.libraries.colors.file-library" : {
"used-in" : [ "src/app/main/ui/workspace/colorpicker.cljs:337", "src/app/main/ui/workspace/colorpalette.cljs:150" ],
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:150", "src/app/main/ui/workspace/colorpicker.cljs:337" ],
"translations" : {
"en" : "File library"
}
},
"workspace.libraries.colors.recent-colors" : {
"used-in" : [ "src/app/main/ui/workspace/colorpicker.cljs:336", "src/app/main/ui/workspace/colorpalette.cljs:160" ],
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:160", "src/app/main/ui/workspace/colorpicker.cljs:336" ],
"translations" : {
"en" : "Recent colors"
}
@ -1787,8 +1787,17 @@
"en" : "Small thumbnails"
}
},
"workspace.libraries.components" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:36" ],
"translations" : {
"en" : "%s components",
"fr" : "",
"ru" : "",
"es" : "%s componentes"
}
},
"workspace.libraries.file-library" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:75" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:80" ],
"translations" : {
"en" : "File library",
"fr" : "",
@ -1797,7 +1806,7 @@
}
},
"workspace.libraries.graphics" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:65" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:39" ],
"translations" : {
"en" : "%s graphics",
"fr" : "",
@ -1806,7 +1815,7 @@
}
},
"workspace.libraries.in-this-file" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:72" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:77" ],
"translations" : {
"en" : "LIBRARIES IN THIS FILE",
"fr" : "",
@ -1815,7 +1824,7 @@
}
},
"workspace.libraries.libraries" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:149" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:171" ],
"translations" : {
"en" : "LIBRARIES",
"fr" : "",
@ -1823,8 +1832,26 @@
"es" : "BIBLIOTECAS"
}
},
"workspace.libraries.library" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:131" ],
"translations" : {
"en" : "LIBRARY",
"fr" : "",
"ru" : "",
"es" : "BIBLIOTECA"
}
},
"workspace.libraries.no-libraries-need-sync" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:129" ],
"translations" : {
"en" : "There are no Shared Libraries that need update",
"fr" : "",
"ru" : "",
"es" : "No hay bibliotecas que necesiten ser actualizadas"
}
},
"workspace.libraries.no-matches-for" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:112" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:117" ],
"translations" : {
"en" : "No matches found for “%s“",
"fr" : "Aucune correspondance pour “%s“",
@ -1833,7 +1860,7 @@
}
},
"workspace.libraries.no-shared-libraries-available" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:111" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:116" ],
"translations" : {
"en" : "There are no Shared Libraries available",
"fr" : "",
@ -1842,7 +1869,7 @@
}
},
"workspace.libraries.remove" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:82" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:87" ],
"translations" : {
"en" : "Remove",
"fr" : "",
@ -1851,7 +1878,7 @@
}
},
"workspace.libraries.search-shared-libraries" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:89" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:94" ],
"translations" : {
"en" : "Search shared libraries",
"fr" : "",
@ -1860,7 +1887,7 @@
}
},
"workspace.libraries.shared-libraries" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:86" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:91" ],
"translations" : {
"en" : "SHARED LIBRARIES",
"fr" : "",
@ -1868,8 +1895,17 @@
"es" : "BIBLIOTECAS COMPARTIDAS"
}
},
"workspace.libraries.update" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:138" ],
"translations" : {
"en" : "Update",
"fr" : "",
"ru" : "",
"es" : "Actualizar"
}
},
"workspace.libraries.updates" : {
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:153" ],
"used-in" : [ "src/app/main/ui/workspace/libraries.cljs:175" ],
"translations" : {
"en" : "UPDATES",
"fr" : "",
@ -2670,7 +2706,17 @@
"es" : "Texto (T)"
}
},
"workspace.updates.dismiss" : {
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:487" ],
"translations" : {
"en" : "Dismiss",
"fr" : "",
"ru" : "",
"es" : "Ignorar"
}
},
"workspace.updates.there-are-updates" : {
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:483" ],
"translations" : {
"en" : "There are updates in shared libraries",
"fr" : "",
@ -2679,6 +2725,7 @@
}
},
"workspace.updates.update" : {
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:485" ],
"translations" : {
"en" : "Update",
"fr" : "",
@ -2686,14 +2733,6 @@
"es" : "Actualizar"
}
},
"workspace.updates.dismiss" : {
"translations" : {
"en" : "Dismiss",
"fr" : "",
"ru" : "",
"es" : "Ignorar"
}
},
"workspace.viewport.click-to-close-path" : {
"used-in" : [ "src/app/main/ui/workspace/drawarea.cljs:59" ],
"translations" : {

View file

@ -153,7 +153,17 @@
(fn [file]
(if (= (:id file) file-id)
(assoc file :initialized true)
file))))))
file))))
ptk/WatchEvent
(watch [_ state stream]
(let [ignore-until (get-in state [:workspace-file :ignore-sync-until])
needs-update? (some #(and (> (:modified-at %) (:synced-at %))
(or (not ignore-until)
(> (:modified-at %) ignore-until)))
(vals (get state :workspace-libraries)))]
(when needs-update?
(rx/of (dwl/notify-sync-file file-id)))))))
(defn finalize-file
[project-id file-id]

View file

@ -15,6 +15,7 @@
[app.common.pages-helpers :as cph]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom]
[app.main.data.messages :as dm]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.selection :as dws]
[app.common.pages :as cp]
@ -24,6 +25,7 @@
[app.util.color :as color]
[app.util.i18n :refer [tr]]
[app.util.router :as rt]
[app.util.time :as dt]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[potok.core :as ptk]))
@ -346,14 +348,16 @@
(st/emit! (rt/nav-new-window :workspace pparams qparams))))))
(defn ext-library-changed
[file-id changes]
[file-id modified-at changes]
(us/assert ::us/uuid file-id)
(us/assert ::cp/changes changes)
(ptk/reify ::ext-library-changed
ptk/UpdateEvent
(update [_ state]
(d/update-in-when state [:workspace-libraries file-id :data]
cp/process-changes changes))))
(-> state
(assoc-in [:workspace-libraries file-id :modified-at] modified-at)
(d/update-in-when [:workspace-libraries file-id :data]
cp/process-changes changes)))))
(declare generate-sync-file)
(declare generate-sync-page)
@ -433,10 +437,55 @@
[file-id]
(us/assert (s/nilable ::us/uuid) file-id)
(ptk/reify ::sync-file
ptk/UpdateEvent
(update [_ state]
(if file-id
(assoc-in state [:workspace-libraries file-id :synced-at] (dt/now))
state))
ptk/WatchEvent
(watch [_ state stream]
(let [[rchanges uchanges] (generate-sync-file state file-id)]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
(rx/concat
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))
(when file-id
(rp/mutation :update-sync
{:file-id (get-in state [:workspace-file :id])
:library-id file-id})))))))
(def ignore-sync
(ptk/reify ::sync-file
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-file :ignore-sync-until] (dt/now)))
ptk/WatchEvent
(watch [_ state stream]
(rp/mutation :ignore-sync
{:file-id (get-in state [:workspace-file :id])
:date (dt/now)}))))
(defn notify-sync-file
[file-id]
(us/assert ::us/uuid file-id)
(ptk/reify ::notify-sync-file
ptk/WatchEvent
(watch [_ state stream]
(let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %))
(vals (get state :workspace-libraries)))
do-update #(do (apply st/emit! (map (fn [library]
(sync-file (:id library)))
libraries-need-sync))
(st/emit! dm/hide))
do-dismiss #(do (st/emit! ignore-sync)
(st/emit! dm/hide))]
(rx/of (dm/info-dialog
(tr "workspace.updates.there-are-updates")
:inline-actions
[{:label (tr "workspace.updates.update")
:callback do-update}
{:label (tr "workspace.updates.dismiss")
:callback do-dismiss}]))))))
(defn- generate-sync-file
[state file-id]

View file

@ -13,7 +13,6 @@
[app.common.geom.point :as gpt]
[app.common.pages :as cp]
[app.common.spec :as us]
[app.main.data.messages :as dm]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.persistence :as dwp]
[app.main.data.workspace.libraries :as dwl]
@ -204,25 +203,21 @@
(rx/from (map dwc/update-indices page-ids))))))))
(s/def ::library-change-event
(s/keys :req-un [::type ::profile-id ::file-id ::session-id ::revn ::changes]))
(s/keys :req-un [::type
::profile-id
::file-id
::session-id
::revn
::modified-at
::changes]))
(defn handle-library-change
[{:keys [file-id changes] :as msg}]
[{:keys [file-id modified-at changes] :as msg}]
(us/assert ::library-change-event msg)
(ptk/reify ::handle-library-change
ptk/WatchEvent
(watch [_ state stream]
(when (contains? (:workspace-libraries state) file-id)
(let [do-update #(do
(st/emit! (dwl/sync-file file-id))
(st/emit! dm/hide))
do-dismiss #(st/emit! dm/hide)]
(rx/of (dwl/ext-library-changed file-id changes)
(dm/info-dialog
(tr "workspace.updates.there-are-updates")
:inline-actions
[{:label (tr "workspace.updates.update")
:callback do-update}
{:label (tr "workspace.updates.dismiss")
:callback do-dismiss}])))))))
(rx/of (dwl/ext-library-changed file-id modified-at changes)
(dwl/notify-sync-file file-id))))))

View file

@ -16,12 +16,32 @@
[app.main.store :as st]
[app.main.refs :as refs]
[app.main.data.workspace :as dw]
[app.main.data.workspace.libraries :as dwl]
[app.main.ui.icons :as i]
[app.main.ui.modal :as modal]))
(def workspace-file
(l/derived :workspace-file st/state))
(defn contents-str
[library]
(let [components-count (count (get-in library [:data :components] []))
graphics-count (count (get-in library [:data :media] []))
colors-count (count (get-in library [:data :colors] []))]
;; Include a   so this block has always some content
(str
(str/join " · "
(cond-> []
(< 0 components-count)
(conj (tr "workspace.libraries.components" components-count))
(< 0 graphics-count)
(conj (tr "workspace.libraries.graphics" graphics-count))
(< 0 colors-count)
(conj (tr "workspace.libraries.colors" colors-count))))
"\u00A0")))
(mf/defc libraries-tab
[{:keys [file libraries shared-files] :as props}]
(let [search-term (mf/use-state "")
@ -51,22 +71,7 @@
(mf/use-callback (mf/deps file) #(st/emit! (dw/link-file-to-library (:id file) %)))
unlink-library
(mf/use-callback (mf/deps file) #(st/emit! (dw/unlink-file-from-library (:id file) %)))
contents-str
(fn [library]
(let [graphics-count (count (get-in library [:data :media] []))
colors-count (count (get-in library [:data :colors] []))]
;; Include a &nbsp; so this block has always some content
(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")))]
(mf/use-callback (mf/deps file) #(st/emit! (dw/unlink-file-from-library (:id file) %)))]
[:*
[:div.section
[:div.section-title (tr "workspace.libraries.in-this-file")]
@ -113,8 +118,25 @@
(mf/defc updates-tab
[]
[:div])
[{:keys [file libraries] :as props}]
(let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %))
(vals libraries))
update-library #(st/emit! (dwl/sync-file %))]
[:div.section
(if (empty? libraries-need-sync)
[:div.section-list-empty
i/library
(tr "workspace.libraries.no-libraries-need-sync")]
[:*
[:div.section-title (tr "workspace.libraries.library")]
[:div.section-list
(for [library libraries-need-sync]
[:div.section-list-item {:key (:id library)}
[:div.item-name (:name library)]
[:div.item-contents (contents-str library)]
[:input.item-button {:type "button"
:value (tr "workspace.libraries.update")
:on-click #(update-library (:id library))}]])]])]))
(mf/defc libraries-dialog
@ -158,5 +180,6 @@
:libraries libraries
:shared-files shared-files}]
:updates
[:& updates-tab {}])]]]]))
[:& updates-tab {:file file
:libraries libraries}])]]]]))