Răsfoiți Sursa

chore: coderabbit suggestions

jamesread 4 săptămâni în urmă
părinte
comite
e1f8c01fe5

+ 9 - 2
frontend/resources/vue/views/DiagnosticsView.vue

@@ -108,7 +108,7 @@
 </template>
 
 <script setup>
-import { ref, computed, onMounted } from 'vue'
+import { ref, computed, onMounted, onUnmounted } from 'vue'
 import Section from 'picocrank/vue/components/Section.vue'
 import Table from 'picocrank/vue/components/Table.vue'
 import { useI18n } from 'vue-i18n'
@@ -130,7 +130,7 @@ const configIssueHeaders = computed(() => [
   { key: 'actionTitle', label: t('diagnostics.config-issue-action'), sortable: true, width: '10rem' },
   { key: 'argumentName', label: t('diagnostics.config-issue-argument'), sortable: true, width: '8rem' },
   { key: 'configFile', label: t('diagnostics.config-issue-config-file'), sortable: true, width: '14rem' },
-  { key: 'source', label: t('diagnostics.config-issue-detail'), sortable: false, width: '12rem' }
+  { key: 'source', label: t('diagnostics.config-issue-source'), sortable: false, width: '12rem' }
 ])
 
 const configIssueRows = computed(() => configIssues.value.map((issue) => ({
@@ -311,5 +311,12 @@ async function copyBrowserInfo () {
 
 onMounted(() => {
   fetchDiagnostics()
+  window.addEventListener('EventConfigChanged', fetchDiagnostics)
+  window.addEventListener('EventEntityChanged', fetchDiagnostics)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('EventConfigChanged', fetchDiagnostics)
+  window.removeEventListener('EventEntityChanged', fetchDiagnostics)
 })
 </script>

+ 52 - 52
lang/combined_output.json

@@ -5,17 +5,17 @@
             "connected": "Verbunden",
             "diagnostics.browser-info": "Browser-Informationen",
             "diagnostics.browser-info-description": "Dieser Abschnitt ermöglicht es Ihnen, einen detaillierten Bericht über Ihre Browser-Informationen zu erstellen. Dies kann bei der Fehlerbehebung von browser-spezifischen Problemen hilfreich sein.",
-            "diagnostics.config-issue-action": "Action",
+            "diagnostics.config-issue-action": "Aktion",
             "diagnostics.config-issue-argument": "Argument",
             "diagnostics.config-issue-code": "Code",
-            "diagnostics.config-issue-config-file": "Config file",
+            "diagnostics.config-issue-config-file": "Konfigurationsdatei",
             "diagnostics.config-issue-detail": "Detail",
-            "diagnostics.config-issue-message": "Message",
-            "diagnostics.config-issue-severity": "Severity",
-            "diagnostics.config-issue-source": "Source",
-            "diagnostics.config-issues": "Configuration issues",
-            "diagnostics.config-issues-description": "Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.",
-            "diagnostics.config-issues-none": "No configuration issues detected.",
+            "diagnostics.config-issue-message": "Meldung",
+            "diagnostics.config-issue-severity": "Schweregrad",
+            "diagnostics.config-issue-source": "Quelle",
+            "diagnostics.config-issues": "Konfigurationsprobleme",
+            "diagnostics.config-issues-description": "In der aktuellen OliveTin-Konfiguration erkannte Probleme. Beheben Sie diese in Ihren Konfigurationsdateien und laden Sie OliveTin neu.",
+            "diagnostics.config-issues-none": "Keine Konfigurationsprobleme erkannt.",
             "diagnostics.copied": "Kopiert!",
             "diagnostics.copy-to-clipboard": "In Zwischenablage kopieren",
             "diagnostics.found-config": "Konfiguration gefunden",
@@ -185,17 +185,17 @@
             "connected": "Conectado",
             "diagnostics.browser-info": "Información del navegador",
             "diagnostics.browser-info-description": "Esta sección le permite generar un informe detallado de su información del navegador. Esto puede ser útil al solucionar problemas específicos del navegador.",
-            "diagnostics.config-issue-action": "Action",
-            "diagnostics.config-issue-argument": "Argument",
-            "diagnostics.config-issue-code": "Code",
-            "diagnostics.config-issue-config-file": "Config file",
-            "diagnostics.config-issue-detail": "Detail",
-            "diagnostics.config-issue-message": "Message",
-            "diagnostics.config-issue-severity": "Severity",
-            "diagnostics.config-issue-source": "Source",
-            "diagnostics.config-issues": "Configuration issues",
-            "diagnostics.config-issues-description": "Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.",
-            "diagnostics.config-issues-none": "No configuration issues detected.",
+            "diagnostics.config-issue-action": "Acción",
+            "diagnostics.config-issue-argument": "Argumento",
+            "diagnostics.config-issue-code": "Código",
+            "diagnostics.config-issue-config-file": "Archivo de configuración",
+            "diagnostics.config-issue-detail": "Detalle",
+            "diagnostics.config-issue-message": "Mensaje",
+            "diagnostics.config-issue-severity": "Severidad",
+            "diagnostics.config-issue-source": "Origen",
+            "diagnostics.config-issues": "Problemas de configuración",
+            "diagnostics.config-issues-description": "Problemas detectados en la configuración actual de OliveTin. Corríjalos en sus archivos de configuración y vuelva a cargar OliveTin.",
+            "diagnostics.config-issues-none": "No se detectaron problemas de configuración.",
             "diagnostics.copied": "¡Copiado!",
             "diagnostics.copy-to-clipboard": "Copiar al portapapeles",
             "diagnostics.found-config": "Configuración encontrada",
@@ -275,17 +275,17 @@
             "connected": "Connesso",
             "diagnostics.browser-info": "Informazioni del browser",
             "diagnostics.browser-info-description": "Questa sezione ti consente di generare un rapporto dettagliato delle informazioni del tuo browser. Questo può essere utile durante la risoluzione dei problemi specifici del browser.",
-            "diagnostics.config-issue-action": "Action",
-            "diagnostics.config-issue-argument": "Argument",
-            "diagnostics.config-issue-code": "Code",
-            "diagnostics.config-issue-config-file": "Config file",
-            "diagnostics.config-issue-detail": "Detail",
-            "diagnostics.config-issue-message": "Message",
-            "diagnostics.config-issue-severity": "Severity",
-            "diagnostics.config-issue-source": "Source",
-            "diagnostics.config-issues": "Configuration issues",
-            "diagnostics.config-issues-description": "Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.",
-            "diagnostics.config-issues-none": "No configuration issues detected.",
+            "diagnostics.config-issue-action": "Azione",
+            "diagnostics.config-issue-argument": "Argomento",
+            "diagnostics.config-issue-code": "Codice",
+            "diagnostics.config-issue-config-file": "File di configurazione",
+            "diagnostics.config-issue-detail": "Dettaglio",
+            "diagnostics.config-issue-message": "Messaggio",
+            "diagnostics.config-issue-severity": "Gravità",
+            "diagnostics.config-issue-source": "Origine",
+            "diagnostics.config-issues": "Problemi di configurazione",
+            "diagnostics.config-issues-description": "Problemi rilevati nella configurazione corrente di OliveTin. Correggili nei file di configurazione e ricarica OliveTin.",
+            "diagnostics.config-issues-none": "Nessun problema di configurazione rilevato.",
             "diagnostics.copied": "Copiato!",
             "diagnostics.copy-to-clipboard": "Copia negli appunti",
             "diagnostics.found-config": "Configurazione trovata",
@@ -365,17 +365,17 @@
             "connected": "已连接",
             "diagnostics.browser-info": "浏览器信息",
             "diagnostics.browser-info-description": "此部分允许您生成浏览器信息的详细报告。这在排查浏览器特定问题时很有帮助。",
-            "diagnostics.config-issue-action": "Action",
-            "diagnostics.config-issue-argument": "Argument",
-            "diagnostics.config-issue-code": "Code",
-            "diagnostics.config-issue-config-file": "Config file",
-            "diagnostics.config-issue-detail": "Detail",
-            "diagnostics.config-issue-message": "Message",
-            "diagnostics.config-issue-severity": "Severity",
-            "diagnostics.config-issue-source": "Source",
-            "diagnostics.config-issues": "Configuration issues",
-            "diagnostics.config-issues-description": "Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.",
-            "diagnostics.config-issues-none": "No configuration issues detected.",
+            "diagnostics.config-issue-action": "操作",
+            "diagnostics.config-issue-argument": "参数",
+            "diagnostics.config-issue-code": "代码",
+            "diagnostics.config-issue-config-file": "配置文件",
+            "diagnostics.config-issue-detail": "详情",
+            "diagnostics.config-issue-message": "消息",
+            "diagnostics.config-issue-severity": "严重程度",
+            "diagnostics.config-issue-source": "来源",
+            "diagnostics.config-issues": "配置问题",
+            "diagnostics.config-issues-description": "当前 OliveTin 配置中检测到的问题。请在配置文件中修复这些问题并重新加载 OliveTin。",
+            "diagnostics.config-issues-none": "未检测到配置问题。",
             "diagnostics.copied": "已复制!",
             "diagnostics.copy-to-clipboard": "复制到剪贴板",
             "diagnostics.found-config": "找到配置",
@@ -455,17 +455,17 @@
             "connected": "已連線",
             "diagnostics.browser-info": "瀏覽器資訊",
             "diagnostics.browser-info-description": "此區塊可讓您產生瀏覽器資訊的詳細報告。這在排解特定瀏覽器問題時相當有幫助。",
-            "diagnostics.config-issue-action": "Action",
-            "diagnostics.config-issue-argument": "Argument",
-            "diagnostics.config-issue-code": "Code",
-            "diagnostics.config-issue-config-file": "Config file",
-            "diagnostics.config-issue-detail": "Detail",
-            "diagnostics.config-issue-message": "Message",
-            "diagnostics.config-issue-severity": "Severity",
-            "diagnostics.config-issue-source": "Source",
-            "diagnostics.config-issues": "Configuration issues",
-            "diagnostics.config-issues-description": "Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.",
-            "diagnostics.config-issues-none": "No configuration issues detected.",
+            "diagnostics.config-issue-action": "動作",
+            "diagnostics.config-issue-argument": "參數",
+            "diagnostics.config-issue-code": "代碼",
+            "diagnostics.config-issue-config-file": "設定檔",
+            "diagnostics.config-issue-detail": "詳細資料",
+            "diagnostics.config-issue-message": "訊息",
+            "diagnostics.config-issue-severity": "嚴重程度",
+            "diagnostics.config-issue-source": "來源",
+            "diagnostics.config-issues": "設定問題",
+            "diagnostics.config-issues-description": "目前 OliveTin 設定中偵測到的問題。請在設定檔中修正這些問題並重新載入 OliveTin。",
+            "diagnostics.config-issues-none": "未偵測到設定問題。",
             "diagnostics.copied": "已複製!",
             "diagnostics.copy-to-clipboard": "複製到剪貼簿",
             "diagnostics.found-config": "找到設定檔 (Config)",

+ 8 - 8
lang/de-DE.yaml

@@ -54,17 +54,17 @@ translations:
   diagnostics.get-support: Unterstützung erhalten Unterstützung erhalten
   diagnostics.get-support-description: Wenn Sie Probleme mit OliveTin haben und eine Support-Anfrage stellen möchten, wäre es sehr hilfreich, Server-Diagnostik von dieser Seite einzufügen.
   diagnostics.where-to-find-help: Wo Sie Hilfe finden
-  diagnostics.config-issues: Configuration issues
-  diagnostics.config-issues-description: Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.
-  diagnostics.config-issues-none: No configuration issues detected.
-  diagnostics.config-issue-severity: Severity
+  diagnostics.config-issues: Konfigurationsprobleme
+  diagnostics.config-issues-description: In der aktuellen OliveTin-Konfiguration erkannte Probleme. Beheben Sie diese in Ihren Konfigurationsdateien und laden Sie OliveTin neu.
+  diagnostics.config-issues-none: Keine Konfigurationsprobleme erkannt.
+  diagnostics.config-issue-severity: Schweregrad
   diagnostics.config-issue-code: Code
-  diagnostics.config-issue-message: Message
-  diagnostics.config-issue-action: Action
+  diagnostics.config-issue-message: Meldung
+  diagnostics.config-issue-action: Aktion
   diagnostics.config-issue-argument: Argument
-  diagnostics.config-issue-config-file: Config file
+  diagnostics.config-issue-config-file: Konfigurationsdatei
   diagnostics.config-issue-detail: Detail
-  diagnostics.config-issue-source: Source
+  diagnostics.config-issue-source: Quelle
   diagnostics.ssh: SSH
   diagnostics.found-key: Schlüssel gefunden
   diagnostics.found-config: Konfiguration gefunden

+ 11 - 11
lang/es-ES.yaml

@@ -54,17 +54,17 @@ translations:
   diagnostics.get-support: Obtener soporte Obtener soporte
   diagnostics.get-support-description: Si tiene problemas con OliveTin y desea presentar una solicitud de soporte, sería muy útil incluir diagnósticos del servidor desde esta página.
   diagnostics.where-to-find-help: Dónde encontrar ayuda
-  diagnostics.config-issues: Configuration issues
-  diagnostics.config-issues-description: Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.
-  diagnostics.config-issues-none: No configuration issues detected.
-  diagnostics.config-issue-severity: Severity
-  diagnostics.config-issue-code: Code
-  diagnostics.config-issue-message: Message
-  diagnostics.config-issue-action: Action
-  diagnostics.config-issue-argument: Argument
-  diagnostics.config-issue-config-file: Config file
-  diagnostics.config-issue-detail: Detail
-  diagnostics.config-issue-source: Source
+  diagnostics.config-issues: Problemas de configuración
+  diagnostics.config-issues-description: Problemas detectados en la configuración actual de OliveTin. Corríjalos en sus archivos de configuración y vuelva a cargar OliveTin.
+  diagnostics.config-issues-none: No se detectaron problemas de configuración.
+  diagnostics.config-issue-severity: Severidad
+  diagnostics.config-issue-code: Código
+  diagnostics.config-issue-message: Mensaje
+  diagnostics.config-issue-action: Acción
+  diagnostics.config-issue-argument: Argumento
+  diagnostics.config-issue-config-file: Archivo de configuración
+  diagnostics.config-issue-detail: Detalle
+  diagnostics.config-issue-source: Origen
   diagnostics.ssh: SSH
   diagnostics.found-key: Clave encontrada
   diagnostics.found-config: Configuración encontrada

+ 11 - 11
lang/it-IT.yaml

@@ -54,17 +54,17 @@ translations:
   diagnostics.get-support: Ottenere supporto Ottenere supporto
   diagnostics.get-support-description: Se hai problemi con OliveTin e vuoi presentare una richiesta di supporto, sarebbe molto utile includere la diagnostica del server da questa pagina.
   diagnostics.where-to-find-help: Dove trovare aiuto
-  diagnostics.config-issues: Configuration issues
-  diagnostics.config-issues-description: Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.
-  diagnostics.config-issues-none: No configuration issues detected.
-  diagnostics.config-issue-severity: Severity
-  diagnostics.config-issue-code: Code
-  diagnostics.config-issue-message: Message
-  diagnostics.config-issue-action: Action
-  diagnostics.config-issue-argument: Argument
-  diagnostics.config-issue-config-file: Config file
-  diagnostics.config-issue-detail: Detail
-  diagnostics.config-issue-source: Source
+  diagnostics.config-issues: Problemi di configurazione
+  diagnostics.config-issues-description: Problemi rilevati nella configurazione corrente di OliveTin. Correggili nei file di configurazione e ricarica OliveTin.
+  diagnostics.config-issues-none: Nessun problema di configurazione rilevato.
+  diagnostics.config-issue-severity: Gravità
+  diagnostics.config-issue-code: Codice
+  diagnostics.config-issue-message: Messaggio
+  diagnostics.config-issue-action: Azione
+  diagnostics.config-issue-argument: Argomento
+  diagnostics.config-issue-config-file: File di configurazione
+  diagnostics.config-issue-detail: Dettaglio
+  diagnostics.config-issue-source: Origine
   diagnostics.ssh: SSH
   diagnostics.found-key: Chiave trovata
   diagnostics.found-config: Configurazione trovata

+ 11 - 11
lang/zh-Hans-CN.yaml

@@ -63,17 +63,17 @@ translations:
   diagnostics.get-support: 获取支持 获取支持
   diagnostics.get-support-description: 如果您在使用 OliveTin 时遇到问题并希望提交支持请求,从本页面包含服务器诊断将非常有帮助。
   diagnostics.where-to-find-help: 在哪里找到帮助
-  diagnostics.config-issues: Configuration issues
-  diagnostics.config-issues-description: Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.
-  diagnostics.config-issues-none: No configuration issues detected.
-  diagnostics.config-issue-severity: Severity
-  diagnostics.config-issue-code: Code
-  diagnostics.config-issue-message: Message
-  diagnostics.config-issue-action: Action
-  diagnostics.config-issue-argument: Argument
-  diagnostics.config-issue-config-file: Config file
-  diagnostics.config-issue-detail: Detail
-  diagnostics.config-issue-source: Source
+  diagnostics.config-issues: 配置问题
+  diagnostics.config-issues-description: 当前 OliveTin 配置中检测到的问题。请在配置文件中修复这些问题并重新加载 OliveTin。
+  diagnostics.config-issues-none: 未检测到配置问题。
+  diagnostics.config-issue-severity: 严重程度
+  diagnostics.config-issue-code: 代码
+  diagnostics.config-issue-message: 消息
+  diagnostics.config-issue-action: 操作
+  diagnostics.config-issue-argument: 参数
+  diagnostics.config-issue-config-file: 配置文件
+  diagnostics.config-issue-detail: 详情
+  diagnostics.config-issue-source: 来源
   diagnostics.ssh: SSH
   diagnostics.found-key: 找到密钥
   diagnostics.found-config: 找到配置

+ 11 - 11
lang/zh-Hant-TW.yaml

@@ -54,17 +54,17 @@ translations:
   diagnostics.get-support: 尋求技術支援
   diagnostics.get-support-description: 如果您在使用 OliveTin 時遇到問題並希望提出支援請求,提供此頁面的「伺服器診斷資訊」將會有很大的幫助。
   diagnostics.where-to-find-help: 哪裡可以尋求協助
-  diagnostics.config-issues: Configuration issues
-  diagnostics.config-issues-description: Problems detected in the current OliveTin configuration. Fix these in your config files and reload OliveTin.
-  diagnostics.config-issues-none: No configuration issues detected.
-  diagnostics.config-issue-severity: Severity
-  diagnostics.config-issue-code: Code
-  diagnostics.config-issue-message: Message
-  diagnostics.config-issue-action: Action
-  diagnostics.config-issue-argument: Argument
-  diagnostics.config-issue-config-file: Config file
-  diagnostics.config-issue-detail: Detail
-  diagnostics.config-issue-source: Source
+  diagnostics.config-issues: 設定問題
+  diagnostics.config-issues-description: 目前 OliveTin 設定中偵測到的問題。請在設定檔中修正這些問題並重新載入 OliveTin。
+  diagnostics.config-issues-none: 未偵測到設定問題。
+  diagnostics.config-issue-severity: 嚴重程度
+  diagnostics.config-issue-code: 代碼
+  diagnostics.config-issue-message: 訊息
+  diagnostics.config-issue-action: 動作
+  diagnostics.config-issue-argument: 參數
+  diagnostics.config-issue-config-file: 設定檔
+  diagnostics.config-issue-detail: 詳細資料
+  diagnostics.config-issue-source: 來源
   diagnostics.ssh: SSH
   diagnostics.found-key: 找到金鑰 (Key)
   diagnostics.found-config: 找到設定檔 (Config)

+ 8 - 8
service/internal/api/api_config_issues_test.go

@@ -31,8 +31,8 @@ func TestGetDiagnosticsReturnsConfigIssues(t *testing.T) {
 		},
 	}
 
-	ts, client := getNewTestServerAndClient(cfg)
-	defer ts.Close()
+	testServer, client := getNewTestServerAndClient(cfg)
+	defer testServer.Close()
 
 	res, err := client.GetDiagnostics(context.Background(), connect.NewRequest(&apiv1.GetDiagnosticsRequest{}))
 	require.NoError(t, err)
@@ -69,8 +69,8 @@ func TestInitHidesConfigIssueCountWithoutDiagnostics(t *testing.T) {
 		},
 	}
 
-	ts, client := getNewTestServerAndClient(cfg)
-	defer ts.Close()
+	testServer, client := getNewTestServerAndClient(cfg)
+	defer testServer.Close()
 
 	initRes, err := client.Init(context.Background(), connect.NewRequest(&apiv1.InitRequest{}))
 	require.NoError(t, err)
@@ -119,8 +119,8 @@ func TestConfigIssuesHideActionsWithoutViewPermission(t *testing.T) {
 	cfg.AuthHttpHeaderUsername = "X-Ot-User"
 	attachBrokenTemplateArgToSecretAction(cfg)
 
-	ts, client := getNewTestServerAndClient(cfg)
-	defer ts.Close()
+	testServer, client := getNewTestServerAndClient(cfg)
+	defer testServer.Close()
 
 	configissues.Report(configissues.Issue{
 		Severity: configissues.SeverityWarning,
@@ -157,8 +157,8 @@ func TestConfigIssuesHideRuntimeWatcherFailuresWithoutViewPermission(t *testing.
 	cfg, _, _ := buildViewPermissionTestConfig(t)
 	cfg.AuthHttpHeaderUsername = "X-Ot-User"
 
-	ts, client := getNewTestServerAndClient(cfg)
-	defer ts.Close()
+	testServer, client := getNewTestServerAndClient(cfg)
+	defer testServer.Close()
 
 	configissues.Report(configissues.Issue{
 		Severity:    configissues.SeverityError,

+ 15 - 3
service/internal/config/source_file.go

@@ -1,6 +1,9 @@
 package config
 
-import "github.com/knadh/koanf/v2"
+import (
+	"github.com/knadh/koanf/v2"
+	log "github.com/sirupsen/logrus"
+)
 
 const sourceFileKey = "x-olivetin-source-file"
 
@@ -34,6 +37,15 @@ func stampSourceOnMap(item any, sourceFile string) {
 }
 
 func stampLoadedConfigSources(k *koanf.Koanf, configPath string) {
-	_ = k.Set("actions", stampSourceOnMaps(k.Get("actions"), configPath))
-	_ = k.Set("entities", stampSourceOnMaps(k.Get("entities"), configPath))
+	stampConfigKey(k, "actions", configPath)
+	stampConfigKey(k, "entities", configPath)
+}
+
+func stampConfigKey(k *koanf.Koanf, key, configPath string) {
+	if err := k.Set(key, stampSourceOnMaps(k.Get(key), configPath)); err != nil {
+		log.WithFields(log.Fields{
+			"key":        key,
+			"configPath": configPath,
+		}).Errorf("Failed to persist source stamps: %v", err)
+	}
 }

+ 22 - 5
service/internal/configcheck/rebuild.go

@@ -114,7 +114,7 @@ func checklistNoChoicesIssue(action *config.Action, arg *config.ActionArgument)
 }
 
 func checklistEntityChoicesIssue(action *config.Action, arg *config.ActionArgument) []configissues.Issue {
-	if arg.Entity == "" || len(arg.Choices) == 1 {
+	if arg.Entity == "" || len(arg.Choices) <= 1 {
 		return nil
 	}
 
@@ -127,7 +127,10 @@ func collectIncludeIssues(cfg *config.Config) []configissues.Issue {
 		return nil
 	}
 
-	includePath := filepath.Join(cfg.GetDir(), cfg.Include)
+	includePath := cfg.Include
+	if !filepath.IsAbs(includePath) {
+		includePath = filepath.Join(cfg.GetDir(), cfg.Include)
+	}
 	info, err := os.Stat(includePath)
 	if err != nil {
 		return []configissues.Issue{{
@@ -410,19 +413,33 @@ func watcherPathIssuesForAction(action *config.Action) []configissues.Issue {
 		return nil
 	}
 
+	out := make([]configissues.Issue, 0)
+	out = append(out, watcherCreatedDirIssues(action)...)
+	out = append(out, watcherChangedDirIssues(action)...)
+	out = append(out, watcherCalendarFileIssues(action)...)
+	return out
+}
+
+func watcherCreatedDirIssues(action *config.Action) []configissues.Issue {
 	out := make([]configissues.Issue, 0)
 	for _, dir := range action.ExecOnFileCreatedInDir {
 		out = append(out, watcherDirIssue(action, dir)...)
 	}
+	return out
+}
+
+func watcherChangedDirIssues(action *config.Action) []configissues.Issue {
+	out := make([]configissues.Issue, 0)
 	for _, dir := range action.ExecOnFileChangedInDir {
 		out = append(out, watcherDirIssue(action, dir)...)
 	}
-	if action.ExecOnCalendarFile != "" {
-		out = append(out, watcherFileIssue(action, action.ExecOnCalendarFile)...)
-	}
 	return out
 }
 
+func watcherCalendarFileIssues(action *config.Action) []configissues.Issue {
+	return watcherFileIssue(action, action.ExecOnCalendarFile)
+}
+
 func watcherPathIssuesForEntities(cfg *config.Config) []configissues.Issue {
 	out := make([]configissues.Issue, 0)
 	baseDir := entities.ResolveEntitiesBaseDir(cfg.GetDir())

+ 2 - 2
service/internal/configissues/store.go

@@ -97,9 +97,9 @@ func Report(issue Issue) {
 	storeMu.Lock()
 	defer storeMu.Unlock()
 
-	fp := issueFingerprint(issue)
+	issueFingerprintValue := issueFingerprint(issue)
 	for _, existing := range issues {
-		if issueFingerprint(existing) == fp {
+		if issueFingerprint(existing) == issueFingerprintValue {
 			return
 		}
 	}

+ 18 - 3
service/internal/entities/entities.go

@@ -69,7 +69,9 @@ func watchAndLoadEntity(baseDir string, ef *config.EntityFile) {
 		p = filepath.Join(baseDir, p)
 		log.WithFields(log.Fields{"entityFile": p}).Debugf("Adding config dir to entity file path")
 	}
-	go filehelper.WatchFileWrite(p, func(filename string) { loadEntityFile(p, ef.Name) }, filehelper.WatchMeta{})
+	go filehelper.WatchFileWrite(p, func(filename string) { loadEntityFile(p, ef.Name) }, filehelper.WatchMeta{
+		ConfigFile: ef.SourceFile,
+	})
 	loadEntityFile(p, ef.Name)
 }
 
@@ -155,10 +157,23 @@ func loadEntityFileYaml(filename string, entityname string) {
 }
 
 func replaceEntitiesFromFile(entityname string, data []map[string]any) {
-	ClearEntitiesOfType(entityname)
+	rwmutex.Lock()
+	defer rwmutex.Unlock()
 
+	delete(entities, entityname)
+
+	if len(data) == 0 {
+		return
+	}
+
+	entities[entityname] = make(entityInstancesByKey, 0)
 	for i, mapp := range data {
-		AddEntity(entityname, fmt.Sprintf("%d", i), mapp)
+		entityKey := fmt.Sprintf("%d", i)
+		entities[entityname][entityKey] = &Entity{
+			Data:      mapp,
+			UniqueKey: entityKey,
+			Title:     findEntityTitle(mapp),
+		}
 	}
 }