Refactor: split ApiClient into domain extension files
This commit is contained in:
@@ -27,6 +27,43 @@ import ru.ysu.lms.web.api.LevelPayload
|
|||||||
import ru.ysu.lms.web.api.LevelSavePayload
|
import ru.ysu.lms.web.api.LevelSavePayload
|
||||||
import ru.ysu.lms.web.api.StudentRowDto
|
import ru.ysu.lms.web.api.StudentRowDto
|
||||||
import ru.ysu.lms.web.api.VariantSavePayload
|
import ru.ysu.lms.web.api.VariantSavePayload
|
||||||
|
import ru.ysu.lms.web.api.addLevel
|
||||||
|
import ru.ysu.lms.web.api.assignDefense
|
||||||
|
import ru.ysu.lms.web.api.assignVariant
|
||||||
|
import ru.ysu.lms.web.api.createGroup
|
||||||
|
import ru.ysu.lms.web.api.createLab
|
||||||
|
import ru.ysu.lms.web.api.createStudent
|
||||||
|
import ru.ysu.lms.web.api.credentials
|
||||||
|
import ru.ysu.lms.web.api.deleteLab
|
||||||
|
import ru.ysu.lms.web.api.deleteLevel
|
||||||
|
import ru.ysu.lms.web.api.deleteVariant
|
||||||
|
import ru.ysu.lms.web.api.distribute
|
||||||
|
import ru.ysu.lms.web.api.downloadSubmissionAsAdmin
|
||||||
|
import ru.ysu.lms.web.api.enrollStudent
|
||||||
|
import ru.ysu.lms.web.api.getLabAssignments
|
||||||
|
import ru.ysu.lms.web.api.getLevels
|
||||||
|
import ru.ysu.lms.web.api.groupCandidates
|
||||||
|
import ru.ysu.lms.web.api.groupDetail
|
||||||
|
import ru.ysu.lms.web.api.groupPublications
|
||||||
|
import ru.ysu.lms.web.api.importGroup
|
||||||
|
import ru.ysu.lms.web.api.importLab
|
||||||
|
import ru.ysu.lms.web.api.issueDefenseCode
|
||||||
|
import ru.ysu.lms.web.api.labDefenses
|
||||||
|
import ru.ysu.lms.web.api.labDetail
|
||||||
|
import ru.ysu.lms.web.api.labSubmissions
|
||||||
|
import ru.ysu.lms.web.api.listGrades
|
||||||
|
import ru.ysu.lms.web.api.listGroups
|
||||||
|
import ru.ysu.lms.web.api.listLabs
|
||||||
|
import ru.ysu.lms.web.api.publishGrades
|
||||||
|
import ru.ysu.lms.web.api.renameLevel
|
||||||
|
import ru.ysu.lms.web.api.resetDefense
|
||||||
|
import ru.ysu.lms.web.api.resetPassword
|
||||||
|
import ru.ysu.lms.web.api.saveVariant
|
||||||
|
import ru.ysu.lms.web.api.setGrade
|
||||||
|
import ru.ysu.lms.web.api.setLevel
|
||||||
|
import ru.ysu.lms.web.api.toggleLabStatus
|
||||||
|
import ru.ysu.lms.web.api.unenrollStudent
|
||||||
|
import ru.ysu.lms.web.api.updateLab
|
||||||
import ru.ysu.lms.web.session.SessionKeys
|
import ru.ysu.lms.web.session.SessionKeys
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ import ru.ysu.lms.web.api.ApiException
|
|||||||
import ru.ysu.lms.web.api.ArticlesReorderDto
|
import ru.ysu.lms.web.api.ArticlesReorderDto
|
||||||
import ru.ysu.lms.web.api.ContentReorderDto
|
import ru.ysu.lms.web.api.ContentReorderDto
|
||||||
import ru.ysu.lms.web.api.SectionsReorderDto
|
import ru.ysu.lms.web.api.SectionsReorderDto
|
||||||
|
import ru.ysu.lms.web.api.createArticle
|
||||||
|
import ru.ysu.lms.web.api.createChapter
|
||||||
|
import ru.ysu.lms.web.api.createSection
|
||||||
|
import ru.ysu.lms.web.api.deleteChapter
|
||||||
|
import ru.ysu.lms.web.api.deleteContentArticle
|
||||||
|
import ru.ysu.lms.web.api.deleteSection
|
||||||
|
import ru.ysu.lms.web.api.deleteSectionWithMove
|
||||||
|
import ru.ysu.lms.web.api.importContent
|
||||||
|
import ru.ysu.lms.web.api.moveArticle
|
||||||
|
import ru.ysu.lms.web.api.renameChapter
|
||||||
|
import ru.ysu.lms.web.api.renameSection
|
||||||
|
import ru.ysu.lms.web.api.reorderArticles
|
||||||
|
import ru.ysu.lms.web.api.reorderContent
|
||||||
|
import ru.ysu.lms.web.api.reorderSections
|
||||||
|
import ru.ysu.lms.web.api.setContentPublished
|
||||||
|
import ru.ysu.lms.web.api.updateContentArticle
|
||||||
import ru.ysu.lms.web.session.SessionKeys
|
import ru.ysu.lms.web.session.SessionKeys
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
60
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientAuth.kt
Normal file
60
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientAuth.kt
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package ru.ysu.lms.web.api
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
|
||||||
|
fun ApiClient.adminExists(): Boolean =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/auth/health")
|
||||||
|
.retrieve()
|
||||||
|
.body(HealthDto::class.java)
|
||||||
|
}.adminExists
|
||||||
|
|
||||||
|
fun ApiClient.setup(
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
password2: String,
|
||||||
|
): AuthResponseDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/auth/setup")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(SetupPayload(login, password, password2))
|
||||||
|
.retrieve()
|
||||||
|
.body(AuthResponseDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.login(
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
): AuthResponseDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/auth/login")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(LoginPayload(login, password))
|
||||||
|
.retrieve()
|
||||||
|
.body(AuthResponseDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.changePassword(
|
||||||
|
token: String,
|
||||||
|
old: String,
|
||||||
|
new: String,
|
||||||
|
new2: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/auth/change-password")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(ChangePasswordPayload(old, new, new2))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
351
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientContent.kt
Normal file
351
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientContent.kt
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
package ru.ysu.lms.web.api
|
||||||
|
|
||||||
|
import org.springframework.core.ParameterizedTypeReference
|
||||||
|
import org.springframework.core.io.ByteArrayResource
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.util.LinkedMultiValueMap
|
||||||
|
|
||||||
|
fun ApiClient.contentTree(
|
||||||
|
token: String?,
|
||||||
|
all: Boolean = false,
|
||||||
|
): ContentTreeNodeDto =
|
||||||
|
call {
|
||||||
|
val uri = if (all) "/api/v1/content/tree/all" else "/api/v1/content/tree"
|
||||||
|
val spec = client.get().uri(uri)
|
||||||
|
(if (token != null) spec.header(HttpHeaders.AUTHORIZATION, bearer(token)) else spec)
|
||||||
|
.retrieve()
|
||||||
|
.body(ContentTreeNodeDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.contentArticle(
|
||||||
|
token: String?,
|
||||||
|
chapter: String,
|
||||||
|
section: String,
|
||||||
|
article: String,
|
||||||
|
all: Boolean = false,
|
||||||
|
): ContentArticleDto =
|
||||||
|
call {
|
||||||
|
val uri = if (all) "/api/v1/content/all/{c}/{s}/{a}" else "/api/v1/content/{c}/{s}/{a}"
|
||||||
|
val spec = client.get().uri(uri, chapter, section, article)
|
||||||
|
(if (token != null) spec.header(HttpHeaders.AUTHORIZATION, bearer(token)) else spec)
|
||||||
|
.retrieve()
|
||||||
|
.body(ContentArticleDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.setContentPublished(
|
||||||
|
token: String,
|
||||||
|
kind: String,
|
||||||
|
id: String,
|
||||||
|
published: Boolean,
|
||||||
|
) {
|
||||||
|
val path =
|
||||||
|
when (kind) {
|
||||||
|
"chapters" -> "/api/v1/content/chapters/{id}/published"
|
||||||
|
"sections" -> "/api/v1/content/sections/{id}/published"
|
||||||
|
"articles" -> "/api/v1/content/articles/{id}/published"
|
||||||
|
else -> throw IllegalArgumentException("Неизвестный тип материала: $kind")
|
||||||
|
}
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri(path, id)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("published" to published))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.contentTreeList(token: String?): List<ContentArticleDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<ContentArticleDto>>() {}
|
||||||
|
return call {
|
||||||
|
val spec = client.get().uri("/api/v1/content/articles")
|
||||||
|
(if (token != null) spec.header(HttpHeaders.AUTHORIZATION, bearer(token)) else spec)
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.reorderContent(
|
||||||
|
token: String,
|
||||||
|
tree: ContentReorderDto,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/reorder")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(tree)
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.reorderSections(
|
||||||
|
token: String,
|
||||||
|
chapterId: String,
|
||||||
|
body: SectionsReorderDto,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/chapters/{id}/sections/reorder", chapterId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(body)
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.reorderArticles(
|
||||||
|
token: String,
|
||||||
|
sectionId: String,
|
||||||
|
body: ArticlesReorderDto,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/sections/{id}/articles/reorder", sectionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(body)
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.importContent(
|
||||||
|
token: String,
|
||||||
|
filename: String,
|
||||||
|
bytes: ByteArray,
|
||||||
|
sync: Boolean = true,
|
||||||
|
): ContentImportResultDto {
|
||||||
|
val parts = LinkedMultiValueMap<String, Any>()
|
||||||
|
parts.add("sync", sync.toString())
|
||||||
|
parts.add(
|
||||||
|
"file",
|
||||||
|
object : ByteArrayResource(bytes) {
|
||||||
|
override fun getFilename(): String = filename
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/import")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
.body(parts)
|
||||||
|
.retrieve()
|
||||||
|
.body(ContentImportResultDto::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.updateContentArticle(
|
||||||
|
token: String,
|
||||||
|
articleId: String,
|
||||||
|
title: String,
|
||||||
|
bodyMd: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/content/articles/{id}", articleId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title, "bodyMd" to bodyMd))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteContentArticle(
|
||||||
|
token: String,
|
||||||
|
articleId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/content/articles/{id}", articleId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.contentAsset(name: String): DownloadDto {
|
||||||
|
val entity =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/content/assets/{name}", name)
|
||||||
|
.retrieve()
|
||||||
|
.toEntity(ByteArray::class.java)
|
||||||
|
}
|
||||||
|
return DownloadDto(
|
||||||
|
bytes = entity.body ?: ByteArray(0),
|
||||||
|
filename = name,
|
||||||
|
contentType = entity.headers.contentType?.toString() ?: "application/octet-stream",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createChapter(
|
||||||
|
token: String,
|
||||||
|
title: String,
|
||||||
|
slug: String?,
|
||||||
|
): Map<String, Any> {
|
||||||
|
val type = object : ParameterizedTypeReference<Map<String, Any>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/chapters")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title, "slug" to slug))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.renameChapter(
|
||||||
|
token: String,
|
||||||
|
chapterId: String,
|
||||||
|
title: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/content/chapters/{id}", chapterId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteChapter(
|
||||||
|
token: String,
|
||||||
|
chapterId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/content/chapters/{id}", chapterId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createSection(
|
||||||
|
token: String,
|
||||||
|
chapterId: String,
|
||||||
|
title: String,
|
||||||
|
slug: String?,
|
||||||
|
): Map<String, Any> {
|
||||||
|
val type = object : ParameterizedTypeReference<Map<String, Any>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/sections?chapterId={cid}", chapterId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title, "slug" to slug))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.renameSection(
|
||||||
|
token: String,
|
||||||
|
sectionId: String,
|
||||||
|
title: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/content/sections/{id}", sectionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteSection(
|
||||||
|
token: String,
|
||||||
|
sectionId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/content/sections/{id}", sectionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteSectionWithMove(
|
||||||
|
token: String,
|
||||||
|
sectionId: String,
|
||||||
|
moveTo: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri { b -> b.path("/api/v1/content/sections/{id}").queryParam("moveTo", moveTo).build(sectionId) }
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createArticle(
|
||||||
|
token: String,
|
||||||
|
chapterId: String?,
|
||||||
|
sectionId: String?,
|
||||||
|
newChapterTitle: String?,
|
||||||
|
newSectionTitle: String?,
|
||||||
|
title: String,
|
||||||
|
bodyMd: String,
|
||||||
|
): ContentArticleDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/articles")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(
|
||||||
|
mapOf(
|
||||||
|
"chapterId" to chapterId,
|
||||||
|
"sectionId" to sectionId,
|
||||||
|
"newChapterTitle" to newChapterTitle,
|
||||||
|
"newSectionTitle" to newSectionTitle,
|
||||||
|
"title" to title,
|
||||||
|
"bodyMd" to bodyMd,
|
||||||
|
),
|
||||||
|
).retrieve()
|
||||||
|
.body(ContentArticleDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.moveArticle(
|
||||||
|
token: String,
|
||||||
|
articleId: String,
|
||||||
|
newSectionId: String,
|
||||||
|
): ContentArticleDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/content/articles/{id}/move", articleId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(ArticleMovePayload(newSectionId))
|
||||||
|
.retrieve()
|
||||||
|
.body(ContentArticleDto::class.java)
|
||||||
|
}
|
||||||
173
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientIdentity.kt
Normal file
173
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientIdentity.kt
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package ru.ysu.lms.web.api
|
||||||
|
|
||||||
|
import org.springframework.core.ParameterizedTypeReference
|
||||||
|
import org.springframework.core.io.ByteArrayResource
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.util.LinkedMultiValueMap
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
fun ApiClient.listGroups(token: String): List<GroupDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<GroupDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/groups")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createGroup(
|
||||||
|
token: String,
|
||||||
|
name: String,
|
||||||
|
): GroupDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/groups")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(CreateGroupPayload(name))
|
||||||
|
.retrieve()
|
||||||
|
.body(GroupDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.importGroup(
|
||||||
|
token: String,
|
||||||
|
name: String?,
|
||||||
|
filename: String,
|
||||||
|
bytes: ByteArray,
|
||||||
|
): ImportResultDto {
|
||||||
|
val parts = LinkedMultiValueMap<String, Any>()
|
||||||
|
parts.add(
|
||||||
|
"file",
|
||||||
|
object : ByteArrayResource(bytes) {
|
||||||
|
override fun getFilename(): String = filename
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (!name.isNullOrBlank()) {
|
||||||
|
parts.add("name", name)
|
||||||
|
}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/groups/import")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
.body(parts)
|
||||||
|
.retrieve()
|
||||||
|
.body(ImportResultDto::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.groupDetail(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
): GroupDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/groups/{id}", groupId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(GroupDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.groupCandidates(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
): List<StudentCandidateDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<StudentCandidateDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/groups/{id}/candidates", groupId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.enrollStudent(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
studentId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/groups/{id}/students/{sid}/enroll", groupId, studentId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.unenrollStudent(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
studentId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/groups/{id}/students/{sid}", groupId, studentId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.resetPassword(
|
||||||
|
token: String,
|
||||||
|
studentId: String,
|
||||||
|
): ResetPasswordDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/students/{id}/reset-password", studentId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(ResetPasswordDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.credentials(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
format: String,
|
||||||
|
): DownloadDto {
|
||||||
|
val entity =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri { builder ->
|
||||||
|
builder.path("/api/v1/groups/{id}/credentials").queryParam("format", format).build(groupId)
|
||||||
|
}.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toEntity(ByteArray::class.java)
|
||||||
|
}
|
||||||
|
val disposition = entity.headers.getFirst(HttpHeaders.CONTENT_DISPOSITION).orEmpty()
|
||||||
|
val rawName = disposition.substringAfter("UTF-8''", "").substringBefore(';').ifBlank { "credentials.$format" }
|
||||||
|
val filename = URLDecoder.decode(rawName, StandardCharsets.UTF_8)
|
||||||
|
val contentType = entity.headers.contentType?.toString() ?: "application/octet-stream"
|
||||||
|
return DownloadDto(entity.body ?: ByteArray(0), filename, contentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createStudent(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
payload: CreateStudentRequestDto,
|
||||||
|
): CredentialDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/groups/{id}/students", groupId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(CredentialDto::class.java)
|
||||||
|
}
|
||||||
246
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientLab.kt
Normal file
246
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientLab.kt
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
package ru.ysu.lms.web.api
|
||||||
|
|
||||||
|
import org.springframework.core.ParameterizedTypeReference
|
||||||
|
import org.springframework.core.io.ByteArrayResource
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.util.LinkedMultiValueMap
|
||||||
|
|
||||||
|
fun ApiClient.listLabs(token: String): List<LabSummaryDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<LabSummaryDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/labs")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.labDetail(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): LabDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/labs/{id}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.importLab(
|
||||||
|
token: String,
|
||||||
|
filename: String,
|
||||||
|
bytes: ByteArray,
|
||||||
|
): LabImportResultDto {
|
||||||
|
val parts = LinkedMultiValueMap<String, Any>()
|
||||||
|
parts.add(
|
||||||
|
"file",
|
||||||
|
object : ByteArrayResource(bytes) {
|
||||||
|
override fun getFilename(): String = filename
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/labs/import")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
.body(parts)
|
||||||
|
.retrieve()
|
||||||
|
.body(LabImportResultDto::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteLab(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/labs/{id}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.toggleLabStatus(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/labs/{id}/toggle-status", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.getLevels(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): List<LevelAssignmentResultDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<LevelAssignmentResultDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/levels?labId={labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.setLevel(
|
||||||
|
token: String,
|
||||||
|
payload: LevelAssignPayload,
|
||||||
|
): LevelAssignmentResultDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/levels")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(LevelAssignmentResultDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.updateLab(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
payload: LabUpdatePayload,
|
||||||
|
): LabDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/labs/{id}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.saveVariant(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
variantId: String?,
|
||||||
|
payload: VariantSavePayload,
|
||||||
|
): LabDetailDto =
|
||||||
|
if (variantId.isNullOrBlank()) {
|
||||||
|
addVariant(token, labId, payload)
|
||||||
|
} else {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/labs/{id}/variants/{vid}", labId, variantId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.addVariant(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
payload: VariantSavePayload,
|
||||||
|
): LabDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/labs/{id}/variants", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteVariant(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
variantId: String,
|
||||||
|
): LabDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/labs/{id}/variants/{vid}", labId, variantId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.createLab(
|
||||||
|
token: String,
|
||||||
|
payload: LabCreatePayload,
|
||||||
|
): LabDetailDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/labs")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(LabDetailDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.addLevel(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
payload: LevelSavePayload,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/labs/{id}/levels", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.renameLevel(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
levelId: String,
|
||||||
|
title: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.put()
|
||||||
|
.uri("/api/v1/labs/{id}/levels/{lid}", labId, levelId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("title" to title))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.deleteLevel(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
levelId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.delete()
|
||||||
|
.uri("/api/v1/labs/{id}/levels/{lid}", labId, levelId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
373
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt
Normal file
373
web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
package ru.ysu.lms.web.api
|
||||||
|
|
||||||
|
import org.springframework.core.ParameterizedTypeReference
|
||||||
|
import org.springframework.core.io.ByteArrayResource
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.util.LinkedMultiValueMap
|
||||||
|
|
||||||
|
fun ApiClient.distribute(
|
||||||
|
token: String,
|
||||||
|
payload: DistributeRequestPayload,
|
||||||
|
): DistributeResultDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/distribute")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(DistributeResultDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.assignVariant(
|
||||||
|
token: String,
|
||||||
|
payload: AssignVariantPayload,
|
||||||
|
): VariantAssignmentResultDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/assign")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(VariantAssignmentResultDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.getLabAssignments(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): List<VariantAssignmentResultDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<VariantAssignmentResultDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/assignments?labId={labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.meAssignments(token: String): List<MeAssignmentDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<MeAssignmentDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/me/assignments")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.listGrades(token: String): List<GradeDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<GradeDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/grades")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.setGrade(
|
||||||
|
token: String,
|
||||||
|
payload: GradeSetPayload,
|
||||||
|
): GradeDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/grades")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(payload)
|
||||||
|
.retrieve()
|
||||||
|
.body(GradeDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.suggestComments(
|
||||||
|
token: String,
|
||||||
|
query: String,
|
||||||
|
): List<CommentDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<CommentDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/comment-templates?q={q}", query)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.myGrades(token: String): List<GradeDto> = myGrades(token, null)
|
||||||
|
|
||||||
|
fun ApiClient.myGrades(
|
||||||
|
token: String,
|
||||||
|
groupId: String?,
|
||||||
|
): List<GradeDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<GradeDto>>() {}
|
||||||
|
return call {
|
||||||
|
val uri =
|
||||||
|
if (groupId.isNullOrBlank()) {
|
||||||
|
"/api/v1/me/grades"
|
||||||
|
} else {
|
||||||
|
"/api/v1/me/grades?groupId={gid}"
|
||||||
|
}
|
||||||
|
val spec =
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri(if (groupId.isNullOrBlank()) uri else uri, *if (groupId.isNullOrBlank()) emptyArray() else arrayOf(groupId))
|
||||||
|
spec.header(HttpHeaders.AUTHORIZATION, bearer(token)).retrieve().body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.groupPublications(
|
||||||
|
token: String,
|
||||||
|
groupId: String,
|
||||||
|
): List<String> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<String>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/grades/publications?groupId={gid}", groupId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.publishGrades(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
groupId: String,
|
||||||
|
published: Boolean,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/grades/publish?labId={lab}&groupId={g}&published={p}", labId, groupId, published)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.myGroup(token: String): List<GroupDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<GroupDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/groups/me")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.submitLab(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
files: List<Pair<String, ByteArray>>,
|
||||||
|
): List<SubmissionDto> {
|
||||||
|
val parts = LinkedMultiValueMap<String, Any>()
|
||||||
|
for ((name, bytes) in files) {
|
||||||
|
parts.add(
|
||||||
|
"files",
|
||||||
|
object : ByteArrayResource(bytes) {
|
||||||
|
override fun getFilename(): String = name
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val type = object : ParameterizedTypeReference<List<SubmissionDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/me/submissions/{labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
.body(parts)
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.mySubmissions(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): List<SubmissionDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<SubmissionDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/me/submissions?labId={labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.labSubmissions(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): List<SubmissionDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<SubmissionDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/submissions?labId={labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.downloadMySubmission(
|
||||||
|
token: String,
|
||||||
|
submissionId: String,
|
||||||
|
): DownloadDto {
|
||||||
|
val entity =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/me/submissions/{id}/download", submissionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toEntity(ByteArray::class.java)
|
||||||
|
}
|
||||||
|
return downloadOf(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.downloadSubmissionAsAdmin(
|
||||||
|
token: String,
|
||||||
|
submissionId: String,
|
||||||
|
): DownloadDto {
|
||||||
|
val entity =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/submissions/{id}/download", submissionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toEntity(ByteArray::class.java)
|
||||||
|
}
|
||||||
|
return downloadOf(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.labDefenses(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): List<DefenseDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<DefenseDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/defenses?labId={labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.assignDefense(
|
||||||
|
token: String,
|
||||||
|
studentId: String,
|
||||||
|
labId: String,
|
||||||
|
assignmentMd: String,
|
||||||
|
): DefenseDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/defenses/assign")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("studentId" to studentId, "labId" to labId, "assignmentMd" to assignmentMd))
|
||||||
|
.retrieve()
|
||||||
|
.body(DefenseDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.issueDefenseCode(
|
||||||
|
token: String,
|
||||||
|
sessionId: String,
|
||||||
|
): String =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/defenses/{id}/issue-code", sessionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(Map::class.java)
|
||||||
|
}.get("code").toString()
|
||||||
|
|
||||||
|
fun ApiClient.resetDefense(
|
||||||
|
token: String,
|
||||||
|
sessionId: String,
|
||||||
|
) {
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/defenses/{id}/reset", sessionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.myDefenses(token: String): List<DefenseDto> {
|
||||||
|
val type = object : ParameterizedTypeReference<List<DefenseDto>>() {}
|
||||||
|
return call {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/me/defenses")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.myDefense(
|
||||||
|
token: String,
|
||||||
|
labId: String,
|
||||||
|
): DefenseDto? =
|
||||||
|
callOrNull {
|
||||||
|
client
|
||||||
|
.get()
|
||||||
|
.uri("/api/v1/me/defenses/{labId}", labId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.retrieve()
|
||||||
|
.body(DefenseDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.startDefense(
|
||||||
|
token: String,
|
||||||
|
code: String,
|
||||||
|
): DefenseDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/me/defenses/start")
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.body(mapOf("code" to code))
|
||||||
|
.retrieve()
|
||||||
|
.body(DefenseDto::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApiClient.finishDefense(
|
||||||
|
token: String,
|
||||||
|
sessionId: String,
|
||||||
|
): DefenseDto =
|
||||||
|
call {
|
||||||
|
client
|
||||||
|
.post()
|
||||||
|
.uri("/api/v1/me/defenses/{id}/finish", sessionId)
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, bearer(token))
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.retrieve()
|
||||||
|
.body(DefenseDto::class.java)
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@ import org.springframework.web.bind.annotation.RequestParam
|
|||||||
import ru.ysu.lms.web.api.ApiClient
|
import ru.ysu.lms.web.api.ApiClient
|
||||||
import ru.ysu.lms.web.api.ApiException
|
import ru.ysu.lms.web.api.ApiException
|
||||||
import ru.ysu.lms.web.api.AuthResponseDto
|
import ru.ysu.lms.web.api.AuthResponseDto
|
||||||
|
import ru.ysu.lms.web.api.adminExists
|
||||||
|
import ru.ysu.lms.web.api.changePassword
|
||||||
|
import ru.ysu.lms.web.api.login
|
||||||
|
import ru.ysu.lms.web.api.setup
|
||||||
import ru.ysu.lms.web.session.SessionKeys
|
import ru.ysu.lms.web.session.SessionKeys
|
||||||
import ru.ysu.lms.web.session.SessionUser
|
import ru.ysu.lms.web.session.SessionUser
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.GetMapping
|
|||||||
import org.springframework.web.bind.annotation.PathVariable
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
import ru.ysu.lms.web.api.ApiClient
|
import ru.ysu.lms.web.api.ApiClient
|
||||||
|
import ru.ysu.lms.web.api.contentAsset
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проксирует картинки статей (public path) через BFF: страницы /learn/...
|
* Проксирует картинки статей (public path) через BFF: страницы /learn/...
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import ru.ysu.lms.web.api.ApiClient
|
|||||||
import ru.ysu.lms.web.api.ApiException
|
import ru.ysu.lms.web.api.ApiException
|
||||||
import ru.ysu.lms.web.api.ContentArticleDto
|
import ru.ysu.lms.web.api.ContentArticleDto
|
||||||
import ru.ysu.lms.web.api.ContentTreeNodeDto
|
import ru.ysu.lms.web.api.ContentTreeNodeDto
|
||||||
|
import ru.ysu.lms.web.api.contentArticle
|
||||||
|
import ru.ysu.lms.web.api.contentTree
|
||||||
|
import ru.ysu.lms.web.api.contentTreeList
|
||||||
import ru.ysu.lms.web.session.SessionKeys
|
import ru.ysu.lms.web.session.SessionKeys
|
||||||
import ru.ysu.lms.web.session.SessionUser
|
import ru.ysu.lms.web.session.SessionUser
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ import ru.ysu.lms.web.DateUtils
|
|||||||
import ru.ysu.lms.web.api.ApiClient
|
import ru.ysu.lms.web.api.ApiClient
|
||||||
import ru.ysu.lms.web.api.ApiException
|
import ru.ysu.lms.web.api.ApiException
|
||||||
import ru.ysu.lms.web.api.SubmissionDto
|
import ru.ysu.lms.web.api.SubmissionDto
|
||||||
|
import ru.ysu.lms.web.api.downloadMySubmission
|
||||||
|
import ru.ysu.lms.web.api.finishDefense
|
||||||
|
import ru.ysu.lms.web.api.labDetail
|
||||||
|
import ru.ysu.lms.web.api.listLabs
|
||||||
|
import ru.ysu.lms.web.api.meAssignments
|
||||||
|
import ru.ysu.lms.web.api.myDefense
|
||||||
|
import ru.ysu.lms.web.api.myGrades
|
||||||
|
import ru.ysu.lms.web.api.myGroup
|
||||||
|
import ru.ysu.lms.web.api.mySubmissions
|
||||||
|
import ru.ysu.lms.web.api.startDefense
|
||||||
|
import ru.ysu.lms.web.api.submitLab
|
||||||
import ru.ysu.lms.web.session.SessionKeys
|
import ru.ysu.lms.web.session.SessionKeys
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
|||||||
Reference in New Issue
Block a user