diff --git a/Services/ServiceTrackerDataStore.cs b/Services/ServiceTrackerDataStore.cs
index 0fb2a95..bb7a992 100644
--- a/Services/ServiceTrackerDataStore.cs
+++ b/Services/ServiceTrackerDataStore.cs
@@ -7,15 +7,12 @@ using System.Linq;
namespace Disco.Plugins.ServiceTracker.Services
{
- ///
- /// JSON file-based data store for ServiceTracker metadata.
- /// Stores ticket extensions and configuration in the plugin data directory.
- ///
public class ServiceTrackerDataStore
{
private readonly string _dataDirectory;
private readonly string _ticketsPath;
private readonly string _configPath;
+ private readonly string _externalPath;
private static readonly object _lock = new object();
public ServiceTrackerDataStore(string pluginDataDirectory)
@@ -23,11 +20,12 @@ namespace Disco.Plugins.ServiceTracker.Services
_dataDirectory = pluginDataDirectory;
_ticketsPath = Path.Combine(_dataDirectory, "tickets.json");
_configPath = Path.Combine(_dataDirectory, "config.json");
-
- if (!Directory.Exists(_dataDirectory))
- Directory.CreateDirectory(_dataDirectory);
+ _externalPath = Path.Combine(_dataDirectory, "external_tickets.json");
+ if (!Directory.Exists(_dataDirectory)) Directory.CreateDirectory(_dataDirectory);
}
+ public string DataDirectory { get { return _dataDirectory; } }
+
// --- Configuration ---
public ServiceTrackerConfig LoadConfig()
@@ -36,12 +34,19 @@ namespace Disco.Plugins.ServiceTracker.Services
{
if (!File.Exists(_configPath))
{
- var defaultConfig = ServiceTrackerConfig.CreateDefault();
- SaveConfig(defaultConfig);
- return defaultConfig;
+ var def = ServiceTrackerConfig.CreateDefault();
+ SaveConfig(def);
+ return def;
}
var json = File.ReadAllText(_configPath);
- return JsonConvert.DeserializeObject(json) ?? ServiceTrackerConfig.CreateDefault();
+ var config = JsonConvert.DeserializeObject(json);
+ if (config == null) return ServiceTrackerConfig.CreateDefault();
+ // Ensure new fields have defaults
+ if (config.Technicians == null) config.Technicians = new List();
+ if (config.GoogleSheet == null) config.GoogleSheet = new GoogleSheetConfig();
+ if (string.IsNullOrEmpty(config.DiscoBaseUrl)) config.DiscoBaseUrl = "http://disco:9292";
+ if (config.DetailInactivitySeconds <= 0) config.DetailInactivitySeconds = 300;
+ return config;
}
}
@@ -54,15 +59,13 @@ namespace Disco.Plugins.ServiceTracker.Services
}
}
- // --- Tickets ---
+ // --- Disco Tickets ---
public List LoadAllTickets()
{
lock (_lock)
{
- if (!File.Exists(_ticketsPath))
- return new List();
-
+ if (!File.Exists(_ticketsPath)) return new List();
var json = File.ReadAllText(_ticketsPath);
return JsonConvert.DeserializeObject>(json) ?? new List();
}
@@ -78,14 +81,9 @@ namespace Disco.Plugins.ServiceTracker.Services
lock (_lock)
{
var tickets = LoadAllTicketsUnsafe();
- var existing = tickets.FindIndex(t => t.JobId == ticket.JobId);
+ var idx = tickets.FindIndex(t => t.JobId == ticket.JobId);
ticket.LastModifiedDate = DateTime.Now;
-
- if (existing >= 0)
- tickets[existing] = ticket;
- else
- tickets.Add(ticket);
-
+ if (idx >= 0) tickets[idx] = ticket; else tickets.Add(ticket);
SaveAllTicketsUnsafe(tickets);
}
}
@@ -108,8 +106,7 @@ namespace Disco.Plugins.ServiceTracker.Services
var ticket = tickets.FirstOrDefault(t => t.JobId == jobId);
if (ticket != null)
{
- if (ticket.Notes == null)
- ticket.Notes = new List();
+ if (ticket.Notes == null) ticket.Notes = new List();
ticket.Notes.Add(note);
ticket.LastModifiedDate = DateTime.Now;
SaveAllTicketsUnsafe(tickets);
@@ -117,19 +114,79 @@ namespace Disco.Plugins.ServiceTracker.Services
}
}
- // Internal methods (caller must hold lock)
+ // --- External Tickets (Google Sheet) ---
+
+ public List LoadExternalTickets()
+ {
+ lock (_lock)
+ {
+ if (!File.Exists(_externalPath)) return new List();
+ var json = File.ReadAllText(_externalPath);
+ return JsonConvert.DeserializeObject>(json) ?? new List();
+ }
+ }
+
+ public void SaveExternalTickets(List tickets)
+ {
+ lock (_lock)
+ {
+ var json = JsonConvert.SerializeObject(tickets, Formatting.Indented);
+ File.WriteAllText(_externalPath, json);
+ }
+ }
+
+ public ServiceTicket GetExternalTicket(int internalId)
+ {
+ return LoadExternalTickets().FirstOrDefault(t => t.JobId == internalId);
+ }
+
+ public void SaveExternalTicket(ServiceTicket ticket)
+ {
+ lock (_lock)
+ {
+ var tickets = LoadExternalTicketsUnsafe();
+ var idx = tickets.FindIndex(t => t.JobId == ticket.JobId);
+ ticket.LastModifiedDate = DateTime.Now;
+ if (idx >= 0) tickets[idx] = ticket; else tickets.Add(ticket);
+ var json = JsonConvert.SerializeObject(tickets, Formatting.Indented);
+ File.WriteAllText(_externalPath, json);
+ }
+ }
+
+ public void AddExternalNote(int internalId, TicketNote note)
+ {
+ lock (_lock)
+ {
+ var tickets = LoadExternalTicketsUnsafe();
+ var ticket = tickets.FirstOrDefault(t => t.JobId == internalId);
+ if (ticket != null)
+ {
+ if (ticket.Notes == null) ticket.Notes = new List();
+ ticket.Notes.Add(note);
+ ticket.LastModifiedDate = DateTime.Now;
+ var json = JsonConvert.SerializeObject(tickets, Formatting.Indented);
+ File.WriteAllText(_externalPath, json);
+ }
+ }
+ }
+
+ // Internal (caller must hold lock)
private List LoadAllTicketsUnsafe()
{
- if (!File.Exists(_ticketsPath))
- return new List();
+ if (!File.Exists(_ticketsPath)) return new List();
var json = File.ReadAllText(_ticketsPath);
return JsonConvert.DeserializeObject>(json) ?? new List();
}
-
private void SaveAllTicketsUnsafe(List tickets)
{
var json = JsonConvert.SerializeObject(tickets, Formatting.Indented);
File.WriteAllText(_ticketsPath, json);
}
+ private List LoadExternalTicketsUnsafe()
+ {
+ if (!File.Exists(_externalPath)) return new List();
+ var json = File.ReadAllText(_externalPath);
+ return JsonConvert.DeserializeObject>(json) ?? new List();
+ }
}
}