Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Alejandro Alonso 2026-09-04 11:00:56 +02:00
commit 7f46c8c80e
9 changed files with 109 additions and 21 deletions

View File

@ -235,9 +235,8 @@
:organization-name (:name organization)
:member-email (:email-to invitation)
:member-id (:id member)
:role role}
organization
(assoc :user-who-send-invitation (str profile-id))
:role role
:user-who-send-invitation (str profile-id)}
(not organization)
(assoc :team-belongs-to-organization (boolean team-organization-id)

View File

@ -308,7 +308,9 @@
(assoc :name "accept-organization-invitation")
(assoc :props
(-> props
(assoc :organization-id organization-id-on-add)
(assoc :organization-id organization-id-on-add
:user-id (:id profile)
:user-who-send-invitation (:created-by invitation))
(audit/clean-props))))))
(cond-> (assoc claims :state :created)
@ -325,6 +327,8 @@
(assoc :organization-id organization-id-on-add
:organization-member-add-source organization-add-source
:belongs-to-team-on-add (boolean team-id)
:user-id (:id profile)
:user-who-send-invitation (:created-by invitation)
:organization-member-count-before
organization-member-count-before)
(audit/clean-props))}))))))

View File

@ -154,10 +154,14 @@
(get-in % [:props :member-email])))
events))]
(doseq [event [create-organization update-organization]]
(t/is (= (str (:id owner))
(get-in event [:props :user-who-send-invitation])))
(t/is (true? (get-in event [:props :team-belongs-to-organization])))
(t/is (true? (get-in event [:props :adds-invitee-to-organization])))
(t/is (true? (get-in event [:props :invitee-already-organization-member]))))
(t/is (= (str (:id owner))
(get-in create-plain [:props :user-who-send-invitation])))
(t/is (false? (get-in create-plain [:props :team-belongs-to-organization])))
(t/is (false? (get-in create-plain [:props :adds-invitee-to-organization])))
(t/is (false? (get-in create-plain [:props :invitee-already-organization-member])))))))
@ -521,6 +525,9 @@
(let [event (organization-event)]
(t/is (= organization-id (get-in event [:props :organization-id])))
(t/is (= (:id invitee) (get-in event [:props :user-id])))
(t/is (= (:id inviter)
(get-in event [:props :user-who-send-invitation])))
(t/is (not (contains? (:props event) :organization-member-add-source)))
(t/is (not (contains? (:props event) :belongs-to-team-on-add)))
(t/is (not (contains? (:props event) :organization-member-count-before)))
@ -530,6 +537,10 @@
(:origin @frontend-event)))
(t/is (= organization-id
(get-in @frontend-event [:props :organization-id])))
(t/is (= (:id invitee)
(get-in @frontend-event [:props :user-id])))
(t/is (= (:id inviter)
(get-in @frontend-event [:props :user-who-send-invitation])))
(t/is (= "direct-organization-invitation"
(get-in @frontend-event [:props :organization-member-add-source])))
(t/is (false? (get-in @frontend-event [:props :belongs-to-team-on-add])))
@ -570,6 +581,9 @@
(t/is (some #(= "accept-team-invitation-from" (:name %)) events))
(t/is (= (:id team) (get-in event [:props :team-id])))
(t/is (= organization-id (get-in event [:props :organization-id])))
(t/is (= (:id invitee) (get-in event [:props :user-id])))
(t/is (= (:id inviter)
(get-in event [:props :user-who-send-invitation])))
(t/is (not (contains? (:props event) :organization-member-add-source)))
(t/is (not (contains? (:props event) :belongs-to-team-on-add)))
(t/is (not (contains? (:props event) :organization-member-count-before)))
@ -578,6 +592,10 @@
(t/is (= (:id team) (get-in @frontend-event [:props :team-id])))
(t/is (= organization-id
(get-in @frontend-event [:props :organization-id])))
(t/is (= (:id invitee)
(get-in @frontend-event [:props :user-id])))
(t/is (= (:id inviter)
(get-in @frontend-event [:props :user-who-send-invitation])))
(t/is (= "team-invitation"
(get-in @frontend-event [:props :organization-member-add-source])))
(t/is (true? (get-in @frontend-event [:props :belongs-to-team-on-add])))

View File

@ -17,7 +17,7 @@
[promesa.core :as p]))
(defn render
[{:keys [file-id page-id share-id token scale type objects skip-children is-wasm] :as params} on-object]
[{:keys [file-id page-id share-id token scale type objects skip-children] :as params} on-object]
(letfn [(prepare-options [uri]
#js {:screen #js {:width bw/default-viewport-width
:height bw/default-viewport-height}
@ -25,7 +25,7 @@
:height bw/default-viewport-height}
:locale "en-US"
:storageState #js {:cookies (bw/create-cookies uri {:token token})}
:deviceScaleFactor (if is-wasm 1 scale) ;; wasm won't use deviceScaleFactor
:deviceScaleFactor scale
:userAgent bw/default-user-agent})
(render-object [page {:keys [id] :as object}]
@ -59,9 +59,7 @@
:share-id share-id
:object-id (mapv :id objects)
:route "objects"
:skip-children skip-children
:wasm (when is-wasm "true")
:scale scale}
:skip-children skip-children}
uri (-> (cf/get-internal-uri)
(u/ensure-path-slash)
(u/join "render.html")

View File

@ -600,6 +600,12 @@ export class WorkspacePage extends BaseWebSocketPage {
.getByRole("button", { name: "Comments (C)" })
.click(clickOptions);
}
async toggleCommentsVisibilityFromMenu(clickOptions = {}) {
await this.page.getByRole("button", { name: "Main menu" }).click();
await this.page.getByText("view").last().click();
await this.page.locator("#file-menu-comments").click(clickOptions);
}
}
export default WorkspacePage;

View File

@ -35,3 +35,64 @@ test("Group bubbles when zooming out if they overlap", async ({ page }) => {
/unread/,
);
});
test("Opening the Comments section only temporarily overrides a disabled global comments setting", async ({
page,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.setupFileWithComments();
await workspacePage.goToWorkspace();
const bubble = page.getByTestId("floating-thread-bubble-1");
// "Display comments" is enabled by default, so the bubble is already visible.
await expect(bubble).toBeVisible();
// Turn the global "Display comments" setting off from the main menu.
await workspacePage.toggleCommentsVisibilityFromMenu();
await expect(bubble).toBeHidden();
// Opening the Comments section shows comments regardless of the global setting.
await workspacePage.showComments();
await expect(bubble).toBeVisible();
// Closing the Comments section falls back to the (still disabled) global setting.
await workspacePage.showComments();
await expect(bubble).toBeHidden();
// The global setting itself must be untouched by opening/closing the section.
await page.getByRole("button", { name: "Main menu" }).click();
await page.getByText("view").last().click();
await expect(page.locator("#file-menu-comments")).toContainText(
"Show comments",
);
await page.keyboard.press("Escape");
});
test("Comments stay visible through opening and closing the Comments section when the global setting is enabled", async ({
page,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.setupFileWithComments();
await workspacePage.goToWorkspace();
const bubble = page.getByTestId("floating-thread-bubble-1");
// "Display comments" is enabled by default.
await expect(bubble).toBeVisible();
await workspacePage.showComments();
await expect(bubble).toBeVisible();
await workspacePage.showComments();
await expect(bubble).toBeVisible();
await page.getByRole("button", { name: "Main menu" }).click();
await page.getByText("view").last().click();
await expect(page.locator("#file-menu-comments")).toContainText(
"Hide comments",
);
await page.keyboard.press("Escape");
});

View File

@ -15,7 +15,6 @@
[app.main.data.workspace.drawing.common :as common]
[app.main.data.workspace.drawing.curve :as curve]
[app.main.data.workspace.drawing.line :as line]
[app.main.data.workspace.layout :as dwlo]
[app.main.data.workspace.path :as path]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@ -47,11 +46,6 @@
(when (= tool :path)
(rx/of (start-drawing :path)))
;; NOTE: comments are a special case and they manage they
;; own interrupt cycle.
(when (= tool :comments)
(rx/of (dwlo/toggle-layout-flag :display-comments :force? true)))
(when (and (not= tool :comments)
(not= tool :path))
(let [stopper (rx/filter (ptk/type? ::clear-drawing) stream)]

View File

@ -539,9 +539,10 @@
(let [objects (dsh/lookup-page-objects state)
selected-ids (dsh/lookup-selected state)
selected-shapes (map (d/getf objects) selected-ids)
add-new-variant? (every? ctc/is-variant? selected-shapes)
add-new-variant? (and (seq selected-shapes) (every? ctc/is-variant? selected-shapes))
undo-id (js/Symbol)]
(if add-new-variant?
(cond
add-new-variant?
(rx/concat
(rx/of
(ev/event {::ev/name "add-new-variant" ::ev/origin "workspace:shortcut-duplicate"})
@ -549,7 +550,12 @@
(add-new-variant (first selected-ids) false))
(rx/from (map #(add-new-variant % true) (rest selected-ids)))
(rx/of (dwu/commit-undo-transaction undo-id)))
(rx/of (dws/duplicate-selected true)))))))
(seq selected-ids)
(rx/of (dws/duplicate-selected true))
:else
(rx/empty))))))
(defn rename-variant
"Rename the variant container and all components belonging to this variant"

View File

@ -136,7 +136,9 @@
(repo/cmd! :get-page {:file-id file-id
:page-id page-id
:share-id share-id
:object-id object-id
:object-id (if (uuid? object-id)
object-id
(set object-id))
:features features}))
(rx/tap (fn [[fonts]]
(when (seq fonts)
@ -155,7 +157,7 @@
[:embed {:optional true} :boolean]
[:skip-children {:optional true} :boolean]
[:object-id
[:or [::sm/set ::sm/uuid] ::sm/uuid]]])
[:or [:vector ::sm/uuid] ::sm/uuid]]])
(def ^:private coerce-render-objects-params
(sm/coercer schema:render-objects))
@ -188,7 +190,7 @@
{:file-id file-id
:page-id page-id
:share-id share-id
:object-ids (into #{} object-id)
:object-ids (into [] (distinct) object-id)
:embed embed
:skip-children skip-children
:wasm wasm