From 6ea236c32e5da32393d8fa6b4c9a3886291e1422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20N=C3=B6rtersh=C3=A4user?= Date: Sun, 17 Jan 2021 19:43:02 +0100 Subject: [PATCH] Project switching, reference nodes, .Net 5.0 --- Config/MiscConfig.cs | 6 +- Constants.cs | 5 + Controllers/Api/AikaApiController.cs | 120 +- Controllers/Api/EvneApiController.cs | 40 +- Controllers/Api/ExportApiController.cs | 199 ++- Controllers/Api/FlexFieldBaseApiController.cs | 153 +- .../Api/ImplementationStatusApiController.cs | 12 +- Controllers/Api/KartaApiController.cs | 86 +- Controllers/Api/KirjaApiController.cs | 93 +- Controllers/Api/KortistoApiController.cs | 90 +- Controllers/Api/LockServiceApiController.cs | 77 +- Controllers/Api/PersonalDataApiController.cs | 8 + Controllers/Api/ProjectApiController.cs | 44 +- Controllers/Api/ProjectConfigApiController.cs | 19 +- Controllers/Api/StyrApiController.cs | 34 +- Controllers/Api/TaleApiController.cs | 47 +- Controllers/Api/TaskApiController.cs | 73 +- Controllers/Api/UserApiController.cs | 6 +- .../Api/UserPreferencesApiController.cs | 13 +- Controllers/ExportController.cs | 15 +- Controllers/HomeController.cs | 11 +- Data/Aika/AikaQuest.cs | 6 + Data/Aika/AikaQuestMongoDbAccess.cs | 8 +- Data/Evne/EvneSkill.cs | 8 +- Data/Evne/EvneSkillMongoDbAccess.cs | 18 +- Data/Evne/IEvneSkillDbAccess.cs | 8 + .../ExportDefaultTemplateProvider.cs | 15 +- Data/Exporting/ExportTemplateMongoDbAccess.cs | 5 +- Data/Exporting/IExportTemplateDbAccess.cs | 3 +- .../Exporting/IObjectExportSnippetDbAccess.cs | 7 + .../ObjectExportSnippetMongoDbAccess.cs | 19 + .../Exporting/ObjectExportSnippetReference.cs | 28 + Data/Exporting/TemplateType.cs | 6 + .../FlexFieldObjectBaseMongoDbAccess.cs | 15 +- Data/FlexFieldDatabase/FlexFieldObjectTag.cs | 6 + .../FlexFieldObjectTagBaseMongoDbAccess.cs | 24 +- .../IFlexFieldObjectDbAccess.cs | 9 +- .../IFlexFieldObjectTagDbAccess.cs | 16 +- Data/Karta/IKartaMapDbAccess.cs | 6 + Data/Karta/KartaMapMongoDbAccess.cs | 14 +- Data/Kortisto/KortistoNpcDailyRoutineTime.cs | 10 + Data/Kortisto/KortistoNpcMongoDbAccess.cs | 3 +- Data/LockService/ILockServiceDbAccess.cs | 13 + Data/LockService/LockServiceMongoDbAccess.cs | 20 + Data/MongoDbSetup.cs | 50 +- Data/NodeGraph/NodeGraphSnippet.cs | 9 +- Data/NodeGraph/NodeObjectDependency.cs | 49 +- Data/NodeGraph/ReferenceNode.cs | 44 + Data/Project/IProjectDbAccess.cs | 23 + Data/Project/ProjectMongoDbAccess.cs | 57 + Data/Project/UserSelectedProject.cs | 23 + Data/Tale/TaleDialog.cs | 6 + Data/Tale/TaleMongoDbAccess.cs | 9 +- DefaultExportTemplates/Tale/ReferenceNode.lua | 0 Dockerfile | 4 +- GoNorth.csproj | 14 +- GoNorthVersion.cs | 2 +- .../Controllers/Api/AikaApiController.de.json | 10 +- .../Controllers/Api/AikaApiController.en.json | 6 +- .../Controllers/Api/EvneApiController.de.json | 12 +- .../Controllers/Api/EvneApiController.en.json | 10 +- .../Api/ExportApiController.de.json | 2 + .../Api/ExportApiController.en.json | 2 + .../Api/KartaApiController.de.json | 14 +- .../Api/KartaApiController.en.json | 12 +- .../Api/KirjaApiController.de.json | 5 + .../Api/KirjaApiController.en.json | 5 + .../Api/KortistoApiController.de.json | 28 +- .../Api/KortistoApiController.en.json | 24 +- .../Controllers/Api/StyrApiController.de.json | 12 +- .../Controllers/Api/StyrApiController.en.json | 12 +- .../ExportReferenceRenderer.de.json | 3 + .../ExportReferenceRenderer.en.json | 3 + .../ScribanReferenceData.de.json | 11 + .../ScribanReferenceData.en.json | 11 + .../ScribanExportMapMarker.de.json | 7 + .../ScribanExportMapMarker.en.json | 7 + .../ScribanExportWikiPage.de.json | 4 + .../ScribanExportWikiPage.en.json | 4 + ...enericImplementationStatusComparer.de.json | 8 + ...enericImplementationStatusComparer.en.json | 8 + .../ReferenceAnalyzer.de.json | 4 + .../ReferenceAnalyzer.en.json | 4 + Resources/Views/Aika/Quest.de.json | 20 +- Resources/Views/Aika/Quest.en.json | 20 +- Resources/Views/Evne/Skill.de.json | 18 +- Resources/Views/Evne/Skill.en.json | 18 +- .../FunctionGenerationCondition.de.json | 1 + .../FunctionGenerationCondition.en.json | 1 + Resources/Views/Kirja/Index.de.json | 6 +- Resources/Views/Kirja/Index.en.json | 6 +- Resources/Views/Kortisto/Npc.de.json | 17 +- Resources/Views/Kortisto/Npc.en.json | 17 +- .../Views/Shared/ChooseObjectDialog.de.json | 9 + .../Views/Shared/ChooseObjectDialog.en.json | 9 + .../Views/Shared/NodeScriptEditor.de.json | 2 + .../Views/Shared/NodeScriptEditor.en.json | 2 + Resources/Views/Styr/Item.de.json | 17 +- Resources/Views/Styr/Item.en.json | 17 +- Resources/Views/Tale/Index.de.json | 1 + Resources/Views/Tale/Index.en.json | 1 + .../DailyRoutineFunctionRenderer.cs | 3 +- Services/Export/Data/ExportCachedDbAccess.cs | 65 +- Services/Export/Data/IExportCachedDbAccess.cs | 12 +- .../NpcValueChangeRenderer.cs | 2 +- .../ScribanNpcValueChangeRenderer.cs | 2 +- .../BaseChangeNpcStateActionRenderer.cs | 2 +- .../BaseMoveNpcActionRenderer.cs | 2 +- .../BasePlayAnimationActionRenderer.cs | 2 +- .../BaseUseItemActionRenderer.cs | 2 +- .../Export/Dialog/ConditionParsingUtil.cs | 27 + Services/Export/Dialog/ConditionRenderer.cs | 7 +- .../NpcValueConditionResolver.cs | 2 +- Services/Export/Dialog/ExportDialogData.cs | 17 +- Services/Export/Dialog/ExportDialogParser.cs | 2 + .../Export/Dialog/ExportDialogRenderer.cs | 7 +- .../ExportDialogActionRenderer.cs | 1 - .../StepRenderers/ExportReferenceRenderer.cs | 257 +++ .../IReferenceStepRenderer.cs | 33 + .../ReferenceRenderer/ReferenceNodeData.cs | 60 + .../ScribanReferenceStepRenderer.cs | 148 ++ .../RenderingObjects/ScribanReferenceData.cs | 65 + .../TextLine/ScribanTextLineRenderer.cs | 2 +- Services/Export/ExportConstants.cs | 17 +- .../ExportSnippetFunctionRenderer.cs | 3 +- .../ExportSnippetRelatedObjectNameResolver.cs | 127 ++ .../ExportSnippetRelatedObjectUpdater.cs | 8 +- ...IExportSnippetRelatedObjectNameResolver.cs | 22 + .../Export/LanguageExport/LanguageExporter.cs | 15 +- .../LanguageKeyGenerator.cs | 18 +- .../Export/NodeGraphExport/NodeGraphParser.cs | 2 + ...DialogExportTemplatePlaceholderResolver.cs | 4 +- ...xportSnippetTemplatePlaceholderResolver.cs | 2 +- ...xFieldExportTemplatePlaceholderResolver.cs | 2 +- .../LanguageKeyTemplatePlaceholderResolver.cs | 2 +- ...yRoutineEventContentPlaceholderResolver.cs | 2 +- ...acyDailyRoutineEventPlaceholderResolver.cs | 2 +- ...pcDailyRoutineExportPlaceholderResolver.cs | 4 +- .../NpcInventoryExportPlaceholderResolver.cs | 2 +- .../NpcSkillExportPlaceholderResolver.cs | 2 +- .../Include/ScribanIncludeTemplateLoader.cs | 2 +- .../ScribanLanguageKeyGenerator.cs | 7 +- .../DailyRoutineEventFunctionListRenderer.cs | 11 +- .../DailyRoutineEventFunctionRenderer.cs | 8 +- .../DailyRoutineEventListRenderer.cs | 8 +- .../DialogFunctionRenderer.cs | 8 +- .../ExportSnippetFunctionPipeRenderer.cs | 8 +- .../FlexFieldAttributeListRenderer.cs | 8 +- .../IndentMultiLineRenderer.cs | 6 +- .../InventoryListRenderer.cs | 8 +- .../ScribanBaseStringRenderingFunction.cs | 64 + .../RenderingFunctions/SkillListRenderer.cs | 8 +- .../ScribanExportMapMarker.cs | 54 + .../RenderingObjects/ScribanExportWikiPage.cs | 33 + .../Util/ScribanDailyRoutineEventUtil.cs | 2 +- .../Util/ScribanStatementExtractor.cs | 10 +- .../Util/ScriptObjectExtensions.cs | 28 + .../AttributeListValueCollector.cs | 6 +- .../BaseFlexFieldValueCollector.cs | 2 +- .../DailyRoutineEventListValueCollector.cs | 2 +- .../DailyRoutineFunctionListValueCollector.cs | 4 +- .../DailyRoutineFunctionValueCollector.cs | 2 +- .../DialogFunctionValueCollector.cs | 2 +- .../ValueCollector/DialogValueCollector.cs | 6 +- .../ExportSnippetFunctionValueCollector.cs | 2 +- .../ExportSnippetValueCollector.cs | 4 +- .../ValueCollector/InventoryValueCollector.cs | 6 +- .../LanguageKeyValueCollector.cs | 4 +- .../NpcDailyRoutineExportValueCollector.cs | 8 +- .../ValueCollector/NpcExportValueCollector.cs | 5 +- .../ValueCollector/NpcSkillValueCollector.cs | 6 +- .../Util/SharedDailyRoutineExportUtil.cs | 5 + .../Util/SharedDialogExportUtil.cs | 2 +- Services/Export/Script/ScriptExporter.cs | 13 +- .../ScribanIncludeTemplateRefParser.cs | 2 +- .../CompareDifferenceValue.cs | 25 + .../GenericImplementationStatusComparer.cs | 103 +- Services/Project/IUserProjectAccess.cs | 17 + Services/Project/UserProjectAccess.cs | 65 + .../ReferenceAnalyzer/IReferenceAnalyzer.cs | 25 + Services/ReferenceAnalyzer/ObjectReference.cs | 33 + .../ReferenceAnalyzer/ReferenceAnalyzer.cs | 153 ++ Services/Timeline/ITimelineService.cs | 3 +- Services/Timeline/TimelineService.cs | 39 +- Services/TimerJob/ITimerJob.cs | 28 + Services/TimerJob/ITimerJobManager.cs | 13 + .../JobDefinitions/ILockCleanupTimerJob.cs | 9 + .../JobDefinitions/LockCleanupTimerJob.cs | 53 + Services/TimerJob/TimerJobManager.cs | 132 ++ Services/TimerJob/TimerJobRunTimeConfig.cs | 31 + Services/User/UserDeleter.cs | 12 +- Startup.cs | 21 +- UITests/package-lock.json | 589 ++----- UITests/package.json | 6 +- Views/Aika/Quest.cshtml | 82 +- Views/Evne/Skill.cshtml | 5 + .../ObjectFormRelatedObjects.cshtml | 44 +- .../ObjectFormScriptRights.cshtml | 31 +- Views/Home/Index.cshtml | 285 ++-- Views/Karta/ManageMaps.cshtml | 4 +- Views/Kirja/Index.cshtml | 105 +- Views/Shared/ChooseObjectDialog.cshtml | 17 +- Views/Shared/NodeScriptEditor.cshtml | 6 + Views/Shared/_Layout.cshtml | 4 +- Views/Shared/_ValidationScriptsPartial.cshtml | 4 +- Views/Tale/Index.cshtml | 5 + appsettings.docker.json | 4 +- appsettings.json | 4 +- bower.json | 4 +- bundleconfig.json | 28 +- wwwroot/css/site.css | 122 +- .../configEncryption.ViewModel.js | 8 +- .../projectManagement.ViewModel.js | 16 +- .../userManagement.viewmodel.js | 38 +- wwwroot/js/Aika/aikaLang.de.js | 1 + wwwroot/js/Aika/aikaLang.en.js | 1 + wwwroot/js/Aika/chapterDetail.viewmodel.js | 257 ++- wwwroot/js/Aika/chapterDetail/questNode.js | 5 +- wwwroot/js/Aika/chapterDetail/viewmodel.js | 13 +- wwwroot/js/Aika/chapterOverview.viewmodel.js | 56 +- wwwroot/js/Aika/chapterOverview/viewmodel.js | 13 +- wwwroot/js/Aika/quest.viewmodel.js | 1164 ++++++++++---- .../actions/changeCurrentQuestValueAction.js | 6 +- .../changeQuestInNpcDialogBaseAction.js | 14 +- .../checkCurrentQuestValueCondition.js | 6 +- .../conditions/checkQuestMarkerCondition.js | 6 +- wwwroot/js/Aika/quest/questLang.de.js | 1 + wwwroot/js/Aika/quest/questLang.en.js | 1 + wwwroot/js/Aika/quest/viewmodel.js | 251 ++- wwwroot/js/Aika/questList.viewmodel.js | 2 +- wwwroot/js/Aika/questList/viewmodel.js | 2 +- .../js/Aika/shared/chapterDetailNodeHelper.js | 10 +- wwwroot/js/Evne/manageTemplates.viewmodel.js | 2 +- wwwroot/js/Evne/overview.viewmodel.js | 60 +- wwwroot/js/Evne/skill.viewmodel.js | 1215 ++++++++++---- .../actions/changeCurrentSkillValueAction.js | 6 +- .../conditions/checkSkillValueCondition.js | 6 +- wwwroot/js/Evne/skillForm/viewmodel.js | 5 +- .../functionGenerationCondition.viewmodel.js | 13 +- .../functionGenerationCondition/viewmodel.js | 13 +- .../Export/manageIncludeTemplate.viewmodel.js | 24 +- .../Export/manageIncludeTemplate/viewmodel.js | 24 +- wwwroot/js/Export/manageTemplate.viewmodel.js | 43 +- wwwroot/js/Export/manageTemplate/viewmodel.js | 43 +- .../js/Export/templateOverview.viewmodel.js | 28 +- .../js/Export/templateOverview/viewmodel.js | 28 +- .../exportForms/valueExportDialog.js | 5 +- .../exportForms/valueImportDialog.js | 27 +- .../flexFieldFolderTreeViewDialog.js | 2 +- .../flexFieldManageTemplates.BaseViewModel.js | 2 +- .../flexFieldOverview.BaseViewModel.js | 26 +- .../objectForm/baseViewmodel.js | 262 +-- .../objectForm/exportSnippetManager.js | 25 +- wwwroot/js/Home/home.viewmodel.js | 60 + .../compareDialog/viewmodel.js | 11 +- .../overview.viewmodel.js | 41 +- .../implementationStatusDialogList.js | 5 +- .../overview/implementationStatusItemList.js | 5 +- .../implementationStatusMarkerList.js | 5 +- .../overview/implementationStatusNpcList.js | 5 +- .../overview/implementationStatusQuestList.js | 5 +- .../overview/implementationStatusSkillList.js | 5 +- wwwroot/js/Karta/manageMaps.viewmodel.js | 16 +- wwwroot/js/Karta/map.viewmodel.js | 1063 +++++++++---- wwwroot/js/Karta/mapForm/aikaMarker.js | 4 +- wwwroot/js/Karta/mapForm/aikaMarkerManager.js | 10 +- wwwroot/js/Karta/mapForm/cachedLoading.js | 4 +- .../js/Karta/mapForm/dailyRoutineEditor.js | 18 +- wwwroot/js/Karta/mapForm/kartaMarker.js | 4 +- .../js/Karta/mapForm/kartaMarkerManager.js | 5 +- wwwroot/js/Karta/mapForm/kirjaMarker.js | 4 +- .../js/Karta/mapForm/kirjaMarkerManager.js | 5 +- .../js/Karta/mapForm/kortistoMarkerManager.js | 5 +- wwwroot/js/Karta/mapForm/styrMarker.js | 4 +- wwwroot/js/Karta/mapForm/styrMarkerManager.js | 5 +- wwwroot/js/Karta/mapForm/viewmodel.js | 39 +- wwwroot/js/Kirja/allPages.viewmodel.js | 5 +- wwwroot/js/Kirja/page.viewmodel.js | 484 ++++-- wwwroot/js/Kirja/page/viewmodel.js | 288 +++- .../js/Kortisto/manageTemplates.viewmodel.js | 2 +- wwwroot/js/Kortisto/npc.viewmodel.js | 1273 ++++++++++----- .../js/Kortisto/npcForm/dailyRoutinesForm.js | 4 +- wwwroot/js/Kortisto/npcForm/inventoryForm.js | 8 +- wwwroot/js/Kortisto/npcForm/skillForm.js | 8 +- wwwroot/js/Kortisto/npcForm/viewmodel.js | 5 +- wwwroot/js/Kortisto/overview.ViewModel.js | 60 +- wwwroot/js/Manage/preferences.viewmodel.js | 13 +- wwwroot/js/Manage/preferences/viewmodel.js | 13 +- wwwroot/js/ProjectConfig/config.viewmodel.js | 24 +- .../config/dayHourMinuteConfigSection.js | 12 +- .../config/textareaConfigSection.js | 10 +- wwwroot/js/ProjectConfig/config/viewmodel.js | 2 +- .../chooseObjectDialogViewModel.js | 196 ++- wwwroot/js/Shared/httpClient.js | 45 + wwwroot/js/Shared/lockService.js | 80 +- wwwroot/js/Shared/nodeGraph/actionNode.js | 4 +- .../nodeGraph/actions/addQuestTextAction.js | 5 +- .../js/Shared/nodeGraph/actions/baseAction.js | 3 + .../actions/changeInventoryAction.js | 8 +- .../actions/changeInventoryChooseNpcAction.js | 16 +- .../nodeGraph/actions/changeNpcValueAction.js | 5 +- .../actions/changePlayerValueAction.js | 5 +- .../actions/changeQuestValueAction.js | 6 +- .../actions/changeSkillValueAction.js | 5 +- .../actions/chooseNpcUseItemAction.js | 27 +- .../actions/learnForgetSkillAction.js | 6 +- .../actions/moveChooseObjectAction.js | 5 +- .../actions/moveChooseObjectToNpcAction.js | 5 +- .../nodeGraph/actions/moveObjectAction.js | 5 +- .../actions/moveObjectToNpcAction.js | 5 +- .../nodeGraph/actions/objectUseItemAction.js | 8 +- .../setDailyRoutineEventStateAction.js | 5 +- .../nodeGraph/actions/setGameTimeAction.js | 5 +- .../nodeGraph/actions/setQuestStateAction.js | 5 +- .../showFloatingTextAboveChooseNpcAction.js | 5 +- .../actions/spawnItemAtMarkerAction.js | 5 +- .../actions/spawnNpcAtMarkerAction.js | 5 +- .../nodeGraph/actions/spawnObjectAction.js | 5 +- .../actions/teleportChooseNpcAction.js | 5 +- .../actions/teleportChooseNpcToNpcAction.js | 5 +- .../actions/walkChooseNpcToMarkerAction.js | 5 +- .../actions/walkChooseNpcToNpcAction.js | 5 +- wwwroot/js/Shared/nodeGraph/baseViewModel.js | 33 + wwwroot/js/Shared/nodeGraph/bindingHandler.js | 13 +- .../checkChooseQuestValueCondition.js | 5 +- .../checkChooseSkillValueCondition.js | 5 +- .../checkDailyRoutineEventStateCondition.js | 5 +- .../conditions/checkGameTimeCondition.js | 5 +- .../conditions/checkInventoryCondition.js | 8 +- .../conditions/checkLearnedSkillCondition.js | 5 +- .../conditions/checkNpcAliveStateCondition.js | 5 +- .../conditions/checkNpcValueCondition.js | 5 +- .../conditions/checkPlayerValueCondition.js | 6 +- .../conditions/checkQuestStateCondition.js | 5 +- .../nodeGraph/nodeGraph.knockout.binding.js | 13 +- wwwroot/js/Shared/nodeGraph/nodeLang.de.js | 9 + wwwroot/js/Shared/nodeGraph/nodeLang.en.js | 9 + wwwroot/js/Shared/nodeGraph/referenceNode.js | 484 ++++++ .../Shared/nodeGraph/sharedObjectLoading.js | 3 + .../Shared/scriptDialog/codeScriptDialog.js | 2 +- .../Shared/scriptDialog/nodeScriptDialog.js | 5 + wwwroot/js/Shared/shared.lib.js | 149 +- wwwroot/js/Shared/util.js | 24 +- wwwroot/js/Styr/item.viewmodel.js | 1413 ++++++++++++----- .../actions/changeCurrentItemValueAction.js | 5 +- .../conditions/checkItemValueCondition.js | 5 +- wwwroot/js/Styr/itemForm/viewmodel.js | 5 +- wwwroot/js/Styr/manageTemplates.viewmodel.js | 2 +- wwwroot/js/Styr/overview.viewmodel.js | 60 +- wwwroot/js/Tale/dialog.viewmodel.js | 1001 +++++++++--- wwwroot/js/Tale/dialogForm/taleLang.de.js | 1 + wwwroot/js/Tale/dialogForm/taleLang.en.js | 1 + wwwroot/js/Tale/dialogForm/viewmodel.js | 45 +- wwwroot/js/Tale/taleLang.de.js | 1 + wwwroot/js/Tale/taleLang.en.js | 1 + wwwroot/js/Task/manageBoards.viewmodel.js | 49 +- .../manageBoards/taskBoardCategoryList.js | 24 +- wwwroot/js/Task/manageBoards/taskBoardList.js | 5 +- wwwroot/js/Task/manageBoards/viewmodel.js | 20 +- wwwroot/js/Task/manageTaskTypes.viewmodel.js | 24 +- .../js/Task/manageTaskTypes/taskTypeList.js | 24 +- wwwroot/js/Task/taskBoard.viewmodel.js | 277 ++-- wwwroot/js/Task/taskBoard/viewmodel.js | 81 +- wwwroot/js/Timeline/timeline.viewmodel.js | 2 +- wwwroot/lib/jquery-validation/.bower.json | 10 +- wwwroot/lib/jquery-validation/README.md | 21 + wwwroot/lib/jquery-validation/bower.json | 2 +- .../lib/jquery-validation/build/release.js | 1 + wwwroot/lib/jquery-validation/changelog.md | 6 + .../dist/additional-methods.js | 4 +- .../dist/additional-methods.min.js | 4 +- .../dist/jquery-validation-sri.json | 544 +++---- .../jquery-validation/dist/jquery.validate.js | 16 +- .../dist/jquery.validate.min.js | 6 +- .../dist/localization/messages_ar.min.js | 4 +- .../dist/localization/messages_az.min.js | 4 +- .../dist/localization/messages_bg.min.js | 4 +- .../dist/localization/messages_bn_BD.min.js | 4 +- .../dist/localization/messages_ca.min.js | 4 +- .../dist/localization/messages_cs.min.js | 4 +- .../dist/localization/messages_da.min.js | 4 +- .../dist/localization/messages_de.min.js | 4 +- .../dist/localization/messages_el.min.js | 4 +- .../dist/localization/messages_es.min.js | 4 +- .../dist/localization/messages_es_AR.min.js | 4 +- .../dist/localization/messages_es_PE.min.js | 4 +- .../dist/localization/messages_et.min.js | 4 +- .../dist/localization/messages_eu.min.js | 4 +- .../dist/localization/messages_fa.min.js | 4 +- .../dist/localization/messages_fi.min.js | 4 +- .../dist/localization/messages_fr.js | 3 +- .../dist/localization/messages_fr.min.js | 6 +- .../dist/localization/messages_ge.min.js | 4 +- .../dist/localization/messages_gl.min.js | 4 +- .../dist/localization/messages_he.min.js | 4 +- .../dist/localization/messages_hr.min.js | 4 +- .../dist/localization/messages_hu.min.js | 4 +- .../dist/localization/messages_hy_AM.min.js | 4 +- .../dist/localization/messages_id.min.js | 4 +- .../dist/localization/messages_is.min.js | 4 +- .../dist/localization/messages_it.min.js | 4 +- .../dist/localization/messages_ja.min.js | 4 +- .../dist/localization/messages_ka.min.js | 4 +- .../dist/localization/messages_kk.min.js | 4 +- .../dist/localization/messages_ko.min.js | 4 +- .../dist/localization/messages_lt.min.js | 4 +- .../dist/localization/messages_lv.min.js | 4 +- .../dist/localization/messages_mk.min.js | 4 +- .../dist/localization/messages_my.min.js | 4 +- .../dist/localization/messages_nl.min.js | 4 +- .../dist/localization/messages_no.min.js | 4 +- .../dist/localization/messages_pl.min.js | 4 +- .../dist/localization/messages_pt_BR.min.js | 4 +- .../dist/localization/messages_pt_PT.min.js | 4 +- .../dist/localization/messages_ro.min.js | 4 +- .../dist/localization/messages_ru.min.js | 4 +- .../dist/localization/messages_sd.min.js | 4 +- .../dist/localization/messages_si.min.js | 4 +- .../dist/localization/messages_sk.min.js | 4 +- .../dist/localization/messages_sl.min.js | 4 +- .../dist/localization/messages_sr.min.js | 4 +- .../dist/localization/messages_sr_lat.min.js | 4 +- .../dist/localization/messages_sv.min.js | 4 +- .../dist/localization/messages_th.min.js | 4 +- .../dist/localization/messages_tj.min.js | 4 +- .../dist/localization/messages_tr.js | 1 + .../dist/localization/messages_tr.min.js | 6 +- .../dist/localization/messages_uk.min.js | 4 +- .../dist/localization/messages_ur.min.js | 4 +- .../dist/localization/messages_vi.min.js | 4 +- .../dist/localization/messages_zh.min.js | 4 +- .../dist/localization/messages_zh_TW.min.js | 4 +- .../dist/localization/methods_de.min.js | 4 +- .../dist/localization/methods_es_CL.min.js | 4 +- .../dist/localization/methods_fi.min.js | 4 +- .../dist/localization/methods_it.min.js | 4 +- .../dist/localization/methods_nl.min.js | 4 +- .../dist/localization/methods_pt.min.js | 4 +- wwwroot/lib/jquery-validation/package.json | 2 +- wwwroot/lib/jquery-validation/src/core.js | 12 +- .../src/localization/messages_fr.js | 3 +- .../src/localization/messages_tr.js | 1 + .../jquery-validation/validation.jquery.json | 2 +- wwwroot/lib/moment/.bower.json | 10 +- wwwroot/lib/moment/CHANGELOG.md | 6 + wwwroot/lib/moment/dist/locale/hi.js | 55 +- wwwroot/lib/moment/dist/moment.js | 7 +- wwwroot/lib/moment/locale/hi.js | 55 +- wwwroot/lib/moment/min/locales.js | 87 +- wwwroot/lib/moment/min/locales.min.js | 2 +- wwwroot/lib/moment/min/locales.min.js.map | 2 +- wwwroot/lib/moment/min/moment-with-locales.js | 92 +- .../lib/moment/min/moment-with-locales.min.js | 2 +- .../moment/min/moment-with-locales.min.js.map | 2 +- wwwroot/lib/moment/min/moment.min.js | 2 +- wwwroot/lib/moment/min/moment.min.js.map | 2 +- wwwroot/lib/moment/moment.js | 7 +- wwwroot/lib/moment/package-lock.json | 463 +++--- .../lib/moment/src/lib/create/from-string.js | 3 +- wwwroot/lib/moment/src/locale/hi.js | 55 +- wwwroot/lib/moment/src/moment.js | 4 +- 461 files changed, 13266 insertions(+), 5624 deletions(-) create mode 100644 Data/Exporting/ObjectExportSnippetReference.cs create mode 100644 Data/NodeGraph/ReferenceNode.cs create mode 100644 Data/Project/UserSelectedProject.cs create mode 100644 DefaultExportTemplates/Tale/ReferenceNode.lua create mode 100644 Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.de.json create mode 100644 Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.en.json create mode 100644 Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.de.json create mode 100644 Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.en.json create mode 100644 Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.de.json create mode 100644 Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.en.json create mode 100644 Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.de.json create mode 100644 Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.en.json create mode 100644 Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.de.json create mode 100644 Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.en.json create mode 100644 Services/Export/Dialog/ConditionParsingUtil.cs create mode 100644 Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.cs create mode 100644 Services/Export/Dialog/StepRenderers/ReferenceRenderer/IReferenceStepRenderer.cs create mode 100644 Services/Export/Dialog/StepRenderers/ReferenceRenderer/ReferenceNodeData.cs create mode 100644 Services/Export/Dialog/StepRenderers/ReferenceRenderer/ScribanReferenceStepRenderer.cs create mode 100644 Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.cs create mode 100644 Services/Export/ExportSnippets/ExportSnippetRelatedObjectNameResolver.cs create mode 100644 Services/Export/ExportSnippets/IExportSnippetRelatedObjectNameResolver.cs create mode 100644 Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ScribanBaseStringRenderingFunction.cs create mode 100644 Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.cs create mode 100644 Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.cs create mode 100644 Services/Export/Placeholder/ScribanRenderingEngine/Util/ScriptObjectExtensions.cs create mode 100644 Services/Project/IUserProjectAccess.cs create mode 100644 Services/Project/UserProjectAccess.cs create mode 100644 Services/ReferenceAnalyzer/IReferenceAnalyzer.cs create mode 100644 Services/ReferenceAnalyzer/ObjectReference.cs create mode 100644 Services/ReferenceAnalyzer/ReferenceAnalyzer.cs create mode 100644 Services/TimerJob/ITimerJob.cs create mode 100644 Services/TimerJob/ITimerJobManager.cs create mode 100644 Services/TimerJob/JobDefinitions/ILockCleanupTimerJob.cs create mode 100644 Services/TimerJob/JobDefinitions/LockCleanupTimerJob.cs create mode 100644 Services/TimerJob/TimerJobManager.cs create mode 100644 Services/TimerJob/TimerJobRunTimeConfig.cs create mode 100644 wwwroot/js/Home/home.viewmodel.js create mode 100644 wwwroot/js/Shared/httpClient.js create mode 100644 wwwroot/js/Shared/nodeGraph/referenceNode.js diff --git a/Config/MiscConfig.cs b/Config/MiscConfig.cs index a8f4f7f0..50ff5aa9 100644 --- a/Config/MiscConfig.cs +++ b/Config/MiscConfig.cs @@ -48,7 +48,11 @@ public class MiscConfig /// /// CSV Delimiter /// - /// public string CsvDelimiter { get; set; } + + /// + /// Timeout for locks + /// + public int? ResourceLockTimespan { get; set;} } } \ No newline at end of file diff --git a/Constants.cs b/Constants.cs index 2c32f986..01ddc496 100644 --- a/Constants.cs +++ b/Constants.cs @@ -9,5 +9,10 @@ public class Constants /// Minium Password Length /// public const int MinPasswordLength = 8; + + /// + /// Default timespan for resource locks + /// + public const int DefaultResourceLockTimespan = 2; }; } \ No newline at end of file diff --git a/Controllers/Api/AikaApiController.cs b/Controllers/Api/AikaApiController.cs index 5fee2e1e..da7a2e36 100644 --- a/Controllers/Api/AikaApiController.cs +++ b/Controllers/Api/AikaApiController.cs @@ -22,6 +22,11 @@ using GoNorth.Services.ImplementationStatusCompare; using Microsoft.AspNetCore.Http; using System.Globalization; +using GoNorth.Services.Project; +using GoNorth.Data.Exporting; +using GoNorth.Services.Export.ExportSnippets; +using GoNorth.Data.Evne; +using GoNorth.Services.ReferenceAnalyzer; namespace GoNorth.Controllers.Api { @@ -118,14 +123,14 @@ public class ChapterDetailDeleteValidationResult private readonly IAikaQuestDbAccess _questDbAccess; /// - /// Project Db Access + /// Kirja Page Db Access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IKirjaPageDbAccess _kirjaPageDbAccess; /// - /// Kirja Page Db Access + /// Skill DB Access /// - private readonly IKirjaPageDbAccess _kirjaPageDbAccess; + private readonly IEvneSkillDbAccess _skillDbAccess; /// /// Tale DB Access @@ -142,6 +147,16 @@ public class ChapterDetailDeleteValidationResult /// private readonly IKartaMapDbAccess _kartaMapDbAccess; + /// + /// User project access + /// + private readonly IUserProjectAccess _userProjectAccess; + + /// + /// Interface to analyze references + /// + private readonly IReferenceAnalyzer _referenceAnalyzer; + /// /// Timeline Service /// @@ -157,6 +172,16 @@ public class ChapterDetailDeleteValidationResult /// private readonly IImplementationStatusComparer _implementationStatusComparer; + /// + /// Object export snippet Db Access + /// + protected readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; + + /// + /// Service that will resolve export snippet related object names + /// + private readonly IExportSnippetRelatedObjectNameResolver _exportSnippetRelatedObjectNameResolver; + /// /// Logger /// @@ -173,30 +198,39 @@ public class ChapterDetailDeleteValidationResult /// Chapter Overview Db Access /// Chapter Detail Db Access /// Quest Db Access - /// Project Db Access /// Kirja Db Access + /// Skill Db Access /// Tale Db Access /// Kortisto Npc Db Access /// Karta Map Db Access + /// User project Access + /// Object export snippet Db Access + /// Service that will resolve export snippet related object names /// User Manager /// Implementation status comparer + /// Reference analyzer /// Timeline Service /// Logger /// Localizer Factory - public AikaApiController(IAikaChapterOverviewDbAccess chapterOverviewDbAccess, IAikaChapterDetailDbAccess chapterDetailDbAccess, IAikaQuestDbAccess questDbAccess, IProjectDbAccess projectDbAccess, - IKirjaPageDbAccess kirjaPageDbAccess, ITaleDbAccess taleDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, IKartaMapDbAccess kartaMapDbAccess, UserManager userManager, - IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, ILogger logger, IStringLocalizerFactory localizerFactory) + public AikaApiController(IAikaChapterOverviewDbAccess chapterOverviewDbAccess, IAikaChapterDetailDbAccess chapterDetailDbAccess, IAikaQuestDbAccess questDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IEvneSkillDbAccess skillDbAccess, + ITaleDbAccess taleDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, IKartaMapDbAccess kartaMapDbAccess, IUserProjectAccess userProjectAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, + IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, IReferenceAnalyzer referenceAnalyzer, + ITimelineService timelineService, ILogger logger, IStringLocalizerFactory localizerFactory) { _chapterOverviewDbAccess = chapterOverviewDbAccess; _chapterDetailDbAccess = chapterDetailDbAccess; _questDbAccess = questDbAccess; - _projectDbAccess = projectDbAccess; _kirjaPageDbAccess = kirjaPageDbAccess; + _skillDbAccess = skillDbAccess; _taleDbAccess = taleDbAccess; _kortistoNpcDbAccess = kortistoNpcDbAccess; _kartaMapDbAccess = kartaMapDbAccess; + _userProjectAccess = userProjectAccess; + _objectExportSnippetDbAccess = objectExportSnippetDbAccess; + _exportSnippetRelatedObjectNameResolver = exportSnippetRelatedObjectNameResolver; _userManager = userManager; _implementationStatusComparer = implementationStatusComparer; + _referenceAnalyzer = referenceAnalyzer; _timelineService = timelineService; _logger = logger; _localizer = localizerFactory.Create(typeof(AikaApiController)); @@ -210,7 +244,7 @@ public class ChapterDetailDeleteValidationResult [HttpGet] public async Task GetChapterOverview() { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); AikaChapterOverview chapterOverview = await _chapterOverviewDbAccess.GetChapterOverviewByProjectId(defaultProject.Id); return Ok(chapterOverview); @@ -268,7 +302,7 @@ public async Task SaveChapterOverview([FromBody]AikaChapterOvervi } // Get Current Overview - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); AikaChapterOverview chapterOverview = await _chapterOverviewDbAccess.GetChapterOverviewByProjectId(defaultProject.Id); bool overviewExisted = true; List chapterDetailsToDelete = new List(); @@ -384,15 +418,15 @@ public async Task SaveChapterOverview([FromBody]AikaChapterOvervi } // Adjust Aika markers for deleted chapters - int minChapterNumber = chapterOverview.Chapter.Min(c => c.ChapterNumber); - int maxChapterNumber = chapterOverview.Chapter.Max(c => c.ChapterNumber); + int minChapterNumber = chapterOverview.Chapter.Any() ? chapterOverview.Chapter.Min(c => c.ChapterNumber) : 0; + int maxChapterNumber = chapterOverview.Chapter.Any() ? chapterOverview.Chapter.Max(c => c.ChapterNumber) : 0; foreach(int curChapterNumber in deletedChapterNumbers) { await AdjustKartaMapMarkersForDeletedChapter(defaultProject.Id, curChapterNumber, minChapterNumber, maxChapterNumber, chapterOverview.Chapter); } // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaChapterOverviewUpdated); + await _timelineService.AddTimelineEntry(chapterOverview.ProjectId, TimelineEvent.AikaChapterOverviewUpdated); return Ok(chapterOverview); } @@ -557,7 +591,7 @@ private int GetNextChapterNumber(int curChapter, List chapters) [HttpGet] public async Task GetChapters() { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); AikaChapterOverview chapterOverview = await _chapterOverviewDbAccess.GetChapterOverviewByProjectId(defaultProject.Id); if(chapterOverview == null || chapterOverview.Chapter == null) { @@ -585,7 +619,7 @@ public async Task GetChapters() [HttpGet] public async Task GetChapterDetails(string searchPattern, int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; @@ -682,10 +716,10 @@ public async Task ValidateChapterDetailDelete(string id) /// /// Creates the detail views for detail nodes in a chapter detail /// - /// Default Project + /// Id of the project /// Detail for which to create the views /// true if successfull, else false - private async Task CreateDetailsForDetail(GoNorthProject defaultProject, AikaChapterDetail detail) + private async Task CreateDetailsForDetail(string projectId, AikaChapterDetail detail) { // Create Detail Views _logger.LogInformation("Creating chapter detail views"); @@ -697,7 +731,7 @@ private async Task CreateDetailsForDetail(GoNorthProject defaultProject, A { try { - AikaChapterDetail newChapterDetail = await CreateNewChapterDetail(defaultProject.Id, string.Empty, curDetail.Name); + AikaChapterDetail newChapterDetail = await CreateNewChapterDetail(projectId, string.Empty, curDetail.Name); curDetail.DetailViewId = newChapterDetail.Id; createdChapterDetails.Add(newChapterDetail); } @@ -748,7 +782,7 @@ private void CopyValidChapterDetailProperties(AikaChapterDetail targetDetail, Ai [ValidateAntiForgeryToken] public async Task CreateChapterDetail([FromBody]AikaChapterDetail chapterDetail) { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); AikaChapterDetail newChapterDetail = new AikaChapterDetail(); newChapterDetail.ProjectId = defaultProject.Id; @@ -759,7 +793,7 @@ public async Task CreateChapterDetail([FromBody]AikaChapterDetail await this.SetModifiedData(_userManager, newChapterDetail); - bool detailSuccess = await CreateDetailsForDetail(defaultProject, newChapterDetail); + bool detailSuccess = await CreateDetailsForDetail(defaultProject.Id, newChapterDetail); if(!detailSuccess) { return StatusCode((int)HttpStatusCode.InternalServerError); @@ -768,7 +802,7 @@ public async Task CreateChapterDetail([FromBody]AikaChapterDetail newChapterDetail = await _chapterDetailDbAccess.CreateChapterDetail(newChapterDetail); // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaChapterDetailCreated, newChapterDetail.Id); + await _timelineService.AddTimelineEntry(newChapterDetail.ProjectId, TimelineEvent.AikaChapterDetailCreated, newChapterDetail.Id); return Ok(newChapterDetail); } @@ -785,7 +819,6 @@ public async Task CreateChapterDetail([FromBody]AikaChapterDetail [ValidateAntiForgeryToken] public async Task UpdateChapterDetail(string id, [FromBody]AikaChapterDetail chapterDetail) { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); AikaChapterDetail updatedChapterDetail = await _chapterDetailDbAccess.GetChapterDetailById(id); if(updatedChapterDetail.Detail == null) { @@ -845,7 +878,7 @@ public async Task UpdateChapterDetail(string id, [FromBody]AikaCh await this.SetModifiedData(_userManager, updatedChapterDetail); - bool detailSuccess = await CreateDetailsForDetail(defaultProject, updatedChapterDetail); + bool detailSuccess = await CreateDetailsForDetail(updatedChapterDetail.ProjectId, updatedChapterDetail); if(!detailSuccess) { return StatusCode((int)HttpStatusCode.InternalServerError); @@ -866,7 +899,7 @@ public async Task UpdateChapterDetail(string id, [FromBody]AikaCh } // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaChapterDetailUpdated, updatedChapterDetail.Id); + await _timelineService.AddTimelineEntry(updatedChapterDetail.ProjectId, TimelineEvent.AikaChapterDetailUpdated, updatedChapterDetail.Id); return Ok(updatedChapterDetail); } @@ -916,7 +949,7 @@ public async Task DeleteChapterDetail(string id) await _chapterDetailDbAccess.DeleteChapterDetail(deletedChapterDetail); // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaChapterDetailDeleted); + await _timelineService.AddTimelineEntry(deletedChapterDetail.ProjectId, TimelineEvent.AikaChapterDetailDeleted); return Ok(id); } @@ -933,7 +966,7 @@ public async Task DeleteChapterDetail(string id) [HttpGet] public async Task GetQuests(string searchPattern, int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; @@ -967,7 +1000,7 @@ public async Task GetQuests(string searchPattern, int start, int [HttpGet] public async Task GetNotImplementedQuests(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask = _questDbAccess.GetNotImplementedQuests(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); Task countTask = _questDbAccess.GetNotImplementedQuestsCount(project.Id, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -997,12 +1030,15 @@ public async Task GetQuest(string id) /// /// Object id /// Quests - [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [HttpGet] public async Task GetQuestsObjectIsReferenced(string objectId) { List quests = await _questDbAccess.GetQuestsObjectIsReferenced(objectId); - return Ok(quests); + List objectReferences = quests.Select(q => { + return _referenceAnalyzer.BuildObjectReferences(objectId, q.Id, q.Name, q.Action, q.Condition, q.Reference, null); + }).Where(o => o != null).ToList(); + return Ok(objectReferences); } /// @@ -1029,7 +1065,7 @@ public async Task ResolveQuestNames([FromBody]List questI [ValidateAntiForgeryToken] public async Task CreateQuest([FromBody]AikaQuest quest) { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); AikaQuest newQuest = new AikaQuest(); newQuest.ProjectId = defaultProject.Id; @@ -1040,7 +1076,7 @@ public async Task CreateQuest([FromBody]AikaQuest quest) newQuest = await _questDbAccess.CreateQuest(newQuest); // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaQuestCreated, newQuest.Id, newQuest.Name); + await _timelineService.AddTimelineEntry(newQuest.ProjectId, TimelineEvent.AikaQuestCreated, newQuest.Id, newQuest.Name); return Ok(newQuest); } @@ -1074,7 +1110,7 @@ public async Task UpdateQuest(string id, [FromBody]AikaQuest ques await _questDbAccess.UpdateQuest(updatedQuest); // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaQuestUpdated, updatedQuest.Id, updatedQuest.Name); + await _timelineService.AddTimelineEntry(updatedQuest.ProjectId, TimelineEvent.AikaQuestUpdated, updatedQuest.Id, updatedQuest.Name); return Ok(updatedQuest); } @@ -1102,6 +1138,7 @@ private void CopyValidQuestProperties(AikaQuest targetQuest, AikaQuest sourceQue targetQuest.Action = sourceQuest.Action != null ? sourceQuest.Action : new List(); targetQuest.AllDone = sourceQuest.AllDone != null ? sourceQuest.AllDone : new List(); targetQuest.Link = sourceQuest.Link != null ? sourceQuest.Link : new List(); + targetQuest.Reference = sourceQuest.Reference != null ? sourceQuest.Reference : new List(); } /// @@ -1145,6 +1182,21 @@ public async Task DeleteQuest(string id) string usedInDailyRoutines = string.Join(", ", referencedInDailyRoutines.Select(m => m.Name)); return BadRequest(_localizer["CanNotDeleteQuestUsedInDailyRoutine", usedInDailyRoutines].Value); } + + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string usedInSkills = string.Join(", ", referencedInSkills.Select(m => m.Name)); + return BadRequest(_localizer["CanNotDeleteQuestUsedInSkill", usedInSkills].Value); + } + + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(id); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return BadRequest(_localizer["CanNotDeleteQuestUsedInExportSnippet", usedInDailyRoutines].Value); + } // Delete Quest AikaQuest deletedQuest = await _questDbAccess.GetQuestById(id); @@ -1154,7 +1206,7 @@ public async Task DeleteQuest(string id) await _kartaMapDbAccess.DeleteMarkersOfQuest(id); // Timeline Entry - await _timelineService.AddTimelineEntry(TimelineEvent.AikaQuestDeleted, deletedQuest.Name); + await _timelineService.AddTimelineEntry(deletedQuest.ProjectId, TimelineEvent.AikaQuestDeleted, deletedQuest.Name); return Ok(id); } diff --git a/Controllers/Api/EvneApiController.cs b/Controllers/Api/EvneApiController.cs index ea66c08a..3ac0bb56 100644 --- a/Controllers/Api/EvneApiController.cs +++ b/Controllers/Api/EvneApiController.cs @@ -22,6 +22,8 @@ using System.Globalization; using Microsoft.AspNetCore.Http; using GoNorth.Services.CsvHandling; +using GoNorth.Services.Project; +using GoNorth.Services.Export.ExportSnippets; namespace GoNorth.Controllers.Api { @@ -149,7 +151,6 @@ public class EvneApiController : FlexFieldBaseApiController /// Folder Db Access /// Template Db Access /// Skill Db Access - /// User Db Access /// Tag Db Access /// Export Template Db Access /// Import field values log Db Access @@ -157,12 +158,14 @@ public class EvneApiController : FlexFieldBaseApiController /// Export Function Id Db Access /// Object export snippet Db Access /// Object export snippet snapshot Db Access + /// Service that will resolve export snippet related object names /// Skill Image Access /// Thumbnail Service /// Aika Quest Db ACcess /// Kirja Page Db Access /// Tale Db Access /// Kortisto Npc Db Access + /// User project Access /// CSV Generator /// CSV Reader /// User Manager @@ -171,12 +174,12 @@ public class EvneApiController : FlexFieldBaseApiController /// Xss Checker /// Logger /// Localizer Factory - public EvneApiController(IEvneFolderDbAccess folderDbAccess, IEvneSkillTemplateDbAccess templateDbAccess, IEvneSkillDbAccess skillDbAccess, IProjectDbAccess projectDbAccess, IEvneSkillTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, ILanguageKeyDbAccess languageKeyDbAccess, IEvneImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, - IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IEvneSkillImageAccess imageAccess, IEvneThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, - ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, ICsvGenerator csvGenerator, ICsvParser csvReader, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, - IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) - : base(folderDbAccess, templateDbAccess, skillDbAccess, projectDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, imageAccess, thumbnailService, csvGenerator, csvReader, - userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) + public EvneApiController(IEvneFolderDbAccess folderDbAccess, IEvneSkillTemplateDbAccess templateDbAccess, IEvneSkillDbAccess skillDbAccess, IEvneSkillTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, ILanguageKeyDbAccess languageKeyDbAccess, IEvneImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, + IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, IEvneSkillImageAccess imageAccess, + IEvneThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, IUserProjectAccess userProjectAccess, ICsvGenerator csvGenerator, ICsvParser csvReader, UserManager userManager, + IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) + : base(folderDbAccess, templateDbAccess, skillDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, exportSnippetRelatedObjectNameResolver, userProjectAccess, imageAccess, + thumbnailService, csvGenerator, csvReader, userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) { _aikaQuestDbAccess = aikaQuestDbAccess; _taleDbAccess = taleDbAccess; @@ -299,6 +302,13 @@ protected override async Task CheckObjectReferences(string id) return _localizer["CanNotDeleteSkillUsedInDailyRoutine", usedInDailyRoutines].Value; } + List referencedInSkills = await ((IEvneSkillDbAccess)_objectDbAccess).GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string referencedInSkillsString = string.Join(", ", referencedInSkills.Select(n => n.Name)); + return _localizer["CanNotDeleteSkillUsedInSkill", referencedInSkillsString].Value; + } + return string.Empty; } @@ -324,6 +334,7 @@ protected override Task RunAdditionalUpdates(EvneSkill flexFieldObjec loadedFlexFieldObject.Action = flexFieldObject.Action != null ? flexFieldObject.Action : new List(); loadedFlexFieldObject.Condition = flexFieldObject.Condition != null ? flexFieldObject.Condition : new List(); loadedFlexFieldObject.Link = flexFieldObject.Link != null ? flexFieldObject.Link : new List(); + loadedFlexFieldObject.Reference = flexFieldObject.Reference != null ? flexFieldObject.Reference : new List(); return Task.FromResult(loadedFlexFieldObject); } @@ -361,7 +372,7 @@ protected override async Task CompareObjectWithImplementationSnap [HttpGet] public async Task GetNotImplementedSkills(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _objectDbAccess.GetNotImplementedFlexFieldObjects(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -374,5 +385,18 @@ public async Task GetNotImplementedSkills(int start, int pageSize return Ok(queryResult); } + /// + /// Returns all skills an object is referenced in (excluding the skill itselfs) + /// + /// Object id + /// Skills + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [HttpGet] + public async Task GetSkillsObjectIsReferencedIn(string objectId) + { + List skills = await ((IEvneSkillDbAccess)_objectDbAccess).GetSkillsObjectIsReferencedIn(objectId); + return Ok(skills); + } + } } \ No newline at end of file diff --git a/Controllers/Api/ExportApiController.cs b/Controllers/Api/ExportApiController.cs index c2fad0a6..7efecbe7 100644 --- a/Controllers/Api/ExportApiController.cs +++ b/Controllers/Api/ExportApiController.cs @@ -30,6 +30,7 @@ using GoNorth.Services.Export.ExportSnippets; using Microsoft.AspNetCore.Http; using System.Globalization; +using GoNorth.Services.Project; namespace GoNorth.Controllers.Api { @@ -233,9 +234,9 @@ public class TemplateIncludeReference private readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; /// - /// Project Db Access + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Npc Db Access @@ -287,6 +288,11 @@ public class TemplateIncludeReference /// private readonly IExportSnippetRelatedObjectUpdater _exportSnippetRelatedObjectUpdater; + /// + /// Service that will resolve export snippet related object names + /// + private readonly IExportSnippetRelatedObjectNameResolver _exportSnippetRelatedObjectNameResolver; + /// /// Dialog Function Generation Condition Provider /// @@ -335,7 +341,6 @@ public class TemplateIncludeReference /// Include export template Db Access /// Export Settings Db Access /// Object export snippet Db Access - /// Project Db Access /// Npc Db Access /// Npc Template Db Access /// Dialog Db Access @@ -343,9 +348,11 @@ public class TemplateIncludeReference /// Item Template Db Access /// Skill Db Access /// Skill Template Db Access + /// User project access /// Template Placeholder Resolver /// Export template parser /// Export Snippet related object updater + /// Export snippet related object name resolver /// Dialog Function Db Access /// Dialog Function Generation Condition Provider /// Language Key Db Access @@ -355,18 +362,18 @@ public class TemplateIncludeReference /// Logger /// Localizer Factory public ExportApiController(IExportDefaultTemplateProvider defaultTemplateProvider, IExportTemplateDbAccess exportTemplateDbAccess, IIncludeExportTemplateDbAccess includeExportTemplateDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, - IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IProjectDbAccess projectDbAccess, IKortistoNpcDbAccess npcDbAccess, IKortistoNpcTemplateDbAccess npcTemplateDbAccess, ITaleDbAccess dialogDbAccess, IStyrItemDbAccess itemDbAccess, - IStyrItemTemplateDbAccess itemTemplateDbAccess, IEvneSkillDbAccess skillDbAccess, IEvneSkillTemplateDbAccess skillTemplateDbAccess, IExportTemplatePlaceholderResolver templatePlaceholderResolver, IExportTemplateParser exportTemplateParser, - IExportSnippetRelatedObjectUpdater exportSnippetRelatedObjectUpdater, IDialogFunctionGenerationConditionDbAccess dialogFunctionDbAccess, IDialogFunctionGenerationConditionProvider dialogFunctionGenerationConditionProvider, - ILanguageKeyDbAccess languageKeyDbAccess, ILanguageKeyReferenceCollector languageKeyReferenceCollector, ITimelineService timelineService, UserManager userManager, ILogger logger, - IStringLocalizerFactory localizerFactory) + IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IKortistoNpcDbAccess npcDbAccess, IKortistoNpcTemplateDbAccess npcTemplateDbAccess, ITaleDbAccess dialogDbAccess, IStyrItemDbAccess itemDbAccess, + IStyrItemTemplateDbAccess itemTemplateDbAccess, IEvneSkillDbAccess skillDbAccess, IEvneSkillTemplateDbAccess skillTemplateDbAccess, IUserProjectAccess userProjectAccess, IExportTemplatePlaceholderResolver templatePlaceholderResolver, + IExportTemplateParser exportTemplateParser, IExportSnippetRelatedObjectUpdater exportSnippetRelatedObjectUpdater, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, IDialogFunctionGenerationConditionDbAccess dialogFunctionDbAccess, + IDialogFunctionGenerationConditionProvider dialogFunctionGenerationConditionProvider, ILanguageKeyDbAccess languageKeyDbAccess, ILanguageKeyReferenceCollector languageKeyReferenceCollector, ITimelineService timelineService, + UserManager userManager, ILogger logger, IStringLocalizerFactory localizerFactory) { _defaultTemplateProvider = defaultTemplateProvider; _exportTemplateDbAccess = exportTemplateDbAccess; _includeExportTemplateDbAccess = includeExportTemplateDbAccess; _exportSettingsDbAccess = exportSettingsDbAccess; _objectExportSnippetDbAccess = objectExportSnippetDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _npcDbAccess = npcDbAccess; _npcTemplateDbAccess = npcTemplateDbAccess; _dialogDbAccess = dialogDbAccess; @@ -377,6 +384,7 @@ public class TemplateIncludeReference _templatePlaceholderResolver = templatePlaceholderResolver; _exportTemplateParser = exportTemplateParser; _exportSnippetRelatedObjectUpdater = exportSnippetRelatedObjectUpdater; + _exportSnippetRelatedObjectNameResolver = exportSnippetRelatedObjectNameResolver; _dialogFunctionDbAccess = dialogFunctionDbAccess; _dialogFunctionGenerationConditionProvider = dialogFunctionGenerationConditionProvider; _languageKeyDbAccess = languageKeyDbAccess; @@ -386,9 +394,9 @@ public class TemplateIncludeReference _localizer = localizerFactory.Create(this.GetType()); _exporters = new Dictionary(); - _exporters.Add("script", new ScriptExporter(templatePlaceholderResolver, projectDbAccess, exportSettingsDbAccess)); + _exporters.Add("script", new ScriptExporter(templatePlaceholderResolver, exportSettingsDbAccess, userProjectAccess)); _exporters.Add("json", new JsonExporter(objectExportSnippetDbAccess)); - _exporters.Add("languagefile", new LanguageExporter(templatePlaceholderResolver, defaultTemplateProvider, projectDbAccess, exportSettingsDbAccess, languageKeyReferenceCollector)); + _exporters.Add("languagefile", new LanguageExporter(templatePlaceholderResolver, defaultTemplateProvider, exportSettingsDbAccess, userProjectAccess, languageKeyReferenceCollector)); } /// @@ -424,7 +432,7 @@ public IActionResult GetTemplateCategories() [HttpGet] public async Task GetDefaultTemplatesByCategory(TemplateCategory category) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List templates = await _defaultTemplateProvider.GetDefaultTemplatesByCategory(project.Id, category); return Ok(templates.Select(t => TranslateTemplateLabel(t)).ToList()); @@ -440,7 +448,7 @@ public async Task GetDefaultTemplatesByCategory(TemplateCategory [HttpGet] public async Task GetDefaultTemplateByType(TemplateType templateType) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate template = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, templateType); return Ok(TranslateTemplateLabel(template)); @@ -456,7 +464,7 @@ public async Task GetDefaultTemplateByType(TemplateType templateT [HttpGet] public async Task DoesExportTemplateExistForObjectId(string id) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, id); ObjectTemplateExistsResult result = new ObjectTemplateExistsResult(); result.DoesTemplateExist = template != null; @@ -518,21 +526,22 @@ public async Task GetObjectsWithInvalidSnippets(string id, Templa { ExportTemplateByObjectIdResult template = await GetValidExportTemplateByIdAndType(id, templateType); - List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(templateType); + string projectId = template.Template.ProjectId; + List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(projectId, templateType); List childObjects = new List(); if(template.IsDefault) { if(templateType == TemplateType.ObjectNpc) { - childObjects = (await _npcDbAccess.GetFlexFieldObjectsNotPartOfIdList(exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); + childObjects = (await _npcDbAccess.GetFlexFieldObjectsNotPartOfIdList(projectId, exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); } else if(templateType == TemplateType.ObjectItem) { - childObjects = (await _itemDbAccess.GetFlexFieldObjectsNotPartOfIdList(exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); + childObjects = (await _itemDbAccess.GetFlexFieldObjectsNotPartOfIdList(projectId, exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); } else if(templateType == TemplateType.ObjectSkill) { - childObjects = (await _skillDbAccess.GetFlexFieldObjectsNotPartOfIdList(exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); + childObjects = (await _skillDbAccess.GetFlexFieldObjectsNotPartOfIdList(projectId, exportTemplates.Select(e => e.CustomizedObjectId))).Cast().ToList(); } } else @@ -540,15 +549,15 @@ public async Task GetObjectsWithInvalidSnippets(string id, Templa List objectId = new List { template.Template.CustomizedObjectId }; if(templateType == TemplateType.ObjectNpc) { - childObjects = (await _npcDbAccess.GetFlexFieldObjectsPartOfIdList(objectId)).Cast().ToList(); + childObjects = (await _npcDbAccess.GetFlexFieldObjectsPartOfIdList(projectId, objectId)).Cast().ToList(); } else if(templateType == TemplateType.ObjectItem) { - childObjects = (await _itemDbAccess.GetFlexFieldObjectsPartOfIdList(objectId)).Cast().ToList(); + childObjects = (await _itemDbAccess.GetFlexFieldObjectsPartOfIdList(projectId, objectId)).Cast().ToList(); } else if(templateType == TemplateType.ObjectSkill) { - childObjects = (await _skillDbAccess.GetFlexFieldObjectsPartOfIdList(objectId)).Cast().ToList(); + childObjects = (await _skillDbAccess.GetFlexFieldObjectsPartOfIdList(projectId, objectId)).Cast().ToList(); } } @@ -595,7 +604,7 @@ public async Task GetFilledExportTemplateSnippetsByObjectId(strin [ValidateAntiForgeryToken] public async Task CreateObjectExportSnippet(string objectType, [FromBody]ObjectExportSnippet snippet) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); snippet.ProjectId = project.Id; await this.SetModifiedData(_userManager, snippet); @@ -676,6 +685,21 @@ public async Task DeleteObjectExportSnippet(string id, string obj return Ok(result); } + + /// + /// Returns the filled object export snippets of an object + /// + /// Id of the object for which to read the export template + /// Object Export Template snippets + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [Authorize(Roles = RoleNames.ExportObjects)] + [HttpGet] + public async Task GetSnippetsObjectIsReferencedIn(string id) + { + List objectSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(id); + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(objectSnippets, User.IsInRole(RoleNames.Kortisto), User.IsInRole(RoleNames.Styr), User.IsInRole(RoleNames.Evne)); + return Ok(references); + } /// /// Returns the object name by type @@ -712,36 +736,46 @@ private async Task GetValidExportTemplateByIdAnd ExportTemplateByObjectIdResult result = new ExportTemplateByObjectIdResult(); result.IsDefault = false; - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + FlexFieldObject flexFieldObject = null; + if(templateType == TemplateType.ObjectNpc) + { + flexFieldObject = await _npcDbAccess.GetFlexFieldObjectById(id); + } + else if(templateType == TemplateType.ObjectItem) + { + flexFieldObject = await _itemDbAccess.GetFlexFieldObjectById(id); + } + else if(templateType == TemplateType.ObjectSkill) + { + flexFieldObject = await _skillDbAccess.GetFlexFieldObjectById(id); + } + + string projectId = null; + if(flexFieldObject != null) + { + projectId = flexFieldObject.ProjectId; + } - ExportTemplate template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, id); + if(string.IsNullOrEmpty(projectId)) + { + GoNorthProject project = await _userProjectAccess.GetUserProject(); + projectId = project.Id; + } + + ExportTemplate template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(projectId, id); if(template == null) { result.IsDefault = true; - FlexFieldObject flexFieldObject = null; - if(templateType == TemplateType.ObjectNpc) - { - flexFieldObject = await _npcDbAccess.GetFlexFieldObjectById(id); - } - else if(templateType == TemplateType.ObjectItem) - { - flexFieldObject = await _itemDbAccess.GetFlexFieldObjectById(id); - } - else if(templateType == TemplateType.ObjectSkill) - { - flexFieldObject = await _skillDbAccess.GetFlexFieldObjectById(id); - } - if(flexFieldObject != null) { - template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, flexFieldObject.TemplateId); + template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(projectId, flexFieldObject.TemplateId); } if(template == null) { - template = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, templateType); + template = await _defaultTemplateProvider.GetDefaultTemplateByType(projectId, templateType); } } @@ -813,12 +847,12 @@ public async Task SaveDefaultExportTemplate(TemplateType template return BadRequest(validationResult.Errors); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate template = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, templateType); template = await SaveExportTemplate(project, template, renderingEngine, code); - await _timelineService.AddTimelineEntry(TimelineEvent.ExportDefaultTemplateUpdated, ((int)templateType).ToString()); + await _timelineService.AddTimelineEntry(template.ProjectId, TimelineEvent.ExportDefaultTemplateUpdated, ((int)templateType).ToString()); return Ok(template); } @@ -844,7 +878,7 @@ public async Task SaveExportTemplateByObjectId(string id, Templat return BadRequest(validationResult.Errors); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, id); if(template == null) @@ -856,7 +890,7 @@ public async Task SaveExportTemplateByObjectId(string id, Templat } template = await SaveExportTemplate(project, template, renderingEngine, code); - await _timelineService.AddTimelineEntry(TimelineEvent.ExportObjectTemplateUpdated, ((int)templateType).ToString(), id); + await _timelineService.AddTimelineEntry(project.Id, TimelineEvent.ExportObjectTemplateUpdated, ((int)templateType).ToString(), id); return Ok(template); } @@ -906,7 +940,7 @@ private async Task SaveExportTemplate(GoNorthProject project, Ex [ValidateAntiForgeryToken] public async Task DeleteExportTemplateByObjectId(string id) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate template = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, id); if(template == null) @@ -916,7 +950,7 @@ public async Task DeleteExportTemplateByObjectId(string id) await _exportTemplateDbAccess.DeleteTemplate(template); - await _timelineService.AddTimelineEntry(TimelineEvent.ExportObjectTemplateDeleted); + await _timelineService.AddTimelineEntry(template.ProjectId, TimelineEvent.ExportObjectTemplateDeleted); return Ok(id); } @@ -952,7 +986,7 @@ public async Task GetIncludeExportTemplateById(string id) [HttpGet] public async Task GetIncludeExportTemplates(int start, int pageSize) { - GoNorthProject curProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; @@ -983,7 +1017,7 @@ public async Task CreateIncludeExportTemplate([FromBody]IncludeEx return BadRequest(); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); bool nameExists = await _includeExportTemplateDbAccess.DoesIncludeTemplateExist(project.Id, string.Empty, saveRequest.Name); if(nameExists) @@ -999,9 +1033,9 @@ public async Task CreateIncludeExportTemplate([FromBody]IncludeEx await this.SetModifiedData(_userManager, exportTemplate); IncludeExportTemplate createdTemplate = await _includeExportTemplateDbAccess.CreateIncludeTemplate(exportTemplate); - await CheckTemplatesForChangedIncludeReference(project, createdTemplate); + await CheckTemplatesForChangedIncludeReference(exportTemplate.ProjectId, createdTemplate); - await _timelineService.AddTimelineEntry(TimelineEvent.IncludeExportTemplateCreated, createdTemplate.Id, createdTemplate.Name); + await _timelineService.AddTimelineEntry(exportTemplate.ProjectId, TimelineEvent.IncludeExportTemplateCreated, createdTemplate.Id, createdTemplate.Name); return Ok(createdTemplate.Id); } @@ -1026,9 +1060,7 @@ public async Task UpdateIncludeExportTemplate(string id, [FromBod return NotFound(); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); - - bool nameExists = await _includeExportTemplateDbAccess.DoesIncludeTemplateExist(project.Id, id, saveRequest.Name); + bool nameExists = await _includeExportTemplateDbAccess.DoesIncludeTemplateExist(existingTemplate.ProjectId, id, saveRequest.Name); if(nameExists) { return BadRequest(_localizer["ErrorIncludeTemplateNameDoesAlreadyExist", saveRequest.Name]); @@ -1039,9 +1071,9 @@ public async Task UpdateIncludeExportTemplate(string id, [FromBod await this.SetModifiedData(_userManager, existingTemplate); await _includeExportTemplateDbAccess.UpdateIncludeTemplate(existingTemplate); - await CheckTemplatesForChangedIncludeReference(project, existingTemplate); + await CheckTemplatesForChangedIncludeReference(existingTemplate.Id, existingTemplate); - await _timelineService.AddTimelineEntry(TimelineEvent.IncludeExportTemplateUpdated, existingTemplate.Id, existingTemplate.Name); + await _timelineService.AddTimelineEntry(existingTemplate.ProjectId, TimelineEvent.IncludeExportTemplateUpdated, existingTemplate.Id, existingTemplate.Name); return Ok(existingTemplate.Id); } @@ -1049,14 +1081,14 @@ public async Task UpdateIncludeExportTemplate(string id, [FromBod /// /// Checks the templates for include references that are changed /// - /// Current project + /// Current project id /// Include export template that is checked /// Task - private async Task CheckTemplatesForChangedIncludeReference(GoNorthProject project, IncludeExportTemplate includeExportTemplate) + private async Task CheckTemplatesForChangedIncludeReference(string projectId, IncludeExportTemplate includeExportTemplate) { try { - List invalidTemplates = await _exportTemplateDbAccess.GetTemplatesByWrongReferencedIncludeTemplate(project.Id, includeExportTemplate.Id, includeExportTemplate.Name); + List invalidTemplates = await _exportTemplateDbAccess.GetTemplatesByWrongReferencedIncludeTemplate(projectId, includeExportTemplate.Id, includeExportTemplate.Name); foreach(ExportTemplate curTemplate in invalidTemplates) { foreach(IncludeExportTemplateReference curReference in curTemplate.UsedIncludeTemplates) @@ -1099,7 +1131,7 @@ public async Task DeleteIncludeExportTemplate(string id) try { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List templates = await _exportTemplateDbAccess.GetTemplatesByReferencedIncludeTemplate(project.Id, id); foreach(ExportTemplate curTemplate in templates) { @@ -1112,7 +1144,7 @@ public async Task DeleteIncludeExportTemplate(string id) _logger.LogError(ex, "Could not reset include template references."); } - await _timelineService.AddTimelineEntry(TimelineEvent.IncludeExportTemplateDeleted, existingTemplate.Name); + await _timelineService.AddTimelineEntry(existingTemplate.ProjectId, TimelineEvent.IncludeExportTemplateDeleted, existingTemplate.Name); return Ok(id); } @@ -1129,7 +1161,7 @@ public async Task DeleteIncludeExportTemplate(string id) [HttpGet] public async Task GetExportTemplatesReferencingIncludeTemplate(string id) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List templates = await _exportTemplateDbAccess.GetTemplatesByReferencedIncludeTemplate(project.Id, id); List templateReferences = await BuildTemplateIncludeReferences(templates, id); @@ -1207,7 +1239,7 @@ private async Task ResolveTemplateName(ExportTemplate template) [HttpGet] public async Task GetExportSettings() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportSettings loadedExportSettings = await _exportSettingsDbAccess.GetExportSettings(project.Id); return Ok(loadedExportSettings); @@ -1224,7 +1256,7 @@ public async Task GetExportSettings() [ValidateAntiForgeryToken] public async Task SaveExportSettings([FromBody]ExportSettings exportSettings) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportSettings loadedExportSettings = await _exportSettingsDbAccess.GetExportSettings(project.Id); loadedExportSettings.ScriptExtension = exportSettings.ScriptExtension; @@ -1243,7 +1275,7 @@ public async Task SaveExportSettings([FromBody]ExportSettings exp await _exportSettingsDbAccess.SaveExportSettings(project.Id, loadedExportSettings); - await _timelineService.AddTimelineEntry(TimelineEvent.ExportSettingsUpdated); + await _timelineService.AddTimelineEntry(project.Id, TimelineEvent.ExportSettingsUpdated); return Ok(); } @@ -1258,7 +1290,7 @@ public async Task SaveExportSettings([FromBody]ExportSettings exp [HttpGet] public async Task GetDialogFunctionGenerationConditions() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); DialogFunctionGenerationConditionCollection dialogFunctionGenerationConditionCollection = await _dialogFunctionGenerationConditionProvider.GetDialogFunctionGenerationConditions(project.Id); return Ok(dialogFunctionGenerationConditionCollection); @@ -1274,13 +1306,13 @@ public async Task GetDialogFunctionGenerationConditions() [HttpPost] public async Task SaveDialogFunctionGenerationConditions([FromBody]DialogFunctionGenerationConditionCollection functionGenerationConditionCollection) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); await this.SetModifiedData(_userManager, functionGenerationConditionCollection); await _dialogFunctionDbAccess.SaveDialogFunctionGenerationCondition(project.Id, functionGenerationConditionCollection); - await _timelineService.AddTimelineEntry(TimelineEvent.ExportDialogFunctionGenerationConditionsUpdated); + await _timelineService.AddTimelineEntry(project.Id, TimelineEvent.ExportDialogFunctionGenerationConditionsUpdated); return Ok(); } @@ -1296,7 +1328,8 @@ public async Task SaveDialogFunctionGenerationConditions([FromBod [HttpGet] public async Task GetCustomizedTemplatesByType(TemplateType templateType) { - List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(templateType); + GoNorthProject userProject = await _userProjectAccess.GetUserProject(); + List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(userProject.Id, templateType); List objectsUsingTemplate = new List(); if(templateType == TemplateType.ObjectNpc) @@ -1358,7 +1391,33 @@ public async Task GetCustomizedTemplatesByType(TemplateType templ [HttpGet] public async Task GetCustomizedTemplatesByParentObject(string customizedObjectId, TemplateType templateType) { - List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(templateType); + FlexFieldObject flexFieldObject = null; + string projectId = string.Empty; + if(templateType == TemplateType.ObjectNpc) + { + flexFieldObject = await _npcTemplateDbAccess.GetFlexFieldObjectById(customizedObjectId); + } + else if(templateType == TemplateType.ObjectItem) + { + flexFieldObject = await _itemTemplateDbAccess.GetFlexFieldObjectById(customizedObjectId); + } + else if(templateType == TemplateType.ObjectSkill) + { + flexFieldObject = await _skillTemplateDbAccess.GetFlexFieldObjectById(customizedObjectId); + } + + if(flexFieldObject != null) + { + projectId = flexFieldObject.ProjectId; + } + + if(string.IsNullOrEmpty(projectId)) + { + GoNorthProject project = await _userProjectAccess.GetUserProject(); + projectId = project.Id; + } + + List exportTemplates = await _exportTemplateDbAccess.GetCustomizedObjectTemplatesByType(projectId, templateType); List childObjects = new List(); if(templateType == TemplateType.ObjectNpc) { @@ -1566,7 +1625,7 @@ private async Task RunExportObject(string exportFormat, stri [HttpDelete] public async Task DeleteLanguageKeysByGroupId(string groupId) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); await _languageKeyDbAccess.DeleteAllLanguageKeysInGroup(project.Id, groupId); diff --git a/Controllers/Api/FlexFieldBaseApiController.cs b/Controllers/Api/FlexFieldBaseApiController.cs index 9d8f8718..74ddc688 100644 --- a/Controllers/Api/FlexFieldBaseApiController.cs +++ b/Controllers/Api/FlexFieldBaseApiController.cs @@ -22,6 +22,8 @@ using System.Text; using GoNorth.Services.CsvHandling; using System.Text.Json; +using GoNorth.Services.Project; +using GoNorth.Services.Export.ExportSnippets; namespace GoNorth.Controllers.Api { @@ -284,11 +286,6 @@ public class ImportFieldValuesLogQueryResult /// protected readonly IFlexFieldObjectDbAccess _objectDbAccess; - /// - /// Project Db Service - /// - protected readonly IProjectDbAccess _projectDbAccess; - /// /// Flex Field Object Tag Db Access /// @@ -317,13 +314,23 @@ public class ImportFieldValuesLogQueryResult /// /// Object export snippet Db Access /// - private readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; + protected readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; /// /// Object export snippet snapshot Db Access /// private readonly IObjectExportSnippetSnapshotDbAccess _objectExportSnippetSnapshotDbAccess; + /// + /// Service that will resolve export snippet related object names + /// + protected readonly IExportSnippetRelatedObjectNameResolver _exportSnippetRelatedObjectNameResolver; + + /// + /// User project access + /// + protected readonly IUserProjectAccess _userProjectAccess; + /// /// Image Access /// @@ -380,7 +387,7 @@ public class ImportFieldValuesLogQueryResult /// Folder Db Access /// Template Db Access /// Object Db Access - /// Project Db Access + /// Project Db Access /// Tag Db Access /// Export Template Db Access /// Import field values log Db Access @@ -388,6 +395,7 @@ public class ImportFieldValuesLogQueryResult /// Export Function Id Db Access /// Object export snippet Db Access /// Object export snippet snapshot Db Access + /// Service that will resolve export snippet related object names /// Image Access /// Thumbnail Service /// CSV Generator @@ -398,15 +406,15 @@ public class ImportFieldValuesLogQueryResult /// Xss Checker /// Logger /// Localizer Factory - public FlexFieldBaseApiController(IFlexFieldFolderDbAccess folderDbAccess, IFlexFieldObjectDbAccess templateDbAccess, IFlexFieldObjectDbAccess objectDbAccess, IProjectDbAccess projectDbAccess, IFlexFieldObjectTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, + public FlexFieldBaseApiController(IFlexFieldFolderDbAccess folderDbAccess, IFlexFieldObjectDbAccess templateDbAccess, IFlexFieldObjectDbAccess objectDbAccess, IFlexFieldObjectTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IFlexFieldImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, ILanguageKeyDbAccess languageKeyDbAccess, IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, - IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IFlexFieldObjectImageAccess imageAccess, IFlexFieldThumbnailService thumbnailService, ICsvGenerator csvGenerator, ICsvParser csvParser, UserManager userManager, - IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger> logger, IStringLocalizerFactory localizerFactory) + IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, IUserProjectAccess userProjectAccess, IFlexFieldObjectImageAccess imageAccess, + IFlexFieldThumbnailService thumbnailService, ICsvGenerator csvGenerator, ICsvParser csvParser, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger> logger, + IStringLocalizerFactory localizerFactory) { _folderDbAccess = folderDbAccess; _templateDbAccess = templateDbAccess; _objectDbAccess = objectDbAccess; - _projectDbAccess = projectDbAccess; _tagDbAccess = tagDbAccess; _exportTemplateDbAccess = exportTemplateDbAccess; _importFieldValuesLogDbAccess = importFieldValuesLogDbAccess; @@ -414,6 +422,8 @@ public class ImportFieldValuesLogQueryResult _exportFunctionIdDbAccess = exportFunctionIdDbAccess; _objectExportSnippetDbAccess = objectExportSnippetDbAccess; _objectExportSnippetSnapshotDbAccess = objectExportSnippetSnapshotDbAccess; + _exportSnippetRelatedObjectNameResolver = exportSnippetRelatedObjectNameResolver; + _userProjectAccess = userProjectAccess; _imageAccess = imageAccess; _thumbnailService = thumbnailService; _csvGenerator = csvGenerator; @@ -443,7 +453,7 @@ public async Task> Folders(string parentId, int Task countTask; if(string.IsNullOrEmpty(parentId)) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); queryTask = _folderDbAccess.GetRootFoldersForProject(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); countTask = _folderDbAccess.GetRootFolderCount(project.Id, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); } @@ -483,7 +493,7 @@ public async Task CreateFolder([FromBody]FolderRequest folder) try { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); FlexFieldFolder newFolder = new FlexFieldFolder { ProjectId = project.Id, ParentFolderId = folder.ParentId, @@ -491,7 +501,7 @@ public async Task CreateFolder([FromBody]FolderRequest folder) Description = folder.Description }; newFolder = await _folderDbAccess.CreateFolder(newFolder); - await _timelineService.AddTimelineEntry(FolderCreatedEvent, folder.Name, newFolder.Id); + await _timelineService.AddTimelineEntry(newFolder.ProjectId, FolderCreatedEvent, folder.Name, newFolder.Id); return Ok(newFolder.Id); } catch(Exception ex) @@ -532,7 +542,7 @@ public async Task DeleteFolder(string id) _imageAccess.CheckAndDeleteUnusedImage(folder.ThumbnailImageFile); } - await _timelineService.AddTimelineEntry(FolderDeletedEvent, folder.Name); + await _timelineService.AddTimelineEntry(folder.ProjectId, FolderDeletedEvent, folder.Name); return Ok(id); } @@ -569,7 +579,7 @@ public async Task UpdateFolder(string id, [FromBody]FolderRequest await _folderDbAccess.UpdateFolder(loadedFolder); _logger.LogInformation("Folder was updated."); - await _timelineService.AddTimelineEntry(FolderUpdatedEvent, folder.Name, loadedFolder.Id); + await _timelineService.AddTimelineEntry(loadedFolder.ProjectId, FolderUpdatedEvent, folder.Name, loadedFolder.Id); return Ok(id); } @@ -622,7 +632,7 @@ public async Task MoveFolderToFolder(string id, string newParentI { eventToUse = FolderMovedToRootEvent; } - await _timelineService.AddTimelineEntry(eventToUse, folderToMove.Name, folderToMove.Id, folderToMoveTo != null ? folderToMoveTo.Name : string.Empty, folderToMoveTo != null ? folderToMoveTo.Id : string.Empty); + await _timelineService.AddTimelineEntry(folderToMove.ProjectId, eventToUse, folderToMove.Name, folderToMove.Id, folderToMoveTo != null ? folderToMoveTo.Name : string.Empty, folderToMoveTo != null ? folderToMoveTo.Id : string.Empty); return Ok(id); } @@ -734,7 +744,7 @@ public async Task> FlexFieldTemplate(string id) [HttpGet] public async Task> FlexFieldTemplates(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _templateDbAccess.GetFlexFieldObjectsInRootFolderForProject(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -787,7 +797,7 @@ protected async Task BaseCreateFlexFieldTemplate(T template) try { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); template.ProjectId = project.Id; template = await RunAdditionalUpdates(template, template); @@ -795,8 +805,8 @@ protected async Task BaseCreateFlexFieldTemplate(T template) await this.SetModifiedData(_userManager, template); template = await _templateDbAccess.CreateFlexFieldObject(template); - await AddNewTags(template.Tags); - await _timelineService.AddTimelineEntry(TemplateCreatedEvent, template.Name, template.Id); + await AddNewTags(template.ProjectId, template.Tags); + await _timelineService.AddTimelineEntry(template.ProjectId, TemplateCreatedEvent, template.Name, template.Id); return Ok(template); } catch(Exception ex) @@ -817,7 +827,7 @@ protected async Task BaseDeleteFlexFieldTemplate(string id) await _templateDbAccess.DeleteFlexFieldObject(template); _logger.LogInformation("Template was deleted."); - await RemoveUnusedTags(template.Tags); + await RemoveUnusedTags(template.ProjectId, template.Tags); if(!string.IsNullOrEmpty(template.ImageFile)) { @@ -831,7 +841,7 @@ protected async Task BaseDeleteFlexFieldTemplate(string id) await DeleteExportTemplateIfExists(id); - await _timelineService.AddTimelineEntry(TemplateDeletedEvent, template.Name); + await _timelineService.AddTimelineEntry(template.ProjectId, TemplateDeletedEvent, template.Name); return Ok(id); } @@ -842,7 +852,7 @@ protected async Task BaseDeleteFlexFieldTemplate(string id) /// Task private async Task DeleteExportTemplateIfExists(string id) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportTemplate exportTemplate = await _exportTemplateDbAccess.GetTemplateByCustomizedObjectId(project.Id, id); if(exportTemplate != null) { @@ -887,11 +897,11 @@ protected async Task BaseUpdateFlexFieldTemplate(string id, T tem await _templateDbAccess.UpdateFlexFieldObject(loadedTemplate); _logger.LogInformation("Template was updated."); - await AddNewTags(template.Tags.Except(oldTags, StringComparer.OrdinalIgnoreCase).ToList()); - await RemoveUnusedTags(oldTags.Except(template.Tags, StringComparer.OrdinalIgnoreCase).ToList()); + await AddNewTags(loadedTemplate.ProjectId, template.Tags.Except(oldTags, StringComparer.OrdinalIgnoreCase).ToList()); + await RemoveUnusedTags(loadedTemplate.ProjectId, oldTags.Except(template.Tags, StringComparer.OrdinalIgnoreCase).ToList()); _logger.LogInformation("Tags were updated."); - await _timelineService.AddTimelineEntry(TemplateUpdatedEvent, loadedTemplate.Name, loadedTemplate.Id); + await _timelineService.AddTimelineEntry(loadedTemplate.ProjectId, TemplateUpdatedEvent, loadedTemplate.Name, loadedTemplate.Id); return Ok(loadedTemplate); } @@ -937,7 +947,7 @@ protected async Task BaseDistributeFlexFieldTemplateFields(string await _objectDbAccess.UpdateFlexFieldObject(curObject); } - await _timelineService.AddTimelineEntry(TemplateFieldsDistributedEvent, template.Name, template.Id); + await _timelineService.AddTimelineEntry(template.ProjectId, TemplateFieldsDistributedEvent, template.Name, template.Id); return Ok(id); } @@ -982,7 +992,7 @@ public async Task> FlexFieldObjects(str Task countTask; if(string.IsNullOrEmpty(parentId)) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); queryTask = _objectDbAccess.GetFlexFieldObjectsInRootFolderForProject(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); countTask = _objectDbAccess.GetFlexFieldObjectsInRootFolderCount(project.Id, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); } @@ -1011,7 +1021,7 @@ public async Task> FlexFieldObjects(str [HttpGet] public async Task> SearchFlexFieldObjects(string searchPattern, int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; @@ -1072,7 +1082,7 @@ public async Task> CreateFlexFieldObject([FromBody]T flexFieldOb try { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); flexFieldObject.ProjectId = project.Id; flexFieldObject = await RunAdditionalUpdates(flexFieldObject, flexFieldObject); @@ -1080,8 +1090,8 @@ public async Task> CreateFlexFieldObject([FromBody]T flexFieldOb await this.SetModifiedData(_userManager, flexFieldObject); flexFieldObject = await _objectDbAccess.CreateFlexFieldObject(flexFieldObject); - await AddNewTags(flexFieldObject.Tags); - await _timelineService.AddTimelineEntry(ObjectCreatedEvent, flexFieldObject.Name, flexFieldObject.Id); + await AddNewTags(flexFieldObject.ProjectId, flexFieldObject.Tags); + await _timelineService.AddTimelineEntry(flexFieldObject.ProjectId, ObjectCreatedEvent, flexFieldObject.Name, flexFieldObject.Id); return Ok(flexFieldObject); } catch(Exception ex) @@ -1122,6 +1132,14 @@ public async Task DeleteFlexFieldObject(string id) return BadRequest(referenceError); } + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(id); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return BadRequest(_localizer["CanNotDeleteObjectUsedInExportSnippet", usedInDailyRoutines].Value); + } + // Delete Object and dialog T flexFieldObject = await _objectDbAccess.GetFlexFieldObjectById(id); await _objectDbAccess.DeleteFlexFieldObject(flexFieldObject); @@ -1134,7 +1152,7 @@ public async Task DeleteFlexFieldObject(string id) await DeleteAdditionalFlexFieldObjectDependencies(flexFieldObject); - await RemoveUnusedTags(flexFieldObject.Tags); + await RemoveUnusedTags(flexFieldObject.ProjectId, flexFieldObject.Tags); if(!string.IsNullOrEmpty(flexFieldObject.ImageFile)) { @@ -1148,7 +1166,7 @@ public async Task DeleteFlexFieldObject(string id) await DeleteExportTemplateIfExists(id); - await _timelineService.AddTimelineEntry(ObjectDeletedEvent, flexFieldObject.Name); + await _timelineService.AddTimelineEntry(flexFieldObject.ProjectId, ObjectDeletedEvent, flexFieldObject.Name); return Ok(id); } @@ -1255,8 +1273,8 @@ public async Task> UpdateFlexFieldObject(string id, [FromBody]T await _objectDbAccess.UpdateFlexFieldObject(loadedFlexFieldObject); _logger.LogInformation("Flex field object was updated."); - await AddNewTags(flexFieldObject.Tags.Except(oldTags, StringComparer.OrdinalIgnoreCase).ToList()); - await RemoveUnusedTags(oldTags.Except(flexFieldObject.Tags, StringComparer.OrdinalIgnoreCase).ToList()); + await AddNewTags(loadedFlexFieldObject.ProjectId, flexFieldObject.Tags.Except(oldTags, StringComparer.OrdinalIgnoreCase).ToList()); + await RemoveUnusedTags(loadedFlexFieldObject.ProjectId, oldTags.Except(flexFieldObject.Tags, StringComparer.OrdinalIgnoreCase).ToList()); _logger.LogInformation("Tags were updated."); if(nameChanged) @@ -1264,7 +1282,7 @@ public async Task> UpdateFlexFieldObject(string id, [FromBody]T await RunMarkerUpdates(loadedFlexFieldObject); } - await _timelineService.AddTimelineEntry(ObjectUpdatedEvent, loadedFlexFieldObject.Name, loadedFlexFieldObject.Id); + await _timelineService.AddTimelineEntry(loadedFlexFieldObject.ProjectId, ObjectUpdatedEvent, loadedFlexFieldObject.Name, loadedFlexFieldObject.Id); return Ok(loadedFlexFieldObject); } @@ -1351,7 +1369,7 @@ private async Task UploadImage(IFlexFieldObjectDbAccess dbAcce _imageAccess.CheckAndDeleteUnusedImage(oldThumbnailImageFile); } - await _timelineService.AddTimelineEntry(timelineEvent, targetFlexFieldObject.Name, targetFlexFieldObject.Id); + await _timelineService.AddTimelineEntry(targetFlexFieldObject.ProjectId, timelineEvent, targetFlexFieldObject.Name, targetFlexFieldObject.Id); } catch(Exception ex) { @@ -1443,7 +1461,7 @@ public async Task MoveObjectToFolder(string id, string newParentI } await _objectDbAccess.MoveToFolder(id, newParentId); - await _timelineService.AddTimelineEntry(eventToUse, objectToMove.Name, objectToMove.Id, folderToMoveTo != null ? folderToMoveTo.Name : string.Empty, folderToMoveTo != null ? folderToMoveTo.Id : string.Empty); + await _timelineService.AddTimelineEntry(objectToMove.ProjectId, eventToUse, objectToMove.Name, objectToMove.Id, folderToMoveTo != null ? folderToMoveTo.Name : string.Empty, folderToMoveTo != null ? folderToMoveTo.Id : string.Empty); return Ok(id); } catch(Exception ex) @@ -1462,23 +1480,25 @@ public async Task MoveObjectToFolder(string id, string newParentI [HttpGet] public async Task FlexFieldObjectTags() { - List allTags = await _tagDbAccess.GetAllTags(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); + List allTags = await _tagDbAccess.GetAllTags(project.Id); return Ok(allTags); } /// /// Adds new tags /// + /// Id of the project /// Tags to check /// Task - private async Task AddNewTags(List tagsToCheck) + private async Task AddNewTags(string projectId, List tagsToCheck) { if(tagsToCheck == null || tagsToCheck.Count == 0) { return; } - List existingTags = await _tagDbAccess.GetAllTags(); + List existingTags = await _tagDbAccess.GetAllTags(projectId); if(existingTags == null) { existingTags = new List(); @@ -1487,16 +1507,17 @@ private async Task AddNewTags(List tagsToCheck) List newTags = tagsToCheck.Except(existingTags, StringComparer.OrdinalIgnoreCase).ToList(); foreach(string curNewTag in newTags) { - await _tagDbAccess.AddTag(curNewTag); + await _tagDbAccess.AddTag(projectId, curNewTag); } } /// /// Removes unused tags /// + /// Id of the project /// Tags to check /// Task - private async Task RemoveUnusedTags(List tagsToCheck) + private async Task RemoveUnusedTags(string projectId, List tagsToCheck) { if(tagsToCheck == null || tagsToCheck.Count == 0) { @@ -1505,15 +1526,15 @@ private async Task RemoveUnusedTags(List tagsToCheck) foreach(string curDeleteTag in tagsToCheck) { - Task objectUsingTag = _objectDbAccess.AnyFlexFieldObjectUsingTag(curDeleteTag); - Task templateUsingTag = _templateDbAccess.AnyFlexFieldObjectUsingTag(curDeleteTag); + Task objectUsingTag = _objectDbAccess.AnyFlexFieldObjectUsingTag(projectId, curDeleteTag); + Task templateUsingTag = _templateDbAccess.AnyFlexFieldObjectUsingTag(projectId, curDeleteTag); Task.WaitAll(objectUsingTag, templateUsingTag); if(objectUsingTag.Result || templateUsingTag.Result) { continue; } - await _tagDbAccess.DeleteTag(curDeleteTag); + await _tagDbAccess.DeleteTag(projectId, curDeleteTag); } } @@ -1541,8 +1562,7 @@ public async Task ExportFieldValues([FromForm]ExportFieldValuesRe List objects = await _objectDbAccess.GetFlexFieldObjectsByTemplate(exportRequest.SelectedTemplate); if(!string.IsNullOrEmpty(exportRequest.FolderId)) { - GoNorthProject curProject = await _projectDbAccess.GetDefaultProject(); - List folders = await _folderDbAccess.GetFoldersForHierarchy(curProject.Id); + List folders = await _folderDbAccess.GetFoldersForHierarchy(template.ProjectId); objects = FilterObjectsByFolder(objects, folders, exportRequest.FolderId); } @@ -1664,12 +1684,19 @@ public async Task ImportFieldValuesPreCheck() } List objectsToUpdate = await LoadObjectsFromCsv(csvReadResult); - FlexFieldImportValuePreCheckResult preCheckResult = await BuildCsvPreCheckResult(uploadFile.FileName, csvReadResult, objectsToUpdate); - if(preCheckResult == null) + try + { + FlexFieldImportValuePreCheckResult preCheckResult = await BuildCsvPreCheckResult(uploadFile.FileName, csvReadResult, objectsToUpdate); + return Ok(preCheckResult); + } + catch(KeyNotFoundException) { return BadRequest(_localizer["ImportFieldValuesNoValidTemplateSpecified"]); } - return Ok(preCheckResult); + catch(InvalidDataException) + { + return BadRequest(_localizer["TemplateIsForDifferentProject"]); + } } /// @@ -1708,14 +1735,20 @@ private async Task BuildCsvPreCheckResult(st string headerTemplateValue = csvReadResult.Columns.FirstOrDefault(c => c.StartsWith(CsvHeaderTemplateIdPrefix)); if(string.IsNullOrEmpty(headerTemplateValue)) { - return null; + throw new KeyNotFoundException(); } string templateId = headerTemplateValue.Replace(CsvHeaderTemplateIdPrefix, string.Empty); T template = await _templateDbAccess.GetFlexFieldObjectById(templateId); if(template == null) { - return null; + throw new KeyNotFoundException(); + } + + GoNorthProject curProject = await _userProjectAccess.GetUserProject(); + if(curProject.Id != template.ProjectId) + { + throw new InvalidDataException(); } preCheckResult.TemplateId = template.Id; @@ -1802,7 +1835,11 @@ public async Task ImportFieldValues([FromBody]FlexFieldImportValu return BadRequest(); } - GoNorthProject curProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _userProjectAccess.GetUserProject(); + if(curProject.Id != template.ProjectId) + { + return BadRequest(); + } FlexFieldImportFieldValuesResultLog importResult = new FlexFieldImportFieldValuesResultLog(); importResult.FileName = importRows.Filename; @@ -1817,7 +1854,7 @@ public async Task ImportFieldValues([FromBody]FlexFieldImportValu if(importResult.ExistingRows.Any(e => e.Result == FlexFieldImportValueRowResult.Success) || importResult.NewRows.Any(e => e.Result == FlexFieldImportValueRowResult.Success)) { - await _timelineService.AddTimelineEntry(ValueFileImportEvent, importResult.ExistingRows.Where(e => e.Result == FlexFieldImportValueRowResult.Success).Count().ToString(), + await _timelineService.AddTimelineEntry(importResult.ProjectId, ValueFileImportEvent, importResult.ExistingRows.Where(e => e.Result == FlexFieldImportValueRowResult.Success).Count().ToString(), importResult.NewRows.Where(e => e.Result == FlexFieldImportValueRowResult.Success).Count().ToString()); } @@ -2195,7 +2232,7 @@ private string GetExportFieldValueLogValue(string column, FlexFieldImportValueRo [HttpGet] public async Task> GetFlexFieldValueImportLogs(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _importFieldValuesLogDbAccess.GetImportLogsByProject(project.Id, start, pageSize); diff --git a/Controllers/Api/ImplementationStatusApiController.cs b/Controllers/Api/ImplementationStatusApiController.cs index 8cd22bf2..0231225d 100644 --- a/Controllers/Api/ImplementationStatusApiController.cs +++ b/Controllers/Api/ImplementationStatusApiController.cs @@ -223,7 +223,7 @@ public async Task FlagNpcAsImplemented(string npcId) await FlagObjectExportSnippetsAsImplemented(npc.Id); // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedNpc, npc.Id, npc.Name); + await _timelineService.AddTimelineEntry(npc.ProjectId, TimelineEvent.ImplementedNpc, npc.Id, npc.Name); return Ok(); } @@ -272,7 +272,7 @@ public async Task FlagItemAsImplemented(string itemId) await FlagObjectExportSnippetsAsImplemented(item.Id); // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedItem, item.Id, item.Name); + await _timelineService.AddTimelineEntry(item.ProjectId, TimelineEvent.ImplementedItem, item.Id, item.Name); return Ok(); } @@ -322,7 +322,7 @@ public async Task FlagSkillAsImplemented(string skillId) await FlagObjectExportSnippetsAsImplemented(skill.Id); // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedSkill, skill.Id, skill.Name); + await _timelineService.AddTimelineEntry(skill.ProjectId, TimelineEvent.ImplementedSkill, skill.Id, skill.Name); return Ok(); } @@ -377,7 +377,7 @@ public async Task FlagDialogAsImplemented(string dialogId) { npcName = npcNames[0].Name; } - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedDialog, dialog.RelatedObjectId, npcName); + await _timelineService.AddTimelineEntry(dialog.ProjectId, TimelineEvent.ImplementedDialog, dialog.RelatedObjectId, npcName); return Ok(); } @@ -426,7 +426,7 @@ public async Task FlagQuestAsImplemented(string questId) await _questDbAccess.UpdateQuest(quest); // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedQuest, quest.Id, quest.Name); + await _timelineService.AddTimelineEntry(quest.ProjectId, TimelineEvent.ImplementedQuest, quest.Id, quest.Name); return Ok(); } @@ -511,7 +511,7 @@ public async Task FlagMarkerAsImplemented(string mapId, string ma } // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedMarker, mapId, markerId, markerType.ToString(), map.Name); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.ImplementedMarker, mapId, markerId, markerType.ToString(), map.Name); return Ok(); } diff --git a/Controllers/Api/KartaApiController.cs b/Controllers/Api/KartaApiController.cs index 1b195d1e..4567d5e5 100644 --- a/Controllers/Api/KartaApiController.cs +++ b/Controllers/Api/KartaApiController.cs @@ -19,6 +19,10 @@ using GoNorth.Data.Tale; using GoNorth.Data.Aika; using Microsoft.AspNetCore.Http; +using GoNorth.Services.Project; +using GoNorth.Data.Evne; +using GoNorth.Data.Exporting; +using GoNorth.Services.Export.ExportSnippets; namespace GoNorth.Controllers.Api { @@ -131,9 +135,19 @@ public class NamedMarkerQueryResult private readonly IAikaQuestDbAccess _questDbAccess; /// - /// Project Db Access + /// Skill Db Access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IEvneSkillDbAccess _skillDbAccess; + + /// + /// Object export snippet Db Access + /// + private readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; + + /// + /// User project access + /// + private readonly IUserProjectAccess _userProjectAccess; /// /// Karta Image Access @@ -144,6 +158,11 @@ public class NamedMarkerQueryResult /// Karta Image Processor /// private readonly IKartaImageProcessor _imageProcessor; + + /// + /// Service that will resolve export snippet related object names + /// + private readonly IExportSnippetRelatedObjectNameResolver _exportSnippetRelatedObjectNameResolver; /// /// Timeline Service @@ -173,15 +192,19 @@ public class NamedMarkerQueryResult /// Kortisto Npc Db Access /// Tale Db Access /// Quest Db Access - /// Project Db Access + /// Skill Db Access + /// Object export snippet Db Access + /// User project access /// Map Image Access /// Map Image Processor + /// Service that will resolve export snippet related object names /// Timeline Service /// User Manager /// Logger /// Localizer Factory public KartaApiController(IKartaMapDbAccess mapDbAccess, IKartaMarkerImplementationSnapshotDbAccess markerImplementationSnapshotDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, ITaleDbAccess taleDbAccess, - IAikaQuestDbAccess questDbAccess, IProjectDbAccess projectDbAccess, IKartaImageAccess mapImageAccess, IKartaImageProcessor imageProcessor, ITimelineService timelineService, + IAikaQuestDbAccess questDbAccess, IEvneSkillDbAccess skillDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IUserProjectAccess userProjectAccess, + IKartaImageAccess mapImageAccess, IKartaImageProcessor imageProcessor, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, ITimelineService timelineService, UserManager userManager, ILogger logger, IStringLocalizerFactory localizerFactory) { _mapDbAccess = mapDbAccess; @@ -189,9 +212,12 @@ public class NamedMarkerQueryResult _kortistoNpcDbAccess = kortistoNpcDbAccess; _taleDbAccess = taleDbAccess; _questDbAccess = questDbAccess; - _projectDbAccess = projectDbAccess; + _skillDbAccess = skillDbAccess; + _objectExportSnippetDbAccess = objectExportSnippetDbAccess; + _userProjectAccess = userProjectAccess; _mapImageAccess = mapImageAccess; _imageProcessor = imageProcessor; + _exportSnippetRelatedObjectNameResolver = exportSnippetRelatedObjectNameResolver; _timelineService = timelineService; _userManager = userManager; _logger = logger; @@ -237,7 +263,7 @@ public async Task Map(string id) [HttpGet] public async Task Maps() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List maps = await _mapDbAccess.GetAllProjectMaps(project.Id); return Ok(maps); } @@ -372,7 +398,7 @@ public async Task CreateMap(string name) await this.SetModifiedData(_userManager, map); - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); map.ProjectId = project.Id; // Process Map @@ -399,7 +425,7 @@ public async Task CreateMap(string name) return StatusCode((int)HttpStatusCode.InternalServerError); } - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapCreated, map.Name, map.Id); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapCreated, map.Name, map.Id); return Ok(map.Id); } @@ -504,7 +530,7 @@ public async Task UpdateMap(string id, string name) // Clean rollback data _mapImageAccess.CleanRollbackMapImages(map.Id); - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapUpdated, name, id); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapUpdated, name, id); return Ok(id); } @@ -576,7 +602,7 @@ public async Task RenameMap(string id, string name) await this.SyncMapNameToMarkers(id, name); } - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapUpdated, name, id); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapUpdated, name, id); return Ok(id); } @@ -630,7 +656,7 @@ public async Task DeleteMap(string id) _mapImageAccess.DeleteMapFolder(map.Id); _logger.LogInformation("Map image was deleted."); - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapDeleted, map.Name); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapDeleted, map.Name); return Ok(id); } @@ -670,6 +696,21 @@ private async Task CheckMapReferencesForDeletion(string id) return _localizer["CanNotDeleteMapReferencedInAikaQuest", referencedInQuests].Value; } + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string usedInSkills = string.Join(", ", referencedInSkills.Select(m => m.Name)); + return _localizer["CanNotDeleteMapReferencedInSkill", usedInSkills].Value; + } + + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(id); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return _localizer["CanNotDeleteMapReferencedInExportSnippet", usedInDailyRoutines].Value; + } + return null; } @@ -856,7 +897,7 @@ public IActionResult GetNewMapMarkerId() await _mapDbAccess.UpdateMap(map); string localizedMarkerType = _localizer["MarkerType" + markerType].Value; - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapMarkerUpdated, map.Name, map.Id, markerId, markerType, localizedMarkerType); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapMarkerUpdated, map.Name, map.Id, markerId, markerType, localizedMarkerType); return Ok(id); } @@ -922,7 +963,7 @@ public IActionResult GetNewMapMarkerId() await _mapDbAccess.UpdateMap(map); string localizedMarkerType = _localizer["MarkerType" + markerType.ToString()].Value; - await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapMarkerDeleted, map.Name, map.Id, localizedMarkerType); + await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapMarkerDeleted, map.Name, map.Id, localizedMarkerType); return Ok(id); } @@ -956,6 +997,21 @@ private async Task CheckMarkerReferencesForDelete(string markerId) return _localizer["CanNotDeleteMarkerReferencedInAikaQuest", referencedInQuests].Value; } + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(markerId); + if(referencedInSkills.Count > 0) + { + string usedInSkills = string.Join(", ", referencedInSkills.Select(m => m.Name)); + return _localizer["CanNotDeleteMarkerReferencedInSkill", usedInSkills].Value; + } + + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(markerId); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return _localizer["CanNotDeleteMarkerReferencedInExportSnippet", usedInDailyRoutines].Value; + } + return null; } @@ -1002,7 +1058,7 @@ private void CopyBaseMarkerAttributes(MapMarker targetMarker, MapMarker sourceMa [HttpGet] public async Task GetNotImplementedMarkers(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _mapDbAccess.GetNotImplementedMarkers(project.Id, start, pageSize); @@ -1031,7 +1087,7 @@ public async Task GetNotImplementedMarkers(int start, int pageSiz [HttpGet] public async Task SearchMarkersByExportName(string searchPattern, int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List markers = await _mapDbAccess.GetMarkersByExportName(project.Id, searchPattern); NamedMarkerQueryResult queryResult = new NamedMarkerQueryResult(); diff --git a/Controllers/Api/KirjaApiController.cs b/Controllers/Api/KirjaApiController.cs index 9a09150e..83db6c0b 100644 --- a/Controllers/Api/KirjaApiController.cs +++ b/Controllers/Api/KirjaApiController.cs @@ -27,6 +27,10 @@ using GoNorth.Data.Evne; using GoNorth.Data.Aika; using System.Globalization; +using GoNorth.Services.Project; +using GoNorth.Data.Tale; +using GoNorth.Data.Exporting; +using GoNorth.Services.Export.ExportSnippets; namespace GoNorth.Controllers.Api { @@ -150,9 +154,9 @@ public class PageVersionReferenceValidationResult private readonly IKirjaPageVersionDbAccess _pageVersionDbAccess; /// - /// Project Db Service + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Karta Map Db Access @@ -179,6 +183,16 @@ public class PageVersionReferenceValidationResult /// private readonly IAikaQuestDbAccess _questDbAccess; + /// + /// Dialog Db Access + /// + private readonly ITaleDbAccess _dialogDbAccess; + + /// + /// Object export snippet Db Access + /// + protected readonly IObjectExportSnippetDbAccess _objectExportSnippetDbAccess; + /// /// File Access /// @@ -194,6 +208,11 @@ public class PageVersionReferenceValidationResult /// private readonly IKirjaPageParserService _pageParserService; + /// + /// Service that will resolve export snippet related object names + /// + private readonly IExportSnippetRelatedObjectNameResolver _exportSnippetRelatedObjectNameResolver; + /// /// User Manager /// @@ -234,35 +253,42 @@ public class PageVersionReferenceValidationResult /// /// Page Db Access /// Page Version Db Access - /// User Db Access /// Karta Map Db Access /// Npc Db Access /// Item Db Access /// Skill Db Access /// Quest Db Access + /// Dialog Db Access + /// Object export snippet Db Access + /// User project access /// File Access /// Timeline Service /// Page parser service + /// Service that will resolve export snippet related object names /// User Manager /// Xss Checker /// Logger /// Localizer Factory /// Config Data - public KirjaApiController(IKirjaPageDbAccess pageDbAccess, IKirjaPageVersionDbAccess pageVersionDbAccess, IProjectDbAccess projectDbAccess, IKartaMapDbAccess kartaMapDbAccess, IKortistoNpcDbAccess npcDbAccess, IStyrItemDbAccess itemDbAccess, IEvneSkillDbAccess skillDbAccess, - IAikaQuestDbAccess questDbAccess, IKirjaFileAccess fileAccess, ITimelineService timelineService, IKirjaPageParserService pageParserService, UserManager userManager, IXssChecker xssChecker, ILogger logger, - IStringLocalizerFactory localizerFactory, IOptions configuration) + public KirjaApiController(IKirjaPageDbAccess pageDbAccess, IKirjaPageVersionDbAccess pageVersionDbAccess, IKartaMapDbAccess kartaMapDbAccess, IKortistoNpcDbAccess npcDbAccess, IStyrItemDbAccess itemDbAccess, IEvneSkillDbAccess skillDbAccess, + IAikaQuestDbAccess questDbAccess, ITaleDbAccess dialogDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IUserProjectAccess userProjectAccess, IKirjaFileAccess fileAccess, ITimelineService timelineService, + IKirjaPageParserService pageParserService, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, UserManager userManager, IXssChecker xssChecker, + ILogger logger, IStringLocalizerFactory localizerFactory, IOptions configuration) { _pageDbAccess = pageDbAccess; _pageVersionDbAccess = pageVersionDbAccess; - _projectDbAccess = projectDbAccess; _kartaMapDbAccess = kartaMapDbAccess; _npcDbAccess = npcDbAccess; _itemDbAccess = itemDbAccess; _skillDbAccess = skillDbAccess; _questDbAccess = questDbAccess; + _dialogDbAccess = dialogDbAccess; + _objectExportSnippetDbAccess = objectExportSnippetDbAccess; + _userProjectAccess = userProjectAccess; _fileAccess = fileAccess; _timelineService = timelineService; _pageParserService = pageParserService; + _exportSnippetRelatedObjectNameResolver = exportSnippetRelatedObjectNameResolver; _userManager = userManager; _xssChecker = xssChecker; _logger = logger; @@ -303,7 +329,7 @@ public async Task Page(string id) } else { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); page = await _pageDbAccess.GetDefaultPageForProject(project.Id); if(page == null) { @@ -357,7 +383,7 @@ public async Task SearchPages(string searchPattern, int start, in searchPattern = ""; } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _pageDbAccess.SearchPages(project.Id, searchPattern, start, pageSize, excludeId, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -483,7 +509,7 @@ public async Task CreatePage([FromBody]PageRequest page) try { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); KirjaPage newPage = new KirjaPage(); newPage.ProjectId = project.Id; @@ -497,7 +523,7 @@ public async Task CreatePage([FromBody]PageRequest page) newPage = await _pageDbAccess.CreatePage(newPage); await SaveVersionOfPage(newPage); - await _timelineService.AddTimelineEntry(TimelineEvent.KirjaPageCreated, newPage.Name, newPage.Id); + await _timelineService.AddTimelineEntry(newPage.ProjectId, TimelineEvent.KirjaPageCreated, newPage.Name, newPage.Id); return Ok(newPage); } catch(Exception ex) @@ -568,7 +594,7 @@ public async Task UpdatePage(string id, [FromBody]PageRequest pag await DeleteUnusedImages(loadedPage.Id, oldImages.Except(loadedPage.UplodadedImages, StringComparer.OrdinalIgnoreCase).ToList()); _logger.LogInformation("Unused Images were deleted."); - await _timelineService.AddTimelineEntry(TimelineEvent.KirjaPageUpdated, loadedPage.Name, loadedPage.Id, versionId, oldVersionId); + await _timelineService.AddTimelineEntry(loadedPage.ProjectId, TimelineEvent.KirjaPageUpdated, loadedPage.Name, loadedPage.Id, versionId, oldVersionId); return Ok(loadedPage); } @@ -725,6 +751,43 @@ public async Task DeletePage(string id) return BadRequest(_localizer["CanNotDeletePageMarkedInKartaMap", markedInMaps].Value); } + List taleDialogs = await _dialogDbAccess.GetDialogsObjectIsReferenced(id); + if(taleDialogs.Count > 0) + { + List npcs = await _npcDbAccess.ResolveFlexFieldObjectNames(taleDialogs.Select(t => t.RelatedObjectId).ToList()); + string referencedInDialogs = string.Join(", ", npcs.Select(n => n.Name)); + return BadRequest(_localizer["CanNotDeletePageReferencedInDialog", referencedInDialogs].Value); + } + + List usedNpcs = await _npcDbAccess.GetNpcsObjectIsReferencedInDailyRoutine(id); + if(usedNpcs.Count > 0) + { + string referencedInNpcs = string.Join(", ", usedNpcs.Select(p => p.Name)); + return BadRequest(_localizer["CanNotDeletePageReferencedInNpc", referencedInNpcs].Value); + } + + List aikaQuests = await _questDbAccess.GetQuestsObjectIsReferenced(id); + if(aikaQuests.Count > 0) + { + string referencedInQuests = string.Join(", ", aikaQuests.Select(p => p.Name)); + return BadRequest(_localizer["CanNotDeletePageReferencedInQuest", referencedInQuests].Value); + } + + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string usedInSkills = string.Join(", ", referencedInSkills.Select(m => m.Name)); + return BadRequest(_localizer["CanNotDeletePageReferencedInSkill", usedInSkills].Value); + } + + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(id); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return BadRequest(_localizer["CanNotDeletePageReferencedInExportSnippet", usedInDailyRoutines].Value); + } + KirjaPage page = await _pageDbAccess.GetPageById(id); if(page.IsDefault) { @@ -767,7 +830,7 @@ public async Task DeletePage(string id) await _pageVersionDbAccess.DeletePageVersionsByPage(page.Id); - await _timelineService.AddTimelineEntry(TimelineEvent.KirjaPageDeleted, page.Name); + await _timelineService.AddTimelineEntry(page.ProjectId, TimelineEvent.KirjaPageDeleted, page.Name); return Ok(id); } @@ -944,7 +1007,7 @@ public async Task UploadPageAttachment(string id) return StatusCode((int)HttpStatusCode.InternalServerError, _localizer["CouldNotUploadFile"]); } - await _timelineService.AddTimelineEntry(TimelineEvent.KirjaAttachmentAdded, page.Name, page.Id, pageAttachment.OriginalFilename); + await _timelineService.AddTimelineEntry(page.ProjectId, TimelineEvent.KirjaAttachmentAdded, page.Name, page.Id, pageAttachment.OriginalFilename); return Ok(pageAttachment); } @@ -1041,7 +1104,7 @@ public async Task DeleteAttachment(string pageId, string attachme return StatusCode((int)HttpStatusCode.InternalServerError); } - await _timelineService.AddTimelineEntry(TimelineEvent.KirjaAttachmentDeleted, page.Name, page.Id, attachment.OriginalFilename); + await _timelineService.AddTimelineEntry(page.ProjectId, TimelineEvent.KirjaAttachmentDeleted, page.Name, page.Id, attachment.OriginalFilename); return Ok(pageId); } diff --git a/Controllers/Api/KortistoApiController.cs b/Controllers/Api/KortistoApiController.cs index 418e2a6d..1eaa3dc7 100644 --- a/Controllers/Api/KortistoApiController.cs +++ b/Controllers/Api/KortistoApiController.cs @@ -26,6 +26,9 @@ using Microsoft.AspNetCore.Http; using System.Globalization; using GoNorth.Services.CsvHandling; +using GoNorth.Services.Project; +using GoNorth.Services.Export.ExportSnippets; +using GoNorth.Data.Evne; namespace GoNorth.Controllers.Api { @@ -131,6 +134,11 @@ public class KortistoApiController : FlexFieldBaseApiController /// private readonly IAikaQuestDbAccess _aikaQuestDbAccess; + /// + /// Skill DB Access + /// + private readonly IEvneSkillDbAccess _skillDbAccess; + /// /// Tale DB Access /// @@ -157,7 +165,6 @@ public class KortistoApiController : FlexFieldBaseApiController /// Folder Db Access /// Template Db Access /// Npc Db Access - /// User Db Access /// Tag Db Access /// Export Template Db Access /// Import field values log Db Access @@ -165,12 +172,15 @@ public class KortistoApiController : FlexFieldBaseApiController /// Export Function Id Db Access /// Object export snippet Db Access /// Object export snippet snapshot Db Access + /// Service that will resolve export snippet related object names /// Npc Image Access /// Thumbnail Service /// Aika Quest Db Access + /// Skill Db Access /// Tale Db Access /// Kirja Page Db Access /// Karta Map Db Access + /// User project access /// Project config provider /// CSV Generator /// CSV Reader @@ -180,14 +190,16 @@ public class KortistoApiController : FlexFieldBaseApiController /// Xss Checker /// Logger /// Localizer Factory - public KortistoApiController(IKortistoFolderDbAccess folderDbAccess, IKortistoNpcTemplateDbAccess templateDbAccess, IKortistoNpcDbAccess npcDbAccess, IProjectDbAccess projectDbAccess, IKortistoNpcTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IKortistoImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, - ILanguageKeyDbAccess languageKeyDbAccess, IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IKortistoNpcImageAccess imageAccess, - IKortistoThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKartaMapDbAccess kartaMapDbAccess, IProjectConfigProvider projectConfigProvider, ICsvGenerator csvGenerator, - ICsvParser csvReader, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) - : base(folderDbAccess, templateDbAccess, npcDbAccess, projectDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, imageAccess, thumbnailService, csvGenerator, - csvReader, userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) + public KortistoApiController(IKortistoFolderDbAccess folderDbAccess, IKortistoNpcTemplateDbAccess templateDbAccess, IKortistoNpcDbAccess npcDbAccess, IKortistoNpcTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IKortistoImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, + ILanguageKeyDbAccess languageKeyDbAccess, IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, + IKortistoNpcImageAccess imageAccess, IKortistoThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, IEvneSkillDbAccess skillDbAccess, ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKartaMapDbAccess kartaMapDbAccess, IUserProjectAccess userProjectAccess, + IProjectConfigProvider projectConfigProvider, ICsvGenerator csvGenerator, ICsvParser csvReader, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, + IStringLocalizerFactory localizerFactory) + : base(folderDbAccess, templateDbAccess, npcDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, exportSnippetRelatedObjectNameResolver, userProjectAccess, imageAccess, thumbnailService, + csvGenerator, csvReader, userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) { _aikaQuestDbAccess = aikaQuestDbAccess; + _skillDbAccess = skillDbAccess; _taleDbAccess = taleDbAccess; _kirjaPageDbAccess = kirjaPageDbAccess; _kartaMapDbAccess = kartaMapDbAccess; @@ -331,6 +343,13 @@ protected override async Task CheckObjectReferences(string id) return _localizer["CanNotDeleteNpcUsedInDailyRoutine", usedInDailyRoutines].Value; } + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string referencedInSkillsString = string.Join(", ", referencedInSkills.Select(n => n.Name)); + return _localizer["CanNotDeleteNpcUsedInSkill", referencedInSkillsString].Value; + } + return string.Empty; } @@ -394,7 +413,7 @@ private async Task CheckForDeletedReferencedDailyRoutines(KortistoNpc fl if(usedNpcs.Count > 0) { string referencedInNpcs = string.Join(", ", usedNpcs.Select(p => p.Name)); - return _localizer["CanNotDeleteDailyRoutineEventReferencedInNpc", referencedInNpcs].Value; + return _localizer["CanNotDeleteDailyRoutineEventReferencedInNpc", FormatDailyRoutineEventTime(loadedFlexFieldObject.DailyRoutine, curDeletedEventId), referencedInNpcs].Value; } List taleDialogs = await _taleDbAccess.GetDialogsObjectIsReferenced(curDeletedEventId); @@ -402,20 +421,60 @@ private async Task CheckForDeletedReferencedDailyRoutines(KortistoNpc fl { List npcs = await _objectDbAccess.ResolveFlexFieldObjectNames(taleDialogs.Select(t => t.RelatedObjectId).ToList()); string referencedInDialogs = string.Join(", ", npcs.Select(n => n.Name)); - return _localizer["CanNotDeleteDailyRoutineEventReferencedInTaleDialog", referencedInDialogs].Value; + return _localizer["CanNotDeleteDailyRoutineEventReferencedInTaleDialog", FormatDailyRoutineEventTime(loadedFlexFieldObject.DailyRoutine, curDeletedEventId), referencedInDialogs].Value; } List aikaQuests = await _aikaQuestDbAccess.GetQuestsObjectIsReferenced(curDeletedEventId); if(aikaQuests.Count > 0) { string referencedInQuests = string.Join(", ", aikaQuests.Select(p => p.Name)); - return _localizer["CanNotDeleteDailyRoutineEventReferencedInAikaQuest", referencedInQuests].Value; + return _localizer["CanNotDeleteDailyRoutineEventReferencedInAikaQuest", FormatDailyRoutineEventTime(loadedFlexFieldObject.DailyRoutine, curDeletedEventId), referencedInQuests].Value; + } + + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(curDeletedEventId); + if(referencedInSkills.Count > 0) + { + string usedInSkills = string.Join(", ", referencedInSkills.Select(m => m.Name)); + return _localizer["CanNotDeleteDailyRoutineEventReferencedInSkill", FormatDailyRoutineEventTime(loadedFlexFieldObject.DailyRoutine, curDeletedEventId), usedInSkills].Value; + } + + List referencedInSnippets = await _objectExportSnippetDbAccess.GetExportSnippetsObjectIsReferenced(curDeletedEventId); + if(referencedInSnippets.Count > 0) + { + List references = await _exportSnippetRelatedObjectNameResolver.ResolveExportSnippetReferences(referencedInSnippets, true, true, true); + string usedInDailyRoutines = string.Join(", ", references.Select(m => string.Format("{0} ({1})", m.ObjectName, m.ExportSnippet))); + return _localizer["CanNotDeleteDailyRoutineEventUsedInExportSnippet", FormatDailyRoutineEventTime(loadedFlexFieldObject.DailyRoutine, curDeletedEventId), usedInDailyRoutines].Value; } } return string.Empty; } + /// + /// Formats the daily routine event time + /// + /// Daily routines + /// Event Id + /// Formatted Routine Event + private string FormatDailyRoutineEventTime(List dailyRoutines, string deletedEventId) + { + KortistoNpcDailyRoutineEvent dailyRoutineEvent = dailyRoutines.FirstOrDefault(d => d.EventId == deletedEventId); + if(dailyRoutineEvent == null) + { + return string.Empty; + } + + string timeFormat = _localizer["TimeFormat"].Value; + if(dailyRoutineEvent.EarliestTime.Hours == dailyRoutineEvent.LatestTime.Hours && dailyRoutineEvent.EarliestTime.Minutes == dailyRoutineEvent.LatestTime.Minutes) + { + return dailyRoutineEvent.EarliestTime.ToString(timeFormat); + } + + string earliestTime = dailyRoutineEvent.EarliestTime.ToString(timeFormat); + string latestTime = dailyRoutineEvent.LatestTime.ToString(timeFormat); + return string.Format("{0} - {1}", earliestTime, latestTime); + } + /// /// Runs additional updates on a flex field object /// @@ -428,8 +487,7 @@ protected override async Task RunAdditionalUpdates(KortistoNpc flex { if(flexFieldObject.IsPlayerNpc && loadedFlexFieldObject.IsPlayerNpc != flexFieldObject.IsPlayerNpc) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); - await ((IKortistoNpcDbAccess)_objectDbAccess).ResetPlayerFlagForAllNpcs(project.Id); + await ((IKortistoNpcDbAccess)_objectDbAccess).ResetPlayerFlagForAllNpcs(loadedFlexFieldObject.ProjectId); } loadedFlexFieldObject.IsPlayerNpc = flexFieldObject.IsPlayerNpc; } @@ -594,7 +652,7 @@ private async Task SaveNpcAfterEventUpdate(KortistoNpc npc) await this.SetModifiedData(_userManager, npc); await SetNotImplementedFlagOnChange(npc); await _objectDbAccess.UpdateFlexFieldObject(npc); - await _timelineService.AddTimelineEntry(ObjectUpdatedEvent, npc.Name, npc.Id); + await _timelineService.AddTimelineEntry(npc.ProjectId, ObjectUpdatedEvent, npc.Name, npc.Id); } @@ -606,7 +664,7 @@ private async Task SaveNpcAfterEventUpdate(KortistoNpc npc) [HttpGet] public async Task GetNpcsWithDailyRoutineOutsideTimeRange() { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); MiscProjectConfig miscConfig = await _projectConfigProvider.GetMiscConfig(defaultProject.Id); List npcs = await ((IKortistoNpcDbAccess)_objectDbAccess).GetNpcsWithDailyRoutineAfterTime(miscConfig.HoursPerDay, miscConfig.MinutesPerHour); @@ -635,7 +693,7 @@ public async Task GetNpcsObjectIsReferencedInDailyRoutine(string [HttpGet] public async Task PlayerNpc() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); KortistoNpc npc = await ((IKortistoNpcDbAccess)_objectDbAccess).GetPlayerNpc(project.Id); return Ok(npc); } @@ -679,7 +737,7 @@ public async Task GetNpcsByLearnedSkill(string skillId) [HttpGet] public async Task GetNotImplementedNpcs(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _objectDbAccess.GetNotImplementedFlexFieldObjects(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); diff --git a/Controllers/Api/LockServiceApiController.cs b/Controllers/Api/LockServiceApiController.cs index 321f802a..68f91f38 100644 --- a/Controllers/Api/LockServiceApiController.cs +++ b/Controllers/Api/LockServiceApiController.cs @@ -1,11 +1,15 @@ using System; using System.Threading.Tasks; +using GoNorth.Config; using GoNorth.Data.LockService; +using GoNorth.Data.Project; using GoNorth.Data.User; +using GoNorth.Services.Project; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; namespace GoNorth.Controllers.Api { @@ -41,27 +45,36 @@ public class LockResponse /// /// Timespan for the lock /// - private const int LockTimespan = 2; + private readonly int LockTimespan = 2; /// /// User Manager /// - private UserManager _userManager; + private readonly UserManager _userManager; /// /// Lock Service Db Access /// - private ILockServiceDbAccess _lockServiceDbAccess; + private readonly ILockServiceDbAccess _lockServiceDbAccess; + + /// + /// User project access + /// + private readonly IUserProjectAccess _userProjectAccess; /// /// Constructor /// /// User Manager /// Lock Service Db Access - public LockServiceApiController(UserManager userManager, ILockServiceDbAccess lockServiceDbAccess) + /// User project access + /// Configuration data + public LockServiceApiController(UserManager userManager, ILockServiceDbAccess lockServiceDbAccess, IUserProjectAccess userProjectAccess, IOptions configuration) { _userManager = userManager; _lockServiceDbAccess = lockServiceDbAccess; + _userProjectAccess = userProjectAccess; + LockTimespan = configuration.Value.Misc.ResourceLockTimespan.HasValue ? configuration.Value.Misc.ResourceLockTimespan.Value : Constants.DefaultResourceLockTimespan; } /// @@ -69,13 +82,14 @@ public LockServiceApiController(UserManager userManager, ILockServi /// /// Category of the lock /// Id of the resource + /// True if the project id must be appended to the key /// Lock Result [ProducesResponseType(typeof(LockResponse), StatusCodes.Status200OK)] [HttpPost] [ValidateAntiForgeryToken] - public async Task AcquireLock(string category, string id) + public async Task AcquireLock(string category, string id, bool appendProjectIdToKey = false) { - return await CheckLockInternal(category, id, true); + return await CheckLockInternal(category, id, true, appendProjectIdToKey); } /// @@ -83,12 +97,13 @@ public async Task AcquireLock(string category, string id) /// /// Category of the lock /// Id of the resource + /// True if the project id must be appended to the key /// Lock Result [ProducesResponseType(typeof(LockResponse), StatusCodes.Status200OK)] [HttpGet] - public async Task CheckLock(string category, string id) + public async Task CheckLock(string category, string id, bool appendProjectIdToKey = false) { - return await CheckLockInternal(category, id, false); + return await CheckLockInternal(category, id, false, appendProjectIdToKey); } /// @@ -97,9 +112,12 @@ public async Task CheckLock(string category, string id) /// Category of the lock /// Id of the resource /// true if the resource should be locked if its free + /// True if the project id must be appended to the key /// Lock Response - private async Task CheckLockInternal(string category, string id, bool lockIfFree) + private async Task CheckLockInternal(string category, string id, bool lockIfFree, bool appendProjectIdToKey) { + id = await AppendProjectIdIfRequired(id, appendProjectIdToKey); + GoNorthUser currentUser = await _userManager.GetUserAsync(User); LockResponse response = new LockResponse(); @@ -125,5 +143,46 @@ private async Task CheckLockInternal(string category, string id, return Ok(response); } + + /// + /// Deletes a lock for a resource + /// + /// Category of the lock + /// Id of the resource + /// True if the project id must be appended to the key + /// Result + [ProducesResponseType(StatusCodes.Status200OK)] + [HttpPost] + public async Task DeleteLock(string category, string id, bool appendProjectIdToKey = false) + { + id = await AppendProjectIdIfRequired(id, appendProjectIdToKey); + + GoNorthUser currentUser = await _userManager.GetUserAsync(User); + + LockEntry existingLock = await _lockServiceDbAccess.GetResourceLockEntry(category, id); + if (existingLock != null && existingLock.UserId == currentUser.Id) + { + await _lockServiceDbAccess.DeleteLockById(existingLock.Id); + } + + return Ok(); + } + + /// + /// Appends the project id to the lock id if required + /// + /// Id of the lock + /// True if the project id musit be appended + /// Updated id + private async Task AppendProjectIdIfRequired(string id, bool appendProjectIdToKey) + { + if (appendProjectIdToKey) + { + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); + id += "|" + defaultProject.Id; + } + + return id; + } } } \ No newline at end of file diff --git a/Controllers/Api/PersonalDataApiController.cs b/Controllers/Api/PersonalDataApiController.cs index e8d736ad..a4ccaf59 100644 --- a/Controllers/Api/PersonalDataApiController.cs +++ b/Controllers/Api/PersonalDataApiController.cs @@ -208,6 +208,12 @@ public class PersonalDataResponse /// Lock Entries /// public List LockEntries { get; set; } + + /// + /// Selected project of the user + /// + /// + public UserSelectedProject SelectedProject { get; set; } } /// @@ -873,6 +879,8 @@ private async Task FillModifiedData(PersonalDataResponse response, GoNorthUser c Name = p.Name, ModifiedDate = p.ModifiedOn })); + + response.SelectedProject = await _projectDbAccess.GetUserSelectedProject(currentUser.Id); } /// diff --git a/Controllers/Api/ProjectApiController.cs b/Controllers/Api/ProjectApiController.cs index f50b0e76..c5be4e78 100644 --- a/Controllers/Api/ProjectApiController.cs +++ b/Controllers/Api/ProjectApiController.cs @@ -13,9 +13,11 @@ using GoNorth.Data.ProjectConfig; using GoNorth.Data.Styr; using GoNorth.Data.TaskManagement; +using GoNorth.Data.User; using GoNorth.Services.Timeline; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; @@ -26,7 +28,7 @@ namespace GoNorth.Controllers.Api /// Project Api controller /// [ApiController] - [Authorize(Roles = RoleNames.Administrator)] + [Authorize] [Route("/api/[controller]/[action]")] public class ProjectApiController : ControllerBase { @@ -120,6 +122,11 @@ public class ProjectApiController : ControllerBase /// private readonly IProjectConfigDbAccess _projectConfigDbAccess; + /// + /// User Manager + /// + private readonly UserManager _userManager; + /// /// Timeline Service /// @@ -156,13 +163,14 @@ public class ProjectApiController : ControllerBase /// Export Template Db Access /// Include export template Db Access /// Project Config Db Access + /// User Manager /// Timeline Service /// Logger /// Localizer Factory public ProjectApiController(IProjectDbAccess projectDbAccess, IKortistoFolderDbAccess kortistoFolderDbAccess, IKortistoNpcDbAccess npcDbAccess, IStyrFolderDbAccess styrFolderDbAccess, IStyrItemDbAccess itemDbAccess, IEvneFolderDbAccess evneFolderDbAccess, IEvneSkillDbAccess skillDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IAikaChapterDetailDbAccess chapterDetailDbAccess, IAikaQuestDbAccess questDbAccess, IKartaMapDbAccess mapDbAccess, ITaskBoardDbAccess taskBoardDbAccess, ITaskNumberDbAccess taskNumberDbAccess, IUserTaskBoardHistoryDbAccess userTaskBoardHistoryDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IIncludeExportTemplateDbAccess includeExportTemplateDbAccess, IProjectConfigDbAccess projectConfigDbAccess, - ITimelineService timelineService, ILogger logger,IStringLocalizerFactory localizerFactory) + UserManager userManager, ITimelineService timelineService, ILogger logger, IStringLocalizerFactory localizerFactory) { _projectDbAccess = projectDbAccess; _kortistoFolderDbAccess = kortistoFolderDbAccess; @@ -182,6 +190,7 @@ public class ProjectApiController : ControllerBase _exportTemplateDbAccess = exportTemplateDbAccess; _includeExportTemplateDbAccess = includeExportTemplateDbAccess; _projectConfigDbAccess = projectConfigDbAccess; + _userManager = userManager; _timelineService = timelineService; _logger = logger; _localizer = localizerFactory.Create(typeof(ProjectApiController)); @@ -199,12 +208,35 @@ public async Task Entries() return Ok(projects); } + + /// + /// Returns all project entries + /// + /// Project Entries + [ValidateAntiForgeryToken] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpPost] + public async Task SetUserSelectedProject(string projectId) + { + GoNorthProject project = await _projectDbAccess.GetProjectById(projectId); + if(project == null) + { + return NotFound(); + } + + string userId = _userManager.GetUserId(this.User); + await _projectDbAccess.SetUserSelectedProject(userId, project.Id); + + return Ok(); + } /// /// Creates a new project /// /// Project to create /// Result + [Authorize(Roles = RoleNames.Administrator)] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [HttpPost] @@ -219,7 +251,7 @@ public async Task CreateProject([FromBody]GoNorthProject project) try { project = await _projectDbAccess.CreateProject(project); - await _timelineService.AddTimelineEntry(TimelineEvent.ProjectCreated, project.Name); + await _timelineService.AddTimelineEntry(null, TimelineEvent.ProjectCreated, project.Name); return Ok(project.Id); } catch(Exception ex) @@ -234,6 +266,7 @@ public async Task CreateProject([FromBody]GoNorthProject project) /// /// Id of the project /// Result Status Code + [Authorize(Roles = RoleNames.Administrator)] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [HttpDelete] @@ -259,7 +292,7 @@ public async Task DeleteProject(string id) await CleanUpAdditionalProjectData(project); _logger.LogInformation("Additional project data was deleted."); - await _timelineService.AddTimelineEntry(TimelineEvent.ProjectDeleted, project.Name); + await _timelineService.AddTimelineEntry(null, TimelineEvent.ProjectDeleted, project.Name); return Ok(id); } @@ -371,6 +404,7 @@ private async Task CleanUpAdditionalProjectData(GoNorthProject project) /// Project Id /// Update project data /// Result Status Code + [Authorize(Roles = RoleNames.Administrator)] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [HttpPost] [ValidateAntiForgeryToken] @@ -383,7 +417,7 @@ public async Task UpdateProject(string id, [FromBody]GoNorthProje await _projectDbAccess.UpdateProject(loadedProject); _logger.LogInformation("Project was updated."); - await _timelineService.AddTimelineEntry(TimelineEvent.ProjectUpdated, project.Name); + await _timelineService.AddTimelineEntry(null, TimelineEvent.ProjectUpdated, project.Name); return Ok(id); } diff --git a/Controllers/Api/ProjectConfigApiController.cs b/Controllers/Api/ProjectConfigApiController.cs index dd9b5ac6..c1020b44 100644 --- a/Controllers/Api/ProjectConfigApiController.cs +++ b/Controllers/Api/ProjectConfigApiController.cs @@ -4,6 +4,7 @@ using GoNorth.Data.ProjectConfig; using GoNorth.Data.User; using GoNorth.Extensions; +using GoNorth.Services.Project; using GoNorth.Services.ProjectConfig; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -48,9 +49,9 @@ public class TrimmedMiscConfig private readonly IProjectConfigDbAccess _projectConfigDbAccess; /// - /// Project Db Service + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// User Manager @@ -62,13 +63,13 @@ public class TrimmedMiscConfig /// /// Project config provider /// Project config Db Access - /// Project Db Access + /// User project access /// User Manager - public ProjectConfigApiController(IProjectConfigProvider projectConfigProvider, IProjectConfigDbAccess projectConfigDbAccess, IProjectDbAccess projectDbAccess, UserManager userManager) + public ProjectConfigApiController(IProjectConfigProvider projectConfigProvider, IProjectConfigDbAccess projectConfigDbAccess, IUserProjectAccess userProjectAccess, UserManager userManager) { _projectConfigProvider = projectConfigProvider; _projectConfigDbAccess = projectConfigDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _userManager = userManager; } @@ -81,7 +82,7 @@ public ProjectConfigApiController(IProjectConfigProvider projectConfigProvider, [HttpGet] public async Task GetJsonConfigByKey(string configKey) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); JsonConfigEntry configEntry = await _projectConfigDbAccess.GetJsonConfigByKey(project.Id, configKey); if(configEntry != null) { @@ -109,7 +110,7 @@ public async Task SaveJsonConfigByKey(string configKey) configData = await reader.ReadToEndAsync(); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); JsonConfigEntry configEntry = await _projectConfigDbAccess.GetJsonConfigByKey(project.Id, configKey); if(configEntry != null) { @@ -142,7 +143,7 @@ public async Task SaveJsonConfigByKey(string configKey) [HttpGet] public async Task GetMiscConfig() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); MiscProjectConfig configEntry = await _projectConfigProvider.GetMiscConfig(project.Id); return Ok(StripMiscConfig(configEntry)); } @@ -177,7 +178,7 @@ public async Task SaveMiscConfig([FromBody]TrimmedMiscConfig conf return BadRequest(); } - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); MiscProjectConfig configEntry = await _projectConfigDbAccess.GetMiscConfig(project.Id); if(configEntry != null) { diff --git a/Controllers/Api/StyrApiController.cs b/Controllers/Api/StyrApiController.cs index c9de2ac3..3f9057ae 100644 --- a/Controllers/Api/StyrApiController.cs +++ b/Controllers/Api/StyrApiController.cs @@ -23,6 +23,9 @@ using Microsoft.AspNetCore.Http; using System.Globalization; using GoNorth.Services.CsvHandling; +using GoNorth.Services.Project; +using GoNorth.Services.Export.ExportSnippets; +using GoNorth.Data.Evne; namespace GoNorth.Controllers.Api { @@ -128,6 +131,11 @@ public class StyrApiController : FlexFieldBaseApiController /// private readonly IAikaQuestDbAccess _aikaQuestDbAccess; + /// + /// Skill DB Access + /// + private readonly IEvneSkillDbAccess _skillDbAccess; + /// /// Tale DB Access /// @@ -154,7 +162,6 @@ public class StyrApiController : FlexFieldBaseApiController /// Folder Db Access /// Template Db Access /// Item Db Access - /// User Db Access /// Tag Db Access /// Export Template Db Access /// Import field values log Db Access @@ -162,13 +169,16 @@ public class StyrApiController : FlexFieldBaseApiController /// Export Function Id Db Access /// Object export snippet Db Access /// Object export snippet snapshot Db Access + /// Service that will resolve export snippet related object names /// Item Image Access /// Thumbnail Service /// Aika Quest Db Access /// Tale Db Access + /// Skill Db Access /// Kirja Page Db Access /// Karta Map Db Access /// Kortisto Npc Db Access + /// User Project Access /// CSV Generator /// CSV Reader /// User Manager @@ -177,14 +187,15 @@ public class StyrApiController : FlexFieldBaseApiController /// Xss Checker /// Logger /// Localizer Factory - public StyrApiController(IStyrFolderDbAccess folderDbAccess, IStyrItemTemplateDbAccess templateDbAccess, IStyrItemDbAccess itemDbAccess, IProjectDbAccess projectDbAccess, IStyrItemTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IStyrImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, - ILanguageKeyDbAccess languageKeyDbAccess, IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IStyrItemImageAccess imageAccess, - IStyrThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKartaMapDbAccess kartaMapDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, ICsvGenerator csvGenerator, - ICsvParser csvReader, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) - : base(folderDbAccess, templateDbAccess, itemDbAccess, projectDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, imageAccess, thumbnailService, csvGenerator, - csvReader, userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) + public StyrApiController(IStyrFolderDbAccess folderDbAccess, IStyrItemTemplateDbAccess templateDbAccess, IStyrItemDbAccess itemDbAccess, IStyrItemTagDbAccess tagDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IStyrImportFieldValuesLogDbAccess importFieldValuesLogDbAccess, + ILanguageKeyDbAccess languageKeyDbAccess, IExportFunctionIdDbAccess exportFunctionIdDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IExportSnippetRelatedObjectNameResolver exportSnippetRelatedObjectNameResolver, + IStyrItemImageAccess imageAccess, IStyrThumbnailService thumbnailService, IAikaQuestDbAccess aikaQuestDbAccess, IEvneSkillDbAccess skillDbAccess, ITaleDbAccess taleDbAccess, IKirjaPageDbAccess kirjaPageDbAccess, IKartaMapDbAccess kartaMapDbAccess, IKortistoNpcDbAccess kortistoNpcDbAccess, IUserProjectAccess userProjectAccess, + ICsvGenerator csvGenerator, ICsvParser csvReader, UserManager userManager, IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) + : base(folderDbAccess, templateDbAccess, itemDbAccess, tagDbAccess, exportTemplateDbAccess, importFieldValuesLogDbAccess, languageKeyDbAccess, exportFunctionIdDbAccess, objectExportSnippetDbAccess, objectExportSnippetSnapshotDbAccess, exportSnippetRelatedObjectNameResolver, userProjectAccess, imageAccess, + thumbnailService, csvGenerator, csvReader, userManager, implementationStatusComparer, timelineService, xssChecker, logger, localizerFactory) { _aikaQuestDbAccess = aikaQuestDbAccess; + _skillDbAccess = skillDbAccess; _taleDbAccess = taleDbAccess; _kirjaPageDbAccess = kirjaPageDbAccess; _kartaMapDbAccess = kartaMapDbAccess; @@ -314,6 +325,13 @@ protected override async Task CheckObjectReferences(string id) return _localizer["CanNotDeleteItemUsedInDailyRoutine", usedInDailyRoutines].Value; } + List referencedInSkills = await _skillDbAccess.GetSkillsObjectIsReferencedIn(id); + if(referencedInSkills.Count > 0) + { + string referencedInSkillsString = string.Join(", ", referencedInSkills.Select(n => n.Name)); + return _localizer["CanNotDeleteItemUsedInSkill", referencedInSkillsString].Value; + } + return string.Empty; } @@ -393,7 +411,7 @@ protected override async Task CompareObjectWithImplementationSnap [HttpGet] public async Task GetNotImplementedItems(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _objectDbAccess.GetNotImplementedFlexFieldObjects(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); diff --git a/Controllers/Api/TaleApiController.cs b/Controllers/Api/TaleApiController.cs index 213e6d82..774e5d0c 100644 --- a/Controllers/Api/TaleApiController.cs +++ b/Controllers/Api/TaleApiController.cs @@ -14,6 +14,8 @@ using System.Linq; using GoNorth.Services.ImplementationStatusCompare; using Microsoft.AspNetCore.Http; +using GoNorth.Services.Project; +using GoNorth.Services.ReferenceAnalyzer; namespace GoNorth.Controllers.Api { @@ -90,15 +92,20 @@ public class DialogImplementedResponse private readonly IKortistoNpcDbAccess _npcDbAccess; /// - /// Project Db Service + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Implementation status comparer /// private readonly IImplementationStatusComparer _implementationStatusComparer; + /// + /// Interface to analyze references + /// + private readonly IReferenceAnalyzer _referenceAnalyzer; + /// /// Timeline Service /// @@ -119,19 +126,21 @@ public class DialogImplementedResponse /// /// Tale Db Access /// Npc Db Access - /// Project Db Access + /// User project access /// User Manager /// Implementation status comparer + /// Reference analyzer /// Timeline Service /// Logger - public TaleApiController(ITaleDbAccess taleDbAccess, IKortistoNpcDbAccess npcDbAccess, IProjectDbAccess projectDbAccess, UserManager userManager, - IImplementationStatusComparer implementationStatusComparer, ITimelineService timelineService, ILogger logger) + public TaleApiController(ITaleDbAccess taleDbAccess, IKortistoNpcDbAccess npcDbAccess, IUserProjectAccess userProjectAccess, UserManager userManager, + IImplementationStatusComparer implementationStatusComparer, IReferenceAnalyzer referenceAnalyzer, ITimelineService timelineService, ILogger logger) { _taleDbAccess = taleDbAccess; _npcDbAccess = npcDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _userManager = userManager; _implementationStatusComparer = implementationStatusComparer; + _referenceAnalyzer = referenceAnalyzer; _timelineService = timelineService; _logger = logger; } @@ -177,12 +186,21 @@ public async Task IsDialogImplementedByRelatedObjectId(string rel /// /// Object id /// Dialogs - [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [HttpGet] public async Task GetDialogsObjectIsReferenced(string objectId) { List dialogs = await _taleDbAccess.GetDialogsObjectIsReferenced(objectId); - return Ok(dialogs); + List npcs = await _npcDbAccess.ResolveFlexFieldObjectNames(dialogs.Select(d => d.RelatedObjectId).ToList()); + Dictionary npcNames = npcs.ToDictionary(n => n.Id, n => n.Name); + List objectReferences = dialogs.Select(d => { + if(!npcNames.ContainsKey(d.RelatedObjectId)) + { + return null; + } + return _referenceAnalyzer.BuildObjectReferences(objectId, d.RelatedObjectId, npcNames[d.RelatedObjectId], d.Action, d.Condition, d.Reference, d.Choice); + }).Where(o => o != null).ToList(); + return Ok(objectReferences); } /// @@ -210,25 +228,26 @@ public async Task SaveDialog(string relatedObjectId, [FromBody]Ta } string npcName = npcNames[0].Name; - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); - // Update or create dialog TaleDialog existingDialog = await _taleDbAccess.GetDialogByRelatedObjectId(relatedObjectId); bool isCreate = false; if(existingDialog == null) { + KortistoNpc npc = await _npcDbAccess.GetFlexFieldObjectById(relatedObjectId); + existingDialog = new TaleDialog(); existingDialog.RelatedObjectId = relatedObjectId; + existingDialog.ProjectId = npc.ProjectId; isCreate = true; } - existingDialog.ProjectId = project.Id; existingDialog.Link = dialog.Link != null ? dialog.Link : new List(); existingDialog.PlayerText = dialog.PlayerText != null ? dialog.PlayerText : new List(); existingDialog.NpcText = dialog.NpcText != null ? dialog.NpcText : new List(); existingDialog.Choice = dialog.Choice != null ? dialog.Choice : new List(); existingDialog.Action = dialog.Action != null ? dialog.Action : new List(); existingDialog.Condition = dialog.Condition != null ? dialog.Condition : new List(); + existingDialog.Reference = dialog.Reference != null ? dialog.Reference : new List(); await this.SetModifiedData(_userManager, existingDialog); @@ -236,7 +255,7 @@ public async Task SaveDialog(string relatedObjectId, [FromBody]Ta if(isCreate) { existingDialog = await _taleDbAccess.CreateDialog(existingDialog); - await _timelineService.AddTimelineEntry(TimelineEvent.TaleDialogCreated, relatedObjectId, npcName); + await _timelineService.AddTimelineEntry(existingDialog.ProjectId, TimelineEvent.TaleDialogCreated, relatedObjectId, npcName); } else { @@ -251,7 +270,7 @@ public async Task SaveDialog(string relatedObjectId, [FromBody]Ta } await _taleDbAccess.UpdateDialog(existingDialog); - await _timelineService.AddTimelineEntry(TimelineEvent.TaleDialogUpdated, relatedObjectId, npcName); + await _timelineService.AddTimelineEntry(existingDialog.ProjectId, TimelineEvent.TaleDialogUpdated, relatedObjectId, npcName); } return Ok(existingDialog); @@ -270,7 +289,7 @@ public async Task SaveDialog(string relatedObjectId, [FromBody]Ta [HttpGet] public async Task GetNotImplementedDialogs(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _taleDbAccess.GetNotImplementedDialogs(project.Id, start, pageSize); diff --git a/Controllers/Api/TaskApiController.cs b/Controllers/Api/TaskApiController.cs index 1e26fd22..3944eddc 100644 --- a/Controllers/Api/TaskApiController.cs +++ b/Controllers/Api/TaskApiController.cs @@ -18,6 +18,7 @@ using GoNorth.Services.TaskManagement; using GoNorth.Services.Security; using System.Globalization; +using GoNorth.Services.Project; namespace GoNorth.Controllers.Api { @@ -77,9 +78,9 @@ public class TaskBoardQueryResult private readonly IUserTaskBoardHistoryDbAccess _userTaskBoardHistoryDbAccess; /// - /// Project Db Access + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Task Image Access @@ -130,7 +131,7 @@ public class TaskBoardQueryResult /// Task Board category Db Access /// Task Number Db Access /// User Task Board History Db Access - /// Project Db Access + /// User project access /// Task Image Access /// Task Image Parser /// Task type default provider @@ -140,7 +141,7 @@ public class TaskBoardQueryResult /// Logger /// Localizer Factory public TaskApiController(ITaskBoardDbAccess taskBoardDbAccess, ITaskGroupTypeDbAccess taskGroupTypeDbAccess, ITaskTypeDbAccess taskTypeDbAccess, ITaskBoardCategoryDbAccess taskBoardCategoryDbAccess, ITaskNumberDbAccess taskNumberDbAccess, - IUserTaskBoardHistoryDbAccess userTaskBoardHistoryDbAccess, IProjectDbAccess projectDbAccess, ITaskImageAccess taskImageAccess, ITaskImageParser taskImageParser, ITaskTypeDefaultProvider taskTypeDefaultProvider, + IUserTaskBoardHistoryDbAccess userTaskBoardHistoryDbAccess, IUserProjectAccess userProjectAccess, ITaskImageAccess taskImageAccess, ITaskImageParser taskImageParser, ITaskTypeDefaultProvider taskTypeDefaultProvider, UserManager userManager, ITimelineService timelineService, IXssChecker xssChecker, ILogger logger, IStringLocalizerFactory localizerFactory) { _taskBoardDbAccess = taskBoardDbAccess; @@ -149,7 +150,7 @@ public class TaskBoardQueryResult _taskBoardCategoryDbAccess = taskBoardCategoryDbAccess; _taskNumberDbAccess = taskNumberDbAccess; _userTaskBoardHistoryDbAccess = userTaskBoardHistoryDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _taskImageAccess = taskImageAccess; _taskImageParser = taskImageParser; _taskTypeDefaultProvider = taskTypeDefaultProvider; @@ -183,7 +184,7 @@ public async Task GetTaskBoard(string id) [HttpGet] public async Task GetOpenTaskBoards(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _taskBoardDbAccess.GetOpenTaskBoards(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -206,7 +207,7 @@ public async Task GetOpenTaskBoards(int start, int pageSize) [HttpGet] public async Task GetClosedTaskBoards(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); Task> queryTask; Task countTask; queryTask = _taskBoardDbAccess.GetClosedTaskBoards(project.Id, start, pageSize, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); @@ -249,7 +250,7 @@ public async Task CreateTaskBoard([FromBody]TaskBoard board) await this.SetModifiedData(_userManager, newBoard); - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); newBoard.ProjectId = project.Id; try @@ -265,7 +266,7 @@ public async Task CreateTaskBoard([FromBody]TaskBoard board) // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardCreated, newBoard.Id, newBoard.Name); + await _timelineService.AddTimelineEntry(newBoard.ProjectId, TimelineEvent.TaskBoardCreated, newBoard.Id, newBoard.Name); } catch(Exception ex) { @@ -322,7 +323,7 @@ public async Task UpdateTaskBoard(string id, [FromBody]TaskBoard } // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskBoardUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name); return Ok(updatedTaskBoard.Id); } @@ -374,7 +375,7 @@ public async Task SetTaskBoardStatus(string id, bool closed) { timelineEvent = TimelineEvent.TaskBoardReopened; } - await _timelineService.AddTimelineEntry(timelineEvent, updatedTaskBoard.Id, updatedTaskBoard.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, timelineEvent, updatedTaskBoard.Id, updatedTaskBoard.Name); return Ok(updatedTaskBoard.Id); } @@ -422,7 +423,7 @@ public async Task DeleteTaskBoard(string id) } // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardDeleted, updatedTaskBoard.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskBoardDeleted, updatedTaskBoard.Name); return Ok(id); } @@ -489,7 +490,7 @@ public async Task CreateTaskGroup(string boardId, [FromBody]TaskG // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskGroupCreated, updatedTaskBoard.Id, updatedTaskBoard.Name, newGroup.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskGroupCreated, updatedTaskBoard.Id, updatedTaskBoard.Name, newGroup.Name); } catch(Exception ex) { @@ -572,7 +573,7 @@ public async Task UpdateTaskGroup(string boardId, string groupId, // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskGroupUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskGroupUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name); } catch(Exception ex) { @@ -642,7 +643,7 @@ public async Task MoveTaskGroupToBoard(string sourceBoardId, stri // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskGroupMoved, targetBoard.Id, targetBoard.Name, moveGroup.Name); + await _timelineService.AddTimelineEntry(sourceBoard.ProjectId, TimelineEvent.TaskGroupMoved, targetBoard.Id, targetBoard.Name, moveGroup.Name); } catch(Exception ex) { @@ -704,7 +705,7 @@ public async Task ReorderTaskGroup(string boardId, string groupId // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskGroupUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskGroupUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name); } catch(Exception ex) { @@ -782,7 +783,7 @@ public async Task DeleteTaskGroup(string boardId, string groupId) // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskGroupDeleted, taskBoard.Id, taskBoard.Name, deletedGroup.Name); + await _timelineService.AddTimelineEntry(taskBoard.ProjectId, TimelineEvent.TaskGroupDeleted, taskBoard.Id, taskBoard.Name, deletedGroup.Name); } catch(Exception ex) { @@ -862,7 +863,7 @@ public async Task CreateTask(string boardId, string groupId, [Fro // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskCreated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name, newTask.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskCreated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name, newTask.Name); } catch(Exception ex) { @@ -1019,7 +1020,7 @@ public async Task UpdateTask(string boardId, string groupId, stri // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name, updatedTask.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoard.ProjectId, TimelineEvent.TaskUpdated, updatedTaskBoard.Id, updatedTaskBoard.Name, updatedGroup.Name, updatedTask.Name); } catch(Exception ex) { @@ -1103,7 +1104,7 @@ public async Task MoveTaskToBoard(string sourceBoardId, string so // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskMoved, targetBoard.Id, targetBoard.Name, targetGroup.Name, moveTask.Name); + await _timelineService.AddTimelineEntry(sourceBoard.ProjectId, TimelineEvent.TaskMoved, targetBoard.Id, targetBoard.Name, targetGroup.Name, moveTask.Name); } catch(Exception ex) { @@ -1183,7 +1184,7 @@ public async Task DeleteTask(string boardId, string groupId, stri // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskDeleted, taskBoard.Id, taskBoard.Name, taskGroup.Name, deleteTask.Name); + await _timelineService.AddTimelineEntry(taskBoard.ProjectId, TimelineEvent.TaskDeleted, taskBoard.Id, taskBoard.Name, taskGroup.Name, deleteTask.Name); } catch(Exception ex) { @@ -1284,7 +1285,7 @@ private void DeleteUnusedImages(List newImages, List oldImages) [HttpGet] public async Task GetLastOpenedTaskBoard() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); string userId = _userManager.GetUserId(this.User); string boardId = await _userTaskBoardHistoryDbAccess.GetLastOpenBoardForUser(project.Id, userId); @@ -1301,7 +1302,7 @@ public async Task GetLastOpenedTaskBoard() [HttpPost] public async Task SetLastOpenedTaskBoard(string boardId) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); string userId = _userManager.GetUserId(this.User); await _userTaskBoardHistoryDbAccess.SetLastOpenBoardForUser(project.Id, userId, boardId); @@ -1318,7 +1319,7 @@ public async Task SetLastOpenedTaskBoard(string boardId) [HttpGet] public async Task GetTaskBoardCategories() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List categoeries = await _taskBoardCategoryDbAccess.GetTaskBoardCategories(project.Id); return Ok(categoeries); } @@ -1348,7 +1349,7 @@ public async Task CreateTaskBoardCategory([FromBody]TaskBoardCate await this.SetModifiedData(_userManager, newCategory); - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); newCategory.ProjectId = project.Id; try @@ -1364,7 +1365,7 @@ public async Task CreateTaskBoardCategory([FromBody]TaskBoardCate // Add Timeline entry try { - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardCategoryCreated, newCategory.Id, newCategory.Name); + await _timelineService.AddTimelineEntry(newCategory.ProjectId, TimelineEvent.TaskBoardCategoryCreated, newCategory.Id, newCategory.Name); } catch(Exception ex) { @@ -1419,7 +1420,7 @@ public async Task UpdateTaskBoardCategory(string id, [FromBody]Ta } // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardCategoryUpdated, updatedTaskBoardCategory.Id, updatedTaskBoardCategory.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoardCategory.ProjectId, TimelineEvent.TaskBoardCategoryUpdated, updatedTaskBoardCategory.Id, updatedTaskBoardCategory.Name); return Ok(updatedTaskBoardCategory.Id); } @@ -1485,7 +1486,7 @@ public async Task DeleteTaskBoardCategory(string id) } // Add Timeline entry - await _timelineService.AddTimelineEntry(TimelineEvent.TaskBoardCategoryDeleted, updatedTaskBoardCategory.Name); + await _timelineService.AddTimelineEntry(updatedTaskBoardCategory.ProjectId, TimelineEvent.TaskBoardCategoryDeleted, updatedTaskBoardCategory.Name); return Ok(id); } @@ -1499,7 +1500,7 @@ public async Task DeleteTaskBoardCategory(string id) /// Task Types private async Task GetTaskTypesFromDb(ITaskTypeBaseDbAccess dbSource, Func> defaultTaskTypeFunction) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); List taskTypes = await dbSource.GetTaskTypes(project.Id); if(taskTypes == null || !taskTypes.Any()) { @@ -1548,7 +1549,7 @@ private async Task ResetDefaultTaskTypeIfChanged(ITaskTypeBaseDbAccess dbTarget, if(project == null) { - project = await _projectDbAccess.GetDefaultProject(); + project = await _userProjectAccess.GetUserProject(); } GoNorthTaskType defaultTaskType = await dbTarget.GetDefaultTaskType(project.Id); @@ -1583,7 +1584,7 @@ private async Task CreateTaskTypeInDb(ITaskTypeBaseDbAccess dbTar await this.SetModifiedData(_userManager, newTaskType); - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); newTaskType.ProjectId = project.Id; try @@ -1609,7 +1610,7 @@ private async Task CreateTaskTypeInDb(ITaskTypeBaseDbAccess dbTar // Add Timeline entry try { - await _timelineService.AddTimelineEntry(timelineEvent, newTaskType.Id, newTaskType.Name); + await _timelineService.AddTimelineEntry(newTaskType.ProjectId, timelineEvent, newTaskType.Id, newTaskType.Name); } catch(Exception ex) { @@ -1700,7 +1701,7 @@ private async Task UpdateTaskTypeInDb(ITaskTypeBaseDbAccess dbTar } // Add Timeline entry - await _timelineService.AddTimelineEntry(timelineEvent, updatedTaskType.Id, updatedTaskType.Name); + await _timelineService.AddTimelineEntry(updatedTaskType.ProjectId, timelineEvent, updatedTaskType.Id, updatedTaskType.Name); return Ok(updatedTaskType.Id); } @@ -1816,7 +1817,7 @@ private async Task DeleteTaskTypeFromDb(ITaskTypeBaseDbAccess dbT } // Add Timeline entry - await _timelineService.AddTimelineEntry(timelineEvent, deleteTaskType.Name); + await _timelineService.AddTimelineEntry(deleteTaskType.ProjectId, timelineEvent, deleteTaskType.Name); return Ok(id); } @@ -1860,7 +1861,7 @@ public async Task DeleteTaskType(string id, string newTaskTypeId) [HttpGet] public async Task AnyTaskBoardHasTaskGroupsWithoutType() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); bool anyWithoutType = await _taskBoardDbAccess.AnyTaskBoardHasTaskGroupsWithoutType(project.Id); return Ok(anyWithoutType); } @@ -1874,7 +1875,7 @@ public async Task AnyTaskBoardHasTaskGroupsWithoutType() [HttpGet] public async Task AnyTaskBoardHasTasksWithoutType() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); bool anyWithoutType = await _taskBoardDbAccess.AnyTaskBoardHasTasksWithoutType(project.Id); return Ok(anyWithoutType); } diff --git a/Controllers/Api/UserApiController.cs b/Controllers/Api/UserApiController.cs index 9e900b12..aba0d0d1 100644 --- a/Controllers/Api/UserApiController.cs +++ b/Controllers/Api/UserApiController.cs @@ -196,7 +196,7 @@ public async Task CreateUser([FromBody]UserCreateRequest userRequ { _logger.LogInformation("User created a new account with password."); - await _timelineService.AddTimelineEntry(TimelineEvent.NewUser, user.Email); + await _timelineService.AddTimelineEntry(null, TimelineEvent.NewUser, user.Email); return Ok(user.Email); } @@ -230,7 +230,7 @@ public async Task DeleteUser(string id) { _logger.LogInformation("User was deleted."); - await _timelineService.AddTimelineEntry(TimelineEvent.UserDeleted, user.Email); + await _timelineService.AddTimelineEntry(null, TimelineEvent.UserDeleted, user.Email); return Ok(id); } else @@ -266,7 +266,7 @@ public async Task SetUserRoles(string id, [FromBody]List } _logger.LogInformation("User roles were set."); - await _timelineService.AddTimelineEntry(TimelineEvent.UserRolesSet, user.Email, string.Join(", ", roles)); + await _timelineService.AddTimelineEntry(null, TimelineEvent.UserRolesSet, user.Email, string.Join(", ", roles)); return Ok(id); } diff --git a/Controllers/Api/UserPreferencesApiController.cs b/Controllers/Api/UserPreferencesApiController.cs index 03c51278..ceb68d69 100644 --- a/Controllers/Api/UserPreferencesApiController.cs +++ b/Controllers/Api/UserPreferencesApiController.cs @@ -2,6 +2,7 @@ using GoNorth.Data.Exporting; using GoNorth.Data.Project; using GoNorth.Data.User; +using GoNorth.Services.Project; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; @@ -45,9 +46,9 @@ public class UserCodeEditorPreferences private readonly IExportSettingsDbAccess _exportSettingsDbAccess; /// - /// Project Db Access + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// User Manager @@ -64,15 +65,15 @@ public class UserCodeEditorPreferences /// /// User Preferences Db Access /// Export settings Db Access - /// Project Db Access + /// User project access /// User Manager /// Logger - public UserPreferencesApiController(IUserPreferencesDbAccess userPreferencesDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, IProjectDbAccess projectDbAccess, UserManager userManager, + public UserPreferencesApiController(IUserPreferencesDbAccess userPreferencesDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, IUserProjectAccess userProjectAccess, UserManager userManager, ILogger logger) { _userPreferencesDbAccess = userPreferencesDbAccess; _exportSettingsDbAccess = exportSettingsDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _userManager = userManager; _logger = logger; } @@ -119,7 +120,7 @@ public async Task GetCodeEditorPreferences() GoNorthUser currentUser = await _userManager.GetUserAsync(this.User); UserPreferences userPreferences = await _userPreferencesDbAccess.GetUserPreferences(currentUser.Id); - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _userProjectAccess.GetUserProject(); ExportSettings settings = await _exportSettingsDbAccess.GetExportSettings(defaultProject.Id); UserCodeEditorPreferences codeEditorPreferences = new UserCodeEditorPreferences(); diff --git a/Controllers/ExportController.cs b/Controllers/ExportController.cs index 4c03f5a3..e3b214f8 100644 --- a/Controllers/ExportController.cs +++ b/Controllers/ExportController.cs @@ -8,6 +8,7 @@ using GoNorth.Services.Export.Dialog; using GoNorth.Services.Export.Dialog.ActionRendering; using GoNorth.Services.Export.Dialog.ActionRendering.Localization; +using GoNorth.Services.Project; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -42,9 +43,9 @@ public class ExportController : Controller private readonly IExportSettingsDbAccess _exportSettings; /// - /// Project Db Access + /// User Project Access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Action translator @@ -58,16 +59,16 @@ public class ExportController : Controller /// User PReferences Database access /// User Manager /// Export settings - /// Project Db Access + /// User project Access /// Action translator - public ExportController(IExportDefaultTemplateProvider exportDefaultTemplateProvider, IUserPreferencesDbAccess userPreferencesDbAccess, UserManager userManager, IExportSettingsDbAccess exportSettings, IProjectDbAccess projectDbAccess, + public ExportController(IExportDefaultTemplateProvider exportDefaultTemplateProvider, IUserPreferencesDbAccess userPreferencesDbAccess, UserManager userManager, IExportSettingsDbAccess exportSettings, IUserProjectAccess userProjectAccess, IActionTranslator actionTranslator) { _exportDefaultTemplateProvider = exportDefaultTemplateProvider; _userPreferencesDbAccess = userPreferencesDbAccess; _userManager = userManager; _exportSettings = exportSettings; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _actionTranslator = actionTranslator; } @@ -142,7 +143,7 @@ public async Task ManageIncludeTemplate() /// View public async Task FunctionGenerationCondition() { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); FunctionGenerationConditionViewModel viewModel = new FunctionGenerationConditionViewModel(); viewModel.DialogFunctionGenerationActionTypes = Enum.GetValues(typeof(ActionType)).Cast().Select(s => new MappedDialogFunctionGenerationActionType { OriginalActionType = s, @@ -163,7 +164,7 @@ public async Task FunctionGenerationCondition() /// Script Language private async Task GetScriptLanguage(bool isLanguage) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportSettings exportSettings = await _exportSettings.GetExportSettings(project.Id); if(exportSettings != null) diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index a92c54eb..167516c9 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Authorization; using GoNorth.Data.Project; using GoNorth.Models.HomeViewModels; +using GoNorth.Services.Project; namespace GoNorth.Controllers { @@ -21,15 +22,15 @@ public class HomeController : Controller /// /// Project Db Access /// - private IProjectDbAccess _projectDbAccess; + private IUserProjectAccess _projectUserAccess; /// /// Constructor /// - /// Project Db Access - public HomeController(IProjectDbAccess projectDbAccess) + /// Project User Access + public HomeController(IUserProjectAccess projectUserAccess) { - _projectDbAccess = projectDbAccess; + _projectUserAccess = projectUserAccess; } /// @@ -38,7 +39,7 @@ public HomeController(IProjectDbAccess projectDbAccess) /// View public async Task Index() { - GoNorthProject defaultProject = await _projectDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _projectUserAccess.GetUserProject(); IndexViewModel viewModel = new IndexViewModel(); viewModel.ProjectName = defaultProject != null ? defaultProject.Name : ""; diff --git a/Data/Aika/AikaQuest.cs b/Data/Aika/AikaQuest.cs index f4f4b7cb..b24d680b 100644 --- a/Data/Aika/AikaQuest.cs +++ b/Data/Aika/AikaQuest.cs @@ -91,6 +91,12 @@ public class AikaQuest : IHasModifiedData, IImplementationComparable, IImplement [ListCompareAttribute(LabelKey = "NodeLinksChanged")] public List Link { get; set; } + /// + /// Reference nodes + /// + [ListCompareAttribute(LabelKey = "NodeReferenceChanged")] + public List Reference {get ; set; } + /// /// true if the object is implemented, else false diff --git a/Data/Aika/AikaQuestMongoDbAccess.cs b/Data/Aika/AikaQuestMongoDbAccess.cs index 843583cc..bcb78f19 100644 --- a/Data/Aika/AikaQuestMongoDbAccess.cs +++ b/Data/Aika/AikaQuestMongoDbAccess.cs @@ -196,10 +196,14 @@ public async Task GetNotImplementedQuestsCount(string projectId, string loc /// All Quests object is referenced in without detail information public async Task> GetQuestsObjectIsReferenced(string objectId) { - List quests = await _QuestCollection.AsQueryable().Where(q => q.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || q.Condition.Any(c => c.Conditions.Any(ce => ce.DependsOnObjects.Any(o => o.ObjectId == objectId)))).Select(q => new AikaQuest() { + List quests = await _QuestCollection.AsQueryable().Where(q => q.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || q.Condition.Any(c => c.Conditions.Any(ce => ce.DependsOnObjects.Any(o => o.ObjectId == objectId))) || + q.Reference.Any(a => a.ReferencedObjects.Any(r => r.ObjectId == objectId))).Select(q => new AikaQuest() { Id = q.Id, Name = q.Name, - IsMainQuest = q.IsMainQuest + IsMainQuest = q.IsMainQuest, + Action = q.Action, + Condition= q.Condition, + Reference = q.Reference }).ToListAsync(); quests = quests.OrderBy(q => q.Name).ToList(); diff --git a/Data/Evne/EvneSkill.cs b/Data/Evne/EvneSkill.cs index 5e65cb37..f9d61638 100644 --- a/Data/Evne/EvneSkill.cs +++ b/Data/Evne/EvneSkill.cs @@ -13,7 +13,6 @@ namespace GoNorth.Data.Evne /// public class EvneSkill : FlexFieldObject, IExportSnippetExportable, ICloneable { - /// /// Text Nodes /// @@ -32,6 +31,12 @@ public class EvneSkill : FlexFieldObject, IExportSnippetExportable, ICloneable [ListCompareAttribute(LabelKey = "NodeActionsChanged")] public List Action { get; set; } + /// + /// Reference nodes + /// + [ListCompareAttribute(LabelKey = "NodeReferenceChanged")] + public List Reference {get ; set; } + /// /// Node Links /// @@ -50,6 +55,7 @@ public object Clone() clonedSkill.Condition = Condition.Select(t => t.Clone()).Cast().ToList(); clonedSkill.Action = Action.Select(t => t.Clone()).Cast().ToList(); clonedSkill.Link = Link.Select(t => t.Clone()).Cast().ToList(); + clonedSkill.Reference = Reference != null ? Reference.Select(t => t.Clone()).Cast().ToList() : new List(); return clonedSkill; } diff --git a/Data/Evne/EvneSkillMongoDbAccess.cs b/Data/Evne/EvneSkillMongoDbAccess.cs index f6222b2f..b968b344 100644 --- a/Data/Evne/EvneSkillMongoDbAccess.cs +++ b/Data/Evne/EvneSkillMongoDbAccess.cs @@ -1,7 +1,5 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using System.Threading.Tasks; using GoNorth.Config; using GoNorth.Data.FlexFieldDatabase; @@ -34,5 +32,21 @@ public EvneSkillMongoDbAccess(IOptions configuration) : base( { } + /// + /// Returns all skills an object is referenced in + /// + /// Object Id + /// All kills the object is referenced in without detail information and the entrie with relatedobjectid = itself + public async Task> GetSkillsObjectIsReferencedIn(string objectId) + { + List skills = await _ObjectCollection.AsQueryable().Where(o => o.Id != objectId && (o.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || o.Condition.Any(c => c.Conditions.Any(co => co.DependsOnObjects.Any(doo => doo.ObjectId == objectId))) || + o.Reference.Any(a => a.ReferencedObjects.Any(r => r.ObjectId == objectId)))).Select(o => new EvneSkill { + Id = o.Id, + Name = o.Name + }).ToListAsync(); + + return skills; + } + } } \ No newline at end of file diff --git a/Data/Evne/IEvneSkillDbAccess.cs b/Data/Evne/IEvneSkillDbAccess.cs index 360b75a3..e9a8fb95 100644 --- a/Data/Evne/IEvneSkillDbAccess.cs +++ b/Data/Evne/IEvneSkillDbAccess.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Threading.Tasks; using GoNorth.Data.FlexFieldDatabase; namespace GoNorth.Data.Evne @@ -7,5 +9,11 @@ namespace GoNorth.Data.Evne /// public interface IEvneSkillDbAccess : IFlexFieldObjectDbAccess { + /// + /// Returns all skills an object is referenced in + /// + /// Object Id + /// All kills the object is referenced in without detail information and the entrie with relatedobjectid = itself + Task> GetSkillsObjectIsReferencedIn(string objectId); } } \ No newline at end of file diff --git a/Data/Exporting/ExportDefaultTemplateProvider.cs b/Data/Exporting/ExportDefaultTemplateProvider.cs index d1815c8c..8b727dfa 100644 --- a/Data/Exporting/ExportDefaultTemplateProvider.cs +++ b/Data/Exporting/ExportDefaultTemplateProvider.cs @@ -159,6 +159,8 @@ public DefaultTemplateEntry(TemplateCategory category, TemplateType templateType new DefaultTemplateEntry(TemplateCategory.Tale, TemplateType.TaleActionSpawnNpcAtMarker), new DefaultTemplateEntry(TemplateCategory.Tale, TemplateType.TaleActionSpawnItemAtMarker), new DefaultTemplateEntry(TemplateCategory.Tale, TemplateType.TaleActionChangeItemValue), + + new DefaultTemplateEntry(TemplateCategory.Tale, TemplateType.ReferenceNode), // General new DefaultTemplateEntry(TemplateCategory.General, TemplateType.GeneralLogicGroup), @@ -216,7 +218,7 @@ public async Task> GetDefaultTemplatesByCategory(string pro List templates = await _templateDbAccess.GetDefaultTemplatesByCategory(projectId, category); await FilterAndDeleteInvalidTemplates(templates); - await AddMissingDefaultTemplates(templates, category); + await AddMissingDefaultTemplates(projectId, templates, category); return templates; } @@ -233,7 +235,7 @@ public async Task GetDefaultTemplateByType(string projectId, Tem if(template == null) { DefaultTemplateEntry defaultTemplate = _DefaultTemplates.First(t => t.TemplateType == templateType); - template = await CreateDefaultTemplate(defaultTemplate.Category, defaultTemplate.TemplateType, true); + template = await CreateDefaultTemplate(projectId, defaultTemplate.Category, defaultTemplate.TemplateType, true); } return template; @@ -260,16 +262,17 @@ private async Task FilterAndDeleteInvalidTemplates(List template /// /// Adds missing default templates to a list of templates without loading the code /// + /// Project Id /// Loaded templates /// Category for which to add the entry /// Task - private async Task AddMissingDefaultTemplates(List templates, TemplateCategory category) + private async Task AddMissingDefaultTemplates(string projectId, List templates, TemplateCategory category) { foreach(DefaultTemplateEntry curDefaultTemplate in _DefaultTemplates) { if(curDefaultTemplate.Category == category && !templates.Any(t => t.TemplateType == curDefaultTemplate.TemplateType)) { - ExportTemplate defaultTemplate = await CreateDefaultTemplate(category, curDefaultTemplate.TemplateType, false); + ExportTemplate defaultTemplate = await CreateDefaultTemplate(projectId, category, curDefaultTemplate.TemplateType, false); templates.Add(defaultTemplate); } } @@ -278,14 +281,16 @@ private async Task AddMissingDefaultTemplates(List templates, Te /// /// Creates a default template /// + /// Project Id /// Category /// Template Type /// true if the code must be loaded, else false /// Default Template - private async Task CreateDefaultTemplate(TemplateCategory category, TemplateType templateType, bool loadCode) + private async Task CreateDefaultTemplate(string projectId, TemplateCategory category, TemplateType templateType, bool loadCode) { ExportTemplate defaultTemplate = new ExportTemplate(); defaultTemplate.Id = string.Empty; + defaultTemplate.ProjectId = projectId; defaultTemplate.CustomizedObjectId = string.Empty; defaultTemplate.Category = category; defaultTemplate.TemplateType = templateType; diff --git a/Data/Exporting/ExportTemplateMongoDbAccess.cs b/Data/Exporting/ExportTemplateMongoDbAccess.cs index 47b43fce..435ebfe5 100644 --- a/Data/Exporting/ExportTemplateMongoDbAccess.cs +++ b/Data/Exporting/ExportTemplateMongoDbAccess.cs @@ -119,11 +119,12 @@ public async Task GetTemplateByCustomizedObjectId(string project /// /// Returns all export templates for a template type which are associated to an object /// + /// Project Id /// Template Type /// Customized object export templates - public async Task> GetCustomizedObjectTemplatesByType(TemplateType templateType) + public async Task> GetCustomizedObjectTemplatesByType(string projectId, TemplateType templateType) { - List templates = await _TemplateCollection.AsQueryable().Where(t => t.TemplateType == templateType && !string.IsNullOrEmpty(t.CustomizedObjectId)).Select(t => new ExportTemplate { + List templates = await _TemplateCollection.AsQueryable().Where(t => t.TemplateType == templateType && t.ProjectId == projectId && !string.IsNullOrEmpty(t.CustomizedObjectId)).Select(t => new ExportTemplate { Id = t.Id, CustomizedObjectId = t.CustomizedObjectId, TemplateType = t.TemplateType, diff --git a/Data/Exporting/IExportTemplateDbAccess.cs b/Data/Exporting/IExportTemplateDbAccess.cs index 9af252ba..9fe14d91 100644 --- a/Data/Exporting/IExportTemplateDbAccess.cs +++ b/Data/Exporting/IExportTemplateDbAccess.cs @@ -52,9 +52,10 @@ public interface IExportTemplateDbAccess /// /// Returns all export templates for a template type which are associated to an object /// + /// Project Id /// Template Type /// Customized object export templates - Task> GetCustomizedObjectTemplatesByType(TemplateType templateType); + Task> GetCustomizedObjectTemplatesByType(string projectId, TemplateType templateType); /// /// Creates a template diff --git a/Data/Exporting/IObjectExportSnippetDbAccess.cs b/Data/Exporting/IObjectExportSnippetDbAccess.cs index ec5f08db..2756de8b 100644 --- a/Data/Exporting/IObjectExportSnippetDbAccess.cs +++ b/Data/Exporting/IObjectExportSnippetDbAccess.cs @@ -50,6 +50,13 @@ public interface IObjectExportSnippetDbAccess /// Task Task DeleteExportSnippetsByObjectId(string objectId); + /// + /// Returns all snippets an object is referenced + /// + /// Object Id + /// All snippets the object is referenced in without details + Task> GetExportSnippetsObjectIsReferenced(string objectId); + /// /// Returns all invalid export snippet objects diff --git a/Data/Exporting/ObjectExportSnippetMongoDbAccess.cs b/Data/Exporting/ObjectExportSnippetMongoDbAccess.cs index 360b1ab8..1dc38849 100644 --- a/Data/Exporting/ObjectExportSnippetMongoDbAccess.cs +++ b/Data/Exporting/ObjectExportSnippetMongoDbAccess.cs @@ -102,6 +102,25 @@ public async Task DeleteExportSnippetsByObjectId(string objectId) await _ObjectExportSnippetCollection.DeleteManyAsync(t => t.ObjectId == objectId); } + /// + /// Returns all snippets an object is referenced + /// + /// Object Id + /// All snippets the object is referenced in without details + public async Task> GetExportSnippetsObjectIsReferenced(string objectId) + { + List exportSnippets = await _ObjectExportSnippetCollection.AsQueryable().Where(o => o.ScriptNodeGraph.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || o.ScriptNodeGraph.Condition.Any(c => c.Conditions.Any(co => co.DependsOnObjects.Any(doo => doo.ObjectId == objectId))) || + o.ScriptNodeGraph.Reference.Any(a => a.ReferencedObjects.Any(r => r.ObjectId == objectId))).Select(o => new ObjectExportSnippet { + Id = o.Id, + ProjectId = o.ProjectId, + ObjectId = o.ObjectId, + SnippetName = o.SnippetName, + ScriptType = o.ScriptType, + ScriptName = o.ScriptName + }).ToListAsync(); + + return exportSnippets; + } /// /// Returns all invalid export snippet objects diff --git a/Data/Exporting/ObjectExportSnippetReference.cs b/Data/Exporting/ObjectExportSnippetReference.cs new file mode 100644 index 00000000..7e1aa611 --- /dev/null +++ b/Data/Exporting/ObjectExportSnippetReference.cs @@ -0,0 +1,28 @@ +namespace GoNorth.Data.Exporting +{ + /// + /// Result of an export snippet reference check + /// + public class ObjectExportSnippetReference + { + /// + /// Id of the object + /// + public string ObjectId { get; set; } + + /// + /// Name of the object + /// + public string ObjectName { get; set; } + + /// + /// Type of the object + /// + public string ObjectType { get; set; } + + /// + /// Name of the snippet + /// + public string ExportSnippet { get; set; } + } +} \ No newline at end of file diff --git a/Data/Exporting/TemplateType.cs b/Data/Exporting/TemplateType.cs index 7b4b5d3f..d4036c90 100644 --- a/Data/Exporting/TemplateType.cs +++ b/Data/Exporting/TemplateType.cs @@ -447,6 +447,12 @@ public enum TemplateType /// TaleActionChooseNpcUseItem = 352, + + /// + /// Reference Node + /// + ReferenceNode = 500, + /// /// Logic Grouping Template diff --git a/Data/FlexFieldDatabase/FlexFieldObjectBaseMongoDbAccess.cs b/Data/FlexFieldDatabase/FlexFieldObjectBaseMongoDbAccess.cs index a3c5faa0..bcd582e2 100644 --- a/Data/FlexFieldDatabase/FlexFieldObjectBaseMongoDbAccess.cs +++ b/Data/FlexFieldDatabase/FlexFieldObjectBaseMongoDbAccess.cs @@ -267,11 +267,12 @@ public async Task> GetFlexFieldObjectsByTemplate(string templateId) /// /// Returns all flex field objects that are not part of an id list. This means that they are not part of the list themselfs and or their template /// + /// Id of the project /// List of ids /// Flex field objects - public async Task> GetFlexFieldObjectsNotPartOfIdList(IEnumerable idList) + public async Task> GetFlexFieldObjectsNotPartOfIdList(string projectId, IEnumerable idList) { - return await _ObjectCollection.AsQueryable().Where(n => !idList.Contains(n.TemplateId) && !idList.Contains(n.Id)).Select(c => new T() { + return await _ObjectCollection.AsQueryable().Where(n => n.ProjectId == projectId && !idList.Contains(n.TemplateId) && !idList.Contains(n.Id)).Select(c => new T() { Id = c.Id, Name = c.Name, }).ToListAsync(); @@ -280,11 +281,12 @@ public async Task> GetFlexFieldObjectsNotPartOfIdList(IEnumerable /// Returns all flex field objects that are part of an id list. This means that they are not part of the list themselfs and or their template /// + /// Id of the project /// List of ids /// Flex field objects - public async Task> GetFlexFieldObjectsPartOfIdList(IEnumerable idList) + public async Task> GetFlexFieldObjectsPartOfIdList(string projectId, IEnumerable idList) { - return await _ObjectCollection.AsQueryable().Where(n => idList.Contains(n.TemplateId) || idList.Contains(n.Id)).Select(c => new T() { + return await _ObjectCollection.AsQueryable().Where(n => n.ProjectId == projectId && idList.Contains(n.TemplateId) || idList.Contains(n.Id)).Select(c => new T() { Id = c.Id, Name = c.Name, }).ToListAsync(); @@ -368,12 +370,13 @@ public async Task AnyFlexFieldObjectUsingImage(string imageFile) /// /// Checks if any Flex Field Object use a tag /// + /// Id of the proejct /// Tag /// true if tag is used, else false - public async Task AnyFlexFieldObjectUsingTag(string tag) + public async Task AnyFlexFieldObjectUsingTag(string projectId, string tag) { tag = tag.ToLowerInvariant(); - return await _ObjectCollection.AsQueryable().Where(n => n.Tags.Any(s => s.ToLowerInvariant() == tag)).AnyAsync(); + return await _ObjectCollection.AsQueryable().Where(n => n.ProjectId == projectId && n.Tags.Any(s => s.ToLowerInvariant() == tag)).AnyAsync(); } diff --git a/Data/FlexFieldDatabase/FlexFieldObjectTag.cs b/Data/FlexFieldDatabase/FlexFieldObjectTag.cs index bada1f28..8028cbf3 100644 --- a/Data/FlexFieldDatabase/FlexFieldObjectTag.cs +++ b/Data/FlexFieldDatabase/FlexFieldObjectTag.cs @@ -10,6 +10,12 @@ public class FlexFieldObjectTag /// public string Id { get; set; } + /// + /// Id of the project + /// + /// + public string ProjectId { get; set; } + /// /// Tag /// diff --git a/Data/FlexFieldDatabase/FlexFieldObjectTagBaseMongoDbAccess.cs b/Data/FlexFieldDatabase/FlexFieldObjectTagBaseMongoDbAccess.cs index a7e803a5..4f0eeff8 100644 --- a/Data/FlexFieldDatabase/FlexFieldObjectTagBaseMongoDbAccess.cs +++ b/Data/FlexFieldDatabase/FlexFieldObjectTagBaseMongoDbAccess.cs @@ -31,21 +31,24 @@ public FlexFieldObjectTagBaseMongoDbAccess(string collectionName, IOptions /// Returns all available tags /// + /// Id of the project /// All available tags - public async Task> GetAllTags() + public async Task> GetAllTags(string projectId) { - return await _TagCollection.AsQueryable().Select(t => t.Tag).ToListAsync(); + return await _TagCollection.AsQueryable().Where(p => p.ProjectId == projectId).Select(t => t.Tag).ToListAsync(); } /// /// Adds a tag /// + /// Id of the project /// Tag to add /// Task - public async Task AddTag(string tag) + public async Task AddTag(string projectId, string tag) { FlexFieldObjectTag newTag = new FlexFieldObjectTag(); newTag.Id = Guid.NewGuid().ToString(); + newTag.ProjectId = projectId; newTag.Tag = tag; await _TagCollection.InsertOneAsync(newTag); } @@ -53,12 +56,23 @@ public async Task AddTag(string tag) /// /// Removes a tag /// + /// Id of the project /// Tag to remove /// Task - public async Task DeleteTag(string tag) + public async Task DeleteTag(string projectId, string tag) { string searchTag = tag.ToLowerInvariant(); - await _TagCollection.DeleteOneAsync(t => t.Tag.ToLowerInvariant() == searchTag); + await _TagCollection.DeleteOneAsync(t => t.ProjectId == projectId && t.Tag.ToLowerInvariant() == searchTag); + } + + /// + /// Sets the project id for legacy tags + /// + /// Id of the default project + /// Task + public async Task SetProjectIdForLegacyTags(string defaultProjectId) + { + await _TagCollection.UpdateManyAsync(t => string.IsNullOrEmpty(t.ProjectId), Builders.Update.Set(n => n.ProjectId, defaultProjectId)); } } } \ No newline at end of file diff --git a/Data/FlexFieldDatabase/IFlexFieldObjectDbAccess.cs b/Data/FlexFieldDatabase/IFlexFieldObjectDbAccess.cs index f9c9447b..53d8f7ea 100644 --- a/Data/FlexFieldDatabase/IFlexFieldObjectDbAccess.cs +++ b/Data/FlexFieldDatabase/IFlexFieldObjectDbAccess.cs @@ -113,16 +113,18 @@ public interface IFlexFieldObjectDbAccess where T: FlexFieldObject /// /// Returns all flex field objects that are not part of an id list. This means that they are not part of the list themselfs and or their template /// + /// Id of the project /// List of ids /// Flex field objects - Task> GetFlexFieldObjectsNotPartOfIdList(IEnumerable idList); + Task> GetFlexFieldObjectsNotPartOfIdList(string projectId, IEnumerable idList); /// /// Returns all flex field objects that are part of an id list. This means that they are not part of the list themselfs and or their template /// + /// Id of the project /// List of ids /// Flex field objects - Task> GetFlexFieldObjectsPartOfIdList(IEnumerable idList); + Task> GetFlexFieldObjectsPartOfIdList(string projectId, IEnumerable idList); /// /// Resolves the names for a list of Flex Field Objects @@ -170,9 +172,10 @@ public interface IFlexFieldObjectDbAccess where T: FlexFieldObject /// /// Checks if any Flex Field Object use a tag /// + /// Id of the proejct /// Tag /// true if tag is used, else false - Task AnyFlexFieldObjectUsingTag(string tag); + Task AnyFlexFieldObjectUsingTag(string projectId, string tag); /// diff --git a/Data/FlexFieldDatabase/IFlexFieldObjectTagDbAccess.cs b/Data/FlexFieldDatabase/IFlexFieldObjectTagDbAccess.cs index 03975f49..13b555c2 100644 --- a/Data/FlexFieldDatabase/IFlexFieldObjectTagDbAccess.cs +++ b/Data/FlexFieldDatabase/IFlexFieldObjectTagDbAccess.cs @@ -11,21 +11,31 @@ public interface IFlexFieldObjectTagDbAccess /// /// Returns all available tags /// + /// Id of the project /// All available tags - Task> GetAllTags(); + Task> GetAllTags(string projectId); /// /// Adds a tag /// + /// Id of the project /// Tag to add /// Task - Task AddTag(string tag); + Task AddTag(string projectId, string tag); /// /// Removes a tag /// + /// Id of the project /// Tag to remove /// Task - Task DeleteTag(string tag); + Task DeleteTag(string projectId, string tag); + + /// + /// Sets the project id for legacy tags + /// + /// Id of the default project + /// Task + Task SetProjectIdForLegacyTags(string defaultProjectId); } } \ No newline at end of file diff --git a/Data/Karta/IKartaMapDbAccess.cs b/Data/Karta/IKartaMapDbAccess.cs index 27ddc9d0..6799075a 100644 --- a/Data/Karta/IKartaMapDbAccess.cs +++ b/Data/Karta/IKartaMapDbAccess.cs @@ -145,6 +145,12 @@ public interface IKartaMapDbAccess /// Async Task Task DeleteMarkersOfQuest(string questId); + /// + /// Resolves the names of a list of maps + /// + /// Id of maps to load + /// Maps with filled names only + Task> ResolveMapNames(List mapIds); /// /// Returns all maps that were last modified by a user diff --git a/Data/Karta/KartaMapMongoDbAccess.cs b/Data/Karta/KartaMapMongoDbAccess.cs index af0bb7de..bd9df0d8 100644 --- a/Data/Karta/KartaMapMongoDbAccess.cs +++ b/Data/Karta/KartaMapMongoDbAccess.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using System.Threading.Tasks; using GoNorth.Config; using GoNorth.Data.Karta.Marker; @@ -551,6 +550,19 @@ public async Task DeleteMarkersOfQuest(string questId) } } + /// + /// Resolves the names of a list of maps + /// + /// Id of maps to load + /// Maps with filled names only + public async Task> ResolveMapNames(List mapIds) + { + return await _MapCollection.AsQueryable().Where(m => mapIds.Contains(m.Id)).Select(m => new KartaMap() { + Id = m.Id, + Name = m.Name + }).ToListAsync(); + } + /// /// Returns all maps that were last modified by a user /// diff --git a/Data/Kortisto/KortistoNpcDailyRoutineTime.cs b/Data/Kortisto/KortistoNpcDailyRoutineTime.cs index 85cb6b0b..c9b12361 100644 --- a/Data/Kortisto/KortistoNpcDailyRoutineTime.cs +++ b/Data/Kortisto/KortistoNpcDailyRoutineTime.cs @@ -31,5 +31,15 @@ public object Clone() Minutes = this.Minutes }; } + + /// + /// Formats the time as a string + /// + /// Time format + /// Formatted Time Value + public string ToString(string format) + { + return format.Replace("hh", Hours.ToString().PadLeft(2, '0')).Replace("mm", Minutes.ToString().PadLeft(2, '0')); + } } } \ No newline at end of file diff --git a/Data/Kortisto/KortistoNpcMongoDbAccess.cs b/Data/Kortisto/KortistoNpcMongoDbAccess.cs index 53cfaa25..c2410bd8 100644 --- a/Data/Kortisto/KortistoNpcMongoDbAccess.cs +++ b/Data/Kortisto/KortistoNpcMongoDbAccess.cs @@ -92,7 +92,8 @@ public async Task> GetNpcsObjectIsReferencedInDailyRoutine(str { // Required to use non Linq syntax here as Linq does not seem to support deep enough queries for this List npcs = await _ObjectCollection.Find(Builders.Filter.Ne(n => n.Id, objectId) & Builders.Filter.ElemMatch(n => n.DailyRoutine, - d => d.ScriptNodeGraph.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || d.ScriptNodeGraph.Condition.Any(c => c.Conditions.Any(co => co.DependsOnObjects.Any(doo => doo.ObjectId == objectId))))).Project(n => new KortistoNpc { + d => d.ScriptNodeGraph.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || d.ScriptNodeGraph.Condition.Any(c => c.Conditions.Any(co => co.DependsOnObjects.Any(doo => doo.ObjectId == objectId))) || + d.ScriptNodeGraph.Reference.Any(a => a.ReferencedObjects.Any(r => r.ObjectId == objectId)))).Project(n => new KortistoNpc { Id = n.Id, Name = n.Name }).ToListAsync(); diff --git a/Data/LockService/ILockServiceDbAccess.cs b/Data/LockService/ILockServiceDbAccess.cs index faf01e88..62c033ab 100644 --- a/Data/LockService/ILockServiceDbAccess.cs +++ b/Data/LockService/ILockServiceDbAccess.cs @@ -28,6 +28,13 @@ public interface ILockServiceDbAccess /// Task Task LockResource(string category, string id, string userId, DateTimeOffset expireDate); + /// + /// Deletes a lock by its id + /// + /// Id + /// Task + Task DeleteLockById(string id); + /// /// Deletes all locks for a user /// @@ -35,6 +42,12 @@ public interface ILockServiceDbAccess /// Task Task DeleteAllLocksOfUser(string userId); + /// + /// Deletes all expired locks + /// + /// Task + Task DeleteExpiredLocks(); + /// /// Returns all locks of a user /// diff --git a/Data/LockService/LockServiceMongoDbAccess.cs b/Data/LockService/LockServiceMongoDbAccess.cs index 460da67d..ce063af6 100644 --- a/Data/LockService/LockServiceMongoDbAccess.cs +++ b/Data/LockService/LockServiceMongoDbAccess.cs @@ -77,6 +77,16 @@ public async Task LockResource(string category, string id, string userId, DateTi } } + /// + /// Deletes a lock by its id + /// + /// Id + /// Task + public async Task DeleteLockById(string id) + { + await _LockCollection.DeleteOneAsync(l => l.Id == id); + } + /// /// Deletes all locks for a user /// @@ -87,6 +97,16 @@ public async Task DeleteAllLocksOfUser(string userId) await _LockCollection.DeleteManyAsync(l => l.UserId == userId); } + /// + /// Deletes all expired locks + /// + /// Task + public async Task DeleteExpiredLocks() + { + DateTimeOffset refDate = DateTimeOffset.UtcNow.AddMinutes(-1); + await _LockCollection.DeleteManyAsync(l => l.ExpireDate < refDate); + } + /// /// Returns all locks of a user /// diff --git a/Data/MongoDbSetup.cs b/Data/MongoDbSetup.cs index 74d5bc62..3fd4fd70 100644 --- a/Data/MongoDbSetup.cs +++ b/Data/MongoDbSetup.cs @@ -33,6 +33,26 @@ public class MongoDbSetup : BaseMongoDbAccess, IDbSetup private const string LegacyCollection_TaleConfig = "TaleConfig"; + /// + /// Project Db Access + /// + private readonly IProjectDbAccess _projectDbAccess; + + /// + /// Npc Tag Db Access + /// + private readonly IKortistoNpcTagDbAccess _npcTagDbAccess; + + /// + /// Item Tag Db Access + /// + private readonly IStyrItemTagDbAccess _itemTagDbAccess; + + /// + /// Skill Tag Db Access + /// + private readonly IEvneSkillTagDbAccess _skillTagDbAccess; + /// /// Timeline Db Access /// @@ -46,11 +66,20 @@ public class MongoDbSetup : BaseMongoDbAccess, IDbSetup /// /// Constructor /// + /// Project Db Access + /// Npc Tag Db Access + /// Item Tag Db Access + /// Skill Tag Db Access /// Timeline Db Access /// Lock Service Db Access /// Configuration - public MongoDbSetup(ITimelineDbAccess timelineDbAccess, ILockServiceDbAccess lockServiceDbAccess, IOptions configuration) : base(configuration) + public MongoDbSetup(IProjectDbAccess projectDbAccess, IKortistoNpcTagDbAccess npcTagDbAccess, IStyrItemTagDbAccess itemTagDbAccess, IEvneSkillTagDbAccess skillTagDbAccess, ITimelineDbAccess timelineDbAccess, + ILockServiceDbAccess lockServiceDbAccess, IOptions configuration) : base(configuration) { + _projectDbAccess = projectDbAccess; + _npcTagDbAccess = npcTagDbAccess; + _itemTagDbAccess = itemTagDbAccess; + _skillTagDbAccess = skillTagDbAccess; _timelineDbAccess = timelineDbAccess; _lockServiceDbAccess = lockServiceDbAccess; } @@ -70,6 +99,7 @@ public async Task SetupDatabaseAsync() await CreateCollectionIfNotExists(RoleMongoDbAccess.RoleCollectionName, collectionNames); await CreateCollectionIfNotExists(ProjectMongoDbAccess.ProjectCollectionName, collectionNames); + await CreateCollectionIfNotExists(ProjectMongoDbAccess.UserSelectedProjectCollectionName, collectionNames); await CreateCollectionIfNotExists(ProjectConfigMongoDbAccess.JsonConfigCollectionName, collectionNames); await CreateCollectionIfNotExists(ProjectConfigMongoDbAccess.MiscConfigCollectionName, collectionNames); @@ -190,6 +220,7 @@ public async Task CheckForNeededMigrations() await CreateIndices(); List collectionNames = await GetExistingCollections(); await RenameLegacyCollections(collectionNames); + await SetTagProjectIds(); } /// @@ -214,5 +245,22 @@ private async Task RenameLegacyCollections(List collectionNames) await _Database.RenameCollectionAsync(LegacyCollection_TaleConfig, ProjectConfigMongoDbAccess.JsonConfigCollectionName); } } + + /// + /// Sets the project ids for tags + /// + /// Task + private async Task SetTagProjectIds() + { + GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + if(project == null) + { + return; + } + + await _npcTagDbAccess.SetProjectIdForLegacyTags(project.Id); + await _itemTagDbAccess.SetProjectIdForLegacyTags(project.Id); + await _skillTagDbAccess.SetProjectIdForLegacyTags(project.Id); + } } } \ No newline at end of file diff --git a/Data/NodeGraph/NodeGraphSnippet.cs b/Data/NodeGraph/NodeGraphSnippet.cs index 381b3880..d8b0af1c 100644 --- a/Data/NodeGraph/NodeGraphSnippet.cs +++ b/Data/NodeGraph/NodeGraphSnippet.cs @@ -28,6 +28,12 @@ public class NodeGraphSnippet : IImplementationComparable, ICloneable [ListCompareAttribute(LabelKey = "NodeConditionsChanged")] public List Condition { get; set; } + /// + /// Reference nodes + /// + [ListCompareAttribute(LabelKey = "NodeReferenceChanged")] + public List Reference {get ; set; } + /// /// Clones the node graph snippet /// @@ -37,7 +43,8 @@ public object Clone() return new NodeGraphSnippet { Link = this.Link != null ? this.Link.Select(l => l.Clone()).Cast().ToList() : null, Action = this.Action != null ? this.Action.Select(l => l.Clone()).Cast().ToList() : null, - Condition = this.Condition != null ? this.Condition.Select(l => l.Clone()).Cast().ToList() : null + Condition = this.Condition != null ? this.Condition.Select(l => l.Clone()).Cast().ToList() : null, + Reference = this.Reference != null ? this.Reference.Select(l => l.Clone()).Cast().ToList() : null }; } } diff --git a/Data/NodeGraph/NodeObjectDependency.cs b/Data/NodeGraph/NodeObjectDependency.cs index ff8b4944..73350cd2 100644 --- a/Data/NodeGraph/NodeObjectDependency.cs +++ b/Data/NodeGraph/NodeObjectDependency.cs @@ -1,11 +1,13 @@ using System; +using System.Text.Json.Serialization; +using GoNorth.Services.ImplementationStatusCompare; namespace GoNorth.Data.NodeGraph { /// /// Node Object dependency /// - public class NodeObjectDependency : ICloneable + public class NodeObjectDependency : ICloneable, IImplementationListComparable { /// /// Type of the object @@ -17,6 +19,51 @@ public class NodeObjectDependency : ICloneable /// public string ObjectId { get; set; } + /// + /// Id which is used in a list compare to detect deleted or new objects + /// + [JsonIgnore] + public string ListComparableId { get { return ObjectId; } } + + /// + /// Value which is used in a list compare for display + /// + [JsonIgnore] + public CompareDifferenceValue ListComparableValue { + get { + CompareDifferenceValue.ValueResolveType valueResolveType = CompareDifferenceValue.ValueResolveType.LanguageKey; + if(ObjectType == "Npc") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveNpcName; + } + else if(ObjectType == "Item") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveItemName; + } + else if(ObjectType == "Skill") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveSkillName; + } + else if(ObjectType == "Quest") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveQuestName; + } + else if(ObjectType == "WikiPage") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveWikiPageName; + } + else if(ObjectType == "Map") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.ResolveMapName; + } + else if(ObjectType == "NpcDailyRoutineEvent" || ObjectType == "MapMarker") + { + valueResolveType = CompareDifferenceValue.ValueResolveType.Ignore; + } + return new CompareDifferenceValue(ObjectId, valueResolveType); + } + } + /// /// Clones the object /// diff --git a/Data/NodeGraph/ReferenceNode.cs b/Data/NodeGraph/ReferenceNode.cs new file mode 100644 index 00000000..42be6766 --- /dev/null +++ b/Data/NodeGraph/ReferenceNode.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using GoNorth.Services.ImplementationStatusCompare; + +namespace GoNorth.Data.NodeGraph +{ + /// + /// Reference Node + /// + public class ReferenceNode : BaseNode + { + /// + /// Referenced object + /// + [ListCompareAttribute(LabelKey = "ReferencedObjectChanged")] + public List ReferencedObjects { get; set; } + + /// + /// In case of a reference on a marker, the type of marker is saved here + /// + public string ReferencedMarkerType { get; set; } + + /// + /// Reference text + /// + [ValueCompareAttribute] + public string ReferenceText { get; set; } + + + /// + /// Clones the reference node + /// + /// Cloned object + public object Clone() + { + ReferenceNode clonedObject = CloneObject(); + clonedObject.ReferencedObjects = ReferencedObjects != null ? ReferencedObjects.Select(r => (NodeObjectDependency)r.Clone()).ToList() : null; + clonedObject.ReferencedMarkerType = ReferencedMarkerType; + clonedObject.ReferenceText = ReferenceText; + + return clonedObject; + } + } +} diff --git a/Data/Project/IProjectDbAccess.cs b/Data/Project/IProjectDbAccess.cs index b9140e60..0d9f58ab 100644 --- a/Data/Project/IProjectDbAccess.cs +++ b/Data/Project/IProjectDbAccess.cs @@ -47,5 +47,28 @@ public interface IProjectDbAccess /// Project /// Task Task DeleteProject(GoNorthProject project); + + + /// + /// Sets the selected project for a user + /// + /// Id of the user + /// Id of the project + /// Task + Task SetUserSelectedProject(string userId, string projectId); + + /// + /// Deletes the selected project for a user + /// + /// Id of the user + /// Task + Task DeleteUserSelectedProject(string userId); + + /// + /// Deletes the selected project for a user + /// + /// Id of the user + /// Task + Task GetUserSelectedProject(string userId); } } \ No newline at end of file diff --git a/Data/Project/ProjectMongoDbAccess.cs b/Data/Project/ProjectMongoDbAccess.cs index 0094da6c..ff2f654a 100644 --- a/Data/Project/ProjectMongoDbAccess.cs +++ b/Data/Project/ProjectMongoDbAccess.cs @@ -18,12 +18,22 @@ public class ProjectMongoDbAccess : BaseMongoDbAccess, IProjectDbAccess /// Collection Name of the projects /// public const string ProjectCollectionName = "Project"; + + /// + /// Collection Name of the selected projects for a user + /// + public const string UserSelectedProjectCollectionName = "UserSelectedProject"; /// /// Project Collection /// private IMongoCollection _ProjectCollection; + /// + /// User selected project Collection + /// + private IMongoCollection _UserSelectedProjectCollection; + /// /// Constructor /// @@ -31,6 +41,7 @@ public class ProjectMongoDbAccess : BaseMongoDbAccess, IProjectDbAccess public ProjectMongoDbAccess(IOptions configuration) : base(configuration) { _ProjectCollection = _Database.GetCollection(ProjectCollectionName); + _UserSelectedProjectCollection = _Database.GetCollection(UserSelectedProjectCollectionName); } /// @@ -104,6 +115,7 @@ public async Task UpdateProject(GoNorthProject project) /// Task public async Task DeleteProject(GoNorthProject project) { + await _UserSelectedProjectCollection.DeleteManyAsync(p => p.ProjectId == project.Id); DeleteResult result = await _ProjectCollection.DeleteOneAsync(p => p.Id == project.Id); } @@ -115,5 +127,50 @@ private async Task SetAllProjectsAsNonDefault() { await _ProjectCollection.UpdateManyAsync(FilterDefinition.Empty, Builders.Update.Set(p => p.IsDefault, false)); } + + + /// + /// Sets the selected project for a user + /// + /// Id of the user + /// Id of the project + /// Task + public async Task SetUserSelectedProject(string userId, string projectId) + { + UserSelectedProject userSelectedProject = await _UserSelectedProjectCollection.Find(f => f.UserId == userId).FirstOrDefaultAsync(); + if(userSelectedProject != null) + { + userSelectedProject.ProjectId = projectId; + await _UserSelectedProjectCollection.ReplaceOneAsync(f => f.Id == userSelectedProject.Id, userSelectedProject); + } + else + { + userSelectedProject = new UserSelectedProject(); + userSelectedProject.Id = Guid.NewGuid().ToString(); + userSelectedProject.UserId = userId; + userSelectedProject.ProjectId = projectId; + await _UserSelectedProjectCollection.InsertOneAsync(userSelectedProject); + } + } + + /// + /// Deletes the selected project for a user + /// + /// Id of the user + /// Task + public async Task DeleteUserSelectedProject(string userId) + { + await _UserSelectedProjectCollection.DeleteManyAsync(p => p.UserId == userId); + } + + /// + /// Deletes the selected project for a user + /// + /// Id of the user + /// Task + public async Task GetUserSelectedProject(string userId) + { + return await _UserSelectedProjectCollection.Find(f => f.UserId == userId).FirstOrDefaultAsync(); + } } } \ No newline at end of file diff --git a/Data/Project/UserSelectedProject.cs b/Data/Project/UserSelectedProject.cs new file mode 100644 index 00000000..46a13397 --- /dev/null +++ b/Data/Project/UserSelectedProject.cs @@ -0,0 +1,23 @@ +namespace GoNorth.Data.Project +{ + /// + /// User selected project + /// + public class UserSelectedProject + { + /// + /// Id of the entry + /// + public string Id {get; set; } + + /// + /// Id of the user + /// + public string UserId { get; set; } + + /// + /// Id of the project + /// + public string ProjectId { get; set; } + } +} diff --git a/Data/Tale/TaleDialog.cs b/Data/Tale/TaleDialog.cs index fd9beca3..664a71e8 100644 --- a/Data/Tale/TaleDialog.cs +++ b/Data/Tale/TaleDialog.cs @@ -62,6 +62,12 @@ public class TaleDialog : IHasModifiedData, IImplementationComparable, IImplemen [ListCompareAttribute(LabelKey = "NodeConditionsChanged")] public List Condition { get; set; } + /// + /// Reference nodes + /// + [ListCompareAttribute(LabelKey = "NodeReferenceChanged")] + public List Reference {get ; set; } + /// /// true if the object is implemented, else false diff --git a/Data/Tale/TaleMongoDbAccess.cs b/Data/Tale/TaleMongoDbAccess.cs index 4abb5902..a981068f 100644 --- a/Data/Tale/TaleMongoDbAccess.cs +++ b/Data/Tale/TaleMongoDbAccess.cs @@ -85,9 +85,14 @@ public async Task GetDialogByRelatedObjectId(string relatedObjectId) /// All Dialogs object is referenced in without detail information and the entrie with relatedobjectid = itself public async Task> GetDialogsObjectIsReferenced(string objectId) { - List dialogs = await _DialogCollection.AsQueryable().Where(t => t.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || t.Condition.Any(c => c.Conditions.Any(ce => ce.DependsOnObjects.Any(o => o.ObjectId == objectId))) || t.Choice.Any(c => c.Choices.Any(co => co.Condition != null && co.Condition.DependsOnObjects.Any(o => o.ObjectId == objectId)))).Select(t => new TaleDialog() { + List dialogs = await _DialogCollection.AsQueryable().Where(t => t.Action.Any(a => a.ActionRelatedToObjectId == objectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(e => e.ObjectId == objectId))) || t.Condition.Any(c => c.Conditions.Any(ce => ce.DependsOnObjects.Any(o => o.ObjectId == objectId))) || t.Choice.Any(c => c.Choices.Any(co => co.Condition != null && co.Condition.DependsOnObjects.Any(o => o.ObjectId == objectId))) || + t.Reference.Any(a => a.ReferencedObjects.Any(r => r.ObjectId == objectId))).Select(t => new TaleDialog() { Id = t.Id, - RelatedObjectId = t.RelatedObjectId + RelatedObjectId = t.RelatedObjectId, + Action = t.Action, + Choice = t.Choice, + Condition = t.Condition, + Reference = t.Reference }).ToListAsync(); return dialogs; } diff --git a/DefaultExportTemplates/Tale/ReferenceNode.lua b/DefaultExportTemplates/Tale/ReferenceNode.lua new file mode 100644 index 00000000..e69de29b diff --git a/Dockerfile b/Dockerfile index d93473eb..6601adad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env WORKDIR /app # Copy csproj and restore as distinct layers @@ -11,7 +11,7 @@ COPY ./appsettings.docker.json ./appsettings.json RUN dotnet publish -c Release -o out # Build runtime image -FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 +FROM mcr.microsoft.com/dotnet/aspnet:5.0 WORKDIR /app COPY --from=build-env /app/out . ENTRYPOINT ["dotnet", "GoNorth.dll"] \ No newline at end of file diff --git a/GoNorth.csproj b/GoNorth.csproj index bf246fbf..7022a293 100644 --- a/GoNorth.csproj +++ b/GoNorth.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 aspnet-GoNorth-BEC9142A-89D7-4A58-904B-BCD87806912F true true @@ -11,12 +11,12 @@ - - - - - - + + + + + + diff --git a/GoNorthVersion.cs b/GoNorthVersion.cs index 0e50f642..d8c47b52 100644 --- a/GoNorthVersion.cs +++ b/GoNorthVersion.cs @@ -10,6 +10,6 @@ public class GoNorthVersion /// /// Current GoNorth Version /// - public static readonly Version CurrentVersion = new Version(1, 8, 0, 5); + public static readonly Version CurrentVersion = new Version(1, 8, 1, 0); }; } \ No newline at end of file diff --git a/Resources/Controllers/Api/AikaApiController.de.json b/Resources/Controllers/Api/AikaApiController.de.json index be883c4d..a7948bdf 100644 --- a/Resources/Controllers/Api/AikaApiController.de.json +++ b/Resources/Controllers/Api/AikaApiController.de.json @@ -3,9 +3,11 @@ "CanNotDeleteNonEmptyChapterDetail": "Die Detailansicht ist nicht leer. Um Story Fehler zu verhindern muss sie erst geleert werden.", "CanNotDeleteQuestUsedInChapterDetail": "Der Quest wird in den Detailansichten \"{0}\" genutzt. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - "CanNotDeleteQuestMentionedInKirjaPage": "Der Quest wird in den Kirja Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - "CanNotDeleteQuestReferencedInTaleDialog": "Der Quest ist in den Tale Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteQuestMentionedInKirjaPage": "Der Quest wird in den Wiki-Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteQuestReferencedInTaleDialog": "Der Quest ist in den Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", "CanNotDeleteQuestUsedInDailyRoutine": "Der Quest ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - - "DuplicateFieldNameExist": "Es existitieren mehrere Felder mit gleichem Namen." + "CanNotDeleteQuestUsedInSkill": "Der Quest ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteQuestUsedInExportSnippet": "Der Quest ist in Export Snippets von \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + + "DuplicateFieldNameExist": "Es existieren mehrere Felder mit gleichem Namen." } \ No newline at end of file diff --git a/Resources/Controllers/Api/AikaApiController.en.json b/Resources/Controllers/Api/AikaApiController.en.json index d553b859..516631b6 100644 --- a/Resources/Controllers/Api/AikaApiController.en.json +++ b/Resources/Controllers/Api/AikaApiController.en.json @@ -3,9 +3,11 @@ "CanNotDeleteNonEmptyChapterDetail": "The detail view is not empty. To prevent errors in the story it must be cleared first.", "CanNotDeleteQuestUsedInChapterDetail": "The quest is being used in the detail view \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteQuestMentionedInKirjaPage": "The quest is mentioned in the Kirja page \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteQuestReferencedInTaleDialog": "The quest is referenced in the Tale dialog \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteQuestMentionedInKirjaPage": "The quest is mentioned in the wiki page \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteQuestReferencedInTaleDialog": "The quest is referenced in the dialog \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteQuestUsedInDailyRoutine": "The quest is referenced in the daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteQuestUsedInSkill": "The quest is referenced in the skill \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteQuestUsedInExportSnippet": "The quest is referenced in export snippets of \"{0}\". To prevent errors while exporting it must be deleted there first.", "DuplicateFieldNameExist": "Multiple fields with the same name exist." } \ No newline at end of file diff --git a/Resources/Controllers/Api/EvneApiController.de.json b/Resources/Controllers/Api/EvneApiController.de.json index 9e13fa1d..bb8e29de 100644 --- a/Resources/Controllers/Api/EvneApiController.de.json +++ b/Resources/Controllers/Api/EvneApiController.de.json @@ -1,17 +1,21 @@ { "FolderNotEmpty": "Der Ordner ist nicht leer.", - "CanNotDeleteSkillReferencedInAikaQuest": "Die Fähigkeit wird in den Aika Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", - "CanNotDeleteSkillReferencedInTaleDialog": "Die Fähigkeit ist in den Tale Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", - "CanNotDeleteSkillMentionedInKirjaPage": "Die Fähigkeit wird in den Kirja Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteSkillReferencedInAikaQuest": "Die Fähigkeit wird in den Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteSkillReferencedInTaleDialog": "Die Fähigkeit ist in den Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteSkillMentionedInKirjaPage": "Die Fähigkeit wird in den Wiki-Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "CanNotDeleteSkillLearnedByNpc": "Die Npcs \"{0}\" beherrschen die Fähigkeit. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "CanNotDeleteSkillUsedInDailyRoutine": "Die Fähigkeit ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteObjectUsedInExportSnippet": "Das Objekt ist in Export Snippets von \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteSkillUsedInSkill": "Die Fähigkeit ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "OnlyOneFileAllowed": "Es darf nur exakt eine Datei hochgeladen werden.", "CouldNotUploadImage": "Bild konnte nicht hochgeladen werden.", "ImageFormatNotSupported": "Das Bildformat wird nicht unterstützt.", - "DuplicateFieldNameExist": "Es existitieren mehrere Felder mit gleichem Namen.", + "DuplicateFieldNameExist": "Es existieren mehrere Felder mit gleichem Namen.", + + "TemplateIsForDifferentProject": "Das hinterlegte Template gehört einem anderen Projekt. Bitte wechsel zu diesem Projekt.", "ImportFieldValuesObjectNotFound": "Die Fähigkeit wurde nicht gefunden.", "ImportFieldValuesFieldNotFoundInTemplate": "Das Feld {0} wurde weder im Template noch in der Fähigkeit gefunden. Der Wert kann nicht importiert werden.", diff --git a/Resources/Controllers/Api/EvneApiController.en.json b/Resources/Controllers/Api/EvneApiController.en.json index 7419ba4d..693ae5c1 100644 --- a/Resources/Controllers/Api/EvneApiController.en.json +++ b/Resources/Controllers/Api/EvneApiController.en.json @@ -1,11 +1,13 @@ { "FolderNotEmpty": "The folder is not empty.", - "CanNotDeleteSkillReferencedInAikaQuest": "The skill is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteSkillReferencedInTaleDialog": "The skill is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteSkillMentionedInKirjaPage": "The skill is mentioned in the Kirja pages \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteSkillReferencedInAikaQuest": "The skill is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteSkillReferencedInTaleDialog": "The skill is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteSkillMentionedInKirjaPage": "The skill is mentioned in the wiki pages \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteSkillLearnedByNpc": "The Npcs \"{0}\" have learned the skill. To prevent errors in the story it must be deleted there first.", "CanNotDeleteSkillUsedInDailyRoutine": "The skill is referenced in the daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteObjectUsedInExportSnippet": "The object is referenced in export snippets of \"{0}\". To prevent errors while exporting it must be deleted there first.", + "CanNotDeleteSkillUsedInSkill": "The skill is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", "OnlyOneFileAllowed": "You must upload exactly one image file.", "CouldNotUploadImage": "Image could not be uploaded.", @@ -13,6 +15,8 @@ "DuplicateFieldNameExist": "Multiple fields with the same name exist.", + "TemplateIsForDifferentProject": "The specified template belongs to a different project. Please switch to that project.", + "ImportFieldValuesObjectNotFound": "Skill not found.", "ImportFieldValuesFieldNotFoundInTemplate": "The field {0} was not found in the template nor in the skill. The value cannot be imported.", "ImportFieldValuesNameIsEmpty": "The name must not be empty.", diff --git a/Resources/Controllers/Api/ExportApiController.de.json b/Resources/Controllers/Api/ExportApiController.de.json index 8d4f3ea2..51957d06 100644 --- a/Resources/Controllers/Api/ExportApiController.de.json +++ b/Resources/Controllers/Api/ExportApiController.de.json @@ -95,6 +95,8 @@ "TemplateTypeTaleActionNpcUseItem": "Aktion: Npc benutzt Item", "TemplateTypeTaleActionPlayerUseItem": "Aktion: Spieler benutzt Item", "TemplateTypeTaleActionChooseNpcUseItem": "Aktion: Beliebiger Npc benutzt Item", + + "TemplateTypeReferenceNode": "Referenz Knoten", "TemplateTypeGeneralLogicGroup": "Logik: Gruppe", diff --git a/Resources/Controllers/Api/ExportApiController.en.json b/Resources/Controllers/Api/ExportApiController.en.json index ba6b9220..44ca26a6 100644 --- a/Resources/Controllers/Api/ExportApiController.en.json +++ b/Resources/Controllers/Api/ExportApiController.en.json @@ -96,6 +96,8 @@ "TemplateTypeTaleActionPlayerUseItem": "Action: Player uses item", "TemplateTypeTaleActionChooseNpcUseItem": "Action: Choose npc uses item", + "TemplateTypeReferenceNode": "Reference node", + "TemplateTypeGeneralLogicGroup": "Logic: Group", "TemplateTypeGeneralLogicAnd": "Logic: And operator", diff --git a/Resources/Controllers/Api/KartaApiController.de.json b/Resources/Controllers/Api/KartaApiController.de.json index 61163b79..285295ae 100644 --- a/Resources/Controllers/Api/KartaApiController.de.json +++ b/Resources/Controllers/Api/KartaApiController.de.json @@ -6,14 +6,18 @@ "MarkerTypeMapChange": "Karta", "MarkerTypeNote": "Notiz", - "CanNotDeleteMapMarkedInKartaMap": "Die Karte ist in den Karta Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", - "CanNotDeleteMapReferencedInTaleDialog": "Die Karte ist in den Tale Dialogen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMapMarkedInKartaMap": "Die Karte ist in den Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMapReferencedInTaleDialog": "Die Karte ist in den Dialogen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "CanNotDeleteMapReferencedInNpc": "Die Karte ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", - "CanNotDeleteMapReferencedInAikaQuest": "Die Karte ist in den Aika Quests von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMapReferencedInAikaQuest": "Die Karte ist in den Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMapReferencedInSkill": "Die Karte ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMapReferencedInExportSnippet": "Die Karte ist in den Export Snippets \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", - "CanNotDeleteMarkerReferencedInTaleDialog": "Die Markierung ist in den Tale Dialogen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMarkerReferencedInTaleDialog": "Die Markierung ist in den Dialogen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "CanNotDeleteMarkerReferencedInNpc": "Die Markierung ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", - "CanNotDeleteMarkerReferencedInAikaQuest": "Die Markierung ist in den Aika Quests von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMarkerReferencedInAikaQuest": "Die Markierung ist in den Quests von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMarkerReferencedInSkill": "Die Markierung ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeleteMarkerReferencedInExportSnippet": "Die Markierung ist in den Export Snippets \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "OnlyOneFileAllowed": "Es darf nur exakt eine Datei hochgeladen werden.", "CouldNotUploadImage": "Bild konnte nicht hochgeladen werden.", diff --git a/Resources/Controllers/Api/KartaApiController.en.json b/Resources/Controllers/Api/KartaApiController.en.json index 89cc7cab..11764803 100644 --- a/Resources/Controllers/Api/KartaApiController.en.json +++ b/Resources/Controllers/Api/KartaApiController.en.json @@ -7,13 +7,17 @@ "MarkerTypeNote": "Note", "CanNotDeleteMapMarkedInKartaMap": "The map is marked in the maps \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteMapReferencedInTaleDialog": "The map is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMapReferencedInTaleDialog": "The map is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteMapReferencedInNpc": "The map is referenced in the daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteMapReferencedInAikaQuest": "The map is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMapReferencedInAikaQuest": "The map is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMapReferencedInSkill": "The map is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMapReferencedInExportSnippet": "The map is referenced in the export snippets \"{0}\". To prevent errors while exporting it must be deleted there first.", - "CanNotDeleteMarkerReferencedInTaleDialog": "The marker is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMarkerReferencedInTaleDialog": "The marker is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteMarkerReferencedInNpc": "The marker is referenced in the daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteMarkerReferencedInAikaQuest": "The marker is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMarkerReferencedInAikaQuest": "The marker is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMarkerReferencedInSkill": "The marker is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteMarkerReferencedInExportSnippet": "The marker is referenced in the export snippets \"{0}\". To prevent errors while exporting it must be deleted there first.", "OnlyOneFileAllowed": "You must upload exactly one image file.", "CouldNotUploadImage": "Image could not be uploaded.", diff --git a/Resources/Controllers/Api/KirjaApiController.de.json b/Resources/Controllers/Api/KirjaApiController.de.json index 195660f0..129f0670 100644 --- a/Resources/Controllers/Api/KirjaApiController.de.json +++ b/Resources/Controllers/Api/KirjaApiController.de.json @@ -4,6 +4,11 @@ "CanNotDeletePageMentionedInOtherPages": "Die Seite wird in den Kirja Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", "CanNotDeletePageMarkedInKartaMap": "Die Seite ist in den Karta Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeletePageReferencedInDialog": "Die Seite ist in den Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeletePageReferencedInNpc": "Die Seite ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeletePageReferencedInQuest": "Die Seite ist in den Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeletePageReferencedInSkill": "Die Seite ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss sie hier erst entfernt werden bevor sie gelöscht werden kann.", + "CanNotDeletePageReferencedInExportSnippet": "Die Seite ist in den Export Snippets \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "CanNotDeleteRootPage": "Die Wiki Startseite kann nicht gelöscht werden", "OnlyOneFileAllowed": "Es darf nur exakt eine Datei hochgeladen werden.", diff --git a/Resources/Controllers/Api/KirjaApiController.en.json b/Resources/Controllers/Api/KirjaApiController.en.json index f944cba0..837ddb74 100644 --- a/Resources/Controllers/Api/KirjaApiController.en.json +++ b/Resources/Controllers/Api/KirjaApiController.en.json @@ -4,6 +4,11 @@ "CanNotDeletePageMentionedInOtherPages": "This page is mentioned in the pages \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeletePageMarkedInKartaMap": "The page is marked in the maps \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeletePageReferencedInDialog": "The page is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeletePageReferencedInNpc": "The page is referenced in the daily routines of the npcs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeletePageReferencedInQuest": "The page is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeletePageReferencedInSkill": "The page is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeletePageReferencedInExportSnippet": "The page is referenced in the export snippets \"{0}\". To prevent errors while exporting it must be deleted there first.", "CanNotDeleteRootPage": "The root page can not be deleted", "OnlyOneFileAllowed": "You must upload exactly one image file..", diff --git a/Resources/Controllers/Api/KortistoApiController.de.json b/Resources/Controllers/Api/KortistoApiController.de.json index ee1adb96..70b24d49 100644 --- a/Resources/Controllers/Api/KortistoApiController.de.json +++ b/Resources/Controllers/Api/KortistoApiController.de.json @@ -1,21 +1,27 @@ { "FolderNotEmpty": "Der Ordner ist nicht leer.", - "CanNotDeleteNpcReferencedInAikaQuest": "Der Npc wird in den Aika Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - "CanNotDeleteNpcMentionedInKirjaPage": "Der Npc wird in den Kirja Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - "CanNotDeleteNpcMarkedInKartaMap": "Der Npc ist in den Karta Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - "CanNotDeleteNpcReferencedInTaleDialog": "Der Npc ist in den Tale Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteNpcReferencedInAikaQuest": "Der Npc wird in den Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteNpcMentionedInKirjaPage": "Der Npc wird in den Wiki-Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteNpcMarkedInKartaMap": "Der Npc ist in den Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + "CanNotDeleteNpcReferencedInTaleDialog": "Der Npc ist in den Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", "CanNotDeleteNpcUsedInDailyRoutine": "Der Npc ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", - - "CanNotDeleteDailyRoutineEventReferencedInNpc": "Ein gelöschtes Tagesablauf Ereignis ist in den Tagesabläufen des Npcs \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", - "CanNotDeleteDailyRoutineEventReferencedInTaleDialog": "Ein gelöschtes Tagesablauf Ereignis ist in den Tale Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", - "CanNotDeleteDailyRoutineEventReferencedInAikaQuest": "Ein gelöschtes Tagesablauf Ereignis ist in den Aika Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteObjectUsedInExportSnippet": "Das Objekt ist in Export Snippets von \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteNpcUsedInSkill": "Der Npc ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss er hier erst entfernt werden bevor er gelöscht werden kann.", + + "CanNotDeleteDailyRoutineEventReferencedInNpc": "Das gelöschte Tagesablauf Ereignis {0} ist in den Tagesabläufen des Npcs \"{1}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteDailyRoutineEventReferencedInTaleDialog": "Das gelöschte Tagesablauf Ereignis {0} ist in den Dialogen \"{1}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteDailyRoutineEventReferencedInAikaQuest": "Das gelöschte Tagesablauf Ereignis {0} ist in den Quests \"{1}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteDailyRoutineEventReferencedInSkill": "Das gelöschte Tagesablauf Ereignis {0} ist in den Fähigkeiten \"{1}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteDailyRoutineEventUsedInExportSnippet": "Das gelöschte Tagesablauf Ereignis {0} ist in Export Snippets von \"{1}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "OnlyOneFileAllowed": "Es darf nur exakt eine Datei hochgeladen werden.", "CouldNotUploadImage": "Bild konnte nicht hochgeladen werden.", "ImageFormatNotSupported": "Das Bildformat wird nicht unterstützt.", - "DuplicateFieldNameExist": "Es existitieren mehrere Felder mit gleichem Namen.", + "DuplicateFieldNameExist": "Es existieren mehrere Felder mit gleichem Namen.", + + "TemplateIsForDifferentProject": "Das hinterlegte Template gehört einem anderen Projekt. Bitte wechsel zu diesem Projekt.", "ImportFieldValuesObjectNotFound": "Der Npc wurde nicht gefunden.", "ImportFieldValuesFieldNotFoundInTemplate": "Das Feld {0} wurde weder im Template noch im Npc gefunden. Der Wert kann nicht importiert werden.", @@ -24,5 +30,7 @@ "ImportFieldValuesObjectCouldNotBeUpdated": "Npc konnte nicht aktualisiert werden.", "ImportFieldValuesObjectCouldNotBeCreated": "Npc konnte nicht angelegt werden.", "ImportFieldValuesNoValidTemplateSpecified": "Es ist keine gültige Template Id in der CSV-Datei angegeben. Bitte exportier eine Vorlagen CSV und nutze diese für den Import.", - "ImportFieldValuesNoValidRows": "Keine gültige Zeilen gefunden. Bitte trag Zeilen für den Import ein." + "ImportFieldValuesNoValidRows": "Keine gültige Zeilen gefunden. Bitte trag Zeilen für den Import ein.", + + "TimeFormat": "hh:mm" } \ No newline at end of file diff --git a/Resources/Controllers/Api/KortistoApiController.en.json b/Resources/Controllers/Api/KortistoApiController.en.json index 6333223d..99b6d8a0 100644 --- a/Resources/Controllers/Api/KortistoApiController.en.json +++ b/Resources/Controllers/Api/KortistoApiController.en.json @@ -1,15 +1,19 @@ { "FolderNotEmpty": "The folder is not empty.", - "CanNotDeleteNpcReferencedInAikaQuest": "The npc is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteNpcMentionedInKirjaPage": "The npc is mentioned in the Kirja pages \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteNpcMarkedInKartaMap": "The npc is marked in the Karta maps \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteNpcReferencedInTaleDialog": "The npc is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteNpcReferencedInAikaQuest": "The npc is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteNpcMentionedInKirjaPage": "The npc is mentioned in the wiki pages \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteNpcMarkedInKartaMap": "The npc is marked in the maps \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteNpcReferencedInTaleDialog": "The npc is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteNpcUsedInDailyRoutine": "The npc is referenced in the daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteObjectUsedInExportSnippet": "The object is referenced in export snippets of \"{0}\". To prevent errors while exporting it must be deleted there first.", + "CanNotDeleteNpcUsedInSkill": "The npc is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteDailyRoutineEventReferencedInNpc": "A deleted daily routine event is referenced in the daily routines of the Npcs \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteDailyRoutineEventReferencedInTaleDialog": "A deleted daily routine event is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteDailyRoutineEventReferencedInAikaQuest": "A deleted daily routine event is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteDailyRoutineEventReferencedInNpc": "The deleted daily routine event {0} is referenced in the daily routines of the npcs \"{1}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteDailyRoutineEventReferencedInTaleDialog": "The deleted daily routine event {0} routine event is referenced in the dialogs \"{1}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteDailyRoutineEventReferencedInAikaQuest": "The deleted daily routine event {0} is referenced in the quests \"{1}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteDailyRoutineEventReferencedInSkill": "The deleted daily routine event {0} is referenced in the skills \"{1}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteDailyRoutineEventUsedInExportSnippet": "The deleted daily routine event {0} is referenced in export snippets of \"{0}\". To prevent errors while exporting it must be deleted there first.", "OnlyOneFileAllowed": "You must upload exactly one image file.", "CouldNotUploadImage": "Image could not be uploaded.", @@ -17,6 +21,8 @@ "DuplicateFieldNameExist": "Multiple fields with the same name exist.", + "TemplateIsForDifferentProject": "The specified template belongs to a different project. Please switch to that project.", + "ImportFieldValuesObjectNotFound": "Npc not found.", "ImportFieldValuesFieldNotFoundInTemplate": "The field {0} was not found in the template nor in the npc. The value cannot be imported.", "ImportFieldValuesNameIsEmpty": "The name must not be empty.", @@ -24,5 +30,7 @@ "ImportFieldValuesObjectCouldNotBeUpdated": "Npc could not be updated.", "ImportFieldValuesObjectCouldNotBeCreated": "Npc could not be created.", "ImportFieldValuesNoValidTemplateSpecified": "No valid template id was specified in the CSV file. Please export a CSV template using the CSV export functionality for an import.", - "ImportFieldValuesNoValidRows": "No valid rows to import. Please enter some rows to import." + "ImportFieldValuesNoValidRows": "No valid rows to import. Please enter some rows to import.", + + "TimeFormat": "hh:mm" } \ No newline at end of file diff --git a/Resources/Controllers/Api/StyrApiController.de.json b/Resources/Controllers/Api/StyrApiController.de.json index 47c9590c..5c3a8d8f 100644 --- a/Resources/Controllers/Api/StyrApiController.de.json +++ b/Resources/Controllers/Api/StyrApiController.de.json @@ -1,18 +1,22 @@ { "FolderNotEmpty": "Der Ordner ist nicht leer.", - "CanNotDeleteItemReferencedInAikaQuest": "Das Item wird in den Aika Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", - "CanNotDeleteItemMentionedInKirjaPage": "Das Item wird in den Kirja Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteItemReferencedInAikaQuest": "Das Item wird in den Quests \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteItemMentionedInKirjaPage": "Das Item wird in den Wiki-Seiten \"{0}\" erwähnt. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "CanNotDeleteItemMarkedInKartaMap": "Das Item ist in den Karta Karten \"{0}\" markiert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", - "CanNotDeleteItemReferencedInTaleDialog": "Das Item ist in den Tale Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteItemReferencedInTaleDialog": "Das Item ist in den Dialogen \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "CanNotDeleteItemUsedInInventory": "Das Item wird in den Inventaren der Npcs \"{0}\" benutzt. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "CanNotDeleteItemUsedInDailyRoutine": "Das Item ist in den Tagesabläufen von \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteObjectUsedInExportSnippet": "Das Objekt ist in Export Snippets von \"{0}\" referenziert. Um Export Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", + "CanNotDeleteItemUsedInSkill": "Das Item ist in den Fähigkeiten \"{0}\" referenziert. Um Story Fehler zu verhindern muss es hier erst entfernt werden bevor es gelöscht werden kann.", "OnlyOneFileAllowed": "Es darf nur exakt eine Datei hochgeladen werden.", "CouldNotUploadImage": "Bild konnte nicht hochgeladen werden.", "ImageFormatNotSupported": "Das Bildformat wird nicht unterstützt.", - "DuplicateFieldNameExist": "Es existitieren mehrere Felder mit gleichem Namen.", + "DuplicateFieldNameExist": "Es existieren mehrere Felder mit gleichem Namen.", + + "TemplateIsForDifferentProject": "Das hinterlegte Template gehört einem anderen Projekt. Bitte wechsel zu diesem Projekt.", "ImportFieldValuesObjectNotFound": "Das Item wurde nicht gefunden.", "ImportFieldValuesFieldNotFoundInTemplate": "Das Feld {0} wurde weder im Template noch im Item gefunden. Der Wert kann nicht importiert werden.", diff --git a/Resources/Controllers/Api/StyrApiController.en.json b/Resources/Controllers/Api/StyrApiController.en.json index 45e971c2..1189ac93 100644 --- a/Resources/Controllers/Api/StyrApiController.en.json +++ b/Resources/Controllers/Api/StyrApiController.en.json @@ -1,12 +1,14 @@ { "FolderNotEmpty": "The folder is not empty.", - "CanNotDeleteItemReferencedInAikaQuest": "The item is referenced in the Aika quests \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteItemMentionedInKirjaPage": "The item is mentioned in the Kirja pages \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteItemMarkedInKartaMap": "The item is marked in the Karta maps \"{0}\". To prevent errors in the story it must be deleted there first.", - "CanNotDeleteItemReferencedInTaleDialog": "The item is referenced in the Tale dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteItemReferencedInAikaQuest": "The item is referenced in the quests \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteItemMentionedInKirjaPage": "The item is mentioned in the wiki pages \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteItemMarkedInKartaMap": "The item is marked in the maps \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteItemReferencedInTaleDialog": "The item is referenced in the dialogs \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteItemUsedInInventory": "The item is used in the npc inventories \"{0}\". To prevent errors in the story it must be deleted there first.", "CanNotDeleteItemUsedInDailyRoutine": "The item is referenced in daily routines of \"{0}\". To prevent errors in the story it must be deleted there first.", + "CanNotDeleteObjectUsedInExportSnippet": "The object is referenced in export snippets of \"{0}\". To prevent errors while exporting it must be deleted there first.", + "CanNotDeleteItemUsedInSkill": "The item is referenced in the skills \"{0}\". To prevent errors in the story it must be deleted there first.", "OnlyOneFileAllowed": "You must upload exactly one image file.", "CouldNotUploadImage": "Image could not be uploaded.", @@ -14,6 +16,8 @@ "DuplicateFieldNameExist": "Multiple fields with the same name exist.", + "TemplateIsForDifferentProject": "The specified template belongs to a different project. Please switch to that project.", + "ImportFieldValuesObjectNotFound": "Item not found.", "ImportFieldValuesFieldNotFoundInTemplate": "The field {0} was not found in the template nor in the item. The value cannot be imported.", "ImportFieldValuesNameIsEmpty": "The name must not be empty.", diff --git a/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.de.json b/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.de.json new file mode 100644 index 00000000..a575e14f --- /dev/null +++ b/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.de.json @@ -0,0 +1,3 @@ +{ + "ErrorContextReference": "Referenz" +} \ No newline at end of file diff --git a/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.en.json b/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.en.json new file mode 100644 index 00000000..2a6736ca --- /dev/null +++ b/Resources/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.en.json @@ -0,0 +1,3 @@ +{ + "ErrorContextReference": "Reference" +} \ No newline at end of file diff --git a/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.de.json b/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.de.json new file mode 100644 index 00000000..1190d493 --- /dev/null +++ b/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.de.json @@ -0,0 +1,11 @@ +{ + "PlaceholderDesc_ReferenceText": "Beschreibungstext des Verweises.", + "PlaceholderDesc_ObjectType": "Art des Objekts. Kann Npc, Item, Skill, Quest, WikiPage, MapMarker oder NpcDailyRoutineEvent sein.", + "PlaceholderDesc_Npc": "Npc auf den verwiesen wird. Ist nur gefüllt wenn der Typ Npc oder NpcDailyRoutineEvent ist.", + "PlaceholderDesc_Item": "Item auf das verwiesen wird. Ist nur gefüllt wenn der Typ Item ist.", + "PlaceholderDesc_Skill": "Fähigkeit auf die verwiesen wird. Ist nur gefüllt wenn der Typ Skill ist.", + "PlaceholderDesc_Quest": "Quest auf den verwiesen wird. Ist nur gefüllt wenn der Typ Quest ist.", + "PlaceholderDesc_WikiPage": "Wiki-Seite auf die verwiesen wird. Ist nur gefüllt wenn der Typ WikiPage ist.", + "PlaceholderDesc_DailyRoutineEvent": "Tagesablauf Ereignis auf das verwiesen wird. Ist nur gefüllt wenn der Typ NpcDailyRoutineEvent ist.", + "PlaceholderDesc_Marker": "Karten Markierung auf die verwiesen wird. Ist nur gefüllt wenn der Typ MapMarker ist." +} \ No newline at end of file diff --git a/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.en.json b/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.en.json new file mode 100644 index 00000000..b44103b8 --- /dev/null +++ b/Resources/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.en.json @@ -0,0 +1,11 @@ +{ + "PlaceholderDesc_ReferenceText": "Description text of the reference.", + "PlaceholderDesc_ObjectType": "Type of the object. Can be Npc, Item, Skill, Quest, WikiPage, MapMarker or NpcDailyRoutineEvent.", + "PlaceholderDesc_Npc": "Npc which is referenced. Is only filled if the type is Npc or NpcDailyRoutineEvent.", + "PlaceholderDesc_Item": "Item which is referenced. Is only filled if the type is Item.", + "PlaceholderDesc_Skill": "Skill which is referenced. Is only filled if the type is Skill.", + "PlaceholderDesc_Quest": "Quest which is referenced. Is only filled if the type is Quest.", + "PlaceholderDesc_WikiPage": "Wiki page which is referenced. Is only filled if the type is WikiPage.", + "PlaceholderDesc_DailyRoutineEvent": "Daily routine event which is referenced. Is only filled if the type is NpcDailyRoutineEvent.", + "PlaceholderDesc_Marker": "Map marker which is referenced. Is only filled if the type is MapMarker." +} \ No newline at end of file diff --git a/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.de.json b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.de.json new file mode 100644 index 00000000..a2922446 --- /dev/null +++ b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.de.json @@ -0,0 +1,7 @@ +{ + "PlaceholderDesc_MapId": "Id der Karte zu der der Marker gehört.", + "PlaceholderDesc_MapName": "Name der Karte zu der der Marker gehört.", + "PlaceholderDesc_MarkerType": "Art des Markers.", + "PlaceholderDesc_MarkerId": "Id des Markers.", + "PlaceholderDesc_MarkerName": "Name des Markers." +} \ No newline at end of file diff --git a/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.en.json b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.en.json new file mode 100644 index 00000000..7252bd2a --- /dev/null +++ b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.en.json @@ -0,0 +1,7 @@ +{ + "PlaceholderDesc_MapId": "Id of the map to which the marker belongs.", + "PlaceholderDesc_MapName": "Name of the map to which the marker belongs.", + "PlaceholderDesc_MarkerType": "Type of the marker.", + "PlaceholderDesc_MarkerId": "Id of the marker.", + "PlaceholderDesc_MarkerName": "Name of the marker." +} \ No newline at end of file diff --git a/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.de.json b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.de.json new file mode 100644 index 00000000..d7954e4b --- /dev/null +++ b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.de.json @@ -0,0 +1,4 @@ +{ + "PlaceholderDesc_Name": "Name der Wiki-Seite", + "PlaceholderDesc_Content": "Inhalt der Wiki-Seite" +} \ No newline at end of file diff --git a/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.en.json b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.en.json new file mode 100644 index 00000000..a3ac3976 --- /dev/null +++ b/Resources/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.en.json @@ -0,0 +1,4 @@ +{ + "PlaceholderDesc_Name": "Name of the wiki page", + "PlaceholderDesc_Content": "Content of the wiki page" +} \ No newline at end of file diff --git a/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.de.json b/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.de.json index b9eadc33..6066b0ba 100644 --- a/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.de.json +++ b/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.de.json @@ -4,8 +4,12 @@ "BlankValue": "", + "NpcWasDeleted": "", "ItemWasDeleted": "", "SkillWasDeleted": "", + "QuestWasDeleted": "", + "WikiPageWasDeleted": "", + "MapWasDeleted": "", "PropertyNameName": "Name", "PropertyNameIsPlayerNpc": "Ist Spieler", @@ -27,6 +31,7 @@ "PropertyNameAddedInChapter": "In Kapitel hinzugefügt", "PropertyNameDeletedInChapter": "In Kapitel gelöscht", "PropertyNameGeoData": "Geometrie Daten", + "PropertyNameReferenceText": "Beschreibung", "EntryRemoved": "Eintrag '{0}' entfernt.", "EntryAdded": "Eintrag '{0}' hinzugefügt.", @@ -42,11 +47,14 @@ "NodeChoicesChanged": "Auswahl Knoten geändert:", "NodeActionsChanged": "Aktionsknoten geändert:", "NodeConditionsChanged": "Bedingungsknoten geändert:", + "NodeReferenceChanged": "Referenzknoten geändert:", "ActionTypeChanged": "Aktionsart geändert", "ActionDataChanged": "Aktionsdaten geändert", "ConditionsChanged": "Bedingungen geändert:", "ConditionDataChanged": "Bedingungsdaten geändert", "Condition": "Bedingung", + "ReferencedObjectChanged": "Referenziertes Objekt geändert", + "ReferenceTextChanged": "Verbindungstext geändert", "Node": "Knoten", "NodeConnection": "Knoten Verbindung", "ChoicesChanged": "Auswahlmöglichkeiten geändert:", diff --git a/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.en.json b/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.en.json index c1396d02..42462070 100644 --- a/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.en.json +++ b/Resources/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.en.json @@ -4,8 +4,12 @@ "BlankValue": "", + "NpcWasDeleted": "", "ItemWasDeleted": "", "SkillWasDeleted": "", + "QuestWasDeleted": "", + "WikiPageWasDeleted": "", + "MapWasDeleted": "", "PropertyNameName": "Name", "PropertyNameIsPlayerNpc": "Is Player", @@ -27,6 +31,7 @@ "PropertyNameAddedInChapter": "Added in chapter", "PropertyNameDeletedInChapter": "Deleted in chapter", "PropertyNameGeoData": "Geometry data", + "PropertyNameReferenceText": "Description", "EntryRemoved": "Entry '{0}' removed.", "EntryAdded": "Entry '{0}' added.", @@ -42,11 +47,14 @@ "NodeChoicesChanged": "Choice nodes changed:", "NodeActionsChanged": "Action nodes changed:", "NodeConditionsChanged": "Condition nodes changed:", + "NodeReferenceChanged": "Reference nodes changed:", "ActionTypeChanged": "Action type changed", "ActionDataChanged": "Action data changed", "ConditionsChanged": "Conditions changed:", "ConditionDataChanged": "Condition data changed", "Condition": "Condition", + "ReferencedObjectChanged": "Referenced object changed", + "ReferenceTextChanged": "Reference text changed", "Node": "Node", "NodeConnection": "Node connection", "ChoicesChanged": "Choices changed:", diff --git a/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.de.json b/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.de.json new file mode 100644 index 00000000..7042ab28 --- /dev/null +++ b/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.de.json @@ -0,0 +1,4 @@ +{ + "Reference": "Referenz", + "EmptyChoiceText": "" +} \ No newline at end of file diff --git a/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.en.json b/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.en.json new file mode 100644 index 00000000..ad046339 --- /dev/null +++ b/Resources/Services/ReferenceAnalyzer/ReferenceAnalyzer.en.json @@ -0,0 +1,4 @@ +{ + "Reference": "Reference", + "EmptyChoiceText": "" +} \ No newline at end of file diff --git a/Resources/Views/Aika/Quest.de.json b/Resources/Views/Aika/Quest.de.json index a8d2be85..fcef70f0 100644 --- a/Resources/Views/Aika/Quest.de.json +++ b/Resources/Views/Aika/Quest.de.json @@ -16,12 +16,21 @@ "NoFieldsAdded": "Es wurden noch keine Felder zum Quest hinzugefügt", "Connections": "Verknüpfungen", - "UsedInAikaDetailView": "In Aika Detailansichten genutzt:", - "UsedInAikaQuest": "In Aika Quests genutzt:", - "MentionedInKirjaPages": "In Kirja Seiten erwähnt:", - "ReferencedInTaleDialogs": "Referenziert in Tale Dialogen:", - "HasMarkersInKartaMaps": "Markierungen in Karta Maps:", + "UsedInAikaDetailView": "In Kapitel Detailansichten genutzt:", + "UsedInAikaQuest": "In Quests genutzt:", + "MentionedInKirjaPages": "In Wiki-Seiten erwähnt:", + "ReferencedInTaleDialogs": "Referenziert in Dialogen:", + "HasMarkersInKartaMaps": "Markierungen in Karten:", "ReferencedInDailyRoutines": "Referenziert in Tagesabläufen:", + "ReferencedInEvneSkills": "Referenziert in Fähigkeiten:", + "ReferencedInExportSnippets": "Referenziert in Export Snippets:", + + "ClickHereForDetailedReferences": "Der Quest ist in mehreren Objekten referenziert. Klick hier für Details.", + "ClickHereToCloseDetailedReferences": "Hier klicken um die Referenzen zu schließen.", + + "Npc": "Npc", + "Item": "Item", + "Skill": "Fähigkeit", "Name": "Name", "Description": "Beschreibung", @@ -32,6 +41,7 @@ "ActionNode": "Aktion", "FinishNode": "Abschluss", "AllDone": "Alles abgeschlossen", + "ReferenceNode": "Referenz", "AreYouSure": "Bist du sicher?", "AreYouSureYouWantToDeleteTheQuest": "Bist du sicher das der Quest gelöscht werden soll?", diff --git a/Resources/Views/Aika/Quest.en.json b/Resources/Views/Aika/Quest.en.json index 5864f0cb..1def5d61 100644 --- a/Resources/Views/Aika/Quest.en.json +++ b/Resources/Views/Aika/Quest.en.json @@ -16,12 +16,21 @@ "NoFieldsAdded": "No fields have been added to the quest", "Connections": "Connections", - "UsedInAikaDetailView": "Used in Aika detail views:", - "UsedInAikaQuest": "Used in Aika quests:", - "MentionedInKirjaPages": "Mentioned in Kirja pages:", - "ReferencedInTaleDialogs": "Referenced in Tale dialogs:", - "HasMarkersInKartaMaps": "Marked in Karta maps:", + "UsedInAikaDetailView": "Used in chapter detail views:", + "UsedInAikaQuest": "Used in quests:", + "MentionedInKirjaPages": "Mentioned in wiki pages:", + "ReferencedInTaleDialogs": "Referenced in dialogs:", + "HasMarkersInKartaMaps": "Marked in maps:", "ReferencedInDailyRoutines": "Referenced in daily routines:", + "ReferencedInEvneSkills": "Referenced in skills:", + "ReferencedInExportSnippets": "Referenced in export snippets:", + + "ClickHereForDetailedReferences": "The quest is referenced in multiple objects. Click here for details.", + "ClickHereToCloseDetailedReferences": "Click here to close the references.", + + "Npc": "Npc", + "Item": "Item", + "Skill": "Skill", "Name": "Name", "Description": "Description", @@ -32,6 +41,7 @@ "ActionNode": "Action", "FinishNode": "Finish", "AllDone": "All done", + "ReferenceNode": "Reference", "AreYouSure": "Are you sure?", "AreYouSureYouWantToDeleteTheQuest": "Are you sure you want to delete the quest?", diff --git a/Resources/Views/Evne/Skill.de.json b/Resources/Views/Evne/Skill.de.json index 2fd960d2..14fccd84 100644 --- a/Resources/Views/Evne/Skill.de.json +++ b/Resources/Views/Evne/Skill.de.json @@ -25,6 +25,7 @@ "TextNode": "Text", "ActionNode": "Aktion", "ConditionNode": "Bedingung", + "ReferenceNode": "Referenz", "ExportResult": "Export Ergebnis", "Warning": "Warnung:", @@ -47,16 +48,25 @@ "UnsavedChanges": "Ungespeicherte Änderungen", "AreYouSureYouWantToExportUnsavedChanges": "Es liegen ungespeicherte Änderungen vor. Der Export wird einen veralteten Stand reflektieren. Bist du sicher das du einen veralteten Stand exportieren willst?", - "ReferencedInAikaQuests": "Referenziert in Aika Quests:", + "ReferencedInAikaQuests": "Referenziert in Quests:", - "MentionedInKirjaPages": "Erwähnt in Kirja Seiten:", + "MentionedInKirjaPages": "Erwähnt in Wiki-Seiten:", - "MarkedInKartaMaps": "Markiert in Karta Karten:", + "MarkedInKartaMaps": "Markiert in Karten:", "MarkedInMapNTimes": "Fähigkeit ist in Karte {{0}} mal markiert. Kein Zoom auf Markierung möglich.", - "ReferencedInTaleDialogs": "Referenziert in Tale Dialogen:", + "ReferencedInTaleDialogs": "Referenziert in Dialogen:", "ReferencedInDailyRoutines": "Referenziert in Tagesabläufen:", + "ReferencedInExportSnippets": "Referenziert in Export Snippets:", + + "ReferencedInEvneSkills": "Referenziert in Fähigkeiten:", + + "ClickHereForDetailedReferences": "Der Skill ist in mehreren Objekten referenziert. Klick hier für Details.", + "ClickHereToCloseDetailedReferences": "Hier klicken um die Referenzen zu schließen.", + + "Npc": "Npc", + "Item": "Item", "LearnedByNpcs": "Gelernt durch Npcs:", diff --git a/Resources/Views/Evne/Skill.en.json b/Resources/Views/Evne/Skill.en.json index 58caf43b..37671125 100644 --- a/Resources/Views/Evne/Skill.en.json +++ b/Resources/Views/Evne/Skill.en.json @@ -25,6 +25,7 @@ "TextNode": "Text", "ActionNode": "Action", "ConditionNode": "Condition", + "ReferenceNode": "Reference", "ExportResult": "Export result", "Warning": "Warning:", @@ -47,16 +48,25 @@ "UnsavedChanges": "Unsaved changes", "AreYouSureYouWantToExportUnsavedChanges": "There are unsaved changes. The export will reflect an old state. Are you sure you want to export the old state?", - "ReferencedInAikaQuests": "Referenced in Aika quests:", + "ReferencedInAikaQuests": "Referenced in quests:", - "MentionedInKirjaPages": "Mentioned in Kirja pages:", + "MentionedInKirjaPages": "Mentioned in pages:", - "MarkedInKartaMaps": "Marked in Karta maps:", + "MarkedInKartaMaps": "Marked in maps:", "MarkedInMapNTimes": "Skill is marked in the map {{0}} times. No zoom on marker is possible.", - "ReferencedInTaleDialogs": "Referenced in Tale dialogs:", + "ReferencedInTaleDialogs": "Referenced in dialogs:", "ReferencedInDailyRoutines": "Referenced in daily routines:", + "ReferencedInExportSnippets": "Referenced in export snippets:", + + "ReferencedInEvneSkills": "Referenced in skills:", + + "ClickHereForDetailedReferences": "The skill is referenced in multiple objects. Click here for details.", + "ClickHereToCloseDetailedReferences": "Click here to close the references.", + + "Npc": "Npc", + "Item": "Item", "LearnedByNpcs": "Learned by Npcs:", diff --git a/Resources/Views/Export/FunctionGenerationCondition.de.json b/Resources/Views/Export/FunctionGenerationCondition.de.json index 8348c6d3..43ccfbbd 100644 --- a/Resources/Views/Export/FunctionGenerationCondition.de.json +++ b/Resources/Views/Export/FunctionGenerationCondition.de.json @@ -6,6 +6,7 @@ "NodeTypeChoice": "Auswahl", "NodeTypeCondition": "Bedingung", "NodeTypeAction": "Aktion", + "NodeTypeReference": "Referenz", "GenerationRules": "Regeln die eine Funktion generieren", "PreventGenerationRules": "Regeln die Funktionsgenerierung verhindern", diff --git a/Resources/Views/Export/FunctionGenerationCondition.en.json b/Resources/Views/Export/FunctionGenerationCondition.en.json index 22f0d4da..a2564418 100644 --- a/Resources/Views/Export/FunctionGenerationCondition.en.json +++ b/Resources/Views/Export/FunctionGenerationCondition.en.json @@ -6,6 +6,7 @@ "NodeTypeChoice": "Choice", "NodeTypeCondition": "Condition", "NodeTypeAction": "Action", + "NodeTypeReference": "Reference", "GenerationRules": "Rules that generate a function", "PreventGenerationRules": "Rules that prevent generating a function", diff --git a/Resources/Views/Kirja/Index.de.json b/Resources/Views/Kirja/Index.de.json index 080fec40..e033f0c1 100644 --- a/Resources/Views/Kirja/Index.de.json +++ b/Resources/Views/Kirja/Index.de.json @@ -31,12 +31,14 @@ "ToogleSidebar": "Hier klicken um die Seitenleiste zu öffnen oder schließen", "Connections": "Verknüpfungen", - "MentionedInPages": "In Kirja Seiten erwähnt", + "MentionedInPages": "In Wiki-Seiten erwähnt", "Quests": "Quests", "Npcs": "Npcs", + "Dialogs": "Dialoge", "Items": "Items", "Skills": "Fähigkeiten", "Maps": "Karten", + "ExportSnippets": "Export snippets", "MarkedInMapNTimes": "Seite ist in Karte {{0}} mal markiert. Kein Zoom auf Markierung möglich.", "Attachments": "Anhänge", "SaveThePageToUploadFiles": "Speichere die Seite um Anhänge anzufügen", @@ -44,6 +46,8 @@ "DeleteAttachmentToolTip": "Hier klicken um den Anhang zu löschen", "ShowVersionsOfPage": "Versionen anzeigen", "OpenPageOverview": "Seitenübersicht öffnen", + "OnPage": "(Auf dieser Seite)", + "ReferencedIn": "(Referenziert in)", "Versions": "Versionen", "VersionNumber": "#", diff --git a/Resources/Views/Kirja/Index.en.json b/Resources/Views/Kirja/Index.en.json index 464cd581..ece0558e 100644 --- a/Resources/Views/Kirja/Index.en.json +++ b/Resources/Views/Kirja/Index.en.json @@ -31,12 +31,14 @@ "ToogleSidebar": "Click here to open or close the sidebar", "Connections": "Connections", - "MentionedInPages": "Mentioned in Kirja page", + "MentionedInPages": "Mentioned in wiki pages", "Quests": "Quests", "Npcs": "Npcs", + "Dialogs": "Dialogs", "Items": "Items", "Skills": "Skills", "Maps": "Maps", + "ExportSnippets": "Export snippets", "MarkedInMapNTimes": "Page is marked in the map {{0}} times. No zoom on marker is possible.", "Attachments": "Attachments", "SaveThePageToUploadFiles": "Save the page to upload files", @@ -44,6 +46,8 @@ "DeleteAttachmentToolTip": "Click here to delete the attachment", "ShowVersionsOfPage": "Show versions", "OpenPageOverview": "Open page list", + "OnPage": "(On page)", + "ReferencedIn": "(Referenced in)", "Versions": "Versions", "VersionNumber": "#", diff --git a/Resources/Views/Kortisto/Npc.de.json b/Resources/Views/Kortisto/Npc.de.json index 2e418455..b70ecfbf 100644 --- a/Resources/Views/Kortisto/Npc.de.json +++ b/Resources/Views/Kortisto/Npc.de.json @@ -102,16 +102,25 @@ "UnsavedChanges": "Ungespeicherte Änderungen", "AreYouSureYouWantToExportUnsavedChanges": "Es liegen ungespeicherte Änderungen vor. Der Export wird einen veralteten Stand reflektieren. Bist du sicher das du einen veralteten Stand exportieren willst?", - "ReferencedInAikaQuests": "Referenziert in Aika Quests:", + "ReferencedInAikaQuests": "Referenziert in Quests:", - "MentionedInKirjaPages": "Erwähnt in Kirja Seiten:", + "MentionedInKirjaPages": "Erwähnt in Wiki-Seiten:", - "MarkedInKartaMaps": "Markiert in Karta Karten:", + "MarkedInKartaMaps": "Markiert in Karten:", "MarkedInMapNTimes": "Npc ist in Karte {{0}} mal markiert. Kein Zoom auf Markierung möglich.", - "ReferencedInTaleDialogs": "Referenziert in Tale Dialogen:", + "ReferencedInTaleDialogs": "Referenziert in Dialogen:", "ReferencedInDailyRoutines": "Referenziert in Tagesabläufen:", + "ReferencedInExportSnippets": "Referenziert in Export Snippets:", + + "ReferencedInEvneSkills": "Referenziert in Fähigkeiten:", + + "ClickHereForDetailedReferences": "Der Npc ist in mehreren Objekten referenziert. Klick hier für Details.", + "ClickHereToCloseDetailedReferences": "Hier klicken um die Referenzen zu schließen.", + + "Item": "Item", + "Skill": "Fähigkeit", "AreYouSure": "Bist du sicher?", "AreYouSureYouWantToDeleteTheObject": "Bist du sicher das der Npc gelöscht werden soll?", diff --git a/Resources/Views/Kortisto/Npc.en.json b/Resources/Views/Kortisto/Npc.en.json index 9cebcd42..3658a9c6 100644 --- a/Resources/Views/Kortisto/Npc.en.json +++ b/Resources/Views/Kortisto/Npc.en.json @@ -102,16 +102,25 @@ "UnsavedChanges": "Unsaved changes", "AreYouSureYouWantToExportUnsavedChanges": "There are unsaved changes. The export will reflect an old state. Are you sure you want to export the old state?", - "ReferencedInAikaQuests": "Referenced in Aika quests:", + "ReferencedInAikaQuests": "Referenced in quests:", - "MentionedInKirjaPages": "Mentioned in Kirja pages:", + "MentionedInKirjaPages": "Mentioned in wiki pages:", - "MarkedInKartaMaps": "Marked in Karta maps:", + "MarkedInKartaMaps": "Marked in maps:", "MarkedInMapNTimes": "Npc is marked in the map {{0}} times. No zoom on marker is possible.", - "ReferencedInTaleDialogs": "Referenced in Tale dialogs:", + "ReferencedInTaleDialogs": "Referenced in dialogs:", "ReferencedInDailyRoutines": "Referenced in daily routines:", + "ReferencedInExportSnippets": "Referenced in export snippets:", + + "ReferencedInEvneSkills": "Referenced in skills:", + + "ClickHereForDetailedReferences": "The npc is referenced in multiple objects. Click here for details.", + "ClickHereToCloseDetailedReferences": "Click here to close the references.", + + "Item": "Item", + "Skill": "Skill", "AreYouSure": "Are you sure?", "AreYouSureYouWantToDeleteTheObject": "Are you sure you want to delete the npc?", diff --git a/Resources/Views/Shared/ChooseObjectDialog.de.json b/Resources/Views/Shared/ChooseObjectDialog.de.json index 4927f121..75018ca4 100644 --- a/Resources/Views/Shared/ChooseObjectDialog.de.json +++ b/Resources/Views/Shared/ChooseObjectDialog.de.json @@ -4,6 +4,15 @@ "Close": "Schließen", "CreateNewPage": "Neue Seite anlegen", + "ObjectType": "Objektart", + "ObjectTypeNpc": "Npc", + "ObjectTypeItem": "Item", + "ObjectTypeSkill": "Fähigkeit", + "ObjectTypeQuest": "Quest", + "ObjectTypeWikiPage": "Wikiseite", + "ObjectTypeDailyRoutine": "Tagesablauf", + "ObjectTypeMarker": "Markierung", + "Search": "Suchen", "PreviousPage": "Vorherige Seite", diff --git a/Resources/Views/Shared/ChooseObjectDialog.en.json b/Resources/Views/Shared/ChooseObjectDialog.en.json index b1f6bad5..06dcf0cb 100644 --- a/Resources/Views/Shared/ChooseObjectDialog.en.json +++ b/Resources/Views/Shared/ChooseObjectDialog.en.json @@ -4,6 +4,15 @@ "Close": "Close", "CreateNewPage": "Create new page", + "ObjectType": "Object type", + "ObjectTypeNpc": "Npc", + "ObjectTypeItem": "Item", + "ObjectTypeSkill": "Skill", + "ObjectTypeQuest": "Quest", + "ObjectTypeWikiPage": "Wiki page", + "ObjectTypeDailyRoutine": "Daily routine", + "ObjectTypeMarker": "Marker", + "Search": "Search", "PreviousPage": "Previous page", diff --git a/Resources/Views/Shared/NodeScriptEditor.de.json b/Resources/Views/Shared/NodeScriptEditor.de.json index 101d0194..c40d1838 100644 --- a/Resources/Views/Shared/NodeScriptEditor.de.json +++ b/Resources/Views/Shared/NodeScriptEditor.de.json @@ -14,7 +14,9 @@ "ConditionNode": "Bedingung", "ActionNode": "Aktion", + "ReferenceNode": "Referenz", + "ChooseGeneralObject": "Objekt auswählen", "ChooseQuest": "Quest auswählen", "ChooseNpc": "Npc auswählen", "ChooseSkill": "Fähigkeit auswählen", diff --git a/Resources/Views/Shared/NodeScriptEditor.en.json b/Resources/Views/Shared/NodeScriptEditor.en.json index 3d9da08d..1c0ab693 100644 --- a/Resources/Views/Shared/NodeScriptEditor.en.json +++ b/Resources/Views/Shared/NodeScriptEditor.en.json @@ -14,7 +14,9 @@ "ConditionNode": "Condition", "ActionNode": "Action", + "ReferenceNode": "Reference", + "ChooseGeneralObject": "Choose object", "ChooseQuest": "Choose quest", "ChooseNpc": "Choose npc", "ChooseSkill": "Choose skill", diff --git a/Resources/Views/Styr/Item.de.json b/Resources/Views/Styr/Item.de.json index c753c310..082ba7d6 100644 --- a/Resources/Views/Styr/Item.de.json +++ b/Resources/Views/Styr/Item.de.json @@ -42,19 +42,28 @@ "UnsavedChanges": "Ungespeicherte Änderungen", "AreYouSureYouWantToExportUnsavedChanges": "Es liegen ungespeicherte Änderungen vor. Der Export wird einen veralteten Stand reflektieren. Bist du sicher das du einen veralteten Stand exportieren willst?", - "ReferencedInAikaQuests": "Referenziert in Aika Quests:", + "ReferencedInAikaQuests": "Referenziert in Quests:", - "MentionedInKirjaPages": "Erwähnt in Kirja Seiten:", + "MentionedInKirjaPages": "Erwähnt in Wiki-Seiten:", - "MarkedInKartaMaps": "Markiert in Karta Karten:", + "MarkedInKartaMaps": "Markiert in Karten:", "MarkedInMapNTimes": "Item ist in Karte {{0}} mal markiert. Kein Zoom auf Markierung möglich.", - "ReferencedInTaleDialogs": "Referenziert in Tale Dialogen:", + "ReferencedInTaleDialogs": "Referenziert in Dialogen:", "ReferencedInDailyRoutines": "Referenziert in Tagesabläufen:", + "ReferencedInExportSnippets": "Referenziert in Export Snippets:", "ReferencedInNpcInventories": "In Npc Inventaren:", + + "ReferencedInEvneSkills": "Referenziert in Fähigkeiten:", + "ClickHereForDetailedReferences": "Das Item ist in mehreren Objekten referenziert. Klick hier für Details.", + "ClickHereToCloseDetailedReferences": "Hier klicken um die Referenzen zu schließen.", + + "Npc": "Npc", + "Skill": "Fähigkeit", + "AreYouSure": "Bist du sicher?", "AreYouSureYouWantToDeleteTheObject": "Bist du sicher das das Item gelöscht werden soll?", "AreYouSureYouWantToDeleteTheTemplate": "Bist du sicher das das Template gelöscht werden soll?", diff --git a/Resources/Views/Styr/Item.en.json b/Resources/Views/Styr/Item.en.json index 6b6644b7..2e0374f9 100644 --- a/Resources/Views/Styr/Item.en.json +++ b/Resources/Views/Styr/Item.en.json @@ -42,19 +42,28 @@ "UnsavedChanges": "Unsaved changes", "AreYouSureYouWantToExportUnsavedChanges": "There are unsaved changes. The export will reflect an old state. Are you sure you want to export the old state?", - "ReferencedInAikaQuests": "Referenced in Aika quests:", + "ReferencedInAikaQuests": "Referenced in quests:", - "MentionedInKirjaPages": "Mentioned in Kirja pages:", + "MentionedInKirjaPages": "Mentioned in wiki pages:", - "MarkedInKartaMaps": "Marked in Karta maps:", + "MarkedInKartaMaps": "Marked in maps:", "MarkedInMapNTimes": "Item is marked in the map {{0}} times. No zoom on marker is possible.", - "ReferencedInTaleDialogs": "Referenced in Tale dialogs:", + "ReferencedInTaleDialogs": "Referenced in dialogs:", "ReferencedInDailyRoutines": "Referenced in daily routines:", + "ReferencedInExportSnippets": "Referenced in export snippets:", "ReferencedInNpcInventories": "In npc inventory:", + "ReferencedInEvneSkills": "Referenced in skills:", + + "ClickHereForDetailedReferences": "The item is referenced in multiple objects. Click here for details.", + "ClickHereToCloseDetailedReferences": "Click here to close the references.", + + "Npc": "Npc", + "Skill": "Skill", + "AreYouSure": "Are you sure?", "AreYouSureYouWantToDeleteTheObject": "Are you sure you want to delete the item?", "AreYouSureYouWantToDeleteTheTemplate": "Are you sure you want to delete the template?", diff --git a/Resources/Views/Tale/Index.de.json b/Resources/Views/Tale/Index.de.json index b72be383..c8dcef78 100644 --- a/Resources/Views/Tale/Index.de.json +++ b/Resources/Views/Tale/Index.de.json @@ -12,6 +12,7 @@ "ChoiceNode": "Auswahl", "ActionNode": "Aktion", "ConditionNode": "Bedingung", + "ReferenceNode": "Referenz", "Error": "Fehler", "ErrorOccured": "Ein Fehler ist aufgetreten.", diff --git a/Resources/Views/Tale/Index.en.json b/Resources/Views/Tale/Index.en.json index 18a76f1a..dbb24add 100644 --- a/Resources/Views/Tale/Index.en.json +++ b/Resources/Views/Tale/Index.en.json @@ -12,6 +12,7 @@ "ChoiceNode": "Choice", "ActionNode": "Action", "ConditionNode": "Condition", + "ReferenceNode": "Reference", "Error": "Error", "ErrorOccured": "An error occured.", diff --git a/Services/Export/DailyRoutine/DailyRoutineFunctionRenderer.cs b/Services/Export/DailyRoutine/DailyRoutineFunctionRenderer.cs index 0ef11c59..0bd747d5 100644 --- a/Services/Export/DailyRoutine/DailyRoutineFunctionRenderer.cs +++ b/Services/Export/DailyRoutine/DailyRoutineFunctionRenderer.cs @@ -70,7 +70,7 @@ public async Task> RenderDailyRoutineFunctions(List public class ExportCachedDbAccess : IExportCachedDbAccess { - /// - /// Project Db Access - /// - private readonly IProjectDbAccess _projectDbAccess; - /// /// Export Settings Db Access /// @@ -58,6 +55,16 @@ public class ExportCachedDbAccess : IExportCachedDbAccess /// private readonly IKartaMapDbAccess _mapDbAccess; + /// + /// Wiki Page Db Access + /// + private readonly IKirjaPageDbAccess _pageDbAccess; + + /// + /// User project access + /// + private readonly IUserProjectAccess _userProjectAccess; + /// /// Project config provider /// @@ -109,6 +116,11 @@ public class ExportCachedDbAccess : IExportCachedDbAccess /// private Dictionary _cachedQuest; + /// + /// Cached Wiki Pages + /// + private Dictionary _cachedPages; + /// /// Cached Markers /// @@ -127,7 +139,6 @@ public class ExportCachedDbAccess : IExportCachedDbAccess /// /// Export Cached Db Access /// - /// Project Db Access /// Export Settings Db Access /// Object export snippet Db Access /// Npc Db Access @@ -135,13 +146,14 @@ public class ExportCachedDbAccess : IExportCachedDbAccess /// Skill Db Access /// Quest Db Access /// Map Db Access + /// Page Db Access + /// User project access /// Project config provider /// Include export template Db access - public ExportCachedDbAccess(IProjectDbAccess projectDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IKortistoNpcDbAccess npcDbAccess, - IStyrItemDbAccess itemDbAccess, IEvneSkillDbAccess skillDbAccess, IAikaQuestDbAccess questDbAccess, IKartaMapDbAccess mapDbAccess, IProjectConfigProvider projectConfigProvider, - IIncludeExportTemplateDbAccess includeExportTemplateDbAccess) + public ExportCachedDbAccess(IExportSettingsDbAccess exportSettingsDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IKortistoNpcDbAccess npcDbAccess, IStyrItemDbAccess itemDbAccess, + IEvneSkillDbAccess skillDbAccess, IAikaQuestDbAccess questDbAccess, IKartaMapDbAccess mapDbAccess, IKirjaPageDbAccess pageDbAccess, IUserProjectAccess userProjectAccess, + IProjectConfigProvider projectConfigProvider,IIncludeExportTemplateDbAccess includeExportTemplateDbAccess) { - _projectDbAccess = projectDbAccess; _exportSettingsDbAccess = exportSettingsDbAccess; _objectExportSnippetDbAccess = objectExportSnippetDbAccess; _npcDbAccess = npcDbAccess; @@ -149,6 +161,8 @@ public class ExportCachedDbAccess : IExportCachedDbAccess _skillDbAccess = skillDbAccess; _questDbAccess = questDbAccess; _mapDbAccess = mapDbAccess; + _pageDbAccess = pageDbAccess; + _userProjectAccess = userProjectAccess; _projectConfigProvider = projectConfigProvider; _includeExportTemplateDbAccess = includeExportTemplateDbAccess; @@ -158,23 +172,24 @@ public class ExportCachedDbAccess : IExportCachedDbAccess _cachedItems = new Dictionary(); _cachedSkills = new Dictionary(); _cachedQuest = new Dictionary(); + _cachedPages = new Dictionary(); _cachedMarkers = new Dictionary(); _cachedExportSnippets = new Dictionary>(); _cachedIncludeExportTemplates = new Dictionary(); } /// - /// Returns the project + /// Returns the user project /// /// Project - public async Task GetDefaultProject() + public async Task GetUserProject() { if(_project != null) { return _project; } - _project = await _projectDbAccess.GetDefaultProject(); + _project = await _userProjectAccess.GetUserProject(); return _project; } @@ -189,7 +204,7 @@ public async Task GetMiscProjectConfig() return _miscProjectConfig; } - GoNorthProject defaultProject = await GetDefaultProject(); + GoNorthProject defaultProject = await GetUserProject(); _miscProjectConfig = await _projectConfigProvider.GetMiscConfig(defaultProject.Id); return _miscProjectConfig; } @@ -427,6 +442,28 @@ public async Task GetMarkerById(string mapId, st return markerQueryResult; } + /// + /// Returns a wiki page by its id + /// + /// Page Id + /// Wiki page + public async Task GetWikiPageById(string pageId) + { + if(string.IsNullOrEmpty(pageId)) + { + return null; + } + + if(_cachedPages.ContainsKey(pageId)) + { + return _cachedPages[pageId]; + } + + KirjaPage page = await _pageDbAccess.GetPageById(pageId); + _cachedPages.Add(pageId, page); + return page; + } + /// /// Returns the object export snippets of an object /// diff --git a/Services/Export/Data/IExportCachedDbAccess.cs b/Services/Export/Data/IExportCachedDbAccess.cs index 07750028..39b8007c 100644 --- a/Services/Export/Data/IExportCachedDbAccess.cs +++ b/Services/Export/Data/IExportCachedDbAccess.cs @@ -4,6 +4,7 @@ using GoNorth.Data.Evne; using GoNorth.Data.Exporting; using GoNorth.Data.Karta; +using GoNorth.Data.Kirja; using GoNorth.Data.Kortisto; using GoNorth.Data.Project; using GoNorth.Data.ProjectConfig; @@ -17,10 +18,10 @@ namespace GoNorth.Services.Export.Data public interface IExportCachedDbAccess { /// - /// Returns the project + /// Returns the user project /// /// Project - Task GetDefaultProject(); + Task GetUserProject(); /// /// Returns the export settings for a project @@ -86,6 +87,13 @@ public interface IExportCachedDbAccess /// Marker Task GetMarkerById(string mapId, string markerId); + /// + /// Returns a wiki page by its id + /// + /// Page Id + /// Wiki page + Task GetWikiPageById(string pageId); + /// /// Returns the misc project config /// diff --git a/Services/Export/Dialog/ActionRendering/LegacyRenderingEngine/NpcValueChangeRenderer.cs b/Services/Export/Dialog/ActionRendering/LegacyRenderingEngine/NpcValueChangeRenderer.cs index d8af3bb7..707cf862 100644 --- a/Services/Export/Dialog/ActionRendering/LegacyRenderingEngine/NpcValueChangeRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/LegacyRenderingEngine/NpcValueChangeRenderer.cs @@ -72,7 +72,7 @@ protected override async Task GetValueObject(ValueFieldAct { if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); flexFieldObject = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(flexFieldObject == null) { diff --git a/Services/Export/Dialog/ActionRendering/ScribanRenderingEngine/ScribanNpcValueChangeRenderer.cs b/Services/Export/Dialog/ActionRendering/ScribanRenderingEngine/ScribanNpcValueChangeRenderer.cs index dad50e47..ff24bb92 100644 --- a/Services/Export/Dialog/ActionRendering/ScribanRenderingEngine/ScribanNpcValueChangeRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/ScribanRenderingEngine/ScribanNpcValueChangeRenderer.cs @@ -54,7 +54,7 @@ protected override async Task GetValueObject(ValueFieldAct { if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); flexFieldObject = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(flexFieldObject == null) { diff --git a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseChangeNpcStateActionRenderer.cs b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseChangeNpcStateActionRenderer.cs index 0f37bb7d..0a494178 100644 --- a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseChangeNpcStateActionRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseChangeNpcStateActionRenderer.cs @@ -106,7 +106,7 @@ private async Task GetNpc(FlexFieldObject flexFieldObject, { if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); flexFieldObject = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(flexFieldObject == null) { diff --git a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseMoveNpcActionRenderer.cs b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseMoveNpcActionRenderer.cs index 81a09b87..3ca9aa2c 100644 --- a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseMoveNpcActionRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseMoveNpcActionRenderer.cs @@ -182,7 +182,7 @@ private async Task GetNpc(MoveNpcActionData parsedData, FlexFieldOb if(_isPlayer) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); return await _cachedDbAccess.GetPlayerNpc(project.Id); } diff --git a/Services/Export/Dialog/ActionRendering/SharedRendering/BasePlayAnimationActionRenderer.cs b/Services/Export/Dialog/ActionRendering/SharedRendering/BasePlayAnimationActionRenderer.cs index 8d2f3426..7be79738 100644 --- a/Services/Export/Dialog/ActionRendering/SharedRendering/BasePlayAnimationActionRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/SharedRendering/BasePlayAnimationActionRenderer.cs @@ -107,7 +107,7 @@ private async Task GetNpc(FlexFieldObject flexFieldObject, { if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); flexFieldObject = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(flexFieldObject == null) { diff --git a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseUseItemActionRenderer.cs b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseUseItemActionRenderer.cs index 66bcbdab..877101d6 100644 --- a/Services/Export/Dialog/ActionRendering/SharedRendering/BaseUseItemActionRenderer.cs +++ b/Services/Export/Dialog/ActionRendering/SharedRendering/BaseUseItemActionRenderer.cs @@ -150,7 +150,7 @@ private async Task GetNpc(FlexFieldObject flexFieldObject, } else if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); KortistoNpc npc = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(npc == null) { diff --git a/Services/Export/Dialog/ConditionParsingUtil.cs b/Services/Export/Dialog/ConditionParsingUtil.cs new file mode 100644 index 00000000..e8704813 --- /dev/null +++ b/Services/Export/Dialog/ConditionParsingUtil.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace GoNorth.Services.Export.Dialog +{ + /// + /// Util class to parse conditions + /// + public static class ConditionParsingUtil + { + /// + /// Parses conditions elements + /// + /// Condition elements to parse + /// Parsed condition elements + public static List ParseConditionElements(string conditionElements) + { + JsonSerializerOptions jsonOptions = new JsonSerializerOptions(); + jsonOptions.Converters.Add(new JsonStringEnumConverter()); + jsonOptions.Converters.Add(new JsonConditionDataParser()); + jsonOptions.PropertyNameCaseInsensitive = true; + + return JsonSerializer.Deserialize>(conditionElements, jsonOptions); + } + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/ConditionRenderer.cs b/Services/Export/Dialog/ConditionRenderer.cs index 2fe1dbe6..e56e8799 100644 --- a/Services/Export/Dialog/ConditionRenderer.cs +++ b/Services/Export/Dialog/ConditionRenderer.cs @@ -161,12 +161,7 @@ public async Task RenderCondition(GoNorthProject project, Condition cond ExportTemplate andTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.GeneralLogicAnd); - JsonSerializerOptions jsonOptions = new JsonSerializerOptions(); - jsonOptions.Converters.Add(new JsonStringEnumConverter()); - jsonOptions.Converters.Add(new JsonConditionDataParser()); - jsonOptions.PropertyNameCaseInsensitive = true; - - List parsedConditionData = JsonSerializer.Deserialize>(condition.ConditionElements, jsonOptions); + List parsedConditionData = ConditionParsingUtil.ParseConditionElements(condition.ConditionElements); return await RenderConditionElements(project, parsedConditionData, andTemplate.Code, errorCollection, flexFieldObject, exportSettings); } diff --git a/Services/Export/Dialog/ConditionRendering/LegacyRenderingEngine/NpcValueConditionResolver.cs b/Services/Export/Dialog/ConditionRendering/LegacyRenderingEngine/NpcValueConditionResolver.cs index 5c54bd4d..58144206 100644 --- a/Services/Export/Dialog/ConditionRendering/LegacyRenderingEngine/NpcValueConditionResolver.cs +++ b/Services/Export/Dialog/ConditionRendering/LegacyRenderingEngine/NpcValueConditionResolver.cs @@ -63,7 +63,7 @@ protected override async Task GetValueObject(ValueFieldCon { if(_isPlayer) { - GoNorthProject curProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _cachedDbAccess.GetUserProject(); flexFieldObject = await _cachedDbAccess.GetPlayerNpc(curProject.Id); if(flexFieldObject == null) { diff --git a/Services/Export/Dialog/ExportDialogData.cs b/Services/Export/Dialog/ExportDialogData.cs index 534d4e6d..c9fb59b3 100644 --- a/Services/Export/Dialog/ExportDialogData.cs +++ b/Services/Export/Dialog/ExportDialogData.cs @@ -33,6 +33,11 @@ public class ExportDialogData /// Node Type for action /// private const string NodeType_Action = "Action"; + + /// + /// Node Type for reference + /// + private const string NodeType_Reference = "Reference"; /// @@ -70,6 +75,11 @@ public class ExportDialogData /// public ConditionNode Condition { get; set; } + /// + /// Reference Data + /// + public ReferenceNode Reference { get; set; } + /// /// Parents @@ -130,6 +140,10 @@ public string GetNodeType() { return NodeType_Action; } + else if(Reference != null) + { + return NodeType_Reference; + } return string.Empty; } @@ -145,7 +159,8 @@ public static string[] GetAllNodeTypes() NodeType_NpcText, NodeType_Choice, NodeType_Condition, - NodeType_Action + NodeType_Action, + NodeType_Reference }; } } diff --git a/Services/Export/Dialog/ExportDialogParser.cs b/Services/Export/Dialog/ExportDialogParser.cs index 2b58fd4f..04aab8b3 100644 --- a/Services/Export/Dialog/ExportDialogParser.cs +++ b/Services/Export/Dialog/ExportDialogParser.cs @@ -45,6 +45,7 @@ protected ExportDialogData SearchDialogRootNode(TaleDialog dialog) rootNodes.AddRange(GetRootNodesFromList(dialog.Choice, dialog.Link, (e, n) => e.Choice = n)); rootNodes.AddRange(GetRootNodesFromList(dialog.Action, dialog.Link, (e, n) => e.Action = n)); rootNodes.AddRange(GetRootNodesFromList(dialog.Condition, dialog.Link, (e, n) => e.Condition = n)); + rootNodes.AddRange(GetRootNodesFromList(dialog.Reference, dialog.Link, (e, n) => e.Reference = n)); if(rootNodes.Count != 1) { @@ -81,6 +82,7 @@ protected override List GetDialogDataChildren(TaleDialog childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Choice, childLinks, (e, n) => e.Choice = n)); childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Action, childLinks, (e, n) => e.Action = n)); childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Condition, childLinks, (e, n) => e.Condition = n)); + childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Reference, childLinks, (e, n) => e.Reference = n)); return childNodes; } diff --git a/Services/Export/Dialog/ExportDialogRenderer.cs b/Services/Export/Dialog/ExportDialogRenderer.cs index 264a0ced..aadd5a05 100644 --- a/Services/Export/Dialog/ExportDialogRenderer.cs +++ b/Services/Export/Dialog/ExportDialogRenderer.cs @@ -59,7 +59,7 @@ public class ExportDialogRenderer : NodeGraphBaseRenderer, IExportDialogRenderer /// Function code public async Task> RenderDialogSteps(ExportDialogData exportDialog, KortistoNpc npc) { - _curProject = await _cachedDbAccess.GetDefaultProject(); + _curProject = await _cachedDbAccess.GetUserProject(); _exportSettings = await _cachedDbAccess.GetExportSettings(_curProject.Id); SetupStepRenderes(); @@ -94,7 +94,8 @@ protected override void SetupStepRenderes() _stepRenderers.Add(new ExportDialogChoiceRenderer(_cachedDbAccess, _errorCollection, _defaultTemplateProvider, _languageKeyGenerator, _scribanLanguageKeyGenerator, _conditionRenderer, _stringLocalizerFactory, _exportSettings, _curProject)); _stepRenderers.Add(new ExportDialogConditionRenderer(_cachedDbAccess, _errorCollection, _defaultTemplateProvider, _languageKeyGenerator, _conditionRenderer, _stringLocalizerFactory, _exportSettings, _curProject)); _stepRenderers.Add(new ExportDialogActionRenderer(_errorCollection, _defaultTemplateProvider, _cachedDbAccess, _legacyDailyRoutineEventPlaceholderResolver, _dailyRoutineFunctionNameGenerator, _languageKeyGenerator, _scribanLanguageKeyGenerator, _stringLocalizerFactory, _actionTranslator, _exportSettings, _curProject)); - + _stepRenderers.Add(new ExportReferenceRenderer(_cachedDbAccess, _errorCollection, _defaultTemplateProvider, _dailyRoutineFunctionNameGenerator, _scribanLanguageKeyGenerator, _stringLocalizerFactory, _exportSettings, _curProject)); + SetExportTemplatePlaceholderResolverToStepRenderers(); } @@ -137,7 +138,7 @@ public bool HasPlaceholdersForTemplateType(TemplateType templateType) public List GetExportTemplatePlaceholdersForType(TemplateType templateType, ExportTemplateRenderingEngine renderingEngine) { // Since project and export settings are not required for resolving placeholders the renderes are setup without loading the data - _curProject = _cachedDbAccess.GetDefaultProject().Result; + _curProject = _cachedDbAccess.GetUserProject().Result; SetupStepRenderes(); List placeholders = new List(); diff --git a/Services/Export/Dialog/StepRenderers/ExportDialogActionRenderer.cs b/Services/Export/Dialog/StepRenderers/ExportDialogActionRenderer.cs index 57a4cd2d..0e016f7a 100644 --- a/Services/Export/Dialog/StepRenderers/ExportDialogActionRenderer.cs +++ b/Services/Export/Dialog/StepRenderers/ExportDialogActionRenderer.cs @@ -12,7 +12,6 @@ using GoNorth.Services.Export.Dialog.ActionRendering.LegacyRenderingEngine; using GoNorth.Services.Export.Dialog.ActionRendering.Localization; using GoNorth.Services.Export.Dialog.ActionRendering.ScribanRenderingEngine; -using GoNorth.Services.Export.Dialog.ActionRendering.SharedRendering; using GoNorth.Services.Export.Dialog.StepRenderers.ActionRenderer; using GoNorth.Services.Export.LanguageKeyGeneration; using GoNorth.Services.Export.Placeholder; diff --git a/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.cs b/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.cs new file mode 100644 index 00000000..877bfb39 --- /dev/null +++ b/Services/Export/Dialog/StepRenderers/ExportReferenceRenderer.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using GoNorth.Data.Exporting; +using GoNorth.Data.FlexFieldDatabase; +using GoNorth.Data.NodeGraph; +using GoNorth.Data.Project; +using GoNorth.Services.Export.DailyRoutine; +using GoNorth.Services.Export.Data; +using GoNorth.Services.Export.Dialog.StepRenderers.ReferenceRenderer; +using GoNorth.Services.Export.Placeholder; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.LanguageKeyGenerator; +using Microsoft.Extensions.Localization; + +namespace GoNorth.Services.Export.Dialog.StepRenderers +{ + /// + /// Class for Rendering Reference Nodes + /// + public class ExportReferenceRenderer : ExportDialogBaseStepRenderer, IExportDialogStepRenderer + { + /// + /// Time Format + /// + private const string TimeFormat = "hh:mm"; + + /// + /// Error collection + /// + private readonly ExportPlaceholderErrorCollection _errorCollection; + + /// + /// Export default template provider + /// + private readonly ICachedExportDefaultTemplateProvider _defaultTemplateProvider; + + /// + /// Export Cached Data Access + /// + private readonly IExportCachedDbAccess _exportCachedDbAccess; + + /// + /// String localizer + /// + private readonly IStringLocalizer _localizer; + + /// + /// Current Project + /// + private readonly GoNorthProject _project; + + /// + /// Renderers for the references steps + /// + private readonly Dictionary _renderers; + + /// + /// Constructor + /// + /// Export cached Db access + /// Error Collection + /// Default Template Provider + /// Daily routine function name generator + /// Scriban Language key generator + /// Localizer Factory + /// Export Settings + /// Project + public ExportReferenceRenderer(IExportCachedDbAccess exportCachedDbAccess, ExportPlaceholderErrorCollection errorCollection, ICachedExportDefaultTemplateProvider defaultTemplateProvider, IDailyRoutineFunctionNameGenerator dailyRoutineFunctionNameGenerator, + IScribanLanguageKeyGenerator scribanLanguageKeyGenerator, IStringLocalizerFactory localizerFactory, ExportSettings exportSettings, GoNorthProject project) + { + _errorCollection = errorCollection; + _defaultTemplateProvider = defaultTemplateProvider; + _exportCachedDbAccess = exportCachedDbAccess; + _localizer = localizerFactory.Create(typeof(ExportReferenceRenderer)); + _project = project; + + _renderers = new Dictionary { + { ExportTemplateRenderingEngine.Scriban, new ScribanReferenceStepRenderer(exportCachedDbAccess, dailyRoutineFunctionNameGenerator, exportSettings, errorCollection, scribanLanguageKeyGenerator, localizerFactory) } + }; + } + + /// + /// Renders a dialog step + /// + /// Dialog Step Data + /// Flex field object to which the dialog belongs + /// Dialog Step Render Result + public async Task RenderDialogStep(ExportDialogData data, FlexFieldObject flexFieldObject) + { + if(data.Reference == null) + { + return null; + } + + ReferenceNodeData referenceNode = await GetReferenceNodeData(data.Reference); + if(referenceNode == null) + { + return null; + } + + ExportTemplate template = await _defaultTemplateProvider.GetDefaultTemplateByType(_project.Id, TemplateType.ReferenceNode); + if(!_renderers.ContainsKey(template.RenderingEngine)) + { + throw new KeyNotFoundException(string.Format("Unknown rendering engine {0} for ReferenceNode", template.RenderingEngine.ToString())); + } + + string oldContext = _errorCollection.CurrentErrorContext; + _errorCollection.CurrentErrorContext = _localizer["ErrorContextReference"]; + try + { + return await _renderers[template.RenderingEngine].RenderDialogStep(template, data, _project, referenceNode, flexFieldObject); + } + catch(Exception ex) + { + _errorCollection.AddException(ex); + return new ExportDialogStepRenderResult { + StepCode = "<>" + }; + } + finally + { + _errorCollection.CurrentErrorContext = oldContext; + } + } + + /// + /// Builds a parent text preview for the a dialog step + /// + /// Child node + /// Parent + /// Flex field to which the dialog belongs + /// Error Collection + /// Parent text preview for the dialog step + public async Task BuildParentTextPreview(ExportDialogData child, ExportDialogData parent, FlexFieldObject flexFieldObject, ExportPlaceholderErrorCollection errorCollection) + { + if(parent.Reference == null) + { + return null; + } + + ReferenceNodeData referenceNode = await GetReferenceNodeData(parent.Reference); + if(referenceNode == null) + { + return null; + } + + string referencedObjectName = "<>"; + switch(referenceNode.ObjectType.ToLowerInvariant()) + { + case ExportConstants.ExportObjectTypeNpc: + referencedObjectName = referenceNode.Npc.Name; + break; + case ExportConstants.ExportObjectTypeItem: + referencedObjectName = referenceNode.Item.Name; + break; + case ExportConstants.ExportObjectTypeSkill: + referencedObjectName = referenceNode.Skill.Name; + break; + case ExportConstants.ExportObjectTypeQuest: + referencedObjectName = referenceNode.Quest.Name; + break; + case ExportConstants.ExportObjectTypeWikiPage: + referencedObjectName = referenceNode.WikiPage.Name; + break; + case ExportConstants.ExportObjectTypeMapMarker: + referencedObjectName = string.Format("{0} ({1})", referenceNode.Marker.MarkerName, referenceNode.Marker.MapName); + break; + case ExportConstants.ExportObjectTypeDailyRoutineEvent: + string formattedTime; + if(referenceNode.DailyRoutineEvent.EarliestTime.Hours != referenceNode.DailyRoutineEvent.LatestTime.Hours || + referenceNode.DailyRoutineEvent.EarliestTime.Minutes != referenceNode.DailyRoutineEvent.LatestTime.Minutes) + { + formattedTime = string.Format("{0} - {1}", referenceNode.DailyRoutineEvent.EarliestTime.ToString(TimeFormat), referenceNode.DailyRoutineEvent.LatestTime.ToString(TimeFormat)); + } + else + { + formattedTime = referenceNode.DailyRoutineEvent.EarliestTime.ToString(TimeFormat); + } + referencedObjectName = string.Format("{0} ({1})", formattedTime, referenceNode.Npc.Name); + break; + } + + return ExportUtil.BuildTextPreview(string.Format("Reference Node ({0})", referencedObjectName)); + } + + /// + /// Loads the reference node data + /// + /// Reference node + /// Reference node data + private async Task GetReferenceNodeData(ReferenceNode referenceNode) + { + ReferenceNodeData referenceNodeData = new ReferenceNodeData(); + referenceNodeData.ReferenceText = referenceNode.ReferenceText; + referenceNodeData.ObjectType = referenceNode.ReferencedObjects[0].ObjectType; + switch(referenceNodeData.ObjectType.ToLowerInvariant()) + { + case ExportConstants.ExportObjectTypeNpc: + referenceNodeData.Npc = await _exportCachedDbAccess.GetNpcById(referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeItem: + referenceNodeData.Item = await _exportCachedDbAccess.GetItemById(referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeSkill: + referenceNodeData.Skill = await _exportCachedDbAccess.GetSkillById(referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeQuest: + referenceNodeData.Quest = await _exportCachedDbAccess.GetQuestById(referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeWikiPage: + referenceNodeData.WikiPage = await _exportCachedDbAccess.GetWikiPageById(referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeMapMarker: + referenceNodeData.Marker = await _exportCachedDbAccess.GetMarkerById(referenceNode.ReferencedObjects[1].ObjectId, referenceNode.ReferencedObjects[0].ObjectId); + break; + case ExportConstants.ExportObjectTypeDailyRoutineEvent: + referenceNodeData.Npc = await _exportCachedDbAccess.GetNpcById(referenceNode.ReferencedObjects[1].ObjectId); + referenceNodeData.DailyRoutineEvent = referenceNodeData.Npc.DailyRoutine != null ? referenceNodeData.Npc.DailyRoutine.FirstOrDefault(d => d.EventId == referenceNode.ReferencedObjects[0].ObjectId) : null; + break; + } + + return referenceNodeData; + } + + /// + /// Returns if the dialog renderer has placeholders for a template type + /// + /// Tempalte Type to check + /// true if the dialog renderer has placeholders for the template type + public bool HasPlaceholdersForTemplateType(TemplateType templateType) + { + return templateType == TemplateType.ReferenceNode; + } + + /// + /// Returns the placeholders for a template + /// + /// Template Type + /// Rendering engine + /// List of template placeholders + public List GetPlaceholdersForTemplate(TemplateType templateType, ExportTemplateRenderingEngine renderingEngine) + { + if(!HasPlaceholdersForTemplateType(templateType)) + { + return new List(); + } + + if(!_renderers.ContainsKey(renderingEngine)) + { + throw new KeyNotFoundException(string.Format("Unknown rendering engine {0} for ReferenceNode", renderingEngine.ToString())); + } + + return _renderers[renderingEngine].GetPlaceholdersForTemplate(templateType); + } + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/StepRenderers/ReferenceRenderer/IReferenceStepRenderer.cs b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/IReferenceStepRenderer.cs new file mode 100644 index 00000000..cb54bc2c --- /dev/null +++ b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/IReferenceStepRenderer.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using GoNorth.Data.Exporting; +using GoNorth.Data.FlexFieldDatabase; +using GoNorth.Data.Project; +using GoNorth.Services.Export.Placeholder; + +namespace GoNorth.Services.Export.Dialog.StepRenderers.ReferenceRenderer +{ + /// + /// Interface for Rendering Reference Nodes + /// + public interface IReferenceStepRenderer + { + /// + /// Renders a dialog step + /// + /// Export template + /// Dialog Step Data + /// Project for which the epxort is running + /// Reference node data + /// Flex field object to which the dialog belongs + /// Dialog Step Render Result + Task RenderDialogStep(ExportTemplate template, ExportDialogData data, GoNorthProject project, ReferenceNodeData referenceNodeData, FlexFieldObject flexFieldObject); + + /// + /// Returns the placeholders for a template + /// + /// Template Type + /// List of template placeholders + List GetPlaceholdersForTemplate(TemplateType templateType); + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ReferenceNodeData.cs b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ReferenceNodeData.cs new file mode 100644 index 00000000..eae1da73 --- /dev/null +++ b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ReferenceNodeData.cs @@ -0,0 +1,60 @@ +using GoNorth.Data.Aika; +using GoNorth.Data.Evne; +using GoNorth.Data.Karta; +using GoNorth.Data.Kirja; +using GoNorth.Data.Kortisto; +using GoNorth.Data.Styr; + +namespace GoNorth.Services.Export.Dialog.StepRenderers.ReferenceRenderer +{ + /// + /// Class to pass data for reference nodes + /// + public class ReferenceNodeData + { + /// + /// Text of the reference + /// + public string ReferenceText { get; set; } + + /// + /// Type of the object + /// + public string ObjectType { get; set; } + + /// + /// Npc + /// + public KortistoNpc Npc { get; set; } + + /// + /// Item + /// + public StyrItem Item { get; set; } + + /// + /// Skill + /// + public EvneSkill Skill { get; set; } + + /// + /// Quest + /// + public AikaQuest Quest { get; set; } + + /// + /// Wiki page + /// + public KirjaPage WikiPage { get; set; } + + /// + /// Marker + /// + public KartaMapNamedMarkerQueryResult Marker { get; set; } + + /// + /// Daily Routine Event + /// + public KortistoNpcDailyRoutineEvent DailyRoutineEvent { get; set;} + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ScribanReferenceStepRenderer.cs b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ScribanReferenceStepRenderer.cs new file mode 100644 index 00000000..566fb84b --- /dev/null +++ b/Services/Export/Dialog/StepRenderers/ReferenceRenderer/ScribanReferenceStepRenderer.cs @@ -0,0 +1,148 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using GoNorth.Data.Aika; +using GoNorth.Data.Evne; +using GoNorth.Data.Exporting; +using GoNorth.Data.FlexFieldDatabase; +using GoNorth.Data.Kortisto; +using GoNorth.Data.Project; +using GoNorth.Data.ProjectConfig; +using GoNorth.Data.Styr; +using GoNorth.Services.Export.DailyRoutine; +using GoNorth.Services.Export.Data; +using GoNorth.Services.Export.Dialog.StepRenderers.RenderingObjects; +using GoNorth.Services.Export.Placeholder; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Include; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.LanguageKeyGenerator; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; +using Microsoft.Extensions.Localization; +using Scriban; +using Scriban.Runtime; + +namespace GoNorth.Services.Export.Dialog.StepRenderers.ReferenceRenderer +{ + /// + /// Class for Rendering Reference Nodes using Scriban + /// + public class ScribanReferenceStepRenderer : ScribanBaseStepRenderer, IReferenceStepRenderer + { + /// + /// Reference Key + /// + private const string ReferenceKey = "reference"; + + /// + /// Export cached Db access + /// + private readonly IExportCachedDbAccess _exportCachedDbAccess; + + /// + /// Daily Routine Function Name Generator + /// + private readonly IDailyRoutineFunctionNameGenerator _dailyRoutineFunctionNameGenerator; + + /// + /// Language key generator + /// + private readonly IScribanLanguageKeyGenerator _languageKeyGenerator; + + /// + /// Constructor + /// + /// Export cached Db access + /// Daily Routine Function Name Generator + /// Export Settings + /// Error Collection + /// Language key generator + /// Localizer Factory + public ScribanReferenceStepRenderer(IExportCachedDbAccess exportCachedDbAccess, IDailyRoutineFunctionNameGenerator dailyRoutineFunctionNameGenerator, ExportSettings exportSettings, ExportPlaceholderErrorCollection errorCollection, + IScribanLanguageKeyGenerator languageKeyGenerator, IStringLocalizerFactory localizerFactory) : base(errorCollection, exportSettings, localizerFactory) + { + _exportCachedDbAccess = exportCachedDbAccess; + _dailyRoutineFunctionNameGenerator = dailyRoutineFunctionNameGenerator; + _languageKeyGenerator = languageKeyGenerator; + } + + /// + /// Renders a dialog step + /// + /// Export template + /// Dialog Step Data + /// Project for which the epxort is running + /// Reference node data + /// Flex field object to which the dialog belongs + /// Dialog Step Render Result + public async Task RenderDialogStep(ExportTemplate template, ExportDialogData data, GoNorthProject project, ReferenceNodeData referenceNodeData, FlexFieldObject flexFieldObject) + { + ExportDialogStepRenderResult renderResult = new ExportDialogStepRenderResult(); + + Template parsedTemplate = ScribanParsingUtil.ParseTemplate(template.Code, _errorCollection); + if (parsedTemplate == null) + { + return renderResult; + } + + MiscProjectConfig projectConfig = await _exportCachedDbAccess.GetMiscProjectConfig(); + + _languageKeyGenerator.SetErrorCollection(_errorCollection); + + ScribanReferenceData referenceData = BuildDialogRenderObject(data, data.Children.FirstOrDefault() != null ? data.Children.FirstOrDefault().Child : null, flexFieldObject); + referenceData.ReferenceText = referenceNodeData.ReferenceText != null ? referenceNodeData.ReferenceText : string.Empty; + referenceData.ObjectType = referenceNodeData.ObjectType; + if(referenceNodeData.Npc != null) + { + referenceData.Npc = FlexFieldValueCollectorUtil.BuildFlexFieldValueObject(null, null, referenceNodeData.Npc, _exportSettings, _errorCollection); + referenceData.Npc.IsPlayer = referenceNodeData.Npc.IsPlayerNpc; + } + else + { + referenceData.Npc = null; + } + referenceData.Item = referenceNodeData.Item != null ? FlexFieldValueCollectorUtil.BuildFlexFieldValueObject(null, null, referenceNodeData.Item, _exportSettings, _errorCollection) : null; + referenceData.Skill = referenceNodeData.Skill != null ? FlexFieldValueCollectorUtil.BuildFlexFieldValueObject(null, null, referenceNodeData.Skill, _exportSettings, _errorCollection) : null; + referenceData.Quest = referenceNodeData.Quest != null ? FlexFieldValueCollectorUtil.BuildFlexFieldValueObject(null, null, referenceNodeData.Quest, _exportSettings, _errorCollection) : null; + referenceData.WikiPage = referenceNodeData.WikiPage != null ? new ScribanExportWikiPage(referenceNodeData.WikiPage) : null; + referenceData.DailyRoutineEvent = referenceNodeData.DailyRoutineEvent != null ? await ScribanDailyRoutineEventUtil.ConvertDailyRoutineEvent(_dailyRoutineFunctionNameGenerator, referenceNodeData.Npc, referenceNodeData.DailyRoutineEvent, project, projectConfig, _exportSettings) : null; + referenceData.Marker = referenceNodeData.Marker != null ? new ScribanExportMapMarker(referenceNodeData.Marker) : null; + + TemplateContext context = BuildTemplateContext(referenceData); + + renderResult.StepCode = await parsedTemplate.RenderAsync(context); + + return renderResult; + } + + /// + /// Builds the template context for exporting + /// + /// Reference node data + /// Template context + private TemplateContext BuildTemplateContext(ScribanReferenceData referenceNodeData) + { + ScriptObject exportObject = new ScriptObject(); + exportObject.Add(ReferenceKey, referenceNodeData); + exportObject.Add(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); + TemplateContext context = new TemplateContext(); + context.TemplateLoader = new ScribanIncludeTemplateLoader(_exportCachedDbAccess, _errorCollection); + context.PushGlobal(exportObject); + return context; + } + + /// + /// Returns the placeholders for a template + /// + /// Template Type + /// List of template placeholders + public List GetPlaceholdersForTemplate(TemplateType templateType) + { + List placeholders = GetNodePlaceholders(ReferenceKey); + placeholders.AddRange(_languageKeyGenerator.GetExportTemplatePlaceholders(string.Format("{0}.{1}.{2} | {0}.{3}.{4} | {0}.{5}.{6} | {0}.{7}.{8} | field.value", ReferenceKey, StandardMemberRenamer.Rename(nameof(ReferenceNodeData.Npc)), StandardMemberRenamer.Rename(nameof(KortistoNpc.Name)), + StandardMemberRenamer.Rename(nameof(ReferenceNodeData.Item)), StandardMemberRenamer.Rename(nameof(StyrItem.Name)), StandardMemberRenamer.Rename(nameof(ReferenceNodeData.Skill)), + StandardMemberRenamer.Rename(nameof(EvneSkill.Name)), StandardMemberRenamer.Rename(nameof(ReferenceNodeData.Quest)), StandardMemberRenamer.Rename(nameof(AikaQuest.Name))))); + + return placeholders; + } + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.cs b/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.cs new file mode 100644 index 00000000..f914c8ce --- /dev/null +++ b/Services/Export/Dialog/StepRenderers/RenderingObjects/ScribanReferenceData.cs @@ -0,0 +1,65 @@ +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; + +namespace GoNorth.Services.Export.Dialog.StepRenderers.RenderingObjects +{ + /// + /// Scriban Class for Rendering choice dialog steps + /// + public class ScribanReferenceData : ScribanDialogStepBaseDataWithNextNode + { + /// + /// Text of the reference + /// + [ScribanExportValueObjectLabel] + public string ReferenceText { get; set; } + + /// + /// Type of the object + /// + [ScribanExportValueObjectLabel] + public string ObjectType { get; set; } + + /// + /// Npc that is exported + /// + [ScribanExportValueObjectLabel] + public ScribanExportNpc Npc { get; set; } + + /// + /// Item that is exported + /// + [ScribanExportValueObjectLabel] + public ScribanExportItem Item { get; set; } + + /// + /// Skill that is exported + /// + [ScribanExportValueObjectLabel] + public ScribanExportSkill Skill { get; set; } + + /// + /// Quest that is exported + /// + [ScribanExportValueObjectLabel] + public ScribanExportQuest Quest { get; set; } + + /// + /// Wiki page that is exported + /// + [ScribanExportValueObjectLabel] + public ScribanExportWikiPage WikiPage { get; set; } + + /// + /// Daily Routine Event + /// + [ScribanExportValueObjectLabel] + public ScribanExportDailyRoutineEvent DailyRoutineEvent { get; set; } + + /// + /// Marker that must be export + /// + [ScribanExportValueObjectLabel] + public ScribanExportMapMarker Marker { get; set; } + } +} \ No newline at end of file diff --git a/Services/Export/Dialog/StepRenderers/TextLine/ScribanTextLineRenderer.cs b/Services/Export/Dialog/StepRenderers/TextLine/ScribanTextLineRenderer.cs index 4b7a92e0..a5f4d366 100644 --- a/Services/Export/Dialog/StepRenderers/TextLine/ScribanTextLineRenderer.cs +++ b/Services/Export/Dialog/StepRenderers/TextLine/ScribanTextLineRenderer.cs @@ -47,9 +47,9 @@ public class ScribanTextLineRenderer : ScribanBaseStepRenderer, ITextLineRendere /// /// Export cached Db access /// Export Settings + /// Error Collection /// Language key generator /// Localizer Factory - /// Error Collection /// true if its a player line, else false public ScribanTextLineRenderer(IExportCachedDbAccess exportCachedDbAccess, ExportSettings exportSettings, ExportPlaceholderErrorCollection errorCollection, IScribanLanguageKeyGenerator languageKeyGenerator, IStringLocalizerFactory localizerFactory, bool isPlayerLine) : diff --git a/Services/Export/ExportConstants.cs b/Services/Export/ExportConstants.cs index 2c33992e..0049342a 100644 --- a/Services/Export/ExportConstants.cs +++ b/Services/Export/ExportConstants.cs @@ -59,10 +59,25 @@ public class ExportConstants public const string ExportObjectTypeSkill = "skill"; /// - /// Export Object Type for skills + /// Export Object Type for quests /// public const string ExportObjectTypeQuest = "quest"; + /// + /// Export Object Type for wiki pages + /// + public const string ExportObjectTypeWikiPage = "wikipage"; + + /// + /// Export Object Type for map markers + /// + public const string ExportObjectTypeMapMarker = "mapmarker"; + + /// + /// Export Object Type for daily routine events + /// + public const string ExportObjectTypeDailyRoutineEvent = "npcdailyroutineevent"; + /// /// String Flex Field Type diff --git a/Services/Export/ExportSnippets/ExportSnippetFunctionRenderer.cs b/Services/Export/ExportSnippets/ExportSnippetFunctionRenderer.cs index 13a6a180..911f4c51 100644 --- a/Services/Export/ExportSnippets/ExportSnippetFunctionRenderer.cs +++ b/Services/Export/ExportSnippets/ExportSnippetFunctionRenderer.cs @@ -91,7 +91,7 @@ private async Task> RenderExportSnippetNodeGraph(str { _nodeGraphParser.SetErrorCollection(_errorCollection); - _curProject = await _cachedDbAccess.GetDefaultProject(); + _curProject = await _cachedDbAccess.GetUserProject(); _exportSettings = await _cachedDbAccess.GetExportSettings(_curProject.Id); SetupStepRenderes(); @@ -152,6 +152,7 @@ protected override void SetupStepRenderes() _stepRenderers.Clear(); _stepRenderers.Add(new ExportDialogConditionRenderer(_cachedDbAccess, _errorCollection, _defaultTemplateProvider, _languageKeyGenerator, _conditionRenderer, _stringLocalizerFactory, _exportSettings, _curProject)); _stepRenderers.Add(new ExportDialogActionRenderer(_errorCollection, _defaultTemplateProvider, _cachedDbAccess, _legacyDailyRoutineEventPlaceholderResolver, _dailyRoutineFunctionNameGenerator, _languageKeyGenerator, _scribanLanguageKeyGenerator, _stringLocalizerFactory, _actionTranslator, _exportSettings, _curProject)); + _stepRenderers.Add(new ExportReferenceRenderer(_cachedDbAccess, _errorCollection, _defaultTemplateProvider, _dailyRoutineFunctionNameGenerator, _scribanLanguageKeyGenerator, _stringLocalizerFactory, _exportSettings, _curProject)); SetExportTemplatePlaceholderResolverToStepRenderers(); } diff --git a/Services/Export/ExportSnippets/ExportSnippetRelatedObjectNameResolver.cs b/Services/Export/ExportSnippets/ExportSnippetRelatedObjectNameResolver.cs new file mode 100644 index 00000000..33890a6f --- /dev/null +++ b/Services/Export/ExportSnippets/ExportSnippetRelatedObjectNameResolver.cs @@ -0,0 +1,127 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using GoNorth.Data.Evne; +using GoNorth.Data.Exporting; +using GoNorth.Data.Kortisto; +using GoNorth.Data.Styr; + +namespace GoNorth.Services.Export.ExportSnippets +{ + /// + /// Service that can resolve names for related objects of export snippets + /// + public class ExportSnippetRelatedObjectNameResolver : IExportSnippetRelatedObjectNameResolver + { + /// + /// Npc Db Access + /// + private readonly IKortistoNpcDbAccess _npcDbAccess; + + /// + /// Item Db Access + /// + private readonly IStyrItemDbAccess _itemDbAccess; + + /// + /// Skill Db Access + /// + private readonly IEvneSkillDbAccess _skillDbAccess; + + /// + /// Constructor + /// + /// Npc Db Access + /// Item Db Access + /// Skill Db Access + public ExportSnippetRelatedObjectNameResolver(IKortistoNpcDbAccess npcDbAccess, IStyrItemDbAccess itemDbAccess, IEvneSkillDbAccess skillDbAccess) + { + _npcDbAccess = npcDbAccess; + _itemDbAccess = itemDbAccess; + _skillDbAccess = skillDbAccess; + } + + /// + /// Resolves the reference for object export snippets + /// + /// Export snippets + /// True if the npcs should be included + /// True if the items should be included + /// True if the skills should be included + /// References + public async Task> ResolveExportSnippetReferences(List exportSnippets, bool includeNpcs, bool includeItems, bool includeSkills) + { + Task> npcsTask = _npcDbAccess.ResolveFlexFieldObjectNames(exportSnippets.Select(o => o.ObjectId).ToList()); + Task> itemsTask = _itemDbAccess.ResolveFlexFieldObjectNames(exportSnippets.Select(o => o.ObjectId).ToList()); + Task> skillsTask = _skillDbAccess.ResolveFlexFieldObjectNames(exportSnippets.Select(o => o.ObjectId).ToList()); + + await Task.WhenAll(npcsTask, itemsTask, skillsTask); + + Dictionary npcs; + if(includeNpcs) + { + npcs = npcsTask.Result.ToDictionary(n => n.Id, n => n.Name); + } + else + { + npcs = new Dictionary(); + } + + Dictionary items; + if(includeItems) + { + items = itemsTask.Result.ToDictionary(i => i.Id, i => i.Name); + } + else + { + items = new Dictionary(); + } + + Dictionary skills; + if(includeSkills) + { + skills = skillsTask.Result.ToDictionary(s => s.Id, s => s.Name); + } + else + { + skills = new Dictionary(); + } + + List references = new List(); + foreach(ObjectExportSnippet snippet in exportSnippets) + { + string objectName = string.Empty; + string objectType = string.Empty; + if(npcs.ContainsKey(snippet.ObjectId)) + { + objectName = npcs[snippet.ObjectId]; + objectType = ExportConstants.ExportObjectTypeNpc; + } + else if(items.ContainsKey(snippet.ObjectId)) + { + objectName = items[snippet.ObjectId]; + objectType = ExportConstants.ExportObjectTypeItem; + } + else if(skills.ContainsKey(snippet.ObjectId)) + { + objectName = skills[snippet.ObjectId]; + objectType = ExportConstants.ExportObjectTypeSkill; + } + else + { + continue; + } + + ObjectExportSnippetReference referenceResult = new ObjectExportSnippetReference(); + referenceResult.ObjectId = snippet.ObjectId; + referenceResult.ObjectName = objectName; + referenceResult.ObjectType = objectType; + referenceResult.ExportSnippet = snippet.SnippetName; + references.Add(referenceResult); + } + + return references; + } + } +} \ No newline at end of file diff --git a/Services/Export/ExportSnippets/ExportSnippetRelatedObjectUpdater.cs b/Services/Export/ExportSnippets/ExportSnippetRelatedObjectUpdater.cs index d951b554..820a8fa8 100644 --- a/Services/Export/ExportSnippets/ExportSnippetRelatedObjectUpdater.cs +++ b/Services/Export/ExportSnippets/ExportSnippetRelatedObjectUpdater.cs @@ -11,7 +11,7 @@ namespace GoNorth.Services.Export.ExportSnippets { /// - /// Interface for Services that update the related object of an export snippet + /// Service that updates the related object of an export snippet /// public class ExportSnippetRelatedObjectUpdater : IExportSnippetRelatedObjectUpdater { @@ -134,7 +134,7 @@ private async Task CheckNpcForUpdate(ObjectExportSnippet export return null; } - await _timelineService.AddTimelineEntry(timelineEvent, exportSnippet.SnippetName, npc.Name, npc.Id); + await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, npc.Name, npc.Id); CompareResult result = await _implementationStatusComparer.CompareNpc(npc.Id, npc); if(result.CompareDifference != null && result.CompareDifference.Count > 0) @@ -161,7 +161,7 @@ private async Task CheckItemForUpdate(ObjectExportSnippet expor return null; } - await _timelineService.AddTimelineEntry(timelineEvent, exportSnippet.SnippetName, item.Name, item.Id); + await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, item.Name, item.Id); CompareResult result = await _implementationStatusComparer.CompareItem(item.Id, item); if(result.CompareDifference != null && result.CompareDifference.Count > 0) @@ -188,7 +188,7 @@ private async Task CheckSkillForUpdate(ObjectExportSnippet expo return null; } - await _timelineService.AddTimelineEntry(timelineEvent, exportSnippet.SnippetName, skill.Name, skill.Id); + await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, skill.Name, skill.Id); CompareResult result = await _implementationStatusComparer.CompareSkill(skill.Id, skill); if(result.CompareDifference != null && result.CompareDifference.Count > 0) diff --git a/Services/Export/ExportSnippets/IExportSnippetRelatedObjectNameResolver.cs b/Services/Export/ExportSnippets/IExportSnippetRelatedObjectNameResolver.cs new file mode 100644 index 00000000..07da9317 --- /dev/null +++ b/Services/Export/ExportSnippets/IExportSnippetRelatedObjectNameResolver.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using GoNorth.Data.Exporting; + +namespace GoNorth.Services.Export.ExportSnippets +{ + /// + /// Interface for classes that can resolve names for related objects of export snippets + /// + public interface IExportSnippetRelatedObjectNameResolver + { + /// + /// Resolves the reference for object export snippets + /// + /// Export snippets + /// True if the npcs should be included + /// True if the items should be included + /// True if the skills should be included + /// References + Task> ResolveExportSnippetReferences(List exportSnippets, bool includeNpcs, bool includeItems, bool includeSkills); + } +} \ No newline at end of file diff --git a/Services/Export/LanguageExport/LanguageExporter.cs b/Services/Export/LanguageExport/LanguageExporter.cs index 34e1c59b..97b05229 100644 --- a/Services/Export/LanguageExport/LanguageExporter.cs +++ b/Services/Export/LanguageExport/LanguageExporter.cs @@ -4,6 +4,7 @@ using GoNorth.Services.Export.LanguageKeyGeneration; using GoNorth.Services.Export.Placeholder; using GoNorth.Services.Export.Script; +using GoNorth.Services.Project; namespace GoNorth.Services.Export.LanguageExport { @@ -33,9 +34,9 @@ public class LanguageExporter : IObjectExporter private readonly IExportSettingsDbAccess _exportSettingsDbAccess; /// - /// Project Db Access + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Language key reference collector @@ -47,19 +48,19 @@ public class LanguageExporter : IObjectExporter /// /// Pkaceholder Resolver /// Default Template Provider - /// Project Db Access /// Export Settings Db Accesss + /// User project access /// Language key reference collector - public LanguageExporter(IExportTemplatePlaceholderResolver placeholderResolver, IExportDefaultTemplateProvider defaultTemplateProvider, IProjectDbAccess projectDbAccess, IExportSettingsDbAccess exportSettingsDbAccess, + public LanguageExporter(IExportTemplatePlaceholderResolver placeholderResolver, IExportDefaultTemplateProvider defaultTemplateProvider, IExportSettingsDbAccess exportSettingsDbAccess, IUserProjectAccess userProjectAccess, ILanguageKeyReferenceCollector languageKeyReferenceCollector) { _placeholderResolver = placeholderResolver; _defaultTemplateProvider = defaultTemplateProvider; - _projectDbAccess = projectDbAccess; _exportSettingsDbAccess = exportSettingsDbAccess; + _userProjectAccess = userProjectAccess; _languageKeyReferenceCollector = languageKeyReferenceCollector; - _scriptExporter = new ScriptExporter(placeholderResolver, projectDbAccess, exportSettingsDbAccess); + _scriptExporter = new ScriptExporter(placeholderResolver, exportSettingsDbAccess, userProjectAccess); } /// @@ -91,7 +92,7 @@ public async Task ExportObject(ExportTemplate template, Expo objectData.ExportData[ExportConstants.ExportDataReferencedLanguageIds] = _languageKeyReferenceCollector.GetReferencedLanguageKeys(); // Export language keys - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportSettings exportSettings = await _exportSettingsDbAccess.GetExportSettings(project.Id); ExportTemplate exportTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.LanguageFile); diff --git a/Services/Export/LanguageKeyGeneration/LanguageKeyGenerator.cs b/Services/Export/LanguageKeyGeneration/LanguageKeyGenerator.cs index 7f775559..f2be0fa4 100644 --- a/Services/Export/LanguageKeyGeneration/LanguageKeyGenerator.cs +++ b/Services/Export/LanguageKeyGeneration/LanguageKeyGenerator.cs @@ -1,8 +1,8 @@ -using System; using System.Text.RegularExpressions; using System.Threading.Tasks; using GoNorth.Data.Exporting; using GoNorth.Data.Project; +using GoNorth.Services.Project; namespace GoNorth.Services.Export.LanguageKeyGeneration { @@ -18,14 +18,14 @@ public class LanguageKeyGenerator : ILanguageKeyGenerator /// - /// Project Db Access + /// Language Key Db Access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly ILanguageKeyDbAccess _languageKeyDbAccess; /// - /// Language Key Db Access + /// User project access /// - private readonly ILanguageKeyDbAccess _languageKeyDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Language key reference collector @@ -40,13 +40,13 @@ public class LanguageKeyGenerator : ILanguageKeyGenerator /// /// Constructor /// - /// Project Db Access /// Language Key Db Access + /// User project access /// Language key reference collector - public LanguageKeyGenerator(IProjectDbAccess projectDbAccess, ILanguageKeyDbAccess languageKeyDbAccess, ILanguageKeyReferenceCollector languageKeyReferenceCollector) + public LanguageKeyGenerator(ILanguageKeyDbAccess languageKeyDbAccess, IUserProjectAccess userProjectAccess, ILanguageKeyReferenceCollector languageKeyReferenceCollector) { - _projectDbAccess = projectDbAccess; _languageKeyDbAccess = languageKeyDbAccess; + _userProjectAccess = userProjectAccess; _languageKeyReferenceCollector = languageKeyReferenceCollector; } @@ -186,7 +186,7 @@ private async Task EnsureProject() { if(_project == null) { - _project = await _projectDbAccess.GetDefaultProject(); + _project = await _userProjectAccess.GetUserProject(); } } diff --git a/Services/Export/NodeGraphExport/NodeGraphParser.cs b/Services/Export/NodeGraphExport/NodeGraphParser.cs index dd23ee7a..228f41fc 100644 --- a/Services/Export/NodeGraphExport/NodeGraphParser.cs +++ b/Services/Export/NodeGraphExport/NodeGraphParser.cs @@ -27,6 +27,7 @@ protected ExportDialogData SearchDialogRootNode(NodeGraphSnippet dialog) List rootNodes = new List(); rootNodes.AddRange(GetRootNodesFromList(dialog.Action, dialog.Link, (e, n) => e.Action = n)); rootNodes.AddRange(GetRootNodesFromList(dialog.Condition, dialog.Link, (e, n) => e.Condition = n)); + rootNodes.AddRange(GetRootNodesFromList(dialog.Reference, dialog.Link, (e, n) => e.Reference = n)); if(rootNodes.Count != 1) { @@ -60,6 +61,7 @@ protected override List GetDialogDataChildren(NodeGraphSn List childNodes = new List(); childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Action, childLinks, (e, n) => e.Action = n)); childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Condition, childLinks, (e, n) => e.Condition = n)); + childNodes.AddRange(FindDialogElementChildrenInList(convertedDialogNodes, exportable.Reference, childLinks, (e, n) => e.Reference = n)); return childNodes; } diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/DialogExportTemplatePlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/DialogExportTemplatePlaceholderResolver.cs index d19f01ad..7a79e658 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/DialogExportTemplatePlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/DialogExportTemplatePlaceholderResolver.cs @@ -156,7 +156,7 @@ public async Task FillPlaceholders(string code, ExportObjectData data) if(dialogFunction != null) { // Replace Dialog Function - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); return await RenderDialogFunction(project, dialogFunction); } @@ -171,7 +171,7 @@ public async Task FillPlaceholders(string code, ExportObjectData data) /// Filled code private async Task FillDialogPlaceholders(string code, KortistoNpc npc) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(npc.Id); try diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/ExportSnippetTemplatePlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/ExportSnippetTemplatePlaceholderResolver.cs index 6e0d30c9..fc582dc9 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/ExportSnippetTemplatePlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/ExportSnippetTemplatePlaceholderResolver.cs @@ -374,7 +374,7 @@ private async Task ExportCodeSnippetAdditionalFunctions(Dictionary functions = await RenderFunctions(renderedFunctions, objectExportSnippet, flexFieldObject); List additionalFunctions = functions.Skip(1).ToList(); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/FlexFieldExportTemplatePlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/FlexFieldExportTemplatePlaceholderResolver.cs index 28af1fea..6c1e66a3 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/FlexFieldExportTemplatePlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/FlexFieldExportTemplatePlaceholderResolver.cs @@ -435,7 +435,7 @@ private string BuildFinalPlaceholder(string placeholder) /// Filled Code private async Task FillFlexFieldPlaceholders(string code, IFlexFieldExportable flexFieldObject, string objectType, ExportObjectData data) { - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); ExportSettings exportSettings = await _exportCachedDbAccess.GetExportSettings(project.Id); HashSet usedFields = new HashSet(); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/LanguageKeyTemplatePlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/LanguageKeyTemplatePlaceholderResolver.cs index ffaf768e..fc18f2e2 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/LanguageKeyTemplatePlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/LanguageKeyTemplatePlaceholderResolver.cs @@ -183,7 +183,7 @@ public Task FillPlaceholders(string code, ExportObjectData data) /// Filled Code private async Task FillLanguageKeyPlaceholders(string code, IFlexFieldExportable flexFieldObject, List referencedLanguageKeys) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); List languageKeys = await _languageKeyDbAccess.GetLanguageKeysByGroupId(project.Id, flexFieldObject.Id); ExportSettings exportSettings = await _cachedDbAccess.GetExportSettings(project.Id); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventContentPlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventContentPlaceholderResolver.cs index 4a508c5d..47cf2ebe 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventContentPlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventContentPlaceholderResolver.cs @@ -133,7 +133,7 @@ public void SetErrorCollection(ExportPlaceholderErrorCollection errorCollection) /// Code with resolved placeholders public async Task ResolveDailyRoutineEventContentPlaceholders(string code, KortistoNpc npc, KortistoNpcDailyRoutineEvent dailyRoutineEvent, ExportPlaceholderErrorCollection errorCollection) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportTemplate dailyRoutineFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectDailyRoutineFunction); List functions = await this.RenderDailyRoutineFunctions(dailyRoutineEvent, npc, errorCollection); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventPlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventPlaceholderResolver.cs index d6d6beac..716fc022 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventPlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/LegacyDailyRoutineEventPlaceholderResolver.cs @@ -243,7 +243,7 @@ public LegacyDailyRoutineEventPlaceholderResolver(IExportCachedDbAccess cachedDb /// Code with resolved placeholders public async Task ResolveDailyRoutineEventPlaceholders(string code, KortistoNpc npc, KortistoNpcDailyRoutineEvent dailyRoutineEvent) { - GoNorthProject defaultProject = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject defaultProject = await _cachedDbAccess.GetUserProject(); MiscProjectConfig projectConfig = await _cachedDbAccess.GetMiscProjectConfig(); code = ExportUtil.RenderPlaceholderIfTrue(code, Placeholder_HasMovementTargetStart, Placeholder_HasMovementTargetEnd, dailyRoutineEvent.MovementTarget != null && !string.IsNullOrEmpty(dailyRoutineEvent.MovementTarget.Name)); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/NpcDailyRoutineExportPlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/NpcDailyRoutineExportPlaceholderResolver.cs index 6ebc6e0c..d5bb4ea4 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/NpcDailyRoutineExportPlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/NpcDailyRoutineExportPlaceholderResolver.cs @@ -189,7 +189,7 @@ public async Task FillPlaceholders(string code, ExportObjectData data) /// Filled code private async Task FillDailyRoutinePlaceholders(string code, KortistoNpc npc, ExportObjectData data) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportTemplate dailyRoutineFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectDailyRoutineFunction); code = await ExportUtil.BuildPlaceholderRegex(Placeholder_DailyRoutine_Events, ExportConstants.ListIndentPrefix).ReplaceAsync(code, async m => { @@ -228,7 +228,7 @@ private async Task FillDailyRoutinePlaceholders(string code, KortistoNpc /// Filled code private async Task FillDailyRoutineFunctionListPlaceholders(string code, List functions) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportTemplate dailyRoutineFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectDailyRoutineFunction); code = ExportUtil.BuildPlaceholderRegex(Placeholder_DailyRoutine_Function, ExportConstants.ListIndentPrefix).Replace(code, m => { diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/NpcInventoryExportPlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/NpcInventoryExportPlaceholderResolver.cs index a6f2e0a3..46f85249 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/NpcInventoryExportPlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/NpcInventoryExportPlaceholderResolver.cs @@ -184,7 +184,7 @@ private async Task FillInventoryPlaceholders(string code, KortistoNpc np /// Item List private async Task RenderInventory(ExportObjectData data, string indent) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportTemplate inventoryTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectInventory); ExportPlaceholderFillResult fillResult = await _placeholderResolver.FillPlaceholders(TemplateType.ObjectInventory, inventoryTemplate.Code, data, inventoryTemplate.RenderingEngine); diff --git a/Services/Export/Placeholder/LegacyRenderingEngine/NpcSkillExportPlaceholderResolver.cs b/Services/Export/Placeholder/LegacyRenderingEngine/NpcSkillExportPlaceholderResolver.cs index 882130aa..13c135d3 100644 --- a/Services/Export/Placeholder/LegacyRenderingEngine/NpcSkillExportPlaceholderResolver.cs +++ b/Services/Export/Placeholder/LegacyRenderingEngine/NpcSkillExportPlaceholderResolver.cs @@ -159,7 +159,7 @@ private async Task FillSkillPlaceholders(string code, KortistoNpc npc, E /// Skill List private async Task RenderSkillList(ExportObjectData data, string indent) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportTemplate skillTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectSkillList); ExportPlaceholderFillResult fillResult = await _placeholderResolver.FillPlaceholders(TemplateType.ObjectSkillList, skillTemplate.Code, data, skillTemplate.RenderingEngine); diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/Include/ScribanIncludeTemplateLoader.cs b/Services/Export/Placeholder/ScribanRenderingEngine/Include/ScribanIncludeTemplateLoader.cs index b97d38c6..3dbec493 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/Include/ScribanIncludeTemplateLoader.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/Include/ScribanIncludeTemplateLoader.cs @@ -55,7 +55,7 @@ public string GetPath(TemplateContext context, SourceSpan callerSpan, string tem /// Code of the template private async Task LoadTemplate(string templateName, SourceSpan callerSpan) { - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); IncludeExportTemplate includeExportTemplate = await _cachedDbAccess.GetIncludeTemplateByName(project.Id, templateName); if(includeExportTemplate == null) { diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/LanguageKeyGenerator/ScribanLanguageKeyGenerator.cs b/Services/Export/Placeholder/ScribanRenderingEngine/LanguageKeyGenerator/ScribanLanguageKeyGenerator.cs index 24d72a35..f0a49001 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/LanguageKeyGenerator/ScribanLanguageKeyGenerator.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/LanguageKeyGenerator/ScribanLanguageKeyGenerator.cs @@ -3,6 +3,7 @@ using GoNorth.Services.Export.Dialog.ActionRendering.ScribanRenderingEngine.RenderingObjects; using GoNorth.Services.Export.Dialog.StepRenderers.RenderingObjects; using GoNorth.Services.Export.LanguageKeyGeneration; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFunctions; using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects; using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; using Microsoft.Extensions.Localization; @@ -15,7 +16,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.LanguageKey /// /// Class for Scriban Language Key Generators /// - public class ScribanLanguageKeyGenerator : IScribanLanguageKeyGenerator, IScriptCustomFunction + public class ScribanLanguageKeyGenerator : ScribanBaseStringRenderingFunction, IScribanLanguageKeyGenerator { /// /// Language Key Generator @@ -249,7 +250,7 @@ private async ValueTask GenerateFlexFieldLanguageKey(ScriptNode callerCo /// Arguments /// Block Statement /// Language Key - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return GetLanguageKey(context, callerContext, arguments).Result; } @@ -262,7 +263,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Language Key - public ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return GetLanguageKey(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionListRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionListRenderer.cs index 22c3ce70..3a35fb61 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionListRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionListRenderer.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using GoNorth.Data.Exporting; -using GoNorth.Data.Kortisto; using GoNorth.Data.Project; using GoNorth.Services.Export.Data; using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects; @@ -17,7 +16,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Class to render daily routine event function list /// - public class DailyRoutineEventFunctionListRenderer : IScriptCustomFunction + public class DailyRoutineEventFunctionListRenderer : ScribanBaseStringRenderingFunction> { /// /// Name of the function @@ -59,7 +58,7 @@ public class DailyRoutineEventFunctionListRenderer : IScriptCustomFunction _defaultTemplateProvider = defaultTemplateProvider; _errorCollection = errorCollection; } - + /// /// Renders an daily routine function list /// @@ -76,7 +75,7 @@ private async ValueTask RenderDailyRoutineFunctionList(TemplateContext c return "<>"; } - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate functionListTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectDailyRoutineFunctionList); ExportObjectData objectData = new ExportObjectData(); @@ -96,7 +95,7 @@ private async ValueTask RenderDailyRoutineFunctionList(TemplateContext c /// Arguments /// Block Statement /// Daily routine function list - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderDailyRoutineFunctionList(context, callerContext, arguments).Result; } @@ -109,7 +108,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Daily routine function list - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderDailyRoutineFunctionList(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionRenderer.cs index 3dfcdf7d..5f973769 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventFunctionRenderer.cs @@ -16,7 +16,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Class to render a daily routine function /// - public class DailyRoutineEventFunctionRenderer : IScriptCustomFunction + public class DailyRoutineEventFunctionRenderer : ScribanBaseStringRenderingFunction { /// /// Name of the function @@ -75,7 +75,7 @@ private async ValueTask RenderDailyRoutineEventFunction(TemplateContext } ScribanExportDailyRoutineFunction exportFunction = (ScribanExportDailyRoutineFunction)arguments[0]; - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate eventFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectDailyRoutineFunction); ExportObjectData objectData = new ExportObjectData(); @@ -95,7 +95,7 @@ private async ValueTask RenderDailyRoutineEventFunction(TemplateContext /// Arguments /// Block Statement /// Daily routine event function - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderDailyRoutineEventFunction(context, callerContext, arguments).Result; } @@ -108,7 +108,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Daily routine event function - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderDailyRoutineEventFunction(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventListRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventListRenderer.cs index e13ae5b7..2900bff1 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventListRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DailyRoutineEventListRenderer.cs @@ -17,7 +17,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Class to render daily routine event list /// - public class DailyRoutineEventListRenderer : IScriptCustomFunction + public class DailyRoutineEventListRenderer : ScribanBaseStringRenderingFunction> { /// /// Name of the function @@ -83,7 +83,7 @@ private async ValueTask RenderDailyRoutineEventList(TemplateContext cont return "<>"; } - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate eventListTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectDailyRoutineEventList); ExportObjectData objectData = _exportObjectData.Clone(); @@ -106,7 +106,7 @@ private async ValueTask RenderDailyRoutineEventList(TemplateContext cont /// Arguments /// Block Statement /// Daily routine event list - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderDailyRoutineEventList(context, callerContext, arguments).Result; } @@ -119,7 +119,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Daily routine event list - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderDailyRoutineEventList(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DialogFunctionRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DialogFunctionRenderer.cs index 349eb4a9..36d25791 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DialogFunctionRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/DialogFunctionRenderer.cs @@ -16,7 +16,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Class to render dialog function /// - public class DialogFunctionRenderer : IScriptCustomFunction + public class DialogFunctionRenderer : ScribanBaseStringRenderingFunction { /// /// Name of the function @@ -82,7 +82,7 @@ private async ValueTask RenderDialogFunction(TemplateContext context, Sc } ScribanExportDialogFunction exportDialogFunction = (ScribanExportDialogFunction)arguments[0]; - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate dialogFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.TaleDialogFunction); ExportObjectData objectData = new ExportObjectData(); @@ -112,7 +112,7 @@ private ExportDialogFunctionCode ConvertScribanDialogFunctionToNodeFunction(Scri /// Arguments /// Block Statement /// Dialog function - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderDialogFunction(context, callerContext, arguments).Result; } @@ -125,7 +125,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Dialog function - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderDialogFunction(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ExportSnippetFunctionPipeRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ExportSnippetFunctionPipeRenderer.cs index ea110038..b0505211 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ExportSnippetFunctionPipeRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ExportSnippetFunctionPipeRenderer.cs @@ -15,7 +15,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Class to render an export snippet function /// - public class ExportSnippetFunctionPipeRenderer : IScriptCustomFunction + public class ExportSnippetFunctionPipeRenderer : ScribanBaseStringRenderingFunction { /// /// Name of the function @@ -74,7 +74,7 @@ private async ValueTask RenderExportSnippetFunction(TemplateContext cont } ScribanExportSnippetFunction exportFunction = (ScribanExportSnippetFunction)arguments[0]; - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate snippetFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectExportSnippetFunction); ExportObjectData objectData = new ExportObjectData(); @@ -94,7 +94,7 @@ private async ValueTask RenderExportSnippetFunction(TemplateContext cont /// Arguments /// Block Statement /// Export snippet function - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderExportSnippetFunction(context, callerContext, arguments).Result; } @@ -107,7 +107,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Export snippet function - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderExportSnippetFunction(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/FlexFieldAttributeListRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/FlexFieldAttributeListRenderer.cs index 7ab2b211..c02a1155 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/FlexFieldAttributeListRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/FlexFieldAttributeListRenderer.cs @@ -17,7 +17,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Function to render a flex field attribute list /// - public class FlexFieldAttributeListRenderer : IScriptCustomFunction + public class FlexFieldAttributeListRenderer : ScribanBaseStringRenderingFunction> { /// /// Name of the function @@ -83,7 +83,7 @@ private async ValueTask RenderAttributeList(TemplateContext context, Scr return "<>"; } - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate attributeListTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectAttributeList); ExportObjectData objectData = _exportObjectData.Clone(); @@ -121,7 +121,7 @@ private List ConvertListToFlexFieldList(List f /// Arguments /// Block Statement /// Attribute list - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderAttributeList(context, callerContext, arguments).Result; } @@ -134,7 +134,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Attribute list - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderAttributeList(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/IndentMultiLineRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/IndentMultiLineRenderer.cs index d4e09fc2..d556b85b 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/IndentMultiLineRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/IndentMultiLineRenderer.cs @@ -11,7 +11,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Function to indent multiple lines of text to match the same indentation /// - public class IndentMultiLineRenderer : IScriptCustomFunction + public class IndentMultiLineRenderer : ScribanBaseStringRenderingFunction { /// /// Name of the function @@ -44,7 +44,7 @@ private ValueTask IndentValue(TemplateContext context, ScriptNode caller /// Arguments /// Block Statement /// Indented text value - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return IndentValue(context, callerContext, arguments).Result; } @@ -57,7 +57,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Indented text value - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await IndentValue(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/InventoryListRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/InventoryListRenderer.cs index b28dd989..b0845164 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/InventoryListRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/InventoryListRenderer.cs @@ -17,7 +17,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Function to render a inventory list /// - public class InventoryListRenderer : IScriptCustomFunction + public class InventoryListRenderer : ScribanBaseStringRenderingFunction> { /// /// Name of the function @@ -89,7 +89,7 @@ private async ValueTask RenderInventoryList(TemplateContext context, Scr return "<>"; } - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate inventoryTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectInventory); ExportObjectData objectData = _exportObjectData.Clone(); @@ -123,7 +123,7 @@ private List ConvertInventoryToKortistoInventory(ListArguments /// Block Statement /// Inventory list - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderInventoryList(context, callerContext, arguments).Result; } @@ -136,7 +136,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Inventory list - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderInventoryList(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ScribanBaseStringRenderingFunction.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ScribanBaseStringRenderingFunction.cs new file mode 100644 index 00000000..f1eefdbd --- /dev/null +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/ScribanBaseStringRenderingFunction.cs @@ -0,0 +1,64 @@ +using System; +using System.Threading.Tasks; +using Scriban; +using Scriban.Runtime; +using Scriban.Syntax; + +namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFunctions +{ + /// + /// Base rendering class for scriban string functions + /// + public abstract class ScribanBaseStringRenderingFunction : IScriptCustomFunction + { + /// + /// Returns the required parameter count + /// + public int RequiredParameterCount => 1; + + /// + /// Parameter count + /// + public int ParameterCount => 1; + + /// + /// Returns the parameter kind + /// + public ScriptVarParamKind VarParamKind => ScriptVarParamKind.Direct; + + /// + /// Returns the return type + /// + public Type ReturnType => typeof(string); + + /// + /// Returns the parameter info + /// + /// Index + /// Script Parameter info + public ScriptParameterInfo GetParameterInfo(int index) + { + return new ScriptParameterInfo(typeof(ParameterType), "value"); + } + + /// + /// Invokes the daily routine function list generation + /// + /// Template context + /// Caller context + /// Arguments + /// Block Statement + /// Daily routine function list + public abstract object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement); + + /// + /// Invokes the daily routine function list generation async + /// + /// Template context + /// Caller context + /// Arguments + /// Block Statement + /// Daily routine function list + public abstract ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement); + } +} \ No newline at end of file diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/SkillListRenderer.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/SkillListRenderer.cs index 91140190..1d5dbf69 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/SkillListRenderer.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/SkillListRenderer.cs @@ -17,7 +17,7 @@ namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFu /// /// Function to render a skill list /// - public class SkillListRenderer : IScriptCustomFunction + public class SkillListRenderer : ScribanBaseStringRenderingFunction> { /// /// Name of the function @@ -89,7 +89,7 @@ private async ValueTask RenderSkillList(TemplateContext context, ScriptN return "<>"; } - GoNorthProject curProject = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject(); ExportTemplate skillListTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectSkillList); ExportObjectData objectData = _exportObjectData.Clone(); @@ -121,7 +121,7 @@ private List ConvertSkillsToKortistoNpcSkill(ListArguments /// Block Statement /// Rendered skill list - public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return RenderSkillList(context, callerContext, arguments).Result; } @@ -134,7 +134,7 @@ public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptAr /// Arguments /// Block Statement /// Rendered skill list - public async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) + public override async ValueTask InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return await RenderSkillList(context, callerContext, arguments); } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.cs new file mode 100644 index 00000000..92e578b7 --- /dev/null +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportMapMarker.cs @@ -0,0 +1,54 @@ +using GoNorth.Data.Karta; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; + +namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects +{ + /// + /// Scriban Export Map Marker + /// + public class ScribanExportMapMarker + { + /// + /// Map Id + /// + [ScribanExportValueLabel] + public string MapId { get; set; } + + /// + /// Name of the map + /// + [ScribanExportValueLabel] + public string MapName { get; set; } + + /// + /// Type of the marker + /// + [ScribanExportValueLabel] + public string MarkerType { get; set; } + + /// + /// Marker Id + /// + [ScribanExportValueLabel] + public string MarkerId { get; set; } + + /// + /// Name of the marker + /// + [ScribanExportValueLabel] + public string MarkerName { get; set; } + + /// + /// Creates a scriban export map marker based on a marker query result + /// + /// Marker + public ScribanExportMapMarker(KartaMapNamedMarkerQueryResult marker) + { + MapId = marker.MapId; + MapName = marker.MapName; + MarkerType = marker.MarkerType; + MarkerId = marker.MarkerId; + MarkerName = marker.MarkerName; + } + } +} \ No newline at end of file diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.cs b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.cs new file mode 100644 index 00000000..f1d06097 --- /dev/null +++ b/Services/Export/Placeholder/ScribanRenderingEngine/RenderingObjects/ScribanExportWikiPage.cs @@ -0,0 +1,33 @@ +using GoNorth.Data.Kirja; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; + +namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects +{ + /// + /// Class to export a wiki page + /// + public class ScribanExportWikiPage + { + /// + /// Name of the wiki page + /// + [ScribanExportValueLabel] + public string Name { get; set; } + + /// + /// Content of the wiki page + /// + [ScribanExportValueLabel] + public string Content { get; set; } + + /// + /// Builds an export wiki page based on a kirja page + /// + /// Wiki page + public ScribanExportWikiPage(KirjaPage page) + { + Name = page.Name; + Content = page.Content; + } + } +} \ No newline at end of file diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanDailyRoutineEventUtil.cs b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanDailyRoutineEventUtil.cs index 91ac89af..34d85ab0 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanDailyRoutineEventUtil.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanDailyRoutineEventUtil.cs @@ -32,7 +32,7 @@ public static async Task> MapNpcDailyRoutin return new List(); } - GoNorthProject project = await cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await cachedDbAccess.GetUserProject(); MiscProjectConfig projectConfig = await cachedDbAccess.GetMiscProjectConfig(); ExportSettings exportSettings = await cachedDbAccess.GetExportSettings(project.Id); diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanStatementExtractor.cs b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanStatementExtractor.cs index 858fcccf..77b1d2e2 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanStatementExtractor.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScribanStatementExtractor.cs @@ -25,7 +25,7 @@ public static List ExtractPlainNonTextStatements(Template templ /// /// Statement list /// Script statement list - private static List ExtractStatementsFromList(List statements) + private static List ExtractStatementsFromList(ScriptList statements) { List scriptStatements = new List(); if(statements == null || !statements.Any()) @@ -56,9 +56,13 @@ private static void ExtractStatement(List scriptStatements, Scr if (statement is ScriptLoopStatementBase) { ScriptLoopStatementBase loopStatement = (ScriptLoopStatementBase)statement; - if (loopStatement.Body != null) + foreach(ScriptNode curChild in loopStatement.Children) { - scriptStatements.AddRange(ExtractStatementsFromList(loopStatement.Body.Statements)); + ScriptStatement curStatement = curChild as ScriptStatement; + if(curStatement != null) + { + ExtractStatement(scriptStatements, curStatement); + } } } else if (statement is ScriptIfStatement) diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScriptObjectExtensions.cs b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScriptObjectExtensions.cs new file mode 100644 index 00000000..25a8bb6e --- /dev/null +++ b/Services/Export/Placeholder/ScribanRenderingEngine/Util/ScriptObjectExtensions.cs @@ -0,0 +1,28 @@ +using Scriban.Runtime; + +namespace GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util +{ + /// + /// Extension methods for script objects + /// + public static class ScriptObjectExtensions + { + /// + /// Adds or updates a value + /// + /// Script object that is being updated + /// Key + /// Value + public static void AddOrUpdate(this ScriptObject scriptObject, string key, object value) + { + if(scriptObject.ContainsKey(key)) + { + scriptObject[key] = value; + } + else + { + scriptObject.Add(key, value); + } + } + } +} \ No newline at end of file diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/AttributeListValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/AttributeListValueCollector.cs index f66e4af5..b873a56a 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/AttributeListValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/AttributeListValueCollector.cs @@ -83,11 +83,11 @@ public override async Task CollectValues(TemplateType templateType, Template par _languageKeyGenerator.SetErrorCollection(_errorCollection); - GoNorthProject project = await _cachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _cachedDbAccess.GetUserProject(); ExportSettings exportSettings = await _cachedDbAccess.GetExportSettings(project.Id); - scriptObject.Add(ObjectKey, FlexFieldValueCollectorUtil.ExtractScribanFields(exportable, exportSettings, _errorCollection)); - scriptObject.Add(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); + scriptObject.AddOrUpdate(ObjectKey, FlexFieldValueCollectorUtil.ExtractScribanFields(exportable, exportSettings, _errorCollection)); + scriptObject.AddOrUpdate(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/BaseFlexFieldValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/BaseFlexFieldValueCollector.cs index f4d67735..c319a160 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/BaseFlexFieldValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/BaseFlexFieldValueCollector.cs @@ -111,7 +111,7 @@ public override async Task CollectValues(TemplateType templateType, Template par _languageKeyGenerator.SetErrorCollection(_errorCollection); - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); ExportSettings exportSettings = await _exportCachedDbAccess.GetExportSettings(project.Id); ExportClass exportObject = BuildExportObject(parsedTemplate, inputObject, exportSettings); diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineEventListValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineEventListValueCollector.cs index 76dd0b16..62c6c348 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineEventListValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineEventListValueCollector.cs @@ -76,7 +76,7 @@ public override async Task CollectValues(TemplateType templateType, Template par List events = await ScribanDailyRoutineEventUtil.MapNpcDailyRoutineEvents(_cachedDbAccess, _dailyRoutineFunctionNameGenerator, inputNpc, inputNpc.DailyRoutine); - scriptObject.Add(ExportConstants.ScribanDailyRoutineEventsObjectKey, events); + scriptObject.AddOrUpdate(ExportConstants.ScribanDailyRoutineEventsObjectKey, events); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionListValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionListValueCollector.cs index 1e3f1b0b..116c8613 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionListValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionListValueCollector.cs @@ -86,11 +86,11 @@ public override Task CollectValues(TemplateType templateType, Template parsedTem } List scribanFunctions = inputFunction.Select(i => new ScribanExportDailyRoutineFunction(i)).ToList(); - scriptObject.Add(ExportConstants.ScribanDailyRoutineFunctionListObjectKey, scribanFunctions); + scriptObject.AddOrUpdate(ExportConstants.ScribanDailyRoutineFunctionListObjectKey, scribanFunctions); if(!scriptObject.ContainsKey(DailyRoutineEventFunctionRenderer.DailyRoutineEventFunctionName)) { - scriptObject.Add(DailyRoutineEventFunctionRenderer.DailyRoutineEventFunctionName, new DailyRoutineEventFunctionRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); + scriptObject.AddOrUpdate(DailyRoutineEventFunctionRenderer.DailyRoutineEventFunctionName, new DailyRoutineEventFunctionRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); } return Task.CompletedTask; diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionValueCollector.cs index 27c152b1..0f928504 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DailyRoutineFunctionValueCollector.cs @@ -55,7 +55,7 @@ public override Task CollectValues(TemplateType templateType, Template parsedTem return Task.CompletedTask; } - scriptObject.Add(ExportConstants.ScribanDailyRoutineFunctionObjectKey, new ScribanExportDailyRoutineFunction(inputFunction)); + scriptObject.AddOrUpdate(ExportConstants.ScribanDailyRoutineFunctionObjectKey, new ScribanExportDailyRoutineFunction(inputFunction)); return Task.CompletedTask; } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogFunctionValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogFunctionValueCollector.cs index bcfd3293..b18bf550 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogFunctionValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogFunctionValueCollector.cs @@ -55,7 +55,7 @@ public override Task CollectValues(TemplateType templateType, Template parsedTem return Task.CompletedTask; } - scriptObject.Add(ExportConstants.ScribanDialogFunctionKey, new ScribanExportDialogFunction(inputFunction)); + scriptObject.AddOrUpdate(ExportConstants.ScribanDialogFunctionKey, new ScribanExportDialogFunction(inputFunction)); return Task.CompletedTask; } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogValueCollector.cs index 797b6a7b..bdc85b77 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/DialogValueCollector.cs @@ -123,14 +123,14 @@ public override async Task CollectValues(TemplateType templateType, Template par _languageKeyGenerator.SetErrorCollection(_errorCollection); - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); TaleDialog dialog = await _taleDbAccess.GetDialogByRelatedObjectId(inputNpc.Id); ExportDialogData parsedDialog = await ParseDialog(inputNpc, project, dialog); ScribanExportDialog exportDialog = await BuildExportDialog(parsedDialog, inputNpc); - scriptObject.Add(ExportConstants.ScribanDialogKey, exportDialog); - scriptObject.Add(DialogFunctionRenderer.DialogFunctionName, new DialogFunctionRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); + scriptObject.AddOrUpdate(ExportConstants.ScribanDialogKey, exportDialog); + scriptObject.AddOrUpdate(DialogFunctionRenderer.DialogFunctionName, new DialogFunctionRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetFunctionValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetFunctionValueCollector.cs index 52208544..49764d45 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetFunctionValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetFunctionValueCollector.cs @@ -55,7 +55,7 @@ public override Task CollectValues(TemplateType templateType, Template parsedTem return Task.CompletedTask; } - scriptObject.Add(ExportConstants.ScribanExportSnippetFunctionObjectKey, new ScribanExportSnippetFunction(inputFunction)); + scriptObject.AddOrUpdate(ExportConstants.ScribanExportSnippetFunctionObjectKey, new ScribanExportSnippetFunction(inputFunction)); return Task.CompletedTask; } diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetValueCollector.cs index c06e331b..ba9bc3fc 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/ExportSnippetValueCollector.cs @@ -100,9 +100,9 @@ public override async Task CollectValues(TemplateType templateType, Template par ScribanExportSnippetsData scribanExportSnippets = new ScribanExportSnippetsData(); scribanExportSnippets.Snippets = new ScribanExportSnippetDictionary(mappedSnippets); - scriptObject.Add(ExportConstants.ScribanExportSnippetsObjectKey, scribanExportSnippets); + scriptObject.AddOrUpdate(ExportConstants.ScribanExportSnippetsObjectKey, scribanExportSnippets); - scriptObject.Add(ExportSnippetFunctionPipeRenderer.ExportSnippetFunctionName, new ExportSnippetFunctionPipeRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection)); + scriptObject.AddOrUpdate(ExportSnippetFunctionPipeRenderer.ExportSnippetFunctionName, new ExportSnippetFunctionPipeRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection)); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/InventoryValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/InventoryValueCollector.cs index 64d4b1ac..bc7d707f 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/InventoryValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/InventoryValueCollector.cs @@ -83,8 +83,8 @@ public override async Task CollectValues(TemplateType templateType, Template par _languageKeyGenerator.SetErrorCollection(_errorCollection); List items = await LoadInventory(parsedTemplate, inputNpc); - scriptObject.Add(ExportConstants.ScribanNpcInventoryObjectKey, items); - scriptObject.Add(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); + scriptObject.AddOrUpdate(ExportConstants.ScribanNpcInventoryObjectKey, items); + scriptObject.AddOrUpdate(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); } /// @@ -101,7 +101,7 @@ private async Task> LoadInventory(Template pars } - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); ExportSettings exportSettings = await _exportCachedDbAccess.GetExportSettings(project.Id); List inventoryItems = new List(); diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/LanguageKeyValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/LanguageKeyValueCollector.cs index 51380de9..b10917e9 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/LanguageKeyValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/LanguageKeyValueCollector.cs @@ -93,7 +93,7 @@ public override async Task CollectValues(TemplateType templateType, Template par referencedLanguageKeys = new List(); } - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); List languageKeys = await _languageKeyDbAccess.GetLanguageKeysByGroupId(project.Id, flexFieldObject.Id); ExportSettings exportSettings = await _exportCachedDbAccess.GetExportSettings(project.Id); @@ -104,7 +104,7 @@ public override async Task CollectValues(TemplateType templateType, Template par languageFileData.LanguageKeys = ConvertLanguageKeysToScriban(languageKeys, exportSettings); languageFileData.ReferencedLanguageKeys = ConvertLanguageKeysToScriban(referencedLanguageKeys, exportSettings); - scriptObject.Add(LanguageObjectKey, languageFileData); + scriptObject.AddOrUpdate(LanguageObjectKey, languageFileData); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcDailyRoutineExportValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcDailyRoutineExportValueCollector.cs index 8e5ed13b..6a133975 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcDailyRoutineExportValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcDailyRoutineExportValueCollector.cs @@ -103,11 +103,11 @@ public override async Task CollectValues(TemplateType templateType, Template par ScribanExportDailyRoutine dailyRoutine = new ScribanExportDailyRoutine(); dailyRoutine.Events = await ScribanDailyRoutineEventUtil.MapNpcDailyRoutineEvents(_cachedDbAccess, _dailyRoutineFunctionNameGenerator, inputNpc, inputNpc.DailyRoutine); dailyRoutine.EventFunctions = await BuildDailyRoutineFunctions(inputNpc, inputNpc.DailyRoutine); - scriptObject.Add(ExportConstants.ScribanDailyRoutineObjectKey, dailyRoutine); + scriptObject.AddOrUpdate(ExportConstants.ScribanDailyRoutineObjectKey, dailyRoutine); - scriptObject.Add(DailyRoutineEventListRenderer.DailyRoutineEventListFunctionName, new DailyRoutineEventListRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); - scriptObject.Add(DailyRoutineEventFunctionRenderer.DailyRoutineEventFunctionName, new DailyRoutineEventFunctionRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); - scriptObject.Add(DailyRoutineEventFunctionListRenderer.DailyRoutineEventFunctionListFunctionName, new DailyRoutineEventFunctionListRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); + scriptObject.AddOrUpdate(DailyRoutineEventListRenderer.DailyRoutineEventListFunctionName, new DailyRoutineEventListRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); + scriptObject.AddOrUpdate(DailyRoutineEventFunctionRenderer.DailyRoutineEventFunctionName, new DailyRoutineEventFunctionRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); + scriptObject.AddOrUpdate(DailyRoutineEventFunctionListRenderer.DailyRoutineEventFunctionListFunctionName, new DailyRoutineEventFunctionListRenderer(_templatePlaceholderResolver, _cachedDbAccess, _defaultTemplateProvider, _errorCollection)); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcExportValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcExportValueCollector.cs index a2cb82c3..4afb8beb 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcExportValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcExportValueCollector.cs @@ -5,6 +5,7 @@ using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.LanguageKeyGenerator; using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingFunctions; using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.RenderingObjects; +using GoNorth.Services.Export.Placeholder.ScribanRenderingEngine.Util; using Microsoft.Extensions.Localization; using Scriban; using Scriban.Runtime; @@ -66,8 +67,8 @@ protected override void SetAdditionalExportValues(ScribanExportNpc exportObject, /// Export Data protected override void AddAdditionalScriptObjectValues(TemplateType templateType, Template parsedTemplate, ScriptObject scriptObject, ExportObjectData data) { - scriptObject.Add(InventoryListRenderer.InventoryListFunctionName, new InventoryListRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); - scriptObject.Add(SkillListRenderer.SkillListFunctionName, new SkillListRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); + scriptObject.AddOrUpdate(InventoryListRenderer.InventoryListFunctionName, new InventoryListRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); + scriptObject.AddOrUpdate(SkillListRenderer.SkillListFunctionName, new SkillListRenderer(_templatePlaceholderResolver, _exportCachedDbAccess, _defaultTemplateProvider, _errorCollection, data)); } /// diff --git a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcSkillValueCollector.cs b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcSkillValueCollector.cs index d6b25cef..af8bd4ec 100644 --- a/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcSkillValueCollector.cs +++ b/Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/NpcSkillValueCollector.cs @@ -83,8 +83,8 @@ public override async Task CollectValues(TemplateType templateType, Template par _languageKeyGenerator.SetErrorCollection(_errorCollection); List skills = await LoadSkills(parsedTemplate, inputNpc); - scriptObject.Add(ExportConstants.ScribanNpcSkillsObjectKey, skills); - scriptObject.Add(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); + scriptObject.AddOrUpdate(ExportConstants.ScribanNpcSkillsObjectKey, skills); + scriptObject.AddOrUpdate(ExportConstants.ScribanLanguageKeyName, _languageKeyGenerator); } /// @@ -100,7 +100,7 @@ private async Task> LoadSkills(Template parsedTemplate, return new List(); } - GoNorthProject project = await _exportCachedDbAccess.GetDefaultProject(); + GoNorthProject project = await _exportCachedDbAccess.GetUserProject(); ExportSettings exportSettings = await _exportCachedDbAccess.GetExportSettings(project.Id); List skills = await _exportCachedDbAccess.GetSkillsById(inputNpc.Skills.Select(i => i.SkillId).ToList()); diff --git a/Services/Export/Placeholder/Util/SharedDailyRoutineExportUtil.cs b/Services/Export/Placeholder/Util/SharedDailyRoutineExportUtil.cs index 9549e659..be1564ee 100644 --- a/Services/Export/Placeholder/Util/SharedDailyRoutineExportUtil.cs +++ b/Services/Export/Placeholder/Util/SharedDailyRoutineExportUtil.cs @@ -14,6 +14,11 @@ public static class SharedDailyRoutineExportUtil /// Daily routine to sort public static void SortDailyRoutine(List dailyRoutine) { + if(dailyRoutine == null) + { + return; + } + dailyRoutine.Sort((d1, d2) => { if (d1.EarliestTime == null && d2.EarliestTime != null) diff --git a/Services/Export/Placeholder/Util/SharedDialogExportUtil.cs b/Services/Export/Placeholder/Util/SharedDialogExportUtil.cs index 20bf45eb..56235349 100644 --- a/Services/Export/Placeholder/Util/SharedDialogExportUtil.cs +++ b/Services/Export/Placeholder/Util/SharedDialogExportUtil.cs @@ -20,7 +20,7 @@ public static bool HasValidDialog(TaleDialog dialog) return false; } - if(!dialog.NpcText.Any() && !dialog.PlayerText.Any() && !dialog.Choice.Any() && !dialog.Condition.Any() && !dialog.Action.Any()) + if(!dialog.NpcText.Any() && !dialog.PlayerText.Any() && !dialog.Choice.Any() && !dialog.Condition.Any() && !dialog.Action.Any() && !dialog.Reference.Any()) { return false; } diff --git a/Services/Export/Script/ScriptExporter.cs b/Services/Export/Script/ScriptExporter.cs index c112c1bc..f407a670 100644 --- a/Services/Export/Script/ScriptExporter.cs +++ b/Services/Export/Script/ScriptExporter.cs @@ -2,6 +2,7 @@ using GoNorth.Data.Exporting; using GoNorth.Data.Project; using GoNorth.Services.Export.Placeholder; +using GoNorth.Services.Project; namespace GoNorth.Services.Export.Script { @@ -16,9 +17,9 @@ public class ScriptExporter : IObjectExporter private readonly IExportTemplatePlaceholderResolver _placeholderResolver; /// - /// Project Db Access + /// User project access /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Export Settings Db Access @@ -29,13 +30,13 @@ public class ScriptExporter : IObjectExporter /// Constructor /// /// Pkaceholder Resolver - /// Project Db Access /// Export Settings Db Accesss - public ScriptExporter(IExportTemplatePlaceholderResolver placeholderResolver, IProjectDbAccess projectDbAccess, IExportSettingsDbAccess exportSettingsDbAccess) + /// User project access + public ScriptExporter(IExportTemplatePlaceholderResolver placeholderResolver, IExportSettingsDbAccess exportSettingsDbAccess, IUserProjectAccess userProjectAccess) { - _projectDbAccess = projectDbAccess; _placeholderResolver = placeholderResolver; _exportSettingsDbAccess = exportSettingsDbAccess; + _userProjectAccess = userProjectAccess; } /// @@ -46,7 +47,7 @@ public ScriptExporter(IExportTemplatePlaceholderResolver placeholderResolver, IP /// Export Result public async Task ExportObject(ExportTemplate template, ExportObjectData objectData) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); ExportSettings exportSettings = await _exportSettingsDbAccess.GetExportSettings(project.Id); ExportObjectResult result = new ExportObjectResult(); diff --git a/Services/Export/TemplateParsing/ScribanIncludeTemplateRefParser.cs b/Services/Export/TemplateParsing/ScribanIncludeTemplateRefParser.cs index 6a2ff6c0..8fd123d7 100644 --- a/Services/Export/TemplateParsing/ScribanIncludeTemplateRefParser.cs +++ b/Services/Export/TemplateParsing/ScribanIncludeTemplateRefParser.cs @@ -77,7 +77,7 @@ private async Task> ParseIncludeTemplates(E continue; } - string templateName = functionCall.Arguments[0].ToString(); + string templateName = functionCall.Arguments[0].ToString().Trim('\"').Trim('\''); IncludeExportTemplate existingTemplate = await _cachedDbAccess.GetIncludeTemplateByName(template.ProjectId, templateName); if(existingTemplate != null && !includeTemplateRefs.Any(e => e.IncludeTemplateId == existingTemplate.Id)) { diff --git a/Services/ImplementationStatusCompare/CompareDifferenceValue.cs b/Services/ImplementationStatusCompare/CompareDifferenceValue.cs index d70dbe3d..e079907c 100644 --- a/Services/ImplementationStatusCompare/CompareDifferenceValue.cs +++ b/Services/ImplementationStatusCompare/CompareDifferenceValue.cs @@ -17,6 +17,11 @@ public enum ValueResolveType /// None, + /// + /// Value is an npc id and must be resolved + /// + ResolveNpcName, + /// /// Value is an item id and must be resolved /// @@ -27,6 +32,26 @@ public enum ValueResolveType /// ResolveSkillName, + /// + /// Value is a quest id and must be resolved + /// + ResolveQuestName, + + /// + /// Value is a wiki page id and must be resolved + /// + ResolveWikiPageName, + + /// + /// Value is a map id and must be resolved + /// + ResolveMapName, + + /// + /// Value must be ignored + /// + Ignore, + /// /// Value is a language key and must be resolved /// diff --git a/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.cs b/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.cs index 0329f667..f16e0979 100644 --- a/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.cs +++ b/Services/ImplementationStatusCompare/GenericImplementationStatusComparer.cs @@ -9,6 +9,7 @@ using GoNorth.Data.Exporting; using GoNorth.Data.Karta; using GoNorth.Data.Karta.Marker; +using GoNorth.Data.Kirja; using GoNorth.Data.Kortisto; using GoNorth.Data.Styr; using GoNorth.Data.Tale; @@ -81,6 +82,11 @@ public class GenericImplementationStatusComparer : IImplementationStatusComparer /// private readonly IKartaMarkerImplementationSnapshotDbAccess _markerSnapshotDbAccess; + /// + /// Kirja Page Db Access + /// + private readonly IKirjaPageDbAccess _pageDbAccess; + /// /// Object Export Snippet Db Access /// @@ -111,13 +117,14 @@ public class GenericImplementationStatusComparer : IImplementationStatusComparer /// Quest Implementation Snapshot Db Access /// Map Db Access /// Marker Db Access + /// Kirja page Db Access /// Object export snippet Db Access /// Object export snippet snapshot Db Access /// Localizer Factory public GenericImplementationStatusComparer(IKortistoNpcDbAccess npcDbAccess, IKortistoNpcImplementationSnapshotDbAccess npcSnapshotDbAccess, IStyrItemDbAccess itemDbAccess, IStyrItemImplementationSnapshotDbAccess itemSnapshotDbAccess, IEvneSkillDbAccess skillDbAccess, IEvneSkillImplementationSnapshotDbAccess skillSnapshotDbAccess, ITaleDbAccess dialogDbAccess, ITaleDialogImplementationSnapshotDbAccess dialogSnapshotDbAccess, IAikaQuestDbAccess questDbAccess, IAikaQuestImplementationSnapshotDbAccess questSnapshotDbAccess, IKartaMapDbAccess mapDbAccess, IKartaMarkerImplementationSnapshotDbAccess markerSnapshotDbAccess, - IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IStringLocalizerFactory localizerFactory) + IKirjaPageDbAccess pageDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IObjectExportSnippetSnapshotDbAccess objectExportSnippetSnapshotDbAccess, IStringLocalizerFactory localizerFactory) { _npcDbAccess = npcDbAccess; _npcSnapshotDbAccess = npcSnapshotDbAccess; @@ -131,6 +138,7 @@ public class GenericImplementationStatusComparer : IImplementationStatusComparer _questSnapshotDbAccess = questSnapshotDbAccess; _mapDbAccess = mapDbAccess; _markerSnapshotDbAccess = markerSnapshotDbAccess; + _pageDbAccess = pageDbAccess; _objectExportSnippetDbAccess = objectExportSnippetDbAccess; _objectExportSnippetSnapshotDbAccess = objectExportSnippetSnapshotDbAccess; _localizer = localizerFactory.Create(typeof(GenericImplementationStatusComparer)); @@ -549,6 +557,12 @@ public async Task> FormatCompareResult(ListDifferences to resolve private async Task ResolveNames(List differences) { + List npcIds = CollectIds(differences, CompareDifferenceValue.ValueResolveType.ResolveNpcName); + if(npcIds.Count > 0) + { + await ResolveNpcNames(npcIds, differences); + } + List itemIds = CollectIds(differences, CompareDifferenceValue.ValueResolveType.ResolveItemName); if(itemIds.Count > 0) { @@ -560,8 +574,28 @@ private async Task ResolveNames(List differences) { await ResolveSkillNames(skillIds, differences); } + + List questIds = CollectIds(differences, CompareDifferenceValue.ValueResolveType.ResolveQuestName); + if(questIds.Count > 0) + { + await ResolveQuestNames(questIds, differences); + } + + List pageIds = CollectIds(differences, CompareDifferenceValue.ValueResolveType.ResolveWikiPageName); + if(pageIds.Count > 0) + { + await ResolveWikiPageNames(pageIds, differences); + } + + List mapIds = CollectIds(differences, CompareDifferenceValue.ValueResolveType.ResolveMapName); + if(mapIds.Count > 0) + { + await ResolveMapNames(mapIds, differences); + } ResolveLanguageKeys(differences); + + RemoveIgnoreValues(differences); } /// @@ -605,6 +639,19 @@ private void CollectId(List ids, CompareDifferenceValue value, CompareDi ids.Add(value.Value); } + /// + /// Resolves npc names + /// + /// Npcs Ids to resolve + /// Differences to fill + private async Task ResolveNpcNames(List npcIds, List differences) + { + npcIds = npcIds.Distinct().ToList(); + List npcs = await _npcDbAccess.ResolveFlexFieldObjectNames(npcIds); + Dictionary npcLookup = npcs.ToDictionary(i => i.Id, i => i.Name); + FillObjectNames(differences, npcLookup, CompareDifferenceValue.ValueResolveType.ResolveNpcName, "NpcWasDeleted"); + } + /// /// Resolves item names /// @@ -631,6 +678,45 @@ private async Task ResolveSkillNames(List skillIds, List + /// Resolves quest names + /// + /// Quest Ids to resolve + /// Differences to fill + private async Task ResolveQuestNames(List questIds, List differences) + { + questIds = questIds.Distinct().ToList(); + List quests = await _questDbAccess.ResolveQuestNames(questIds); + Dictionary questLookup = quests.ToDictionary(i => i.Id, i => i.Name); + FillObjectNames(differences, questLookup, CompareDifferenceValue.ValueResolveType.ResolveQuestName, "QuestWasDeleted"); + } + + /// + /// Resolves wiki page names + /// + /// Page Ids to resolve + /// Differences to fill + private async Task ResolveWikiPageNames(List pageIds, List differences) + { + pageIds = pageIds.Distinct().ToList(); + List pages = await _pageDbAccess.ResolveNames(pageIds); + Dictionary pageLookup = pages.ToDictionary(i => i.Id, i => i.Name); + FillObjectNames(differences, pageLookup, CompareDifferenceValue.ValueResolveType.ResolveWikiPageName, "WikiPageWasDeleted"); + } + + /// + /// Resolves map names + /// + /// Map Ids to resolve + /// Differences to fill + private async Task ResolveMapNames(List mapIds, List differences) + { + mapIds = mapIds.Distinct().ToList(); + List maps = await _mapDbAccess.ResolveMapNames(mapIds); + Dictionary mapLookup = maps.ToDictionary(i => i.Id, i => i.Name); + FillObjectNames(differences, mapLookup, CompareDifferenceValue.ValueResolveType.ResolveMapName, "MapWasDeleted"); + } + /// /// Fills object names /// @@ -714,6 +800,21 @@ private void ResolveSingleLanguageKey(CompareDifferenceValue value) value.Value = _localizer[value.Value, value.AdditionalValuesForLanguageKey.ToArray()].Value; } + /// + /// Removes all values that must be ignored + /// + /// Differences to update + private void RemoveIgnoreValues(List differences) + { + if(differences == null) + { + return; + } + + differences.RemoveAll(d => (d.OldValue != null && d.OldValue.ResolveType == CompareDifferenceValue.ValueResolveType.Ignore) || (d.NewValue != null && d.NewValue.ResolveType == CompareDifferenceValue.ValueResolveType.Ignore)); + differences.ForEach(d => RemoveIgnoreValues(d.SubDifferences)); + } + /// /// Formats a compare result array /// diff --git a/Services/Project/IUserProjectAccess.cs b/Services/Project/IUserProjectAccess.cs new file mode 100644 index 00000000..b7146d14 --- /dev/null +++ b/Services/Project/IUserProjectAccess.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; +using GoNorth.Data.Project; + +namespace GoNorth.Services.Project +{ + /// + /// Interface for project access + /// + public interface IUserProjectAccess + { + /// + /// Returns the current user project + /// + /// Current user project + Task GetUserProject(); + } +} \ No newline at end of file diff --git a/Services/Project/UserProjectAccess.cs b/Services/Project/UserProjectAccess.cs new file mode 100644 index 00000000..8349f443 --- /dev/null +++ b/Services/Project/UserProjectAccess.cs @@ -0,0 +1,65 @@ +using System.Threading.Tasks; +using GoNorth.Data.Project; +using GoNorth.Data.User; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; + +namespace GoNorth.Services.Project +{ + /// + /// Class for project access + /// + public class UserProjectAccess : IUserProjectAccess + { + /// + /// Project Db Access + /// + private readonly IProjectDbAccess _projectDbAccess; + + /// + /// User Manager + /// + private readonly UserManager _userManager; + + /// + /// Http Context accessor + /// + private readonly IHttpContextAccessor _httpContext; + + /// + /// User project access + /// + /// Project Db Access + /// User Manager + /// Http Context Accessor + public UserProjectAccess(IProjectDbAccess projectDbAccess, UserManager userManager, IHttpContextAccessor httpContextAccessor) + { + _projectDbAccess = projectDbAccess; + _userManager = userManager; + _httpContext = httpContextAccessor; + } + + /// + /// Returns the current user project + /// + /// Current user project + public async Task GetUserProject() + { + string userId = _userManager.GetUserId(_httpContext.HttpContext.User); + UserSelectedProject selectedProject = await _projectDbAccess.GetUserSelectedProject(userId); + + GoNorthProject project = null; + if(selectedProject != null) + { + project = await _projectDbAccess.GetProjectById(selectedProject.ProjectId); + } + + if(project == null) + { + project = await _projectDbAccess.GetDefaultProject(); + } + + return project; + } + } +} \ No newline at end of file diff --git a/Services/ReferenceAnalyzer/IReferenceAnalyzer.cs b/Services/ReferenceAnalyzer/IReferenceAnalyzer.cs new file mode 100644 index 00000000..96240e3e --- /dev/null +++ b/Services/ReferenceAnalyzer/IReferenceAnalyzer.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using GoNorth.Data.NodeGraph; +using GoNorth.Data.Tale; + +namespace GoNorth.Services.ReferenceAnalyzer +{ + /// + /// Interface for services to build object references + /// + public interface IReferenceAnalyzer + { + /// + /// Builds an object reference + /// + /// Id of the object that is referenced and for which the references are built + /// Id of the object + /// Name of the object + /// Optional actions for detailed references + /// Optional conditions for detailed references + /// Optional references for detailed references + /// Optional choice nodes for detailed references + /// Object reference + ObjectReference BuildObjectReferences(string referencedObjectId, string objectId, string objectName, List actions, List conditions, List referenceNodes, List choices); + } +} \ No newline at end of file diff --git a/Services/ReferenceAnalyzer/ObjectReference.cs b/Services/ReferenceAnalyzer/ObjectReference.cs new file mode 100644 index 00000000..2970d843 --- /dev/null +++ b/Services/ReferenceAnalyzer/ObjectReference.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace GoNorth.Services.ReferenceAnalyzer +{ + /// + /// Object Reference + /// + public class ObjectReference + { + /// + /// Id of the object + /// + public string ObjectId { get; set; } + + /// + /// Name of the object + /// + public string ObjectName { get; set; } + + /// + /// Detailed references where the object is referenced. These are nodes for example + /// + public List DetailedReferences { get; set; } + + /// + /// Constructor + /// + public ObjectReference() + { + DetailedReferences = new List(); + } + } +} \ No newline at end of file diff --git a/Services/ReferenceAnalyzer/ReferenceAnalyzer.cs b/Services/ReferenceAnalyzer/ReferenceAnalyzer.cs new file mode 100644 index 00000000..1de629a0 --- /dev/null +++ b/Services/ReferenceAnalyzer/ReferenceAnalyzer.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using GoNorth.Data.NodeGraph; +using GoNorth.Data.Tale; +using GoNorth.Services.Export.Dialog; +using GoNorth.Services.Export.Dialog.ActionRendering; +using GoNorth.Services.Export.Dialog.ActionRendering.Localization; +using GoNorth.Services.Export.Dialog.ConditionRendering; +using GoNorth.Services.Export.Dialog.ConditionRendering.Localization; +using Microsoft.Extensions.Localization; + +namespace GoNorth.Services.ReferenceAnalyzer +{ + /// + /// Service to build object references + /// + public class ReferenceAnalyzer : IReferenceAnalyzer + { + /// + /// Translation service for actions + /// + private readonly IActionTranslator _actionTranslator; + + /// + /// Translation service for conditions + /// + private readonly IConditionTranslator _conditionTranslator; + + /// + /// Localizer + /// + private readonly IStringLocalizer _localizer; + + /// + /// Constructor + /// + /// Translation service for actions + /// Translation service for conditions + /// Localizer Factory + public ReferenceAnalyzer(IActionTranslator actionTranslator, IConditionTranslator conditionTranslator, IStringLocalizerFactory localizerFactory) + { + _actionTranslator = actionTranslator; + _conditionTranslator = conditionTranslator; + _localizer = localizerFactory.Create(typeof(ReferenceAnalyzer)); + } + + /// + /// Builds an object reference + /// + /// Id of the object that is referenced and for which the references are built + /// Id of the object + /// Name of the object + /// Optional actions for detailed references + /// Optional conditions for detailed references + /// Optional references for detailed references + /// Optional choice nodes for detailed references + /// Object reference + public ObjectReference BuildObjectReferences(string referencedObjectId, string objectId, string objectName, List actions, List conditions, List referenceNodes, List choices) + { + ObjectReference objReference = new ObjectReference(); + objReference.ObjectId = objectId; + objReference.ObjectName = objectName; + if(actions != null) + { + objReference.DetailedReferences.AddRange(BuildActionReferences(referencedObjectId, actions)); + } + + if(conditions != null) + { + objReference.DetailedReferences.AddRange(BuildConditionsReferences(referencedObjectId, conditions)); + } + + if(referenceNodes != null) + { + objReference.DetailedReferences.AddRange(BuildReferenceNodeReferences(referencedObjectId, referenceNodes)); + } + + if(choices != null) + { + objReference.DetailedReferences.AddRange(BuildChoicesReferences(referencedObjectId, choices)); + } + + return objReference; + } + + /// + /// Builds a list of references in actions + /// + /// Id of the object that is referenced and for which the references are built + /// Actions to analyze + /// References for the object + private IEnumerable BuildActionReferences(string referencedObjectId, List actions) + { + return actions.Where(a => a.ActionRelatedToObjectId == referencedObjectId || (a.ActionRelatedToAdditionalObjects != null && a.ActionRelatedToAdditionalObjects.Any(a => a.ObjectId == referencedObjectId))).Select(a => new ObjectReference { + ObjectId = a.Id, + ObjectName = _actionTranslator.TranslateActionType((ActionType)a.ActionType) + }); + } + + /// + /// Builds a list of references in conditions + /// + /// Id of the object that is referenced and for which the references are built + /// Conditions to analyze + /// References for the object + private IEnumerable BuildConditionsReferences(string referencedObjectId, List conditions) + { + return conditions.Where(c => c.Conditions.Any(co => co.DependsOnObjects != null && co.DependsOnObjects.Any(d => d.ObjectId == referencedObjectId))).Select(c => new ObjectReference { + ObjectId = c.Id, + ObjectName = string.Join("; ", c.Conditions.Where(co => co.DependsOnObjects != null && co.DependsOnObjects.Any(d => d.ObjectId == referencedObjectId)).Select(co => BuildConditionName(co.ConditionElements))) + }); + } + + /// + /// Builds a condition name + /// + /// Condition elements + /// Condition name + private string BuildConditionName(string conditionElements) + { + List parsedConditionData = ConditionParsingUtil.ParseConditionElements(conditionElements); + return string.Join(",", parsedConditionData.Select(c => _conditionTranslator.TranslateConditionType((ConditionType)c.ConditionType))); + } + + /// + /// Builds a list of references in reference nodes + /// + /// Id of the object that is referenced and for which the references are built + /// Reference nodes to analyze + /// References for the object + private IEnumerable BuildReferenceNodeReferences(string referencedObjectId, List referenceNodes) + { + return referenceNodes.Where(r => r.ReferencedObjects != null && r.ReferencedObjects.Any(ro => ro.ObjectId == referencedObjectId)).Select(r => new ObjectReference { + ObjectId = r.Id, + ObjectName = !string.IsNullOrEmpty(r.ReferenceText) ? r.ReferenceText : _localizer["Reference"].Value + }); + } + + /// + /// Builds a list of references in choice nodes + /// + /// Id of the object that is referenced and for which the references are built + /// Choices to analyze + /// References for the object + private IEnumerable BuildChoicesReferences(string referencedObjectId, List choices) + { + return choices.Where(c => c.Choices.Any(co => co.Condition != null && co.Condition.DependsOnObjects.Any(o => o.ObjectId == referencedObjectId))).Select(c => new ObjectReference { + ObjectId = c.Id, + ObjectName = string.Join("; ", c.Choices.Where(co => co.Condition != null && co.Condition.DependsOnObjects.Any(o => o.ObjectId == referencedObjectId)).Select(c => !string.IsNullOrEmpty(c.Text) ? c.Text : _localizer["EmptyChoiceText"].Value)) + }); + } + } +} \ No newline at end of file diff --git a/Services/Timeline/ITimelineService.cs b/Services/Timeline/ITimelineService.cs index 523c39e8..a46654ff 100644 --- a/Services/Timeline/ITimelineService.cs +++ b/Services/Timeline/ITimelineService.cs @@ -10,10 +10,11 @@ public interface ITimelineService /// /// Adds a timeline event /// + /// Id of the project to associate, if null the project will be loaded /// Timeline Event /// Additional Values /// Task - Task AddTimelineEntry(TimelineEvent timelineEvent, params string[] additionalValues); + Task AddTimelineEntry(string projectId, TimelineEvent timelineEvent, params string[] additionalValues); /// /// Returns the timeline entries for a paged view diff --git a/Services/Timeline/TimelineService.cs b/Services/Timeline/TimelineService.cs index 36b0f9e7..d1f0b489 100644 --- a/Services/Timeline/TimelineService.cs +++ b/Services/Timeline/TimelineService.cs @@ -9,6 +9,7 @@ using GoNorth.Data.Project; using GoNorth.Data.Timeline; using GoNorth.Data.User; +using GoNorth.Services.Project; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; @@ -26,9 +27,9 @@ public class TimelineService : ITimelineService private readonly ITimelineDbAccess _timelineDbAccess; /// - /// Project Db Accesss + /// User Project Accesss /// - private readonly IProjectDbAccess _projectDbAccess; + private readonly IUserProjectAccess _userProjectAccess; /// /// Template Service @@ -59,15 +60,15 @@ public class TimelineService : ITimelineService /// Constructor /// /// Timeline Db Access - /// Project Db Access + /// User project Access /// Template Service /// User Manager /// Http Context /// Config Data - public TimelineService(ITimelineDbAccess timelineDbAccess, IProjectDbAccess projectDbAccess, ITimelineTemplateService templateService, UserManager userManager, IHttpContextAccessor httpContext, IOptions configuration) + public TimelineService(ITimelineDbAccess timelineDbAccess, IUserProjectAccess userProjectAccess, ITimelineTemplateService templateService, UserManager userManager, IHttpContextAccessor httpContext, IOptions configuration) { _timelineDbAccess = timelineDbAccess; - _projectDbAccess = projectDbAccess; + _userProjectAccess = userProjectAccess; _templateService = templateService; _userManager = userManager; _httpContext = httpContext; @@ -240,22 +241,32 @@ private void SetupFilters() /// /// Adds a timeline event /// + /// Id of the project to associate, if null the project will be loaded /// Timeline Event /// Additional Values /// Task - public async Task AddTimelineEntry(TimelineEvent timelineEvent, params string[] additionalValues) + public async Task AddTimelineEntry(string projectId, TimelineEvent timelineEvent, params string[] additionalValues) { - Task currentUserTask = _userManager.GetUserAsync(_httpContext.HttpContext.User); - Task projectTask = _projectDbAccess.GetDefaultProject(); - Task.WaitAll(currentUserTask, projectTask); - GoNorthUser currentUser = currentUserTask.Result; - GoNorthProject project = projectTask.Result; + GoNorthUser currentUser; + if(string.IsNullOrEmpty(projectId)) + { + Task currentUserTask = _userManager.GetUserAsync(_httpContext.HttpContext.User); + Task projectTask = _userProjectAccess.GetUserProject(); + Task.WaitAll(currentUserTask, projectTask); + currentUser = currentUserTask.Result; + GoNorthProject project = projectTask.Result; + projectId = project != null ? project.Id : string.Empty; + } + else + { + currentUser = await _userManager.GetUserAsync(_httpContext.HttpContext.User); + } string updateId = null; if(_eventMergeTimeSpan > 0) { DateTimeOffset dateLimit = DateTimeOffset.UtcNow.AddMinutes(-_eventMergeTimeSpan); - List timelineEntries = await _timelineDbAccess.GetTimelineEntriesByUserInTimeSpan(project.Id, currentUser.UserName, timelineEvent, dateLimit); + List timelineEntries = await _timelineDbAccess.GetTimelineEntriesByUserInTimeSpan(projectId, currentUser.UserName, timelineEvent, dateLimit); foreach(TimelineEntry curEntry in timelineEntries) { if(curEntry.AdditionalValues == null && additionalValues == null) @@ -294,7 +305,7 @@ public async Task AddTimelineEntry(TimelineEvent timelineEvent, params string[] } TimelineEntry entry = new TimelineEntry(); - entry.ProjectId = project != null ? project.Id : string.Empty; + entry.ProjectId = projectId; entry.Event = timelineEvent; entry.Timestamp = DateTimeOffset.UtcNow; entry.AdditionalValues = additionalValues; @@ -320,7 +331,7 @@ public async Task AddTimelineEntry(TimelineEvent timelineEvent, params string[] /// Query result public async Task GetTimelineEntriesPaged(int start, int pageSize) { - GoNorthProject project = await _projectDbAccess.GetDefaultProject(); + GoNorthProject project = await _userProjectAccess.GetUserProject(); string projectId = project != null ? project.Id : string.Empty; Task currentUserTask = _userManager.GetUserAsync(_httpContext.HttpContext.User); diff --git a/Services/TimerJob/ITimerJob.cs b/Services/TimerJob/ITimerJob.cs new file mode 100644 index 00000000..74d4aaf5 --- /dev/null +++ b/Services/TimerJob/ITimerJob.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; + +namespace GoNorth.Services.TimerJob +{ + /// + /// Interface for timer jobs + /// + public interface ITimerJob + { + /// + /// Returns the optional preferred start time + /// + /// Preferred Start Time + TimerJobRuntimeConfig GetPreferredStartTime(); + + /// + /// Returns the interval between run events in minutes + /// + /// Interval + int GetRunInterval(); + + /// + /// Runs the timer job + /// + /// Task + Task RunTimerJob(); + } +} diff --git a/Services/TimerJob/ITimerJobManager.cs b/Services/TimerJob/ITimerJobManager.cs new file mode 100644 index 00000000..74aa7019 --- /dev/null +++ b/Services/TimerJob/ITimerJobManager.cs @@ -0,0 +1,13 @@ +namespace GoNorth.Services.TimerJob +{ + /// + /// Interface for Timer Job Manager + /// + public interface ITimerJobManager + { + /// + /// Initializes the timer jobs + /// + void InitializeTimerJobs(); + } +} diff --git a/Services/TimerJob/JobDefinitions/ILockCleanupTimerJob.cs b/Services/TimerJob/JobDefinitions/ILockCleanupTimerJob.cs new file mode 100644 index 00000000..b6da8587 --- /dev/null +++ b/Services/TimerJob/JobDefinitions/ILockCleanupTimerJob.cs @@ -0,0 +1,9 @@ +namespace GoNorth.Services.TimerJob.JobDefinitions +{ + /// + /// Interface for lock cleanup timerjobs + /// + public interface ILockCleanupTimerJob : ITimerJob + { + } +} diff --git a/Services/TimerJob/JobDefinitions/LockCleanupTimerJob.cs b/Services/TimerJob/JobDefinitions/LockCleanupTimerJob.cs new file mode 100644 index 00000000..da79fa06 --- /dev/null +++ b/Services/TimerJob/JobDefinitions/LockCleanupTimerJob.cs @@ -0,0 +1,53 @@ +using System; +using System.Threading.Tasks; +using GoNorth.Data.LockService; + +namespace GoNorth.Services.TimerJob.JobDefinitions +{ + /// + /// Class to cleanup locks + /// + public class LockCleanupTimerJob : ILockCleanupTimerJob + { + /// + /// Lock Database access + /// + private readonly ILockServiceDbAccess _lockDbAccess; + + /// + /// Constructor + /// + /// Lock Database access + public LockCleanupTimerJob(ILockServiceDbAccess lockDbAccess) + { + _lockDbAccess = lockDbAccess; + } + + /// + /// Returns the optional preferred start time + /// + /// Preferred Start Time + public TimerJobRuntimeConfig GetPreferredStartTime() + { + return new TimerJobRuntimeConfig(new TimeSpan(23, 0, 0), true); + } + + /// + /// Returns the interval between run events in minutes + /// + /// Interval + public int GetRunInterval() + { + return 1440; + } + + /// + /// Runs the timer job + /// + /// Task + public async Task RunTimerJob() + { + await _lockDbAccess.DeleteExpiredLocks(); + } + } +} diff --git a/Services/TimerJob/TimerJobManager.cs b/Services/TimerJob/TimerJobManager.cs new file mode 100644 index 00000000..15bb4abb --- /dev/null +++ b/Services/TimerJob/TimerJobManager.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using GoNorth.Services.TimerJob.JobDefinitions; +using Microsoft.Extensions.Logging; + +namespace GoNorth.Services.TimerJob +{ + /// + /// Manager for Timerjobs + /// + public class TimerJobManager : ITimerJobManager + { + /// + /// Logger + /// + private readonly ILogger _logger; + + /// + /// Timer jobs + /// + private readonly List _timerJobs; + + /// + /// Job Timers + /// + private List _timers; + + /// + /// Constructor + /// + /// Timer job to clean locks + /// Logger + public TimerJobManager(ILockCleanupTimerJob lockCleanUpTimerJob, ILogger logger) + { + _timerJobs = new List + { + lockCleanUpTimerJob + }; + + _logger = logger; + } + + /// + /// Destructor + /// + ~TimerJobManager() + { + CleanUpTimerJobs(); + } + + /// + /// Cleans up all timer jobs + /// + private void CleanUpTimerJobs() + { + if (_timers == null) + { + return; + } + + foreach (Timer curTimer in _timers) + { + curTimer.Dispose(); + } + _timers.Clear(); + } + + /// + /// Initializes the timer jobs + /// + public void InitializeTimerJobs() + { + CleanUpTimerJobs(); + + _timers = new List(); + foreach (ITimerJob curTimerJob in _timerJobs) + { + TimeSpan offset = TimeSpan.FromSeconds(0); + TimerJobRuntimeConfig runtimeConfig = curTimerJob.GetPreferredStartTime(); + if(runtimeConfig != null) + { + if(!runtimeConfig.IsAbsoluteTime) + { + offset = runtimeConfig.Time; + } + else + { + offset = GetTimeSpanFromAbsoluteTime(runtimeConfig.Time); + } + } + + Timer jobTimer = new Timer(async (state) => + { + try + { + await ((ITimerJob)state).RunTimerJob(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error running timerjob: {0}", curTimerJob.GetType().ToString()); + } + }, curTimerJob, offset, TimeSpan.FromMinutes(curTimerJob.GetRunInterval())); + + _timers.Add(jobTimer); + } + } + + /// + /// Returns the offset for an absolut time + /// + /// Target Time + /// Timespan for absolut Time + private TimeSpan GetTimeSpanFromAbsoluteTime(TimeSpan time) + { + DateTime now = DateTime.Now; + DateTime refTime = new DateTime(now.Year, now.Month, now.Day, time.Hours, time.Minutes, 0); + if (time.Hours < now.Hour || (time.Hours == now.Hour && time.Minutes < now.Minute)) + { + refTime = refTime.AddDays(1); + } + + TimeSpan runtimeOffset = refTime - now; + if(runtimeOffset.Ticks < 0) + { + return TimeSpan.FromSeconds(0); + } + + return runtimeOffset; + } + } +} diff --git a/Services/TimerJob/TimerJobRunTimeConfig.cs b/Services/TimerJob/TimerJobRunTimeConfig.cs new file mode 100644 index 00000000..32ccfbc0 --- /dev/null +++ b/Services/TimerJob/TimerJobRunTimeConfig.cs @@ -0,0 +1,31 @@ +using System; + +namespace GoNorth.Services.TimerJob +{ + /// + /// Configuration for the runtime of timerjobs + /// + public class TimerJobRuntimeConfig + { + /// + /// Time component + /// + public TimeSpan Time { get; set; } + + /// + /// True if the time component is a time, else its an offset + /// + public bool IsAbsoluteTime { get; set; } + + /// + /// Constructor + /// + /// Time Component + /// True if the time component is a time, else its an offset + public TimerJobRuntimeConfig(TimeSpan time, bool isAbsoluteTime) + { + Time = time; + IsAbsoluteTime = isAbsoluteTime; + } + } +} diff --git a/Services/User/UserDeleter.cs b/Services/User/UserDeleter.cs index 3e10d120..c71fe37e 100644 --- a/Services/User/UserDeleter.cs +++ b/Services/User/UserDeleter.cs @@ -9,6 +9,7 @@ using GoNorth.Data.Kirja; using GoNorth.Data.Kortisto; using GoNorth.Data.LockService; +using GoNorth.Data.Project; using GoNorth.Data.ProjectConfig; using GoNorth.Data.Styr; using GoNorth.Data.Tale; @@ -179,6 +180,11 @@ public class UserDeleter : IUserDeleter /// private readonly IUserTaskBoardHistoryDbAccess _userTaskBoardHistoryDbAccess; + /// + /// Project Db Access + /// + private readonly IProjectDbAccess _projectDbAccess; + /// /// User manager /// @@ -218,6 +224,7 @@ public class UserDeleter : IUserDeleter /// User Task Board History /// Lock Db Service /// Timeline Db Access + /// Project Db Access /// User manager public UserDeleter(IAikaQuestDbAccess questDbAccess, IAikaQuestImplementationSnapshotDbAccess questImplementationSnapshotDbAccess, IAikaChapterDetailDbAccess chapterDetailDbAccess, IAikaChapterOverviewDbAccess chapterOverviewDbAccess, IEvneSkillDbAccess skillDbAccess, IEvneSkillTemplateDbAccess skillTemplateDbAccess, IEvneSkillImplementationSnapshotDbAccess skillImplementationSnapshotDbAccess, IEvneImportFieldValuesLogDbAccess skillImportFieldValuesLogDbAccess, IKortistoNpcDbAccess npcDbAccess, IKortistoNpcTemplateDbAccess npcTemplateDbAccess, @@ -225,7 +232,7 @@ public class UserDeleter : IUserDeleter IStyrItemImplementationSnapshotDbAccess itemImplementationSnapshotDbAccess, IStyrImportFieldValuesLogDbAccess itemImportFieldValuesLogDbAccess, IExportTemplateDbAccess exportTemplateDbAccess, IIncludeExportTemplateDbAccess includeExportTemplateDbAccess, IObjectExportSnippetDbAccess objectExportSnippetDbAccess, IKartaMapDbAccess mapDbAccess, IKirjaPageDbAccess pageDbAccess, IKirjaPageVersionDbAccess pageVersionDbAccess, ITaleDbAccess taleDbAccess, ITaleDialogImplementationSnapshotDbAccess taleImplementationSnapshotDbAccess, IProjectConfigDbAccess projectConfigDbAccess, ITaskBoardDbAccess taskBoardDbAccess, ITaskGroupTypeDbAccess taskGroupTypeDbAccess, ITaskTypeDbAccess taskTypeDbAccess, IUserTaskBoardHistoryDbAccess userTaskBoardHistoryDbAccess, ILockServiceDbAccess lockDbService, - ITimelineDbAccess timelineDbAccess, UserManager userManager) + ITimelineDbAccess timelineDbAccess, IProjectDbAccess projectDbAccess, UserManager userManager) { _questDbAccess = questDbAccess; _questImplementationSnapshotDbAccess = questImplementationSnapshotDbAccess; @@ -258,6 +265,7 @@ public class UserDeleter : IUserDeleter _userTaskBoardHistoryDbAccess = userTaskBoardHistoryDbAccess; _lockDbService = lockDbService; _timelineDbAccess = timelineDbAccess; + _projectDbAccess = projectDbAccess; _userManager = userManager; } @@ -513,6 +521,8 @@ private async Task DeleteModifiedData(GoNorthUser user) curType.ModifiedOn = DateTimeOffset.UtcNow; await _taskTypeDbAccess.UpdateTaskType(curType); } + + await _projectDbAccess.DeleteUserSelectedProject(user.Id); } /// diff --git a/Startup.cs b/Startup.cs index 0517b2cd..ef773977 100644 --- a/Startup.cs +++ b/Startup.cs @@ -61,6 +61,10 @@ using GoNorth.Services.Export.Dialog.ConditionRendering.Localization; using GoNorth.Services.Export.DailyRoutine; using GoNorth.Services.CsvHandling; +using GoNorth.Services.Project; +using GoNorth.Services.ReferenceAnalyzer; +using GoNorth.Services.TimerJob; +using GoNorth.Services.TimerJob.JobDefinitions; namespace GoNorth { @@ -157,13 +161,15 @@ public void ConfigureServices(IServiceCollection services) } // Framework services - services.AddSingleton(); + services.AddHttpContextAccessor(); // Application services services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -222,6 +228,7 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddScoped(); services.AddScoped(); @@ -231,9 +238,14 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(); services.AddTransient(); + + services.AddTransient(); + + services.AddTransient(); + services.AddSingleton(); // Database - services.AddScoped(); + services.AddTransient(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -359,7 +371,8 @@ public void ConfigureServices(IServiceCollection services) /// /// Application builder /// Hosting environment - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + /// Timer Job Manager + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ITimerJobManager timerJobManager) { ConfigurationData configData = Configuration.Get(); @@ -398,6 +411,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) endpoints.MapRazorPages(); }); + timerJobManager.InitializeTimerJobs(); + if(env.IsDevelopment()) { app.UseSwagger(); diff --git a/UITests/package-lock.json b/UITests/package-lock.json index ac9d2205..794c90ae 100644 --- a/UITests/package-lock.json +++ b/UITests/package-lock.json @@ -4,15 +4,10 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "@types/node": { - "version": "14.11.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", - "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", + "version": "14.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.12.tgz", + "integrity": "sha512-ASH8OPHMNlkdjrEdmoILmzFfsJICvhBsFfAum4aKZ/9U4B6M6tTmTPh+f3ttWdD74CEGV5XvXWkbyfSdXaTd7g==", "optional": true }, "@types/yauzl": { @@ -24,6 +19,11 @@ "@types/node": "*" } }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" + }, "agent-base": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", @@ -49,11 +49,10 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -204,17 +203,6 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "array.prototype.map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", - "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.4" - } - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -332,9 +320,9 @@ } }, "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "binary-extensions": { "version": "1.13.1", @@ -408,12 +396,12 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-crc32": { @@ -736,11 +724,11 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decamelize": { @@ -781,6 +769,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -833,9 +822,9 @@ "dev": true }, "devtools-protocol": { - "version": "0.0.799653", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.799653.tgz", - "integrity": "sha512-t1CcaZbvm8pOlikqrsIM9GOa7Ipp07+4h/q9u0JXBWjPCjHdBl9KkddX87Vv9vBHoBGtwV79sYQNGnQM6iS5gg==" + "version": "0.0.818844", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", + "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" }, "diff": { "version": "4.0.2", @@ -886,72 +875,6 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - } - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "es-get-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", - "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", - "requires": { - "es-abstract": "^1.17.4", - "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", @@ -1166,21 +1089,6 @@ "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "fancy-log": { @@ -1267,12 +1175,9 @@ "dev": true }, "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "requires": { - "is-buffer": "~2.0.3" - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" }, "flush-write-stream": { "version": "1.1.1", @@ -1879,7 +1784,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -2223,14 +2129,6 @@ "glogg": "^1.0.0" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2239,7 +2137,8 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true }, "has-value": { "version": "1.0.0", @@ -2306,27 +2205,12 @@ "requires": { "agent-base": "5", "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "inflight": { "version": "1.0.6", @@ -2390,11 +2274,6 @@ } } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2410,16 +2289,6 @@ "binary-extensions": "^1.0.0" } }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -2446,11 +2315,6 @@ } } }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -2494,11 +2358,6 @@ "is-extglob": "^2.1.1" } }, - "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==" - }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -2532,9 +2391,9 @@ } }, "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" }, "is-plain-object": { "version": "2.0.4", @@ -2545,21 +2404,6 @@ "isobject": "^3.0.1" } }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - } - } - }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -2569,31 +2413,6 @@ "is-unc-path": "^1.0.0" } }, - "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==" - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "requires": { - "has-symbols": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - } - } - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -2638,20 +2457,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==" - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -2745,9 +2550,9 @@ } }, "lodash": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.12.tgz", - "integrity": "sha512-+CiwtLnsJhX03p20mwXuvhoebatoh5B3tt+VvYlrPgZC1g36y+RRbkufX95Xa+X4I59aWEacDFYwnJZiyBh9gA==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "log-symbols": { "version": "4.0.0", @@ -2902,14 +2707,15 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mocha": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", - "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", + "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", "requires": { + "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.4.2", - "debug": "4.1.1", + "chokidar": "3.4.3", + "debug": "4.2.0", "diff": "4.0.2", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", @@ -2920,17 +2726,16 @@ "log-symbols": "4.0.0", "minimatch": "3.0.4", "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", + "nanoid": "3.1.12", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "7.2.0", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.0.0", + "workerpool": "6.0.2", "yargs": "13.3.2", "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" + "yargs-unparser": "2.0.0" }, "dependencies": { "anymatch": { @@ -2956,9 +2761,9 @@ } }, "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -2967,15 +2772,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" + "readdirp": "~3.5.0" } }, "fill-range": { @@ -3026,20 +2823,15 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "requires": { "picomatch": "^2.2.1" } @@ -3090,18 +2882,18 @@ } }, "mocha-multi-reporters": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", - "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", + "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", "requires": { - "debug": "^3.1.0", - "lodash": "^4.16.4" + "debug": "^4.1.1", + "lodash": "^4.17.15" } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mute-stdout": { "version": "1.0.1", @@ -3116,6 +2908,11 @@ "dev": true, "optional": true }, + "nanoid": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==" + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -3141,6 +2938,11 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3214,15 +3016,11 @@ } } }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=" + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -3237,6 +3035,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -3303,11 +3102,11 @@ } }, "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { @@ -3529,18 +3328,6 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, - "promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "requires": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - } - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -3579,14 +3366,15 @@ } }, "puppeteer": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.3.1.tgz", - "integrity": "sha512-YTM1RaBeYrj6n7IlRXRYLqJHF+GM7tasbvrNFx6w1S16G76NrPq7oYFKLDO+BQsXNtS8kW2GxWCXjIMPvfDyaQ==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", + "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", "requires": { "debug": "^4.1.0", - "devtools-protocol": "0.0.799653", + "devtools-protocol": "0.0.818844", "extract-zip": "^2.0.0", "https-proxy-agent": "^4.0.0", + "node-fetch": "^2.6.1", "pkg-dir": "^4.2.0", "progress": "^2.0.1", "proxy-from-env": "^1.0.0", @@ -3594,21 +3382,6 @@ "tar-fs": "^2.0.0", "unbzip2-stream": "^1.3.3", "ws": "^7.2.3" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "randombytes": { @@ -3858,9 +3631,9 @@ } }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", "requires": { "randombytes": "^2.1.0" } @@ -4146,24 +3919,6 @@ "strip-ansi": "^4.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4190,14 +3945,14 @@ } }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -4213,14 +3968,14 @@ } }, "tar-fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", - "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" } }, "tar-stream": { @@ -4582,9 +4337,9 @@ } }, "workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" }, "wrap-ansi": { "version": "2.1.0", @@ -4639,9 +4394,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==" + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", + "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==" }, "xml": { "version": "1.0.1", @@ -4655,9 +4410,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" }, "yargs": { "version": "13.3.2", @@ -4749,104 +4504,25 @@ } }, "yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" }, - "yargs-parser": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", - "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" } } }, @@ -4867,6 +4543,11 @@ "requires": { "buffer-crc32": "~0.2.3" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/UITests/package.json b/UITests/package.json index c957f7fa..1814ed23 100644 --- a/UITests/package.json +++ b/UITests/package.json @@ -14,10 +14,10 @@ "author": "Steffen Nörtershäuser", "license": "MIT", "dependencies": { - "mocha": "^8.1.3", + "mocha": "^8.2.1", "mocha-junit-reporter": "^2.0.0", - "mocha-multi-reporters": "^1.1.7", - "puppeteer": "^5.3.1" + "mocha-multi-reporters": "^1.5.1", + "puppeteer": "^5.5.0" }, "devDependencies": { "gulp": "^4.0.2", diff --git a/Views/Aika/Quest.cshtml b/Views/Aika/Quest.cshtml index 59f5239f..f6ee3cbe 100644 --- a/Views/Aika/Quest.cshtml +++ b/Views/Aika/Quest.cshtml @@ -143,7 +143,17 @@
@Localizer["UsedInAikaQuest"]
  • - + + + + +
@@ -162,7 +172,17 @@
@Localizer["ReferencedInTaleDialogs"]
  • - + + + + +
} @@ -186,6 +206,26 @@ } + + @if(User.IsInRole(RoleNames.Evne)) + { +
@Localizer["ReferencedInEvneSkills"]
+
    +
  • + +
  • +
+ } + + @if(User.IsInRole(RoleNames.ExportObjects)) + { +
@Localizer["ReferencedInExportSnippets"]
+
    +
  • + +
  • +
+ } @@ -216,6 +256,11 @@
@Localizer["FinishNode"]
+
+
+
@Localizer["ReferenceNode"]
+
+
@@ -264,6 +309,13 @@ @await Html.PartialAsync("~/Views/FlexFieldDatabase/FlexFieldScriptLocalization.cshtml") \ No newline at end of file diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index 5b724d75..5da13d15 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -1,5 +1,4 @@ @using Microsoft.AspNetCore.Mvc.Localization -@using GoNorth.Models.HomeViewModels @using GoNorth @model GoNorth.Models.HomeViewModels.IndexViewModel @@ -10,138 +9,170 @@ ViewData["Title"] = @Localizer["HomePage"]; } -

@Localizer["WelcomeToProject"] @Model.ProjectName

- -
-
- @if(User.IsInRole(RoleNames.Task)) - { -
- -
-
-
@Localizer["Tasks"]
-
@Localizer["TaskManagement"]
-
-
+
+

@Localizer["WelcomeToProject"] + +

- @if(User.IsInRole(RoleNames.Aika)) - { - - } +
+
+ @if(User.IsInRole(RoleNames.Task)) + { + + } - @if(User.IsInRole(RoleNames.Kortisto)) - { - - } + @if(User.IsInRole(RoleNames.Aika)) + { + + } - @if(User.IsInRole(RoleNames.Styr)) - { - - } + @if(User.IsInRole(RoleNames.Kortisto)) + { + + } - @if(User.IsInRole(RoleNames.Evne)) - { - - } + @if(User.IsInRole(RoleNames.Styr)) + { + + } - @if(User.IsInRole(RoleNames.Kirja)) - { - - } + @if(User.IsInRole(RoleNames.Evne)) + { + + } - @if(User.IsInRole(RoleNames.Karta)) - { - - } + @if(User.IsInRole(RoleNames.Kirja)) + { + + } - @if(User.IsInRole(RoleNames.ImplementationStatusTracker)) - { - - } - - @if(User.IsInRole(RoleNames.ManageExportTemplates)) - { - - } - - @if(User.IsInRole(RoleNames.ProjectConfigManager)) - { - - } + @if(User.IsInRole(RoleNames.Karta)) + { + + } + + @if(User.IsInRole(RoleNames.ImplementationStatusTracker)) + { + + } + + @if(User.IsInRole(RoleNames.ManageExportTemplates)) + { + + } + + @if(User.IsInRole(RoleNames.ProjectConfigManager)) + { + + } +
-
\ No newline at end of file +
+ +@section Scripts { + + + + + + + +} \ No newline at end of file diff --git a/Views/Karta/ManageMaps.cshtml b/Views/Karta/ManageMaps.cshtml index a11b0c2b..c96f905e 100644 --- a/Views/Karta/ManageMaps.cshtml +++ b/Views/Karta/ManageMaps.cshtml @@ -51,7 +51,7 @@
- +
@@ -62,8 +62,8 @@
@Localizer["ProcessingMap"]
- +
diff --git a/Views/Kirja/Index.cshtml b/Views/Kirja/Index.cshtml index 0350c8e7..8fe248c8 100644 --- a/Views/Kirja/Index.cshtml +++ b/Views/Kirja/Index.cshtml @@ -219,26 +219,56 @@
@Localizer["MentionedInPages"]
  • - + + @Localizer["ReferencedIn"]
@if(User.IsInRole(RoleNames.Aika)) { -
@Localizer["Quests"]
-
    +
    @Localizer["Quests"]
    +
      +
    • - + + @Localizer["OnPage"]
    • + + +
    • + + @Localizer["ReferencedIn"] +
    • +
    } @if(User.IsInRole(RoleNames.Kortisto)) { -
    @Localizer["Npcs"]
    -
      +
      @Localizer["Npcs"]
      +
        + +
      • + + @Localizer["OnPage"] +
      • + + +
      • + + @Localizer["ReferencedIn"] +
      • + +
      + } + + @if(User.IsInRole(RoleNames.Kortisto) && User.IsInRole(RoleNames.Tale)) + { +
      @Localizer["Dialogs"]
      +
      • - + + @Localizer["ReferencedIn"]
      } @@ -248,18 +278,28 @@
      @Localizer["Items"]
      • - + + @Localizer["OnPage"]
      } @if(User.IsInRole(RoleNames.Evne)) { -
      @Localizer["Skills"]
      -
        +
        @Localizer["Skills"]
        +
          +
        • - + + @Localizer["OnPage"]
        • + + +
        • + + @Localizer["ReferencedIn"] +
        • +
        } @@ -268,8 +308,21 @@
        @Localizer["Maps"]
        • - - () + + () + + @Localizer["ReferencedIn"] +
        • +
        + } + + @if(User.IsInRole(RoleNames.ExportObjects)) + { +
        @Localizer["ExportSnippets"]
        +
          +
        • + + @Localizer["ReferencedIn"]
        } @@ -424,6 +477,19 @@ } + @if(User.IsInRole(RoleNames.Tale)) + { + + GoNorth.Kirja.Page.hasTaleRights = true; + + } + else + { + + GoNorth.Kirja.Page.hasTaleRights = false; + + } + @if(User.IsInRole(RoleNames.Styr)) { @@ -463,6 +529,19 @@ } + @if(User.IsInRole(RoleNames.ExportObjects)) + { + + GoNorth.Kirja.Page.hasExportObjectsRights = true; + + } + else + { + + GoNorth.Kirja.Page.hasExportObjectsRights = false; + + } + jQuery(document).ready(function() { ko.applyBindings(new GoNorth.Kirja.Page.ViewModel(), jQuery("#gn-kirjaPageContainer")[0]); }); diff --git a/Views/Shared/ChooseObjectDialog.cshtml b/Views/Shared/ChooseObjectDialog.cshtml index 7156536e..663a8253 100644 --- a/Views/Shared/ChooseObjectDialog.cshtml +++ b/Views/Shared/ChooseObjectDialog.cshtml @@ -6,7 +6,16 @@ window.GoNorth = window.GoNorth || {}; window.GoNorth.ChooseObjectDialog = window.GoNorth.ChooseObjectDialog || {}; window.GoNorth.ChooseObjectDialog.Localization = { - TimeFormat: "@Localizer["TimeFormat"]" + TimeFormat: "@Localizer["TimeFormat"]", + + ObjectTypeNpc: "@Localizer["ObjectTypeNpc"]", + ObjectTypeItem: "@Localizer["ObjectTypeItem"]", + ObjectTypeSkill: "@Localizer["ObjectTypeSkill"]", + ObjectTypeQuest: "@Localizer["ObjectTypeQuest"]", + ObjectTypeWikiPage: "@Localizer["ObjectTypeWikiPage"]", + ObjectTypeChapterDetail: "@Localizer["ObjectTypeChapterDetail"]", + ObjectTypeDailyRoutine: "@Localizer["ObjectTypeDailyRoutine"]", + ObjectTypeMarker: "@Localizer["ObjectTypeMarker"]" } @@ -26,6 +35,12 @@ @Localizer["Error"] @Localizer["ErrorOccured"]
+ +
diff --git a/Views/Shared/NodeScriptEditor.cshtml b/Views/Shared/NodeScriptEditor.cshtml index 55f6c6c8..3ccd8c2f 100644 --- a/Views/Shared/NodeScriptEditor.cshtml +++ b/Views/Shared/NodeScriptEditor.cshtml @@ -29,6 +29,11 @@
@Localizer["ActionNode"]
+
+
+
@Localizer["ReferenceNode"]
+
+
@@ -74,6 +79,7 @@ window.GoNorth.ScriptDialog = window.GoNorth.ScriptDialog || {}; window.GoNorth.ScriptDialog.Localization = window.GoNorth.ScriptDialog.Localization || {}; window.GoNorth.ScriptDialog.Localization.NodeScripts = { + ChooseGeneralObject: "@Localizer["ChooseGeneralObject"]", ChooseQuest: "@Localizer["ChooseQuest"]", ChooseNpc: "@Localizer["ChooseNpc"]", ChooseSkill: "@Localizer["ChooseSkill"]", diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 89484d5a..f72e07bd 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -162,11 +162,11 @@ crossorigin="anonymous" integrity="sha384-PA7LgTHoYGwvEy2evWvC3sNOQlmK/vfk//sStiSk3QK3fUDO8oN3VKvHgSPyVKqx"> - diff --git a/Views/Shared/_ValidationScriptsPartial.cshtml b/Views/Shared/_ValidationScriptsPartial.cshtml index f354b9a6..b910874b 100644 --- a/Views/Shared/_ValidationScriptsPartial.cshtml +++ b/Views/Shared/_ValidationScriptsPartial.cshtml @@ -8,11 +8,11 @@ -