Skip to content

Commit fbcdeb9

Browse files
committed
feat(content): rename folders
1 parent 532304d commit fbcdeb9

File tree

7 files changed

+57
-32
lines changed

7 files changed

+57
-32
lines changed

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script setup lang="ts">
22
import { computed, reactive, type PropType } from 'vue'
33
import * as z from 'zod'
4-
import type { FormSubmitEvent } from '@nuxt/ui'
54
import { type CreateFileParams, type CreateFolderParams, type RenameFileParams, type StudioAction, type TreeItem, ContentFileExtension } from '../../../types'
65
import { joinURL, withLeadingSlash, withoutLeadingSlash } from 'ufo'
76
import { contentFileExtensions } from '../../../utils/content'
@@ -35,14 +34,21 @@ const props = defineProps({
3534
})
3635
3736
const originalName = computed(() => props.renamedItem?.name || '')
38-
const originalExtension = computed(() => props.renamedItem?.id.split('.').pop() as ContentFileExtension || ContentFileExtension.Markdown)
37+
const originalExtension = computed(() => {
38+
const ext = props.renamedItem?.id.split('.').pop()
39+
if (ext && contentFileExtensions.includes(ext as ContentFileExtension)) {
40+
return ext as ContentFileExtension
41+
}
42+
43+
return ContentFileExtension.Markdown
44+
})
3945
4046
const schema = z.object({
4147
name: z.string()
4248
.min(1, 'Name cannot be empty')
4349
.refine((name: string) => !name.endsWith('.'), 'Name cannot end with "."')
4450
.refine((name: string) => !name.startsWith('/'), 'Name cannot start with "/"'),
45-
extension: z.enum(ContentFileExtension),
51+
extension: z.optional(z.enum(ContentFileExtension)),
4652
})
4753
4854
type Schema = z.output<typeof schema>
@@ -88,23 +94,27 @@ const tooltipText = computed(() => {
8894
}
8995
})
9096
91-
function onSubmit(_event: FormSubmitEvent<Schema>) {
97+
function onSubmit() {
9298
let params: CreateFileParams | CreateFolderParams | RenameFileParams
99+
const newFsPath = isFolderAction.value
100+
? joinURL(props.parentItem.fsPath, state.name)
101+
: joinURL(props.parentItem.fsPath, `${state.name}.${state.extension}`)
102+
93103
switch (props.actionId) {
94104
case StudioItemActionId.CreateDocument:
95105
params = {
96-
fsPath: withoutLeadingSlash(joinURL(props.parentItem.fsPath, `${state.name}.${state.extension}`)),
106+
fsPath: withoutLeadingSlash(newFsPath),
97107
content: `# ${upperFirst(state.name)} file`,
98108
}
99109
break
100110
case StudioItemActionId.CreateFolder:
101111
params = {
102-
fsPath: withoutLeadingSlash(joinURL(props.parentItem.fsPath, state.name)),
112+
fsPath: withoutLeadingSlash(newFsPath),
103113
}
104114
break
105115
case StudioItemActionId.RenameItem:
106116
params = {
107-
newFsPath: withoutLeadingSlash(joinURL(props.parentItem.fsPath, `${state.name}.${state.extension}`)),
117+
newFsPath: withoutLeadingSlash(newFsPath),
108118
id: props.renamedItem.id,
109119
}
110120
break
@@ -126,7 +136,7 @@ function onSubmit(_event: FormSubmitEvent<Schema>) {
126136
class="hover:bg-white relative w-full min-w-0"
127137
>
128138
<div
129-
v-if="!isFolderAction"
139+
v-show="!isFolderAction"
130140
class="relative"
131141
>
132142
<div class="z-[-1] aspect-video rounded-lg bg-elevated" />

src/app/src/composables/useContext.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { oneStepActions, STUDIO_ITEM_ACTION_DEFINITIONS, twoStepActions } from '
1616
import { useModal } from './useModal'
1717
import type { useTree } from './useTree'
1818
import { useRoute } from 'vue-router'
19-
import { findDescendantsFileItemsFromId } from '../utils/tree'
19+
import { findDescendantsFileItemsFromId, findItemFromId } from '../utils/tree'
2020
import type { useDraftMedias } from './useDraftMedias'
2121
import { joinURL } from 'ufo'
2222
import { upperFirst } from 'scule'
@@ -109,7 +109,16 @@ export const useContext = createSharedComposable((
109109
},
110110
[StudioItemActionId.RenameItem]: async (params: TreeItem | RenameFileParams) => {
111111
const { id, newFsPath } = params as RenameFileParams
112-
await activeTree.value.draft.rename(id, newFsPath)
112+
113+
const descendants = findDescendantsFileItemsFromId(activeTree.value.root.value, id)
114+
if (descendants.length > 0) {
115+
const parent = findItemFromId(activeTree.value.root.value, id)!
116+
const itemsToRename = descendants.map(item => ({ id: item.id, newFsPath: item.fsPath.replace(parent.fsPath, newFsPath) }))
117+
await activeTree.value.draft.rename(itemsToRename)
118+
}
119+
else {
120+
await activeTree.value.draft.rename([{ id, newFsPath }])
121+
}
113122
},
114123
[StudioItemActionId.DeleteItem]: async (item: TreeItem) => {
115124
modal.openConfirmActionModal(item.id, StudioItemActionId.DeleteItem, async () => {

src/app/src/composables/useDraftDocuments.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,24 @@ export const useDraftDocuments = createSharedComposable((host: StudioHost, git:
171171
host.app.requestRerender()
172172
}
173173

174-
async function rename(id: string, newFsPath: string) {
175-
const currentDbItem: DatabaseItem = await host.document.get(id)
176-
if (!currentDbItem) {
177-
throw new Error(`Database item not found for document ${id}`)
178-
}
174+
async function rename(items: { id: string, newFsPath: string }[]) {
175+
for (const item of items) {
176+
const { id, newFsPath } = item
179177

180-
const content = await generateContentFromDocument(currentDbItem)
178+
const currentDbItem: DatabaseItem = await host.document.get(id)
179+
if (!currentDbItem) {
180+
throw new Error(`Database item not found for document ${id}`)
181+
}
182+
183+
const content = await generateContentFromDocument(currentDbItem)
181184

182-
// Delete renamed draft item
183-
await remove([id])
185+
// Delete renamed draft item
186+
await remove([id])
184187

185-
// Create new draft item
186-
const newDbItem = await host.document.create(newFsPath, content!)
187-
return await create(newDbItem, currentDbItem)
188+
// Create new draft item
189+
const newDbItem = await host.document.create(newFsPath, content!)
190+
await create(newDbItem, currentDbItem)
191+
}
188192
}
189193

190194
async function duplicate(id: string): Promise<DraftItem<DatabaseItem>> {

src/app/src/composables/useDraftMedias.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export const useDraftMedias = createSharedComposable((host: StudioHost, git: Ret
153153
// host.app.requestRerender()
154154
// }
155155

156-
async function rename(_id: string, _newFsPath: string) {
156+
async function rename(_items: { id: string, newFsPath: string }[]) {
157157
// let currentDbItem: MediaItem = await host.document.get(id)
158158
// if (!currentDbItem) {
159159
// throw new Error(`Database item not found for document ${id}`)

src/app/src/utils/context.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ export function computeActionItems(itemActions: StudioAction[], item?: TreeItem
7272
forbiddenActions.push(StudioItemActionId.DuplicateItem, StudioItemActionId.RenameItem, StudioItemActionId.DeleteItem)
7373
break
7474
case TreeStatus.Renamed:
75-
forbiddenActions.push(StudioItemActionId.RenameItem)
7675
break
7776
default:
7877
forbiddenActions.push(StudioItemActionId.RevertItem)

src/app/src/utils/tree.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -317,15 +317,20 @@ function calculateDirectoryStatuses(items: TreeItem[]) {
317317
const childrenWithStatus = item.children.filter(child => child.status && child.status !== TreeStatus.Opened)
318318

319319
if (childrenWithStatus.length > 0) {
320-
// Check if ALL children with status are deleted
321-
const allDeleted = childrenWithStatus.every(child => child.status === TreeStatus.Deleted)
322-
323-
if (allDeleted && childrenWithStatus.length === item.children.length) {
324-
// If all children are deleted, mark directory as deleted
325-
item.status = TreeStatus.Deleted
320+
const allChildrenHaveStatus = childrenWithStatus.length === item.children.length
321+
322+
if (allChildrenHaveStatus) {
323+
if (childrenWithStatus.every(child => child.status === TreeStatus.Deleted)) {
324+
item.status = TreeStatus.Created
325+
}
326+
else if (childrenWithStatus.every(child => child.status === TreeStatus.Renamed)) {
327+
item.status = TreeStatus.Renamed
328+
}
329+
else if (childrenWithStatus.every(child => child.status === TreeStatus.Created)) {
330+
item.status = TreeStatus.Created
331+
}
326332
}
327333
else {
328-
// Otherwise, mark as updated
329334
item.status = TreeStatus.Updated
330335
}
331336
}

src/module/src/runtime/utils/content.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ async function generateDocumentFromMarkdownContent(id: string, content: string):
111111
},
112112
})
113113

114-
console.log('document =>', document)
115-
116114
// Remove nofollow from links
117115
visit(document.body, (node: Node) => (node as MDCElement).type === 'element' && (node as MDCElement).tag === 'a', (node: Node) => {
118116
if ((node as MDCElement).props?.rel?.join(' ') === 'nofollow') {

0 commit comments

Comments
 (0)