diff --git a/.serena/memories/frontend/core.md b/.serena/memories/frontend/core.md index b5fb47dce4..1233aaaf31 100644 --- a/.serena/memories/frontend/core.md +++ b/.serena/memories/frontend/core.md @@ -13,6 +13,7 @@ Frontend: CLJS SPA; React/Rumext; Potok; RxJS; okulary refs; SCSS modules; share - `app.util.*`: DOM, HTTP, i18n, keyboard, codegen, and general frontend utilities. - `frontend/packages/*` and `frontend/text-editor`: JS/TS workspace packages consumed by the app. - Nitrate subscription/organization UI and flows live under `app.main.data.nitrate` and `app.main.ui.nitrate*`; backend/API behavior is covered by backend memories, and shared permission rules are in `common/src/app/common/types/nitrate_permissions.cljc`. +- `app.config` external bridges (`external-feature-flag`, `external-session-id`, `external-context-info`, `external-notify-register-success`, `initialize-external-context-info`) delegate to `globalThis` hooks injected by the SaaS host. Never delete `external-feature-flag`, even with zero call sites: it is the seam for future A/B tests. ## Lint and Format diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 78d2ac45c4..14119c819b 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -33,11 +33,9 @@ [app.rpc.doc :as-alias doc] [app.rpc.helpers :as rph] [app.setup :as-alias setup] - [app.setup.welcome-file :refer [create-welcome-file]] [app.storage :as sto] [app.tokens :as tokens] [app.util.services :as sv] - [app.worker :as wrk] [cuerdas.core :as str])) (def schema:password @@ -308,7 +306,6 @@ [:fullname ::sm/text] [:email ::sm/email] [:password schema:password] - [:create-welcome-file {:optional true} :boolean] [:accept-newsletter-updates {:optional true} :boolean] [:invitation-token {:optional true} schema:token]]) @@ -446,7 +443,7 @@ :extra-data ptoken})))) (defn register-profile - [{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}] + [{:keys [::db/conn] :as cfg} {:keys [token] :as params}] (let [claims (tokens/verify cfg {:token token :iss :prepared-register}) params (cond-> claims (:accept-newsletter-updates params) @@ -469,14 +466,7 @@ (tokens/verify cfg {:token token :iss :team-invitation})) props (-> (audit/profile->props profile) - (assoc :from-invitation (some? invitation))) - - - create-welcome-file-when-needed - (fn [] - (when (:create-welcome-file params) - (let [cfg (dissoc cfg ::db/conn)] - (wrk/submit! executor (create-welcome-file cfg profile)))))] + (assoc :from-invitation (some? invitation)))] (cond ;; When profile is blocked, we just ignore it and return plain data @@ -525,7 +515,6 @@ :email (:email profile) :invitation-token token} (rph/with-transform (session/create-fn cfg profile claims)) - (rph/with-defer create-welcome-file-when-needed) (rph/with-meta {::audit/replace-props props ::audit/context {:action "accept-invitation"} ::audit/profile-id (:id profile)}))) @@ -533,7 +522,6 @@ (:is-active profile) (-> (profile/strip-private-attrs profile) (rph/with-transform (session/create-fn cfg profile claims)) - (rph/with-defer create-welcome-file-when-needed) (rph/with-meta {::audit/replace-props props ::audit/context {:action "login"} @@ -548,7 +536,6 @@ (-> {:id (:id profile) :email (:email profile)} - (rph/with-defer create-welcome-file-when-needed) (rph/with-meta {::audit/replace-props props ::audit/context {:action "email-verification"} diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 22c7e3dfa5..346f275e9f 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -69,7 +69,6 @@ [:onboarding-questions-answered {:optional true} ::sm/boolean] [:nitrate-onboarding-viewed {:optional true} ::sm/boolean] [:v2-info-shown {:optional true} ::sm/boolean] - [:welcome-file-id {:optional true} [:maybe ::sm/boolean]] [:release-notes-viewed {:optional true} [::sm/text {:max 100}]] [:notifications {:optional true} schema:props-notifications] diff --git a/backend/src/app/setup/welcome_file.clj b/backend/src/app/setup/welcome_file.clj deleted file mode 100644 index 48887e53ed..0000000000 --- a/backend/src/app/setup/welcome_file.clj +++ /dev/null @@ -1,67 +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) KALEIDOS INC Sucursal en EspaƱa SL - -(ns app.setup.welcome-file - (:require - [app.common.logging :as l] - [app.db :as db] - [app.rpc :as-alias rpc] - [app.rpc.climit :as-alias climit] - [app.rpc.commands.files :as files] - [app.rpc.commands.files-update :as fupdate] - [app.rpc.commands.management :as management] - [app.rpc.commands.profile :as profile] - [app.rpc.doc :as-alias doc] - [app.setup :as-alias setup] - [app.setup.templates :as tmpl] - [app.worker :as-alias wrk])) - -(def ^:private page-id #uuid "2c6952ee-d00e-8160-8004-d2250b7210cb") -(def ^:private shape-id #uuid "765e9f82-c44e-802e-8004-d72a10b7b445") - -(def ^:private update-path - [:data :pages-index page-id :objects shape-id - :content :children 0 :children 0 :children 0]) - -(def ^:private sql:mark-file-object-thumbnails-deleted - "UPDATE file_tagged_object_thumbnail - SET deleted_at = now() - WHERE file_id = ?") - -(def ^:private sql:mark-file-thumbnail-deleted - "UPDATE file_thumbnail - SET deleted_at = now() - WHERE file_id = ?") - -(defn- update-welcome-shape - [_ file name] - (let [text (str "Welcome to Penpot, " name "!")] - (-> file - (update-in update-path assoc :text text) - (update-in [:data :pages-index page-id :objects shape-id] assoc :name "Welcome to Penpot!") - (update-in [:data :pages-index page-id :objects shape-id] dissoc :position-data)))) - -(defn create-welcome-file - [cfg {:keys [id fullname] :as profile}] - (try - (let [cfg (dissoc cfg ::db/conn) - params {:profile-id (:id profile) - :project-id (:default-project-id profile)} - template-stream (tmpl/get-template-stream cfg "welcome") - file-id (-> (management/clone-template cfg params template-stream) - first) - file-name (str fullname "'s first file")] - - (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}] - (files/rename-file conn {:id file-id :name file-name}) - (fupdate/update-file! cfg file-id update-welcome-shape fullname) - (profile/update-profile-props cfg id {:welcome-file-id file-id}) - (db/exec-one! conn [sql:mark-file-object-thumbnails-deleted file-id]) - (db/exec-one! conn [sql:mark-file-thumbnail-deleted file-id])))) - - (catch Throwable cause - (l/error :hint "unexpected error on create welcome file " :cause cause)))) - diff --git a/frontend/src/app/main/data/auth.cljs b/frontend/src/app/main/data/auth.cljs index 2339c02452..05bd5e9621 100644 --- a/frontend/src/app/main/data/auth.cljs +++ b/frontend/src/app/main/data/auth.cljs @@ -37,7 +37,7 @@ "This is the main event that is executed once we have logged in profile. The profile can proceed from standard login or from accepting invitation, or third party auth signup or singin." - [{:keys [props] :as profile}] + [profile] (letfn [(get-redirect-events [teams] (if-let [token (:invitation-token profile)] (rx/of (rt/nav :auth-verify-token {:token token})) @@ -47,22 +47,16 @@ (if (= redirect-href (rt/get-current-href)) (rx/of (rt/reload true)) (rx/of (rt/nav-raw :href redirect-href)))) - (if-let [file-id (get props :welcome-file-id)] - (rx/of (dcm/go-to-workspace - :file-id file-id - :team-id (:default-team-id profile)) - (dp/update-profile-props {:welcome-file-id nil})) - - (let [default-team-id (:default-team-id profile) - team-ids (into #{} (map :id) teams) - team-id (dtm/get-last-team-id) - team-id (if (and team-id (contains? team-ids team-id)) - team-id - default-team-id)] - (->> (dtm/resolve-login-team-id {:team-id team-id - :default-team-id default-team-id}) - (rx/mapcat (fn [team-id] - (rx/of (dcm/go-to-dashboard-recent {:team-id team-id}))))))))))] + (let [default-team-id (:default-team-id profile) + team-ids (into #{} (map :id) teams) + team-id (dtm/get-last-team-id) + team-id (if (and team-id (contains? team-ids team-id)) + team-id + default-team-id)] + (->> (dtm/resolve-login-team-id {:team-id team-id + :default-team-id default-team-id}) + (rx/mapcat (fn [team-id] + (rx/of (dcm/go-to-dashboard-recent {:team-id team-id})))))))))] (ptk/reify ::logged-in ptk/WatchEvent diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 58175de604..dac8975f1f 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -270,24 +270,12 @@ file-id (some-> params :file-id uuid/parse*) page-id (some-> params :page-id uuid/parse*) layout (some-> params :layout keyword)] - [:? {} - (when (cf/external-feature-flag "onboarding-03" "test") - (cond - show-question-modal? - [:& questions-modal] - - show-team-modal? - [:> onboarding-team-modal* {:go-to-team false}] - - show-release-modal? - [:& release-notes-modal {:version (:main cf/version)}])) - - [:> team-container* {:team-id team-id} - [:> workspace-page* {:team-id team-id - :file-id file-id - :page-id page-id - :layout-name layout - :key file-id}]]]) + [:> team-container* {:team-id team-id} + [:> workspace-page* {:team-id team-id + :file-id file-id + :page-id page-id + :layout-name layout + :key file-id}]]) :viewer (let [params (get params :query) diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index da3438640f..1b8fc40f10 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -155,14 +155,7 @@ (mf/deps on-success-callback) (fn [form _event] (reset! submitted? true) - (let [create-welcome-file? - (cf/external-feature-flag "onboarding-03" "test") - - cdata - (cond-> (:clean-data @form) - create-welcome-file? - (assoc :create-welcome-file true))] - + (let [cdata (:clean-data @form)] (->> (rp/cmd! :prepare-register-profile cdata) (rx/subs! on-register-profile on-error #(reset! submitted? false))))))] @@ -321,13 +314,7 @@ (mf/deps on-success on-error) (fn [form _] (reset! submitted? true) - (let [create-welcome-file? - (cf/external-feature-flag "onboarding-03" "test") - - params - (cond-> (:clean-data @form) - create-welcome-file? (assoc :create-welcome-file true))] - + (let [params (:clean-data @form)] (->> (rp/cmd! :register-profile params) (rx/finalize #(reset! submitted? false)) (rx/subs! on-success on-error)))))]