Show all users editing an app in the app list
This commit is contained in:
parent
4948086952
commit
b335e492d7
|
@ -2,7 +2,7 @@
|
||||||
import { Icon } from "@budibase/bbui"
|
import { Icon } from "@budibase/bbui"
|
||||||
import { createEventDispatcher, getContext } from "svelte"
|
import { createEventDispatcher, getContext } from "svelte"
|
||||||
import { helpers } from "@budibase/shared-core"
|
import { helpers } from "@budibase/shared-core"
|
||||||
import UserAvatars from "../../pages/builder/app/[application]/_components/UserAvatars.svelte"
|
import { UserAvatars } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export let icon
|
export let icon
|
||||||
export let withArrow = false
|
export let withArrow = false
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
import { Heading, Body, Button, Icon } from "@budibase/bbui"
|
import { Heading, Body, Button, Icon } from "@budibase/bbui"
|
||||||
import { processStringSync } from "@budibase/string-templates"
|
import { processStringSync } from "@budibase/string-templates"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { UserAvatar } from "@budibase/frontend-core"
|
import { UserAvatars } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export let app
|
export let app
|
||||||
export let lockedAction
|
export let lockedAction
|
||||||
|
|
||||||
$: editing = app?.lockedBy != null
|
$: editing = app.sessions?.length
|
||||||
|
|
||||||
const handleDefaultClick = () => {
|
const handleDefaultClick = () => {
|
||||||
if (window.innerWidth < 640) {
|
if (window.innerWidth < 640) {
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<div class="updated">
|
<div class="updated">
|
||||||
{#if editing}
|
{#if editing}
|
||||||
Currently editing
|
Currently editing
|
||||||
<UserAvatar user={app.lockedBy} />
|
<UserAvatars users={app.sessions} />
|
||||||
{:else if app.updatedAt}
|
{:else if app.updatedAt}
|
||||||
{processStringSync("Updated {{ duration time 'millisecond' }} ago", {
|
{processStringSync("Updated {{ duration time 'millisecond' }} ago", {
|
||||||
time: new Date().getTime() - new Date(app.updatedAt).getTime(),
|
time: new Date().getTime() - new Date(app.updatedAt).getTime(),
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
import TourWrap from "components/portal/onboarding/TourWrap.svelte"
|
import TourWrap from "components/portal/onboarding/TourWrap.svelte"
|
||||||
import TourPopover from "components/portal/onboarding/TourPopover.svelte"
|
import TourPopover from "components/portal/onboarding/TourPopover.svelte"
|
||||||
import BuilderSidePanel from "./_components/BuilderSidePanel.svelte"
|
import BuilderSidePanel from "./_components/BuilderSidePanel.svelte"
|
||||||
import UserAvatars from "./_components/UserAvatars.svelte"
|
import { UserAvatars } from "@budibase/frontend-core"
|
||||||
import { TOUR_KEYS, TOURS } from "components/portal/onboarding/tours.js"
|
import { TOUR_KEYS, TOURS } from "components/portal/onboarding/tours.js"
|
||||||
import PreviewOverlay from "./_components/PreviewOverlay.svelte"
|
import PreviewOverlay from "./_components/PreviewOverlay.svelte"
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,5 @@ export { default as SplitPage } from "./SplitPage.svelte"
|
||||||
export { default as TestimonialPage } from "./TestimonialPage.svelte"
|
export { default as TestimonialPage } from "./TestimonialPage.svelte"
|
||||||
export { default as Testimonial } from "./Testimonial.svelte"
|
export { default as Testimonial } from "./Testimonial.svelte"
|
||||||
export { default as UserAvatar } from "./UserAvatar.svelte"
|
export { default as UserAvatar } from "./UserAvatar.svelte"
|
||||||
|
export { default as UserAvatars } from "./UserAvatars.svelte"
|
||||||
export { Grid } from "./grid"
|
export { Grid } from "./grid"
|
||||||
|
|
|
@ -49,6 +49,7 @@ import {
|
||||||
MigrationType,
|
MigrationType,
|
||||||
PlanType,
|
PlanType,
|
||||||
Screen,
|
Screen,
|
||||||
|
SocketSession,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
||||||
|
@ -178,11 +179,12 @@ export const addSampleData = async (ctx: UserCtx) => {
|
||||||
export async function fetch(ctx: UserCtx) {
|
export async function fetch(ctx: UserCtx) {
|
||||||
const dev = ctx.query && ctx.query.status === AppStatus.DEV
|
const dev = ctx.query && ctx.query.status === AppStatus.DEV
|
||||||
const all = ctx.query && ctx.query.status === AppStatus.ALL
|
const all = ctx.query && ctx.query.status === AppStatus.ALL
|
||||||
const apps = (await dbCore.getAllApps({ dev, all })) as App[]
|
let apps = (await dbCore.getAllApps({ dev, all })) as App[]
|
||||||
|
|
||||||
const appIds = apps
|
const appIds = apps
|
||||||
.filter((app: any) => app.status === "development")
|
.filter((app: any) => app.status === "development")
|
||||||
.map((app: any) => app.appId)
|
.map((app: any) => app.appId)
|
||||||
|
|
||||||
// get the locks for all the dev apps
|
// get the locks for all the dev apps
|
||||||
if (dev || all) {
|
if (dev || all) {
|
||||||
const locks = await getLocksById(appIds)
|
const locks = await getLocksById(appIds)
|
||||||
|
@ -197,6 +199,30 @@ export async function fetch(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all builder sessions in each app
|
||||||
|
const sessions = await builderSocket?.getRoomSessions(appIds)
|
||||||
|
if (sessions?.length) {
|
||||||
|
let appSessionMap: { [key: string]: SocketSession[] } = {}
|
||||||
|
sessions.forEach(session => {
|
||||||
|
const room = session.room
|
||||||
|
if (!room) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!appSessionMap[room]) {
|
||||||
|
appSessionMap[room] = []
|
||||||
|
}
|
||||||
|
appSessionMap[room].push(session)
|
||||||
|
})
|
||||||
|
apps.forEach(app => {
|
||||||
|
const sessions = appSessionMap[app.appId]
|
||||||
|
if (sessions?.length) {
|
||||||
|
app.sessions = sessions
|
||||||
|
} else {
|
||||||
|
delete app.sessions
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ctx.body = await checkAppMetadata(apps)
|
ctx.body = await checkAppMetadata(apps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,9 +125,18 @@ export class BaseSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets an array of all redis keys of users inside a certain room
|
// Gets an array of all redis keys of users inside a certain room
|
||||||
async getRoomSessionIds(room: string): Promise<string[]> {
|
async getRoomSessionIds(room: string | string[]): Promise<string[]> {
|
||||||
const keys = await this.redisClient?.get(this.getRoomKey(room))
|
if (Array.isArray(room)) {
|
||||||
return keys || []
|
const roomKeys = room.map(this.getRoomKey.bind(this))
|
||||||
|
const roomSessionIdMap = await this.redisClient?.bulkGet(roomKeys)
|
||||||
|
let sessionIds: any[] = []
|
||||||
|
Object.values(roomSessionIdMap || {}).forEach(roomSessionIds => {
|
||||||
|
sessionIds = sessionIds.concat(roomSessionIds)
|
||||||
|
})
|
||||||
|
return sessionIds
|
||||||
|
} else {
|
||||||
|
return (await this.redisClient?.get(this.getRoomKey(room))) || []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the list of redis keys for users inside a certain room.
|
// Sets the list of redis keys for users inside a certain room.
|
||||||
|
@ -137,7 +146,7 @@ export class BaseSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a list of all users inside a certain room
|
// Gets a list of all users inside a certain room
|
||||||
async getRoomSessions(room?: string): Promise<SocketSession[]> {
|
async getRoomSessions(room?: string | string[]): Promise<SocketSession[]> {
|
||||||
if (room) {
|
if (room) {
|
||||||
const sessionIds = await this.getRoomSessionIds(room)
|
const sessionIds = await this.getRoomSessionIds(room)
|
||||||
const keys = sessionIds.map(this.getSessionKey.bind(this))
|
const keys = sessionIds.map(this.getSessionKey.bind(this))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { User, Document } from "../"
|
import { User, Document } from "../"
|
||||||
|
import { SocketSession } from "../../sdk"
|
||||||
|
|
||||||
export type AppMetadataErrors = { [key: string]: string[] }
|
export type AppMetadataErrors = { [key: string]: string[] }
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ export interface App extends Document {
|
||||||
customTheme?: AppCustomTheme
|
customTheme?: AppCustomTheme
|
||||||
revertableVersion?: string
|
revertableVersion?: string
|
||||||
lockedBy?: User
|
lockedBy?: User
|
||||||
|
sessions?: SocketSession[]
|
||||||
navigation?: AppNavigation
|
navigation?: AppNavigation
|
||||||
automationErrors?: AppMetadataErrors
|
automationErrors?: AppMetadataErrors
|
||||||
icon?: AppIcon
|
icon?: AppIcon
|
||||||
|
|
Loading…
Reference in New Issue