Skip to content

Commit

Permalink
Merge pull request #1163 from Aalto-LeTech/services
Browse files Browse the repository at this point in the history
Services
  • Loading branch information
jaakkonakaza authored Nov 13, 2024
2 parents 5521c3e + 4912362 commit e102c4e
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 58 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

# Validate wrapper
- name: Gradle Wrapper Validation
uses: gradle/actions/wrapper-validation@v3
uses: gradle/actions/wrapper-validation@v4

# Set up Java environment for the next steps
- name: Setup Java
Expand All @@ -54,7 +54,7 @@ jobs:

# Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v4
with:
gradle-home-cache-cleanup: true

Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:

# Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v4
with:
gradle-home-cache-cleanup: true

Expand Down Expand Up @@ -169,7 +169,7 @@ jobs:

# Run Qodana inspections
- name: Qodana - Code Inspection
uses: JetBrains/qodana-action@v2024.1.5
uses: JetBrains/qodana-action@v2024.2.6
with:
cache-default-branch-only: true
env:
Expand Down Expand Up @@ -202,7 +202,7 @@ jobs:

# Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v4
with:
gradle-home-cache-cleanup: true

Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ pluginName = A+ Courses
pluginRepositoryUrl = https://github.com/Aalto-LeTech/aplus-courses

# SemVer format -> https://semver.org
pluginVersion=4.1.0
pluginVersion=4.1.1

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

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

# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
platformPlugins = org.intellij.scala:2024.2.20
platformPlugins=org.intellij.scala:2024.3.10
platformBundledPlugins = com.intellij.java

# Gradle Releases -> https://github.com/gradle/gradle/releases
Expand Down
10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[versions]
# plugins
kotlin = "2.0.20"
intelliJPlatform = "2.0.1"
kotlin = "2.0.21"
intelliJPlatform = "2.1.0"
changelog = "2.2.1"
qodana = "2024.1.9"
qodana = "2024.2.6"
kover = "0.8.3"

# libraries
jsonSerialization = "1.7.1"
jsonSerialization = "1.7.3"
datetime = "0.6.1"
ktor = "2.3.12"
ktor = "3.0.1"

[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ internal class APlusModuleBuilder : ModuleBuilder() {
project: Project,
model: ModifiableModuleModel?,
modulesProvider: ModulesProvider?
): List<Module?>? {
): List<Module>? {
CoursesLogger.info("Creating project from $courseConfigUrl, language: $language")
project.service<CourseFileManager>().updateSettings(
language,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessModuleDir
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.toNioPathOrNull
import com.intellij.platform.ide.progress.withModalProgress
import com.intellij.ui.dsl.builder.panel
import fi.aalto.cs.apluscourses.MyBundle.message
import fi.aalto.cs.apluscourses.api.APlusApi
import fi.aalto.cs.apluscourses.model.component.Component
Expand All @@ -21,12 +23,14 @@ import fi.aalto.cs.apluscourses.model.people.User
import fi.aalto.cs.apluscourses.notifications.ModuleExportedNotification
import fi.aalto.cs.apluscourses.services.course.CourseManager
import fi.aalto.cs.apluscourses.ui.module.ExportModuleDialog
import fi.aalto.cs.apluscourses.utils.CoursesLogger
import fi.aalto.cs.apluscourses.utils.Version
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.FileOutputStream
import java.util.concurrent.atomic.AtomicBoolean
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
Expand All @@ -36,71 +40,107 @@ class ModuleImportExport(
val project: Project,
val cs: CoroutineScope
) {
private val running = AtomicBoolean(false)

fun importModules() {
if (!running.compareAndSet(false, true)) {
return
}
val modulesWithErrors = mutableListOf<String>()
FileChooser.chooseFiles(FileChooserDescriptorImpl(), project, null) { files ->
cs.launch {
withModalProgress(project, message("ui.ModuleImportExport.import.progress")) {

files.forEach { file ->
val zip = ZipFile(file.toNioPath().toFile())
val desiredModuleName = file.nameWithoutExtension

val zipFile = FileUtil.createTempDirectory("apluscourses", "modules")
zip.entries().asSequence().forEach { entry ->
val entryName = if (entry.name.endsWith(".iml")) {
"$desiredModuleName.iml"
} else {
entry.name
try {
val zip = ZipFile(file.toNioPath().toFile())
val desiredModuleName = file.nameWithoutExtension

val zipFile = FileUtil.createTempDirectory("apluscourses", "modules")
zip.entries().asSequence().forEach { entry ->
val entryName = if (entry.name.endsWith(".iml")) {
"$desiredModuleName.iml"
} else {
entry.name
}
val entryFile = zipFile.resolve(entryName)

if (entry.isDirectory) {
entryFile.mkdirs()
} else {
entryFile.parentFile.mkdirs()
entryFile.writeBytes(zip.getInputStream(entry).readBytes())

}
}
val entryFile = zipFile.resolve(entryName)

if (entry.isDirectory) {
entryFile.mkdirs()
} else {
entryFile.parentFile.mkdirs()
entryFile.writeBytes(zip.getInputStream(entry).readBytes())
// Create and load module
val module = Module(
name = desiredModuleName,
zipUrl = "",
changelog = null,
latestVersion = Version.DEFAULT,
language = null,
project = project
)

}
}
val moduleDir = module.fullPath.toFile()
zipFile.copyRecursively(moduleDir, overwrite = true)

// Create and load module
val module = Module(
name = desiredModuleName,
zipUrl = "",
changelog = null,
latestVersion = Version.DEFAULT,
language = null,
project = project
)

val moduleDir = module.fullPath.toFile()
zipFile.copyRecursively(moduleDir, overwrite = true)

withContext(Dispatchers.EDT) {
if (module.updateAndGetStatus() == Component.Status.NOT_LOADED) {
module.loadToProject()
withContext(Dispatchers.EDT) {
if (module.updateAndGetStatus() == Component.Status.NOT_LOADED) {
module.loadToProject()
}
}
}

module.downloadAndInstall()
val missingDependencies = CourseManager.getInstance(project).getMissingDependencies(module)
missingDependencies.forEach { it.downloadAndInstall() }
module.downloadAndInstall()
val missingDependencies = CourseManager.getInstance(project).getMissingDependencies(module)
missingDependencies.forEach { it.downloadAndInstall() }

zipFile.deleteRecursively()
zipFile.deleteRecursively()
} catch (e: Exception) {
CoursesLogger.error("Failed to import module", e)
modulesWithErrors.add(file.nameWithoutExtension)
}
}


CourseManager.getInstance(project).refreshModuleStatuses()
}
if (modulesWithErrors.isNotEmpty()) {
withContext(Dispatchers.EDT) {
DialogBuilder(project)
.title(message("ui.ModuleImportExport.import.error.title"))
.centerPanel(
panel {
row {
text(
message("ui.ModuleImportExport.import.error.content", modulesWithErrors
.map { "<li>${it}</li>" }
.joinToString(""))
)
}
}
)
.show()
}
}
}
}
running.set(false)
}

fun exportModule() {
cs.launch {
if (!running.compareAndSet(false, true)) {
return@launch
}
exportModuleSuspend()
running.set(false)
}
}

suspend fun exportModuleSuspend() {
private suspend fun exportModuleSuspend() {
val (student, modules, groups) = withModalProgress(
project,
message("ui.ModuleImportExport.export.loading")
Expand Down Expand Up @@ -198,7 +238,7 @@ class ModuleImportExport(
return false
}

val extension = file.getExtension()
val extension = file.extension
return Comparing.strEqual(extension, "zip")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,22 @@ import fi.aalto.cs.apluscourses.utils.FileUtil
import kotlinx.coroutines.*
import java.io.IOException
import java.nio.file.Path
import java.util.concurrent.atomic.AtomicBoolean

@Service(Service.Level.PROJECT)
class SubmitExercise(
private val project: Project,
private val cs: CoroutineScope
) {
private val submissionInfos: MutableMap<Long, SubmissionInfo> = HashMap()
private val submitting = AtomicBoolean(false)

fun submit(exercise: Exercise) {
cs.launch {
if (!submitting.compareAndSet(false, true)) {
CoursesLogger.warn("Already submitting exercise")
return@launch
}
try {
CoursesLogger.info("Submitting $exercise")
var submissionInfo = submissionInfos[exercise.id]
Expand All @@ -57,12 +63,14 @@ class SubmitExercise(
if (!submittable) {
CoursesLogger.warn("$exercise not submittable")
notifier.notify(NotSubmittableNotification(), project)
submitting.set(false)
return@launch
}

val course = CourseManager.course(project)
if (course == null) {
CoursesLogger.error("Course not found")
submitting.set(false)
return@launch
}

Expand Down Expand Up @@ -97,6 +105,7 @@ class SubmitExercise(
)
}) {
CoursesLogger.info("Duplicate submission detected and user chose to cancel")
submitting.set(false)
return@launch
}

Expand Down Expand Up @@ -126,6 +135,7 @@ class SubmitExercise(
if (withContext(Dispatchers.EDT) {
!submissionDialog.showAndGet()
}) {
submitting.set(false)
return@launch
}

Expand All @@ -147,6 +157,7 @@ class SubmitExercise(
notifier.notify(MissingModuleNotification(), project)
}
CoursesLogger.debug("Finished submitting exercise")
submitting.set(false)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ class ExportModuleDialog(
}
row(message("ui.ExportModuleDialog.outputPath")) {
textFieldWithBrowseButton(
message("ui.ExportModuleDialog.selectOutput"),
project,
FileChooserDescriptor(false, true, false, false, false, false)
.withTitle(message("ui.ExportModuleDialog.selectOutput")),
project
)
.bindText(outputPath)
.validationOnApply {
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages/resources.properties
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ ui.ExportModuleDialog.error.noFilename=Please enter a file name
ui.ModuleImportExport.import.title=Import Module
ui.ModuleImportExport.import.description=Choose module zip file(s) to import
ui.ModuleImportExport.import.progress=Importing modules
ui.ModuleImportExport.import.error.title=Error Importing Modules
ui.ModuleImportExport.import.error.content=Could not import the following modules:<br><ul>{0}</ul><br>They might not have been properly exported or are not IntelliJ modules. Try importing them manually.
ui.ModuleImportExport.export.loading=Loading…
ui.ModuleImportExport.export.submitter=Submitter: {0} ({1})
# News
Expand Down

0 comments on commit e102c4e

Please sign in to comment.