Skip to content

Commit

Permalink
Merge branch 'private-release/v2.1.0' into zowe-release/v2.1.0
Browse files Browse the repository at this point in the history
Signed-off-by: Uladzislau <[email protected]>
  • Loading branch information
KUGDev committed Sep 26, 2024
2 parents dc98d25 + bcb2b20 commit 2ff2f58
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 123 deletions.
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
#
org.gradle.jvmargs=-Xss1M
# SemVer format -> https://semver.org
pluginVersion=2.0.0
pluginGroup=eu.ibagroup
pluginVersion=2.1.0
pluginGroup=org.zowe
pluginRepositoryUrl=https://github.com/zowe/zowe-explorer-intellij
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.ui.showYesNoDialog
import org.zowe.explorer.explorer.JesWorkingSetImpl
import org.zowe.explorer.explorer.ui.JesExplorerView
import org.zowe.explorer.explorer.ui.JesFilterNode
import org.zowe.explorer.explorer.ui.JesWsNode
import org.zowe.explorer.explorer.ui.getExplorerView
import org.zowe.explorer.explorer.ui.*
import org.zowe.explorer.utils.performUnitsDeletionBasedOnSelection
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty

/**
* Action class for delete JES node action (working set or filter)
Expand All @@ -40,39 +39,18 @@ class DeleteJesNodeAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val view = e.getExplorerView<JesExplorerView>() ?: return
val selected = view.mySelectedNodesData
// Delete selected JES working sets
selected
.map { it.node }
.filterIsInstance<JesWsNode>()
.forEach {
if (
showYesNoDialog(
title = "Deletion of JES Working Set ${it.unit.name}",
message = "Do you want to delete this JES Working Set from configs? Note: all data under it will be untouched",
project = e.project,
icon = AllIcons.General.QuestionDialog
)
) {
view.explorer.disposeUnit(it.unit as JesWorkingSetImpl)
}
}
// Delete selected job filters
selected
.map { it.node }
.filterIsInstance<JesFilterNode>()
.filter { view.explorer.isUnitPresented(it.unit) }
.forEach {
if (
showYesNoDialog(
title = "Deletion Of Jobs Filter",
message = "Do you want to delete this jobs filter with ${it.value} from configs? Note: all data under the filter will be untouched",
project = e.project,
icon = AllIcons.General.QuestionDialog
)
) {
it.unit.removeFilter(it.value)
}
}

// Find items to delete (working set node or filter node)
val suitableToDelete = selected.map { it.node }
.filter { node -> node is JesWsNode || node is JesFilterNode }

val (workingSetsToDelete, selectedFilters) = suitableToDelete.partition { node -> node is JesWsNode }
val jesFiltersToDelete = selectedFilters.filter { jesFilter -> !workingSetsToDelete.contains(jesFilter.parent) }

// Delete working sets and filters that do not belong to them
(workingSetsToDelete + jesFiltersToDelete).ifNotEmpty {
performUnitsDeletionBasedOnSelection(e.project, null, view)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ class PurgeJobAction : AnAction() {
e: AnActionEvent,
view: JesExplorerView
) {
val dataOpsManager = DataOpsManager.getService()
nodes.forEach { nodeData ->
val jobAttributes = nodeData.attributes as RemoteJobAttributes
val jobStatus = jobAttributes.jobInfo
Expand All @@ -271,7 +270,7 @@ class PurgeJobAction : AnAction() {
cancellable = true
) {
runCatching {
dataOpsManager.performOperation(
DataOpsManager.getService().performOperation(
operation = PurgeJobOperation(
request = BasicPurgeJobParams(jobStatus.jobName, jobStatus.jobId),
connectionConfig = connectionConfig
Expand Down Expand Up @@ -312,7 +311,7 @@ class PurgeJobAction : AnAction() {
val selected = view.mySelectedNodesData
val wrongNode = selected.find { it.node !is JobNode }
e.presentation.apply {
isEnabledAndVisible = wrongNode == null && isSelectedJobNodesFromSameWS(selected)
isEnabledAndVisible = selected.isNotEmpty() && wrongNode == null && isSelectedJobNodesFromSameWS(selected)
text = if (isEnabledAndVisible && selected.size > 1) "Purge Jobs" else "Purge Job"
}
} else if (view is JobBuildTreeView) {
Expand Down
73 changes: 16 additions & 57 deletions src/main/kotlin/org/zowe/explorer/explorer/ui/FileExplorerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ import org.zowe.explorer.explorer.FilesWorkingSet
import org.zowe.explorer.telemetry.NotificationsService
import org.zowe.explorer.utils.getMinimalCommonParents
import org.zowe.explorer.utils.getParentsChain
import org.zowe.explorer.utils.performUnitsDeletionBasedOnSelection
import org.zowe.explorer.vfs.MFVirtualFile
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.Transferable
Expand Down Expand Up @@ -435,63 +437,20 @@ class FileExplorerView(
/** Deletes files corresponding to the selected nodes data. */
override fun deleteElement(dataContext: DataContext) {
val selected = mySelectedNodesData
selected.map { it.node }
.filterIsInstance<FilesWorkingSetNode>()
.forEach {
if (
showYesNoDialog(
title = "Deletion of Working Set ${it.unit.name}",
message = "Do you want to delete this Working Set from configs? Note: all data under it will be untouched",
project = project,
icon = AllIcons.General.QuestionDialog
)
) {
explorer.disposeUnit(it.unit as FilesWorkingSet)
}
}
selected.map { it.node }
.filterIsInstance<DSMaskNode>()
.filter { explorer.isUnitPresented(it.unit) }
.forEach {
if (
showYesNoDialog(
title = "Deletion of DS Mask ${it.value.mask}",
message = "Do you want to delete this mask from configs? Note: all data sets under it will be untouched",
project = project,
icon = AllIcons.General.QuestionDialog
)
) {
it.cleanCache(
recursively = true,
cleanFetchProviderCache = true,
cleanBatchedQuery = true,
sendTopic = false
)
it.unit.removeMask(it.value)
}
}
selected.map { it.node }
.filterIsInstance<UssDirNode>()
.filter { it.isUssMask && explorer.isUnitPresented(it.unit) }
.forEach {
val node = it
if (
showYesNoDialog(
title = "Deletion of Uss Path Root ${node.value.path}",
message = "Do you want to delete this USS path root from configs? Note: all files under it will be untouched",
project = project,
icon = AllIcons.General.QuestionDialog
)
) {
node.cleanCache(
recursively = true,
cleanFetchProviderCache = true,
cleanBatchedQuery = true,
sendTopic = false
)
node.unit.removeUssPath(node.value)
}
}

// Find items to delete (working set node or dataset mask node or USS mask node)
val suitableToDelete = selected.map { it.node }
.filter { node -> node is FilesWorkingSetNode || node is DSMaskNode || (node is UssDirNode && node.isUssMask) }

val (workingSetsToDelete, selectedMasks) = suitableToDelete.partition { node -> node is FilesWorkingSetNode }
val masksToDelete = selectedMasks.filter { mask -> !workingSetsToDelete.contains(mask.parent) }

// Delete working sets and masks that do not belong to them
(workingSetsToDelete + masksToDelete).ifNotEmpty {
performUnitsDeletionBasedOnSelection(project, this@FileExplorerView, null)
}

// perform files deletion
val nodeAndFilePairs = optimizeDeletion(selected)
if (nodeAndFilePairs.isNotEmpty()) {
val files = nodeAndFilePairs.map { it.second }.toSet().toList()
Expand Down
38 changes: 24 additions & 14 deletions src/main/kotlin/org/zowe/explorer/explorer/ui/JobNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ class JobNode(
} else {
"ENDED AT: " + parseJobTimestampValueToDisplay(job.execSubmitted) + ". RC = ${job.returnedCode}"
},
if (isErrorReturnCode(job.returnedCode)) {
SimpleTextAttributes(STYLE_BOLD, JBColor.RED)
} else {
SimpleTextAttributes(STYLE_BOLD, JBColor.GREEN)
when (getReturnCode(job.returnedCode)) {
ReturnCode.SUCCESS -> SimpleTextAttributes(STYLE_BOLD, JBColor.GREEN)
ReturnCode.WARNING -> SimpleTextAttributes(STYLE_BOLD, JBColor.ORANGE)
else -> SimpleTextAttributes(STYLE_BOLD, JBColor.RED)
}
)
} else {
Expand All @@ -130,10 +130,10 @@ class JobNode(
} else {
parseJobTimestampValueToDisplay(job.execEnded)
} + ". RC = ${job.returnedCode}",
if (isErrorReturnCode(job.returnedCode)) {
SimpleTextAttributes(STYLE_BOLD, JBColor.RED)
} else {
SimpleTextAttributes(STYLE_BOLD, JBColor.GREEN)
when (getReturnCode(job.returnedCode)) {
ReturnCode.SUCCESS -> SimpleTextAttributes(STYLE_BOLD, JBColor.GREEN)
ReturnCode.WARNING -> SimpleTextAttributes(STYLE_BOLD, JBColor.ORANGE)
else -> SimpleTextAttributes(STYLE_BOLD, JBColor.RED)
}
)
}
Expand Down Expand Up @@ -176,19 +176,29 @@ class JobNode(
/**
* Function to parse return code after job completion
* @param returnCode - return code to parse
* @return true if return code is kind of Error. False otherwise
* @return ReturnCode.ERR if return code is kind of Error.
* ReturnCode.WARN if return code in [1..8] range.
* ReturnCode.SUCCESS otherwise
*/
private fun isErrorReturnCode(returnCode: String?): Boolean {
private fun getReturnCode(returnCode: String?): ReturnCode {
if (returnCode != null) {
return if (!returnCode.contains(Regex("ERR|ABEND|CANCEL|FAIL"))) {
val numberedRC = returnCode.split(" ").getOrNull(1)?.toIntOrNull()
if (numberedRC != null) {
numberedRC > 0
when (numberedRC) {
0 -> ReturnCode.SUCCESS
in 1..7 -> ReturnCode.WARNING
else -> ReturnCode.ERROR
}
} else {
true
ReturnCode.ERROR
}
} else true
} else ReturnCode.ERROR
}
return false
return ReturnCode.SUCCESS
}

enum class ReturnCode {
SUCCESS, WARNING, ERROR
}
}
30 changes: 20 additions & 10 deletions src/main/kotlin/org/zowe/explorer/tso/TSOWindowFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.intellij.ui.content.ContentManagerListener
import com.intellij.util.messages.Topic
import org.zowe.explorer.dataops.DataOpsManager
import org.zowe.explorer.dataops.exceptions.CallException
import org.zowe.explorer.dataops.exceptions.CredentialsNotFoundForConnection
import org.zowe.explorer.dataops.operations.MessageData
import org.zowe.explorer.dataops.operations.MessageType
import org.zowe.explorer.dataops.operations.TsoOperation
Expand Down Expand Up @@ -347,16 +348,25 @@ class TSOWindowFactory : ToolWindowFactory, PossiblyDumbAware, DumbAware {
processHandler.notifyTextAvailable(parseTSODataResponse(response), ProcessOutputType.STDOUT)
}
}.onFailure {
processHandler.notifyTextAvailable(
"Unsuccessful execution of the TSO request. Connection was broken.\n",
ProcessOutputType.STDOUT
)
executeTsoReconnectWithTimeout(
timeout = session.getTSOSessionConfig().timeout,
maxAttempts = session.getTSOSessionConfig().maxAttempts,
tsoConsole = console
) {
wrapInlineCall { sendTopic(SESSION_RECONNECT_TOPIC, project).reconnect(project, console, session) }
if (it is CredentialsNotFoundForConnection) {
processHandler.notifyTextAvailable(
"Unable to obtain the connection information for connection=${session.getConnectionConfig()}.\n Session will be closed.",
ProcessOutputType.STDOUT
)
session.markSessionUnresponsive()
processHandler.destroyProcess()
} else {
processHandler.notifyTextAvailable(
"Unsuccessful execution of the TSO request. Connection was broken.\n",
ProcessOutputType.STDOUT
)
executeTsoReconnectWithTimeout(
timeout = session.getTSOSessionConfig().timeout,
maxAttempts = session.getTSOSessionConfig().maxAttempts,
tsoConsole = console
) {
wrapInlineCall { sendTopic(SESSION_RECONNECT_TOPIC, project).reconnect(project, console, session) }
}
}
}
}
Expand Down
82 changes: 82 additions & 0 deletions src/main/kotlin/org/zowe/explorer/utils/explorerUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2020-2024 IBA Group.
*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
* Contributors:
* IBA Group
* Zowe Community
*/
package org.zowe.explorer.utils

import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.showYesNoDialog
import org.zowe.explorer.explorer.FilesWorkingSet
import org.zowe.explorer.explorer.JesWorkingSetImpl
import org.zowe.explorer.explorer.ui.*

/**
* Function is used to perform units deletion based on current selection
* Function accepts only:
* Files Working Set nodes
* Dataset Mask nodes
* Uss Directory Root nodes (isUssMask = true)
* JES Working Set nodes
* JES Filter nodes
* @param project
* @param fileExplorerView
* @param jesExplorerView
* @receiver List of filtered nodes by type, e.g. List<DSMaskNode> dsMasksToDelete
*/
fun <T : ExplorerTreeNode<*, *>> List<T>.performUnitsDeletionBasedOnSelection(
project: Project?,
fileExplorerView: FileExplorerView?,
jesExplorerView: JesExplorerView?
) {
var unitTypes = when (first()) {
is FilesWorkingSetNode -> "File Working Set(s)"
is DSMaskNode -> "Dataset Mask(s)"
is UssDirNode -> "Uss Root Path(s)"
is JesWsNode -> "JES Working Set(s)"
else -> "Job Filter(s)"
}
// Change the header and body of the dialog in case both JesWsNode's and JesFilter's are present in receiver list
unitTypes =
if (this.filterIsInstance<JesWsNode>().isNotEmpty() && this.filterIsInstance<JesWsNode>().size != this.size)
"Jes Working Set(s) and Jes Filter(s)"
else unitTypes

if (showYesNoDialog(
title = "Confirm $unitTypes Deletion",
message = "Do you want to delete selected $unitTypes from config? Note: all data under it(them) will be untouched",
project = project,
icon = AllIcons.General.QuestionDialog
)
) {
forEach {
when (val node: T = it) {
is FilesWorkingSetNode -> fileExplorerView?.explorer?.disposeUnit(node.unit as FilesWorkingSet)
is DSMaskNode, is UssDirNode -> {
(node as FileFetchNode<*,*,*,*,*,*>).cleanCache(
recursively = true,
cleanFetchProviderCache = true,
cleanBatchedQuery = true,
sendTopic = false
)
}
}
when (val node: T = it) {
is DSMaskNode -> node.unit.removeMask(node.value)
is UssDirNode -> node.unit.removeUssPath(node.value)
is JesWsNode -> jesExplorerView?.explorer?.disposeUnit(node.unit as JesWorkingSetImpl)
is JesFilterNode -> node.unit.removeFilter(node.value)
}
}
}
}
Loading

0 comments on commit 2ff2f58

Please sign in to comment.