Skip to content

Commit deb3037

Browse files
Adding content endpoint of content of folder (#568)
1 parent 85f7b65 commit deb3037

File tree

5 files changed

+146
-0
lines changed

5 files changed

+146
-0
lines changed

backend/documents/documents/src/main/java/io/writeopia/api/documents/documents/repository/DocumentSqlBeDao.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,13 @@ class DocumentSqlBeDao(
739739
?: emptyList()
740740
}
741741

742+
fun loadFoldersByParentId(parentId: String): List<Folder> {
743+
return foldersQueries?.selectChildrenFolder(parentId)
744+
?.executeAsList()
745+
?.map { it.toModel(0) }
746+
?: emptyList()
747+
}
748+
742749
fun deleteDocumentsByUserId(userId: String) {
743750
documentQueries?.deleteByUserId(Clock.System.now().toEpochMilliseconds(), userId)
744751
}

backend/documents/documents/src/main/java/io/writeopia/api/documents/documents/repository/DocumentsRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ suspend fun WriteopiaDbBackend.getFolderById(id: String = "test", userId: String
5858
suspend fun WriteopiaDbBackend.getIdsByParentId(parentId: String = "root"): List<String> =
5959
getDocumentDaoFn().loadDocumentIdsByParentId(parentId)
6060

61+
fun WriteopiaDbBackend.getFoldersByParentId(parentId: String = "root"): List<Folder> =
62+
getDocumentDaoFn().loadFoldersByParentId(parentId)
63+
6164
suspend fun WriteopiaDbBackend.deleteDocumentById(vararg documentIds: String) {
6265
val dao = getDocumentDaoFn()
6366
documentIds.forEach(dao::deleteDocumentById)

backend/documents/documents/src/main/java/io/writeopia/api/documents/routing/DocumentsRouting.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import io.writeopia.api.documents.documents.repository.allFoldersByWorkspaceId
1616
import io.writeopia.api.documents.documents.repository.documentsDiffByFolder
1717
import io.writeopia.api.documents.documents.repository.documentsDiffByWorkspace
1818
import io.writeopia.api.documents.documents.repository.getDocumentsByParentId
19+
import io.writeopia.api.documents.documents.repository.getFoldersByParentId
1920
import io.writeopia.api.documents.documents.repository.getIdsByParentId
2021
import io.writeopia.backend.models.ImageStorageService
2122
import io.writeopia.buckets.GcpBucketImageStorageService
@@ -28,6 +29,7 @@ import io.writeopia.sdk.serialization.json.SendDocumentsRequest
2829
import io.writeopia.sdk.serialization.json.SendFoldersRequest
2930
import io.writeopia.sdk.serialization.request.ImageUploadRequest
3031
import io.writeopia.sdk.serialization.request.WorkspaceDiffRequest
32+
import io.writeopia.sdk.serialization.response.FolderContentResponse
3133
import io.writeopia.sdk.serialization.response.WorkspaceDiffResponse
3234
import io.writeopia.sql.WriteopiaDbBackend
3335
import kotlin.time.Clock
@@ -163,6 +165,34 @@ fun Routing.documentsRoute(
163165
}
164166
}
165167

168+
authenticate("auth-jwt", optional = debug) {
169+
get("/api/workspace/{workspaceId}/folder/{folderId}/contents") {
170+
val folderId = call.pathParameters["folderId"]!!
171+
val userId = getUserId() ?: ""
172+
val workspaceId = call.pathParameters["workspaceId"] ?: ""
173+
174+
runIfMember(userId, workspaceId, writeopiaDb, debug) {
175+
try {
176+
val folders = writeopiaDb.getFoldersByParentId(folderId)
177+
val documents = writeopiaDb.getDocumentsByParentId(folderId)
178+
179+
call.respond(
180+
status = HttpStatusCode.OK,
181+
message = FolderContentResponse(
182+
folders = folders.map { it.toApi() },
183+
documents = documents.map { it.toApi() }
184+
)
185+
)
186+
} catch (e: Exception) {
187+
call.respond(
188+
status = HttpStatusCode.InternalServerError,
189+
message = "${e.message}"
190+
)
191+
}
192+
}
193+
}
194+
}
195+
166196
authenticate("auth-jwt", optional = debug) {
167197
post<SendDocumentsRequest>("/api/workspace/document") { request ->
168198
val userId = getUserId() ?: ""

backend/gateway/src/test/kotlin/io/writeopia/api/gateway/DocumentsIntegrationTest.kt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import io.writeopia.sdk.serialization.extensions.toApi
2323
import io.writeopia.sdk.serialization.json.SendDocumentsRequest
2424
import io.writeopia.sdk.serialization.json.SendFoldersRequest
2525
import io.writeopia.sdk.serialization.request.WorkspaceDiffRequest
26+
import io.writeopia.sdk.serialization.response.FolderContentResponse
2627
import io.writeopia.sdk.serialization.response.WorkspaceDiffResponse
2728
import kotlin.time.Clock
2829
import kotlin.random.Random
@@ -325,4 +326,98 @@ class DocumentationIntegrationTests {
325326
db.deleteDocumentById(documentApi.id)
326327
db.deleteDocumentById(documentApi2.id)
327328
}
329+
330+
@Test
331+
fun `it should be possible to get folder contents with folders and documents`() = testApplication {
332+
application {
333+
module(db, debugMode = true)
334+
}
335+
336+
val client = defaultClient()
337+
val workspaceId = Random.nextInt().toString()
338+
val parentFolderId = "parentFolderId"
339+
340+
val childFolder1 = FolderApi(
341+
id = "childFolder1",
342+
title = "Child Folder 1",
343+
parentId = parentFolderId,
344+
createdAt = Clock.System.now(),
345+
lastUpdatedAt = Clock.System.now(),
346+
workspaceId = workspaceId,
347+
itemCount = 0L,
348+
)
349+
350+
val childFolder2 = FolderApi(
351+
id = "childFolder2",
352+
title = "Child Folder 2",
353+
parentId = parentFolderId,
354+
createdAt = Clock.System.now(),
355+
lastUpdatedAt = Clock.System.now(),
356+
workspaceId = workspaceId,
357+
itemCount = 0L,
358+
)
359+
360+
val document1 = DocumentApi(
361+
id = "document1",
362+
title = "Document 1",
363+
workspaceId = workspaceId,
364+
parentId = parentFolderId,
365+
isLocked = false,
366+
createdAt = 1000L,
367+
lastUpdatedAt = 2000L,
368+
lastSyncedAt = 0L
369+
)
370+
371+
val document2 = DocumentApi(
372+
id = "document2",
373+
title = "Document 2",
374+
workspaceId = workspaceId,
375+
parentId = parentFolderId,
376+
isLocked = false,
377+
createdAt = 1000L,
378+
lastUpdatedAt = 2000L,
379+
lastSyncedAt = 0L
380+
)
381+
382+
// Save folders
383+
val folderResponse = client.post("/api/workspace/folder") {
384+
contentType(ContentType.Application.Json)
385+
setBody(SendFoldersRequest(listOf(childFolder1, childFolder2), workspaceId))
386+
}
387+
388+
assertEquals(HttpStatusCode.OK, folderResponse.status)
389+
390+
// Save documents
391+
val documentResponse = client.post("/api/workspace/document") {
392+
contentType(ContentType.Application.Json)
393+
setBody(SendDocumentsRequest(listOf(document1, document2), workspaceId))
394+
}
395+
396+
assertEquals(HttpStatusCode.OK, documentResponse.status)
397+
398+
// Get folder contents
399+
val contentsResponse = client.get("/api/workspace/$workspaceId/folder/$parentFolderId/contents")
400+
401+
assertEquals(HttpStatusCode.OK, contentsResponse.status)
402+
403+
val contents = contentsResponse.body<FolderContentResponse>()
404+
405+
// Verify folders
406+
assertEquals(2, contents.folders.size)
407+
assertEquals(
408+
listOf(childFolder1.id, childFolder2.id).sorted(),
409+
contents.folders.map { it.id }.sorted()
410+
)
411+
412+
// Verify documents
413+
assertEquals(2, contents.documents.size)
414+
assertEquals(
415+
listOf(document1.id, document2.id).sorted(),
416+
contents.documents.map { it.id }.sorted()
417+
)
418+
419+
// Clean up
420+
db.deleteDocumentById(document1.id)
421+
db.deleteDocumentById(document2.id)
422+
}
328423
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.writeopia.sdk.serialization.response
2+
3+
import io.writeopia.sdk.serialization.data.DocumentApi
4+
import io.writeopia.sdk.serialization.data.FolderApi
5+
import kotlinx.serialization.Serializable
6+
7+
@Serializable
8+
data class FolderContentResponse(
9+
val folders: List<FolderApi> = emptyList(),
10+
val documents: List<DocumentApi> = emptyList()
11+
)

0 commit comments

Comments
 (0)