Skip to content

Commit 1ba1c70

Browse files
committed
up
1 parent fbcdeb9 commit 1ba1c70

File tree

14 files changed

+169
-131
lines changed

14 files changed

+169
-131
lines changed

src/app/src/components/AppFooter.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const userMenuItems = computed(() => [
6060
>
6161
<USwitch
6262
v-model="showTechnicalMode"
63-
label="Technical view"
63+
label="Developer view"
6464
size="xs"
6565
:ui="{ root: 'w-full flex-row-reverse justify-between', wrapper: 'ms-0' }"
6666
/>

src/app/src/components/shared/item/ItemBreadcrumb.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,26 @@ import type { DropdownMenuItem } from '@nuxt/ui/components/DropdownMenu.vue.d.ts
44
import { computed, unref } from 'vue'
55
import { type TreeItem, TreeStatus } from '../../../types'
66
import { useStudio } from '../../../composables/useStudio'
7-
import { findParentFromId, ROOT_ITEM } from '../../../utils/tree'
7+
import { findParentFromId } from '../../../utils/tree'
88
99
const { context } = useStudio()
1010
1111
const currentItem = computed(() => context.activeTree.value.currentItem.value)
1212
const tree = computed(() => context.activeTree.value.root.value)
1313
1414
const items = computed<BreadcrumbItem[]>(() => {
15-
const rootItem = {
15+
const rootTreeItem = context.activeTree.value.rootItem.value
16+
const rootBreadcrumbItem = {
1617
icon: 'i-lucide-folder-git',
18+
label: rootTreeItem.name,
1719
onClick: () => {
1820
// TODO: update for ROOT_DOCUMENT_ITEM and ROOT_MEDIA_ITEM
19-
context.activeTree.value.select(ROOT_ITEM)
21+
context.activeTree.value.select(rootTreeItem)
2022
},
2123
}
2224
23-
if (currentItem.value.id === ROOT_ITEM.id) {
24-
return [rootItem]
25+
if (currentItem.value.id === rootTreeItem.id) {
26+
return [rootBreadcrumbItem]
2527
}
2628
2729
const breadcrumbItems: BreadcrumbItem[] = []
@@ -39,7 +41,7 @@ const items = computed<BreadcrumbItem[]>(() => {
3941
currentTreeItem = findParentFromId(tree.value, currentTreeItem.id)
4042
}
4143
42-
const allItems = [rootItem, ...breadcrumbItems]
44+
const allItems = [rootBreadcrumbItem, ...breadcrumbItems]
4345
4446
// Handle ellipsis dropdown
4547
if (allItems.length > 3) {

src/app/src/composables/useDraftMedias.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { useGit } from './useGit'
88
import { getDraftStatus } from '../utils/draft'
99
import { createSharedComposable } from '@vueuse/core'
1010
import { useHooks } from './useHooks'
11+
import { TreeRootId } from '../utils/tree'
1112

1213
const storage = createStorage({
1314
driver: indexedDbDriver({
@@ -267,12 +268,12 @@ export const useDraftMedias = createSharedComposable((host: StudioHost, git: Ret
267268
const fsPath = directory && directory !== '/' ? joinURL(directory, file.name) : file.name
268269

269270
return {
270-
id: `public-assets/${fsPath}`,
271+
id: `${TreeRootId.Media}/${fsPath}`,
271272
fsPath,
272273
githubFile: undefined,
273274
status: DraftStatus.Created,
274275
modified: {
275-
id: `public-assets/${fsPath}`,
276+
id: `${TreeRootId.Media}/${fsPath}`,
276277
fsPath,
277278
extension: fsPath.split('.').pop()!,
278279
stem: fsPath.split('.').join('.'),

src/app/src/composables/useTree.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,28 @@ import { StudioFeature, type StudioHost, type TreeItem } from '../types'
22
import { ref, computed } from 'vue'
33
import type { useDraftDocuments } from './useDraftDocuments'
44
import type { useDraftMedias } from './useDraftMedias'
5-
import { buildTree, findItemFromId, findItemFromRoute, ROOT_ITEM, findParentFromId } from '../utils/tree'
5+
import { buildTree, findItemFromId, findItemFromRoute, findParentFromId, TreeRootId } from '../utils/tree'
66
import type { RouteLocationNormalized } from 'vue-router'
77
import { useHooks } from './useHooks'
88
import type { useUI } from './useUI'
99

1010
export const useTree = (type: StudioFeature, host: StudioHost, ui: ReturnType<typeof useUI>, draft: ReturnType<typeof useDraftDocuments | typeof useDraftMedias>) => {
1111
const hooks = useHooks()
1212

13+
const rootItem = computed<TreeItem>(() => {
14+
return {
15+
id: type === StudioFeature.Content ? TreeRootId.Content : TreeRootId.Media,
16+
name: type === StudioFeature.Content ? 'content' : 'media',
17+
type: 'root',
18+
fsPath: '/',
19+
} as TreeItem
20+
})
21+
1322
const tree = ref<TreeItem[]>([])
14-
const currentItem = ref<TreeItem>(ROOT_ITEM)
23+
const currentItem = ref<TreeItem>(rootItem.value)
1524

1625
const currentTree = computed<TreeItem[]>(() => {
17-
if (currentItem.value.id === ROOT_ITEM.id) {
26+
if (currentItem.value.id === rootItem.value.id) {
1827
return tree.value
1928
}
2029

@@ -31,15 +40,8 @@ export const useTree = (type: StudioFeature, host: StudioHost, ui: ReturnType<ty
3140
return subTree
3241
})
3342

34-
// const parentItem = computed<TreeItem | null>(() => {
35-
// if (currentItem.value.id === ROOT_ITEM.id) return null
36-
37-
// const parent = findParentFromId(tree.value, currentItem.value.id)
38-
// return parent || ROOT_ITEM
39-
// })
40-
4143
async function select(item: TreeItem) {
42-
currentItem.value = item || ROOT_ITEM
44+
currentItem.value = item || rootItem.value
4345
if (item?.type === 'file') {
4446
if (type === StudioFeature.Content && ui.config.value.syncEditorAndRoute) {
4547
host.app.navigateTo(item.routePath!)
@@ -103,6 +105,7 @@ export const useTree = (type: StudioFeature, host: StudioHost, ui: ReturnType<ty
103105

104106
return {
105107
root: tree,
108+
rootItem,
106109
current: currentTree,
107110
currentItem,
108111
// parentItem,

src/app/src/pages/content.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const showFileForm = computed(() => {
2525
</script>
2626

2727
<template>
28-
<div class="flex flex-col">
28+
<div>
2929
<div class="flex items-center justify-between gap-2 px-4 py-1 border-b-[0.5px] border-default bg-muted/70">
3030
<ItemBreadcrumb />
3131
<ItemActionsToolbar />

src/app/src/pages/media.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ const isFileCreationInProgress = computed(() => context.actionInProgress.value?.
1212
const isFolderCreationInProgress = computed(() => context.actionInProgress.value?.id === StudioItemActionId.CreateFolder)
1313
1414
async function onFileDrop(event: DragEvent) {
15+
if (mediaTree.draft.current.value) {
16+
return
17+
}
18+
1519
if (event.dataTransfer?.files) {
1620
await context.itemActionHandler[StudioItemActionId.UploadMedia]({
1721
directory: mediaTree.currentItem.value.fsPath,
@@ -22,7 +26,11 @@ async function onFileDrop(event: DragEvent) {
2226
</script>
2327

2428
<template>
25-
<div class="flex flex-col">
29+
<div
30+
class="flex flex-col"
31+
@drop.prevent.stop="onFileDrop"
32+
@dragover.prevent.stop
33+
>
2634
<div class="flex items-center justify-between gap-2 px-4 py-1 border-b-[0.5px] border-default bg-muted/70">
2735
<ItemBreadcrumb />
2836
<ItemActionsToolbar />
@@ -33,9 +41,7 @@ async function onFileDrop(event: DragEvent) {
3341
/>
3442
<div
3543
v-else
36-
class="flex flex-col p-4"
37-
@drop.prevent.stop="onFileDrop"
38-
@dragover.prevent.stop
44+
class="flex flex-col p-4 min-h-[200px]"
3945
>
4046
<ItemTree
4147
v-if="folderTree?.length > 0 || isFolderCreationInProgress"

src/app/src/utils/context.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type StudioAction, type TreeItem, TreeStatus, StudioItemActionId } from '../types'
2+
import { TreeRootId } from './tree'
23

34
export const oneStepActions: StudioItemActionId[] = [StudioItemActionId.RevertItem, StudioItemActionId.DeleteItem, StudioItemActionId.DuplicateItem]
45
export const twoStepActions: StudioItemActionId[] = [StudioItemActionId.CreateDocument, StudioItemActionId.CreateFolder, StudioItemActionId.RenameItem]
@@ -16,6 +17,12 @@ export const STUDIO_ITEM_ACTION_DEFINITIONS: StudioAction[] = [
1617
icon: 'i-lucide-file-plus',
1718
tooltip: 'Create a new file',
1819
},
20+
{
21+
id: StudioItemActionId.UploadMedia,
22+
label: 'Upload media',
23+
icon: 'i-lucide-upload',
24+
tooltip: 'Upload media',
25+
},
1926
{
2027
id: StudioItemActionId.CreateFolder,
2128
label: 'Create folder',
@@ -49,14 +56,18 @@ export function computeActionItems(itemActions: StudioAction[], item?: TreeItem
4956

5057
const forbiddenActions: StudioItemActionId[] = []
5158

52-
if (item.type === 'root') {
53-
return itemActions.filter(action => ![StudioItemActionId.RenameItem, StudioItemActionId.DeleteItem, StudioItemActionId.DuplicateItem].includes(action.id))
59+
// Upload only available for medias
60+
if (!item.id.startsWith(TreeRootId.Media)) {
61+
forbiddenActions.push(StudioItemActionId.UploadMedia)
5462
}
5563

5664
// Item type filtering
5765
switch (item.type) {
66+
case 'root':
67+
forbiddenActions.push(StudioItemActionId.RenameItem, StudioItemActionId.DeleteItem, StudioItemActionId.DuplicateItem)
68+
break
5869
case 'file':
59-
forbiddenActions.push(StudioItemActionId.CreateFolder, StudioItemActionId.CreateDocument)
70+
forbiddenActions.push(StudioItemActionId.CreateFolder, StudioItemActionId.CreateDocument, StudioItemActionId.UploadMedia)
6071
break
6172
case 'directory':
6273
forbiddenActions.push(StudioItemActionId.DuplicateItem)

src/app/src/utils/draft.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type DatabasePageItem, type DraftItem, type BaseItem, ContentFileExtension } from '../types'
22
import { DraftStatus } from '../types'
3-
import { ROOT_ITEM } from './tree'
43
import { isEqual } from './database'
4+
import { TreeRootId } from './tree'
55

66
export function getDraftStatus(modified?: BaseItem, original?: BaseItem): DraftStatus {
77
if (!modified && !original) {
@@ -31,7 +31,7 @@ export function getDraftStatus(modified?: BaseItem, original?: BaseItem): DraftS
3131
}
3232

3333
export function findDescendantsFromId(list: DraftItem[], id: string): DraftItem[] {
34-
if (id === ROOT_ITEM.id) {
34+
if ([TreeRootId.Content, TreeRootId.Media].includes(id as TreeRootId)) {
3535
return list
3636
}
3737

src/app/src/utils/tree.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import type { RouteLocationNormalized } from 'vue-router'
55
import type { BaseItem } from '../types/item'
66
import { isEqual } from './database'
77

8-
export const ROOT_ITEM: TreeItem = { id: 'root', name: 'content', fsPath: '/', type: 'root' }
8+
export enum TreeRootId {
9+
Content = 'content',
10+
Media = 'public-assets',
11+
}
912

1013
export const EXTENSIONS_WITH_PREVIEW = new Set([
1114
'jpg',
@@ -317,11 +320,13 @@ function calculateDirectoryStatuses(items: TreeItem[]) {
317320
const childrenWithStatus = item.children.filter(child => child.status && child.status !== TreeStatus.Opened)
318321

319322
if (childrenWithStatus.length > 0) {
323+
item.status = TreeStatus.Updated
324+
320325
const allChildrenHaveStatus = childrenWithStatus.length === item.children.length
321326

322327
if (allChildrenHaveStatus) {
323328
if (childrenWithStatus.every(child => child.status === TreeStatus.Deleted)) {
324-
item.status = TreeStatus.Created
329+
item.status = TreeStatus.Deleted
325330
}
326331
else if (childrenWithStatus.every(child => child.status === TreeStatus.Renamed)) {
327332
item.status = TreeStatus.Renamed
@@ -330,9 +335,6 @@ function calculateDirectoryStatuses(items: TreeItem[]) {
330335
item.status = TreeStatus.Created
331336
}
332337
}
333-
else {
334-
item.status = TreeStatus.Updated
335-
}
336338
}
337339
}
338340
}

src/app/test/integration/composables/useDraftDocuments.test.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,6 @@ describe('useDraftDocuments - Action Chains Integration Tests', () => {
141141
const draftDocuments = useDraftDocuments(mockHost, mockGit as never)
142142
const { selectById, update, revert, list } = draftDocuments
143143

144-
const mockDocument = createMockDocument(documentId)
145-
const fsPath = mockHost.document.getFileSystemPath(documentId)
146-
await mockHost.document.create(fsPath, mockDocument.path, '')
147-
148144
/*
149145
STEP 1: SELECT
150146
*/
@@ -198,9 +194,7 @@ describe('useDraftDocuments - Action Chains Integration Tests', () => {
198194
const draftDocuments = useDraftDocuments(mockHost, mockGit as never)
199195
const { selectById, rename, update, list } = draftDocuments
200196

201-
const mockDocument = createMockDocument(documentId)
202-
const fsPath = mockHost.document.getFileSystemPath(documentId)
203-
const createdDocument = await mockHost.document.create(fsPath, mockDocument.path, '')
197+
const createdDocument = createMockDocument(documentId)
204198

205199
/*
206200
STEP 1: SELECT
@@ -220,12 +214,13 @@ describe('useDraftDocuments - Action Chains Integration Tests', () => {
220214
STEP 2: RENAME
221215
*/
222216
const newId = generateUniqueDocumentId()
223-
const renamedDraftItem = await rename(documentId, newId)
217+
const newFsPath = mockHost.document.getFileSystemPath(newId)
218+
await rename([{ id: documentId, newFsPath }])
224219

225220
// Storage
226221
expect(mockStorage.size).toEqual(2)
227222

228-
const renamedDraftStorage = JSON.parse(mockStorage.get(normalizeKey(renamedDraftItem.id))!)
223+
const renamedDraftStorage = JSON.parse(mockStorage.get(normalizeKey(newId))!)
229224
expect(renamedDraftStorage).toHaveProperty('status', DraftStatus.Created)
230225
expect(renamedDraftStorage).toHaveProperty('id', newId)
231226
expect(renamedDraftStorage).toHaveProperty('original', createdDocument)

0 commit comments

Comments
 (0)