mirror of
https://github.com/penpot/penpot.git
synced 2025-05-11 06:46:38 +02:00
♻️ Refactor application routing
Mainly removes an inconsistent use of path params and normalize all routes to use query params for make it extensible without breaking urls.
This commit is contained in:
parent
b2f02de5c1
commit
3e090b126e
90 changed files with 1617 additions and 1548 deletions
|
@ -77,7 +77,7 @@
|
||||||
:share-links links
|
:share-links links
|
||||||
:libraries libs
|
:libraries libs
|
||||||
:file file
|
:file file
|
||||||
:team team
|
:team (assoc team :permissions perms)
|
||||||
:permissions perms}))
|
:permissions perms}))
|
||||||
|
|
||||||
(def schema:get-view-only-bundle
|
(def schema:get-view-only-bundle
|
||||||
|
|
|
@ -1010,6 +1010,9 @@
|
||||||
(def valid-safe-number?
|
(def valid-safe-number?
|
||||||
(lazy-validator ::safe-number))
|
(lazy-validator ::safe-number))
|
||||||
|
|
||||||
|
(def valid-text?
|
||||||
|
(validator ::text))
|
||||||
|
|
||||||
(def check-safe-int!
|
(def check-safe-int!
|
||||||
(check-fn ::safe-int))
|
(check-fn ::safe-int))
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,6 @@
|
||||||
(recur (when continue? (rest styles)) taking? to result))
|
(recur (when continue? (rest styles)) taking? to result))
|
||||||
result))))
|
result))))
|
||||||
|
|
||||||
|
|
||||||
(defn content->text
|
(defn content->text
|
||||||
"Given a root node of a text content extracts the texts with its associated styles"
|
"Given a root node of a text content extracts the texts with its associated styles"
|
||||||
[content]
|
[content]
|
||||||
|
|
|
@ -18,11 +18,18 @@
|
||||||
java.nio.ByteBuffer)))
|
java.nio.ByteBuffer)))
|
||||||
|
|
||||||
(defn uuid
|
(defn uuid
|
||||||
"Parse string uuid representation into proper UUID instance."
|
"Creates an UUID instance from string, expectes valid uuid strings,
|
||||||
|
the existense of validation is implementation detail"
|
||||||
[s]
|
[s]
|
||||||
#?(:clj (UUID/fromString s)
|
#?(:clj (UUID/fromString s)
|
||||||
:cljs (c/uuid s)))
|
:cljs (c/uuid s)))
|
||||||
|
|
||||||
|
(defn parse
|
||||||
|
"Parse string uuid representation into proper UUID instance, validates input"
|
||||||
|
[s]
|
||||||
|
#?(:clj (UUID/fromString s)
|
||||||
|
:cljs (c/parse-uuid s)))
|
||||||
|
|
||||||
(defn next
|
(defn next
|
||||||
[]
|
[]
|
||||||
#?(:clj (UUIDv8/create)
|
#?(:clj (UUIDv8/create)
|
||||||
|
|
23
frontend/playwright/data/get-teams-role-viewer.json
Normal file
23
frontend/playwright/data/get-teams-role-viewer.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[{
|
||||||
|
"~:features": {
|
||||||
|
"~#set": [
|
||||||
|
"layout/grid",
|
||||||
|
"styles/v2",
|
||||||
|
"fdata/pointer-map",
|
||||||
|
"fdata/objects-map",
|
||||||
|
"components/v2",
|
||||||
|
"fdata/shape-data-type"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"~:permissions": {
|
||||||
|
"~:type": "~:membership",
|
||||||
|
"~:is-owner": false,
|
||||||
|
"~:is-admin": false,
|
||||||
|
"~:can-edit": false
|
||||||
|
},
|
||||||
|
"~:name": "Default",
|
||||||
|
"~:modified-at": "~m1713533116375",
|
||||||
|
"~:id": "~uc7ce0794-0992-8105-8004-38e630f7920a",
|
||||||
|
"~:created-at": "~m1713533116375",
|
||||||
|
"~:is-default": true
|
||||||
|
}]
|
23
frontend/playwright/data/get-teams.json
Normal file
23
frontend/playwright/data/get-teams.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[{
|
||||||
|
"~:features": {
|
||||||
|
"~#set": [
|
||||||
|
"layout/grid",
|
||||||
|
"styles/v2",
|
||||||
|
"fdata/pointer-map",
|
||||||
|
"fdata/objects-map",
|
||||||
|
"components/v2",
|
||||||
|
"fdata/shape-data-type"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"~:permissions": {
|
||||||
|
"~:type": "~:membership",
|
||||||
|
"~:is-owner": true,
|
||||||
|
"~:is-admin": true,
|
||||||
|
"~:can-edit": true
|
||||||
|
},
|
||||||
|
"~:name": "Default",
|
||||||
|
"~:modified-at": "~m1713533116375",
|
||||||
|
"~:id": "~uc7ce0794-0992-8105-8004-38e630f7920a",
|
||||||
|
"~:created-at": "~m1713533116375",
|
||||||
|
"~:is-default": true
|
||||||
|
}]
|
|
@ -211,60 +211,64 @@ export class DashboardPage extends BaseWebSocketPage {
|
||||||
|
|
||||||
async goToDashboard() {
|
async goToDashboard() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.anyTeamId}/projects`,
|
`#/dashboard/recent?team-id=${DashboardPage.anyTeamId}`,
|
||||||
);
|
);
|
||||||
await expect(this.mainHeading).toBeVisible();
|
await expect(this.mainHeading).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamDashboard() {
|
async goToSecondTeamDashboard() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/projects`,
|
`#/dashboard/recent?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamMembersSection() {
|
async goToSecondTeamMembersSection() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/members`,
|
`#/dashboard/members?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamInvitationsSection() {
|
async goToSecondTeamInvitationsSection() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/invitations`,
|
`#/dashboard/invitations?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamWebhooksSection() {
|
async goToSecondTeamWebhooksSection() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`,
|
`#/dashboard/webhooks?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamWebhooksSection() {
|
async goToSecondTeamWebhooksSection() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`,
|
`#/dashboard/webhooks?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecondTeamSettingsSection() {
|
async goToSecondTeamSettingsSection() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.secondTeamId}/settings`,
|
`#/dashboard/settings?team-id=${DashboardPage.secondTeamId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSearch() {
|
async goToSearch() {
|
||||||
await this.page.goto(`#/dashboard/team/${DashboardPage.anyTeamId}/search`);
|
await this.page.goto(
|
||||||
|
`#/dashboard/search?team-id=${DashboardPage.anyTeamId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToDrafts() {
|
async goToDrafts() {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`#/dashboard/team/${DashboardPage.anyTeamId}/projects/${DashboardPage.draftProjectId}`,
|
`#/dashboard/files?team-id=${DashboardPage.anyTeamId}&project-id=${DashboardPage.draftProjectId}`,
|
||||||
);
|
);
|
||||||
await expect(this.mainHeading).toHaveText("Drafts");
|
await expect(this.mainHeading).toHaveText("Drafts");
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToFonts() {
|
async goToFonts() {
|
||||||
await this.page.goto(`#/dashboard/team/${DashboardPage.anyTeamId}/fonts`);
|
await this.page.goto(
|
||||||
|
`#/dashboard/fonts?team-id=${DashboardPage.anyTeamId}`,
|
||||||
|
);
|
||||||
await expect(this.mainHeading).toHaveText("Fonts");
|
await expect(this.mainHeading).toHaveText("Fonts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ export class ViewerPage extends BaseWebSocketPage {
|
||||||
pageId = ViewerPage.anyPageId,
|
pageId = ViewerPage.anyPageId,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`/#/view/${fileId}?page-id=${pageId}§ion=interactions&index=0`,
|
`/#/view?file-id=${fileId}&page-id=${pageId}§ion=interactions&index=0`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.#ws = await this.waitForNotificationsWebSocket();
|
this.#ws = await this.waitForNotificationsWebSocket();
|
||||||
|
|
|
@ -36,6 +36,14 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||||
"get-team?id=*",
|
"get-team?id=*",
|
||||||
"workspace/get-team-default.json",
|
"workspace/get-team-default.json",
|
||||||
);
|
);
|
||||||
|
await BaseWebSocketPage.mockRPC(page, "get-teams", "get-teams.json");
|
||||||
|
|
||||||
|
await BaseWebSocketPage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-team-members?team-id=*",
|
||||||
|
"logged-in-user/get-team-members-your-penpot.json",
|
||||||
|
);
|
||||||
|
|
||||||
await BaseWebSocketPage.mockRPC(
|
await BaseWebSocketPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profiles-for-file-comments?file-id=*",
|
"get-profiles-for-file-comments?file-id=*",
|
||||||
|
@ -43,6 +51,7 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static anyTeamId = "c7ce0794-0992-8105-8004-38e630f7920a";
|
||||||
static anyProjectId = "c7ce0794-0992-8105-8004-38e630f7920b";
|
static anyProjectId = "c7ce0794-0992-8105-8004-38e630f7920b";
|
||||||
static anyFileId = "c7ce0794-0992-8105-8004-38f280443849";
|
static anyFileId = "c7ce0794-0992-8105-8004-38f280443849";
|
||||||
static anyPageId = "c7ce0794-0992-8105-8004-38f28044384a";
|
static anyPageId = "c7ce0794-0992-8105-8004-38f28044384a";
|
||||||
|
@ -83,7 +92,7 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||||
pageId = WorkspacePage.anyPageId,
|
pageId = WorkspacePage.anyPageId,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
await this.page.goto(
|
await this.page.goto(
|
||||||
`/#/workspace/${WorkspacePage.anyProjectId}/${fileId}?page-id=${pageId}`,
|
`/#/workspace?team-id=${WorkspacePage.anyTeamId}&file-id=${fileId}&page-id=${pageId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.#ws = await this.waitForNotificationsWebSocket();
|
this.#ws = await this.waitForNotificationsWebSocket();
|
||||||
|
|
|
@ -7,11 +7,7 @@ test.beforeEach(async ({ page }) => {
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
const workspacePage = new WorkspacePage(page);
|
||||||
await workspacePage.setupEmptyFile(page);
|
await workspacePage.setupEmptyFile(page);
|
||||||
await WorkspacePage.mockRPC(
|
await WorkspacePage.mockRPC(page, "get-teams", "get-teams-role-viewer.json");
|
||||||
page,
|
|
||||||
"get-team?id=*",
|
|
||||||
"workspace/get-team-role-viewer.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await workspacePage.goToWorkspace();
|
await workspacePage.goToWorkspace();
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,14 +12,15 @@
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.profile :as dp]
|
[app.main.data.profile :as dp]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
[app.main.data.websocket :as ws]
|
[app.main.data.websocket :as ws]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
@ -45,8 +46,9 @@
|
||||||
(rx/of (rt/reload true))
|
(rx/of (rt/reload true))
|
||||||
(rx/of (rt/nav-raw :href redirect-href))))
|
(rx/of (rt/nav-raw :href redirect-href))))
|
||||||
(if-let [file-id (get props :welcome-file-id)]
|
(if-let [file-id (get props :welcome-file-id)]
|
||||||
(rx/of (rt/nav' :workspace {:project-id (:default-project-id profile)
|
(rx/of (dcm/go-to-workspace
|
||||||
:file-id file-id})
|
:file-id file-id
|
||||||
|
:team-id (:default-team-id profile))
|
||||||
(dp/update-profile-props {:welcome-file-id nil}))
|
(dp/update-profile-props {:welcome-file-id nil}))
|
||||||
|
|
||||||
(let [teams (into #{} (map :id) teams)
|
(let [teams (into #{} (map :id) teams)
|
||||||
|
@ -54,7 +56,7 @@
|
||||||
team-id (if (and team-id (contains? teams team-id))
|
team-id (if (and team-id (contains? teams team-id))
|
||||||
team-id
|
team-id
|
||||||
(:default-team-id profile))]
|
(:default-team-id profile))]
|
||||||
(rx/of (rt/nav' :dashboard-projects {:team-id team-id}))))))]
|
(rx/of (dcm/go-to-dashboard-recent {:team-id team-id}))))))]
|
||||||
|
|
||||||
(ptk/reify ::logged-in
|
(ptk/reify ::logged-in
|
||||||
ev/Event
|
ev/Event
|
||||||
|
|
|
@ -603,3 +603,18 @@
|
||||||
(filter (fn [comment] (some #(= % (:frame-id comment)) frame-ids?)))
|
(filter (fn [comment] (some #(= % (:frame-id comment)) frame-ids?)))
|
||||||
(map update-comment-thread-frame)
|
(map update-comment-thread-frame)
|
||||||
(rx/from))))))
|
(rx/from))))))
|
||||||
|
|
||||||
|
(defn fetch-profiles
|
||||||
|
"Fetch or refresh all profile data for comments of the current file"
|
||||||
|
[]
|
||||||
|
(ptk/reify ::fetch-comments-profiles
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [file-id (:current-file-id state)
|
||||||
|
share-id (or (-> state :viewer-local :share-id)
|
||||||
|
(:current-share-id state))]
|
||||||
|
(->> (rp/cmd! :get-profiles-for-file-comments {:file-id file-id :share-id share-id})
|
||||||
|
(rx/map (fn [profiles]
|
||||||
|
#(update % :profiles merge (d/index-by :id profiles)))))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,18 @@
|
||||||
[app.common.types.team :as ctt]
|
[app.common.types.team :as ctt]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
[app.main.data.persistence :as-alias dps]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
[app.util.dom :as-alias dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
(declare go-to-dashboard-recent)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; SHARE LINK
|
;; SHARE LINK
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -233,12 +237,165 @@
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(when (= :removed change)
|
(when (= :removed change)
|
||||||
(let [message (tr "dashboard.removed-from-team" team-name)
|
(let [message (tr "dashboard.removed-from-team" team-name)
|
||||||
profile (:profile state)]
|
team-id (-> state :profile :default-team-id)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (rt/nav :dashboard-projects {:team-id (:default-team-id profile)}))
|
(rx/of (go-to-dashboard-recent :team-id team-id))
|
||||||
(->> (rx/of (ntf/info message))
|
(->> (rx/of (ntf/info message))
|
||||||
;; Delay so the navigation can finish
|
;; Delay so the navigation can finish
|
||||||
(rx/delay 250))))))))
|
(rx/delay 250))))))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; NAVEGATION EVENTS
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn go-to-feedback
|
||||||
|
[]
|
||||||
|
(ptk/reify ::go-to-feedback
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/of (rt/nav :settings-feedback {}
|
||||||
|
::rt/new-window true
|
||||||
|
::rt/window-name "penpot-feedback")))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-files
|
||||||
|
[& {:keys [project-id team-id] :as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-files
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [profile (get state :profile)
|
||||||
|
team-id (or team-id (:current-team-id state))
|
||||||
|
project-id (if (= project-id :default)
|
||||||
|
(:default-project-id profile)
|
||||||
|
project-id)
|
||||||
|
|
||||||
|
params {:team-id team-id
|
||||||
|
:project-id project-id}]
|
||||||
|
(rx/of (rt/nav :dashboard-files params options))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-search
|
||||||
|
[& {:keys [term] :as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-search
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(rx/merge
|
||||||
|
(->> (rx/of (rt/nav :dashboard-search
|
||||||
|
{:team-id team-id
|
||||||
|
:search-term term})
|
||||||
|
(modal/hide))
|
||||||
|
(rx/observe-on :async))
|
||||||
|
|
||||||
|
(->> stream
|
||||||
|
(rx/filter (ptk/type? ::rt/navigated))
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map (fn [_]
|
||||||
|
(ptk/event ::dom/focus-element
|
||||||
|
{:name "search-input"})))))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-libraries
|
||||||
|
[& {:keys [team-id] :as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-libraries
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (or team-id (:current-team-id state))]
|
||||||
|
(rx/of (rt/nav :dashboard-libraries {:team-id team-id}))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn go-to-dashboard-fonts
|
||||||
|
[& {:keys [team-id] :as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-fonts
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (or team-id (:current-team-id state))]
|
||||||
|
(rx/of (rt/nav :dashboard-libraries {:team-id team-id}))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-recent
|
||||||
|
[& {:keys [team-id] :as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-recent
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [profile (get state :profile)
|
||||||
|
team-id (cond
|
||||||
|
(= :default team-id)
|
||||||
|
(:default-team-id profile)
|
||||||
|
|
||||||
|
(uuid? team-id)
|
||||||
|
team-id
|
||||||
|
|
||||||
|
:else
|
||||||
|
(:current-team-id state))
|
||||||
|
params {:team-id team-id}]
|
||||||
|
(rx/of (modal/hide)
|
||||||
|
(rt/nav :dashboard-recent params options))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-members
|
||||||
|
[& {:as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-members
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(rx/of (rt/nav :dashboard-members {:team-id team-id}))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-invitations
|
||||||
|
[& {:as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-invitations
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(rx/of (rt/nav :dashboard-invitations {:team-id team-id}))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-webhooks
|
||||||
|
[& {:as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-webhooks
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(rx/of (rt/nav :dashboard-webhooks {:team-id team-id}))))))
|
||||||
|
|
||||||
|
(defn go-to-dashboard-settings
|
||||||
|
[& {:as options}]
|
||||||
|
(ptk/reify ::go-to-dashboard-settings
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(rx/of (rt/nav :dashboard-settings {:team-id team-id}))))))
|
||||||
|
|
||||||
|
(defn go-to-workspace
|
||||||
|
[& {:keys [team-id file-id page-id layout] :as options}]
|
||||||
|
(ptk/reify ::go-to-workspace
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (or team-id (:current-team-id state))
|
||||||
|
file-id (or file-id (:current-file-id state))
|
||||||
|
;: FIXME: why not :current-page-id
|
||||||
|
page-id (or page-id
|
||||||
|
(dm/get-in state [:workspace-data :pages 0]))
|
||||||
|
params (-> (rt/get-params state)
|
||||||
|
(assoc :team-id team-id)
|
||||||
|
(assoc :file-id file-id)
|
||||||
|
(assoc :page-id page-id)
|
||||||
|
(assoc :layout layout)
|
||||||
|
(d/without-nils))]
|
||||||
|
(rx/of (rt/nav :workspace params options))))))
|
||||||
|
|
||||||
|
(defn go-to-viewer
|
||||||
|
[& {:keys [file-id page-id section frame-id index] :as options}]
|
||||||
|
(ptk/reify ::go-to-viewer
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [page-id (or page-id (:current-page-id state))
|
||||||
|
file-id (or file-id (:current-file-id state))
|
||||||
|
section (or section :interactions)
|
||||||
|
params {:file-id file-id
|
||||||
|
:page-id page-id
|
||||||
|
:section section
|
||||||
|
:frame-id frame-id
|
||||||
|
:index index}
|
||||||
|
params (d/without-nils params)
|
||||||
|
name (dm/str "viewer-" file-id)
|
||||||
|
options (merge {::rt/new-window true
|
||||||
|
::rt/window-name name}
|
||||||
|
options)]
|
||||||
|
(rx/of ::dps/force-persist
|
||||||
|
(rt/nav :viewer params options))))))
|
||||||
|
|
||||||
|
|
|
@ -13,18 +13,15 @@
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.common :as dc]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.fonts :as df]
|
[app.main.data.fonts :as df]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.websocket :as dws]
|
[app.main.data.websocket :as dws]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.dom :as dom]
|
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.sse :as sse]
|
[app.util.sse :as sse]
|
||||||
[app.util.storage :as storage]
|
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
|
@ -115,55 +112,6 @@
|
||||||
(rx/map (fn [result]
|
(rx/map (fn [result]
|
||||||
#(assoc % :search-result result)))))))))
|
#(assoc % :search-result result)))))))))
|
||||||
|
|
||||||
;; --- EVENT: files
|
|
||||||
|
|
||||||
(defn files-fetched
|
|
||||||
[project-id files]
|
|
||||||
(letfn [(remove-project-files [files]
|
|
||||||
(reduce-kv (fn [result id file]
|
|
||||||
(cond-> result
|
|
||||||
(= (:project-id file) project-id) (dissoc id)))
|
|
||||||
files
|
|
||||||
files))]
|
|
||||||
(ptk/reify ::files-fetched
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(-> state
|
|
||||||
(update :files
|
|
||||||
(fn [files']
|
|
||||||
(reduce #(assoc %1 (:id %2) %2)
|
|
||||||
(remove-project-files files')
|
|
||||||
files)))
|
|
||||||
(assoc-in [:projects project-id :count] (count files)))))))
|
|
||||||
|
|
||||||
(defn fetch-files
|
|
||||||
[{:keys [project-id] :as params}]
|
|
||||||
(dm/assert! (uuid? project-id))
|
|
||||||
(ptk/reify ::fetch-files
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
(->> (rp/cmd! :get-project-files {:project-id project-id})
|
|
||||||
(rx/map #(files-fetched project-id %))))))
|
|
||||||
|
|
||||||
;; --- EVENT: shared-files
|
|
||||||
|
|
||||||
(defn shared-files-fetched
|
|
||||||
[files]
|
|
||||||
(ptk/reify ::shared-files-fetched
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [files (d/index-by :id files)]
|
|
||||||
(assoc state :shared-files files)))))
|
|
||||||
|
|
||||||
(defn fetch-shared-files
|
|
||||||
[]
|
|
||||||
(ptk/reify ::fetch-shared-files
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
|
||||||
(rx/map shared-files-fetched))))))
|
|
||||||
|
|
||||||
;; --- EVENT: recent-files
|
;; --- EVENT: recent-files
|
||||||
|
|
||||||
(defn recent-files-fetched
|
(defn recent-files-fetched
|
||||||
|
@ -630,133 +578,6 @@
|
||||||
(rx/tap on-success)
|
(rx/tap on-success)
|
||||||
(rx/catch on-error))))))
|
(rx/catch on-error))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Navigation
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(defn go-to-workspace
|
|
||||||
[{:keys [id project-id] :as file}]
|
|
||||||
(ptk/reify ::go-to-workspace
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
(let [pparams {:project-id project-id :file-id id}]
|
|
||||||
(rx/of (rt/nav :workspace pparams))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn go-to-files
|
|
||||||
([project-id] (go-to-files project-id nil))
|
|
||||||
([project-id team-id]
|
|
||||||
(ptk/reify ::go-to-files
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (or team-id (:current-team-id state))]
|
|
||||||
(rx/of (rt/nav :dashboard-files {:team-id team-id
|
|
||||||
:project-id project-id})))))))
|
|
||||||
|
|
||||||
(defn go-to-search
|
|
||||||
([] (go-to-search nil))
|
|
||||||
([term]
|
|
||||||
(ptk/reify ::go-to-search
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(if (empty? term)
|
|
||||||
(do
|
|
||||||
(dom/focus! (dom/get-element "search-input"))
|
|
||||||
(rx/of (rt/nav :dashboard-search
|
|
||||||
{:team-id team-id})))
|
|
||||||
(rx/of (rt/nav :dashboard-search
|
|
||||||
{:team-id team-id}
|
|
||||||
{:search-term term})))))
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
|
||||||
(effect [_ _ _]
|
|
||||||
(dom/focus! (dom/get-element "search-input"))))))
|
|
||||||
|
|
||||||
(defn go-to-projects
|
|
||||||
[team-id]
|
|
||||||
(ptk/reify ::go-to-projects
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (or team-id (:current-team-id state))]
|
|
||||||
(rx/of (rt/nav :dashboard-projects {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn go-to-default-team
|
|
||||||
"High-level component for redirect to the current profile default
|
|
||||||
team and hide all modals"
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-default-team
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (dm/get-in state [:profile :default-team-id])]
|
|
||||||
(rx/of (go-to-projects team-id)
|
|
||||||
(modal/hide))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn go-to-current-team
|
|
||||||
"High-level component for redirect to the current profile default
|
|
||||||
team and hide all modals"
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-current-team
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (or (::current-team-id storage/user)
|
|
||||||
(dm/get-in state [:profile :default-team-id]))]
|
|
||||||
(rx/of (go-to-projects team-id)
|
|
||||||
(modal/hide))))))
|
|
||||||
|
|
||||||
(defn go-to-team-members
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-team-members
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of (rt/nav :dashboard-team-members {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn go-to-team-invitations
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-team-invitations
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of (rt/nav :dashboard-team-invitations {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn go-to-team-webhooks
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-team-webhooks
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of (rt/nav :dashboard-team-webhooks {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn go-to-team-settings
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-team-settings
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of (rt/nav :dashboard-team-settings {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn go-to-drafts
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-drafts
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)
|
|
||||||
projects (:projects state)
|
|
||||||
default-project (d/seek :is-default (vals projects))]
|
|
||||||
(when default-project
|
|
||||||
(rx/of (rt/nav :dashboard-files {:team-id team-id
|
|
||||||
:project-id (:id default-project)})))))))
|
|
||||||
|
|
||||||
(defn go-to-libs
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-libs
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of (rt/nav :dashboard-libraries {:team-id team-id}))))))
|
|
||||||
|
|
||||||
(defn create-element
|
(defn create-element
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::create-element
|
(ptk/reify ::create-element
|
||||||
|
@ -793,8 +614,7 @@
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [[file-id :as files] (get state :selected-files)]
|
(let [[file-id :as files] (get state :selected-files)]
|
||||||
(if (= 1 (count files))
|
(if (= 1 (count files))
|
||||||
(let [file (dm/get-in state [files file-id])]
|
(rx/of (dcm/go-to-workspace :file-id file-id))
|
||||||
(rx/of (go-to-workspace file)))
|
|
||||||
(rx/empty))))))
|
(rx/empty))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -806,13 +626,13 @@
|
||||||
(ptk/reify ::handle-change-team-role
|
(ptk/reify ::handle-change-team-role
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/of (dc/change-team-role params)
|
(rx/of (dcm/change-team-role params)
|
||||||
(modal/hide)))))
|
(modal/hide)))))
|
||||||
|
|
||||||
(defn- process-message
|
(defn- process-message
|
||||||
[{:keys [type] :as msg}]
|
[{:keys [type] :as msg}]
|
||||||
(case type
|
(case type
|
||||||
:notification (dc/handle-notification msg)
|
:notification (dcm/handle-notification msg)
|
||||||
:team-role-change (handle-change-team-role msg)
|
:team-role-change (handle-change-team-role msg)
|
||||||
:team-membership-change (dc/team-membership-change msg)
|
:team-membership-change (dcm/team-membership-change msg)
|
||||||
nil))
|
nil))
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.data.dashboard.shortcuts
|
(ns app.main.data.dashboard.shortcuts
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
|
@ -16,17 +17,17 @@
|
||||||
{:go-to-search {:tooltip (ds/meta "F")
|
{:go-to-search {:tooltip (ds/meta "F")
|
||||||
:command (ds/c-mod "f")
|
:command (ds/c-mod "f")
|
||||||
:subsections [:navigation-dashboard]
|
:subsections [:navigation-dashboard]
|
||||||
:fn #(st/emit! (dd/go-to-search))}
|
:fn #(st/emit! (dcm/go-to-dashboard-search))}
|
||||||
|
|
||||||
:go-to-drafts {:tooltip "G D"
|
:go-to-drafts {:tooltip "G D"
|
||||||
:command "g d"
|
:command "g d"
|
||||||
:subsections [:navigation-dashboard]
|
:subsections [:navigation-dashboard]
|
||||||
:fn #(st/emit! (dd/go-to-drafts))}
|
:fn #(st/emit! (dcm/go-to-dashboard-files :project-id :default))}
|
||||||
|
|
||||||
:go-to-libs {:tooltip "G L"
|
:go-to-libs {:tooltip "G L"
|
||||||
:command "g l"
|
:command "g l"
|
||||||
:subsections [:navigation-dashboard]
|
:subsections [:navigation-dashboard]
|
||||||
:fn #(st/emit! (dd/go-to-libs))}
|
:fn #(st/emit! (dcm/go-to-dashboard-libraries))}
|
||||||
|
|
||||||
:create-new-project {:tooltip "+"
|
:create-new-project {:tooltip "+"
|
||||||
:command "+"
|
:command "+"
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(let [stopper (rx/filter (ptk/type? ::hide) stream)]
|
(let [stopper (rx/filter (ptk/type? ::hide) stream)]
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? :app.util.router/navigate))
|
(rx/filter (ptk/type? :app.main.router/navigate))
|
||||||
(rx/map (fn [_] (hide)))
|
(rx/map (fn [_] (hide)))
|
||||||
(rx/take-until stopper)))
|
(rx/take-until stopper)))
|
||||||
(when (:timeout data)
|
(when (:timeout data)
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
[app.main.data.media :as di]
|
[app.main.data.media :as di]
|
||||||
[app.main.data.team :as-alias dtm]
|
[app.main.data.team :as-alias dtm]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.plugins.register :as plugins.register]
|
[app.plugins.register :as plugins.register]
|
||||||
[app.util.i18n :as i18n]
|
[app.util.i18n :as i18n]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
80
frontend/src/app/main/data/project.cljs
Normal file
80
frontend/src/app/main/data/project.cljs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
;; 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
|
||||||
|
|
||||||
|
(ns app.main.data.project
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.logging :as log]
|
||||||
|
[app.main.repo :as rp]
|
||||||
|
[beicon.v2.core :as rx]
|
||||||
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
(log/set-level! :warn)
|
||||||
|
|
||||||
|
(defn- project-fetched
|
||||||
|
[{:keys [id] :as project}]
|
||||||
|
(ptk/reify ::project-fetched
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:projects id] merge project))))
|
||||||
|
|
||||||
|
(defn fetch-project
|
||||||
|
"Fetch or refresh a single project"
|
||||||
|
([] (fetch-project))
|
||||||
|
([project-id]
|
||||||
|
(assert (uuid? project-id) "expected a valid uuid for `project-id`")
|
||||||
|
|
||||||
|
(ptk/reify ::fetch-project
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [project-id (or project-id (:current-project-id state))]
|
||||||
|
(->> (rp/cmd! :get-project {:id project-id})
|
||||||
|
(rx/map project-fetched)))))))
|
||||||
|
|
||||||
|
(defn initialize-project
|
||||||
|
[project-id]
|
||||||
|
(ptk/reify ::initialize-project
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc state :current-project-id project-id))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/of (fetch-project project-id)))))
|
||||||
|
|
||||||
|
(defn finalize-project
|
||||||
|
[project-id]
|
||||||
|
(ptk/reify ::finalize-project
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [project-id' (get state :current-project-id)]
|
||||||
|
(if (= project-id' project-id)
|
||||||
|
(dissoc state :current-project-id)
|
||||||
|
state)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn- files-fetched
|
||||||
|
[project-id files]
|
||||||
|
(ptk/reify ::files-fetched
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(-> state
|
||||||
|
(update :files merge (d/index-by :id files))
|
||||||
|
(d/update-in-when [:projects project-id] (fn [project]
|
||||||
|
(assoc project :count (count files))))))))
|
||||||
|
|
||||||
|
(defn fetch-files
|
||||||
|
[project-id]
|
||||||
|
(assert (uuid? project-id) "expected valid uuid for `project-id`")
|
||||||
|
(ptk/reify ::fetch-files
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(->> (rp/cmd! :get-project-files {:project-id project-id})
|
||||||
|
(rx/map (partial files-fetched project-id))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.data.team
|
(ns app.main.data.team
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
@ -16,7 +17,7 @@
|
||||||
[app.main.data.media :as di]
|
[app.main.data.media :as di]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.router :as rt]
|
[app.main.router :as rt]
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
|
@ -57,7 +58,9 @@
|
||||||
(ptk/reify ::members-fetched
|
(ptk/reify ::members-fetched
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update-in state [:teams team-id] assoc :members members))))
|
(-> state
|
||||||
|
(update-in [:teams team-id] assoc :members members)
|
||||||
|
(update :profiles merge (d/index-by :id members))))))
|
||||||
|
|
||||||
(defn fetch-members
|
(defn fetch-members
|
||||||
[]
|
[]
|
||||||
|
@ -145,6 +148,7 @@
|
||||||
(if (= team-id' team-id)
|
(if (= team-id' team-id)
|
||||||
(-> state
|
(-> state
|
||||||
(dissoc :current-team-id)
|
(dissoc :current-team-id)
|
||||||
|
(dissoc :shared-files)
|
||||||
(dissoc :fonts))
|
(dissoc :fonts))
|
||||||
state)))))
|
state)))))
|
||||||
|
|
||||||
|
@ -220,6 +224,26 @@
|
||||||
(->> (rp/cmd! :get-webhooks {:team-id team-id})
|
(->> (rp/cmd! :get-webhooks {:team-id team-id})
|
||||||
(rx/map (partial webhooks-fetched team-id)))))))
|
(rx/map (partial webhooks-fetched team-id)))))))
|
||||||
|
|
||||||
|
(defn- shared-files-fetched
|
||||||
|
[files]
|
||||||
|
(ptk/reify ::shared-files-fetched
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [files (d/index-by :id files)]
|
||||||
|
(assoc state :shared-files files)))))
|
||||||
|
|
||||||
|
(defn fetch-shared-files
|
||||||
|
"Event mainly used for fetch a list of shared libraries for a team,
|
||||||
|
this list does not includes the content of the library per se. It
|
||||||
|
is used mainly for show available libraries and a summary of it."
|
||||||
|
[]
|
||||||
|
(ptk/reify ::fetch-shared-files
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)]
|
||||||
|
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||||
|
(rx/map shared-files-fetched))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Data Modification
|
;; Data Modification
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -334,7 +358,7 @@
|
||||||
(when reassign-to
|
(when reassign-to
|
||||||
(assert (uuid? reassign-to) "expect a valid uuid for `reassign-to`"))
|
(assert (uuid? reassign-to) "expect a valid uuid for `reassign-to`"))
|
||||||
|
|
||||||
(ptk/reify ::leave-team
|
(ptk/reify ::leave-current-team
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [team-id (get state :current-team-id)
|
(let [team-id (get state :current-team-id)
|
||||||
|
@ -405,7 +429,7 @@
|
||||||
|
|
||||||
(->> (rp/cmd! :get-team-invitation-token params)
|
(->> (rp/cmd! :get-team-invitation-token params)
|
||||||
(rx/map (fn [params]
|
(rx/map (fn [params]
|
||||||
(rt/resolve router :auth-verify-token {} params)))
|
(rt/resolve router :auth-verify-token params)))
|
||||||
(rx/map (fn [fragment]
|
(rx/map (fn [fragment]
|
||||||
(assoc cf/public-uri :fragment fragment)))
|
(assoc cf/public-uri :fragment fragment)))
|
||||||
(rx/tap (fn [uri]
|
(rx/tap (fn [uri]
|
||||||
|
@ -532,3 +556,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
[app.main.data.comments :as dcm]
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.comments :as dcmt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.fonts :as df]
|
[app.main.data.fonts :as df]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.util.globals :as ug]
|
[app.util.globals :as ug]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
@ -32,7 +34,7 @@
|
||||||
{:zoom 1
|
{:zoom 1
|
||||||
:fullscreen? false
|
:fullscreen? false
|
||||||
:interactions-mode :show-on-click
|
:interactions-mode :show-on-click
|
||||||
:interactions-show? false
|
:show-interactions false
|
||||||
:comments-mode :all
|
:comments-mode :all
|
||||||
:comments-show :unresolved
|
:comments-show :unresolved
|
||||||
:selected #{}
|
:selected #{}
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
[:page-id {:optional true} ::sm/uuid]])
|
[:page-id {:optional true} ::sm/uuid]])
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
[{:keys [file-id share-id interactions-show?] :as params}]
|
[{:keys [file-id share-id] :as params}]
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid params"
|
"expected valid params"
|
||||||
(sm/check schema:initialize params))
|
(sm/check schema:initialize params))
|
||||||
|
@ -65,13 +67,13 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(-> state
|
||||||
(assoc :current-file-id file-id)
|
(assoc :current-file-id file-id)
|
||||||
|
(assoc :current-share-id share-id)
|
||||||
(update :viewer-local
|
(update :viewer-local
|
||||||
(fn [lstate]
|
(fn [lstate]
|
||||||
(if (nil? lstate)
|
(if (nil? lstate)
|
||||||
default-local-state
|
default-local-state
|
||||||
lstate)))
|
lstate)))
|
||||||
(assoc-in [:viewer-local :share-id] share-id)
|
(assoc-in [:viewer-local :share-id] share-id)))
|
||||||
(assoc-in [:viewer-local :interactions-show?] interactions-show?)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
|
@ -256,12 +258,9 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [zoom-type (get-in state [:viewer-local :zoom-type])
|
(let [zoom-type (get-in state [:viewer-local :zoom-type])
|
||||||
route (:route state)
|
params (rt/get-params state)]
|
||||||
screen (-> route :data :name keyword)
|
|
||||||
qparams (:query-params route)
|
|
||||||
pparams (:path-params route)]
|
|
||||||
|
|
||||||
(rx/of (rt/nav screen pparams (assoc qparams :zoom zoom-type)))))))
|
(rx/of (rt/nav :viewer (assoc params :zoom zoom-type)))))))
|
||||||
|
|
||||||
(def increase-zoom
|
(def increase-zoom
|
||||||
(ptk/reify ::increase-zoom
|
(ptk/reify ::increase-zoom
|
||||||
|
@ -293,13 +292,16 @@
|
||||||
(ptk/reify ::zoom-to-fit
|
(ptk/reify ::zoom-to-fit
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [srect (as-> (get-in state [:route :query-params :page-id]) %
|
(let [params (rt/get-params state)
|
||||||
(get-in state [:viewer :pages % :frames])
|
page-id (some-> (:page-id params) uuid/parse)
|
||||||
(nth % (get-in state [:route :query-params :index]))
|
index (some-> (:index params) parse-long)
|
||||||
(get % :selrect))
|
|
||||||
orig-size (get-in state [:viewer-local :viewport-size])
|
frames (dm/get-in state [:viewer :pages page-id :frames])
|
||||||
wdiff (/ (:width orig-size) (:width srect))
|
srect (-> (nth frames index)
|
||||||
hdiff (/ (:height orig-size) (:height srect))
|
(get :selrect))
|
||||||
|
osize (dm/get-in state [:viewer-local :viewport-size])
|
||||||
|
wdiff (/ (:width osize) (:width srect))
|
||||||
|
hdiff (/ (:height osize) (:height srect))
|
||||||
minzoom (min wdiff hdiff)]
|
minzoom (min wdiff hdiff)]
|
||||||
(-> state
|
(-> state
|
||||||
(assoc-in [:viewer-local :zoom] minzoom)
|
(assoc-in [:viewer-local :zoom] minzoom)
|
||||||
|
@ -312,17 +314,25 @@
|
||||||
(ptk/reify ::zoom-to-fill
|
(ptk/reify ::zoom-to-fill
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [srect (as-> (get-in state [:route :query-params :page-id]) %
|
|
||||||
(get-in state [:viewer :pages % :frames])
|
(let [params (rt/get-params state)
|
||||||
(nth % (get-in state [:route :query-params :index]))
|
page-id (some-> (:page-id params) uuid/parse)
|
||||||
(get % :selrect))
|
index (some-> (:index params) parse-long)
|
||||||
orig-size (get-in state [:viewer-local :viewport-size])
|
|
||||||
wdiff (/ (:width orig-size) (:width srect))
|
frames (dm/get-in state [:viewer :pages page-id :frames])
|
||||||
hdiff (/ (:height orig-size) (:height srect))
|
srect (-> (nth frames index)
|
||||||
|
(get :selrect))
|
||||||
|
|
||||||
|
osize (dm/get-in state [:viewer-local :viewport-size])
|
||||||
|
|
||||||
|
wdiff (/ (:width osize) (:width srect))
|
||||||
|
hdiff (/ (:height osize) (:height srect))
|
||||||
|
|
||||||
maxzoom (max wdiff hdiff)]
|
maxzoom (max wdiff hdiff)]
|
||||||
(-> state
|
(-> state
|
||||||
(assoc-in [:viewer-local :zoom] maxzoom)
|
(assoc-in [:viewer-local :zoom] maxzoom)
|
||||||
(assoc-in [:viewer-local :zoom-type] :fill))))
|
(assoc-in [:viewer-local :zoom-type] :fill))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _] (rx/of update-zoom-querystring))))
|
(watch [_ _ _] (rx/of update-zoom-querystring))))
|
||||||
|
|
||||||
|
@ -376,16 +386,15 @@
|
||||||
(-> state
|
(-> state
|
||||||
(dissoc :viewer-animations)
|
(dissoc :viewer-animations)
|
||||||
(assoc :viewer-overlays [])))
|
(assoc :viewer-overlays [])))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)
|
||||||
qparams (:query-params route)
|
index (some-> params :index parse-long)]
|
||||||
pparams (:path-params route)
|
|
||||||
index (:index qparams)]
|
|
||||||
(when (pos? index)
|
(when (pos? index)
|
||||||
(rx/of
|
(rx/of
|
||||||
(dcm/close-thread)
|
(dcmt/close-thread)
|
||||||
(rt/nav :viewer pparams (assoc qparams :index (dec index)))))))))
|
(rt/nav :viewer (assoc params :index (dec index)))))))))
|
||||||
|
|
||||||
(def select-next-frame
|
(def select-next-frame
|
||||||
(ptk/reify ::select-next-frame
|
(ptk/reify ::select-next-frame
|
||||||
|
@ -396,30 +405,25 @@
|
||||||
(assoc :viewer-overlays [])))
|
(assoc :viewer-overlays [])))
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)
|
||||||
pparams (:path-params route)
|
index (some-> params :index parse-long)
|
||||||
qparams (:query-params route)
|
page-id (some-> params :page-id parse-uuid)
|
||||||
|
|
||||||
page-id (:page-id qparams)
|
|
||||||
index (:index qparams)
|
|
||||||
|
|
||||||
total (count (get-in state [:viewer :pages page-id :frames]))]
|
total (count (get-in state [:viewer :pages page-id :frames]))]
|
||||||
|
|
||||||
(when (< index (dec total))
|
(when (< index (dec total))
|
||||||
(rx/of
|
(rx/of
|
||||||
(dcm/close-thread)
|
(dcmt/close-thread)
|
||||||
(rt/nav :viewer pparams (assoc qparams :index (inc index)))))))))
|
(rt/nav :viewer params (assoc params :index (inc index)))))))))
|
||||||
|
|
||||||
(def select-first-frame
|
(def select-first-frame
|
||||||
(ptk/reify ::select-first-frame
|
(ptk/reify ::select-first-frame
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)]
|
||||||
qparams (:query-params route)
|
|
||||||
pparams (:path-params route)]
|
|
||||||
(rx/of
|
(rx/of
|
||||||
(dcm/close-thread)
|
(dcmt/close-thread)
|
||||||
(rt/nav :viewer pparams (assoc qparams :index 0)))))))
|
(rt/nav :viewer (assoc params :index 0)))))))
|
||||||
|
|
||||||
(def valid-interaction-modes
|
(def valid-interaction-modes
|
||||||
#{:hide :show :show-on-click})
|
#{:hide :show :show-on-click})
|
||||||
|
@ -434,17 +438,14 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(-> state
|
||||||
(assoc-in [:viewer-local :interactions-mode] mode)
|
(assoc-in [:viewer-local :interactions-mode] mode)
|
||||||
(assoc-in [:viewer-local :interactions-show?] (case mode
|
(assoc-in [:viewer-local :show-interactions] (case mode
|
||||||
:hide false
|
:hide false
|
||||||
:show true
|
:show true
|
||||||
:show-on-click false))))
|
:show-on-click false))))
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)]
|
||||||
screen (-> route :data :name keyword)
|
(rx/of (rt/nav :viewer (assoc params :interactions-mode mode)))))))
|
||||||
qparams (:query-params route)
|
|
||||||
pparams (:path-params route)]
|
|
||||||
(rx/of (rt/nav screen pparams (assoc qparams :interactions-mode mode)))))))
|
|
||||||
|
|
||||||
(declare flash-done)
|
(declare flash-done)
|
||||||
|
|
||||||
|
@ -453,7 +454,7 @@
|
||||||
(ptk/reify ::flash-interactions
|
(ptk/reify ::flash-interactions
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:viewer-local :interactions-show?] true))
|
(assoc-in state [:viewer-local :show-interactions] true))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ stream]
|
(watch [_ _ stream]
|
||||||
|
@ -466,7 +467,7 @@
|
||||||
(ptk/reify ::flash-done
|
(ptk/reify ::flash-done
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:viewer-local :interactions-show?] false))))
|
(assoc-in state [:viewer-local :show-interactions] false))))
|
||||||
|
|
||||||
(defn set-nav-scroll
|
(defn set-nav-scroll
|
||||||
[scroll]
|
[scroll]
|
||||||
|
@ -500,11 +501,8 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)]
|
||||||
screen (-> route :data :name keyword)
|
(rx/of (rt/nav :viewer (assoc params :index index)))))))
|
||||||
qparams (:query-params route)
|
|
||||||
pparams (:path-params route)]
|
|
||||||
(rx/of (rt/nav screen pparams (assoc qparams :index index)))))))
|
|
||||||
|
|
||||||
(defn go-to-frame
|
(defn go-to-frame
|
||||||
([frame-id]
|
([frame-id]
|
||||||
|
@ -573,10 +571,8 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)]
|
||||||
pparams (:path-params route)
|
(rx/of (rt/nav :viewer (assoc params :section section)))))))
|
||||||
qparams (:query-params route)]
|
|
||||||
(rx/of (rt/nav :viewer pparams (assoc qparams :section section)))))))
|
|
||||||
|
|
||||||
;; --- Overlays
|
;; --- Overlays
|
||||||
|
|
||||||
|
@ -771,9 +767,8 @@
|
||||||
(ptk/reify ::go-to-dashboard
|
(ptk/reify ::go-to-dashboard
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [team-id (get-in state [:viewer :project :team-id])
|
(let [team-id (get-in state [:viewer :project :team-id])]
|
||||||
params {:team-id team-id}]
|
(rx/of (dcm/go-to-dashboard-recent :team-id team-id))))))
|
||||||
(rx/of (rt/nav :dashboard-projects params))))))
|
|
||||||
|
|
||||||
(defn go-to-page
|
(defn go-to-page
|
||||||
[page-id]
|
[page-id]
|
||||||
|
@ -784,13 +779,10 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (-> (rt/get-params state)
|
||||||
pparams (:path-params route)
|
|
||||||
qparams (-> (:query-params route)
|
|
||||||
(assoc :index 0)
|
(assoc :index 0)
|
||||||
(assoc :page-id page-id))
|
(assoc :page-id page-id))]
|
||||||
rname (get-in route [:data :name])]
|
(rx/of (rt/nav :viewer params))))))
|
||||||
(rx/of (rt/nav rname pparams qparams))))))
|
|
||||||
|
|
||||||
(defn go-to-workspace
|
(defn go-to-workspace
|
||||||
([] (go-to-workspace nil))
|
([] (go-to-workspace nil))
|
||||||
|
@ -798,14 +790,16 @@
|
||||||
(ptk/reify ::go-to-workspace
|
(ptk/reify ::go-to-workspace
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [route (:route state)
|
(let [params (rt/get-params state)
|
||||||
project-id (get-in state [:viewer :project :id])
|
|
||||||
file-id (get-in state [:viewer :file :id])
|
file-id (get-in state [:viewer :file :id])
|
||||||
saved-page-id (get-in route [:query-params :page-id])
|
team-id (get-in state [:viewer :project :team-id])
|
||||||
pparams {:project-id project-id :file-id file-id}
|
page-id (or page-id
|
||||||
qparams {:page-id (or page-id saved-page-id)}]
|
(some-> (:page-id params) uuid/parse))
|
||||||
(rx/of (rt/nav-new-window*
|
params {:page-id page-id
|
||||||
{:rname :workspace
|
:file-id file-id
|
||||||
:path-params pparams
|
:team-id team-id}
|
||||||
:query-params qparams
|
name (dm/str "workspace-" file-id)]
|
||||||
:name (str "workspace-" file-id)})))))))
|
|
||||||
|
(rx/of (rt/nav :workspace params
|
||||||
|
::rt/new-window true
|
||||||
|
::rt/window-name name)))))))
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.data.viewer.shortcuts
|
(ns app.main.data.viewer.shortcuts
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.shortcuts :as ds]
|
[app.main.data.shortcuts :as ds]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.store :as st]))
|
[app.main.store :as st]))
|
||||||
|
@ -69,7 +70,7 @@
|
||||||
:open-workspace {:tooltip "G W"
|
:open-workspace {:tooltip "G W"
|
||||||
:command "g w"
|
:command "g w"
|
||||||
:subsections [:navigation-viewer]
|
:subsections [:navigation-viewer]
|
||||||
:fn #(st/emit! (dv/go-to-workspace))}})
|
:fn #(st/emit! (dcm/go-to-workspace))}})
|
||||||
|
|
||||||
(defn get-tooltip [shortcut]
|
(defn get-tooltip [shortcut]
|
||||||
(assert (contains? shortcuts shortcut) (str shortcut))
|
(assert (contains? shortcuts shortcut) (str shortcut))
|
||||||
|
|
|
@ -36,17 +36,18 @@
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcmt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.fonts :as df]
|
[app.main.data.fonts :as df]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.persistence :as dps]
|
|
||||||
[app.main.data.plugins :as dp]
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.project :as dpj]
|
||||||
[app.main.data.workspace.bool :as dwb]
|
[app.main.data.workspace.bool :as dwb]
|
||||||
[app.main.data.workspace.collapse :as dwco]
|
[app.main.data.workspace.collapse :as dwco]
|
||||||
|
[app.main.data.workspace.colors :as dwcl]
|
||||||
[app.main.data.workspace.drawing :as dwd]
|
[app.main.data.workspace.drawing :as dwd]
|
||||||
[app.main.data.workspace.edition :as dwe]
|
[app.main.data.workspace.edition :as dwe]
|
||||||
[app.main.data.workspace.fix-broken-shapes :as fbs]
|
[app.main.data.workspace.fix-broken-shapes :as fbs]
|
||||||
|
@ -75,6 +76,7 @@
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.features.pointer-map :as fpmap]
|
[app.main.features.pointer-map :as fpmap]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[app.main.worker :as uw]
|
[app.main.worker :as uw]
|
||||||
[app.render-wasm :as wasm]
|
[app.render-wasm :as wasm]
|
||||||
|
@ -82,7 +84,6 @@
|
||||||
[app.util.globals :as ug]
|
[app.util.globals :as ug]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[app.util.timers :as tm]
|
[app.util.timers :as tm]
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
|
@ -101,12 +102,15 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(declare ^:private workspace-initialized)
|
(declare ^:private workspace-initialized)
|
||||||
|
(declare ^:private fetch-libraries)
|
||||||
(declare ^:private libraries-fetched)
|
(declare ^:private libraries-fetched)
|
||||||
(declare go-to-layout)
|
(declare ^:private preload-data-uris)
|
||||||
|
|
||||||
|
;; (declare go-to-layout)
|
||||||
|
|
||||||
;; --- Initialize Workspace
|
;; --- Initialize Workspace
|
||||||
|
|
||||||
(defn initialize-layout
|
(defn initialize-workspace-layout
|
||||||
[lname]
|
[lname]
|
||||||
(ptk/reify ::initialize-layout
|
(ptk/reify ::initialize-layout
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -121,73 +125,35 @@
|
||||||
(rx/of (layout/ensure-layout lname))
|
(rx/of (layout/ensure-layout lname))
|
||||||
(rx/of (layout/ensure-layout :layers))))))
|
(rx/of (layout/ensure-layout :layers))))))
|
||||||
|
|
||||||
(defn- workspace-initialized
|
(defn- datauri->blob-uri
|
||||||
[]
|
[uri]
|
||||||
(ptk/reify ::workspace-initialized
|
(->> (http/send! {:uri uri
|
||||||
ptk/UpdateEvent
|
:response-type :blob
|
||||||
(update [_ state]
|
:method :get})
|
||||||
(-> state
|
(rx/map :body)
|
||||||
(assoc :workspace-undo {})
|
(rx/map (fn [blob] (wapi/create-uri blob)))))
|
||||||
(assoc :workspace-ready? true)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
(defn- get-file-object-thumbnails
|
||||||
(watch [_ state _]
|
[file-id]
|
||||||
(rx/of
|
(->> (rp/cmd! :get-file-object-thumbnails {:file-id file-id})
|
||||||
(when (and (not (boolean (-> state :profile :props :v2-info-shown)))
|
(rx/mapcat (fn [thumbnails]
|
||||||
(features/active-feature? state "components/v2"))
|
(->> (rx/from thumbnails)
|
||||||
(modal/show :v2-info {}))
|
(rx/mapcat (fn [[k v]]
|
||||||
(dp/check-open-plugin)
|
;; we only need to fetch the thumbnail if
|
||||||
(fdf/fix-deleted-fonts)
|
;; it is a data:uri, otherwise we can just
|
||||||
(fbs/fix-broken-shapes)))))
|
;; use the value as is.
|
||||||
|
(if (str/starts-with? v "data:")
|
||||||
|
(->> (datauri->blob-uri v)
|
||||||
|
(rx/map (fn [uri] [k uri])))
|
||||||
|
(rx/of [k v])))))))
|
||||||
|
(rx/reduce conj {})))
|
||||||
|
|
||||||
(defn- workspace-data-loaded
|
(defn- resolve-file
|
||||||
[data]
|
[file]
|
||||||
(ptk/reify ::workspace-data-loaded
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [data (d/removem (comp t/pointer? val) data)]
|
|
||||||
(assoc state :workspace-data data)))))
|
|
||||||
|
|
||||||
(defn- bundle-fetched
|
|
||||||
[{:keys [features file thumbnails project team team-users comments-users]}]
|
|
||||||
(ptk/reify ::bundle-fetched
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(-> state
|
|
||||||
(assoc :users (d/index-by :id team-users))
|
|
||||||
(assoc :workspace-thumbnails thumbnails)
|
|
||||||
(assoc :workspace-file (dissoc file :data))
|
|
||||||
(assoc :workspace-project project)
|
|
||||||
(assoc :current-file-comments-users (d/index-by :id comments-users))))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ stream]
|
|
||||||
(let [team-id (:id team)
|
|
||||||
file-id (:id file)
|
|
||||||
stopper (rx/filter (ptk/type? ::bundle-fetched) stream)]
|
|
||||||
|
|
||||||
(->> (rx/concat
|
|
||||||
;; Initialize notifications
|
|
||||||
;; FIXME: this should not be initialized here looks like
|
|
||||||
(rx/of (dwn/initialize team-id file-id)
|
|
||||||
(dwsl/initialize))
|
|
||||||
|
|
||||||
;; Load team fonts. We must ensure custom fonts are
|
|
||||||
;; fully loadad before mark workspace as initialized
|
|
||||||
(rx/merge
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::df/fonts-loaded))
|
|
||||||
(rx/take 1)
|
|
||||||
(rx/ignore))
|
|
||||||
|
|
||||||
(rx/of (df/fetch-fonts))
|
|
||||||
|
|
||||||
;; FIXME: move to bundle fetch stages
|
|
||||||
|
|
||||||
;; Load main file
|
|
||||||
(->> (fpmap/resolve-file file)
|
(->> (fpmap/resolve-file file)
|
||||||
(rx/map :data)
|
(rx/map :data)
|
||||||
(rx/mapcat (fn [{:keys [pages-index] :as data}]
|
(rx/mapcat
|
||||||
|
(fn [{:keys [pages-index] :as data}]
|
||||||
(->> (rx/from (seq pages-index))
|
(->> (rx/from (seq pages-index))
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [[id page]]
|
(fn [[id page]]
|
||||||
|
@ -196,30 +162,8 @@
|
||||||
(rx/map (fn [_] [id page]))))))
|
(rx/map (fn [_] [id page]))))))
|
||||||
(rx/reduce conj {})
|
(rx/reduce conj {})
|
||||||
(rx/map (fn [pages-index]
|
(rx/map (fn [pages-index]
|
||||||
(assoc data :pages-index pages-index))))))
|
(let [data (assoc data :pages-index pages-index)]
|
||||||
(rx/map workspace-data-loaded))
|
(assoc file :data (d/removem (comp t/pointer? val) data))))))))))
|
||||||
|
|
||||||
;; Load libraries
|
|
||||||
(->> (rp/cmd! :get-file-libraries {:file-id file-id})
|
|
||||||
(rx/mapcat (fn [libraries]
|
|
||||||
(rx/merge
|
|
||||||
(->> (rx/from libraries)
|
|
||||||
(rx/merge-map
|
|
||||||
(fn [{:keys [id synced-at]}]
|
|
||||||
(->> (rp/cmd! :get-file {:id id :features features})
|
|
||||||
(rx/map #(assoc % :synced-at synced-at)))))
|
|
||||||
(rx/merge-map fpmap/resolve-file)
|
|
||||||
(rx/reduce conj [])
|
|
||||||
(rx/map libraries-fetched))
|
|
||||||
(->> (rx/from libraries)
|
|
||||||
(rx/map :id)
|
|
||||||
(rx/mapcat (fn [file-id]
|
|
||||||
(rp/cmd! :get-file-object-thumbnails {:file-id file-id :tag "component"})))
|
|
||||||
(rx/map dwl/library-thumbnails-fetched)))))))
|
|
||||||
|
|
||||||
(rx/of (with-meta (workspace-initialized)
|
|
||||||
{:file-id file-id})))
|
|
||||||
(rx/take-until stopper))))))
|
|
||||||
|
|
||||||
(defn- libraries-fetched
|
(defn- libraries-fetched
|
||||||
[libraries]
|
[libraries]
|
||||||
|
@ -240,151 +184,153 @@
|
||||||
(rx/concat (rx/timer 1000)
|
(rx/concat (rx/timer 1000)
|
||||||
(rx/of (dwl/notify-sync-file file-id))))))))
|
(rx/of (dwl/notify-sync-file file-id))))))))
|
||||||
|
|
||||||
(defn- datauri->blob-uri
|
(defn- fetch-libraries
|
||||||
[uri]
|
|
||||||
(->> (http/send! {:uri uri
|
|
||||||
:response-type :blob
|
|
||||||
:method :get})
|
|
||||||
(rx/map :body)
|
|
||||||
(rx/map (fn [blob] (wapi/create-uri blob)))))
|
|
||||||
|
|
||||||
(defn- fetch-file-object-thumbnails
|
|
||||||
[file-id]
|
[file-id]
|
||||||
(->> (rp/cmd! :get-file-object-thumbnails {:file-id file-id})
|
(ptk/reify ::fetch-libries
|
||||||
(rx/mapcat (fn [thumbnails]
|
ptk/WatchEvent
|
||||||
(->> (rx/from thumbnails)
|
(watch [_ state _]
|
||||||
(rx/mapcat (fn [[k v]]
|
(let [features (features/get-team-enabled-features state)]
|
||||||
;; we only need to fetch the thumbnail if
|
(->> (rp/cmd! :get-file-libraries {:file-id file-id})
|
||||||
;; it is a data:uri, otherwise we can just
|
(rx/mapcat
|
||||||
;; use the value as is.
|
(fn [libraries]
|
||||||
(if (str/starts-with? v "data:")
|
(rx/merge
|
||||||
(->> (datauri->blob-uri v)
|
(->> (rx/from libraries)
|
||||||
(rx/map (fn [uri] [k uri])))
|
(rx/merge-map
|
||||||
(rx/of [k v])))))))
|
(fn [{:keys [id synced-at]}]
|
||||||
(rx/reduce conj {})))
|
(->> (rp/cmd! :get-file {:id id :features features})
|
||||||
|
(rx/map #(assoc % :synced-at synced-at)))))
|
||||||
|
(rx/merge-map resolve-file)
|
||||||
|
(rx/reduce conj [])
|
||||||
|
(rx/map libraries-fetched))
|
||||||
|
(->> (rx/from libraries)
|
||||||
|
(rx/map :id)
|
||||||
|
(rx/mapcat (fn [file-id]
|
||||||
|
(rp/cmd! :get-file-object-thumbnails {:file-id file-id :tag "component"})))
|
||||||
|
(rx/map dwl/library-thumbnails-fetched))))))))))
|
||||||
|
|
||||||
(defn- fetch-bundle-stage-1
|
(defn- workspace-initialized
|
||||||
[project-id file-id]
|
[]
|
||||||
(ptk/reify ::fetch-bundle-stage-1
|
(ptk/reify ::workspace-initialized
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(-> state
|
||||||
|
(assoc :workspace-undo {})
|
||||||
|
(assoc :workspace-ready true)))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(rx/of
|
||||||
|
(when (and (not (boolean (-> state :profile :props :v2-info-shown)))
|
||||||
|
(features/active-feature? state "components/v2"))
|
||||||
|
(modal/show :v2-info {}))
|
||||||
|
(dp/check-open-plugin)
|
||||||
|
(fdf/fix-deleted-fonts)
|
||||||
|
(fbs/fix-broken-shapes)))))
|
||||||
|
|
||||||
|
(defn- bundle-fetched
|
||||||
|
[{:keys [features file thumbnails]}]
|
||||||
|
(ptk/reify ::bundle-fetched
|
||||||
|
IDeref
|
||||||
|
(-deref [_]
|
||||||
|
{:features features
|
||||||
|
:file file
|
||||||
|
:thumbnails thumbnails})
|
||||||
|
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(-> state
|
||||||
|
(assoc :thumbnails thumbnails)
|
||||||
|
(assoc :workspace-file (dissoc file :data))
|
||||||
|
(assoc :workspace-data (:data file))))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [team-id (:current-team-id state)
|
||||||
|
file-id (:id file)]
|
||||||
|
|
||||||
|
(rx/of (dwn/initialize team-id file-id)
|
||||||
|
(dwsl/initialize-shape-layout)
|
||||||
|
(fetch-libraries file-id))))))
|
||||||
|
|
||||||
|
(defn- fetch-bundle
|
||||||
|
"Multi-stage file bundle fetch coordinator"
|
||||||
|
[file-id]
|
||||||
|
(ptk/reify ::fetch-bundle
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [render-wasm? (features/active-feature? state "render-wasm/v1")]
|
(let [features (features/get-team-enabled-features state)
|
||||||
(->> (rp/cmd! :get-project {:id project-id})
|
render-wasm? (contains? features "render-wasm/v1")
|
||||||
(rx/mapcat (fn [project]
|
stopper-s (rx/filter (ptk/type? ::finalize-workspace) stream)]
|
||||||
(rx/concat
|
|
||||||
;; Wait the wasm module to be loaded or failed to
|
|
||||||
;; load. We need to wait the promise to be resolved
|
|
||||||
;; before continue with the next workspace loading
|
|
||||||
;; steps
|
|
||||||
|
|
||||||
|
(->> (rx/concat
|
||||||
|
;; Firstly load wasm module if it is enabled and fonts
|
||||||
|
(rx/merge
|
||||||
(if ^boolean render-wasm?
|
(if ^boolean render-wasm?
|
||||||
(->> (rx/from @wasm/module)
|
(->> (rx/from @wasm/module)
|
||||||
(rx/ignore))
|
(rx/ignore))
|
||||||
(rx/empty))
|
(rx/empty))
|
||||||
|
|
||||||
(->> (rp/cmd! :get-team {:id (:team-id project)})
|
(->> stream
|
||||||
(rx/mapcat (fn [team]
|
(rx/filter (ptk/type? ::df/fonts-loaded))
|
||||||
(let [bundle {:team team
|
|
||||||
:project project
|
|
||||||
:file-id file-id
|
|
||||||
:project-id project-id}]
|
|
||||||
;; FIXME: this should not be handled here, pending
|
|
||||||
;; refactor of urls and team initialization
|
|
||||||
;; normalization
|
|
||||||
(rx/of (dtm/set-current-team team)
|
|
||||||
(ptk/data-event ::bundle-stage-1 bundle)))))))))
|
|
||||||
(rx/take-until
|
|
||||||
(rx/filter (ptk/type? ::fetch-bundle) stream)))))))
|
|
||||||
|
|
||||||
(defn- fetch-bundle-stage-2
|
|
||||||
[{:keys [file-id project-id project] :as bundle}]
|
|
||||||
(ptk/reify ::fetch-bundle-stage-2
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(-> state
|
|
||||||
(update :projects assoc project-id project)))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [features (features/get-team-enabled-features state)
|
|
||||||
|
|
||||||
;; WTF is this?
|
|
||||||
share-id (-> state :viewer-local :share-id)]
|
|
||||||
(->> (rx/zip (rp/cmd! :get-file {:id file-id :features features :project-id project-id})
|
|
||||||
(fetch-file-object-thumbnails file-id)
|
|
||||||
(rp/cmd! :get-team-users {:file-id file-id})
|
|
||||||
(rp/cmd! :get-profiles-for-file-comments {:file-id file-id :share-id share-id}))
|
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map (fn [[file thumbnails team-users comments-users]]
|
(rx/ignore))
|
||||||
(let [bundle (-> bundle
|
(rx/of (df/fetch-fonts)))
|
||||||
(assoc :file file)
|
|
||||||
(assoc :features features)
|
|
||||||
(assoc :thumbnails thumbnails)
|
|
||||||
(assoc :team-users team-users)
|
|
||||||
(assoc :comments-users comments-users))]
|
|
||||||
(ptk/data-event ::bundle-stage-2 bundle))))
|
|
||||||
(rx/take-until
|
|
||||||
(rx/filter (ptk/type? ::fetch-bundle) stream)))))))
|
|
||||||
|
|
||||||
(declare go-to-component)
|
;; Then fetch file and thumbnails
|
||||||
|
(->> (rx/zip (rp/cmd! :get-file {:id file-id :features features})
|
||||||
(defn- fetch-bundle
|
(get-file-object-thumbnails file-id))
|
||||||
"Multi-stage file bundle fetch coordinator"
|
|
||||||
[project-id file-id]
|
|
||||||
(ptk/reify ::fetch-bundle
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(->> (rx/merge
|
|
||||||
(rx/of (fetch-bundle-stage-1 project-id file-id))
|
|
||||||
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::bundle-stage-1))
|
|
||||||
(rx/observe-on :async)
|
|
||||||
(rx/map deref)
|
|
||||||
(rx/map fetch-bundle-stage-2))
|
|
||||||
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::bundle-stage-2))
|
|
||||||
(rx/observe-on :async)
|
|
||||||
(rx/map deref)
|
|
||||||
(rx/map bundle-fetched))
|
|
||||||
|
|
||||||
(when-let [component-id (get-in state [:route :query-params :component-id])]
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::workspace-initialized))
|
|
||||||
(rx/observe-on :async)
|
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map #(go-to-component (uuid/uuid component-id))))))
|
(rx/mapcat
|
||||||
|
(fn [[file thumbnails]]
|
||||||
|
(->> (resolve-file file)
|
||||||
|
(rx/map (fn [file]
|
||||||
|
{:file file
|
||||||
|
:features features
|
||||||
|
:thumbnails thumbnails})))))
|
||||||
|
(rx/map bundle-fetched)))
|
||||||
|
|
||||||
(rx/take-until
|
(rx/take-until stopper-s))))))
|
||||||
(rx/filter (ptk/type? ::fetch-bundle) stream))))))
|
|
||||||
|
|
||||||
(defn initialize-file
|
(defn initialize-workspace
|
||||||
[project-id file-id]
|
[file-id]
|
||||||
(dm/assert! (uuid? project-id))
|
(assert (uuid? file-id) "expected valud uuid for `file-id`")
|
||||||
(dm/assert! (uuid? file-id))
|
|
||||||
|
|
||||||
(ptk/reify ::initialize-file
|
(ptk/reify ::initialize-workspace
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc state
|
(assoc state
|
||||||
:recent-colors (:recent-colors storage/user)
|
:recent-colors (:recent-colors storage/user)
|
||||||
:workspace-ready? false
|
:workspace-ready false
|
||||||
:current-file-id file-id
|
:current-file-id file-id
|
||||||
:current-project-id project-id
|
|
||||||
:workspace-presence {}))
|
:workspace-presence {}))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ stream]
|
(watch [_ state stream]
|
||||||
(log/debug :hint "initialize-file" :file-id file-id)
|
(log/debug :hint "initialize-workspace" :file-id file-id)
|
||||||
(let [stoper-s (rx/filter (ptk/type? ::finalize-file) stream)]
|
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||||
(rx/merge
|
rparams (rt/get-params state)]
|
||||||
|
|
||||||
|
(->> (rx/merge
|
||||||
(rx/of (ntf/hide)
|
(rx/of (ntf/hide)
|
||||||
;; We initialize the features without knowning the
|
(dcmt/retrieve-comment-threads file-id)
|
||||||
;; team specific features in this step.
|
(dcmt/fetch-profiles)
|
||||||
(features/initialize)
|
(fetch-bundle file-id))
|
||||||
(dcm/retrieve-comment-threads file-id)
|
|
||||||
(fetch-bundle project-id file-id))
|
(->> stream
|
||||||
|
(rx/filter (ptk/type? ::bundle-fetched))
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map deref)
|
||||||
|
(rx/mapcat (fn [{:keys [file]}]
|
||||||
|
(rx/of (dpj/initialize-project (:project-id file))
|
||||||
|
(-> (workspace-initialized)
|
||||||
|
(with-meta {:file-id file-id}))))))
|
||||||
|
|
||||||
|
(when-let [component-id (some-> rparams :component-id parse-uuid)]
|
||||||
|
(->> stream
|
||||||
|
(rx/filter (ptk/type? ::workspace-initialized))
|
||||||
|
(rx/observe-on :async)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map #(dwl/go-to-local-component :id component-id))))
|
||||||
|
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter dch/commit?)
|
(rx/filter dch/commit?)
|
||||||
|
@ -396,37 +342,22 @@
|
||||||
:undo-group undo-group
|
:undo-group undo-group
|
||||||
:tags tags}]
|
:tags tags}]
|
||||||
(rx/of (dwu/append-undo entry stack-undo?)))
|
(rx/of (dwu/append-undo entry stack-undo?)))
|
||||||
(rx/empty))))
|
(rx/empty))))))
|
||||||
|
(rx/take-until stoper-s))))
|
||||||
(rx/take-until stoper-s)))))
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ _ _]
|
(effect [_ _ _]
|
||||||
(let [name (dm/str "workspace-" file-id)]
|
(let [name (dm/str "workspace-" file-id)]
|
||||||
(unchecked-set ug/global "name" name)))))
|
(unchecked-set ug/global "name" name)))))
|
||||||
|
|
||||||
(defn reload-file
|
(defn finalize-workspace
|
||||||
[]
|
[file-id]
|
||||||
(ptk/reify ::reload-file
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [file-id (:current-file-id state)
|
|
||||||
project-id (:current-project-id state)]
|
|
||||||
(rx/of (initialize-file project-id file-id))))))
|
|
||||||
|
|
||||||
;; We need to inject this so there are no cycles
|
|
||||||
(set! app.main.data.workspace.notifications/reload-file reload-file)
|
|
||||||
(set! app.main.errors/reload-file reload-file)
|
|
||||||
|
|
||||||
(defn finalize-file
|
|
||||||
[_project-id file-id]
|
|
||||||
(ptk/reify ::finalize-file
|
(ptk/reify ::finalize-file
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(-> state
|
||||||
(dissoc
|
(dissoc
|
||||||
:current-file-id
|
:current-file-id
|
||||||
:current-project-id
|
|
||||||
:workspace-data
|
:workspace-data
|
||||||
:workspace-editor-state
|
:workspace-editor-state
|
||||||
:workspace-file
|
:workspace-file
|
||||||
|
@ -434,22 +365,37 @@
|
||||||
:workspace-media-objects
|
:workspace-media-objects
|
||||||
:workspace-persistence
|
:workspace-persistence
|
||||||
:workspace-presence
|
:workspace-presence
|
||||||
:workspace-ready?
|
:workspace-ready
|
||||||
:workspace-undo)
|
:workspace-undo)
|
||||||
(update :workspace-global dissoc :read-only?)
|
(update :workspace-global dissoc :read-only?)
|
||||||
(assoc-in [:workspace-global :options-mode] :design)))
|
(assoc-in [:workspace-global :options-mode] :design)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
(rx/of (dwn/finalize file-id)
|
(let [project-id (:current-project-id state)]
|
||||||
(dwsl/finalize)))))
|
|
||||||
|
|
||||||
(declare go-to-page)
|
(rx/of (dwn/finalize file-id)
|
||||||
(declare ^:private preload-data-uris)
|
(dpj/finalize-project project-id)
|
||||||
|
(dwsl/finalize-shape-layout)
|
||||||
|
(dwcl/stop-picker)
|
||||||
|
(modal/hide)
|
||||||
|
(ntf/hide))))))
|
||||||
|
|
||||||
|
(defn- reload-current-file
|
||||||
|
[]
|
||||||
|
(ptk/reify ::reload-current-file
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [file-id (:current-file-id state)]
|
||||||
|
(rx/of (initialize-workspace file-id))))))
|
||||||
|
|
||||||
|
;; Make this event callable through dynamic resolution
|
||||||
|
(defmethod ptk/resolve ::reload-current-file [_ _] (reload-current-file))
|
||||||
|
|
||||||
(defn initialize-page
|
(defn initialize-page
|
||||||
[page-id]
|
[page-id]
|
||||||
(dm/assert! (uuid? page-id))
|
(assert (uuid? page-id) "expected valid uuid for `page-id`")
|
||||||
|
|
||||||
(ptk/reify ::initialize-page
|
(ptk/reify ::initialize-page
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -464,30 +410,20 @@
|
||||||
|
|
||||||
;; FIXME: this should be done on `initialize-layout` (?)
|
;; FIXME: this should be done on `initialize-layout` (?)
|
||||||
(update :workspace-layout layout/load-layout-flags)
|
(update :workspace-layout layout/load-layout-flags)
|
||||||
(update :workspace-global layout/load-layout-state)
|
(update :workspace-global layout/load-layout-state)))
|
||||||
|
|
||||||
(update :workspace-global assoc :background-color (-> page :options :background))
|
|
||||||
(update-in [:route :params :query] assoc :page-id (dm/str id))))
|
|
||||||
|
|
||||||
state))
|
state))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
;; NOTE: there are cases between files navigation when this
|
|
||||||
;; event is emmited but the page-index is still not loaded, so
|
|
||||||
;; we only need to proceed when page-index is properly loaded
|
|
||||||
(when-let [pindex (-> state :workspace-data :pages-index)]
|
|
||||||
(if (contains? pindex page-id)
|
|
||||||
(let [file-id (:current-file-id state)]
|
(let [file-id (:current-file-id state)]
|
||||||
(rx/of (preload-data-uris page-id)
|
(rx/of (preload-data-uris page-id)
|
||||||
(dwth/watch-state-changes file-id page-id)
|
(dwth/watch-state-changes file-id page-id)
|
||||||
(dwl/watch-component-changes)))
|
(dwl/watch-component-changes))))))
|
||||||
(let [page-id (dm/get-in state [:workspace-data :pages 0])]
|
|
||||||
(rx/of (go-to-page page-id))))))))
|
|
||||||
|
|
||||||
(defn finalize-page
|
(defn finalize-page
|
||||||
[page-id]
|
[page-id]
|
||||||
(dm/assert! (uuid? page-id))
|
(assert (uuid? page-id) "expected valid uuid for `page-id`")
|
||||||
(ptk/reify ::finalize-page
|
(ptk/reify ::finalize-page
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -683,7 +619,7 @@
|
||||||
|
|
||||||
(rx/of (dch/commit-changes changes)
|
(rx/of (dch/commit-changes changes)
|
||||||
(when (= id (:current-page-id state))
|
(when (= id (:current-page-id state))
|
||||||
go-to-file))))))
|
(go-to-file)))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; WORKSPACE File Actions
|
;; WORKSPACE File Actions
|
||||||
|
@ -847,7 +783,7 @@
|
||||||
(let [selected (wsh/lookup-selected state)
|
(let [selected (wsh/lookup-selected state)
|
||||||
id (first selected)]
|
id (first selected)]
|
||||||
(when (= (count selected) 1)
|
(when (= (count selected) 1)
|
||||||
(rx/of (go-to-layout :layers)
|
(rx/of (dcm/go-to-workspace :layout :layers)
|
||||||
(start-rename-shape id)))))))
|
(start-rename-shape id)))))))
|
||||||
|
|
||||||
;; --- Shape Vertical Ordering
|
;; --- Shape Vertical Ordering
|
||||||
|
@ -1111,76 +1047,17 @@
|
||||||
(rx/of (dwsh/update-shapes selected #(assoc % :proportion-lock true)))
|
(rx/of (dwsh/update-shapes selected #(assoc % :proportion-lock true)))
|
||||||
(rx/of (dwsh/update-shapes selected #(update % :proportion-lock not))))))))
|
(rx/of (dwsh/update-shapes selected #(update % :proportion-lock not))))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Navigation
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(defn workspace-focus-lost
|
(defn workspace-focus-lost
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::workspace-focus-lost
|
(ptk/reify ::workspace-focus-lost
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
;; FIXME: remove the `?` from show-distances?
|
||||||
(assoc-in state [:workspace-global :show-distances?] false))))
|
(assoc-in state [:workspace-global :show-distances?] false))))
|
||||||
|
|
||||||
(defn navigate-to-project
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
[project-id]
|
;; Navigation
|
||||||
(ptk/reify ::navigate-to-project
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [page-ids (get-in state [:projects project-id :pages])
|
|
||||||
params {:project project-id :page (first page-ids)}]
|
|
||||||
(rx/of (rt/nav :workspace/page params))))))
|
|
||||||
|
|
||||||
(defn go-to-page
|
|
||||||
([]
|
|
||||||
(ptk/reify ::go-to-page
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [project-id (:current-project-id state)
|
|
||||||
file-id (:current-file-id state)
|
|
||||||
page-id (get-in state [:workspace-data :pages 0])
|
|
||||||
|
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id page-id}]
|
|
||||||
(rx/of (rt/nav' :workspace pparams qparams))))))
|
|
||||||
([page-id]
|
|
||||||
(dm/assert! (uuid? page-id))
|
|
||||||
(ptk/reify ::go-to-page-2
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [project-id (:current-project-id state)
|
|
||||||
file-id (:current-file-id state)
|
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id page-id}]
|
|
||||||
(rx/of (rt/nav :workspace pparams qparams)))))))
|
|
||||||
|
|
||||||
(defn go-to-layout
|
|
||||||
[layout]
|
|
||||||
(ptk/reify ::go-to-layout
|
|
||||||
IDeref
|
|
||||||
(-deref [_] {:layout layout})
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [project-id (:current-project-id state)
|
|
||||||
file-id (:current-file-id state)
|
|
||||||
page-id (:current-page-id state)
|
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id page-id :layout (name layout)}]
|
|
||||||
(rx/of (rt/nav :workspace pparams qparams))))))
|
|
||||||
|
|
||||||
(defn navigate-to-library
|
|
||||||
"Open a new tab, and navigate to the workspace with the provided file"
|
|
||||||
[library-id]
|
|
||||||
(ptk/reify ::navigate-to-file
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(when-let [file (dm/get-in state [:workspace-libraries library-id])]
|
|
||||||
(let [params {:rname :workspace
|
|
||||||
:path-params {:project-id (:project-id file)
|
|
||||||
:file-id (:id file)}
|
|
||||||
:query-params {:page-id (dm/get-in file [:data :pages 0])}}]
|
|
||||||
(rx/of (rt/nav-new-window* params)))))))
|
|
||||||
|
|
||||||
(defn set-assets-section-open
|
(defn set-assets-section-open
|
||||||
[file-id section open?]
|
[file-id section open?]
|
||||||
|
@ -1242,111 +1119,18 @@
|
||||||
(update-in state [:workspace-assets :selected] dissoc file-id)
|
(update-in state [:workspace-assets :selected] dissoc file-id)
|
||||||
(update state :workspace-assets dissoc :selected))))))
|
(update state :workspace-assets dissoc :selected))))))
|
||||||
|
|
||||||
(defn go-to-main-instance
|
|
||||||
[file-id component-id]
|
|
||||||
(dm/assert!
|
|
||||||
"expected uuid type for `file-id` parameter (nilable)"
|
|
||||||
(or (nil? file-id)
|
|
||||||
(uuid? file-id)))
|
|
||||||
|
|
||||||
(dm/assert!
|
|
||||||
"expected uuid type for `component-id` parameter"
|
|
||||||
(uuid? component-id))
|
|
||||||
|
|
||||||
(ptk/reify ::go-to-main-instance
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [current-file-id (:current-file-id state)
|
|
||||||
current-page-id (:current-page-id state)
|
|
||||||
current-project-id (:current-project-id state)
|
|
||||||
file-id (or file-id current-file-id)
|
|
||||||
|
|
||||||
select-and-zoom
|
|
||||||
(fn [shape-id]
|
|
||||||
(rx/of (dws/select-shapes (d/ordered-set shape-id))
|
|
||||||
dwz/zoom-to-selected-shape))
|
|
||||||
|
|
||||||
redirect-to-page
|
|
||||||
(fn [page-id shape-id]
|
|
||||||
(rx/concat
|
|
||||||
(rx/of (go-to-page page-id))
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::initialize-page))
|
|
||||||
(rx/take 1)
|
|
||||||
(rx/observe-on :async))
|
|
||||||
(select-and-zoom shape-id)))
|
|
||||||
|
|
||||||
redirect-to-file
|
|
||||||
(fn [file-id page-id]
|
|
||||||
(let [pparams {:file-id file-id :project-id current-project-id}
|
|
||||||
qparams {:page-id page-id}]
|
|
||||||
(rx/merge
|
|
||||||
(rx/of (rt/nav :workspace pparams qparams))
|
|
||||||
(->> stream
|
|
||||||
(rx/filter (ptk/type? ::workspace-initialized))
|
|
||||||
(rx/map meta)
|
|
||||||
(rx/filter #(= file-id (:file-id %)))
|
|
||||||
(rx/take 1)
|
|
||||||
(rx/observe-on :async)
|
|
||||||
(rx/map #(go-to-main-instance file-id component-id))))))]
|
|
||||||
|
|
||||||
(if (= file-id current-file-id)
|
|
||||||
(let [component (dm/get-in state [:workspace-data :components component-id])
|
|
||||||
page-id (:main-instance-page component)
|
|
||||||
shape-id (:main-instance-id component)]
|
|
||||||
(when (some? page-id)
|
|
||||||
(if (= page-id current-page-id)
|
|
||||||
(select-and-zoom shape-id)
|
|
||||||
(redirect-to-page page-id shape-id))))
|
|
||||||
|
|
||||||
(let [component (dm/get-in state [:workspace-libraries file-id :data :components component-id])]
|
|
||||||
(some->> (:main-instance-page component)
|
|
||||||
(redirect-to-file file-id))))))))
|
|
||||||
|
|
||||||
(defn go-to-component
|
|
||||||
[component-id]
|
|
||||||
(ptk/reify ::go-to-component
|
|
||||||
IDeref
|
|
||||||
(-deref [_] {:layout :assets})
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [components-v2 (features/active-feature? state "components/v2")]
|
|
||||||
(if components-v2
|
|
||||||
(rx/of (go-to-main-instance nil component-id))
|
|
||||||
(let [file-id (:current-file-id state)
|
|
||||||
project-id (:current-project-id state)
|
|
||||||
page-id (:current-page-id state)
|
|
||||||
|
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id page-id :layout :assets}]
|
|
||||||
(rx/of (rt/nav :workspace pparams qparams)
|
|
||||||
(set-assets-section-open file-id :library true)
|
|
||||||
(set-assets-section-open file-id :components true)
|
|
||||||
(select-single-asset file-id component-id :components))))))
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
|
||||||
(effect [_ state _]
|
|
||||||
(let [components-v2 (features/active-feature? state "components/v2")
|
|
||||||
wrapper-id (str "component-shape-id-" component-id)]
|
|
||||||
(when-not components-v2
|
|
||||||
(tm/schedule-on-idle #(dom/scroll-into-view-if-needed! (dom/get-element wrapper-id))))))))
|
|
||||||
|
|
||||||
(defn show-component-in-assets
|
(defn show-component-in-assets
|
||||||
[component-id]
|
[component-id]
|
||||||
|
|
||||||
(ptk/reify ::show-component-in-assets
|
(ptk/reify ::show-component-in-assets
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [project-id (:current-project-id state)
|
(let [component-path (cfh/split-path (get-in state [:workspace-data :components component-id :path]))
|
||||||
file-id (:current-file-id state)
|
paths (map (fn [i] (cfh/join-path (take (inc i) component-path))) (range (count component-path)))
|
||||||
page-id (:current-page-id state)
|
file-id (:current-file-id state)]
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id page-id :layout :assets}
|
|
||||||
component-path (cfh/split-path (get-in state [:workspace-data :components component-id :path]))
|
|
||||||
paths (map (fn [i] (cfh/join-path (take (inc i) component-path))) (range (count component-path)))]
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/from (map #(set-assets-group-open file-id :components % true) paths))
|
(rx/from (map #(set-assets-group-open file-id :components % true) paths))
|
||||||
(rx/of (rt/nav :workspace pparams qparams)
|
(rx/of (dcm/go-to-workspace :layout :assets)
|
||||||
(set-assets-section-open file-id :library true)
|
(set-assets-section-open file-id :library true)
|
||||||
(set-assets-section-open file-id :components true)
|
(set-assets-section-open file-id :components true)
|
||||||
(select-single-asset file-id component-id :components)))))
|
(select-single-asset file-id component-id :components)))))
|
||||||
|
@ -1356,55 +1140,6 @@
|
||||||
(let [wrapper-id (str "component-shape-id-" component-id)]
|
(let [wrapper-id (str "component-shape-id-" component-id)]
|
||||||
(tm/schedule-on-idle #(dom/scroll-into-view-if-needed! (dom/get-element wrapper-id)))))))
|
(tm/schedule-on-idle #(dom/scroll-into-view-if-needed! (dom/get-element wrapper-id)))))))
|
||||||
|
|
||||||
(def go-to-file
|
|
||||||
(ptk/reify ::go-to-file
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [{:keys [id project-id data] :as file} (:workspace-file state)
|
|
||||||
page-id (get-in data [:pages 0])
|
|
||||||
pparams {:project-id project-id :file-id id}
|
|
||||||
qparams {:page-id page-id}]
|
|
||||||
(rx/of (rt/nav :workspace pparams qparams))))))
|
|
||||||
|
|
||||||
(defn go-to-viewer
|
|
||||||
([] (go-to-viewer {}))
|
|
||||||
([{:keys [file-id page-id section frame-id]}]
|
|
||||||
(ptk/reify ::go-to-viewer
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [{:keys [current-file-id current-page-id]} state
|
|
||||||
pparams {:file-id (or file-id current-file-id)}
|
|
||||||
qparams (cond-> {:page-id (or page-id current-page-id)}
|
|
||||||
(some? section)
|
|
||||||
(assoc :section section)
|
|
||||||
(some? frame-id)
|
|
||||||
(assoc :frame-id frame-id))]
|
|
||||||
(rx/of ::dps/force-persist
|
|
||||||
(rt/nav-new-window* {:rname :viewer
|
|
||||||
:path-params pparams
|
|
||||||
:query-params qparams
|
|
||||||
:name (str "viewer-" (:file-id pparams))})))))))
|
|
||||||
|
|
||||||
(defn go-to-dashboard
|
|
||||||
([] (go-to-dashboard nil))
|
|
||||||
([{:keys [team-id]}]
|
|
||||||
(ptk/reify ::go-to-dashboard
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(when-let [team-id (or team-id (:current-team-id state))]
|
|
||||||
(rx/of ::dps/force-persist
|
|
||||||
(rt/nav :dashboard-projects {:team-id team-id})))))))
|
|
||||||
|
|
||||||
(defn go-to-dashboard-fonts
|
|
||||||
[]
|
|
||||||
(ptk/reify ::go-to-dashboard-fonts
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [team-id (:current-team-id state)]
|
|
||||||
(rx/of ::dps/force-persist
|
|
||||||
(rt/nav :dashboard-fonts {:team-id team-id}))))))
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Context Menu
|
;; Context Menu
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1640,8 +1375,8 @@
|
||||||
(rx/catch on-copy-error)
|
(rx/catch on-copy-error)
|
||||||
(rx/ignore)))
|
(rx/ignore)))
|
||||||
|
|
||||||
;; FIXME: this is to support Firefox versions below 116 that don't support `ClipboardItem`
|
;; FIXME: this is to support Firefox versions below 116 that don't support
|
||||||
;; after the version 116 is less common we could remove this.
|
;; `ClipboardItem` after the version 116 is less common we could remove this.
|
||||||
;; https://caniuse.com/?search=ClipboardItem
|
;; https://caniuse.com/?search=ClipboardItem
|
||||||
(->> (rx/from shapes)
|
(->> (rx/from shapes)
|
||||||
(rx/merge-map (partial prepare-object objects frame-id))
|
(rx/merge-map (partial prepare-object objects frame-id))
|
||||||
|
@ -1924,7 +1659,8 @@
|
||||||
;; the pasted object doesn't fit we try to:
|
;; the pasted object doesn't fit we try to:
|
||||||
;;
|
;;
|
||||||
;; - Align it to the limits on the x and y axis
|
;; - Align it to the limits on the x and y axis
|
||||||
;; - Respect the distance of the object to the right and bottom in the original frame
|
;; - Respect the distance of the object to the right
|
||||||
|
;; and bottom in the original frame
|
||||||
(gpt/point paste-x paste-y))]
|
(gpt/point paste-x paste-y))]
|
||||||
[frame-id delta (dec (count (:shapes selected-frame-obj)))]))
|
[frame-id delta (dec (count (:shapes selected-frame-obj)))]))
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcmt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.common :as dwco]
|
[app.main.data.workspace.common :as dwco]
|
||||||
|
@ -23,7 +24,6 @@
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[app.util.mouse :as mse]
|
[app.util.mouse :as mse]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
(watch [_ _ stream]
|
(watch [_ _ stream]
|
||||||
(let [stopper (rx/filter #(= ::finalize %) stream)]
|
(let [stopper (rx/filter #(= ::finalize %) stream)]
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (dcm/retrieve-comment-threads file-id))
|
(rx/of (dcmt/retrieve-comment-threads file-id))
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter mse/mouse-event?)
|
(rx/filter mse/mouse-event?)
|
||||||
(rx/filter mse/mouse-click-event?)
|
(rx/filter mse/mouse-click-event?)
|
||||||
|
@ -60,8 +60,8 @@
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [local (:comments-local state)]
|
(let [local (:comments-local state)]
|
||||||
(cond
|
(cond
|
||||||
(:draft local) (rx/of (dcm/close-thread))
|
(:draft local) (rx/of (dcmt/close-thread))
|
||||||
(:open local) (rx/of (dcm/close-thread))
|
(:open local) (rx/of (dcmt/close-thread))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(rx/of (dw/clear-edition-mode)
|
(rx/of (dw/clear-edition-mode)
|
||||||
|
@ -78,19 +78,19 @@
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [local (:comments-local state)]
|
(let [local (:comments-local state)]
|
||||||
(if (some? (:open local))
|
(if (some? (:open local))
|
||||||
(rx/of (dcm/close-thread))
|
(rx/of (dcmt/close-thread))
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
file-id (:current-file-id state)
|
file-id (:current-file-id state)
|
||||||
params {:position position
|
params {:position position
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:file-id file-id}]
|
:file-id file-id}]
|
||||||
(rx/of (dcm/create-draft params))))))))
|
(rx/of (dcmt/create-draft params))))))))
|
||||||
|
|
||||||
(defn center-to-comment-thread
|
(defn center-to-comment-thread
|
||||||
[{:keys [position] :as thread}]
|
[{:keys [position] :as thread}]
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid comment thread"
|
"expected valid comment thread"
|
||||||
(dcm/check-comment-thread! thread))
|
(dcmt/check-comment-thread! thread))
|
||||||
|
|
||||||
(ptk/reify ::center-to-comment-thread
|
(ptk/reify ::center-to-comment-thread
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -109,22 +109,21 @@
|
||||||
[thread]
|
[thread]
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid comment thread"
|
"expected valid comment thread"
|
||||||
(dcm/check-comment-thread! thread))
|
(dcmt/check-comment-thread! thread))
|
||||||
(ptk/reify ::open-comment-thread
|
(ptk/reify ::open-comment-thread
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ stream]
|
(watch [_ _ stream]
|
||||||
(let [pparams {:project-id (:project-id thread)
|
|
||||||
:file-id (:file-id thread)}
|
|
||||||
qparams {:page-id (:page-id thread)}]
|
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (rt/nav :workspace pparams qparams))
|
(rx/of (dcm/go-to-workspace :file-id (:file-id thread)
|
||||||
|
:page-id (:page-id thread)))
|
||||||
|
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/mapcat #(rx/of (center-to-comment-thread thread)
|
(rx/mapcat #(rx/of (center-to-comment-thread thread)
|
||||||
(dwd/select-for-drawing :comments)
|
(dwd/select-for-drawing :comments)
|
||||||
(with-meta (dcm/open-thread thread)
|
(with-meta (dcmt/open-thread thread)
|
||||||
{::ev/origin "workspace"})))))))))
|
{::ev/origin "workspace"}))))))))
|
||||||
|
|
||||||
(defn update-comment-thread-position
|
(defn update-comment-thread-position
|
||||||
([thread [new-x new-y]]
|
([thread [new-x new-y]]
|
||||||
|
@ -133,7 +132,7 @@
|
||||||
([thread [new-x new-y] frame-id]
|
([thread [new-x new-y] frame-id]
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid comment thread"
|
"expected valid comment thread"
|
||||||
(dcm/check-comment-thread! thread))
|
(dcmt/check-comment-thread! thread))
|
||||||
(ptk/reify ::update-comment-thread-position
|
(ptk/reify ::update-comment-thread-position
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.comments :as dc]
|
[app.main.data.comments :as dc]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
@ -40,14 +41,15 @@
|
||||||
[app.main.data.workspace.thumbnails :as dwt]
|
[app.main.data.workspace.thumbnails :as dwt]
|
||||||
[app.main.data.workspace.transforms :as dwtr]
|
[app.main.data.workspace.transforms :as dwtr]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
|
[app.main.data.workspace.zoom :as dwz]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.features.pointer-map :as fpmap]
|
[app.main.features.pointer-map :as fpmap]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
|
@ -684,21 +686,49 @@
|
||||||
(rx/of (when can-detach?
|
(rx/of (when can-detach?
|
||||||
(dch/commit-changes changes)))))))
|
(dch/commit-changes changes)))))))
|
||||||
|
|
||||||
(defn nav-to-component-file
|
(defn go-to-component-file
|
||||||
[file-id component]
|
[file-id component]
|
||||||
(dm/assert! (uuid? file-id))
|
(dm/assert! (uuid? file-id))
|
||||||
(dm/assert! (some? component))
|
(dm/assert! (some? component))
|
||||||
(ptk/reify ::nav-to-component-file
|
(ptk/reify ::nav-to-component-file
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [project-id (get-in state [:workspace-libraries file-id :project-id])
|
(let [params (-> (rt/get-params state)
|
||||||
path-params {:project-id project-id
|
(assoc :file-id file-id)
|
||||||
:file-id file-id}
|
(assoc :page-id (:main-instance-page component))
|
||||||
query-params {:page-id (:main-instance-page component)
|
(assoc :component-id (:id component)))]
|
||||||
:component-id (:id component)}]
|
(rx/of (rt/nav :workspace params :new-window? true))))))
|
||||||
(rx/of (rt/nav-new-window* {:rname :workspace
|
|
||||||
:path-params path-params
|
|
||||||
:query-params query-params}))))))
|
(defn go-to-local-component
|
||||||
|
[& {:keys [id] :as options}]
|
||||||
|
(ptk/reify ::go-to-local-component
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [current-page-id (:current-page-id state)
|
||||||
|
|
||||||
|
select-and-zoom
|
||||||
|
(fn [shape-id]
|
||||||
|
(rx/of (dws/select-shapes (d/ordered-set shape-id))
|
||||||
|
dwz/zoom-to-selected-shape))
|
||||||
|
|
||||||
|
redirect-to-page
|
||||||
|
(fn [page-id shape-id]
|
||||||
|
(rx/merge
|
||||||
|
(rx/of (dcm/go-to-workspace :page-id page-id))
|
||||||
|
(->> stream
|
||||||
|
(rx/filter (ptk/type? ::initialize-page))
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/observe-on :async)
|
||||||
|
(rx/mapcat (fn [_] (select-and-zoom shape-id))))))]
|
||||||
|
|
||||||
|
(when-let [component (dm/get-in state [:workspace-data :components id])]
|
||||||
|
(let [page-id (:main-instance-page component)
|
||||||
|
shape-id (:main-instance-id component)]
|
||||||
|
(when (some? page-id)
|
||||||
|
(if (= page-id current-page-id)
|
||||||
|
(select-and-zoom shape-id)
|
||||||
|
(redirect-to-page page-id shape-id)))))))))
|
||||||
|
|
||||||
(defn library-thumbnails-fetched
|
(defn library-thumbnails-fetched
|
||||||
[thumbnails]
|
[thumbnails]
|
||||||
|
@ -1117,9 +1147,11 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(rp/cmd! :ignore-file-library-sync-status
|
(let [file-id (:current-file-id state)]
|
||||||
{:file-id (get-in state [:workspace-file :id])
|
(->> (rp/cmd! :ignore-file-library-sync-status
|
||||||
:date (dt/now)}))))
|
{:file-id file-id
|
||||||
|
:date (dt/now)})
|
||||||
|
(rx/ignore))))))
|
||||||
|
|
||||||
(defn assets-need-sync
|
(defn assets-need-sync
|
||||||
"Get a lazy sequence of all the assets of each type in the library that have
|
"Get a lazy sequence of all the assets of each type in the library that have
|
||||||
|
@ -1309,23 +1341,6 @@
|
||||||
(->> (rp/cmd! :set-file-shared params)
|
(->> (rp/cmd! :set-file-shared params)
|
||||||
(rx/ignore))))))
|
(rx/ignore))))))
|
||||||
|
|
||||||
(defn- shared-files-fetched
|
|
||||||
[files]
|
|
||||||
(ptk/reify ::shared-files-fetched
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [state (dissoc state :files)]
|
|
||||||
(assoc state :workspace-shared-files files)))))
|
|
||||||
|
|
||||||
(defn fetch-shared-files
|
|
||||||
[{:keys [team-id] :as params}]
|
|
||||||
(dm/assert! (uuid? team-id))
|
|
||||||
(ptk/reify ::fetch-shared-files
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
|
||||||
(rx/map shared-files-fetched)))))
|
|
||||||
|
|
||||||
;; --- Link and unlink Files
|
;; --- Link and unlink Files
|
||||||
|
|
||||||
(defn link-file-to-library
|
(defn link-file-to-library
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.plugins :as dpl]
|
[app.main.data.plugins :as dpl]
|
||||||
[app.main.data.websocket :as dws]
|
[app.main.data.websocket :as dws]
|
||||||
|
[app.main.data.workspace :as-alias dw]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.edition :as dwe]
|
[app.main.data.workspace.edition :as dwe]
|
||||||
[app.main.data.workspace.layout :as dwly]
|
[app.main.data.workspace.layout :as dwly]
|
||||||
|
@ -30,9 +31,6 @@
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
;; From app.main.data.workspace we can use directly because it causes a circular dependency
|
|
||||||
(def reload-file nil)
|
|
||||||
|
|
||||||
;; FIXME: this ns should be renamed to something different
|
;; FIXME: this ns should be renamed to something different
|
||||||
|
|
||||||
(declare process-message)
|
(declare process-message)
|
||||||
|
@ -292,7 +290,7 @@
|
||||||
curr-vern (dm/get-in state [:workspace-file :vern])
|
curr-vern (dm/get-in state [:workspace-file :vern])
|
||||||
reload? (and (= file-id curr-file-id) (not= vern curr-vern))]
|
reload? (and (= file-id curr-file-id) (not= vern curr-vern))]
|
||||||
(when reload?
|
(when reload?
|
||||||
(rx/of (reload-file)))))))
|
(rx/of (ptk/event ::dw/reload-current-file)))))))
|
||||||
|
|
||||||
(def ^:private schema:handle-library-change
|
(def ^:private schema:handle-library-change
|
||||||
[:map {:title "handle-library-change"}
|
[:map {:title "handle-library-change"}
|
||||||
|
|
|
@ -110,13 +110,15 @@
|
||||||
:undo-group undo-group})))
|
:undo-group undo-group})))
|
||||||
(rx/empty))))))
|
(rx/empty))))))
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize-shape-layout
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::initialize
|
(ptk/reify ::initialize-shape-layout
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ stream]
|
(watch [_ _ stream]
|
||||||
(let [stopper (rx/filter (ptk/type? ::finalize) stream)]
|
(let [stopper (rx/filter (ptk/type? ::finalize-shape-layout) stream)]
|
||||||
(->> stream
|
(->> stream
|
||||||
|
;; FIXME: we don't need use types for simple signaling,
|
||||||
|
;; we can just use a keyword for it
|
||||||
(rx/filter (ptk/type? :layout/update))
|
(rx/filter (ptk/type? :layout/update))
|
||||||
(rx/map deref)
|
(rx/map deref)
|
||||||
;; We buffer the updates to the layout so if there are many changes at the same time
|
;; We buffer the updates to the layout so if there are many changes at the same time
|
||||||
|
@ -129,9 +131,9 @@
|
||||||
(update-layout-positions {:ids ids}))))
|
(update-layout-positions {:ids ids}))))
|
||||||
(rx/take-until stopper))))))
|
(rx/take-until stopper))))))
|
||||||
|
|
||||||
(defn finalize
|
(defn finalize-shape-layout
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::finalize))
|
(ptk/data-event ::finalize-shape-layout))
|
||||||
|
|
||||||
(defn create-layout-from-id
|
(defn create-layout-from-id
|
||||||
[id type & {:keys [from-frame? calculate-params?] :or {from-frame? false calculate-params? true}}]
|
[id type & {:keys [from-frame? calculate-params?] :or {from-frame? false calculate-params? true}}]
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.data.workspace.shortcuts
|
(ns app.main.data.workspace.shortcuts
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.exports.assets :as de]
|
[app.main.data.exports.assets :as de]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
@ -440,17 +441,18 @@
|
||||||
:toggle-layers {:tooltip (ds/alt "L")
|
:toggle-layers {:tooltip (ds/alt "L")
|
||||||
:command (ds/a-mod "l")
|
:command (ds/a-mod "l")
|
||||||
:subsections [:panels]
|
:subsections [:panels]
|
||||||
:fn #(st/emit! (dw/go-to-layout :layers))}
|
:fn #(st/emit! (dcm/go-to-workspace :layout :layers))}
|
||||||
|
|
||||||
:toggle-assets {:tooltip (ds/alt "I")
|
:toggle-assets {:tooltip (ds/alt "I")
|
||||||
:command (ds/a-mod "i")
|
:command (ds/a-mod "i")
|
||||||
:subsections [:panels]
|
:subsections [:panels]
|
||||||
:fn #(st/emit! (dw/go-to-layout :assets))}
|
:fn #(st/emit! (dcm/go-to-workspace :layout :assets))}
|
||||||
|
|
||||||
:toggle-history {:tooltip (ds/alt "H")
|
:toggle-history {:tooltip (ds/alt "H")
|
||||||
:command (ds/a-mod "h")
|
:command (ds/a-mod "h")
|
||||||
:subsections [:panels]
|
:subsections [:panels]
|
||||||
:fn #(emit-when-no-readonly (dw/go-to-layout :document-history))}
|
:fn #(emit-when-no-readonly
|
||||||
|
(dcm/go-to-workspace :layout :document-history))}
|
||||||
|
|
||||||
:toggle-colorpalette {:tooltip (ds/alt "P")
|
:toggle-colorpalette {:tooltip (ds/alt "P")
|
||||||
:command (ds/a-mod "p")
|
:command (ds/a-mod "p")
|
||||||
|
@ -516,22 +518,22 @@
|
||||||
:open-viewer {:tooltip "G V"
|
:open-viewer {:tooltip "G V"
|
||||||
:command "g v"
|
:command "g v"
|
||||||
:subsections [:navigation-workspace]
|
:subsections [:navigation-workspace]
|
||||||
:fn #(st/emit! (dw/go-to-viewer))}
|
:fn #(st/emit! (dcm/go-to-viewer))}
|
||||||
|
|
||||||
:open-inspect {:tooltip "G I"
|
:open-inspect {:tooltip "G I"
|
||||||
:command "g i"
|
:command "g i"
|
||||||
:subsections [:navigation-workspace]
|
:subsections [:navigation-workspace]
|
||||||
:fn #(st/emit! (dw/go-to-viewer {:section :inspect}))}
|
:fn #(st/emit! (dcm/go-to-viewer :section :inspect))}
|
||||||
|
|
||||||
:open-comments {:tooltip "G C"
|
:open-comments {:tooltip "G C"
|
||||||
:command "g c"
|
:command "g c"
|
||||||
:subsections [:navigation-workspace]
|
:subsections [:navigation-workspace]
|
||||||
:fn #(st/emit! (dw/go-to-viewer {:section :comments}))}
|
:fn #(st/emit! (dcm/go-to-viewer :section :comments))}
|
||||||
|
|
||||||
:open-dashboard {:tooltip "G D"
|
:open-dashboard {:tooltip "G D"
|
||||||
:command "g d"
|
:command "g d"
|
||||||
:subsections [:navigation-workspace]
|
:subsections [:navigation-workspace]
|
||||||
:fn #(st/emit! (dw/go-to-dashboard))}
|
:fn #(st/emit! (dcm/go-to-dashboard-recent))}
|
||||||
|
|
||||||
:select-prev {:tooltip (ds/shift "tab")
|
:select-prev {:tooltip (ds/shift "tab")
|
||||||
:command "shift+tab"
|
:command "shift+tab"
|
||||||
|
|
|
@ -27,10 +27,6 @@
|
||||||
(-> (lookup-page state page-id)
|
(-> (lookup-page state page-id)
|
||||||
(get :objects))))
|
(get :objects))))
|
||||||
|
|
||||||
(defn lookup-viewer-objects
|
|
||||||
([state page-id]
|
|
||||||
(dm/get-in state [:viewer :pages page-id :objects])))
|
|
||||||
|
|
||||||
(defn lookup-library-objects
|
(defn lookup-library-objects
|
||||||
[state file-id page-id]
|
[state file-id page-id]
|
||||||
(dm/get-in state [:workspace-libraries file-id :data :pages-index page-id :objects]))
|
(dm/get-in state [:workspace-libraries file-id :data :pages-index page-id :objects]))
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.util.router :as rt]
|
[app.main.router :as rt]
|
||||||
[app.util.text-editor :as ted]
|
[app.util.text-editor :as ted]
|
||||||
[app.util.text.content.styles :as styles]
|
[app.util.text.content.styles :as styles]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
@ -290,14 +290,8 @@
|
||||||
(ptk/reify ::assure-valid-current-page
|
(ptk/reify ::assure-valid-current-page
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [current_page (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
pages (get-in state [:workspace-data :pages])
|
pages (dm/get-in state [:workspace-data :pages])]
|
||||||
exists? (some #(= current_page %) pages)
|
(if (contains? pages page-id)
|
||||||
|
|
||||||
project-id (:current-project-id state)
|
|
||||||
file-id (:current-file-id state)
|
|
||||||
pparams {:file-id file-id :project-id project-id}
|
|
||||||
qparams {:page-id (first pages)}]
|
|
||||||
(if exists?
|
|
||||||
(rx/empty)
|
(rx/empty)
|
||||||
(rx/of (rt/nav :workspace pparams qparams)))))))
|
(rx/of (dcm/go-to-workspace :page-id (first pages))))))))
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.schema :as sm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.persistence :as dwp]
|
[app.main.data.persistence :as dwp]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
(declare fetch-versions)
|
(declare fetch-versions)
|
||||||
|
|
||||||
(defn init-version-state
|
(defn init-version-state
|
||||||
[file-id]
|
[]
|
||||||
(ptk/reify ::init-version-state
|
(ptk/reify ::init-version-state
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -33,7 +34,7 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/of (fetch-versions file-id)))))
|
(rx/of (fetch-versions)))))
|
||||||
|
|
||||||
(defn update-version-state
|
(defn update-version-state
|
||||||
[version-state]
|
[version-state]
|
||||||
|
@ -43,123 +44,90 @@
|
||||||
(update state :workspace-versions merge version-state))))
|
(update state :workspace-versions merge version-state))))
|
||||||
|
|
||||||
(defn fetch-versions
|
(defn fetch-versions
|
||||||
[file-id]
|
[]
|
||||||
(dm/assert! (uuid? file-id))
|
|
||||||
(ptk/reify ::fetch-versions
|
(ptk/reify ::fetch-versions
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
|
(let [file-id (:current-file-id state)]
|
||||||
(->> (rp/cmd! :get-file-snapshots {:file-id file-id})
|
(->> (rp/cmd! :get-file-snapshots {:file-id file-id})
|
||||||
(rx/map #(update-version-state {:status :loaded :data %}))))))
|
(rx/map #(update-version-state {:status :loaded :data %})))))))
|
||||||
|
|
||||||
(defn create-version
|
(defn create-version
|
||||||
[file-id]
|
[]
|
||||||
(dm/assert! (uuid? file-id))
|
|
||||||
(ptk/reify ::create-version
|
(ptk/reify ::create-version
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
(let [label (dt/format (dt/now) :date-full)]
|
(let [label (dt/format (dt/now) :date-full)
|
||||||
|
file-id (:current-file-id state)]
|
||||||
|
|
||||||
;; Force persist before creating snapshot, otherwise we could loss changes
|
;; Force persist before creating snapshot, otherwise we could loss changes
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of ::dwp/force-persist)
|
(rx/of ::dwp/force-persist
|
||||||
|
(ptk/event ::ev/event {::ev/name "create-version"}))
|
||||||
|
|
||||||
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
||||||
(rx/filter #(or (nil? %) (= :saved %)))
|
(rx/filter #(or (nil? %) (= :saved %)))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/mapcat #(rp/cmd! :create-file-snapshot {:file-id file-id :label label}))
|
(rx/mapcat #(rp/cmd! :create-file-snapshot {:file-id file-id :label label}))
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [{:keys [id]}]
|
(fn [{:keys [id]}]
|
||||||
(rx/of
|
(rx/of (update-version-state {:editing id})
|
||||||
(update-version-state {:editing id})
|
(fetch-versions))))))))))
|
||||||
(fetch-versions file-id)))))
|
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "create-version"})))))))
|
|
||||||
|
|
||||||
(defn create-version-from-plugins
|
|
||||||
[file-id label resolve reject]
|
|
||||||
(dm/assert! (uuid? file-id))
|
|
||||||
(ptk/reify ::create-version-plugins
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ _ _]
|
|
||||||
;; Force persist before creating snapshot, otherwise we could loss changes
|
|
||||||
(->> (rx/concat
|
|
||||||
(rx/of ::dwp/force-persist)
|
|
||||||
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
|
||||||
(rx/filter #(or (nil? %) (= :saved %)))
|
|
||||||
(rx/take 1)
|
|
||||||
(rx/mapcat #(rp/cmd! :create-file-snapshot {:file-id file-id :label label}))
|
|
||||||
|
|
||||||
(rx/mapcat
|
|
||||||
(fn [{:keys [id]}]
|
|
||||||
(->> (rp/cmd! :get-file-snapshots {:file-id file-id})
|
|
||||||
(rx/take 1)
|
|
||||||
(rx/map (fn [versions] (d/seek #(= id (:id %)) versions))))))
|
|
||||||
(rx/tap resolve)
|
|
||||||
(rx/ignore))
|
|
||||||
(rx/of (ptk/event ::ev/event {::ev/origin "plugins"
|
|
||||||
::ev/name "create-version"})))
|
|
||||||
|
|
||||||
;; On error reject the promise and empty the stream
|
|
||||||
(rx/catch (fn [error]
|
|
||||||
(reject error)
|
|
||||||
(rx/empty)))))))
|
|
||||||
|
|
||||||
(defn rename-version
|
(defn rename-version
|
||||||
[file-id id label]
|
[id label]
|
||||||
(dm/assert! (uuid? file-id))
|
(assert (uuid? id) "expected valid uuid for `id`")
|
||||||
(dm/assert! (uuid? id))
|
(assert (sm/valid-text? label) "expected not empty string for `label`")
|
||||||
(dm/assert! (and (string? label) (d/not-empty? label)))
|
|
||||||
|
|
||||||
(ptk/reify ::rename-version
|
(ptk/reify ::rename-version
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
|
(let [file-id (:current-file-id state)]
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (update-version-state {:editing false}))
|
(rx/of (update-version-state {:editing false})
|
||||||
|
(ptk/event ::ev/event {::ev/name "rename-version"
|
||||||
|
:file-id file-id}))
|
||||||
(->> (rp/cmd! :update-file-snapshot {:id id :label label})
|
(->> (rp/cmd! :update-file-snapshot {:id id :label label})
|
||||||
(rx/map #(fetch-versions file-id)))
|
(rx/map fetch-versions)))))))
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "rename-version"}))))))
|
|
||||||
|
|
||||||
(defn restore-version
|
(defn restore-version
|
||||||
[project-id file-id id origin]
|
[id origin]
|
||||||
(dm/assert! (uuid? project-id))
|
(assert (uuid? id) "expected valid uuid for `id`")
|
||||||
(dm/assert! (uuid? file-id))
|
|
||||||
(dm/assert! (uuid? id))
|
|
||||||
|
|
||||||
(ptk/reify ::restore-version
|
(ptk/reify ::restore-version
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ state _]
|
||||||
|
(let [file-id (:current-file-id state)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of ::dwp/force-persist)
|
(rx/of ::dwp/force-persist)
|
||||||
|
|
||||||
|
;; FIXME: we should abstract this
|
||||||
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
||||||
(rx/filter #(or (nil? %) (= :saved %)))
|
(rx/filter #(or (nil? %) (= :saved %)))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
|
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
|
||||||
(rx/map #(dw/initialize-file project-id file-id)))
|
(rx/map #(dw/initialize-workspace file-id)))
|
||||||
(case origin
|
|
||||||
:version
|
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "restore-pin-version"}))
|
|
||||||
|
|
||||||
:snapshot
|
(when-let [name (case origin
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "restore-autosave"}))
|
:version "restore-pin-version"
|
||||||
|
:snapshot "restore-autosave"
|
||||||
:plugin
|
:plugin "restore-version-plugin"
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "restore-version-plugin"}))
|
nil)]
|
||||||
|
(rx/of (ptk/event ::ev/event {::ev/name name}))))))))
|
||||||
(rx/empty))))))
|
|
||||||
|
|
||||||
(defn delete-version
|
(defn delete-version
|
||||||
[file-id id]
|
[id]
|
||||||
(dm/assert! (uuid? file-id))
|
(assert (uuid? id) "expected valid uuid for `id`")
|
||||||
(dm/assert! (uuid? id))
|
|
||||||
|
|
||||||
(ptk/reify ::delete-version
|
(ptk/reify ::delete-version
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(->> (rp/cmd! :delete-file-snapshot {:id id})
|
(->> (rp/cmd! :delete-file-snapshot {:id id})
|
||||||
(rx/map #(fetch-versions file-id))))))
|
(rx/map fetch-versions)))))
|
||||||
|
|
||||||
(defn pin-version
|
(defn pin-version
|
||||||
[file-id id]
|
[id]
|
||||||
(dm/assert! (uuid? file-id))
|
(assert (uuid? id) "expected valid uuid for `id`")
|
||||||
(dm/assert! (uuid? id))
|
|
||||||
|
|
||||||
(ptk/reify ::pin-version
|
(ptk/reify ::pin-version
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
|
@ -168,8 +136,82 @@
|
||||||
params {:id id
|
params {:id id
|
||||||
:label (dt/format (:created-at version) :date-full)}]
|
:label (dt/format (:created-at version) :date-full)}]
|
||||||
|
|
||||||
(rx/concat
|
|
||||||
(->> (rp/cmd! :update-file-snapshot params)
|
(->> (rp/cmd! :update-file-snapshot params)
|
||||||
(rx/mapcat #(rx/of (update-version-state {:editing id})
|
(rx/mapcat (fn [_]
|
||||||
(fetch-versions file-id))))
|
(rx/of (update-version-state {:editing id})
|
||||||
(rx/of (ptk/event ::ev/event {::ev/name "pin-version"})))))))
|
(fetch-versions)
|
||||||
|
(ptk/event ::ev/event {::ev/name "pin-version"})))))))))
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; PLUGINS SPECIFIC EVENTS
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn- wait-persisted-status
|
||||||
|
[]
|
||||||
|
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
||||||
|
(rx/filter #(or (nil? %) (= :saved %)))
|
||||||
|
(rx/take 1)))
|
||||||
|
|
||||||
|
(defn create-version-from-plugins
|
||||||
|
[file-id label resolve reject]
|
||||||
|
|
||||||
|
(assert (uuid? file-id) "expected valid uuid for `file-id`")
|
||||||
|
(assert (sm/valid-text? label) "expected not empty string for `label`")
|
||||||
|
|
||||||
|
(ptk/reify ::create-version-from-plugins
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [current-file-id (:current-file-id state)]
|
||||||
|
;; Force persist before creating snapshot, otherwise we could loss changes
|
||||||
|
(->> (rx/concat
|
||||||
|
(rx/of (ptk/event ::ev/event {::ev/origin "plugins"
|
||||||
|
::ev/name "create-version"}))
|
||||||
|
|
||||||
|
(when (= file-id current-file-id)
|
||||||
|
(rx/of ::dwp/force-persist))
|
||||||
|
|
||||||
|
(->> (if (= file-id current-file-id)
|
||||||
|
(wait-persisted-status)
|
||||||
|
(rx/of :nothing))
|
||||||
|
(rx/mapcat
|
||||||
|
(fn [_]
|
||||||
|
(rp/cmd! :create-file-snapshot {:file-id file-id :label label})))
|
||||||
|
(rx/mapcat
|
||||||
|
(fn [{:keys [id]}]
|
||||||
|
(->> (rp/cmd! :get-file-snapshots {:file-id file-id})
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map (fn [versions] (d/seek #(= id (:id %)) versions))))))
|
||||||
|
(rx/tap resolve)
|
||||||
|
(rx/ignore)))
|
||||||
|
|
||||||
|
;; On error reject the promise and empty the stream
|
||||||
|
(rx/catch (fn [error]
|
||||||
|
(reject error)
|
||||||
|
(rx/empty))))))))
|
||||||
|
|
||||||
|
(defn restore-version-from-plugin
|
||||||
|
[file-id id resolve _reject]
|
||||||
|
(assert (uuid? id) "expected valid uuid for `id`")
|
||||||
|
|
||||||
|
(ptk/reify ::restore-version-from-plugins
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(rx/concat
|
||||||
|
(rx/of (ptk/event ::ev/event {::ev/name "restore-version-plugin"})
|
||||||
|
::dwp/force-persist)
|
||||||
|
|
||||||
|
;; FIXME: we should abstract this
|
||||||
|
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
|
||||||
|
(rx/filter #(or (nil? %) (= :saved %)))
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
|
||||||
|
(rx/map #(dw/initialize-workspace file-id)))
|
||||||
|
|
||||||
|
(->> (rx/of 1)
|
||||||
|
(rx/tap resolve)
|
||||||
|
(rx/ignore))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,11 @@
|
||||||
[app.main.data.auth :as da]
|
[app.main.data.auth :as da]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
[app.main.data.workspace :as-alias dw]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.globals :as glob]
|
[app.util.globals :as glob]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
@ -141,7 +142,7 @@
|
||||||
:timeout 3000})))
|
:timeout 3000})))
|
||||||
|
|
||||||
(= code :vern-conflict)
|
(= code :vern-conflict)
|
||||||
(st/emit! (reload-file))
|
(st/emit! (ptk/event ::dw/reload-current-file))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/async-emit! (rt/assign-exception error))))
|
(st/async-emit! (rt/assign-exception error))))
|
||||||
|
@ -212,7 +213,6 @@
|
||||||
(ts/schedule
|
(ts/schedule
|
||||||
#(st/emit! (rt/assign-exception error))))
|
#(st/emit! (rt/assign-exception error))))
|
||||||
|
|
||||||
|
|
||||||
(defn- redirect-to-dashboard
|
(defn- redirect-to-dashboard
|
||||||
[]
|
[]
|
||||||
(let [team-id (:current-team-id @st/state)
|
(let [team-id (:current-team-id @st/state)
|
||||||
|
|
|
@ -22,13 +22,13 @@
|
||||||
;; ---- Global refs
|
;; ---- Global refs
|
||||||
|
|
||||||
(def route
|
(def route
|
||||||
(l/derived :route st/state))
|
(l/derived (l/key :route) st/state))
|
||||||
|
|
||||||
(def router
|
(def router
|
||||||
(l/derived :router st/state))
|
(l/derived (l/key :router) st/state))
|
||||||
|
|
||||||
(def profile
|
(def profile
|
||||||
(l/derived :profile st/state))
|
(l/derived (l/key :profile) st/state))
|
||||||
|
|
||||||
(def team
|
(def team
|
||||||
(l/derived (fn [state]
|
(l/derived (fn [state]
|
||||||
|
@ -37,11 +37,18 @@
|
||||||
(get teams team-id)))
|
(get teams team-id)))
|
||||||
st/state))
|
st/state))
|
||||||
|
|
||||||
|
(def project
|
||||||
|
(l/derived (fn [state]
|
||||||
|
(let [project-id (:current-project-id state)
|
||||||
|
projects (:projects state)]
|
||||||
|
(get projects project-id)))
|
||||||
|
st/state))
|
||||||
|
|
||||||
(def permissions
|
(def permissions
|
||||||
(l/derived :permissions team))
|
(l/derived (l/key :permissions) team))
|
||||||
|
|
||||||
(def teams
|
(def teams
|
||||||
(l/derived :teams st/state))
|
(l/derived (l/key :teams) st/state))
|
||||||
|
|
||||||
(def exception
|
(def exception
|
||||||
(l/derived :exception st/state))
|
(l/derived :exception st/state))
|
||||||
|
@ -65,8 +72,13 @@
|
||||||
(l/derived :files st/state))
|
(l/derived :files st/state))
|
||||||
|
|
||||||
(def shared-files
|
(def shared-files
|
||||||
|
"A derived state that points to the current list of shared
|
||||||
|
files (without the content, only summary)"
|
||||||
(l/derived :shared-files st/state))
|
(l/derived :shared-files st/state))
|
||||||
|
|
||||||
|
(def libraries
|
||||||
|
(l/derived :libraries st/state))
|
||||||
|
|
||||||
(defn extract-selected-files
|
(defn extract-selected-files
|
||||||
[files selected]
|
[files selected]
|
||||||
(let [get-file #(get files %)
|
(let [get-file #(get files %)
|
||||||
|
@ -86,7 +98,6 @@
|
||||||
(def selected-project
|
(def selected-project
|
||||||
(l/derived :selected-project st/state))
|
(l/derived :selected-project st/state))
|
||||||
|
|
||||||
|
|
||||||
(def dashboard-local
|
(def dashboard-local
|
||||||
(l/derived :dashboard-local st/state))
|
(l/derived :dashboard-local st/state))
|
||||||
|
|
||||||
|
@ -243,12 +254,6 @@
|
||||||
(def workspace-file-typography
|
(def workspace-file-typography
|
||||||
(l/derived :typographies workspace-data))
|
(l/derived :typographies workspace-data))
|
||||||
|
|
||||||
(def workspace-project
|
|
||||||
(l/derived :workspace-project st/state))
|
|
||||||
|
|
||||||
(def workspace-shared-files
|
|
||||||
(l/derived :workspace-shared-files st/state))
|
|
||||||
|
|
||||||
(def workspace-local-library
|
(def workspace-local-library
|
||||||
(l/derived (fn [state]
|
(l/derived (fn [state]
|
||||||
(select-keys (:workspace-data state)
|
(select-keys (:workspace-data state)
|
||||||
|
@ -505,12 +510,16 @@
|
||||||
|
|
||||||
;; ---- Viewer refs
|
;; ---- Viewer refs
|
||||||
|
|
||||||
|
(defn get-viewer-objects
|
||||||
|
[state page-id]
|
||||||
|
(dm/get-in state [:viewer :pages page-id :objects]))
|
||||||
|
|
||||||
(defn lookup-viewer-objects-by-id
|
(defn lookup-viewer-objects-by-id
|
||||||
[page-id]
|
[page-id]
|
||||||
(l/derived #(wsh/lookup-viewer-objects % page-id) st/state =))
|
(l/derived #(get-viewer-objects % page-id) st/state =))
|
||||||
|
|
||||||
(def viewer-data
|
(def viewer-data
|
||||||
(l/derived :viewer st/state))
|
(l/derived (l/key :viewer) st/state))
|
||||||
|
|
||||||
(def viewer-file
|
(def viewer-file
|
||||||
(l/derived :file viewer-data))
|
(l/derived :file viewer-data))
|
||||||
|
@ -536,14 +545,8 @@
|
||||||
(def comments-local
|
(def comments-local
|
||||||
(l/derived :comments-local st/state))
|
(l/derived :comments-local st/state))
|
||||||
|
|
||||||
(def users
|
(def profiles
|
||||||
(l/derived :users st/state))
|
(l/derived :profiles st/state))
|
||||||
|
|
||||||
(def current-file-comments-users
|
|
||||||
(l/derived :current-file-comments-users st/state))
|
|
||||||
|
|
||||||
(def current-team-comments-users
|
|
||||||
(l/derived :current-team-comments-users st/state))
|
|
||||||
|
|
||||||
(def viewer-fullscreen?
|
(def viewer-fullscreen?
|
||||||
(l/derived (fn [state]
|
(l/derived (fn [state]
|
||||||
|
@ -555,14 +558,11 @@
|
||||||
(dm/get-in state [:viewer-local :zoom-type]))
|
(dm/get-in state [:viewer-local :zoom-type]))
|
||||||
st/state))
|
st/state))
|
||||||
|
|
||||||
(def workspace-thumbnails
|
|
||||||
(l/derived :workspace-thumbnails st/state))
|
|
||||||
|
|
||||||
(defn workspace-thumbnail-by-id
|
(defn workspace-thumbnail-by-id
|
||||||
[object-id]
|
[object-id]
|
||||||
(l/derived
|
(l/derived
|
||||||
(fn [state]
|
(fn [state]
|
||||||
(some-> (dm/get-in state [:workspace-thumbnails object-id])
|
(some-> (dm/get-in state [:thumbnails object-id])
|
||||||
(cf/resolve-media)))
|
(cf/resolve-media)))
|
||||||
st/state))
|
st/state))
|
||||||
|
|
||||||
|
@ -608,35 +608,9 @@
|
||||||
(every? (partial ctl/grid-layout-immediate-child? objects))))
|
(every? (partial ctl/grid-layout-immediate-child? objects))))
|
||||||
workspace-page-objects =))
|
workspace-page-objects =))
|
||||||
|
|
||||||
;; FIXME: move to viewer.inspect.code
|
|
||||||
(defn get-flex-child-viewer
|
|
||||||
[ids page-id]
|
|
||||||
(l/derived
|
|
||||||
(fn [state]
|
|
||||||
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
|
||||||
(into []
|
|
||||||
(comp (map (d/getf objects))
|
|
||||||
(filter (partial ctl/flex-layout-immediate-child? objects)))
|
|
||||||
ids)))
|
|
||||||
st/state =))
|
|
||||||
|
|
||||||
;; FIXME: move to viewer.inspect.code
|
|
||||||
(defn get-viewer-objects
|
|
||||||
([]
|
|
||||||
(let [route (deref route)
|
|
||||||
page-id (:page-id (:query-params route))]
|
|
||||||
(get-viewer-objects page-id)))
|
|
||||||
([page-id]
|
|
||||||
(l/derived
|
|
||||||
(fn [state]
|
|
||||||
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
|
||||||
objects))
|
|
||||||
st/state =)))
|
|
||||||
|
|
||||||
(def colorpicker
|
(def colorpicker
|
||||||
(l/derived :colorpicker st/state))
|
(l/derived :colorpicker st/state))
|
||||||
|
|
||||||
|
|
||||||
(def workspace-grid-edition
|
(def workspace-grid-edition
|
||||||
(l/derived :workspace-grid-edition st/state))
|
(l/derived :workspace-grid-edition st/state))
|
||||||
|
|
||||||
|
@ -644,6 +618,7 @@
|
||||||
[id]
|
[id]
|
||||||
(l/derived #(get % id) workspace-grid-edition))
|
(l/derived #(get % id) workspace-grid-edition))
|
||||||
|
|
||||||
|
;; FIXME: remove
|
||||||
(def current-file-id
|
(def current-file-id
|
||||||
(l/derived :current-file-id st/state))
|
(l/derived :current-file-id st/state))
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) KALEIDOS INC
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
(ns app.util.router
|
(ns app.main.router
|
||||||
(:refer-clojure :exclude [resolve])
|
(:refer-clojure :exclude [resolve])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
@ -28,11 +28,10 @@
|
||||||
(r/map->Match data))
|
(r/map->Match data))
|
||||||
|
|
||||||
(defn resolve
|
(defn resolve
|
||||||
([router id] (resolve router id {} {}))
|
([router id] (resolve router id {}))
|
||||||
([router id path-params] (resolve router id path-params {}))
|
([router id params]
|
||||||
([router id path-params query-params]
|
(when-let [match (r/match-by-name router id)]
|
||||||
(when-let [match (r/match-by-name router id path-params)]
|
(r/match->path match params))))
|
||||||
(r/match->path match query-params))))
|
|
||||||
|
|
||||||
(defn create
|
(defn create
|
||||||
[routes]
|
[routes]
|
||||||
|
@ -63,6 +62,9 @@
|
||||||
(defn navigated
|
(defn navigated
|
||||||
[match]
|
[match]
|
||||||
(ptk/reify ::navigated
|
(ptk/reify ::navigated
|
||||||
|
IDeref
|
||||||
|
(-deref [_] match)
|
||||||
|
|
||||||
ev/Event
|
ev/Event
|
||||||
(-data [_]
|
(-data [_]
|
||||||
(let [route (dm/get-in match [:data :name])
|
(let [route (dm/get-in match [:data :name])
|
||||||
|
@ -77,25 +79,29 @@
|
||||||
(assoc :route match)
|
(assoc :route match)
|
||||||
(dissoc :exception)))))
|
(dissoc :exception)))))
|
||||||
|
|
||||||
(defn navigate*
|
(defn navigate
|
||||||
[id path-params query-params replace]
|
[id params & {:keys [::replace ::new-window] :as options}]
|
||||||
(ptk/reify ::navigate
|
(ptk/reify ::navigate
|
||||||
IDeref
|
IDeref
|
||||||
(-deref [_]
|
(-deref [_]
|
||||||
{:id id
|
{:id id
|
||||||
:path-params path-params
|
:params params
|
||||||
:query-params query-params
|
:options options})
|
||||||
:replace replace})
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ state _]
|
(effect [_ state _]
|
||||||
(let [router (:router state)
|
(let [router (:router state)
|
||||||
history (:history state)
|
history (:history state)
|
||||||
path (resolve router id path-params query-params)]
|
path (resolve router id params)]
|
||||||
|
|
||||||
|
(if ^boolean new-window
|
||||||
|
(let [name (or (::window-name options) "_blank")
|
||||||
|
uri (assoc cf/public-uri :fragment path)]
|
||||||
|
(dom/open-new-window uri name nil))
|
||||||
(ts/asap
|
(ts/asap
|
||||||
#(if ^boolean replace
|
#(if ^boolean replace
|
||||||
(bhistory/replace-token! history path)
|
(bhistory/replace-token! history path)
|
||||||
(bhistory/set-token! history path)))))))
|
(bhistory/set-token! history path))))))))
|
||||||
|
|
||||||
(defn assign-exception
|
(defn assign-exception
|
||||||
[error]
|
[error]
|
||||||
|
@ -107,27 +113,14 @@
|
||||||
(assoc state :exception error)))))
|
(assoc state :exception error)))))
|
||||||
|
|
||||||
(defn nav
|
(defn nav
|
||||||
([id] (nav id nil nil))
|
([id] (navigate id nil))
|
||||||
([id path-params] (nav id path-params nil))
|
([id params] (navigate id params))
|
||||||
([id path-params query-params] (navigate* id path-params query-params false)))
|
([id params & {:as options}]
|
||||||
|
(navigate id params options)))
|
||||||
|
|
||||||
(defn nav'
|
(defn get-params
|
||||||
([id] (nav id nil nil))
|
[state]
|
||||||
([id path-params] (nav id path-params nil))
|
(dm/get-in state [:route :params :query]))
|
||||||
([id path-params query-params] (navigate* id path-params query-params true)))
|
|
||||||
|
|
||||||
(def navigate nav)
|
|
||||||
|
|
||||||
(defn nav-new-window*
|
|
||||||
[{:keys [rname path-params query-params name]}]
|
|
||||||
(ptk/reify ::nav-new-window
|
|
||||||
ptk/EffectEvent
|
|
||||||
(effect [_ state _]
|
|
||||||
(let [router (:router state)
|
|
||||||
path (resolve router rname path-params query-params)
|
|
||||||
name (or name "_blank")
|
|
||||||
uri (assoc cf/public-uri :fragment path)]
|
|
||||||
(dom/open-new-window uri name nil)))))
|
|
||||||
|
|
||||||
(defn nav-back
|
(defn nav-back
|
||||||
[]
|
[]
|
|
@ -60,7 +60,7 @@
|
||||||
:app.main.data.workspace.persistence/update-persistence-status
|
:app.main.data.workspace.persistence/update-persistence-status
|
||||||
:app.main.data.websocket/send-message
|
:app.main.data.websocket/send-message
|
||||||
:app.main.data.workspace.notifications/handle-pointer-send
|
:app.main.data.workspace.notifications/handle-pointer-send
|
||||||
:app.util.router/assign-exception}]
|
:app.main.router/assign-exception}]
|
||||||
(->> (rx/merge
|
(->> (rx/merge
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter (ptk/type? :app.main.data.changes/commit))
|
(rx/filter (ptk/type? :app.main.data.changes/commit))
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
(mf/lazy-component app.main.ui.auth.verify-token/verify-token))
|
(mf/lazy-component app.main.ui.auth.verify-token/verify-token))
|
||||||
|
|
||||||
(def viewer-page
|
(def viewer-page
|
||||||
(mf/lazy-component app.main.ui.viewer/viewer))
|
(mf/lazy-component app.main.ui.viewer/viewer*))
|
||||||
|
|
||||||
(def dashboard-page
|
(def dashboard-page
|
||||||
(mf/lazy-component app.main.ui.dashboard/dashboard*))
|
(mf/lazy-component app.main.ui.dashboard/dashboard*))
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
(mf/lazy-component app.main.ui.settings/settings))
|
(mf/lazy-component app.main.ui.settings/settings))
|
||||||
|
|
||||||
(def workspace-page
|
(def workspace-page
|
||||||
(mf/lazy-component app.main.ui.workspace/workspace))
|
(mf/lazy-component app.main.ui.workspace/workspace*))
|
||||||
|
|
||||||
(mf/defc team-container*
|
(mf/defc team-container*
|
||||||
{::mf/props :obj
|
{::mf/props :obj
|
||||||
|
@ -62,13 +62,13 @@
|
||||||
;; all dom tree instead of simple rerender.
|
;; all dom tree instead of simple rerender.
|
||||||
[:* {:key (str team-id)} children]]])))
|
[:* {:key (str team-id)} children]]])))
|
||||||
|
|
||||||
(mf/defc page-container*
|
(mf/defc page*
|
||||||
{::mf/props :obj
|
{::mf/props :obj
|
||||||
::mf/private true}
|
::mf/private true}
|
||||||
[{:keys [route profile]}]
|
[{:keys [route profile]}]
|
||||||
(let [{:keys [data params]} route
|
(let [{:keys [data params]} route
|
||||||
props (get profile :props)
|
props (get profile :props)
|
||||||
route-name (get data :name)
|
section (get data :name)
|
||||||
|
|
||||||
|
|
||||||
show-question-modal?
|
show-question-modal?
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
(not= "0.0" (:main cf/version)))]
|
(not= "0.0" (:main cf/version)))]
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-route) {:value route}
|
[:& (mf/provider ctx/current-route) {:value route}
|
||||||
(case route-name
|
(case section
|
||||||
(:auth-login
|
(:auth-login
|
||||||
:auth-register
|
:auth-register
|
||||||
:auth-register-validate
|
:auth-register-validate
|
||||||
|
@ -119,20 +119,20 @@
|
||||||
[:& icons-preview])
|
[:& icons-preview])
|
||||||
|
|
||||||
(:dashboard-search
|
(:dashboard-search
|
||||||
:dashboard-projects
|
:dashboard-recent
|
||||||
:dashboard-files
|
:dashboard-files
|
||||||
:dashboard-libraries
|
:dashboard-libraries
|
||||||
:dashboard-fonts
|
:dashboard-fonts
|
||||||
:dashboard-font-providers
|
:dashboard-font-providers
|
||||||
:dashboard-team-members
|
:dashboard-members
|
||||||
:dashboard-team-invitations
|
:dashboard-invitations
|
||||||
:dashboard-team-webhooks
|
:dashboard-webhooks
|
||||||
:dashboard-team-settings)
|
:dashboard-settings)
|
||||||
(let [team-id (some-> params :path :team-id uuid)
|
(let [params (get params :query)
|
||||||
project-id (some-> params :path :project-id uuid)
|
team-id (some-> params :team-id uuid)
|
||||||
search-term (some-> params :query :search-term)
|
project-id (some-> params :project-id uuid)
|
||||||
plugin-url (some-> params :query :plugin)]
|
search-term (some-> params :search-term)
|
||||||
|
plugin-url (some-> params :plugin)]
|
||||||
[:?
|
[:?
|
||||||
#_[:& app.main.ui.releases/release-notes-modal {:version "2.3"}]
|
#_[:& app.main.ui.releases/release-notes-modal {:version "2.3"}]
|
||||||
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
||||||
|
@ -154,13 +154,105 @@
|
||||||
|
|
||||||
[:> team-container* {:team-id team-id}
|
[:> team-container* {:team-id team-id}
|
||||||
[:> dashboard-page {:profile profile
|
[:> dashboard-page {:profile profile
|
||||||
:route-name route-name
|
:section section
|
||||||
|
:team-id team-id
|
||||||
|
:search-term search-term
|
||||||
|
:plugin-url plugin-url
|
||||||
|
:project-id project-id}]]])
|
||||||
|
|
||||||
|
(:dashboard-legacy-search
|
||||||
|
:dashboard-legacy-projects
|
||||||
|
:dashboard-legacy-files
|
||||||
|
:dashboard-legacy-libraries
|
||||||
|
:dashboard-legacy-fonts
|
||||||
|
:dashboard-legacy-font-providers
|
||||||
|
:dashboard-legacy-team-members
|
||||||
|
:dashboard-legacy-team-invitations
|
||||||
|
:dashboard-legacy-team-webhooks
|
||||||
|
:dashboard-legacy-team-settings)
|
||||||
|
(let [team-id (some-> params :path :team-id uuid)
|
||||||
|
project-id (some-> params :path :project-id uuid)
|
||||||
|
search-term (some-> params :query :search-term)
|
||||||
|
plugin-url (some-> params :query :plugin)
|
||||||
|
section (case section
|
||||||
|
:dashboard-legacy-search
|
||||||
|
:dashboard-search
|
||||||
|
:dashboard-legacy-projects
|
||||||
|
:dashboard-recent
|
||||||
|
:dashboard-legacy-files
|
||||||
|
:dashboard-files
|
||||||
|
:dashboard-legacy-libraries
|
||||||
|
:dashboard-libraries
|
||||||
|
:dashboard-legacy-fonts
|
||||||
|
:dashboard-fonts
|
||||||
|
:dashboard-legacy-font-providers
|
||||||
|
:dashboard-font-providers
|
||||||
|
:dashboard-legacy-team-members
|
||||||
|
:dashboard-members
|
||||||
|
:dashboard-legacy-team-invitations
|
||||||
|
:dashboard-invitations
|
||||||
|
:dashboard-legacy-team-webhooks
|
||||||
|
:dashboard-webhooks
|
||||||
|
:dashboard-legacy-team-settings
|
||||||
|
:dashboard-settings)]
|
||||||
|
[:?
|
||||||
|
#_[:& app.main.ui.releases/release-notes-modal {:version "2.3"}]
|
||||||
|
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
||||||
|
#_[:& app.main.ui.onboarding/onboarding-modal]
|
||||||
|
#_[:& app.main.ui.onboarding.team-choice/onboarding-team-modal]
|
||||||
|
|
||||||
|
(cond
|
||||||
|
show-question-modal?
|
||||||
|
[:& questions-modal]
|
||||||
|
|
||||||
|
show-newsletter-modal?
|
||||||
|
[:& onboarding-newsletter]
|
||||||
|
|
||||||
|
show-team-modal?
|
||||||
|
[:& onboarding-team-modal {:go-to-team? true}]
|
||||||
|
|
||||||
|
show-release-modal?
|
||||||
|
[:& release-notes-modal {:version (:main cf/version)}])
|
||||||
|
|
||||||
|
[:> team-container* {:team-id team-id}
|
||||||
|
[:> dashboard-page {:profile profile
|
||||||
|
:section section
|
||||||
:team-id team-id
|
:team-id team-id
|
||||||
:search-term search-term
|
:search-term search-term
|
||||||
:plugin-url plugin-url
|
:plugin-url plugin-url
|
||||||
:project-id project-id}]]])
|
:project-id project-id}]]])
|
||||||
|
|
||||||
:workspace
|
:workspace
|
||||||
|
(let [params (get params :query)
|
||||||
|
team-id (some-> params :team-id uuid)
|
||||||
|
project-id (some-> params :project-id uuid)
|
||||||
|
file-id (some-> params :file-id uuid)
|
||||||
|
page-id (some-> params :page-id uuid)
|
||||||
|
layout (some-> params :layout keyword)]
|
||||||
|
[:? {}
|
||||||
|
(when (cf/external-feature-flag "onboarding-03" "test")
|
||||||
|
(cond
|
||||||
|
show-question-modal?
|
||||||
|
[:& questions-modal]
|
||||||
|
|
||||||
|
show-newsletter-modal?
|
||||||
|
[:& onboarding-newsletter]
|
||||||
|
|
||||||
|
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 {:project-id project-id
|
||||||
|
:team-id team-id
|
||||||
|
:file-id file-id
|
||||||
|
:page-id page-id
|
||||||
|
:layout-name layout
|
||||||
|
:key file-id}]]])
|
||||||
|
|
||||||
|
:workspace-legacy
|
||||||
(let [project-id (some-> params :path :project-id uuid)
|
(let [project-id (some-> params :path :project-id uuid)
|
||||||
file-id (some-> params :path :file-id uuid)
|
file-id (some-> params :path :file-id uuid)
|
||||||
page-id (some-> params :query :page-id uuid)
|
page-id (some-> params :query :page-id uuid)
|
||||||
|
@ -181,14 +273,38 @@
|
||||||
[:& release-notes-modal {:version (:main cf/version)}]))
|
[:& release-notes-modal {:version (:main cf/version)}]))
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:& workspace-page {:project-id project-id
|
[:> workspace-page {:project-id project-id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:layout-name layout
|
:layout-name layout
|
||||||
:key file-id}]]])
|
:key file-id}]]])
|
||||||
|
|
||||||
|
|
||||||
:viewer
|
:viewer
|
||||||
|
(let [params (get params :query)
|
||||||
|
index (some-> (:index params) parse-long)
|
||||||
|
share-id (some-> (:share-id params) parse-uuid)
|
||||||
|
section (or (some-> (:section params) keyword)
|
||||||
|
:interactions)
|
||||||
|
|
||||||
|
file-id (some-> (:file-id params) parse-uuid)
|
||||||
|
page-id (some-> (:page-id params) parse-uuid)
|
||||||
|
imode (or (some-> (:interactions-mode params) keyword)
|
||||||
|
:show-on-click)
|
||||||
|
frame-id (some-> (:frame-id params) parse-uuid)
|
||||||
|
share (:share params)]
|
||||||
|
|
||||||
|
[:? {}
|
||||||
|
[:> viewer-page
|
||||||
|
{:page-id page-id
|
||||||
|
:file-id file-id
|
||||||
|
:frame-id frame-id
|
||||||
|
:section section
|
||||||
|
:index index
|
||||||
|
:share-id share-id
|
||||||
|
:interactions-mode imode
|
||||||
|
:share share}]])
|
||||||
|
|
||||||
|
:viewer-legacy
|
||||||
(let [{:keys [query-params path-params]} route
|
(let [{:keys [query-params path-params]} route
|
||||||
{:keys [index share-id section page-id interactions-mode frame-id share]
|
{:keys [index share-id section page-id interactions-mode frame-id share]
|
||||||
:or {section :interactions interactions-mode :show-on-click}} query-params
|
:or {section :interactions interactions-mode :show-on-click}} query-params
|
||||||
|
@ -200,14 +316,14 @@
|
||||||
[:div.main-message (tr "viewer.breaking-change.message")]
|
[:div.main-message (tr "viewer.breaking-change.message")]
|
||||||
[:div.desc-message (tr "viewer.breaking-change.description")]]
|
[:div.desc-message (tr "viewer.breaking-change.description")]]
|
||||||
|
|
||||||
[:& viewer-page
|
[:> viewer-page
|
||||||
{:page-id page-id
|
{:page-id page-id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:section section
|
:section section
|
||||||
:index index
|
:index index
|
||||||
:share-id share-id
|
:share-id share-id
|
||||||
:interactions-mode (keyword interactions-mode)
|
:interactions-mode (keyword interactions-mode)
|
||||||
:interactions-show? (case (keyword interactions-mode)
|
:show-interactions (case (keyword interactions-mode)
|
||||||
:hide false
|
:hide false
|
||||||
:show true
|
:show true
|
||||||
:show-on-click false)
|
:show-on-click false)
|
||||||
|
@ -237,4 +353,4 @@
|
||||||
[:> error-boundary* {:fallback static/internal-error*}
|
[:> error-boundary* {:fallback static/internal-error*}
|
||||||
[:& notifications/current-notification]
|
[:& notifications/current-notification]
|
||||||
(when route
|
(when route
|
||||||
[:> page-container* {:route route :profile profile}])])]]))
|
[:> page* {:route route :profile profile}])])]]))
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[app.main.data.auth :as da]
|
[app.main.data.auth :as da]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.button-link :as bl]
|
[app.main.ui.components.button-link :as bl]
|
||||||
[app.main.ui.components.forms :as fm]
|
[app.main.ui.components.forms :as fm]
|
||||||
|
@ -22,7 +23,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.keyboard :as k]
|
[app.util.keyboard :as k]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as s]
|
[app.util.storage :as s]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [data]
|
(fn [data]
|
||||||
(when-let [token (:invitation-token data)]
|
(when-let [token (:invitation-token data)]
|
||||||
(st/emit! (rt/nav :auth-verify-token {} {:token token})))))
|
(st/emit! (rt/nav :auth-verify-token {:token token})))))
|
||||||
|
|
||||||
on-success
|
on-success
|
||||||
(fn [data]
|
(fn [data]
|
||||||
|
@ -283,7 +283,7 @@
|
||||||
[{:keys [params] :as props}]
|
[{:keys [params] :as props}]
|
||||||
(let [go-register
|
(let [go-register
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
#(st/emit! (rt/nav :auth-register {} params)))]
|
#(st/emit! (rt/nav :auth-register params)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :auth-form-wrapper)}
|
[:div {:class (stl/css :auth-form-wrapper)}
|
||||||
[:h1 {:class (stl/css :auth-title)
|
[:h1 {:class (stl/css :auth-title)
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.forms :as fm]
|
[app.main.ui.components.forms :as fm]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def ^:private schema:recovery-form
|
(def ^:private schema:recovery-form
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.forms :as fm]
|
[app.main.ui.components.forms :as fm]
|
||||||
[app.main.ui.components.link :as lk]
|
[app.main.ui.components.link :as lk]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
[app.main.data.auth :as da]
|
[app.main.data.auth :as da]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.auth.login :as login]
|
[app.main.ui.auth.login :as login]
|
||||||
[app.main.ui.components.forms :as fm]
|
[app.main.ui.components.forms :as fm]
|
||||||
[app.main.ui.components.link :as lk]
|
[app.main.ui.components.link :as lk]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
on-success (fn [data]
|
on-success (fn [data]
|
||||||
(if (fn? on-success-callback)
|
(if (fn? on-success-callback)
|
||||||
(on-success-callback data)
|
(on-success-callback data)
|
||||||
(st/emit! (rt/nav :auth-register-validate {} data))))]
|
(st/emit! (rt/nav :auth-register-validate data))))]
|
||||||
|
|
||||||
(->> (rp/cmd! :prepare-register-profile cdata)
|
(->> (rp/cmd! :prepare-register-profile cdata)
|
||||||
(rx/map #(merge % params))
|
(rx/map #(merge % params))
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
[:div {:class (stl/css :links)}
|
[:div {:class (stl/css :links)}
|
||||||
[:div {:class (stl/css :account)}
|
[:div {:class (stl/css :account)}
|
||||||
[:span {:class (stl/css :account-text)} (tr "auth.already-have-account") " "]
|
[:span {:class (stl/css :account-text)} (tr "auth.already-have-account") " "]
|
||||||
[:& lk/link {:action #(st/emit! (rt/nav :auth-login {} params))
|
[:& lk/link {:action #(st/emit! (rt/nav :auth-login params))
|
||||||
:class (stl/css :account-link)
|
:class (stl/css :account-link)
|
||||||
:data-testid "login-here-link"}
|
:data-testid "login-here-link"}
|
||||||
(tr "auth.login-here")]]
|
(tr "auth.login-here")]]
|
||||||
|
@ -191,7 +191,7 @@
|
||||||
(cond
|
(cond
|
||||||
(some? (:invitation-token params))
|
(some? (:invitation-token params))
|
||||||
(let [token (:invitation-token params)]
|
(let [token (:invitation-token params)]
|
||||||
(st/emit! (rt/nav :auth-verify-token {} {:token token})))
|
(st/emit! (rt/nav :auth-verify-token {:token token})))
|
||||||
|
|
||||||
(:is-active params)
|
(:is-active params)
|
||||||
(st/emit! (da/login-from-register))
|
(st/emit! (da/login-from-register))
|
||||||
|
@ -257,7 +257,7 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :links)}
|
[:div {:class (stl/css :links)}
|
||||||
[:div {:class (stl/css :go-back)}
|
[:div {:class (stl/css :go-back)}
|
||||||
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {} {}))
|
[:& lk/link {:action #(st/emit! (rt/nav :auth-register {}))
|
||||||
:class (stl/css :go-back-link)}
|
:class (stl/css :go-back-link)}
|
||||||
(tr "labels.go-back")]]]])
|
(tr "labels.go-back")]]]])
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
(ns app.main.ui.auth.verify-token
|
(ns app.main.ui.auth.verify-token
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.auth :as da]
|
[app.main.data.auth :as da]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.ds.product.loader :refer [loader*]]
|
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||||
[app.main.ui.static :as static]
|
[app.main.ui.static :as static]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -43,15 +44,16 @@
|
||||||
[tdata]
|
[tdata]
|
||||||
(case (:state tdata)
|
(case (:state tdata)
|
||||||
:created
|
:created
|
||||||
|
(let [team-id (:team-id tdata)]
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(ntf/success (tr "auth.notifications.team-invitation-accepted"))
|
(ntf/success (tr "auth.notifications.team-invitation-accepted"))
|
||||||
(du/fetch-profile)
|
(du/fetch-profile)
|
||||||
(rt/nav :dashboard-projects {:team-id (:team-id tdata)}))
|
(dcm/go-to-dashboard-recent :team-id team-id)))
|
||||||
|
|
||||||
:pending
|
:pending
|
||||||
(let [token (:invitation-token tdata)
|
(let [token (:invitation-token tdata)
|
||||||
route-id (:redirect-to tdata :auth-register)]
|
route-id (:redirect-to tdata :auth-register)]
|
||||||
(st/emit! (rt/nav route-id {} {:invitation-token token})))))
|
(st/emit! (rt/nav route-id {:invitation-token token})))))
|
||||||
|
|
||||||
(defmethod handle-token :default
|
(defmethod handle-token :default
|
||||||
[_tdata]
|
[_tdata]
|
||||||
|
|
|
@ -253,8 +253,8 @@
|
||||||
:disabled disabled?}]]]))
|
:disabled disabled?}]]]))
|
||||||
|
|
||||||
(mf/defc comment-item
|
(mf/defc comment-item
|
||||||
[{:keys [comment thread users origin] :as props}]
|
[{:keys [comment thread profiles origin] :as props}]
|
||||||
(let [owner (get users (:owner-id comment))
|
(let [owner (get profiles (:owner-id comment))
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
options (mf/deref comments-local-options)
|
options (mf/deref comments-local-options)
|
||||||
edition? (mf/use-state false)
|
edition? (mf/use-state false)
|
||||||
|
@ -384,7 +384,7 @@
|
||||||
|
|
||||||
(mf/defc thread-comments
|
(mf/defc thread-comments
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [thread zoom users origin position-modifier viewport]}]
|
[{:keys [thread zoom profiles origin position-modifier viewport]}]
|
||||||
(let [ref (mf/use-ref)
|
(let [ref (mf/use-ref)
|
||||||
thread-id (:id thread)
|
thread-id (:id thread)
|
||||||
thread-pos (:position thread)
|
thread-pos (:position thread)
|
||||||
|
@ -435,13 +435,13 @@
|
||||||
|
|
||||||
[:div {:class (stl/css :comments)}
|
[:div {:class (stl/css :comments)}
|
||||||
[:& comment-item {:comment comment
|
[:& comment-item {:comment comment
|
||||||
:users users
|
:profiles profiles
|
||||||
:thread thread
|
:thread thread
|
||||||
:origin origin}]
|
:origin origin}]
|
||||||
(for [item (rest comments)]
|
(for [item (rest comments)]
|
||||||
[:* {:key (dm/str (:id item))}
|
[:* {:key (dm/str (:id item))}
|
||||||
[:& comment-item {:comment item
|
[:& comment-item {:comment item
|
||||||
:users users
|
:profiles profiles
|
||||||
:origin origin}]])]
|
:origin origin}]])]
|
||||||
[:& reply-form {:thread thread}]
|
[:& reply-form {:thread thread}]
|
||||||
[:div {:ref ref}]])))
|
[:div {:ref ref}]])))
|
||||||
|
@ -573,8 +573,8 @@
|
||||||
[:span (:seqn thread)]]))
|
[:span (:seqn thread)]]))
|
||||||
|
|
||||||
(mf/defc comment-thread
|
(mf/defc comment-thread
|
||||||
[{:keys [item users on-click]}]
|
[{:keys [item profiles on-click]}]
|
||||||
(let [owner (get users (:owner-id item))
|
(let [owner (get profiles (:owner-id item))
|
||||||
on-click*
|
on-click*
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps item)
|
||||||
|
@ -613,7 +613,7 @@
|
||||||
[:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]))
|
[:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]]))
|
||||||
|
|
||||||
(mf/defc comment-thread-group
|
(mf/defc comment-thread-group
|
||||||
[{:keys [group users on-thread-click]}]
|
[{:keys [group profiles on-thread-click]}]
|
||||||
[:div {:class (stl/css :thread-group)}
|
[:div {:class (stl/css :thread-group)}
|
||||||
(if (:file-name group)
|
(if (:file-name group)
|
||||||
[:div {:class (stl/css :section-title)
|
[:div {:class (stl/css :section-title)
|
||||||
|
@ -631,5 +631,5 @@
|
||||||
[:& comment-thread
|
[:& comment-thread
|
||||||
{:item item
|
{:item item
|
||||||
:on-click on-thread-click
|
:on-click on-thread-click
|
||||||
:users users
|
:profiles profiles
|
||||||
:key (:id item)}])]])
|
:key (:id item)}])]])
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[app.main.data.notifications :as notif]
|
[app.main.data.notifications :as notif]
|
||||||
[app.main.data.plugins :as dp]
|
[app.main.data.plugins :as dp]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.dashboard.files :refer [files-section*]]
|
[app.main.ui.dashboard.files :refer [files-section*]]
|
||||||
|
@ -33,7 +34,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
:on-click clear-selected-fn
|
:on-click clear-selected-fn
|
||||||
:ref container}
|
:ref container}
|
||||||
(case section
|
(case section
|
||||||
:dashboard-projects
|
:dashboard-recent
|
||||||
[:*
|
[:*
|
||||||
[:> projects-section*
|
[:> projects-section*
|
||||||
{:team team
|
{:team team
|
||||||
|
@ -126,16 +126,16 @@
|
||||||
[:> libraries-page* {:team team
|
[:> libraries-page* {:team team
|
||||||
:default-project default-project}]
|
:default-project default-project}]
|
||||||
|
|
||||||
:dashboard-team-members
|
:dashboard-members
|
||||||
[:> team-members-page* {:team team :profile profile}]
|
[:> team-members-page* {:team team :profile profile}]
|
||||||
|
|
||||||
:dashboard-team-invitations
|
:dashboard-invitations
|
||||||
[:> team-invitations-page* {:team team}]
|
[:> team-invitations-page* {:team team}]
|
||||||
|
|
||||||
:dashboard-team-webhooks
|
:dashboard-webhooks
|
||||||
[:> webhooks-page* {:team team}]
|
[:> webhooks-page* {:team team}]
|
||||||
|
|
||||||
:dashboard-team-settings
|
:dashboard-settings
|
||||||
[:> team-settings-page* {:team team :profile profile}]
|
[:> team-settings-page* {:team team :profile profile}]
|
||||||
|
|
||||||
nil)]))
|
nil)]))
|
||||||
|
@ -151,8 +151,9 @@
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(dp/delay-open-plugin plugin)
|
(dp/delay-open-plugin plugin)
|
||||||
(rt/nav :workspace
|
(rt/nav :workspace
|
||||||
{:project-id project-id :file-id id}
|
{:page-id (dm/get-in data [:pages 0])
|
||||||
{:page-id (dm/get-in data [:pages 0])})))
|
:project-id project-id
|
||||||
|
:file-id id})))
|
||||||
|
|
||||||
create-file!
|
create-file!
|
||||||
(fn [plugin]
|
(fn [plugin]
|
||||||
|
@ -182,11 +183,11 @@
|
||||||
:on-accept
|
:on-accept
|
||||||
#(do (preg/install-plugin! plugin)
|
#(do (preg/install-plugin! plugin)
|
||||||
(st/emit! (modal/hide)
|
(st/emit! (modal/hide)
|
||||||
(rt/nav :dashboard-projects {:team-id team-id})
|
(rt/nav :dashboard-recent {:team-id team-id})
|
||||||
(open-try-out-dialog plugin)))
|
(open-try-out-dialog plugin)))
|
||||||
:on-close
|
:on-close
|
||||||
#(st/emit! (modal/hide)
|
#(st/emit! (modal/hide)
|
||||||
(rt/nav :dashboard-projects {:team-id team-id}))}))]
|
(rt/nav :dashboard-recent {:team-id team-id}))}))]
|
||||||
|
|
||||||
(mf/with-layout-effect
|
(mf/with-layout-effect
|
||||||
[plugin-url team-id project-id]
|
[plugin-url team-id project-id]
|
||||||
|
@ -204,7 +205,7 @@
|
||||||
|
|
||||||
(mf/defc dashboard*
|
(mf/defc dashboard*
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [profile project-id team-id search-term plugin-url route-name]}]
|
[{:keys [profile project-id team-id search-term plugin-url section]}]
|
||||||
(let [team (mf/deref refs/team)
|
(let [team (mf/deref refs/team)
|
||||||
projects (mf/deref refs/projects)
|
projects (mf/deref refs/projects)
|
||||||
|
|
||||||
|
@ -253,7 +254,7 @@
|
||||||
:project project
|
:project project
|
||||||
:default-project default-project
|
:default-project default-project
|
||||||
:profile profile
|
:profile profile
|
||||||
:section route-name
|
:section section
|
||||||
:search-term search-term}]
|
:search-term search-term}]
|
||||||
(when (seq projects)
|
(when (seq projects)
|
||||||
[:> dashboard-content*
|
[:> dashboard-content*
|
||||||
|
@ -261,6 +262,6 @@
|
||||||
:profile profile
|
:profile profile
|
||||||
:project project
|
:project project
|
||||||
:default-project default-project
|
:default-project default-project
|
||||||
:section route-name
|
:section section
|
||||||
:search-term search-term
|
:search-term search-term
|
||||||
:team team}])]]))
|
:team team}])]]))
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
(mf/defc comments-section
|
(mf/defc comments-section
|
||||||
[{:keys [profile team show? on-hide-comments]}]
|
[{:keys [profile team show? on-hide-comments]}]
|
||||||
(let [threads-map (mf/deref refs/comment-threads)
|
(let [threads-map (mf/deref refs/comment-threads)
|
||||||
users (mf/deref refs/current-team-comments-users)
|
profiles (mf/deref refs/profiles)
|
||||||
team-id (:id team)
|
team-id (:id team)
|
||||||
|
|
||||||
tgroups (->> (vals threads-map)
|
tgroups (->> (vals threads-map)
|
||||||
|
@ -114,13 +114,13 @@
|
||||||
{:group (first tgroups)
|
{:group (first tgroups)
|
||||||
:on-thread-click on-navigate
|
:on-thread-click on-navigate
|
||||||
:show-file-name true
|
:show-file-name true
|
||||||
:users users}]
|
:profiles profiles}]
|
||||||
(for [tgroup (rest tgroups)]
|
(for [tgroup (rest tgroups)]
|
||||||
[:& cmt/comment-thread-group
|
[:& cmt/comment-thread-group
|
||||||
{:group tgroup
|
{:group tgroup
|
||||||
:on-thread-click on-navigate
|
:on-thread-click on-navigate
|
||||||
:show-file-name true
|
:show-file-name true
|
||||||
:users users
|
:profiles profiles
|
||||||
:key (:page-id tgroup)}])]
|
:key (:page-id tgroup)}])]
|
||||||
|
|
||||||
[:div {:class (stl/css :thread-groups-placeholder)}
|
[:div {:class (stl/css :thread-groups-placeholder)}
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.context-menu-a11y :refer [context-menu*]]
|
[app.main.ui.components.context-menu-a11y :refer [context-menu*]]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -85,10 +85,9 @@
|
||||||
|
|
||||||
on-new-tab
|
on-new-tab
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(let [path-params {:project-id (:project-id file)
|
(st/emit! (dcm/go-to-workspace
|
||||||
:file-id (:id file)}]
|
{:file-id (:id file)
|
||||||
(st/emit! (rt/nav-new-window* {:rname :workspace
|
::rt/new-window true})))
|
||||||
:path-params path-params}))))
|
|
||||||
|
|
||||||
on-duplicate
|
on-duplicate
|
||||||
(fn [_]
|
(fn [_]
|
||||||
|
@ -134,7 +133,9 @@
|
||||||
(st/emit! (ntf/success (tr "dashboard.success-move-files")))
|
(st/emit! (ntf/success (tr "dashboard.success-move-files")))
|
||||||
(st/emit! (ntf/success (tr "dashboard.success-move-file"))))
|
(st/emit! (ntf/success (tr "dashboard.success-move-file"))))
|
||||||
(if (or navigate (not= team-id current-team-id))
|
(if (or navigate (not= team-id current-team-id))
|
||||||
(st/emit! (dd/go-to-files project-id team-id))
|
(st/emit! (dcm/go-to-dashboard-files
|
||||||
|
{:project-id project-id
|
||||||
|
:team-id team-id}))
|
||||||
(st/emit! (dd/fetch-recent-files)
|
(st/emit! (dd/fetch-recent-files)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
(ns app.main.ui.dashboard.files
|
(ns app.main.ui.dashboard.files
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
|
[app.main.data.project :as dpj]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.dashboard.grid :refer [grid]]
|
[app.main.ui.dashboard.grid :refer [grid]]
|
||||||
|
@ -21,7 +23,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -32,7 +33,10 @@
|
||||||
{::mf/props :obj
|
{::mf/props :obj
|
||||||
::mf/private true}
|
::mf/private true}
|
||||||
[{:keys [project create-fn can-edit]}]
|
[{:keys [project create-fn can-edit]}]
|
||||||
(let [local (mf/use-state
|
(let [project-id (:id project)
|
||||||
|
|
||||||
|
local
|
||||||
|
(mf/use-state
|
||||||
{:menu-open false
|
{:menu-open false
|
||||||
:edition false})
|
:edition false})
|
||||||
|
|
||||||
|
@ -63,9 +67,9 @@
|
||||||
|
|
||||||
on-import
|
on-import
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps (:id project))
|
(mf/deps project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/fetch-files {:project-id (:id project)})
|
(st/emit! (dpj/fetch-files project-id)
|
||||||
(dd/clear-selected-files))))]
|
(dd/clear-selected-files))))]
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,11 +157,10 @@
|
||||||
|
|
||||||
on-file-created
|
on-file-created
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [data]
|
(fn [file-data]
|
||||||
(let [pparams {:project-id (:project-id data)
|
(let [file-id (:id file-data)
|
||||||
:file-id (:id data)}
|
page-id (get-in file-data [:pages 0])]
|
||||||
qparams {:page-id (get-in data [:data :pages 0])}]
|
(st/emit! (dcm/go-to-workspace :file-id file-id :page-id page-id)))))
|
||||||
(st/emit! (rt/nav :workspace pparams qparams)))))
|
|
||||||
|
|
||||||
create-file
|
create-file
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -176,7 +179,7 @@
|
||||||
(dom/set-html-title (tr "title.dashboard.files" pname)))))
|
(dom/set-html-title (tr "title.dashboard.files" pname)))))
|
||||||
|
|
||||||
(mf/with-effect [project-id]
|
(mf/with-effect [project-id]
|
||||||
(st/emit! (dd/fetch-files {:project-id project-id})
|
(st/emit! (dpj/fetch-files project-id)
|
||||||
(dd/clear-selected-files)))
|
(dd/clear-selected-files)))
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
[app.main.data.project :as dpj]
|
||||||
|
[app.main.data.team :as dtm]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.rasterizer :as thr]
|
[app.main.rasterizer :as thr]
|
||||||
|
@ -79,8 +82,7 @@
|
||||||
revn (get file :revn)
|
revn (get file :revn)
|
||||||
thumbnail-id (get file :thumbnail-id)
|
thumbnail-id (get file :thumbnail-id)
|
||||||
|
|
||||||
;; FIXME: revisit maybe bug
|
bg-color (dm/get-in file [:data :background])
|
||||||
bg-color (dm/get-in file [:data :options :background])
|
|
||||||
|
|
||||||
container (mf/use-ref)
|
container (mf/use-ref)
|
||||||
visible? (h/use-visible container :once? true)]
|
visible? (h/use-visible container :once? true)]
|
||||||
|
@ -270,12 +272,12 @@
|
||||||
|
|
||||||
on-navigate
|
on-navigate
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file)
|
(mf/deps file-id)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [menu-icon (mf/ref-val menu-ref)
|
(let [menu-icon (mf/ref-val menu-ref)
|
||||||
target (dom/get-target event)]
|
target (dom/get-target event)]
|
||||||
(when-not (dom/child? target menu-icon)
|
(when-not (dom/child? target menu-icon)
|
||||||
(st/emit! (dd/go-to-workspace file))))))
|
(st/emit! (dcm/go-to-workspace :file-id file-id))))))
|
||||||
|
|
||||||
on-drag-start
|
on-drag-start
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -427,10 +429,12 @@
|
||||||
on-finish-import
|
on-finish-import
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/fetch-files {:project-id project-id})
|
(st/emit! (dpj/fetch-files project-id)
|
||||||
(dd/fetch-shared-files)
|
(dtm/fetch-shared-files)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import-files (use-import-file project-id on-finish-import)
|
import-files (use-import-file project-id on-finish-import)
|
||||||
|
|
||||||
on-drag-enter
|
on-drag-enter
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
|
[app.main.data.team :as dtm]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.dashboard.grid :refer [grid]]
|
[app.main.ui.dashboard.grid :refer [grid]]
|
||||||
|
@ -41,7 +42,7 @@
|
||||||
(dom/set-html-title (tr "title.dashboard.shared-libraries" tname))))
|
(dom/set-html-title (tr "title.dashboard.shared-libraries" tname))))
|
||||||
|
|
||||||
(mf/with-effect [team]
|
(mf/with-effect [team]
|
||||||
(st/emit! (dd/fetch-shared-files)
|
(st/emit! (dtm/fetch-shared-files)
|
||||||
(dd/clear-selected-files)))
|
(dd/clear-selected-files)))
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.dashboard.project-menu
|
(ns app.main.ui.dashboard.project-menu
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
@ -16,7 +17,6 @@
|
||||||
[app.main.ui.dashboard.import :as udi]
|
[app.main.ui.dashboard.import :as udi]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc project-menu*
|
(mf/defc project-menu*
|
||||||
|
@ -32,9 +32,9 @@
|
||||||
on-duplicate-success
|
on-duplicate-success
|
||||||
(fn [new-project]
|
(fn [new-project]
|
||||||
(st/emit! (ntf/success (tr "dashboard.success-duplicate-project"))
|
(st/emit! (ntf/success (tr "dashboard.success-duplicate-project"))
|
||||||
(rt/nav :dashboard-files
|
(dcm/go-to-dashboard-files
|
||||||
{:team-id (:team-id new-project)
|
:team-id (:team-id new-project)
|
||||||
:project-id (:id new-project)})))
|
:project-id (:id new-project))))
|
||||||
|
|
||||||
on-duplicate
|
on-duplicate
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
on-move-success
|
on-move-success
|
||||||
(fn [team-id]
|
(fn [team-id]
|
||||||
(st/emit! (dd/go-to-projects team-id)))
|
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id)))
|
||||||
|
|
||||||
on-move
|
on-move
|
||||||
(fn [team-id]
|
(fn [team-id]
|
||||||
|
@ -57,9 +57,10 @@
|
||||||
|
|
||||||
delete-fn
|
delete-fn
|
||||||
(fn [_]
|
(fn [_]
|
||||||
|
(let [team-id (:team-id project)]
|
||||||
(st/emit! (ntf/success (tr "dashboard.success-delete-project"))
|
(st/emit! (ntf/success (tr "dashboard.success-delete-project"))
|
||||||
(dd/delete-project project)
|
(dd/delete-project project)
|
||||||
(dd/go-to-projects (:team-id project))))
|
(dcm/go-to-dashboard-recent :team-id team-id))))
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
#(st/emit!
|
#(st/emit!
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.project :as dpj]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.dashboard.grid :refer [line-grid]]
|
[app.main.ui.dashboard.grid :refer [line-grid]]
|
||||||
|
@ -23,7 +25,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -62,7 +63,7 @@
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/props :obj}
|
::mf/props :obj}
|
||||||
[{:keys [team on-close]}]
|
[{:keys [team on-close]}]
|
||||||
(let [on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members)))
|
(let [on-nav-members-click (mf/use-fn #(st/emit! (dcm/go-to-dashboard-members)))
|
||||||
|
|
||||||
on-invite
|
on-invite
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -105,7 +106,6 @@
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [locale (mf/deref i18n/locale)
|
||||||
|
|
||||||
project-id (:id project)
|
project-id (:id project)
|
||||||
team-id (:id team)
|
|
||||||
|
|
||||||
file-count (or (:count project) 0)
|
file-count (or (:count project) 0)
|
||||||
is-draft? (:is-default project)
|
is-draft? (:is-default project)
|
||||||
|
@ -124,11 +124,10 @@
|
||||||
|
|
||||||
on-nav
|
on-nav
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project-id team-id)
|
(mf/deps project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (rt/nav :dashboard-files
|
(st/emit! (dcm/go-to-dashboard-files :project-id project-id))))
|
||||||
{:team-id team-id
|
|
||||||
:project-id project-id}))))
|
|
||||||
toggle-pin
|
toggle-pin
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project)
|
(mf/deps project)
|
||||||
|
@ -171,11 +170,9 @@
|
||||||
|
|
||||||
on-file-created
|
on-file-created
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [data]
|
(fn [{:keys [id data]}]
|
||||||
(let [pparams {:project-id (:project-id data)
|
(let [page-id (get-in data [:pages 0])]
|
||||||
:file-id (:id data)}
|
(st/emit! (dcm/go-to-workspace :file-id id :page-id page-id)))))
|
||||||
qparams {:page-id (get-in data [:data :pages 0])}]
|
|
||||||
(st/emit! (rt/nav :workspace pparams qparams)))))
|
|
||||||
|
|
||||||
create-file
|
create-file
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -194,9 +191,9 @@
|
||||||
|
|
||||||
on-import
|
on-import
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project-id (:id team))
|
(mf/deps project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/fetch-files {:project-id project-id})
|
(st/emit! (dpj/fetch-files project-id)
|
||||||
(dd/fetch-recent-files)
|
(dd/fetch-recent-files)
|
||||||
(dd/fetch-projects)
|
(dd/fetch-projects)
|
||||||
(dd/clear-selected-files))))
|
(dd/clear-selected-files))))
|
||||||
|
|
|
@ -11,12 +11,14 @@
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.auth :as da]
|
[app.main.data.auth :as da]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
|
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
|
||||||
[app.main.ui.components.link :refer [link]]
|
[app.main.ui.components.link :refer [link]]
|
||||||
|
@ -29,7 +31,6 @@
|
||||||
[app.util.dom.dnd :as dnd]
|
[app.util.dom.dnd :as dnd]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
|
@ -73,32 +74,34 @@
|
||||||
edit-id (:project-for-edit dstate)
|
edit-id (:project-for-edit dstate)
|
||||||
|
|
||||||
local* (mf/use-state
|
local* (mf/use-state
|
||||||
{:menu-open false
|
#(do {:menu-open false
|
||||||
:menu-pos nil
|
:menu-pos nil
|
||||||
:edition? (= (:id item) edit-id)
|
:edition? (= (:id item) edit-id)
|
||||||
:dragging? false})
|
:dragging? false}))
|
||||||
|
|
||||||
local @local*
|
local (deref local*)
|
||||||
|
|
||||||
|
project-id (get item :id)
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dd/go-to-files (:id item)))))
|
(st/emit! (dcm/go-to-dashboard-files :project-id project-id))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps item)
|
(mf/deps project-id)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
(st/emit! (dd/go-to-files (:id item))
|
(st/emit!
|
||||||
|
(dcm/go-to-dashboard-files :project-id project-id)
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
(fn []
|
(fn []
|
||||||
(let [project-title (dom/get-element (str (:id item)))]
|
(when-let [title (dom/get-element (str project-id))]
|
||||||
(when project-title
|
(dom/set-attribute! title "tabindex" "0")
|
||||||
(dom/set-attribute! project-title "tabindex" "0")
|
(dom/focus! title)
|
||||||
(dom/focus! project-title)
|
(dom/set-attribute! title "tabindex" "-1"))))))))
|
||||||
(dom/set-attribute! project-title "tabindex" "-1")))))))))
|
|
||||||
|
|
||||||
on-menu-click
|
on-menu-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -148,9 +151,10 @@
|
||||||
|
|
||||||
on-drop-success
|
on-drop-success
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps (:id item))
|
(mf/deps project-id)
|
||||||
#(st/emit! (ntf/success (tr "dashboard.success-move-file"))
|
(fn [_]
|
||||||
(dd/go-to-files (:id item))))
|
(st/emit! (dcm/go-to-dashboard-files :project-id project-id)
|
||||||
|
(ntf/success (tr "dashboard.success-move-file")))))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -201,19 +205,18 @@
|
||||||
|
|
||||||
on-search-change
|
on-search-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team-id)
|
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (dom/get-target-val event)]
|
(let [value (dom/get-target-val event)]
|
||||||
(emit! (dd/go-to-search value)))))
|
(emit! (dcm/go-to-dashboard-search :term value)))))
|
||||||
|
|
||||||
on-clear-click
|
on-clear-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team-id)
|
(mf/deps team-id)
|
||||||
(fn [e]
|
(fn [e]
|
||||||
|
(emit! (dcm/go-to-dashboard-search))
|
||||||
(let [search-input (dom/get-element "search-input")]
|
(let [search-input (dom/get-element "search-input")]
|
||||||
(dom/clean-value! search-input)
|
(dom/clean-value! search-input)
|
||||||
(dom/focus! search-input)
|
(dom/focus! search-input)
|
||||||
(emit! (dd/go-to-search))
|
|
||||||
(dom/prevent-default e)
|
(dom/prevent-default e)
|
||||||
(dom/stop-propagation e))))
|
(dom/stop-propagation e))))
|
||||||
|
|
||||||
|
@ -278,7 +281,8 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [team-id (-> (dom/get-current-target event)
|
(let [team-id (-> (dom/get-current-target event)
|
||||||
(dom/get-data "value"))]
|
(dom/get-data "value"))]
|
||||||
(st/emit! (dd/go-to-projects team-id)))))
|
|
||||||
|
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id)))))
|
||||||
|
|
||||||
handle-select-default
|
handle-select-default
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -343,10 +347,10 @@
|
||||||
|
|
||||||
(mf/defc team-options-dropdown
|
(mf/defc team-options-dropdown
|
||||||
[{:keys [team profile] :as props}]
|
[{:keys [team profile] :as props}]
|
||||||
(let [go-members #(st/emit! (dd/go-to-team-members))
|
(let [go-members #(st/emit! (dcm/go-to-dashboard-members))
|
||||||
go-invitations #(st/emit! (dd/go-to-team-invitations))
|
go-invitations #(st/emit! (dcm/go-to-dashboard-invitations))
|
||||||
go-webhooks #(st/emit! (dd/go-to-team-webhooks))
|
go-webhooks #(st/emit! (dcm/go-to-dashboard-webhooks))
|
||||||
go-settings #(st/emit! (dd/go-to-team-settings))
|
go-settings #(st/emit! (dcm/go-to-dashboard-settings))
|
||||||
|
|
||||||
members (get team :members)
|
members (get team :members)
|
||||||
permissions (get team :permissions)
|
permissions (get team :permissions)
|
||||||
|
@ -356,9 +360,9 @@
|
||||||
on-success
|
on-success
|
||||||
(fn []
|
(fn []
|
||||||
;; FIXME: this should be handled in the event, not here
|
;; FIXME: this should be handled in the event, not here
|
||||||
(st/emit! (dd/go-to-projects (:default-team-id profile))
|
(let [team-id (:default-team-id profile)]
|
||||||
(modal/hide)
|
(rx/of (dcm/go-to-dashboard-recent :team-id team-id)
|
||||||
(dtm/fetch-teams)))
|
(modal/hide))))
|
||||||
|
|
||||||
on-error
|
on-error
|
||||||
(fn [{:keys [code] :as error}]
|
(fn [{:keys [code] :as error}]
|
||||||
|
@ -692,38 +696,38 @@
|
||||||
(let [default-project-id
|
(let [default-project-id
|
||||||
(get default-project :id)
|
(get default-project :id)
|
||||||
|
|
||||||
projects? (= section :dashboard-projects)
|
team-id (get team :id)
|
||||||
|
|
||||||
|
projects? (= section :dashboard-recent)
|
||||||
fonts? (= section :dashboard-fonts)
|
fonts? (= section :dashboard-fonts)
|
||||||
libs? (= section :dashboard-libraries)
|
libs? (= section :dashboard-libraries)
|
||||||
drafts? (and (= section :dashboard-files)
|
drafts? (and (= section :dashboard-files)
|
||||||
(= (:id project) default-project-id))
|
(= (:id project) default-project-id))
|
||||||
|
|
||||||
go-projects
|
go-projects
|
||||||
(mf/use-fn
|
(mf/use-fn #(st/emit! (dcm/go-to-dashboard-recent)))
|
||||||
(mf/deps team)
|
|
||||||
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})))
|
|
||||||
|
|
||||||
go-projects-with-key
|
go-projects-with-key
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team-id)
|
||||||
#(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)})
|
(fn []
|
||||||
|
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id)
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
(fn []
|
(fn []
|
||||||
(let [projects-title (dom/get-element "dashboard-projects-title")]
|
(when-let [projects-title (dom/get-element "dashboard-projects-title")]
|
||||||
(when projects-title
|
|
||||||
(dom/set-attribute! projects-title "tabindex" "0")
|
(dom/set-attribute! projects-title "tabindex" "0")
|
||||||
(dom/focus! projects-title)
|
(dom/focus! projects-title)
|
||||||
(dom/set-attribute! projects-title "tabindex" "-1")))))))
|
(dom/set-attribute! projects-title "tabindex" "-1")))))))
|
||||||
|
|
||||||
go-fonts
|
go-fonts
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team-id)
|
||||||
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})))
|
#(st/emit! (dcm/go-to-dashboard-fonts :team-id team-id)))
|
||||||
|
|
||||||
go-fonts-with-key
|
go-fonts-with-key
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
#(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)})
|
#(st/emit! (dcm/go-to-dashboard-fonts :team-id team-id)
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
(fn []
|
(fn []
|
||||||
(let [font-title (dom/get-element "dashboard-fonts-title")]
|
(let [font-title (dom/get-element "dashboard-fonts-title")]
|
||||||
|
@ -733,34 +737,31 @@
|
||||||
(dom/set-attribute! font-title "tabindex" "-1")))))))
|
(dom/set-attribute! font-title "tabindex" "-1")))))))
|
||||||
go-drafts
|
go-drafts
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team default-project-id)
|
(mf/deps team-id default-project-id)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (rt/nav :dashboard-files
|
(st/emit! (dcm/go-to-dashboard-files :team-id team-id :project-id default-project-id))))
|
||||||
{:team-id (:id team)
|
|
||||||
:project-id default-project-id}))))
|
|
||||||
|
|
||||||
go-drafts-with-key
|
go-drafts-with-key
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team default-project-id)
|
(mf/deps team-id default-project-id)
|
||||||
#(st/emit! (rt/nav :dashboard-files {:team-id (:id team)
|
(fn []
|
||||||
:project-id default-project-id})
|
(st/emit! (dcm/go-to-dashboard-files :team-id team-id :project-id default-project-id))
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
(fn []
|
(fn []
|
||||||
(let [drafts-title (dom/get-element "dashboard-drafts-title")]
|
(when-let [title (dom/get-element "dashboard-drafts-title")]
|
||||||
(when drafts-title
|
(dom/set-attribute! title "tabindex" "0")
|
||||||
(dom/set-attribute! drafts-title "tabindex" "0")
|
(dom/focus! title)
|
||||||
(dom/focus! drafts-title)
|
(dom/set-attribute! title "tabindex" "-1"))))))
|
||||||
(dom/set-attribute! drafts-title "tabindex" "-1")))))))
|
|
||||||
|
|
||||||
go-libs
|
go-libs
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team-id)
|
||||||
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})))
|
#(st/emit! (dcm/go-to-dashboard-libraries :team-id team-id)))
|
||||||
|
|
||||||
go-libs-with-key
|
go-libs-with-key
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team)
|
(mf/deps team-id)
|
||||||
#(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)})
|
#(st/emit! (dcm/go-to-dashboard-libraries :team-id team-id)
|
||||||
(ts/schedule-on-idle
|
(ts/schedule-on-idle
|
||||||
(fn []
|
(fn []
|
||||||
(let [libs-title (dom/get-element "dashboard-libraries-title")]
|
(let [libs-title (dom/get-element "dashboard-libraries-title")]
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
@ -62,10 +62,10 @@
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/props :obj}
|
::mf/props :obj}
|
||||||
[{:keys [section team]}]
|
[{:keys [section team]}]
|
||||||
(let [on-nav-members (mf/use-fn #(st/emit! (dd/go-to-team-members)))
|
(let [on-nav-members (mf/use-fn #(st/emit! (dcm/go-to-dashboard-members)))
|
||||||
on-nav-settings (mf/use-fn #(st/emit! (dd/go-to-team-settings)))
|
on-nav-settings (mf/use-fn #(st/emit! (dcm/go-to-dashboard-settings)))
|
||||||
on-nav-invitations (mf/use-fn #(st/emit! (dd/go-to-team-invitations)))
|
on-nav-invitations (mf/use-fn #(st/emit! (dcm/go-to-dashboard-invitations)))
|
||||||
on-nav-webhooks (mf/use-fn #(st/emit! (dd/go-to-team-webhooks)))
|
on-nav-webhooks (mf/use-fn #(st/emit! (dcm/go-to-dashboard-webhooks)))
|
||||||
|
|
||||||
route (mf/deref refs/route)
|
route (mf/deref refs/route)
|
||||||
invite-email (-> route :query-params :invite-email)
|
invite-email (-> route :query-params :invite-email)
|
||||||
|
@ -375,7 +375,7 @@
|
||||||
(st/emit! (modal/show params)))))
|
(st/emit! (modal/show params)))))
|
||||||
|
|
||||||
on-success
|
on-success
|
||||||
(mf/use-fn (fn [] (rx/of (dd/go-to-default-team))))
|
(mf/use-fn #(rx/of (dcm/go-to-dashboard-recent :team-id :default)))
|
||||||
|
|
||||||
on-error
|
on-error
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
|
@ -18,7 +19,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -28,15 +28,15 @@
|
||||||
|
|
||||||
(defn- on-create-success
|
(defn- on-create-success
|
||||||
[_form response]
|
[_form response]
|
||||||
(let [msg "Team created successfully"]
|
(let [message "Team created successfully"
|
||||||
(st/emit! (ntf/success msg)
|
team-id (:id response)]
|
||||||
(modal/hide)
|
(st/emit! (ntf/success message)
|
||||||
(rt/nav :dashboard-projects {:team-id (:id response)}))))
|
(dcm/go-to-dashboard-recent :team-id team-id))))
|
||||||
|
|
||||||
(defn- on-update-success
|
(defn- on-update-success
|
||||||
[_form _response]
|
[_form _response]
|
||||||
(let [msg "Team created successfully"]
|
(let [message "Team created successfully"]
|
||||||
(st/emit! (ntf/success msg)
|
(st/emit! (ntf/success message)
|
||||||
(modal/hide))))
|
(modal/hide))))
|
||||||
|
|
||||||
(defn- on-error
|
(defn- on-error
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.dashboard :as dd]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
@ -18,7 +19,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.storage :as storage]
|
[app.util.storage :as storage]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
|
@ -43,9 +43,9 @@
|
||||||
:section section})
|
:section section})
|
||||||
|
|
||||||
(when-not (some? project-id)
|
(when-not (some? project-id)
|
||||||
(rt/nav :dashboard-files
|
(dcm/go-to-dashboard-recent
|
||||||
{:team-id team-id
|
:team-id team-id
|
||||||
:project-id default-project-id}))))]
|
:project-id default-project-id))))]
|
||||||
|
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(ptk/event ::ev/event {::ev/name "import-template-launch"
|
(ptk/event ::ev/event {::ev/name "import-template-launch"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
|
@ -17,7 +18,6 @@
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.notifications.context-notification :refer [context-notification]]
|
[app.main.ui.notifications.context-notification :refer [context-notification]]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
(st/emit! (du/update-profile-props {:onboarding-team-id team-id
|
(st/emit! (du/update-profile-props {:onboarding-team-id team-id
|
||||||
:onboarding-viewed true})
|
:onboarding-viewed true})
|
||||||
(when go-to-team?
|
(when go-to-team?
|
||||||
(rt/nav :dashboard-projects {:team-id team-id}))))))
|
(dcm/go-to-dashboard-recent :team-id team-id))))))
|
||||||
|
|
||||||
on-error
|
on-error
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -7,34 +7,17 @@
|
||||||
(ns app.main.ui.routes
|
(ns app.main.ui.routes
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.uri :as u]
|
[app.common.uri :as u]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
(s/def ::page-id ::us/uuid)
|
|
||||||
(s/def ::file-id ::us/uuid)
|
|
||||||
(s/def ::section ::us/keyword)
|
|
||||||
(s/def ::index ::us/integer)
|
|
||||||
(s/def ::token (s/nilable ::us/not-empty-string))
|
|
||||||
(s/def ::share-id ::us/uuid)
|
|
||||||
|
|
||||||
(s/def ::viewer-path-params
|
|
||||||
(s/keys :req-un [::file-id]))
|
|
||||||
|
|
||||||
(s/def ::viewer-query-params
|
|
||||||
(s/keys :opt-un [::index ::share-id ::section ::page-id]))
|
|
||||||
|
|
||||||
(s/def ::any any?)
|
|
||||||
|
|
||||||
(def routes
|
(def routes
|
||||||
[["/auth"
|
[["/auth"
|
||||||
["/login" :auth-login]
|
["/login" :auth-login]
|
||||||
|
@ -53,11 +36,10 @@
|
||||||
["/access-tokens" :settings-access-tokens]]
|
["/access-tokens" :settings-access-tokens]]
|
||||||
|
|
||||||
["/frame-preview" :frame-preview]
|
["/frame-preview" :frame-preview]
|
||||||
["/view/:file-id"
|
|
||||||
{:name :viewer
|
["/view" :viewer]
|
||||||
:conform
|
|
||||||
{:path-params ::viewer-path-params
|
["/view/:file-id" :viewer-legacy]
|
||||||
:query-params ::viewer-query-params}}]
|
|
||||||
|
|
||||||
(when *assert*
|
(when *assert*
|
||||||
["/debug/icons-preview" :debug-icons-preview])
|
["/debug/icons-preview" :debug-icons-preview])
|
||||||
|
@ -65,33 +47,32 @@
|
||||||
;; Used for export
|
;; Used for export
|
||||||
["/render-sprite/:file-id" :render-sprite]
|
["/render-sprite/:file-id" :render-sprite]
|
||||||
|
|
||||||
["/dashboard/team/:team-id"
|
["/dashboard"
|
||||||
["/members" :dashboard-team-members]
|
["/members" :dashboard-members]
|
||||||
["/invitations" :dashboard-team-invitations]
|
["/invitations" :dashboard-invitations]
|
||||||
["/webhooks" :dashboard-team-webhooks]
|
["/webhooks" :dashboard-webhooks]
|
||||||
["/settings" :dashboard-team-settings]
|
["/settings" :dashboard-settings]
|
||||||
["/projects" :dashboard-projects]
|
["/recent" :dashboard-recent]
|
||||||
["/search" :dashboard-search]
|
["/search" :dashboard-search]
|
||||||
["/fonts" :dashboard-fonts]
|
["/fonts" :dashboard-fonts]
|
||||||
["/fonts/providers" :dashboard-font-providers]
|
["/fonts/providers" :dashboard-font-providers]
|
||||||
["/libraries" :dashboard-libraries]
|
["/libraries" :dashboard-libraries]
|
||||||
["/projects/:project-id" :dashboard-files]]
|
["/files" :dashboard-files]]
|
||||||
|
|
||||||
["/workspace/:project-id/:file-id" :workspace]])
|
["/dashboard/team/:team-id"
|
||||||
|
["/members" :dashboard-legacy-team-members]
|
||||||
|
["/invitations" :dashboard-legacy-team-invitations]
|
||||||
|
["/webhooks" :dashboard-legacy-team-webhooks]
|
||||||
|
["/settings" :dashboard-legacy-team-settings]
|
||||||
|
["/projects" :dashboard-legacy-projects]
|
||||||
|
["/search" :dashboard-legacy-search]
|
||||||
|
["/fonts" :dashboard-legacy-fonts]
|
||||||
|
["/fonts/providers" :dashboard-legacy-font-providers]
|
||||||
|
["/libraries" :dashboard-legacy-libraries]
|
||||||
|
["/projects/:project-id" :dashboard-legacy-files]]
|
||||||
|
|
||||||
(defn- match-path
|
["/workspace" :workspace]
|
||||||
[router path]
|
["/workspace/:project-id/:file-id" :workspace-legacy]])
|
||||||
(when-let [match (rt/match router path)]
|
|
||||||
(if-let [conform (get-in match [:data :conform])]
|
|
||||||
(let [spath (get conform :path-params ::any)
|
|
||||||
squery (get conform :query-params ::any)]
|
|
||||||
(try
|
|
||||||
(-> (dissoc match :params)
|
|
||||||
(assoc :path-params (us/conform spath (get match :path-params))
|
|
||||||
:query-params (us/conform squery (get match :query-params))))
|
|
||||||
(catch :default _
|
|
||||||
nil)))
|
|
||||||
match)))
|
|
||||||
|
|
||||||
(defn on-navigate
|
(defn on-navigate
|
||||||
[router path]
|
[router path]
|
||||||
|
@ -99,8 +80,9 @@
|
||||||
[base-path qs] (str/split path "?")
|
[base-path qs] (str/split path "?")
|
||||||
location-path (dm/str (.-origin location) (.-pathname location))
|
location-path (dm/str (.-origin location) (.-pathname location))
|
||||||
valid-location? (= location-path (dm/str cf/public-uri))
|
valid-location? (= location-path (dm/str cf/public-uri))
|
||||||
match (match-path router path)
|
match (rt/match router path)
|
||||||
empty-path? (or (= base-path "") (= base-path "/"))]
|
empty-path? (or (= base-path "") (= base-path "/"))]
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(not valid-location?)
|
(not valid-location?)
|
||||||
(st/emit! (rt/assign-exception {:type :not-found}))
|
(st/emit! (rt/assign-exception {:type :not-found}))
|
||||||
|
@ -121,9 +103,9 @@
|
||||||
empty-path?
|
empty-path?
|
||||||
(let [team-id (or (dtm/get-last-team-id)
|
(let [team-id (or (dtm/get-last-team-id)
|
||||||
(:default-team-id profile))]
|
(:default-team-id profile))]
|
||||||
(st/emit! (rt/nav :dashboard-projects
|
(st/emit! (rt/nav :dashboard-recent
|
||||||
{:team-id team-id}
|
(-> (u/query-string->map qs)
|
||||||
(u/query-string->map qs))))
|
(assoc :team-id team-id)))))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.dashboard.shortcuts :as sc]
|
[app.main.data.dashboard.shortcuts :as sc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.settings.access-tokens :refer [access-tokens-page]]
|
[app.main.ui.settings.access-tokens :refer [access-tokens-page]]
|
||||||
|
@ -20,7 +21,6 @@
|
||||||
[app.main.ui.settings.profile :refer [profile-page]]
|
[app.main.ui.settings.profile :refer [profile-page]]
|
||||||
[app.main.ui.settings.sidebar :refer [sidebar]]
|
[app.main.ui.settings.sidebar :refer [sidebar]]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc header
|
(mf/defc header
|
||||||
|
|
|
@ -8,15 +8,16 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.dashboard.sidebar :refer [profile-section*]]
|
[app.main.ui.dashboard.sidebar :refer [profile-section*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
(def ^:private feedback-icon
|
(def ^:private feedback-icon
|
||||||
(i/icon-xref :feedback (stl/css :feedback-icon)))
|
(i/icon-xref :feedback (stl/css :feedback-icon)))
|
||||||
|
|
||||||
|
;; FIXME: move to common
|
||||||
(def ^:private go-settings-profile
|
(def ^:private go-settings-profile
|
||||||
#(st/emit! (rt/nav :settings-profile)))
|
#(st/emit! (rt/nav :settings-profile)))
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@
|
||||||
go-dashboard
|
go-dashboard
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team-id)
|
(mf/deps team-id)
|
||||||
#(st/emit! (rt/nav :dashboard-projects {:team-id team-id})))]
|
#(st/emit! (dcm/go-to-dashboard-recent :team-id team-id)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :sidebar-content)}
|
[:div {:class (stl/css :sidebar-content)}
|
||||||
[:div {:class (stl/css :sidebar-content-section)}
|
[:div {:class (stl/css :sidebar-content-section)}
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.pprint :as pp]
|
[app.common.pprint :as pp]
|
||||||
[app.common.uri :as u]
|
[app.common.uri :as u]
|
||||||
[app.main.data.common :as dc]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.auth.login :refer [login-methods]]
|
[app.main.ui.auth.login :refer [login-methods]]
|
||||||
[app.main.ui.auth.recovery-request :refer [recovery-request-page recovery-sent-page]]
|
[app.main.ui.auth.recovery-request :refer [recovery-request-page recovery-sent-page]]
|
||||||
|
@ -26,7 +27,6 @@
|
||||||
[app.main.ui.viewer.header :as viewer.header]
|
[app.main.ui.viewer.header :as viewer.header]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -213,7 +213,8 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps profile)
|
(mf/deps profile)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (rt/nav :dashboard-projects {:team-id (:default-team-id profile)}))))
|
(let [team-id (:default-team-id profile)]
|
||||||
|
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id)))))
|
||||||
|
|
||||||
on-success
|
on-success
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -233,7 +234,7 @@
|
||||||
{:team-id team-id})
|
{:team-id team-id})
|
||||||
mdata {:on-success on-success
|
mdata {:on-success on-success
|
||||||
:on-error on-error}]
|
:on-error on-error}]
|
||||||
(st/emit! (dc/create-team-access-request
|
(st/emit! (dcm/create-team-access-request
|
||||||
(with-meta params mdata))))))]
|
(with-meta params mdata))))))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
[app.main.ui.ds.product.loader :refer [loader*]]
|
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
|
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar*]]
|
||||||
[app.main.ui.viewer.header :as header]
|
[app.main.ui.viewer.header :as header]
|
||||||
[app.main.ui.viewer.inspect :as inspect]
|
[app.main.ui.viewer.inspect :as inspect]
|
||||||
[app.main.ui.viewer.interactions :as interactions]
|
[app.main.ui.viewer.interactions :as interactions]
|
||||||
|
@ -129,8 +129,8 @@
|
||||||
:comment-sidebar show-sidebar?}]
|
:comment-sidebar show-sidebar?}]
|
||||||
|
|
||||||
(when show-sidebar?
|
(when show-sidebar?
|
||||||
[:& comments-sidebar
|
[:> comments-sidebar*
|
||||||
{:users users
|
{:profiles users
|
||||||
:frame frame
|
:frame frame
|
||||||
:page page}])]))
|
:page page}])]))
|
||||||
|
|
||||||
|
@ -274,9 +274,9 @@
|
||||||
:page page
|
:page page
|
||||||
:zoom zoom}])]])
|
:zoom zoom}])]])
|
||||||
|
|
||||||
(mf/defc viewer-content
|
(mf/defc viewer-content*
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj}
|
||||||
[{:keys [data page-id share-id section index interactions-mode share] :as props}]
|
[{:keys [data page-id share-id section index interactions-mode share]}]
|
||||||
(let [{:keys [file users project permissions]} data
|
(let [{:keys [file users project permissions]} data
|
||||||
allowed (or
|
allowed (or
|
||||||
(= section :interactions)
|
(= section :interactions)
|
||||||
|
@ -620,8 +620,8 @@
|
||||||
|
|
||||||
;; --- Component: Viewer
|
;; --- Component: Viewer
|
||||||
|
|
||||||
(mf/defc viewer
|
(mf/defc viewer*
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj}
|
||||||
[{:keys [file-id share-id page-id] :as props}]
|
[{:keys [file-id share-id page-id] :as props}]
|
||||||
(mf/with-effect [file-id page-id share-id]
|
(mf/with-effect [file-id page-id share-id]
|
||||||
(let [params {:file-id file-id
|
(let [params {:file-id file-id
|
||||||
|
@ -630,9 +630,10 @@
|
||||||
(st/emit! (dv/initialize params))
|
(st/emit! (dv/initialize params))
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dv/finalize params)))))
|
(st/emit! (dv/finalize params)))))
|
||||||
|
|
||||||
(if-let [data (mf/deref refs/viewer-data)]
|
(if-let [data (mf/deref refs/viewer-data)]
|
||||||
(let [props (obj/merge props #js {:data data :key (dm/str file-id)})]
|
(let [props (obj/merge props #js {:data data :key (dm/str file-id)})]
|
||||||
[:> viewer-content props])
|
[:> viewer-content* props])
|
||||||
|
|
||||||
[:> loader* {:title (tr "labels.loading")
|
[:> loader* {:title (tr "labels.loading")
|
||||||
:overlay true}]))
|
:overlay true}]))
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
{:thread thread
|
{:thread thread
|
||||||
:position-modifier modifier1
|
:position-modifier modifier1
|
||||||
:viewport {:offset-x 0 :offset-y 0 :width (:width vsize) :height (:height vsize)}
|
:viewport {:offset-x 0 :offset-y 0 :width (:width vsize) :height (:height vsize)}
|
||||||
:users users
|
:profiles users
|
||||||
:zoom zoom}])
|
:zoom zoom}])
|
||||||
|
|
||||||
(when-let [draft (:draft local)]
|
(when-let [draft (:draft local)]
|
||||||
|
@ -231,8 +231,9 @@
|
||||||
:on-submit on-draft-submit
|
:on-submit on-draft-submit
|
||||||
:zoom zoom}])]]]))
|
:zoom zoom}])]]]))
|
||||||
|
|
||||||
(mf/defc comments-sidebar
|
(mf/defc comments-sidebar*
|
||||||
[{:keys [users frame page]}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [profiles frame page]}]
|
||||||
(let [profile (mf/deref refs/profile)
|
(let [profile (mf/deref refs/profile)
|
||||||
local (mf/deref refs/comments-local)
|
local (mf/deref refs/comments-local)
|
||||||
threads-map (mf/deref refs/comment-threads)
|
threads-map (mf/deref refs/comment-threads)
|
||||||
|
@ -242,4 +243,8 @@
|
||||||
(gsh/has-point? frame position))))]
|
(gsh/has-point? frame position))))]
|
||||||
[:aside {:class (stl/css :comments-sidebar)}
|
[:aside {:class (stl/css :comments-sidebar)}
|
||||||
[:div {:class (stl/css :settings-bar-inside)}
|
[:div {:class (stl/css :settings-bar-inside)}
|
||||||
[:& wc/comments-sidebar {:from-viewer true :users users :threads threads :page-id (:id page)}]]]))
|
[:> wc/comments-sidebar*
|
||||||
|
{:from-viewer true
|
||||||
|
:profiles profiles
|
||||||
|
:threads threads
|
||||||
|
:page-id (:id page)}]]]))
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.viewer.comments :refer [comments-menu]]
|
[app.main.ui.viewer.comments :refer [comments-menu]]
|
||||||
[app.main.ui.viewer.interactions :refer [flows-menu* interactions-menu]]
|
[app.main.ui.viewer.interactions :refer [flows-menu* interactions-menu*]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
|
@ -173,7 +173,8 @@
|
||||||
:interactions [:*
|
:interactions [:*
|
||||||
(when index
|
(when index
|
||||||
[:> flows-menu* {:page page :index index}])
|
[:> flows-menu* {:page page :index index}])
|
||||||
[:& interactions-menu {:interactions-mode interactions-mode}]]
|
[:> interactions-menu*
|
||||||
|
{:interactions-mode interactions-mode}]]
|
||||||
:comments [:& comments-menu]
|
:comments [:& comments-menu]
|
||||||
[:div {:class (stl/css :view-options)}])
|
[:div {:class (stl/css :view-options)}])
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[okulary.core :as l]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -49,13 +50,26 @@
|
||||||
</body>
|
</body>
|
||||||
</html>")
|
</html>")
|
||||||
|
|
||||||
|
;; FIXME: this code need to be refactored
|
||||||
|
(defn get-viewer-objects
|
||||||
|
([]
|
||||||
|
(let [route (deref refs/route)
|
||||||
|
page-id (:page-id (:query-params route))]
|
||||||
|
(get-viewer-objects page-id)))
|
||||||
|
([page-id]
|
||||||
|
(l/derived
|
||||||
|
(fn [state]
|
||||||
|
(let [objects (refs/get-viewer-objects state page-id)]
|
||||||
|
objects))
|
||||||
|
st/state =)))
|
||||||
|
|
||||||
(defn- use-objects [from]
|
(defn- use-objects [from]
|
||||||
(let [page-objects-ref
|
(let [page-objects-ref
|
||||||
(mf/with-memo [from]
|
(mf/with-memo [from]
|
||||||
(if (= from :workspace)
|
(if (= from :workspace)
|
||||||
;; FIXME: fix naming consistency issues
|
;; FIXME: fix naming consistency issues
|
||||||
refs/workspace-page-objects
|
refs/workspace-page-objects
|
||||||
(refs/get-viewer-objects)))]
|
(get-viewer-objects)))]
|
||||||
(mf/deref page-objects-ref)))
|
(mf/deref page-objects-ref)))
|
||||||
|
|
||||||
(defn- shapes->images
|
(defn- shapes->images
|
||||||
|
|
|
@ -267,7 +267,8 @@
|
||||||
(when (= flow-id (:id current-flow))
|
(when (= flow-id (:id current-flow))
|
||||||
[:span {:class (stl/css :icon)} i/tick])])]]])))
|
[:span {:class (stl/css :icon)} i/tick])])]]])))
|
||||||
|
|
||||||
(mf/defc interactions-menu
|
(mf/defc interactions-menu*
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [interactions-mode]}]
|
[{:keys [interactions-mode]}]
|
||||||
(let [show-dropdown? (mf/use-state false)
|
(let [show-dropdown? (mf/use-state false)
|
||||||
toggle-dropdown (mf/use-fn #(swap! show-dropdown? not))
|
toggle-dropdown (mf/use-fn #(swap! show-dropdown? not))
|
||||||
|
@ -281,6 +282,7 @@
|
||||||
(keyword))]
|
(keyword))]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dv/set-interactions-mode mode)))))]
|
(st/emit! (dv/set-interactions-mode mode)))))]
|
||||||
|
|
||||||
[:div {:on-click toggle-dropdown
|
[:div {:on-click toggle-dropdown
|
||||||
:class (stl/css :view-options)}
|
:class (stl/css :view-options)}
|
||||||
[:span {:class (stl/css :dropdown-title)} (tr "viewer.header.interactions")]
|
[:span {:class (stl/css :dropdown-title)} (tr "viewer.header.interactions")]
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.shapes.bool :as bool]
|
[app.main.ui.shapes.bool :as bool]
|
||||||
[app.main.ui.shapes.circle :as circle]
|
[app.main.ui.shapes.circle :as circle]
|
||||||
|
@ -26,7 +27,6 @@
|
||||||
[app.main.ui.shapes.text :as text]
|
[app.main.ui.shapes.text :as text]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.timers :as tm]
|
[app.util.timers :as tm]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
(def base-frame-ctx (mf/create-context nil))
|
(def base-frame-ctx (mf/create-context nil))
|
||||||
(def frame-offset-ctx (mf/create-context nil))
|
(def frame-offset-ctx (mf/create-context nil))
|
||||||
|
|
||||||
(def viewer-interactions-show?
|
(def ^:private ref:viewer-show-interactions
|
||||||
(l/derived :interactions-show? refs/viewer-local))
|
(l/derived :show-interactions refs/viewer-local))
|
||||||
|
|
||||||
(defn- find-relative-to-base-frame
|
(defn- find-relative-to-base-frame
|
||||||
[shape objects overlays-ids base-frame]
|
[shape objects overlays-ids base-frame]
|
||||||
|
@ -280,7 +280,7 @@
|
||||||
sems))))
|
sems))))
|
||||||
|
|
||||||
(mf/defc interaction
|
(mf/defc interaction
|
||||||
[{:keys [shape interactions interactions-show?]}]
|
[{:keys [shape interactions show-interactions]}]
|
||||||
(let [{:keys [x y width height]} (:selrect shape)]
|
(let [{:keys [x y width height]} (:selrect shape)]
|
||||||
(when-not (empty? interactions)
|
(when-not (empty? interactions)
|
||||||
[:rect {:x (- x 1)
|
[:rect {:x (- x 1)
|
||||||
|
@ -289,8 +289,8 @@
|
||||||
:height (+ height 2)
|
:height (+ height 2)
|
||||||
:fill "var(--color-accent-tertiary)"
|
:fill "var(--color-accent-tertiary)"
|
||||||
:stroke "var(--color-accent-tertiary)"
|
:stroke "var(--color-accent-tertiary)"
|
||||||
:stroke-width (if interactions-show? 1 0)
|
:stroke-width (if show-interactions 1 0)
|
||||||
:fill-opacity (if interactions-show? 0.2 0)
|
:fill-opacity (if show-interactions 0.2 0)
|
||||||
:transform (gsh/transform-str shape)}])))
|
:transform (gsh/transform-str shape)}])))
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@
|
||||||
all-objects (or (unchecked-get props "all-objects") objects)
|
all-objects (or (unchecked-get props "all-objects") objects)
|
||||||
base-frame (mf/use-ctx base-frame-ctx)
|
base-frame (mf/use-ctx base-frame-ctx)
|
||||||
frame-offset (mf/use-ctx frame-offset-ctx)
|
frame-offset (mf/use-ctx frame-offset-ctx)
|
||||||
interactions-show? (mf/deref viewer-interactions-show?)
|
show-interactions (mf/deref ref:viewer-show-interactions)
|
||||||
overlays (mf/deref refs/viewer-overlays)
|
overlays (mf/deref refs/viewer-overlays)
|
||||||
interactions (:interactions shape)
|
interactions (:interactions shape)
|
||||||
svg-element? (and (= :svg-raw (:type shape))
|
svg-element? (and (= :svg-raw (:type shape))
|
||||||
|
@ -355,7 +355,7 @@
|
||||||
|
|
||||||
[:& interaction {:shape shape
|
[:& interaction {:shape shape
|
||||||
:interactions interactions
|
:interactions interactions
|
||||||
:interactions-show? interactions-show?}]]
|
:show-interactions show-interactions}]]
|
||||||
|
|
||||||
;; Don't wrap svg elements inside a <g> otherwise some can break
|
;; Don't wrap svg elements inside a <g> otherwise some can break
|
||||||
[:& component {:shape shape
|
[:& component {:shape shape
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.select :refer [select]]
|
[app.main.ui.components.select :refer [select]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -69,17 +69,16 @@
|
||||||
(= (:pages %) pages))
|
(= (:pages %) pages))
|
||||||
slinks)]
|
slinks)]
|
||||||
(when slink
|
(when slink
|
||||||
(let [pparams (:path-params route)
|
(let [page-id (d/seek #(contains? (:pages slink) %) page-ids)
|
||||||
page-id (d/seek #(contains? (:pages slink) %) page-ids)
|
params (-> (:query-params route)
|
||||||
qparams (-> (:query-params route)
|
|
||||||
(assoc :share-id (:id slink))
|
(assoc :share-id (:id slink))
|
||||||
(assoc :page-id page-id)
|
(assoc :page-id page-id)
|
||||||
(assoc :index "0"))
|
(assoc :index "0"))
|
||||||
qparams (if (nil? zoom-type)
|
params (if (nil? zoom-type)
|
||||||
(dissoc qparams :zoom)
|
(dissoc params :zoom)
|
||||||
(assoc qparams :zoom zoom-type))
|
(assoc params :zoom zoom-type))
|
||||||
|
|
||||||
href (rt/resolve router :viewer pparams qparams)]
|
href (rt/resolve router :viewer params)]
|
||||||
(dm/str (assoc cf/public-uri :fragment href))))))
|
(dm/str (assoc cf/public-uri :fragment href))))))
|
||||||
|
|
||||||
on-close
|
on-close
|
||||||
|
|
|
@ -8,12 +8,10 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.notifications :as ntf]
|
|
||||||
[app.main.data.persistence :as dps]
|
[app.main.data.persistence :as dps]
|
||||||
[app.main.data.plugins :as dpl]
|
[app.main.data.plugins :as dpl]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.colors :as dc]
|
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -46,7 +44,7 @@
|
||||||
[file-id]
|
[file-id]
|
||||||
(l/derived (fn [state]
|
(l/derived (fn [state]
|
||||||
(let [data (:workspace-data state)]
|
(let [data (:workspace-data state)]
|
||||||
(and (:workspace-ready? state)
|
(and (:workspace-ready state)
|
||||||
(= file-id (:current-file-id state))
|
(= file-id (:current-file-id state))
|
||||||
(= file-id (:id data)))))
|
(= file-id (:id data)))))
|
||||||
st/state))
|
st/state))
|
||||||
|
@ -125,14 +123,17 @@
|
||||||
:file file
|
:file file
|
||||||
:page-id page-id}]])]))
|
:page-id page-id}]])]))
|
||||||
|
|
||||||
(mf/defc workspace-loader
|
(mf/defc workspace-loader*
|
||||||
|
{::mf/props :obj
|
||||||
|
::mf/private true}
|
||||||
[]
|
[]
|
||||||
[:> loader* {:title (tr "labels.loading")
|
[:> loader* {:title (tr "labels.loading")
|
||||||
:class (stl/css :workspace-loader)
|
:class (stl/css :workspace-loader)
|
||||||
:overlay true}])
|
:overlay true}])
|
||||||
|
|
||||||
(mf/defc workspace-page
|
(mf/defc workspace-page*
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj
|
||||||
|
::mf/private true}
|
||||||
[{:keys [page-id file layout wglobal]}]
|
[{:keys [page-id file layout wglobal]}]
|
||||||
(let [page-id (hooks/use-equal-memo page-id)
|
(let [page-id (hooks/use-equal-memo page-id)
|
||||||
page-ready* (mf/with-memo [page-id]
|
page-ready* (mf/with-memo [page-id]
|
||||||
|
@ -147,18 +148,20 @@
|
||||||
(mf/with-effect [page-id]
|
(mf/with-effect [page-id]
|
||||||
(if (some? page-id)
|
(if (some? page-id)
|
||||||
(st/emit! (dw/initialize-page page-id))
|
(st/emit! (dw/initialize-page page-id))
|
||||||
(st/emit! (dw/go-to-page)))
|
(st/emit! (dcm/go-to-workspace)))
|
||||||
(fn []
|
(fn []
|
||||||
(when (some? page-id)
|
(when (some? page-id)
|
||||||
(st/emit! (dw/finalize-page page-id)))))
|
(st/emit! (dw/finalize-page page-id)))))
|
||||||
|
|
||||||
(if ^boolean page-ready?
|
(if ^boolean page-ready?
|
||||||
[:& workspace-content {:page-id page-id
|
[:& workspace-content {:page-id page-id
|
||||||
:file file
|
:file file
|
||||||
:wglobal wglobal
|
:wglobal wglobal
|
||||||
:layout layout}]
|
:layout layout}]
|
||||||
[:& workspace-loader])))
|
[:& workspace-loader*])))
|
||||||
|
|
||||||
(mf/defc workspace
|
|
||||||
|
(mf/defc workspace*
|
||||||
{::mf/wrap-props false
|
{::mf/wrap-props false
|
||||||
::mf/wrap [mf/memo]}
|
::mf/wrap [mf/memo]}
|
||||||
[{:keys [project-id file-id page-id layout-name]}]
|
[{:keys [project-id file-id page-id layout-name]}]
|
||||||
|
@ -168,9 +171,7 @@
|
||||||
|
|
||||||
team (mf/deref refs/team)
|
team (mf/deref refs/team)
|
||||||
file (mf/deref refs/workspace-file)
|
file (mf/deref refs/workspace-file)
|
||||||
project (mf/deref refs/workspace-project)
|
|
||||||
|
|
||||||
team-id (:team-id project)
|
|
||||||
file-name (:name file)
|
file-name (:name file)
|
||||||
permissions (:permissions team)
|
permissions (:permissions team)
|
||||||
|
|
||||||
|
@ -192,36 +193,32 @@
|
||||||
|
|
||||||
;; Setting the layout preset by its name
|
;; Setting the layout preset by its name
|
||||||
(mf/with-effect [layout-name]
|
(mf/with-effect [layout-name]
|
||||||
(st/emit! (dw/initialize-layout layout-name)))
|
(st/emit! (dw/initialize-workspace-layout layout-name)))
|
||||||
|
|
||||||
(mf/with-effect [file-name]
|
(mf/with-effect [file-name]
|
||||||
(when file-name
|
(when file-name
|
||||||
(dom/set-html-title (tr "title.workspace" file-name))))
|
(dom/set-html-title (tr "title.workspace" file-name))))
|
||||||
|
|
||||||
(mf/with-effect [project-id file-id]
|
(mf/with-effect [file-id]
|
||||||
(st/emit! (dw/initialize-file project-id file-id))
|
(st/emit! (dw/initialize-workspace file-id))
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! ::dps/force-persist
|
(st/emit! ::dps/force-persist
|
||||||
(dc/stop-picker)
|
(dw/finalize-workspace file-id))))
|
||||||
(modal/hide)
|
|
||||||
(ntf/hide)
|
|
||||||
(dw/finalize-file project-id file-id))))
|
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-file-id) {:value file-id}
|
|
||||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||||
[:& (mf/provider ctx/current-team-id) {:value team-id}
|
[:& (mf/provider ctx/current-file-id) {:value file-id}
|
||||||
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
||||||
[:& (mf/provider ctx/components-v2) {:value components-v2?}
|
[:& (mf/provider ctx/components-v2) {:value components-v2?}
|
||||||
[:& (mf/provider ctx/design-tokens) {:value design-tokens?}
|
[:& (mf/provider ctx/design-tokens) {:value design-tokens?}
|
||||||
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||||
[:& (mf/provider ctx/permissions) {:value permissions}
|
|
||||||
[:section {:class (stl/css :workspace)
|
[:section {:class (stl/css :workspace)
|
||||||
:style {:background-color background-color
|
:style {:background-color background-color
|
||||||
:touch-action "none"}}
|
:touch-action "none"}}
|
||||||
[:& context-menu]
|
[:& context-menu]
|
||||||
|
|
||||||
(if ^boolean file-ready?
|
(if ^boolean file-ready?
|
||||||
[:& workspace-page {:page-id page-id
|
[:> workspace-page* {:page-id page-id
|
||||||
:file file
|
:file file
|
||||||
:wglobal wglobal
|
:wglobal wglobal
|
||||||
:layout layout}]
|
:layout layout}]
|
||||||
[:& workspace-loader])]]]]]]]]]))
|
[:> workspace-loader* {}])]]]]]]]))
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
(ns app.main.ui.workspace.comments
|
(ns app.main.ui.workspace.comments
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcmt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.comments :as dwcm]
|
[app.main.data.workspace.comments :as dwcm]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.comments :as cmt]
|
[app.main.ui.comments :as cmt]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
@ -37,14 +39,14 @@
|
||||||
(let [mode (-> (dom/get-current-target event)
|
(let [mode (-> (dom/get-current-target event)
|
||||||
(dom/get-data "value")
|
(dom/get-data "value")
|
||||||
(keyword))]
|
(keyword))]
|
||||||
(st/emit! (dcm/update-filters {:mode mode})))))
|
(st/emit! (dcmt/update-filters {:mode mode})))))
|
||||||
|
|
||||||
update-show
|
update-show
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps cshow)
|
(mf/deps cshow)
|
||||||
(fn []
|
(fn []
|
||||||
(let [mode (if (= :pending cshow) :all :pending)]
|
(let [mode (if (= :pending cshow) :all :pending)]
|
||||||
(st/emit! (dcm/update-filters {:show mode})))))]
|
(st/emit! (dcmt/update-filters {:show mode})))))]
|
||||||
|
|
||||||
[:ul {:class (stl/css-case :comment-mode-dropdown true
|
[:ul {:class (stl/css-case :comment-mode-dropdown true
|
||||||
:viewer-dropdown from-viewer)}
|
:viewer-dropdown from-viewer)}
|
||||||
|
@ -68,13 +70,13 @@
|
||||||
[:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")]
|
[:span {:class (stl/css :label)} (tr "labels.hide-resolved-comments")]
|
||||||
[:span {:class (stl/css :icon)} i/tick]]]))
|
[:span {:class (stl/css :icon)} i/tick]]]))
|
||||||
|
|
||||||
(mf/defc comments-sidebar
|
(mf/defc comments-sidebar*
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [users threads page-id from-viewer]}]
|
[{:keys [profiles threads page-id from-viewer]}]
|
||||||
(let [threads-map (mf/deref refs/threads-ref)
|
(let [threads-map (mf/deref refs/threads-ref)
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
users-refs (mf/deref refs/current-file-comments-users)
|
profiles' (mf/deref refs/profiles)
|
||||||
users (or users users-refs)
|
profiles (or profiles profiles')
|
||||||
local (mf/deref refs/comments-local)
|
local (mf/deref refs/comments-local)
|
||||||
|
|
||||||
state* (mf/use-state false)
|
state* (mf/use-state false)
|
||||||
|
@ -84,7 +86,7 @@
|
||||||
(->> (vals threads-map)
|
(->> (vals threads-map)
|
||||||
(sort-by :modified-at)
|
(sort-by :modified-at)
|
||||||
(reverse)
|
(reverse)
|
||||||
(dcm/apply-filters local profile))
|
(dcmt/apply-filters local profile))
|
||||||
threads)
|
threads)
|
||||||
|
|
||||||
close-section
|
close-section
|
||||||
|
@ -92,12 +94,12 @@
|
||||||
(mf/deps from-viewer)
|
(mf/deps from-viewer)
|
||||||
(fn []
|
(fn []
|
||||||
(if from-viewer
|
(if from-viewer
|
||||||
(st/emit! (dcm/update-options {:show-sidebar? false}))
|
(st/emit! (dcmt/update-options {:show-sidebar? false}))
|
||||||
(st/emit! (dw/clear-edition-mode)
|
(st/emit! (dw/clear-edition-mode)
|
||||||
(dw/deselect-all true)))))
|
(dw/deselect-all true)))))
|
||||||
|
|
||||||
tgroups (->> threads
|
tgroups (->> threads
|
||||||
(dcm/group-threads-by-page))
|
(dcmt/group-threads-by-page))
|
||||||
|
|
||||||
page-id (or page-id (mf/use-ctx ctx/current-page-id))
|
page-id (or page-id (mf/use-ctx ctx/current-page-id))
|
||||||
|
|
||||||
|
@ -112,14 +114,16 @@
|
||||||
(mf/deps page-id)
|
(mf/deps page-id)
|
||||||
(fn [thread]
|
(fn [thread]
|
||||||
(when (not= page-id (:page-id thread))
|
(when (not= page-id (:page-id thread))
|
||||||
(st/emit! (dw/go-to-page (:page-id thread))))
|
(st/emit! (dcm/go-to-workspace :page-id (:page-id thread)
|
||||||
|
::rt/new-window true)))
|
||||||
(tm/schedule
|
(tm/schedule
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (when (not= page-id (:page-id thread))
|
(st/emit! (when (not= page-id (:page-id thread))
|
||||||
(dw/select-for-drawing :comments))
|
(dw/select-for-drawing :comments))
|
||||||
(dwcm/center-to-comment-thread thread)
|
(dwcm/center-to-comment-thread thread)
|
||||||
(-> (dcm/open-thread thread)
|
(-> (dcmt/open-thread thread)
|
||||||
(with-meta {::ev/origin "workspace"})))))))]
|
(with-meta {::ev/origin "workspace"})))))))]
|
||||||
|
|
||||||
[:div {:class (stl/css-case :comments-section true
|
[:div {:class (stl/css-case :comments-section true
|
||||||
:from-viewer from-viewer)}
|
:from-viewer from-viewer)}
|
||||||
[:div {:class (stl/css-case :comments-section-title true
|
[:div {:class (stl/css-case :comments-section-title true
|
||||||
|
@ -149,12 +153,12 @@
|
||||||
[:& cmt/comment-thread-group
|
[:& cmt/comment-thread-group
|
||||||
{:group (first tgroups)
|
{:group (first tgroups)
|
||||||
:on-thread-click on-thread-click
|
:on-thread-click on-thread-click
|
||||||
:users users}]
|
:profiles profiles}]
|
||||||
(for [tgroup (rest tgroups)]
|
(for [tgroup (rest tgroups)]
|
||||||
[:& cmt/comment-thread-group
|
[:& cmt/comment-thread-group
|
||||||
{:group tgroup
|
{:group tgroup
|
||||||
:on-thread-click on-thread-click
|
:on-thread-click on-thread-click
|
||||||
:users users
|
:profiles profiles
|
||||||
:key (:page-id tgroup)}])]
|
:key (:page-id tgroup)}])]
|
||||||
|
|
||||||
[:div {:class (stl/css :thread-group-placeholder)}
|
[:div {:class (stl/css :thread-group-placeholder)}
|
||||||
|
|
|
@ -8,10 +8,12 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.colors :as dc]
|
[app.main.data.workspace.colors :as dc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
@ -19,21 +21,20 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
;; --- Header Component
|
;; --- Header Component
|
||||||
|
|
||||||
(mf/defc left-header
|
(mf/defc left-header
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj}
|
||||||
[{:keys [file layout project page-id class]}]
|
[{:keys [file layout project page-id class]}]
|
||||||
(let [profile (mf/deref refs/profile)
|
(let [profile (mf/deref refs/profile)
|
||||||
file-id (:id file)
|
file-id (:id file)
|
||||||
file-name (:name file)
|
file-name (:name file)
|
||||||
project-id (:id project)
|
|
||||||
team-id (:team-id project)
|
team-id (:team-id project)
|
||||||
shared? (:is-shared file)
|
shared? (:is-shared file)
|
||||||
|
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
|
|
||||||
editing* (mf/use-state false)
|
editing* (mf/use-state false)
|
||||||
|
@ -69,22 +70,20 @@
|
||||||
|
|
||||||
go-back
|
go-back
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project)
|
|
||||||
(fn []
|
(fn []
|
||||||
(close-modals)
|
(close-modals)
|
||||||
|
;; FIXME: move set-mode to uri?
|
||||||
(st/emit! (dw/set-options-mode :design)
|
(st/emit! (dw/set-options-mode :design)
|
||||||
(dw/go-to-dashboard project))))
|
(dcm/go-to-dashboard-recent))))
|
||||||
|
|
||||||
nav-to-project
|
nav-to-project
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps team-id project-id)
|
#(st/emit! (dcm/go-to-dashboard-files ::rt/new-window true)))]
|
||||||
#(st/emit! (rt/nav-new-window* {:rname :dashboard-files
|
|
||||||
:path-params {:team-id team-id
|
|
||||||
:project-id project-id}})))]
|
|
||||||
|
|
||||||
(mf/with-effect [editing?]
|
(mf/with-effect [editing?]
|
||||||
(when ^boolean editing?
|
(when ^boolean editing?
|
||||||
(dom/select-text! (mf/ref-val input-ref))))
|
(dom/select-text! (mf/ref-val input-ref))))
|
||||||
|
|
||||||
[:header {:class (dm/str class " " (stl/css :workspace-header-left))}
|
[:header {:class (dm/str class " " (stl/css :workspace-header-left))}
|
||||||
[:a {:on-click go-back
|
[:a {:on-click go-back
|
||||||
:class (stl/css :main-icon)} i/logo-icon]
|
:class (stl/css :main-icon)} i/logo-icon]
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.profile :as du]
|
[app.main.data.profile :as du]
|
||||||
|
[app.main.data.team :as dtm]
|
||||||
[app.main.data.workspace.colors :as mdc]
|
[app.main.data.workspace.colors :as mdc]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -103,10 +104,10 @@
|
||||||
[:li {:class (stl/css :element-count)}
|
[:li {:class (stl/css :element-count)}
|
||||||
(tr "workspace.libraries.typography" typography-count)])])
|
(tr "workspace.libraries.typography" typography-count)])])
|
||||||
|
|
||||||
|
(mf/defc libraries-tab*
|
||||||
(mf/defc libraries-tab
|
{::mf/props :obj
|
||||||
{::mf/wrap-props false}
|
::mf/private true}
|
||||||
[{:keys [file-id shared? linked-libraries shared-libraries]}]
|
[{:keys [file-id is-shared linked-libraries shared-libraries]}]
|
||||||
(let [search-term* (mf/use-state "")
|
(let [search-term* (mf/use-state "")
|
||||||
search-term (deref search-term*)
|
search-term (deref search-term*)
|
||||||
library-ref (mf/with-memo [file-id]
|
library-ref (mf/with-memo [file-id]
|
||||||
|
@ -127,7 +128,7 @@
|
||||||
shared-libraries
|
shared-libraries
|
||||||
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
||||||
(when shared-libraries
|
(when shared-libraries
|
||||||
(->> shared-libraries
|
(->> (vals shared-libraries)
|
||||||
(remove #(= (:id %) file-id))
|
(remove #(= (:id %) file-id))
|
||||||
(remove #(contains? linked-libraries (:id %)))
|
(remove #(contains? linked-libraries (:id %)))
|
||||||
(filter #(matches-search (:name %) search-term))
|
(filter #(matches-search (:name %) search-term))
|
||||||
|
@ -219,7 +220,7 @@
|
||||||
:graphics-count (count media)
|
:graphics-count (count media)
|
||||||
:colors-count (count colors)
|
:colors-count (count colors)
|
||||||
:typography-count (count typographies)}]]]
|
:typography-count (count typographies)}]]]
|
||||||
(if ^boolean shared?
|
(if ^boolean is-shared
|
||||||
[:input {:class (stl/css :item-unpublish)
|
[:input {:class (stl/css :item-unpublish)
|
||||||
:type "button"
|
:type "button"
|
||||||
:value (tr "common.unpublish")
|
:value (tr "common.unpublish")
|
||||||
|
@ -348,8 +349,9 @@
|
||||||
:colors colors
|
:colors colors
|
||||||
:typographies typographies}]))
|
:typographies typographies}]))
|
||||||
|
|
||||||
(mf/defc updates-tab
|
(mf/defc updates-tab*
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj
|
||||||
|
::mf/private true}
|
||||||
[{:keys [file-id file-data libraries]}]
|
[{:keys [file-id file-data libraries]}]
|
||||||
(let [summary?* (mf/use-state true)
|
(let [summary?* (mf/use-state true)
|
||||||
summary? (deref summary?*)
|
summary? (deref summary?*)
|
||||||
|
@ -487,11 +489,9 @@
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :libraries-dialog}
|
::mf/register-as :libraries-dialog}
|
||||||
[{:keys [starting-tab] :as props :or {starting-tab :libraries}}]
|
[{:keys [starting-tab] :as props :or {starting-tab :libraries}}]
|
||||||
(let [project (mf/deref refs/workspace-project)
|
(let [file-data (mf/deref refs/workspace-data)
|
||||||
file-data (mf/deref refs/workspace-data)
|
|
||||||
file (mf/deref ref:workspace-file)
|
file (mf/deref ref:workspace-file)
|
||||||
|
|
||||||
team-id (:team-id project)
|
|
||||||
file-id (:id file)
|
file-id (:id file)
|
||||||
shared? (:is-shared file)
|
shared? (:is-shared file)
|
||||||
|
|
||||||
|
@ -499,37 +499,44 @@
|
||||||
libraries (mf/with-memo [libraries]
|
libraries (mf/with-memo [libraries]
|
||||||
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||||
|
|
||||||
;; NOTE: we really don't need react on shared files
|
|
||||||
shared-libraries
|
shared-libraries
|
||||||
(mf/deref refs/workspace-shared-files)
|
(mf/deref refs/shared-files)
|
||||||
|
|
||||||
close-dialog-outside
|
close-dialog-outside
|
||||||
(mf/use-fn (fn [event]
|
(mf/use-fn
|
||||||
|
(fn [event]
|
||||||
(when (= (dom/get-target event) (dom/get-current-target event))
|
(when (= (dom/get-target event) (dom/get-current-target event))
|
||||||
(modal/hide!))))
|
(modal/hide!))))
|
||||||
|
|
||||||
close-dialog
|
close-dialog
|
||||||
(mf/use-fn (fn [_]
|
(mf/use-fn
|
||||||
|
(fn [_]
|
||||||
(modal/hide!)
|
(modal/hide!)
|
||||||
(modal/disallow-click-outside!)))
|
(modal/disallow-click-outside!)))
|
||||||
|
|
||||||
|
libraries-tab
|
||||||
|
(mf/html [:> libraries-tab*
|
||||||
|
{:file-id file-id
|
||||||
|
:is-shared shared?
|
||||||
|
:linked-libraries libraries
|
||||||
|
:shared-libraries shared-libraries}])
|
||||||
|
|
||||||
|
updates-tab
|
||||||
|
(mf/html [:> updates-tab*
|
||||||
|
{:file-id file-id
|
||||||
|
:file-data file-data
|
||||||
|
:libraries libraries}])
|
||||||
|
|
||||||
tabs
|
tabs
|
||||||
#js [#js {:label (tr "workspace.libraries.libraries")
|
#js [#js {:label (tr "workspace.libraries.libraries")
|
||||||
:id "libraries"
|
:id "libraries"
|
||||||
:content (mf/html [:& libraries-tab {:file-id file-id
|
:content libraries-tab}
|
||||||
:shared? shared?
|
|
||||||
:linked-libraries libraries
|
|
||||||
:shared-libraries shared-libraries}])}
|
|
||||||
|
|
||||||
#js {:label (tr "workspace.libraries.updates")
|
#js {:label (tr "workspace.libraries.updates")
|
||||||
:id "updates"
|
:id "updates"
|
||||||
:content (mf/html [:& updates-tab {:file-id file-id
|
:content updates-tab}]]
|
||||||
:file-data file-data
|
|
||||||
:libraries libraries}])}]]
|
|
||||||
|
|
||||||
(mf/with-effect [team-id]
|
(mf/with-effect []
|
||||||
(when team-id
|
(st/emit! (dtm/fetch-shared-files)))
|
||||||
(st/emit! (dwl/fetch-shared-files {:team-id team-id}))))
|
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-overlay) :on-click close-dialog-outside :data-testid "libraries-modal"}
|
[:div {:class (stl/css :modal-overlay) :on-click close-dialog-outside :data-testid "libraries-modal"}
|
||||||
[:div {:class (stl/css :modal-dialog)}
|
[:div {:class (stl/css :modal-dialog)}
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -68,7 +67,7 @@
|
||||||
(mf/use-fn #(dom/open-new-window "https://penpot.app/terms"))
|
(mf/use-fn #(dom/open-new-window "https://penpot.app/terms"))
|
||||||
|
|
||||||
nav-to-feedback
|
nav-to-feedback
|
||||||
(mf/use-fn #(st/emit! (rt/nav-new-window* {:rname :settings-feedback})))
|
(mf/use-fn #(st/emit! (dcm/go-to-feedback)))
|
||||||
|
|
||||||
plugins?
|
plugins?
|
||||||
(features/active-feature? @st/state "plugins/runtime")
|
(features/active-feature? @st/state "plugins/runtime")
|
||||||
|
@ -540,9 +539,8 @@
|
||||||
|
|
||||||
on-pin-version
|
on-pin-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(st/emit! (dwv/create-version file-id))))
|
(st/emit! (dwv/create-version))))
|
||||||
|
|
||||||
on-pin-version-key-down
|
on-pin-version-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
(mf/defc active-sessions
|
(mf/defc active-sessions
|
||||||
{::mf/memo true}
|
{::mf/memo true}
|
||||||
[]
|
[]
|
||||||
(let [users (mf/deref refs/users)
|
(let [profiles (mf/deref refs/profiles)
|
||||||
presence (mf/deref refs/workspace-presence)
|
presence (mf/deref refs/workspace-presence)
|
||||||
|
|
||||||
sessions (vals presence)
|
sessions (vals presence)
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
[:& session-widget
|
[:& session-widget
|
||||||
{:color (:color session)
|
{:color (:color session)
|
||||||
:index 0
|
:index 0
|
||||||
:profile (get users (:profile-id session))
|
:profile (get profiles (:profile-id session))
|
||||||
:key (dm/str (:id session))}])]])
|
:key (dm/str (:id session))}])]])
|
||||||
|
|
||||||
[:button {:class (stl/css-case :active-users true)
|
[:button {:class (stl/css-case :active-users true)
|
||||||
|
@ -74,5 +74,5 @@
|
||||||
[:& session-widget
|
[:& session-widget
|
||||||
{:color (:color session)
|
{:color (:color session)
|
||||||
:index index
|
:index index
|
||||||
:profile (get users (:profile-id session))
|
:profile (get profiles (:profile-id session))
|
||||||
:key (dm/str (:id session))}])]]]))
|
:key (dm/str (:id session))}])]]]))
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.shortcuts :as scd]
|
[app.main.data.shortcuts :as scd]
|
||||||
|
@ -169,7 +170,7 @@
|
||||||
(let [params {:page-id page-id
|
(let [params {:page-id page-id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:section "interactions"}]
|
:section "interactions"}]
|
||||||
(st/emit! (dw/go-to-viewer params)))))
|
(st/emit! (dcm/go-to-viewer params)))))
|
||||||
|
|
||||||
active-comments
|
active-comments
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
[app.main.features :as features]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as muc]
|
[app.main.ui.context :as muc]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||||
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
[app.main.ui.hooks.resize :refer [use-resize-hook]]
|
||||||
[app.main.ui.workspace.comments :refer [comments-sidebar]]
|
[app.main.ui.workspace.comments :refer [comments-sidebar*]]
|
||||||
[app.main.ui.workspace.left-header :refer [left-header]]
|
[app.main.ui.workspace.left-header :refer [left-header]]
|
||||||
[app.main.ui.workspace.right-header :refer [right-header]]
|
[app.main.ui.workspace.right-header :refer [right-header]]
|
||||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
|
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
|
||||||
|
@ -47,36 +49,44 @@
|
||||||
|
|
||||||
(mf/defc left-sidebar
|
(mf/defc left-sidebar
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/props :obj}
|
||||||
[{:keys [layout file page-id] :as props}]
|
[{:keys [layout file page-id] :as props}]
|
||||||
(let [options-mode (mf/deref refs/options-mode-global)
|
(let [options-mode (mf/deref refs/options-mode-global)
|
||||||
|
project (mf/deref refs/project)
|
||||||
|
|
||||||
|
design-tokens? (features/use-feature "design-tokens/v1")
|
||||||
mode-inspect? (= options-mode :inspect)
|
mode-inspect? (= options-mode :inspect)
|
||||||
project (mf/deref refs/workspace-project)
|
|
||||||
|
|
||||||
design-tokens? (mf/use-ctx muc/design-tokens)
|
|
||||||
|
|
||||||
section (cond (or mode-inspect? (contains? layout :layers)) :layers
|
|
||||||
(contains? layout :assets) :assets
|
|
||||||
(contains? layout :tokens) :tokens)
|
|
||||||
|
|
||||||
shortcuts? (contains? layout :shortcuts)
|
shortcuts? (contains? layout :shortcuts)
|
||||||
show-debug? (contains? layout :debug-panel)
|
show-debug? (contains? layout :debug-panel)
|
||||||
|
|
||||||
{on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size}
|
section (cond
|
||||||
|
(or mode-inspect? (contains? layout :layers)) :layers
|
||||||
|
(contains? layout :assets) :assets
|
||||||
|
(contains? layout :tokens) :tokens)
|
||||||
|
|
||||||
|
{on-pointer-down :on-pointer-down
|
||||||
|
on-lost-pointer-capture :on-lost-pointer-capture
|
||||||
|
on-pointer-move :on-pointer-move
|
||||||
|
parent-ref :parent-ref
|
||||||
|
size :size}
|
||||||
(use-resize-hook :left-sidebar 275 275 500 :x false :left)
|
(use-resize-hook :left-sidebar 275 275 500 :x false :left)
|
||||||
|
|
||||||
{on-pointer-down-pages :on-pointer-down on-lost-pointer-capture-pages :on-lost-pointer-capture on-pointer-move-pages :on-pointer-move size-pages-opened :size}
|
{on-pointer-down-pages :on-pointer-down
|
||||||
|
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
||||||
|
on-pointer-move-pages :on-pointer-move
|
||||||
|
size-pages-opened :size}
|
||||||
(use-resize-hook :sitemap 200 38 400 :y false nil)
|
(use-resize-hook :sitemap 200 38 400 :y false nil)
|
||||||
|
|
||||||
show-pages? (mf/use-state true)
|
show-pages? (mf/use-state true)
|
||||||
toggle-pages (mf/use-callback #(reset! show-pages? not))
|
toggle-pages (mf/use-fn #(reset! show-pages? not))
|
||||||
size-pages (mf/use-memo (mf/deps show-pages? size-pages-opened) (fn [] (if @show-pages? size-pages-opened 32)))
|
size-pages (mf/with-memo [show-pages? size-pages-opened]
|
||||||
|
(if @show-pages? size-pages-opened 32))
|
||||||
|
|
||||||
handle-collapse
|
handle-collapse
|
||||||
(mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
(mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
||||||
|
|
||||||
on-tab-change
|
on-tab-change
|
||||||
(mf/use-fn #(st/emit! (dw/go-to-layout (keyword %))))
|
(mf/use-fn #(st/emit! (dcm/go-to-workspace :layout (keyword %))))
|
||||||
|
|
||||||
layers-tab
|
layers-tab
|
||||||
(mf/html
|
(mf/html
|
||||||
|
@ -138,7 +148,11 @@
|
||||||
:global/four-row (> size 400))
|
:global/four-row (> size 400))
|
||||||
:style #js {"--width" (dm/str size "px")}}
|
:style #js {"--width" (dm/str size "px")}}
|
||||||
|
|
||||||
[:& left-header {:file file :layout layout :project project :page-id page-id
|
[:& left-header
|
||||||
|
{:file file
|
||||||
|
:layout layout
|
||||||
|
:project project
|
||||||
|
:page-id page-id
|
||||||
:class (stl/css :left-header)}]
|
:class (stl/css :left-header)}]
|
||||||
|
|
||||||
[:div {:on-pointer-down on-pointer-down
|
[:div {:on-pointer-down on-pointer-down
|
||||||
|
@ -234,7 +248,7 @@
|
||||||
[:& debug-shape-info]
|
[:& debug-shape-info]
|
||||||
|
|
||||||
(true? is-comments?)
|
(true? is-comments?)
|
||||||
[:& comments-sidebar]
|
[:> comments-sidebar* {}]
|
||||||
|
|
||||||
(true? is-history?)
|
(true? is-history?)
|
||||||
[:> tab-switcher*
|
[:> tab-switcher*
|
||||||
|
|
|
@ -25,9 +25,10 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc assets-libraries
|
(mf/defc assets-libraries*
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/props :obj
|
||||||
|
::mf/private true}
|
||||||
[{:keys [filters]}]
|
[{:keys [filters]}]
|
||||||
(let [libraries (mf/deref refs/workspace-libraries)
|
(let [libraries (mf/deref refs/workspace-libraries)
|
||||||
libraries (mf/with-memo [libraries]
|
libraries (mf/with-memo [libraries]
|
||||||
|
@ -193,4 +194,4 @@
|
||||||
[:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style}
|
[:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style}
|
||||||
[:*
|
[:*
|
||||||
[:& assets-local-library {:filters filters}]
|
[:& assets-local-library {:filters filters}]
|
||||||
[:& assets-libraries {:filters filters}]]]]]]))
|
[:> assets-libraries* {:filters filters}]]]]]]))
|
||||||
|
|
|
@ -391,20 +391,18 @@
|
||||||
(do-update-remote-component))
|
(do-update-remote-component))
|
||||||
|
|
||||||
do-show-in-assets
|
do-show-in-assets
|
||||||
#(st/emit! (if components-v2
|
#(st/emit! (dw/show-component-in-assets component-id))
|
||||||
(dw/show-component-in-assets component-id)
|
|
||||||
(dw/go-to-component component-id)))
|
|
||||||
|
|
||||||
do-create-annotation
|
do-create-annotation
|
||||||
#(st/emit! (dw/set-annotations-id-for-create id))
|
#(st/emit! (dw/set-annotations-id-for-create id))
|
||||||
|
|
||||||
do-show-local-component
|
do-show-local-component
|
||||||
#(st/emit! (dw/go-to-component component-id))
|
#(st/emit! (dwl/go-to-local-component component-id))
|
||||||
|
|
||||||
|
;; When the show-remote is after a restore, the component may still be deleted
|
||||||
do-show-remote-component
|
do-show-remote-component
|
||||||
#(let [comp (find-component shape true)] ;; When the show-remote is after a restore, the component may still be deleted
|
#(when-let [comp (find-component shape true)]
|
||||||
(when comp
|
(st/emit! (dwl/go-to-component-file library-id comp)))
|
||||||
(st/emit! (dwl/nav-to-component-file library-id comp))))
|
|
||||||
|
|
||||||
do-show-component
|
do-show-component
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -98,8 +98,8 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(if local
|
(if local
|
||||||
(st/emit! (dw/go-to-component component-id))
|
(st/emit! (dwl/go-to-local-component component-id))
|
||||||
(st/emit! (dwl/nav-to-component-file file-id component)))))
|
(st/emit! (dwl/go-to-component-file file-id component)))))
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -491,9 +491,9 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(if local?
|
(if local?
|
||||||
(st/emit! (dw/go-to-component current-component-id))
|
(st/emit! (dwl/go-to-local-component :id current-component-id))
|
||||||
(let [component (d/seek #(= (:id %) current-component-id) components)]
|
(let [component (d/seek #(= (:id %) current-component-id) components)]
|
||||||
(st/emit! (dwl/nav-to-component-file file-id component))))))
|
(st/emit! (dwl/go-to-component-file file-id component))))))
|
||||||
|
|
||||||
on-asset-click
|
on-asset-click
|
||||||
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
|
@ -27,54 +28,53 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.router :as rt]
|
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[potok.v2.core :as ptk]
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def lens:open-status
|
(def ^:private ref:open-status
|
||||||
(l/derived (l/in [:workspace-assets :open-status]) st/state))
|
(l/derived (l/in [:workspace-assets :open-status]) st/state))
|
||||||
|
|
||||||
(def lens:selected
|
(def ^:private ref:selected
|
||||||
(-> (l/in [:workspace-assets :selected])
|
(-> (l/in [:workspace-assets :selected])
|
||||||
(l/derived st/state)))
|
(l/derived st/state)))
|
||||||
|
|
||||||
(mf/defc file-library-title
|
(mf/defc file-library-title*
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj}
|
||||||
[{:keys [open? local? project-id file-id page-id file-name]}]
|
[{:keys [is-open is-local file-id page-id file-name]}]
|
||||||
(let [router (mf/deref refs/router)
|
(let [router (mf/deref refs/router)
|
||||||
|
team-id (mf/use-ctx ctx/current-team-id)
|
||||||
url (rt/resolve router :workspace
|
url (rt/resolve router :workspace
|
||||||
{:project-id project-id
|
{:team-id team-id
|
||||||
:file-id file-id}
|
:file-id file-id
|
||||||
{:page-id page-id})
|
:page-id page-id})
|
||||||
toggle-open
|
toggle-open
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id open?)
|
(mf/deps file-id is-open)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dw/set-assets-section-open file-id :library (not open?)))))
|
(st/emit! (dw/set-assets-section-open file-id :library (not is-open)))))
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [ev]
|
(fn [ev]
|
||||||
(dom/stop-propagation ev)
|
(dom/stop-propagation ev)
|
||||||
(st/emit!
|
(st/emit! (ptk/data-event ::ev/event {::ev/name "navigate-to-library-file"}))))]
|
||||||
(ptk/event ::ev/event {::ev/name "navigate-to-library-file"}))))]
|
|
||||||
|
|
||||||
[:div {:class (stl/css-case :library-title true
|
[:div {:class (stl/css-case :library-title true
|
||||||
:open open?)}
|
:open is-open)}
|
||||||
[:& title-bar {:collapsable true
|
[:& title-bar {:collapsable true
|
||||||
:collapsed (not open?)
|
:collapsed (not is-open)
|
||||||
:all-clickable true
|
:all-clickable true
|
||||||
:on-collapsed toggle-open
|
:on-collapsed toggle-open
|
||||||
:title (if local?
|
:title (if is-local
|
||||||
(mf/html [:div {:class (stl/css :special-title)}
|
(mf/html [:div {:class (stl/css :special-title)}
|
||||||
(tr "workspace.assets.local-library")])
|
(tr "workspace.assets.local-library")])
|
||||||
;; Do we need to add shared info here?
|
;; Do we need to add shared info here?
|
||||||
|
|
||||||
(mf/html [:div {:class (stl/css :special-title)}
|
(mf/html [:div {:class (stl/css :special-title)}
|
||||||
file-name]))}
|
file-name]))}
|
||||||
(when-not local?
|
(when-not is-local
|
||||||
[:span {:title (tr "workspace.assets.open-library")}
|
[:span {:title (tr "workspace.assets.open-library")}
|
||||||
[:a {:class (stl/css :file-link)
|
[:a {:class (stl/css :file-link)
|
||||||
:href (str "#" url)
|
:href (str "#" url)
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
|
|
||||||
selected-lens (mf/with-memo [file-id]
|
selected-lens (mf/with-memo [file-id]
|
||||||
(-> (l/key file-id)
|
(-> (l/key file-id)
|
||||||
(l/derived lens:selected)))
|
(l/derived ref:selected)))
|
||||||
|
|
||||||
selected (mf/deref selected-lens)
|
selected (mf/deref selected-lens)
|
||||||
|
|
||||||
|
@ -329,17 +329,15 @@
|
||||||
(some #(> 60 (count %)) [filtered-components filtered-colors filtered-media filtered-typographies]))))
|
(some #(> 60 (count %)) [filtered-components filtered-colors filtered-media filtered-typographies]))))
|
||||||
|
|
||||||
(mf/defc file-library
|
(mf/defc file-library
|
||||||
{::mf/wrap-props false}
|
{::mf/props :obj}
|
||||||
[{:keys [file local? default-open? filters]}]
|
[{:keys [file local? default-open? filters]}]
|
||||||
(let [file-id (:id file)
|
(let [file-id (:id file)
|
||||||
file-name (:name file)
|
file-name (:name file)
|
||||||
shared? (:is-shared file)
|
|
||||||
project-id (:project-id file)
|
|
||||||
page-id (dm/get-in file [:data :pages 0])
|
page-id (dm/get-in file [:data :pages 0])
|
||||||
|
|
||||||
open-status-ref (mf/with-memo [file-id]
|
open-status-ref (mf/with-memo [file-id]
|
||||||
(-> (l/key file-id)
|
(-> (l/key file-id)
|
||||||
(l/derived lens:open-status)))
|
(l/derived ref:open-status)))
|
||||||
open-status (mf/deref open-status-ref)
|
open-status (mf/deref open-status-ref)
|
||||||
force-open-lib? (force-lib-open? file-id filters)
|
force-open-lib? (force-lib-open? file-id filters)
|
||||||
|
|
||||||
|
@ -356,14 +354,12 @@
|
||||||
[:div {:class (stl/css :tool-window)
|
[:div {:class (stl/css :tool-window)
|
||||||
:on-context-menu dom/prevent-default
|
:on-context-menu dom/prevent-default
|
||||||
:on-click unselect-all}
|
:on-click unselect-all}
|
||||||
[:& file-library-title
|
[:> file-library-title*
|
||||||
{:project-id project-id
|
{:file-id file-id
|
||||||
:file-id file-id
|
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:file-name file-name
|
:file-name file-name
|
||||||
:open? open?
|
:is-open open?
|
||||||
:local? local?
|
:is-local local?}]
|
||||||
:shared? shared?}]
|
|
||||||
(when ^boolean open?
|
(when ^boolean open?
|
||||||
[:& file-library-content
|
[:& file-library-content
|
||||||
{:file file
|
{:file file
|
||||||
|
|
|
@ -277,7 +277,6 @@
|
||||||
(assoc file :data data))))]
|
(assoc file :data data))))]
|
||||||
(l/derived get-libraries st/state)))
|
(l/derived get-libraries st/state)))
|
||||||
|
|
||||||
|
|
||||||
(defn- find-common-path
|
(defn- find-common-path
|
||||||
([components]
|
([components]
|
||||||
(let [paths (map (comp cfh/split-path :path) components)]
|
(let [paths (map (comp cfh/split-path :path) components)]
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.fonts :as fts]
|
[app.main.data.fonts :as fts]
|
||||||
[app.main.data.shortcuts :as dsc]
|
[app.main.data.shortcuts :as dsc]
|
||||||
[app.main.data.workspace :as dw]
|
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -564,7 +564,7 @@
|
||||||
(mf/deps file-id)
|
(mf/deps file-id)
|
||||||
(fn []
|
(fn []
|
||||||
(when file-id
|
(when file-id
|
||||||
(st/emit! (dw/navigate-to-library file-id)))))
|
(st/emit! (dcm/go-to-workspace :file-id file-id)))))
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -34,7 +35,7 @@
|
||||||
(let [input-ref (mf/use-ref)
|
(let [input-ref (mf/use-ref)
|
||||||
id (:id page)
|
id (:id page)
|
||||||
delete-fn (mf/use-fn (mf/deps id) #(st/emit! (dw/delete-page id)))
|
delete-fn (mf/use-fn (mf/deps id) #(st/emit! (dw/delete-page id)))
|
||||||
navigate-fn (mf/use-fn (mf/deps id) #(st/emit! :interrupt (dw/go-to-page id)))
|
navigate-fn (mf/use-fn (mf/deps id) #(st/emit! :interrupt (dcm/go-to-workspace :page-id id)))
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
|
|
|
@ -226,12 +226,12 @@
|
||||||
|
|
||||||
(mf/defc versions-toolbox
|
(mf/defc versions-toolbox
|
||||||
[]
|
[]
|
||||||
(let [users (mf/deref refs/users)
|
(let [profiles (mf/deref refs/profiles)
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
project-id (mf/deref refs/current-project-id)
|
|
||||||
file-id (mf/deref refs/current-file-id)
|
|
||||||
expanded (mf/use-state #{})
|
expanded (mf/use-state #{})
|
||||||
|
|
||||||
|
|
||||||
{:keys [status data editing]}
|
{:keys [status data editing]}
|
||||||
(mf/deref versions)
|
(mf/deref versions)
|
||||||
|
|
||||||
|
@ -242,7 +242,6 @@
|
||||||
(fn []
|
(fn []
|
||||||
(into #{} (keep (fn [{:keys [created-by profile-id]}]
|
(into #{} (keep (fn [{:keys [created-by profile-id]}]
|
||||||
(when (= "user" created-by) profile-id))) data)))
|
(when (= "user" created-by) profile-id))) data)))
|
||||||
|
|
||||||
data
|
data
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(mf/deps @versions)
|
(mf/deps @versions)
|
||||||
|
@ -257,7 +256,7 @@
|
||||||
handle-create-version
|
handle-create-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwv/create-version file-id))))
|
(st/emit! (dwv/create-version))))
|
||||||
|
|
||||||
handle-toggle-expand
|
handle-toggle-expand
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -271,14 +270,12 @@
|
||||||
|
|
||||||
handle-rename-version
|
handle-rename-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
|
||||||
(fn [id label]
|
(fn [id label]
|
||||||
(st/emit! (dwv/rename-version file-id id label))))
|
(st/emit! (dwv/rename-version id label))))
|
||||||
|
|
||||||
|
|
||||||
handle-restore-version
|
handle-restore-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps project-id file-id)
|
|
||||||
(fn [origin id]
|
(fn [origin id]
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(ntf/dialog
|
(ntf/dialog
|
||||||
|
@ -289,7 +286,7 @@
|
||||||
:callback #(st/emit! (ntf/hide))}
|
:callback #(st/emit! (ntf/hide))}
|
||||||
{:label (tr "labels.restore")
|
{:label (tr "labels.restore")
|
||||||
:type :primary
|
:type :primary
|
||||||
:callback #(st/emit! (dwv/restore-version project-id file-id id origin))}]
|
:callback #(st/emit! (dwv/restore-version id origin))}]
|
||||||
:tag :restore-dialog))))
|
:tag :restore-dialog))))
|
||||||
|
|
||||||
handle-restore-version-pinned
|
handle-restore-version-pinned
|
||||||
|
@ -306,15 +303,13 @@
|
||||||
|
|
||||||
handle-delete-version
|
handle-delete-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
|
||||||
(fn [id]
|
(fn [id]
|
||||||
(st/emit! (dwv/delete-version file-id id))))
|
(st/emit! (dwv/delete-version id))))
|
||||||
|
|
||||||
handle-pin-version
|
handle-pin-version
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
|
||||||
(fn [id]
|
(fn [id]
|
||||||
(st/emit! (dwv/pin-version file-id id))))
|
(st/emit! (dwv/pin-version id))))
|
||||||
|
|
||||||
handle-change-filter
|
handle-change-filter
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -329,10 +324,8 @@
|
||||||
:else
|
:else
|
||||||
(st/emit! (dwv/update-version-state {:filter filter})))))]
|
(st/emit! (dwv/update-version-state {:filter filter})))))]
|
||||||
|
|
||||||
(mf/with-effect
|
(mf/with-effect []
|
||||||
[file-id]
|
(st/emit! (dwv/init-version-state)))
|
||||||
(when file-id
|
|
||||||
(st/emit! (dwv/init-version-state file-id))))
|
|
||||||
|
|
||||||
[:div {:class (stl/css :version-toolbox)}
|
[:div {:class (stl/css :version-toolbox)}
|
||||||
[:& select
|
[:& select
|
||||||
|
@ -343,7 +336,7 @@
|
||||||
(->> data-users
|
(->> data-users
|
||||||
(keep
|
(keep
|
||||||
(fn [id]
|
(fn [id]
|
||||||
(let [{:keys [fullname]} (get users id)]
|
(let [{:keys [fullname]} (get profiles id)]
|
||||||
(when (not= id (:id profile))
|
(when (not= id (:id profile))
|
||||||
{:value id :label (tr "workspace.versions.filter.user" fullname)}))))))
|
{:value id :label (tr "workspace.versions.filter.user" fullname)}))))))
|
||||||
:on-change handle-change-filter}]
|
:on-change handle-change-filter}]
|
||||||
|
@ -374,7 +367,7 @@
|
||||||
[:& version-entry {:key idx-entry
|
[:& version-entry {:key idx-entry
|
||||||
:entry entry
|
:entry entry
|
||||||
:editing? (= (:id entry) editing)
|
:editing? (= (:id entry) editing)
|
||||||
:profile (get users (:profile-id entry))
|
:profile (get profiles (:profile-id entry))
|
||||||
:on-rename-version handle-rename-version
|
:on-rename-version handle-rename-version
|
||||||
:on-restore-version handle-restore-version-pinned
|
:on-restore-version handle-restore-version-pinned
|
||||||
:on-delete-version handle-delete-version}]
|
:on-delete-version handle-delete-version}]
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
pos-y (* (- vbox-y) zoom)
|
pos-y (* (- vbox-y) zoom)
|
||||||
|
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
users (mf/deref refs/current-file-comments-users)
|
profiles (mf/deref refs/profiles)
|
||||||
local (mf/deref refs/comments-local)
|
local (mf/deref refs/comments-local)
|
||||||
|
|
||||||
positions-ref
|
positions-ref
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
(when-let [thread (get threads-map id)]
|
(when-let [thread (get threads-map id)]
|
||||||
(when (seq (dcm/apply-filters local profile [thread]))
|
(when (seq (dcm/apply-filters local profile [thread]))
|
||||||
[:& cmt/thread-comments {:thread (update-position positions thread)
|
[:& cmt/thread-comments {:thread (update-position positions thread)
|
||||||
:users users
|
:profiles profiles
|
||||||
:viewport {:offset-x pos-x :offset-y pos-y :width (:width vport) :height (:height vport)}
|
:viewport {:offset-x pos-x :offset-y pos-y :width (:width vport) :height (:height vport)}
|
||||||
:zoom zoom}])))
|
:zoom zoom}])))
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [page-id]}]
|
[{:keys [page-id]}]
|
||||||
(let [counter (mf/use-state 0)
|
(let [counter (mf/use-state 0)
|
||||||
users (mf/deref refs/users)
|
profiles (mf/deref refs/profiles)
|
||||||
sessions (mf/deref refs/workspace-presence)
|
sessions (mf/deref refs/workspace-presence)
|
||||||
zoom (mf/deref refs/selected-zoom)
|
zoom (mf/deref refs/selected-zoom)
|
||||||
|
|
||||||
|
@ -73,5 +73,5 @@
|
||||||
[:& session-cursor
|
[:& session-cursor
|
||||||
{:session session
|
{:session session
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:profile (get users (:profile-id session))
|
:profile (get profiles (:profile-id session))
|
||||||
:key (dm/str (:id session))}])))
|
:key (dm/str (:id session))}])))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.interactions :as dwi]
|
[app.main.data.workspace.interactions :as dwi]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -291,7 +292,7 @@
|
||||||
(when (dom/left-mouse? event)
|
(when (dom/left-mouse? event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dw/go-to-viewer params))))))
|
(st/emit! (dcm/go-to-viewer params))))))
|
||||||
|
|
||||||
on-double-click
|
on-double-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.changes :as ch]
|
[app.main.data.changes :as ch]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.bool :as dwb]
|
[app.main.data.workspace.bool :as dwb]
|
||||||
[app.main.data.workspace.colors :as dwc]
|
[app.main.data.workspace.colors :as dwc]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.media :as dwm]
|
[app.main.data.workspace.media :as dwm]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
|
[app.main.router :as rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.events :as events]
|
[app.plugins.events :as events]
|
||||||
[app.plugins.file :as file]
|
[app.plugins.file :as file]
|
||||||
|
@ -409,7 +411,7 @@
|
||||||
(let [params {:page-id (:current-page-id @st/state)
|
(let [params {:page-id (:current-page-id @st/state)
|
||||||
:file-id (:current-file-id @st/state)
|
:file-id (:current-file-id @st/state)
|
||||||
:section "interactions"}]
|
:section "interactions"}]
|
||||||
(st/emit! (dw/go-to-viewer params))))
|
(st/emit! (dcm/go-to-viewer params))))
|
||||||
|
|
||||||
:createPage
|
:createPage
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -420,7 +422,7 @@
|
||||||
:openPage
|
:openPage
|
||||||
(fn [page]
|
(fn [page]
|
||||||
(let [id (obj/get page "$id")]
|
(let [id (obj/get page "$id")]
|
||||||
(st/emit! (dw/go-to-page id))))
|
(st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window true))))
|
||||||
|
|
||||||
:alignHorizontal
|
:alignHorizontal
|
||||||
(fn [shapes direction]
|
(fn [shapes direction]
|
||||||
|
|
|
@ -70,14 +70,15 @@
|
||||||
|
|
||||||
:restore
|
:restore
|
||||||
(fn []
|
(fn []
|
||||||
|
(js/Promise.
|
||||||
|
(fn [resolve reject]
|
||||||
(cond
|
(cond
|
||||||
(not (r/check-permission plugin-id "content:write"))
|
(not (r/check-permission plugin-id "content:write"))
|
||||||
(u/display-not-valid :restore "Plugin doesn't have 'content:write' permission")
|
(u/reject-not-valid reject :restore "Plugin doesn't have 'content:write' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [project-id (:current-project-id @st/state)
|
(let [version-id (get @data :id)]
|
||||||
version-id (get @data :id)]
|
(st/emit! (dwv/restore-version-from-plugin file-id version-id resolve reject)))))))
|
||||||
(st/emit! (dwv/restore-version project-id file-id version-id :plugin)))))
|
|
||||||
|
|
||||||
:remove
|
:remove
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -90,7 +91,8 @@
|
||||||
:else
|
:else
|
||||||
(let [version-id (:id @data)]
|
(let [version-id (:id @data)]
|
||||||
(->> (rp/cmd! :delete-file-snapshot {:id version-id})
|
(->> (rp/cmd! :delete-file-snapshot {:id version-id})
|
||||||
(rx/subs! #(resolve) reject)))))))
|
(rx/map (constantly nil))
|
||||||
|
(rx/subs! resolve reject)))))))
|
||||||
|
|
||||||
:pin
|
:pin
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.comments :as dc]
|
[app.main.data.comments :as dc]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.guides :as dwgu]
|
[app.main.data.workspace.guides :as dwgu]
|
||||||
[app.main.data.workspace.interactions :as dwi]
|
[app.main.data.workspace.interactions :as dwi]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.router :as-alias rt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.comments :as pc]
|
[app.plugins.comments :as pc]
|
||||||
[app.plugins.format :as format]
|
[app.plugins.format :as format]
|
||||||
|
@ -266,7 +268,7 @@
|
||||||
(u/display-not-valid :openPage "Plugin doesn't have 'content:read' permission")
|
(u/display-not-valid :openPage "Plugin doesn't have 'content:read' permission")
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(st/emit! (dw/go-to-page id))))
|
(st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window true))))
|
||||||
|
|
||||||
:createFlow
|
:createFlow
|
||||||
(fn [name frame]
|
(fn [name frame]
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[goog.dom :as dom]
|
[goog.dom :as dom]
|
||||||
|
[potok.v2.core :as ptk]
|
||||||
[promesa.core :as p])
|
[promesa.core :as p])
|
||||||
(:import goog.events.BrowserEvent))
|
(:import goog.events.BrowserEvent))
|
||||||
|
|
||||||
|
@ -853,3 +854,10 @@
|
||||||
measures (.measureText context-2d text)]
|
measures (.measureText context-2d text)]
|
||||||
{:descent (.-actualBoundingBoxDescent measures)
|
{:descent (.-actualBoundingBoxDescent measures)
|
||||||
:ascent (.-actualBoundingBoxAscent measures)}))
|
:ascent (.-actualBoundingBoxAscent measures)}))
|
||||||
|
|
||||||
|
(defmethod ptk/resolve ::focus-element
|
||||||
|
[_ {:keys [name]}]
|
||||||
|
(ptk/reify ::focus-element
|
||||||
|
ptk/EffectEvent
|
||||||
|
(effect [_ _ _]
|
||||||
|
(focus! (get-element name)))))
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.changes :as dwc]
|
[app.main.data.changes :as dwc]
|
||||||
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.dashboard.shortcuts]
|
[app.main.data.dashboard.shortcuts]
|
||||||
[app.main.data.preview :as dp]
|
[app.main.data.preview :as dp]
|
||||||
[app.main.data.viewer.shortcuts]
|
[app.main.data.viewer.shortcuts]
|
||||||
|
@ -232,7 +233,7 @@
|
||||||
(defn ^:export select-by-object-id
|
(defn ^:export select-by-object-id
|
||||||
[object-id]
|
[object-id]
|
||||||
(let [[_ page-id shape-id _] (str/split object-id #"/")]
|
(let [[_ page-id shape-id _] (str/split object-id #"/")]
|
||||||
(st/emit! (dw/go-to-page (uuid/uuid page-id)))
|
(st/emit! (dcm/go-to-workspace :page-id (uuid/uuid page-id)))
|
||||||
(st/emit! (dws/select-shape (uuid/uuid shape-id)))))
|
(st/emit! (dws/select-shape (uuid/uuid shape-id)))))
|
||||||
|
|
||||||
(defn ^:export select-by-id
|
(defn ^:export select-by-id
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue