mirror of
https://github.com/TermoraDev/termora.git
synced 2026-03-31 21:32:20 +08:00
feat: Add guest mode support and permission controls
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.account.TeamRole
|
||||
import app.termora.actions.AnAction
|
||||
import app.termora.actions.AnActionEvent
|
||||
import app.termora.database.OwnerType
|
||||
import app.termora.protocol.*
|
||||
import app.termora.transfer.ScaleIcon
|
||||
import com.formdev.flatlaf.extras.components.FlatToolBar
|
||||
@@ -13,9 +15,11 @@ import kotlinx.coroutines.swing.Swing
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||
import org.jdesktop.swingx.SwingXUtilities
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.CardLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.Graphics
|
||||
import java.awt.Window
|
||||
import javax.swing.*
|
||||
|
||||
@@ -144,10 +148,33 @@ class NewHostDialogV2(
|
||||
val provider = extension.getProtocolProvider()
|
||||
testConnectionBtn.isVisible = provider is ProtocolTester
|
||||
|
||||
preventImportantData()
|
||||
}
|
||||
|
||||
private fun preventImportantData() {
|
||||
if (visitorMode()) {
|
||||
for (component in SwingUtils.getDescendantsOfType(JComponent::class.java, cardPanel)) {
|
||||
if (component is OutlinePasswordField) {
|
||||
component.styleMap = component.styleMap.toMutableMap().apply {
|
||||
put("showRevealButton", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitorMode(): Boolean {
|
||||
return accountOwner.isVisitorMode()
|
||||
}
|
||||
|
||||
override fun createActions(): List<AbstractAction> {
|
||||
return listOf(createOkAction(), testConnectionAction, CancelAction())
|
||||
val actions = mutableListOf<AbstractAction>()
|
||||
if (visitorMode().not()) {
|
||||
actions.add(createOkAction())
|
||||
actions.add(testConnectionAction)
|
||||
}
|
||||
actions.add(CancelAction())
|
||||
return actions
|
||||
}
|
||||
|
||||
override fun createJButtonForAction(action: Action): JButton {
|
||||
@@ -238,5 +265,4 @@ class NewHostDialogV2(
|
||||
super.doOKAction()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,8 +40,8 @@ object AccountHttp {
|
||||
throw ResponseException(response.code, response)
|
||||
}
|
||||
|
||||
val text = response.use { response.body.use { it?.string() } }
|
||||
if (text.isNullOrBlank()) {
|
||||
val text = response.use { response.body.use { it.string() } }
|
||||
if (text.isBlank()) {
|
||||
throw ResponseException(response.code, "response body is empty", response)
|
||||
}
|
||||
|
||||
|
||||
@@ -54,24 +54,24 @@ class AccountManager private constructor() : ApplicationRunnerExtension {
|
||||
fun getOwnerIds() = account.teams.map { it.id }.toMutableList().apply { add(getAccountId()) }.toSet()
|
||||
fun getOwners(): Set<AccountOwner> {
|
||||
val owners = mutableSetOf<AccountOwner>()
|
||||
owners.add(AccountOwner(getAccountId(), getEmail(), OwnerType.User))
|
||||
owners.add(AccountOwner(getAccountId(), getEmail(), OwnerType.User, StringUtils.EMPTY))
|
||||
for (team in getTeams()) {
|
||||
owners.add(AccountOwner(team.id, team.name, OwnerType.Team))
|
||||
owners.add(AccountOwner(team.id, team.name, OwnerType.Team, team.role))
|
||||
}
|
||||
return owners
|
||||
}
|
||||
|
||||
fun isFreePlan(): Boolean {
|
||||
return isLocally() || getSubscription().plan == SubscriptionPlan.Free
|
||||
return isLocally() || getSubscription().plan == SubscriptionPlan.Free.name
|
||||
}
|
||||
|
||||
fun getSubscription(): Subscription {
|
||||
|
||||
if (isLocally().not()) {
|
||||
val subscriptions = getSubscriptions()
|
||||
val enterprises = getSubscriptions().filter { it.plan == SubscriptionPlan.Enterprise }
|
||||
val teams = subscriptions.filter { it.plan == SubscriptionPlan.Team }
|
||||
val pros = subscriptions.filter { it.plan == SubscriptionPlan.Pro }
|
||||
val enterprises = getSubscriptions().filter { it.plan == SubscriptionPlan.Enterprise.name }
|
||||
val teams = subscriptions.filter { it.plan == SubscriptionPlan.Team.name }
|
||||
val pros = subscriptions.filter { it.plan == SubscriptionPlan.Pro.name }
|
||||
val now = System.currentTimeMillis()
|
||||
|
||||
if (enterprises.any { it.endAt > now }) {
|
||||
@@ -83,16 +83,9 @@ class AccountManager private constructor() : ApplicationRunnerExtension {
|
||||
}
|
||||
}
|
||||
|
||||
return Subscription(id = "0", plan = SubscriptionPlan.Free, startAt = 0, endAt = 0)
|
||||
return Subscription(id = "0", plan = SubscriptionPlan.Free.name, startAt = 0, endAt = 0)
|
||||
}
|
||||
|
||||
fun hasTeamFeature(): Boolean {
|
||||
if (accountProperties.signed.not()) return false
|
||||
val plan = getSubscription().plan
|
||||
return SubscriptionPlan.Team == plan || SubscriptionPlan.Enterprise == plan
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新 Token
|
||||
*/
|
||||
|
||||
@@ -123,7 +123,7 @@ class AccountOption : JPanel(BorderLayout()), OptionsPane.Option, Disposable {
|
||||
}
|
||||
|
||||
val planBox = Box.createHorizontalBox()
|
||||
planBox.add(JLabel(if (isLocally) "-" else subscription.plan.name))
|
||||
planBox.add(JLabel(if (isLocally) "-" else subscription.plan))
|
||||
if (isFreePlan && isLocally.not()) {
|
||||
planBox.add(Box.createHorizontalStrut(16))
|
||||
val upgrade = JXHyperlink(object : AnAction(I18n.getString("termora.settings.account.upgrade")) {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
package app.termora.account
|
||||
|
||||
import app.termora.database.OwnerType
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
data class AccountOwner(val id: String, val name: String, val type: OwnerType)
|
||||
data class AccountOwner(val id: String, val name: String, val type: OwnerType, val role: String) {
|
||||
constructor(id: String, name: String, type: OwnerType) : this(id, name, type, StringUtils.EMPTY)
|
||||
|
||||
fun isVisitorMode(): Boolean {
|
||||
return type == OwnerType.Team && role == TeamRole.Visitor.name
|
||||
}
|
||||
}
|
||||
@@ -159,5 +159,5 @@ class ServerManager private constructor() {
|
||||
|
||||
|
||||
@Serializable
|
||||
data class MeTeam(val id: String, val name: String, val role: TeamRole, val secretKey: String)
|
||||
data class MeTeam(val id: String, val name: String, val role: String, val secretKey: String)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class Subscription(
|
||||
val id: String,
|
||||
val plan: SubscriptionPlan,
|
||||
val plan: String,
|
||||
val startAt: Long,
|
||||
val endAt: Long,
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ class Team(
|
||||
/**
|
||||
* 所属角色
|
||||
*/
|
||||
val role: TeamRole,
|
||||
val role: String,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -3,4 +3,5 @@ package app.termora.account
|
||||
enum class TeamRole {
|
||||
Member,
|
||||
Owner,
|
||||
Visitor,
|
||||
}
|
||||
@@ -409,7 +409,8 @@ class DatabaseManager private constructor() : Disposable {
|
||||
val accountOwner = AccountOwner(
|
||||
id = account.id,
|
||||
name = account.email,
|
||||
type = OwnerType.User
|
||||
type = OwnerType.User,
|
||||
role = StringUtils.EMPTY,
|
||||
)
|
||||
|
||||
for (host in hostManager.hosts()) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import app.termora.account.AccountManager
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.database.OwnerType
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import javax.swing.BorderFactory
|
||||
@@ -45,12 +46,13 @@ class KeywordHighlightDialog(owner: Window) : DialogWrapper(owner) {
|
||||
AccountOwner(
|
||||
accountManager.getAccountId(),
|
||||
accountManager.getEmail(),
|
||||
OwnerType.User
|
||||
OwnerType.User,
|
||||
StringUtils.EMPTY,
|
||||
)
|
||||
).apply { Disposer.register(disposable, this) }
|
||||
)
|
||||
|
||||
if (accountManager.hasTeamFeature()) {
|
||||
// if (accountManager.hasTeamFeature()) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
tabbed.addTab(
|
||||
team.name,
|
||||
@@ -59,11 +61,12 @@ class KeywordHighlightDialog(owner: Window) : DialogWrapper(owner) {
|
||||
AccountOwner(
|
||||
team.id,
|
||||
team.name,
|
||||
OwnerType.Team
|
||||
OwnerType.Team,
|
||||
team.role,
|
||||
)
|
||||
).apply { Disposer.register(disposable, this) })
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
|
||||
return tabbed
|
||||
|
||||
@@ -248,6 +248,9 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
||||
|
||||
table.addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (accountOwner.isVisitorMode()) {
|
||||
return
|
||||
}
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
val row = table.rowAtPoint(e.point)
|
||||
val column = table.columnAtPoint(e.point)
|
||||
@@ -299,7 +302,8 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
||||
|
||||
if (keywordHighlight.backgroundColor in 0..16) {
|
||||
if (keywordHighlight.backgroundColor == 0) {
|
||||
dialog.backgroundColor.background = Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND))
|
||||
dialog.backgroundColor.background =
|
||||
Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND))
|
||||
dialog.backgroundColor.colorIndex = -1
|
||||
} else {
|
||||
dialog.backgroundColor.color =
|
||||
@@ -402,7 +406,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
||||
val panel = JPanel(BorderLayout())
|
||||
panel.add(JScrollPane(table).apply {
|
||||
border = BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createEmptyBorder(8, 8, 8, 0),
|
||||
BorderFactory.createEmptyBorder(8, 8, 8, if (accountOwner.isVisitorMode()) 8 else 0),
|
||||
BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
||||
)
|
||||
}, BorderLayout.CENTER)
|
||||
@@ -414,6 +418,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
||||
"default:grow",
|
||||
"pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref"
|
||||
)
|
||||
if (accountOwner.isVisitorMode().not()) {
|
||||
panel.add(
|
||||
FormBuilder.create().layout(layout)
|
||||
.border(BorderFactory.createEmptyBorder(8, 8, 8, 8))
|
||||
@@ -424,7 +429,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
||||
.add(exportBtn).xy(1, rows).apply { rows += step }
|
||||
.build(),
|
||||
BorderLayout.EAST)
|
||||
|
||||
}
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import app.termora.account.AccountManager
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.database.OwnerType
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import javax.swing.BorderFactory
|
||||
@@ -65,13 +66,14 @@ class KeyManagerDialog(
|
||||
AccountOwner(
|
||||
accountManager.getAccountId(),
|
||||
accountManager.getEmail(),
|
||||
OwnerType.User
|
||||
OwnerType.User,
|
||||
StringUtils.EMPTY,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (accountOwner != null && accountManager.hasTeamFeature()) {
|
||||
if (accountOwner != null) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
if (team.id == accountOwner.id) {
|
||||
tabbed.addTab(
|
||||
@@ -81,7 +83,8 @@ class KeyManagerDialog(
|
||||
AccountOwner(
|
||||
team.id,
|
||||
team.name,
|
||||
OwnerType.Team
|
||||
OwnerType.Team,
|
||||
team.role,
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -91,8 +94,7 @@ class KeyManagerDialog(
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (accountManager.hasTeamFeature()) {
|
||||
// if (accountManager.hasTeamFeature()) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
tabbed.addTab(
|
||||
team.name,
|
||||
@@ -101,12 +103,13 @@ class KeyManagerDialog(
|
||||
AccountOwner(
|
||||
team.id,
|
||||
team.name,
|
||||
OwnerType.Team
|
||||
OwnerType.Team,
|
||||
team.role,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
|
||||
return tabbed
|
||||
|
||||
@@ -2,8 +2,10 @@ package app.termora.keymgr
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.account.TeamRole
|
||||
import app.termora.actions.AnAction
|
||||
import app.termora.actions.AnActionEvent
|
||||
import app.termora.database.OwnerType
|
||||
import app.termora.plugin.internal.ssh.SSHProtocolProvider
|
||||
import app.termora.tree.Filter
|
||||
import app.termora.tree.HostTreeNode
|
||||
@@ -56,6 +58,7 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
preventImportantData()
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +92,8 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
||||
add(JScrollPane(keyPairTable).apply {
|
||||
border = BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
||||
}, BorderLayout.CENTER)
|
||||
|
||||
if (accountOwner.type == OwnerType.User || (accountOwner.type == OwnerType.Team && accountOwner.role != TeamRole.Visitor.name)) {
|
||||
add(
|
||||
FormBuilder.create().layout(layout).padding(EmptyBorder(0, 12, 0, 0))
|
||||
.add(generateBtn).xy(1, rows).apply { rows += step }
|
||||
@@ -98,6 +103,8 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
||||
.add(deleteBtn).xy(1, rows).apply { rows += step }
|
||||
.add(sshCopyIdBtn).xy(1, rows).apply { rows += step }
|
||||
.build(), BorderLayout.EAST)
|
||||
}
|
||||
|
||||
border = BorderFactory.createEmptyBorder(12, 12, 12, 12)
|
||||
|
||||
}
|
||||
@@ -199,6 +206,17 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
||||
}
|
||||
}
|
||||
|
||||
private fun preventImportantData() {
|
||||
if (accountOwner.isVisitorMode()) {
|
||||
generateBtn.isVisible = false
|
||||
editBtn.isVisible = false
|
||||
deleteBtn.isVisible = false
|
||||
importBtn.isVisible = false
|
||||
exportBtn.isVisible = false
|
||||
sshCopyIdBtn.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun sshCopyId(evt: AnActionEvent) {
|
||||
val keyPairs = keyPairTable.selectedRows.map { keyPairTableModel.getOhKeyPair(it) }
|
||||
val publicKeys = mutableListOf<Pair<String, String>>()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.termora.plugin.internal.rdp
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.plugin.internal.BasicProxyOption
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.formdev.flatlaf.extras.components.FlatComboBox
|
||||
@@ -17,7 +18,7 @@ import java.awt.event.ComponentEvent
|
||||
import java.awt.event.ItemEvent
|
||||
import javax.swing.*
|
||||
|
||||
internal open class RDPHostOptionsPane : OptionsPane() {
|
||||
internal open class RDPHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||
protected val generalOption = GeneralOption()
|
||||
protected val proxyOption = BasicProxyOption()
|
||||
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
@@ -2,11 +2,12 @@ package app.termora.plugin.internal.rdp
|
||||
|
||||
import app.termora.Disposer
|
||||
import app.termora.Host
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.protocol.ProtocolHostPanel
|
||||
import java.awt.BorderLayout
|
||||
|
||||
class RDPProtocolHostPanel : ProtocolHostPanel() {
|
||||
private val pane = RDPHostOptionsPane()
|
||||
class RDPProtocolHostPanel(private val accountOwner: AccountOwner) : ProtocolHostPanel() {
|
||||
private val pane = RDPHostOptionsPane(accountOwner)
|
||||
|
||||
init {
|
||||
initView()
|
||||
|
||||
@@ -16,7 +16,7 @@ internal class RDPProtocolHostPanelExtension private constructor() : ProtocolHos
|
||||
}
|
||||
|
||||
override fun createProtocolHostPanel(accountOwner: AccountOwner): ProtocolHostPanel {
|
||||
return RDPProtocolHostPanel()
|
||||
return RDPProtocolHostPanel(accountOwner)
|
||||
}
|
||||
|
||||
override fun ordered(): Long {
|
||||
|
||||
@@ -46,12 +46,12 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
||||
AccountOwner(
|
||||
accountManager.getAccountId(),
|
||||
accountManager.getEmail(),
|
||||
OwnerType.User
|
||||
OwnerType.User,
|
||||
StringUtils.EMPTY,
|
||||
)
|
||||
).apply { Disposer.register(disposable, this) }
|
||||
)
|
||||
|
||||
if (accountManager.hasTeamFeature()) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
tabbed.addTab(
|
||||
team.name,
|
||||
@@ -60,7 +60,8 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
||||
AccountOwner(
|
||||
team.id,
|
||||
team.name,
|
||||
OwnerType.Team
|
||||
OwnerType.Team,
|
||||
team.role,
|
||||
)
|
||||
).apply { Disposer.register(disposable, this) })
|
||||
|
||||
@@ -68,7 +69,6 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
||||
tabbed.selectedIndex = tabbed.tabCount - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tabbed
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package app.termora.tag
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.account.TeamRole
|
||||
import app.termora.database.OwnerType
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
import com.jgoodies.forms.layout.FormLayout
|
||||
import java.awt.BorderLayout
|
||||
@@ -9,7 +11,7 @@ import java.awt.Component
|
||||
import javax.swing.*
|
||||
import javax.swing.border.EmptyBorder
|
||||
|
||||
class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable {
|
||||
class TagPanel(private val accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable {
|
||||
|
||||
private val owner get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
@@ -23,6 +25,7 @@ class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
preventImportantData()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
@@ -108,6 +111,14 @@ class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable
|
||||
|
||||
}
|
||||
|
||||
private fun preventImportantData() {
|
||||
if (accountOwner.isVisitorMode()) {
|
||||
addBtn.isVisible = false
|
||||
editBtn.isVisible = false
|
||||
deleteBtn.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCenterPanel(): JComponent {
|
||||
|
||||
val panel = JPanel(BorderLayout())
|
||||
|
||||
@@ -3,6 +3,8 @@ package app.termora.tree
|
||||
import app.termora.*
|
||||
import app.termora.Application.ohMyJson
|
||||
import app.termora.account.AccountManager
|
||||
import app.termora.account.Team
|
||||
import app.termora.account.TeamRole
|
||||
import app.termora.actions.AnAction
|
||||
import app.termora.actions.AnActionEvent
|
||||
import app.termora.actions.OpenHostAction
|
||||
@@ -455,6 +457,33 @@ class NewHostTree : SimpleTree(), Disposable {
|
||||
|
||||
})
|
||||
|
||||
popupMenu.addPopupMenuListener(object : PopupMenuListener {
|
||||
|
||||
override fun popupMenuWillBecomeVisible(e: PopupMenuEvent?) {
|
||||
for (node in nodes) {
|
||||
val team = TeamTreeNode.parentTeam(node) ?: continue
|
||||
if (team.role == TeamRole.Visitor.name) {
|
||||
copy.isEnabled = false
|
||||
remove.isEnabled = false
|
||||
rename.isEnabled = false
|
||||
importMenu.isEnabled = false
|
||||
newMenu.isEnabled = false
|
||||
tagsMenu.isEnabled = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun popupMenuWillBecomeInvisible(e: PopupMenuEvent?) {
|
||||
|
||||
}
|
||||
|
||||
override fun popupMenuCanceled(e: PopupMenuEvent?) {
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
val mnemonics = mapOf(
|
||||
refresh to KeyEvent.VK_R,
|
||||
newMenu to KeyEvent.VK_W,
|
||||
|
||||
@@ -61,11 +61,11 @@ class NewHostTreeModel private constructor() : SimpleTreeModel<Host>(
|
||||
|
||||
// 如果是根,需要引入团队功能
|
||||
if (parent == getRoot()) {
|
||||
if (accountManager.hasTeamFeature()) {
|
||||
// if (accountManager.hasTeamFeature()) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
nodes[team.id] = TeamTreeNode(team)
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
nodes[accountManager.getAccountId()] = HostTreeNode(
|
||||
Host(
|
||||
@@ -93,11 +93,11 @@ class NewHostTreeModel private constructor() : SimpleTreeModel<Host>(
|
||||
}
|
||||
|
||||
if (parent == getRoot()) {
|
||||
if (accountManager.hasTeamFeature()) {
|
||||
// if (accountManager.hasTeamFeature()) {
|
||||
for (team in accountManager.getTeams()) {
|
||||
parent.add(nodes.getValue(team.id))
|
||||
}
|
||||
}
|
||||
// }
|
||||
parent.add(nodes.getValue(accountManager.getAccountId()))
|
||||
} else {
|
||||
for (node in nodes.values) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.termora.tree
|
||||
|
||||
import app.termora.OutlineTextField
|
||||
import app.termora.account.TeamRole
|
||||
import com.formdev.flatlaf.ui.FlatTreeUI
|
||||
import org.jdesktop.swingx.JXTree
|
||||
import java.awt.Dimension
|
||||
@@ -134,6 +135,13 @@ open class SimpleTree : JXTree() {
|
||||
}
|
||||
}
|
||||
|
||||
for (node in nodes) {
|
||||
val team = TeamTreeNode.parentTeam(node) ?: continue
|
||||
if (team.role == TeamRole.Visitor.name) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return MoveNodeTransferable(nodes)
|
||||
}
|
||||
|
||||
@@ -153,9 +161,14 @@ open class SimpleTree : JXTree() {
|
||||
if (nodes.isEmpty()) return false
|
||||
if (!node.isFolder) return false
|
||||
|
||||
val team = TeamTreeNode.parentTeam(node)
|
||||
if (team?.role == TeamRole.Visitor.name) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (e in nodes) {
|
||||
// 禁止拖拽到自己的子下面
|
||||
if (path.equals(TreePath(e.path)) || TreePath(e.path).isDescendant(path)) {
|
||||
if (path == TreePath(e.path) || TreePath(e.path).isDescendant(path)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -333,7 +346,7 @@ open class SimpleTree : JXTree() {
|
||||
|
||||
private inner class MyTreeUI : FlatTreeUI() {
|
||||
|
||||
override fun createNodeDimensions(): AbstractLayoutCache.NodeDimensions? {
|
||||
override fun createNodeDimensions(): AbstractLayoutCache.NodeDimensions {
|
||||
return object : NodeDimensionsHandler() {
|
||||
override fun getNodeDimensions(
|
||||
value: Any?, row: Int, depth: Int, expanded: Boolean,
|
||||
|
||||
@@ -26,4 +26,16 @@ class TeamTreeNode(val team: Team) : HostTreeNode(
|
||||
override fun toString(): String {
|
||||
return team.name
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun parentTeam(node: SimpleTreeNode<*>?): Team? {
|
||||
if (node is TeamTreeNode) {
|
||||
return node.team
|
||||
} else if (node == null) {
|
||||
return null
|
||||
}
|
||||
return parentTeam(node.parent)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user