mirror of
https://github.com/penxio/penx.git
synced 2026-04-19 03:03:06 -04:00
feat: improve task ui
This commit is contained in:
1
.github/workflows/desktop-publish.yml
vendored
1
.github/workflows/desktop-publish.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
# - "v*"
|
||||
branches:
|
||||
- desktop
|
||||
- develop
|
||||
- release
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export function MobileAddCreationButton({ className }: Props) {
|
||||
size="icon"
|
||||
className={cn('size-12 shadow-xl', className)}
|
||||
onClick={async () => {
|
||||
const creation = await addCreation(CreationType.PAGE)
|
||||
const creation = await addCreation({ type: CreationType.PAGE })
|
||||
store.set(creationIdAtom, creation.id)
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -18,7 +18,7 @@ export function AddCreationButton({ className }: Props) {
|
||||
size="icon"
|
||||
className={cn('hover:bg-foreground/10 size-8 rounded-full', className)}
|
||||
onClick={() => {
|
||||
addCreation(CreationType.PAGE)
|
||||
addCreation({ type: CreationType.PAGE })
|
||||
}}
|
||||
>
|
||||
<PlusIcon size={20} className="" />
|
||||
|
||||
@@ -22,13 +22,13 @@ export function PanelLayout({ children }: { children: ReactNode }) {
|
||||
// useSiteTags()
|
||||
return (
|
||||
<SidebarProvider className="">
|
||||
<AppSidebar className="z-2" />
|
||||
<AppSidebar className="z-3" />
|
||||
<SidebarInset className="z-2 relative">
|
||||
<PanelList />
|
||||
</SidebarInset>
|
||||
|
||||
<div
|
||||
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-80"
|
||||
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-0"
|
||||
style={{
|
||||
filter: 'blur(150px) saturate(150%)',
|
||||
transform: 'translateZ(0)',
|
||||
|
||||
@@ -58,35 +58,36 @@ export function PanelWidget({ panel, index }: Props) {
|
||||
</div>
|
||||
<ClosePanelButton panel={panel} />
|
||||
</PanelHeaderWrapper>
|
||||
<div
|
||||
ref={ref}
|
||||
className="flex-1 overflow-y-auto overflow-x-hidden px-4 pt-8"
|
||||
>
|
||||
{widget.type === WidgetType.AI_CHAT && (
|
||||
<PanelChat panel={panel} index={index} />
|
||||
)}
|
||||
|
||||
{mold?.type === CreationType.NOTE && (
|
||||
{mold?.type === CreationType.NOTE && (
|
||||
<div
|
||||
ref={ref}
|
||||
className="flex-1 overflow-y-auto overflow-x-hidden px-4 pt-8"
|
||||
>
|
||||
<NoteList
|
||||
panel={panel}
|
||||
index={index}
|
||||
mold={mold}
|
||||
columnCount={columns}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{mold?.type === CreationType.TASK && (
|
||||
<TasksList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
{widget.type === WidgetType.AI_CHAT && (
|
||||
<PanelChat panel={panel} index={index} />
|
||||
)}
|
||||
|
||||
{mold?.type === CreationType.BOOKMARK && (
|
||||
<BookmarkList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
{mold?.type === CreationType.TASK && (
|
||||
<TasksList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
|
||||
{mold?.type === CreationType.ARTICLE && (
|
||||
<ArticleList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
</div>
|
||||
{mold?.type === CreationType.BOOKMARK && (
|
||||
<BookmarkList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
|
||||
{mold?.type === CreationType.ARTICLE && (
|
||||
<ArticleList panel={panel} index={index} mold={mold} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
'use client'
|
||||
|
||||
import type React from 'react'
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
type ChangeEvent,
|
||||
type Dispatch,
|
||||
type SetStateAction,
|
||||
} from 'react'
|
||||
import type { UseChatHelpers } from '@ai-sdk/react'
|
||||
import type { Attachment, UIMessage } from 'ai'
|
||||
import cx from 'classnames'
|
||||
import equal from 'fast-deep-equal'
|
||||
import { CogIcon, ExpandIcon, SendHorizonalIcon, XIcon } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { useAddCreation } from '@penx/hooks/useAddCreation'
|
||||
import { CreationType } from '@penx/types'
|
||||
import { Button } from '@penx/uikit/button'
|
||||
import { Textarea } from '@penx/uikit/textarea'
|
||||
import { cn } from '@penx/utils'
|
||||
|
||||
export function TaskInput() {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||
const [focused, setFocused] = useState(false)
|
||||
const [input, setInput] = useState('')
|
||||
const addCreation = useAddCreation()
|
||||
|
||||
useEffect(() => {
|
||||
if (textareaRef.current) {
|
||||
// adjustHeight()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const adjustHeight = () => {
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = 'auto'
|
||||
textareaRef.current.style.height = `${textareaRef.current.scrollHeight + 2}px`
|
||||
}
|
||||
}
|
||||
|
||||
const resetHeight = () => {
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = 'auto'
|
||||
textareaRef.current.style.height = '98px'
|
||||
}
|
||||
}
|
||||
|
||||
const handleInput = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setInput(event.target.value)
|
||||
adjustHeight()
|
||||
}
|
||||
|
||||
const submitForm = useCallback(() => {
|
||||
const title = input.split('\n').join(',')
|
||||
addCreation({
|
||||
type: CreationType.TASK,
|
||||
title,
|
||||
isAddPanel: false,
|
||||
})
|
||||
setInput('')
|
||||
}, [input])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'bg-linear-to-r relative flex w-full flex-col gap-4 rounded-xl from-indigo-500 via-purple-500 to-pink-500 p-0.5',
|
||||
focused && 'shadow-2xl',
|
||||
)}
|
||||
>
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
placeholder="What's on your mind?"
|
||||
value={input}
|
||||
onChange={handleInput}
|
||||
onFocus={() => {
|
||||
setFocused(true)
|
||||
}}
|
||||
onBlur={() => {
|
||||
setFocused(false)
|
||||
}}
|
||||
className={cx(
|
||||
'bg-background max-h-[calc(75dvh)] min-h-[24px] resize-none overflow-hidden rounded-xl pb-8 !text-base shadow-md focus-visible:ring-0',
|
||||
)}
|
||||
// rows={2}
|
||||
onKeyDown={(event) => {
|
||||
if (
|
||||
event.key === 'Enter' &&
|
||||
!event.shiftKey &&
|
||||
!event.nativeEvent.isComposing
|
||||
) {
|
||||
event.preventDefault()
|
||||
submitForm()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="text-foreground/60 absolute bottom-2 flex w-fit flex-row items-center justify-start gap-0.5 py-0 pl-2"></div>
|
||||
<div className="absolute bottom-0 right-0 flex w-fit flex-row justify-end gap-1 p-2">
|
||||
<SendButton input={input} submitForm={submitForm} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PureSendButton({
|
||||
submitForm,
|
||||
input,
|
||||
}: {
|
||||
submitForm: () => void
|
||||
input: string
|
||||
}) {
|
||||
return (
|
||||
<Button
|
||||
size="sm"
|
||||
className="h-7"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
submitForm()
|
||||
}}
|
||||
>
|
||||
<SendHorizonalIcon size={16} />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const SendButton = memo(PureSendButton, (prevProps, nextProps) => {
|
||||
if (prevProps.input !== nextProps.input) return false
|
||||
return true
|
||||
})
|
||||
@@ -5,6 +5,7 @@ import { Creation } from '@penx/domain'
|
||||
import { updateCreation } from '@penx/hooks/useCreation'
|
||||
import { useCreations } from '@penx/hooks/useCreations'
|
||||
import { store } from '@penx/store'
|
||||
import { PanelType } from '@penx/types'
|
||||
import { Checkbox } from '@penx/uikit/checkbox'
|
||||
import { cn } from '@penx/utils'
|
||||
|
||||
@@ -14,11 +15,22 @@ interface PostItemProps {
|
||||
|
||||
export function TaskItem({ creation: creation }: PostItemProps) {
|
||||
return (
|
||||
<div className={cn('flex break-inside-avoid flex-col rounded-2xl')}>
|
||||
<div
|
||||
className={cn(
|
||||
'hover:text-brand text-foreground flex cursor-pointer break-inside-avoid flex-col rounded-md py-1 text-lg transition-all hover:font-bold',
|
||||
)}
|
||||
onClick={() => {
|
||||
store.panels.updateMainPanel({
|
||||
type: PanelType.CREATION,
|
||||
creationId: creation.id,
|
||||
})
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox
|
||||
className="size-5"
|
||||
checked={creation.checked}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(v) => {
|
||||
updateCreation({
|
||||
id: creation.id,
|
||||
@@ -27,21 +39,11 @@ export function TaskItem({ creation: creation }: PostItemProps) {
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextareaAutosize
|
||||
className="dark:placeholder-text-600 placeholder:text-foreground/40 w-full resize-none border-none bg-transparent px-0 text-xl font-bold focus:outline-none focus:ring-0"
|
||||
placeholder="Title"
|
||||
defaultValue={creation.title || ''}
|
||||
autoFocus
|
||||
onChange={(e) => {
|
||||
const title = e.target.value
|
||||
updateCreation({ id: creation.id, title })
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={cn(creation.checked && 'text-foreground/60 line-through')}
|
||||
>
|
||||
{creation.title || ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
import { Trans } from '@lingui/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { Mold } from '@penx/domain'
|
||||
import { useCreations } from '@penx/hooks/useCreations'
|
||||
import { useMolds } from '@penx/hooks/useMolds'
|
||||
import { api } from '@penx/trpc-client'
|
||||
import { Panel } from '@penx/types'
|
||||
import { TaskInput } from './TaskInput'
|
||||
import { TaskItem } from './TaskItem'
|
||||
|
||||
interface PostListProps {
|
||||
@@ -14,28 +17,36 @@ interface PostListProps {
|
||||
}
|
||||
|
||||
export function TasksList({ mold }: PostListProps) {
|
||||
const { data: creations = [], isLoading } = useQuery({
|
||||
queryKey: ['creations', mold.id],
|
||||
queryFn: async () => {
|
||||
return api.creation.listCreationsByMold.query({ moldId: mold.id })
|
||||
},
|
||||
})
|
||||
const { creations } = useCreations()
|
||||
const tasks = creations.filter((item) => item.moldId === mold.id)
|
||||
|
||||
if (isLoading) return <div className="text-foreground/60">Loading...</div>
|
||||
const todoTasks = tasks
|
||||
.filter((item) => !item.checked)
|
||||
.sort((a, b) => new Date(b.createdAt).getTime() - a.createdAt.getTime())
|
||||
|
||||
if (!creations.length) {
|
||||
return (
|
||||
<div className="text-foreground/60">
|
||||
<Trans id="No creations yet."></Trans>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const completedTasks = tasks
|
||||
.filter((item) => item.checked)
|
||||
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
{creations.map((post) => {
|
||||
return <TaskItem key={post.id} creation={post as any} />
|
||||
})}
|
||||
<div className="flex flex-1 flex-col">
|
||||
{!tasks.length && (
|
||||
<div className="text-foreground/60">
|
||||
<Trans id="No task yet."></Trans>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex w-full flex-1 overflow-auto px-6 pt-6">
|
||||
<div className="mx-auto flex w-full max-w-2xl flex-col gap-2">
|
||||
{[...todoTasks, ...completedTasks].map((item) => {
|
||||
return <TaskItem key={item.id} creation={item as any} />
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-6 pb-2">
|
||||
<div className="mx-auto flex w-full max-w-2xl flex-col gap-2">
|
||||
<TaskInput />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { toast } from 'sonner'
|
||||
import { useLocalStorage, useWindowSize } from 'usehooks-ts'
|
||||
import { useAddCreation } from '@penx/hooks/useAddCreation'
|
||||
import { store } from '@penx/store'
|
||||
import { PanelType } from '@penx/types'
|
||||
import { CreationType, PanelType } from '@penx/types'
|
||||
import { Button } from '@penx/uikit/button'
|
||||
import { Checkbox } from '@penx/uikit/checkbox'
|
||||
import { Textarea } from '@penx/uikit/textarea'
|
||||
@@ -65,7 +65,10 @@ export function QuickInput({ onCancel }: { onCancel?: () => void }) {
|
||||
type: 'p',
|
||||
children: [{ text: line }],
|
||||
}))
|
||||
addCreation('NOTE', JSON.stringify(slateValue))
|
||||
addCreation({
|
||||
type: CreationType.NOTE,
|
||||
content: JSON.stringify(slateValue),
|
||||
})
|
||||
setInput('')
|
||||
}, [input])
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export const QuickSearchTrigger = ({}: Props) => {
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<div
|
||||
className="bg-background shadow-xs flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 transition-all hover:shadow-md"
|
||||
className="bg-background shadow-xs dark:bg-foreground/8 flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 transition-all hover:shadow-md"
|
||||
onClick={() => {
|
||||
setOpen(true)
|
||||
}}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import React from 'react'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { useMolds } from '@penx/hooks/useMolds'
|
||||
import { Area } from '@penx/db/client'
|
||||
import { useAddCreation } from '@penx/hooks/useAddCreation'
|
||||
import { useMolds } from '@penx/hooks/useMolds'
|
||||
import { Widget } from '@penx/types'
|
||||
import { Button } from '@penx/uikit/button'
|
||||
|
||||
@@ -25,7 +25,7 @@ export function AddChatButton({ widget }: Props) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const mold = molds.find((mold) => mold.id === widget.moldId)!
|
||||
addCreation(mold.type)
|
||||
addCreation({ type: mold.type })
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="text-muted-foreground pointer-events-none size-4 transition-transform duration-200" />
|
||||
|
||||
@@ -31,7 +31,7 @@ export function AddCreationButton({ area, widget }: Props) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
const mold = molds.find((mold) => mold.id === widget.moldId)!
|
||||
addCreation(mold.type)
|
||||
addCreation({ type: mold.type })
|
||||
}}
|
||||
>
|
||||
<PlusIcon
|
||||
|
||||
@@ -95,11 +95,7 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
|
||||
return
|
||||
}
|
||||
|
||||
if (widget.type === WidgetType.AI_CHAT) {
|
||||
store.panels.openWidgetPanel(widget)
|
||||
return
|
||||
}
|
||||
|
||||
store.panels.openWidgetPanel(widget)
|
||||
setVisible(!visible)
|
||||
}}
|
||||
>
|
||||
@@ -132,7 +128,8 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
|
||||
isDragging && 'bg-foreground/6 opacity-50',
|
||||
isDragging && 'z-[1000000]',
|
||||
dragOverlay && 'shadow',
|
||||
!isMobileApp && 'shadow-2xs rounded-md bg-white dark:bg-[#181818]',
|
||||
!isMobileApp &&
|
||||
'shadow-2xs dark:bg-foreground/8 rounded-md bg-white',
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
|
||||
@@ -56,10 +56,10 @@ export class Area {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,10 @@ export class Creation {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ export class CreationTag {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ export class Mold {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ export class Node {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
|
||||
toHash(): string {
|
||||
|
||||
@@ -45,10 +45,10 @@ export class Site {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ export class Tag {
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return this.raw.createdAt
|
||||
return new Date(this.raw.createdAt)
|
||||
}
|
||||
|
||||
get updatedAt() {
|
||||
return this.raw.updatedAt
|
||||
return new Date(this.raw.updatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,20 @@ import { CreationStatus, GateType, PanelType } from '@penx/types'
|
||||
import { uniqueId } from '@penx/unique-id'
|
||||
import { useMySite } from './useMySite'
|
||||
|
||||
export type Input = {
|
||||
type: string
|
||||
isAddPanel?: boolean
|
||||
content?: string
|
||||
title?: string
|
||||
}
|
||||
|
||||
export function useAddCreation() {
|
||||
const { molds } = useMolds()
|
||||
const { site } = useMySite()
|
||||
|
||||
return async (type: string, content?: string) => {
|
||||
const mold = molds.find((mold) => mold.type === type)
|
||||
return async (input: Input) => {
|
||||
const { isAddPanel = true } = input
|
||||
const mold = molds.find((mold) => mold.type === input.type)
|
||||
const area = store.area.get()
|
||||
|
||||
if (!mold) throw new Error('Invalid mold type')
|
||||
@@ -27,10 +35,10 @@ export function useAddCreation() {
|
||||
const addCreationInput: AddCreationInput = {
|
||||
slug: uniqueId(),
|
||||
siteId: site.id,
|
||||
title: '',
|
||||
title: input.title || '',
|
||||
description: '',
|
||||
image: '',
|
||||
content: content || JSON.stringify(editorDefaultValue),
|
||||
content: input.content || JSON.stringify(editorDefaultValue),
|
||||
type: mold.type,
|
||||
moldId: mold.id,
|
||||
areaId: area.id,
|
||||
@@ -69,14 +77,16 @@ export function useAddCreation() {
|
||||
|
||||
updateCreationState(newCreation)
|
||||
|
||||
if (isMobileApp && !content) {
|
||||
if (isMobileApp && !input.content) {
|
||||
appEmitter.emit('ROUTE_TO_CREATION', newCreation)
|
||||
} else {
|
||||
store.panels.addPanel({
|
||||
id: uniqueId(),
|
||||
type: PanelType.CREATION,
|
||||
creationId: newCreation.id,
|
||||
})
|
||||
if (isAddPanel) {
|
||||
store.panels.addPanel({
|
||||
id: uniqueId(),
|
||||
type: PanelType.CREATION,
|
||||
creationId: newCreation.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
return newCreation
|
||||
}
|
||||
|
||||
@@ -125,7 +125,9 @@ const debouncedSaveCreation = debounce(persistCreation, 300, {
|
||||
|
||||
export async function updateCreation(input: UpdateCreationInput) {
|
||||
const { id, ...props } = input
|
||||
const creation = getCreation(input.id)
|
||||
|
||||
const creation = getCreation(input.id) || (await localDB.getNode(id))
|
||||
console.log('=======input:', input, 'creation:', creation)
|
||||
const newCreation: ICreationNode = {
|
||||
...creation,
|
||||
props: { ...creation.props, ...props },
|
||||
|
||||
@@ -60,7 +60,7 @@ export class PanelsStore {
|
||||
let panels = this.get()
|
||||
|
||||
let index = panels.findIndex((p) => p.type !== PanelType.WIDGET)
|
||||
if (index < 0) index = 0
|
||||
if (index < 0) index = panels.length - 1
|
||||
|
||||
if (panel.type === PanelType.CREATION) {
|
||||
panels = produce(panels, (draft) => {
|
||||
|
||||
Reference in New Issue
Block a user