mirror of
https://github.com/OliveTin/OliveTin
synced 2026-08-26 12:36:30 +00:00
250 lines
7.2 KiB
Go
250 lines
7.2 KiB
Go
package executor
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
config "github.com/OliveTin/OliveTin/internal/config"
|
|
"github.com/OliveTin/OliveTin/internal/entities"
|
|
)
|
|
|
|
type DashboardNavigationTarget struct {
|
|
Title string
|
|
EntityType string
|
|
EntityKey string
|
|
Path string
|
|
}
|
|
|
|
func (target DashboardNavigationTarget) key() string {
|
|
return target.Title + "\x00" + target.EntityType + "\x00" + target.EntityKey
|
|
}
|
|
|
|
func (b *ActionBinding) IsOnConfiguredDashboard() bool {
|
|
for _, dashboard := range b.OnDashboards {
|
|
if dashboard.Title != "Actions" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type dashboardTargetIndex struct {
|
|
byTitle map[string][]DashboardNavigationTarget
|
|
byTitleEntityKey map[string]map[string][]DashboardNavigationTarget
|
|
}
|
|
|
|
func buildDashboardTargetIndex(cfg *config.Config) *dashboardTargetIndex {
|
|
index := &dashboardTargetIndex{
|
|
byTitle: make(map[string][]DashboardNavigationTarget),
|
|
byTitleEntityKey: make(map[string]map[string][]DashboardNavigationTarget),
|
|
}
|
|
|
|
for _, dashboard := range cfg.Dashboards {
|
|
walkDashboardContents(dashboard.Contents, dashboard.Title, index)
|
|
}
|
|
|
|
return index
|
|
}
|
|
|
|
func walkDashboardContents(contents []*config.DashboardComponent, rootDashboardTitle string, index *dashboardTargetIndex) {
|
|
for _, component := range contents {
|
|
walkDashboardComponent(component, rootDashboardTitle, index)
|
|
}
|
|
}
|
|
|
|
func walkDashboardComponent(component *config.DashboardComponent, rootDashboardTitle string, index *dashboardTargetIndex) {
|
|
if component.Type == "fieldset" && component.Entity != "" {
|
|
walkEntityFieldset(component, rootDashboardTitle, component.Entity, index)
|
|
return
|
|
}
|
|
|
|
recordActionTarget(component, rootDashboardTitle, "", "", index)
|
|
|
|
if len(component.Contents) > 0 {
|
|
walkDashboardContents(component.Contents, rootDashboardTitle, index)
|
|
}
|
|
}
|
|
|
|
func walkEntityFieldset(fieldset *config.DashboardComponent, rootDashboardTitle, entityType string, index *dashboardTargetIndex) {
|
|
for _, component := range fieldset.Contents {
|
|
if component.Type == "directory" {
|
|
walkEntityDirectory(component, entityType, index)
|
|
continue
|
|
}
|
|
|
|
recordActionTargetForAllEntities(component, rootDashboardTitle, entityType, index)
|
|
|
|
if len(component.Contents) > 0 {
|
|
walkEntityFieldsetContents(component.Contents, rootDashboardTitle, entityType, index)
|
|
}
|
|
}
|
|
}
|
|
|
|
func walkEntityFieldsetContents(contents []*config.DashboardComponent, rootDashboardTitle, entityType string, index *dashboardTargetIndex) {
|
|
for _, component := range contents {
|
|
if component.Type == "directory" {
|
|
walkEntityDirectory(component, entityType, index)
|
|
continue
|
|
}
|
|
|
|
recordActionTargetForAllEntities(component, rootDashboardTitle, entityType, index)
|
|
|
|
if len(component.Contents) > 0 {
|
|
walkEntityFieldsetContents(component.Contents, rootDashboardTitle, entityType, index)
|
|
}
|
|
}
|
|
}
|
|
|
|
func walkEntityDirectory(directory *config.DashboardComponent, entityType string, index *dashboardTargetIndex) {
|
|
for _, entity := range entities.GetEntityInstancesOrdered(entityType) {
|
|
for _, component := range directory.Contents {
|
|
recordActionTarget(component, directory.Title, entityType, entity.UniqueKey, index)
|
|
}
|
|
}
|
|
}
|
|
|
|
func recordActionTargetForAllEntities(component *config.DashboardComponent, rootDashboardTitle, entityType string, index *dashboardTargetIndex) {
|
|
actionTitle := actionTitleFromComponent(component)
|
|
if actionTitle == "" {
|
|
return
|
|
}
|
|
|
|
target := dashboardNavigationTarget(rootDashboardTitle, "", "")
|
|
for _, entity := range entities.GetEntityInstancesOrdered(entityType) {
|
|
addEntityTarget(index, actionTitle, entity.UniqueKey, target)
|
|
}
|
|
}
|
|
|
|
func recordActionTarget(component *config.DashboardComponent, dashboardTitle, entityType, entityKey string, index *dashboardTargetIndex) {
|
|
actionTitle := actionTitleFromComponent(component)
|
|
if actionTitle == "" {
|
|
return
|
|
}
|
|
|
|
target := dashboardNavigationTarget(dashboardTitle, entityType, entityKey)
|
|
if entityType != "" && entityKey != "" {
|
|
addEntityTarget(index, actionTitle, entityKey, target)
|
|
return
|
|
}
|
|
|
|
addTitleTarget(index, actionTitle, target)
|
|
}
|
|
|
|
func actionTitleFromComponent(component *config.DashboardComponent) string {
|
|
if title := inlineActionTitle(component); title != "" {
|
|
return title
|
|
}
|
|
|
|
if component.Type == "link" || component.Type == "" {
|
|
return component.Title
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func inlineActionTitle(component *config.DashboardComponent) string {
|
|
if component.InlineAction == nil {
|
|
return ""
|
|
}
|
|
|
|
if component.Title != "" {
|
|
return component.Title
|
|
}
|
|
|
|
return component.InlineAction.Title
|
|
}
|
|
|
|
func dashboardNavigationTarget(title, entityType, entityKey string) DashboardNavigationTarget {
|
|
return DashboardNavigationTarget{
|
|
Title: title,
|
|
EntityType: entityType,
|
|
EntityKey: entityKey,
|
|
Path: dashboardNavigationPath(title, entityType, entityKey),
|
|
}
|
|
}
|
|
|
|
func dashboardNavigationPath(title, entityType, entityKey string) string {
|
|
if title == "Actions" {
|
|
return "/"
|
|
}
|
|
|
|
if entityType != "" && entityKey != "" {
|
|
return fmt.Sprintf("/dashboards/%s/%s/%s", title, entityType, entityKey)
|
|
}
|
|
|
|
return fmt.Sprintf("/dashboards/%s", title)
|
|
}
|
|
|
|
func addTitleTarget(index *dashboardTargetIndex, actionTitle string, target DashboardNavigationTarget) {
|
|
index.byTitle[actionTitle] = appendUniqueTarget(index.byTitle[actionTitle], target)
|
|
}
|
|
|
|
func addEntityTarget(index *dashboardTargetIndex, actionTitle, entityKey string, target DashboardNavigationTarget) {
|
|
if index.byTitleEntityKey[actionTitle] == nil {
|
|
index.byTitleEntityKey[actionTitle] = make(map[string][]DashboardNavigationTarget)
|
|
}
|
|
|
|
entityTargets := index.byTitleEntityKey[actionTitle][entityKey]
|
|
index.byTitleEntityKey[actionTitle][entityKey] = appendUniqueTarget(entityTargets, target)
|
|
}
|
|
|
|
func appendUniqueTarget(targets []DashboardNavigationTarget, target DashboardNavigationTarget) []DashboardNavigationTarget {
|
|
for _, existing := range targets {
|
|
if existing.key() == target.key() {
|
|
return targets
|
|
}
|
|
}
|
|
|
|
return append(targets, target)
|
|
}
|
|
|
|
func (index *dashboardTargetIndex) targetsForAction(actionTitle string) []DashboardNavigationTarget {
|
|
return dedupeTargets(index.byTitle[actionTitle])
|
|
}
|
|
|
|
func (index *dashboardTargetIndex) targetsForEntityAction(actionTitle, entityKey string) []DashboardNavigationTarget {
|
|
targets := make([]DashboardNavigationTarget, 0)
|
|
targets = append(targets, index.byTitle[actionTitle]...)
|
|
|
|
if entityTargets, ok := index.byTitleEntityKey[actionTitle]; ok {
|
|
targets = append(targets, entityTargets[entityKey]...)
|
|
}
|
|
|
|
return dedupeTargets(targets)
|
|
}
|
|
|
|
func dedupeTargets(targets []DashboardNavigationTarget) []DashboardNavigationTarget {
|
|
if len(targets) == 0 {
|
|
return nil
|
|
}
|
|
|
|
seen := make(map[string]bool, len(targets))
|
|
result := make([]DashboardNavigationTarget, 0, len(targets))
|
|
|
|
for _, target := range targets {
|
|
key := target.key()
|
|
if seen[key] {
|
|
continue
|
|
}
|
|
|
|
seen[key] = true
|
|
result = append(result, target)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func resolveOnDashboards(index *dashboardTargetIndex, actionTitle, entityKey string) []DashboardNavigationTarget {
|
|
var targets []DashboardNavigationTarget
|
|
if entityKey == "" {
|
|
targets = index.targetsForAction(actionTitle)
|
|
} else {
|
|
targets = index.targetsForEntityAction(actionTitle, entityKey)
|
|
}
|
|
|
|
if len(targets) == 0 {
|
|
return []DashboardNavigationTarget{dashboardNavigationTarget("Actions", "", "")}
|
|
}
|
|
|
|
return targets
|
|
}
|