diff --git a/.gitignore b/.gitignore index 22ae73c02..b7f152cd6 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ /backend/resources/public/assets /backend/resources/public/media /backend/target/ +/backend/builtin-templates /bundle* /cd.md /clj-profiler/ diff --git a/backend/resources/app/onboarding.edn b/backend/resources/app/onboarding.edn new file mode 100644 index 000000000..88fa714a9 --- /dev/null +++ b/backend/resources/app/onboarding.edn @@ -0,0 +1,8 @@ +[{:id "penpot-design-system" + :name "Penpot Design System" + :thumbnail-uri "https://penpot.app/images/libraries/cover-ds-penpot.jpg" + :file-uri "https://github.com/penpot/penpot-files/raw/main/Penpot-Design-system.penpot"} + {:id "wireframing-kit" + :name "Wireframing Kit" + :thumbnail-uri "https://penpot.app/images/libraries/cover-wireframes.jpg" + :file-uri "https://github.com/penpot/penpot-files/raw/main/wireframing-kit.penpot"}] diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index cc20cc7e5..ed2661764 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -235,7 +235,8 @@ :audit (ig/ref :app.loggers.audit/collector) :ldap (ig/ref :app.auth.ldap/provider) :http-client (ig/ref :app.http/client) - :executors (ig/ref :app.worker/executors)} + :executors (ig/ref :app.worker/executors) + :templates (ig/ref :app.setup/builtin-templates)} :app.rpc.doc/routes {:methods (ig/ref :app.rpc/methods)} @@ -352,6 +353,9 @@ {:port (cf/get :srepl-port) :host (cf/get :srepl-host)} + :app.setup/builtin-templates + {:http-client (ig/ref :app.http/client)} + :app.setup/props {:pool (ig/ref :app.db/pool) :key (cf/get :secret-key)} diff --git a/backend/src/app/setup.clj b/backend/src/app/setup.clj index b1b5e9313..7bc0960ba 100644 --- a/backend/src/app/setup.clj +++ b/backend/src/app/setup.clj @@ -10,6 +10,7 @@ [app.common.logging :as l] [app.common.uuid :as uuid] [app.db :as db] + [app.setup.builtin-templates] [buddy.core.codecs :as bc] [buddy.core.nonce :as bn] [clojure.spec.alpha :as s] diff --git a/backend/src/app/setup/builtin_templates.clj b/backend/src/app/setup/builtin_templates.clj new file mode 100644 index 000000000..d05255058 --- /dev/null +++ b/backend/src/app/setup/builtin_templates.clj @@ -0,0 +1,74 @@ +;; 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.setup.builtin-templates + "A service/module that is reponsible for download, load & internally + expose a set of builtin penpot file templates." + (:require + [app.common.logging :as l] + [app.common.spec :as us] + [app.http.client :as http] + [clojure.edn :as edn] + [clojure.java.io :as io] + [clojure.spec.alpha :as s] + [datoteka.core :as fs] + [integrant.core :as ig])) + +(declare download-all!) + +(s/def ::id ::us/not-empty-string) +(s/def ::name ::us/not-empty-string) +(s/def ::thumbnail-uri ::us/not-empty-string) +(s/def ::file-uri ::us/not-empty-string) +(s/def ::path fs/path?) + +(s/def ::template + (s/keys :req-un [::id ::name ::thumbnail-uri ::file-uri] + :opt-un [::path])) + +(s/def ::http-client ::http/client) + +(defmethod ig/pre-init-spec :app.setup/builtin-templates [_] + (s/keys :req-un [::http-client])) + +(defmethod ig/init-key :app.setup/builtin-templates + [_ cfg] + (let [presets (-> "app/onboarding.edn" io/resource slurp edn/read-string)] + (l/info :hint "loading template files" :total (count presets)) + (let [result (download-all! cfg presets)] + (us/conform (s/coll-of ::template) result)))) + +(defn- download-preset! + [cfg {:keys [path file-uri] :as preset}] + (let [response (http/req! (:http-client cfg) + {:method :get + :uri file-uri} + {:response-type :input-stream + :sync? true})] + (us/verify! (= 200 (:status response)) "unexpected response found on fetching preset") + (with-open [output (io/output-stream path)] + (with-open [input (io/input-stream (:body response))] + (io/copy input output))))) + +(defn- download-all! + "Download presets to the default directory, if preset is already + downloaded, no action will be performed." + [cfg presets] + (let [dest (fs/join fs/*cwd* "builtin-templates")] + (when-not (fs/exists? dest) + (fs/create-dir dest)) + + (doall + (map (fn [item] + (let [path (fs/join dest (:id item)) + item (assoc item :path path)] + (if (fs/exists? path) + (l/trace :hint "template file already present" :id (:id item)) + (do + (l/trace :hint "downloading template file" :id (:id item) :dest (str path)) + (download-preset! cfg item))) + item)) + presets))))