Skip to content

Commit 5521c3e

Browse files
authored
Merge pull request #1154 from Aalto-LeTech/4.1.0
4.1.0
2 parents 0bf8c5d + 2979b0a commit 5521c3e

File tree

18 files changed

+513
-36
lines changed

18 files changed

+513
-36
lines changed

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,43 @@
22

33
# A+ Courses Changelog
44

5+
## [4.1.0] - 2024-10-30
6+
7+
### Added
8+
9+
- Module exporting: Students can now export modules for submission.
10+
- Module importing: Users can import multiple module zip files simultaneously. This feature helps assistants in grading
11+
and allows students to test their zips.
12+
13+
### Changed
14+
15+
- Hid point counter from feedback assignments.
16+
- Removed submission IDs from the assignment tree.
17+
18+
### Fixed
19+
20+
- Improved enrollment detection.
21+
- Added token invalidation detection: The plugin now prompts users to re-enter their token if it is invalid (i.e., a new
22+
one was generated, or it got revoked).
23+
524
## [4.0.3] - 2024-09-04
625

726
### Fixed
827

928
- Increased network timeout to prevent module downloads from stopping on slower connections
1029

30+
## [4.0.2] - 2024-08-28
31+
32+
### Fixed
33+
34+
- Resolved issues for external users and importing IDE settings.
35+
36+
## [4.0.1] - 2024-08-26
37+
38+
### Changed
39+
40+
- Minor UI improvements.
41+
1142
## [4.0.0] - 2024-08-23
1243

1344
### Changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ pluginName = A+ Courses
55
pluginRepositoryUrl = https://github.com/Aalto-LeTech/aplus-courses
66

77
# SemVer format -> https://semver.org
8-
pluginVersion=4.0.3
8+
pluginVersion=4.1.0
99

1010
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1111
pluginSinceBuild = 242
12-
pluginUntilBuild = 242.*
12+
pluginUntilBuild=242.*
1313

1414
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
1515
platformType = IC

src/main/kotlin/fi/aalto/cs/apluscourses/actions/ActionGroups.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ object ActionGroups {
77
val EXERCISE_ACTIONS: DefaultActionGroup
88
get() = actionGroup("fi.aalto.cs.apluscourses.actions.ActionGroups.EXERCISE_ACTIONS")
99

10+
val MODULE_ACTIONS: DefaultActionGroup
11+
get() = actionGroup("fi.aalto.cs.apluscourses.actions.ActionGroups.MODULE_ACTIONS")
12+
1013
val TOOL_WINDOW_ACTIONS: DefaultActionGroup
1114
get() = actionGroup("fi.aalto.cs.apluscourses.actions.ActionGroups.TOOL_WINDOW_ACTIONS")
1215

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package fi.aalto.cs.apluscourses.actions
2+
3+
import com.intellij.openapi.actionSystem.AnAction
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import com.intellij.openapi.components.service
6+
import fi.aalto.cs.apluscourses.services.ModuleImportExport
7+
8+
class ExportModuleAction : AnAction() {
9+
override fun actionPerformed(e: AnActionEvent) {
10+
val project = e.project ?: return
11+
project.service<ModuleImportExport>().exportModule()
12+
}
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package fi.aalto.cs.apluscourses.actions
2+
3+
import com.intellij.openapi.actionSystem.AnAction
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import com.intellij.openapi.components.service
6+
import fi.aalto.cs.apluscourses.services.ModuleImportExport
7+
8+
class ImportModuleAction : AnAction() {
9+
override fun actionPerformed(e: AnActionEvent) {
10+
val project = e.project ?: return
11+
project.service<ModuleImportExport>().importModules()
12+
}
13+
}

src/main/kotlin/fi/aalto/cs/apluscourses/api/APlusApi.kt

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ import io.ktor.client.request.parameter
1111
import io.ktor.client.statement.bodyAsText
1212
import io.ktor.http.*
1313
import io.ktor.resources.*
14-
import kotlinx.serialization.ExperimentalSerializationApi
1514
import kotlinx.serialization.Serializable
1615
import kotlinx.serialization.json.Json
17-
import kotlinx.serialization.json.JsonNamingStrategy
1816
import org.jsoup.Jsoup
1917
import java.time.ZonedDateTime
2018
import kotlin.collections.component1
@@ -43,12 +41,8 @@ object APlusApi {
4341
@Resource("exercises")
4442
class Exercises(val parent: Course) {
4543
suspend fun get(project: Project): List<CourseModule> {
46-
// TODO remove after hasSubmittableFiles fixed
47-
// CoursesClient.getInstance(project).getBody<Exercises, CourseModuleResults>(this@Exercises).results
48-
val res = CoursesClient.getInstance(project).get<Exercises>(this@Exercises)
49-
return json.decodeFromString<CourseModuleResults>(
50-
res.bodyAsText().replace("\"has_submittable_files\":[]", "\"has_submittable_files\":false")
51-
).results
44+
return CoursesClient.getInstance(project)
45+
.getBody<Exercises, CourseModuleResults>(this@Exercises).results
5246
}
5347

5448
@Serializable
@@ -77,18 +71,8 @@ object APlusApi {
7771
val maxSubmissions: Int,
7872
val hierarchicalName: String,
7973
val difficulty: String,
80-
// val hasSubmittableFiles: Boolean // TODO should always be bool, currently boolean or null or array
81-
val hasSubmittableFiles: Boolean?
74+
val hasSubmittableFiles: Boolean
8275
)
83-
84-
companion object {
85-
@OptIn(ExperimentalSerializationApi::class)
86-
private val json = Json { // TODO remove after hasSubmittableFiles fixed
87-
ignoreUnknownKeys = true
88-
isLenient = true
89-
namingStrategy = JsonNamingStrategy.SnakeCase
90-
}
91-
}
9276
}
9377

9478
@Resource("points/me")

src/main/kotlin/fi/aalto/cs/apluscourses/model/exercise/Exercise.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ data class Exercise(
1616
val difficulty: String = "",
1717
val isOptional: Boolean,
1818
val isSubmittable: Boolean,
19+
val isFeedback: Boolean
1920
) {
2021

2122
/**
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package fi.aalto.cs.apluscourses.notifications
2+
3+
import com.intellij.ide.actions.RevealFileAction
4+
import com.intellij.notification.Notification
5+
import com.intellij.notification.NotificationAction
6+
import com.intellij.notification.NotificationType
7+
import com.intellij.openapi.module.Module
8+
import fi.aalto.cs.apluscourses.MyBundle.message
9+
import fi.aalto.cs.apluscourses.services.PluginSettings
10+
import java.io.File
11+
12+
class ModuleExportedNotification(module: Module, exportedFile: File) : Notification(
13+
PluginSettings.A_PLUS,
14+
message("notification.ModuleExportedNotification.title"),
15+
message("notification.ModuleExportedNotification.content", module.name, exportedFile.path),
16+
NotificationType.INFORMATION
17+
) {
18+
init {
19+
addAction(NotificationAction.createSimple(
20+
message("notification.ModuleExportedNotification.showInFiles")
21+
) {
22+
RevealFileAction.openFile(exportedFile)
23+
})
24+
}
25+
}

src/main/kotlin/fi/aalto/cs/apluscourses/services/CoursesClient.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.intellij.openapi.components.service
55
import com.intellij.openapi.project.Project
66
import com.intellij.platform.ide.progress.withBackgroundProgress
77
import com.intellij.platform.util.progress.reportSequentialProgress
8+
import com.intellij.serialization.PropertyMapping
89
import fi.aalto.cs.apluscourses.MyBundle.message
910
import io.ktor.client.*
1011
import io.ktor.client.call.*
@@ -36,6 +37,10 @@ import kotlin.io.readBytes
3637
import kotlin.sequences.forEach
3738
import kotlin.text.contains
3839

40+
class UnauthorizedException @PropertyMapping() constructor() : Exception() {
41+
private val serialVersionUID: Long = 1L
42+
}
43+
3944
@OptIn(ExperimentalSerializationApi::class)
4045
@Service(Service.Level.PROJECT)
4146
class CoursesClient(
@@ -141,6 +146,9 @@ class CoursesClient(
141146
requestBuilder()
142147
}
143148
}
149+
if (res.status == HttpStatusCode.Unauthorized) {
150+
throw UnauthorizedException()
151+
}
144152
if (res.status != HttpStatusCode.OK) {
145153
throw IOException("Failed to get body: ${res.status}")
146154
}

0 commit comments

Comments
 (0)