Spaces:
Running
Running
File size: 32,155 Bytes
e4a761a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | using System;
using System.Collections.Generic;
using FlowAPI.Application.DTOs.Graph;
using FlowAPI.Domain.Entities;
using FlowAPI.Domain.Enums;
namespace FlowAPI.Application.Services
{
public static class TemplateLibrary
{
private class TemplateNodeDef
{
public string TempId { get; set; } = string.Empty;
public string Label { get; set; } = string.Empty;
public double PosX { get; set; }
public double PosY { get; set; }
public string Type { get; set; } = "sketch";
public string Color { get; set; } = "white";
public string Description { get; set; } = string.Empty;
public string DecisionJson { get; set; } = string.Empty;
public double? Width { get; set; }
public double? Height { get; set; }
}
private class TemplateEdgeDef
{
public string FromTempId { get; set; } = string.Empty;
public string ToTempId { get; set; } = string.Empty;
public string Condition { get; set; } = "True";
}
private class TemplateDef
{
public string Key { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string Icon { get; set; } = string.Empty;
public string Category { get; set; } = string.Empty;
public List<TemplateNodeDef> Nodes { get; set; } = new();
public List<TemplateEdgeDef> Edges { get; set; } = new();
}
private static readonly Dictionary<string, TemplateDef> Templates = new()
{
{
"startup",
new TemplateDef
{
Key = "startup",
Title = "Запуск Стартапу",
Description = "Шлях від формулювання ціннісної пропозиції та CustDev до запуску MVP та перших 100 користувачів.",
Icon = "Rocket",
Category = "Business",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "vprop", Label = "Формулювання ціннісної пропозиції", PosX = 250, PosY = 50, Color = "purple", Description = "Чітко опишіть, яку проблему вирішує ваш продукт і для кого." },
new() { TempId = "custdev", Label = "CustDev: Інтерв'ю з клієнтами", PosX = 250, PosY = 170, Color = "blue", Description = "Проведіть принаймні 10 інтерв'ю з потенційними користувачами." },
new() { TempId = "fit", Label = "Чи підтверджено проблему?", PosX = 250, PosY = 290, Type = "condition", DecisionJson = "{\"options\":[{\"id\":\"opt-yes\",\"label\":\"Так (Є інтерес)\"},{\"id\":\"opt-no\",\"label\":\"Ні (Потрібен півот)\"}],\"selected\":[],\"multiSelect\":false}" },
new() { TempId = "mvp", Label = "Розробка MVP", PosX = 100, PosY = 420, Color = "green", Description = "Створіть мінімально життєздатний продукт з однією ключовою функцією." },
new() { TempId = "pivot", Label = "Півот ідеї", PosX = 400, PosY = 420, Color = "orange", Description = "Змініть напрямок або цільову аудиторію на основі фідбеку з інтерв'ю." },
new() { TempId = "landing", Label = "Лендинг та збір заявок", PosX = 100, PosY = 550, Color = "pink", Description = "Налаштуйте просту сторінку для збору контактів зацікавлених клієнтів." },
new() { TempId = "users", Label = "Залучення перших 100 користувачів", PosX = 100, PosY = 680, Color = "yellow", Description = "Використовуйте безкоштовні канали (соцмережі, профільні форуми, зв'язки)." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "vprop", ToTempId = "custdev" },
new() { FromTempId = "custdev", ToTempId = "fit" },
new() { FromTempId = "fit", ToTempId = "mvp", Condition = "True" },
new() { FromTempId = "fit", ToTempId = "pivot", Condition = "False" },
new() { FromTempId = "pivot", ToTempId = "vprop" },
new() { FromTempId = "mvp", ToTempId = "landing" },
new() { FromTempId = "landing", ToTempId = "users" }
}
}
},
{
"software",
new TemplateDef
{
Key = "software",
Title = "Розробка ПЗ (Web App)",
Description = "Стандартний життєвий цикл розробки веб-додатку: вимоги, дизайн, UI/UX, API, інтеграція та реліз.",
Icon = "Code",
Category = "Development",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "req", Label = "Збір та аналіз вимог", PosX = 250, PosY = 50, Color = "blue", Description = "Опишіть функціонал проекту та підготуйте ТЗ." },
new() { TempId = "arch", Label = "Архітектура та проектування БД", PosX = 250, PosY = 170, Color = "purple", Description = "Спроектуйте схему бази даних та виберіть стек технологій." },
new() { TempId = "uiux", Label = "UI/UX макети та дизайн", PosX = 100, PosY = 300, Color = "pink", Description = "Створіть клікабельний прототип у Figma." },
new() { TempId = "api", Label = "Розробка API та Бекенду", PosX = 400, PosY = 300, Color = "yellow", Description = "Реалізуйте серверу логіку, авторизацію та базу даних." },
new() { TempId = "integ", Label = "Інтеграція та тестування", PosX = 250, PosY = 440, Color = "green", Description = "З'єднайте фронтенд з бекендом та проведіть ручне тестування." },
new() { TempId = "staging", Label = "Деплой на Staging сервер", PosX = 250, PosY = 560, Color = "orange", Description = "Розгорніть тестову версію додатку для фінальної перевірки." },
new() { TempId = "prod", Label = "Реліз у Production та моніторинг", PosX = 250, PosY = 680, Color = "green", Description = "Запустіть додаток для реальних користувачів та підключіть аналітику." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "req", ToTempId = "arch" },
new() { FromTempId = "arch", ToTempId = "uiux" },
new() { FromTempId = "arch", ToTempId = "api" },
new() { FromTempId = "uiux", ToTempId = "integ" },
new() { FromTempId = "api", ToTempId = "integ" },
new() { FromTempId = "integ", ToTempId = "staging" },
new() { FromTempId = "staging", ToTempId = "prod" }
}
}
},
{
"language",
new TemplateDef
{
Key = "language",
Title = "Вивчення Іноземної Мови",
Description = "Методика освоєння мови через щоденні звички, проходження базового курсу та вихід у практику.",
Icon = "Languages",
Category = "Education",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "goal", Label = "Визначення цілей та ресурсів", PosX = 250, PosY = 50, Color = "purple", Description = "Оберіть додатки, підручники та поставте чітку ціль (наприклад, рівень B1)." },
new() { TempId = "words", Label = "Вчити 15 нових слів щодня", PosX = 100, PosY = 170, Type = "habit", Color = "blue", Description = "Використовуйте картки Anki або Quizlet для регулярного повторення.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Використовуйте картки Anki або Quizlet для регулярного повторення.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "listen", Label = "Слухати подкаст / дивитись відео", PosX = 400, PosY = 170, Type = "habit", Color = "pink", Description = "Принаймні 20 хвилин фонового або активного слухання щодня.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Принаймні 20 хвилин фонового або активного слухання щодня.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "course", Label = "Завершити курс для початківців", PosX = 250, PosY = 300, Color = "yellow", Description = "Пройти базову граматику та отримати розуміння структури мови." },
new() { TempId = "speak", Label = "Розмовна сесія (1 раз на тиждень)", PosX = 100, PosY = 430, Type = "habit", Color = "green", Description = "Знайдіть партнера для спілкування на Tandem або викладача.", DecisionJson = "{\"resetRule\":{\"type\":\"weekly\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Знайдіть партнера для спілкування на Tandem або викладача.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "read", Label = "Прочитати першу коротку розповідь", PosX = 400, PosY = 430, Color = "orange", Description = "Оберіть адаптовану книгу під ваш поточний рівень." },
new() { TempId = "exam", Label = "Скласти тестовий іспит", PosX = 250, PosY = 560, Color = "green", Description = "Перевірте свій прогрес за допомогою офіційного пробного тесту." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "goal", ToTempId = "words" },
new() { FromTempId = "goal", ToTempId = "listen" },
new() { FromTempId = "words", ToTempId = "course" },
new() { FromTempId = "listen", ToTempId = "course" },
new() { FromTempId = "course", ToTempId = "speak" },
new() { FromTempId = "course", ToTempId = "read" },
new() { FromTempId = "speak", ToTempId = "exam" },
new() { FromTempId = "read", ToTempId = "exam" }
}
}
},
{
"fitness",
new TemplateDef
{
Key = "fitness",
Title = "Фітнес та Здорове Тіло",
Description = "Збалансований план тренувань, контролю харчування та циклічного аналізу результатів.",
Icon = "Activity",
Category = "Health",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "setup", Label = "Поставити ціль та розрахувати КБЖВ", PosX = 250, PosY = 50, Color = "blue", Description = "Визначте добову норму калорій залежно від мети (схуднення чи набір маси)." },
new() { TempId = "plan", Label = "Скласти план тренувань та раціон", PosX = 250, PosY = 170, Color = "purple", Description = "Виберіть 3 дні для занять та підготуйте перелік здорових страв." },
new() { TempId = "diet", Label = "Трекати щоденне харчування та воду", PosX = 100, PosY = 300, Type = "habit", Color = "green", Description = "Записуйте все з'їдене в MyFitnessPal та пийте достатньо води.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Записуйте все з'їдене в MyFitnessPal та пийте достатньо води.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "workout", Label = "Силове або кардіо тренування", PosX = 400, PosY = 300, Type = "habit", Color = "orange", Description = "Виконуйте заплановане тренування 3 рази на тиждень.", DecisionJson = "{\"resetRule\":{\"type\":\"weekly\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Виконуйте заплановане тренування 3 рази на тиждень.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "check", Label = "Контрольне зважування та заміри (4 тижні)", PosX = 250, PosY = 430, Color = "yellow", Description = "Порівняйте поточну вагу та об'єми тіла з початковими показниками." },
new() { TempId = "satisfied", Label = "Чи є прогрес задовільним?", PosX = 250, PosY = 550, Type = "condition", DecisionJson = "{\"options\":[{\"id\":\"opt-yes\",\"label\":\"Так (Продовжуємо)\"},{\"id\":\"opt-no\",\"label\":\"Ні (Потрібні коригування)\"}],\"selected\":[],\"multiSelect\":false}" },
new() { TempId = "advance", Label = "Ускладнити програму тренувань", PosX = 100, PosY = 680, Color = "pink", Description = "Додайте вагу на снарядах або збільшіть інтенсивність." },
new() { TempId = "adjust", Label = "Скоригувати КБЖВ та план їжі", PosX = 400, PosY = 680, Color = "yellow", Description = "Зменшіть або збільшіть калорійність раціону на 10%." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "setup", ToTempId = "plan" },
new() { FromTempId = "plan", ToTempId = "diet" },
new() { FromTempId = "plan", ToTempId = "workout" },
new() { FromTempId = "diet", ToTempId = "check" },
new() { FromTempId = "workout", ToTempId = "check" },
new() { FromTempId = "check", ToTempId = "satisfied" },
new() { FromTempId = "satisfied", ToTempId = "advance", Condition = "True" },
new() { FromTempId = "satisfied", ToTempId = "adjust", Condition = "False" },
new() { FromTempId = "adjust", ToTempId = "plan" }
}
}
},
{
"gamedev",
new TemplateDef
{
Key = "gamedev",
Title = "Створення Інді-Гри",
Description = "Повний цикл геймдеву від ідеї та прототипу до створення сторінки в Steam та релізу.",
Icon = "Gamepad",
Category = "Creative",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "concept", Label = "Концепт та написання GDD", PosX = 250, PosY = 50, Color = "pink", Description = "Сформулюйте основну ідею гри та опишіть її механіки в дизайн-документі." },
new() { TempId = "proto", Label = "Прототип базового геймплею", PosX = 250, PosY = 170, Color = "purple", Description = "Створіть «сіру коробку» на рушії, щоб перевірити, чи весело грати." },
new() { TempId = "art", Label = "Стилістика та створення артів", PosX = 100, PosY = 300, Color = "orange", Description = "Визначте художній стиль та підготуйте перші 2D/3D моделі." },
new() { TempId = "level", Label = "Дизайн рівнів та звуковий супровід", PosX = 400, PosY = 300, Color = "blue", Description = "Створіть тестовий рівень та додайте базові звукові ефекти." },
new() { TempId = "playable", Label = "Перша грабельна демо-версія", PosX = 250, PosY = 430, Color = "yellow", Description = "Зберіть стабільний білд для тестування друзями." },
new() { TempId = "test", Label = "Плейтести та виправлення багів", PosX = 100, PosY = 560, Type = "habit", Color = "pink", Description = "Щодня грайте, збирайте фідбек та виправляйте помилки.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Щодня грайте, збирайте фідбек та виправляйте помилки.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "steam", Label = "Створення сторінки в Steam", PosX = 400, PosY = 560, Color = "yellow", Description = "Підготуйте красиві скріншоти, трейлер та запустіть сторінку для збору Wishlists." },
new() { TempId = "release", Label = "Реліз гри в Steam", PosX = 250, PosY = 690, Color = "green", Description = "Опублікуйте фінальний білд та підтримайте запуск маркетинговою кампанією." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "concept", ToTempId = "proto" },
new() { FromTempId = "proto", ToTempId = "art" },
new() { FromTempId = "proto", ToTempId = "level" },
new() { FromTempId = "art", ToTempId = "playable" },
new() { FromTempId = "level", ToTempId = "playable" },
new() { FromTempId = "playable", ToTempId = "test" },
new() { FromTempId = "playable", ToTempId = "steam" },
new() { FromTempId = "test", ToTempId = "release" },
new() { FromTempId = "steam", ToTempId = "release" }
}
}
},
{
"finance",
new TemplateDef
{
Key = "finance",
Title = "Фінансова Свобода",
Description = "Покроковий план досягнення фінансової незалежності: облік витрат, подушка безпеки та інвестиції.",
Icon = "DollarSign",
Category = "Finance",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "audit", Label = "Аудит активів та боргових зобов'язань", PosX = 250, PosY = 50, Color = "yellow", Description = "Запишіть усі свої збереження, майно та кредити." },
new() { TempId = "track", Label = "Щоденний облік усіх витрат", PosX = 100, PosY = 170, Type = "habit", Color = "blue", Description = "Записуйте кожну покупку в мобільний додаток або Excel таблицю.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Записуйте кожну покупку в мобільний додаток або Excel таблицю.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "emergency", Label = "Сформувати подушку на 3 місяці", PosX = 300, PosY = 170, Color = "orange", Description = "Розрахуйте мінімальний бюджет життя та накопичте цю суму на депозиті." },
new() { TempId = "debt", Label = "Виплатити всі споживчі кредити", PosX = 250, PosY = 290, Color = "pink", Description = "Спрямуйте вільні кошти на швидке закриття боргів з найвищими відсотками." },
new() { TempId = "invest", Label = "Інвестувати 20% від доходу", PosX = 100, PosY = 420, Type = "habit", Color = "green", Description = "Регулярно купуйте надійні індекси (ETF) або облігації.", DecisionJson = "{\"resetRule\":{\"type\":\"monthly\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Регулярно купуйте надійні індекси (ETF) або облігації.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "passive", Label = "Створити джерело пасивного доходу", PosX = 400, PosY = 420, Color = "purple", Description = "Створіть власний блог, курс, невеликий онлайн-сервіс чи придбайте дивідендні акції." },
new() { TempId = "freedom", Label = "Досягти фінансової незалежності", PosX = 250, PosY = 550, Color = "green", Description = "Коли пасивний дохід повністю перекриє ваші щомісячні витрати." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "audit", ToTempId = "track" },
new() { FromTempId = "audit", ToTempId = "emergency" },
new() { FromTempId = "track", ToTempId = "debt" },
new() { FromTempId = "emergency", ToTempId = "debt" },
new() { FromTempId = "debt", ToTempId = "invest" },
new() { FromTempId = "debt", ToTempId = "passive" },
new() { FromTempId = "invest", ToTempId = "freedom" },
new() { FromTempId = "passive", ToTempId = "freedom" }
}
}
},
{
"writing",
new TemplateDef
{
Key = "writing",
Title = "Написання та Публікація Книги",
Description = "Шлях автора: від розробки сюжету та персонажів до щоденного написання, редактури та релізу.",
Icon = "BookOpen",
Category = "Creative",
Nodes = new List<TemplateNodeDef>
{
new() { TempId = "outline", Label = "Побудова сюжету та анкет персонажів", PosX = 250, PosY = 50, Color = "pink", Description = "Напишіть синопсис та детально розпишіть структуру розділів книги." },
new() { TempId = "words", Label = "Писати по 1000 слів щодня", PosX = 100, PosY = 170, Type = "habit", Color = "purple", Description = "Формуйте звичку писати без критики та внутрішнього редактора.", DecisionJson = "{\"resetRule\":{\"type\":\"daily\",\"time\":\"00:00\"},\"createdAt\":\"" + DateTime.UtcNow.ToString("o") + "\",\"description\":\"Формуйте звичку писати без критики та внутрішнього редактора.\",\"tags\":[],\"status\":\"Todo\",\"progress\":0}" },
new() { TempId = "draft", Label = "Завершити першу чернетку", PosX = 350, PosY = 170, Color = "yellow", Description = "Напишіть повну історію від початку до кінця (орієнтовно 50-80 тис. слів)." },
new() { TempId = "edit", Label = "Самостійна редактура та вичитка", PosX = 250, PosY = 300, Color = "orange", Description = "Виправте логічні помилки, покращіть діалоги та стиль оповідання." },
new() { TempId = "beta", Label = "Отримати фідбек від бета-рідерів", PosX = 250, PosY = 420, Color = "blue", Description = "Дайте почитати книгу кільком людям із вашої цільової аудиторії." },
new() { TempId = "professional", Label = "Професійна коректура та верстка", PosX = 250, PosY = 540, Color = "pink", Description = "Знайдіть професійного редактора для виправлення граматики та підготовки макету." },
new() { TempId = "cover", Label = "Створення обкладинки та форматування", PosX = 100, PosY = 660, Color = "purple", Description = "Замовте обкладинку в дизайнера та підготуйте формати ePub, PDF." },
new() { TempId = "publish", Label = "Публікація та запуск маркетингу", PosX = 350, PosY = 660, Color = "green", Description = "Опублікуйте книгу на Amazon / Litres та запустіть промо-акції." }
},
Edges = new List<TemplateEdgeDef>
{
new() { FromTempId = "outline", ToTempId = "words" },
new() { FromTempId = "words", ToTempId = "draft" },
new() { FromTempId = "draft", ToTempId = "edit" },
new() { FromTempId = "edit", ToTempId = "beta" },
new() { FromTempId = "beta", ToTempId = "professional" },
new() { FromTempId = "professional", ToTempId = "cover" },
new() { FromTempId = "professional", ToTempId = "publish" }
}
}
}
};
public static IEnumerable<TemplateInfoDto> GetTemplateInfos()
{
var list = new List<TemplateInfoDto>();
foreach (var kv in Templates)
{
list.Add(new TemplateInfoDto
{
Key = kv.Value.Key,
Title = kv.Value.Title,
Description = kv.Value.Description,
Icon = kv.Value.Icon,
Category = kv.Value.Category
});
}
return list;
}
public static (List<TaskNode> Nodes, List<Edge> Edges) GetTemplateContent(string key, Guid graphId)
{
if (!Templates.TryGetValue(key.ToLower().Trim(), out var template))
{
return (new List<TaskNode>(), new List<Edge>());
}
var nodes = new List<TaskNode>();
var edges = new List<Edge>();
var idMapping = new Dictionary<string, Guid>();
// 1. Instantiate nodes and map their IDs
foreach (var nodeDef in template.Nodes)
{
var newId = Guid.NewGuid();
idMapping[nodeDef.TempId] = newId;
var taskNode = new TaskNode
{
Id = newId,
GraphId = graphId,
Label = nodeDef.Label,
PosX = nodeDef.PosX,
PosY = nodeDef.PosY,
Type = nodeDef.Type,
State = NodeState.Pending,
CreatedAt = DateTime.UtcNow,
Description = nodeDef.Description,
Color = nodeDef.Color,
IsPinned = false,
Decision = string.IsNullOrEmpty(nodeDef.DecisionJson) ? null : nodeDef.DecisionJson
};
// For normal sketch nodes without custom Decision JSON, populate standard default JSON
if (nodeDef.Type == "sketch" && string.IsNullOrEmpty(nodeDef.DecisionJson))
{
taskNode.Decision = $"{{\"description\":\"{nodeDef.Description}\",\"progress\":0,\"showProgress\":false,\"decision\":\"bottom\",\"assignees\":[],\"color\":\"{nodeDef.Color}\",\"isPinned\":false,\"tags\":[],\"status\":\"Todo\"}}";
}
nodes.Add(taskNode);
}
// 2. Instantiate edges
foreach (var edgeDef in template.Edges)
{
if (idMapping.TryGetValue(edgeDef.FromTempId, out var fromId) &&
idMapping.TryGetValue(edgeDef.ToTempId, out var toId))
{
var edge = new Edge
{
Id = Guid.NewGuid(),
GraphId = graphId,
FromNodeId = fromId,
ToNodeId = toId,
Condition = edgeDef.Condition
};
edges.Add(edge);
}
}
return (nodes, edges);
}
}
}
|