From 40aeb7d23e7a8b0ff7159cc5e2ae40511370110e Mon Sep 17 00:00:00 2001 From: MiraGeowerktstatt Date: Tue, 13 Sep 2022 16:16:27 +0200 Subject: [PATCH 1/2] Enable search for title --- src/ClientApp/src/components/Detail.js | 7 +++++ src/ClientApp/src/components/Results.js | 7 +++++ src/ClientApp/src/translations/de/common.json | 3 +- src/ClientApp/src/translations/fr/common.json | 3 +- src/ClientApp/src/translations/it/common.json | 3 +- src/Controllers/SearchController.cs | 3 ++ src/Crawler/RepositoryCrawler.cs | 29 ++++++++++--------- src/Crawler/XmlModels/IliModelsModel.cs | 2 ++ src/Models/Model.cs | 2 ++ tests/ModelControllerTest.cs | 2 ++ tests/RepoBrowserContextExtensions.cs | 1 + 11 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/ClientApp/src/components/Detail.js b/src/ClientApp/src/components/Detail.js index c096b1a..1055f6e 100644 --- a/src/ClientApp/src/components/Detail.js +++ b/src/ClientApp/src/components/Detail.js @@ -13,6 +13,7 @@ import LinkIcon from "@mui/icons-material/Link"; import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; import AutoStoriesIcon from "@mui/icons-material/AutoStories"; +import TitleIcon from "@mui/icons-material/Title"; import { SchemaLanguages } from "./SchemaLanguages"; import { useTranslation } from "react-i18next"; import { getAllModels } from "./Utils"; @@ -119,6 +120,12 @@ export function Detail() { {model.tags && model.tags.map((tag) => )} + {!!model.title && ( + + + {t("title")}: {model.title} + + )} {t("schema-language")}: {SchemaLanguages[model.schemaLanguage]} diff --git a/src/ClientApp/src/components/Results.js b/src/ClientApp/src/components/Results.js index 4916653..21b42ca 100644 --- a/src/ClientApp/src/components/Results.js +++ b/src/ClientApp/src/components/Results.js @@ -8,6 +8,7 @@ import InfoIcon from "@mui/icons-material/Info"; import RestoreIcon from "@mui/icons-material/Restore"; import FilterAltIcon from "@mui/icons-material/FilterAlt"; import FlagIcon from "@mui/icons-material/Flag"; +import TitleIcon from "@mui/icons-material/Title"; import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import HubIcon from "@mui/icons-material/Hub"; import { useTranslation } from "react-i18next"; @@ -94,6 +95,12 @@ export function Results(props) { flexWrap="wrap" sx={{ color: "text.secondary" }} > + {!!model.title && ( + + + {t("title")}: {model.title} + + )} {t("schema-language")}: {SchemaLanguages[model.schemaLanguage]} diff --git a/src/ClientApp/src/translations/de/common.json b/src/ClientApp/src/translations/de/common.json index f4dc381..eeb5cc5 100644 --- a/src/ClientApp/src/translations/de/common.json +++ b/src/ClientApp/src/translations/de/common.json @@ -43,5 +43,6 @@ "hide-results-for-depends-on-models": "Resultate die sich auf referenzierte Modelle beziehen ausblenden", "catalogue-files": "Zugehörige Katalogdateien", "impressum": "Impressum", - "open-impressum": "Impressum öffnen" + "open-impressum": "Impressum öffnen", + "title": "Titel" } diff --git a/src/ClientApp/src/translations/fr/common.json b/src/ClientApp/src/translations/fr/common.json index d29fa1a..cab14cd 100644 --- a/src/ClientApp/src/translations/fr/common.json +++ b/src/ClientApp/src/translations/fr/common.json @@ -43,5 +43,6 @@ "hide-results-for-depends-on-models": "Masquer les résultats liés aux modèles référencés", "catalogue-files": "Fichiers de catalogue associés", "impressum": "Empreinte", - "open-impressum": "Ouvrir l'empreinte" + "open-impressum": "Ouvrir l'empreinte", + "title": "Titre" } diff --git a/src/ClientApp/src/translations/it/common.json b/src/ClientApp/src/translations/it/common.json index c6b953e..6a56968 100644 --- a/src/ClientApp/src/translations/it/common.json +++ b/src/ClientApp/src/translations/it/common.json @@ -43,5 +43,6 @@ "hide-results-for-depends-on-models": "Nascondi i risultati relativi ai modelli di riferimento", "catalogue-files": "File di catalogo correlati", "impressum": "Impressum", - "open-impressum": "Aprire impressum" + "open-impressum": "Aprire impressum", + "title": "Titolo" } diff --git a/src/Controllers/SearchController.cs b/src/Controllers/SearchController.cs index 6802651..0d6423e 100644 --- a/src/Controllers/SearchController.cs +++ b/src/Controllers/SearchController.cs @@ -172,6 +172,7 @@ private Task> SearchRepositories(string query, st if (dependsOnModels != null && dependsOnModels.All(string.IsNullOrEmpty)) dependsOnModels = null; if (issuers != null && issuers.All(string.IsNullOrEmpty)) issuers = null; +#pragma warning disable CS8604 // Possible null reference argument. return context.Repositories .Include(r => r.SubsidiarySites) .Include(r => r.ParentSites) @@ -184,11 +185,13 @@ private Task> SearchRepositories(string query, st EF.Functions.ILike(m.Name, searchPattern, @"\") || EF.Functions.ILike(m.Version, searchPattern, @"\") || EF.Functions.ILike(m.File, searchPattern, @"\") + || EF.Functions.ILike(m.Title, searchPattern, @"\") || modelsNamesFoundFromCatalogs.Contains(m.Name) || m.Tags.Contains(query) || m.DependsOnModel.Contains(query))) .AsNoTracking() .ToDictionaryAsync(r => r.HostNameId); +#pragma warning restore CS8604 // Possible null reference argument. } /// diff --git a/src/Crawler/RepositoryCrawler.cs b/src/Crawler/RepositoryCrawler.cs index 4573441..edee530 100644 --- a/src/Crawler/RepositoryCrawler.cs +++ b/src/Crawler/RepositoryCrawler.cs @@ -147,20 +147,21 @@ private async Task> CrawlIlimodels(Uri repositoryUri) { var models = RepositoryFilesDeserializer.ParseIliModels(ilimodelsStream) .Select(model => new Model - { - Name = model.Name, - SchemaLanguage = model.SchemaLanguage, - File = model.File, - Version = model.Version, - PublishingDate = model.publishingDate.ToUniversalTime(), - DependsOnModel = model.dependsOnModel.Where(s => !string.IsNullOrEmpty(s?.value)).Select(m => m.value!).ToList(), - ShortDescription = model.shortDescription, - Issuer = model.Issuer, - TechnicalContact = model.technicalContact, - FurtherInformation = model.furtherInformation, - MD5 = model.md5, - Tags = model.Tags?.Split(',').Distinct().ToList() ?? new List(), - }) + { + Name = model.Name, + SchemaLanguage = model.SchemaLanguage, + File = model.File, + Version = model.Version, + PublishingDate = model.publishingDate.ToUniversalTime(), + DependsOnModel = model.dependsOnModel.Where(s => !string.IsNullOrEmpty(s?.value)).Select(m => m.value!).ToList(), + ShortDescription = model.shortDescription, + Title = model.Title, + Issuer = model.Issuer, + TechnicalContact = model.technicalContact, + FurtherInformation = model.furtherInformation, + MD5 = model.md5, + Tags = model.Tags?.Split(',').Distinct().ToList() ?? new List(), + }) .ToHashSet(); foreach (var model in models) diff --git a/src/Crawler/XmlModels/IliModelsModel.cs b/src/Crawler/XmlModels/IliModelsModel.cs index c3321e5..1908f62 100644 --- a/src/Crawler/XmlModels/IliModelsModel.cs +++ b/src/Crawler/XmlModels/IliModelsModel.cs @@ -43,6 +43,8 @@ public class ModelMetadata [XmlElement(DataType = "date")] public DateTime publishingDate { get; set; } + public string? Title { get; set; } + [XmlArray("dependsOnModel")] [XmlArrayItem("IliRepository09.ModelName_", typeof(DependsOnModel09))] [XmlArrayItem("IliRepository20.ModelName_", typeof(DependsOnModel20))] diff --git a/src/Models/Model.cs b/src/Models/Model.cs index e9a45ec..3ae9506 100644 --- a/src/Models/Model.cs +++ b/src/Models/Model.cs @@ -19,6 +19,8 @@ public class Model public DateTime? PublishingDate { get; set; } + public string? Title { get; set; } + public List DependsOnModel { get; set; } public List Tags { get; set; } diff --git a/tests/ModelControllerTest.cs b/tests/ModelControllerTest.cs index 63ac5fd..90f9c46 100644 --- a/tests/ModelControllerTest.cs +++ b/tests/ModelControllerTest.cs @@ -34,6 +34,7 @@ public void ModelDetails() Assert.AreEqual("Cotton_Officer", model.Name); Assert.AreEqual("544a7e2f91f51172f1d471dc3b3ce10c", model.MD5); Assert.AreEqual("home/scalable_assistant_georgia.json5", model.File); + Assert.AreEqual("Papua New Guinea interactive Tasty Sleek navigate", model.Title); Assert.IsNotNull(model.ModelRepository, "ModelRepository has to be included."); Assert.AreEqual("white", model.ModelRepository.Name); } @@ -47,6 +48,7 @@ public void ModelDetailsWithCatalogs() Assert.AreEqual("Borders_Home Loan Account", model.Name); Assert.AreEqual("2abd30d77a016df846307c50a621139b", model.MD5); Assert.AreEqual("usr/libexec/agp.bz2", model.File); + Assert.AreEqual("copy orange IB Regional Refined", model.Title); Assert.IsNotNull(model.ModelRepository, "ModelRepository has to be included."); Assert.AreEqual("g7yn9ioz927y65aoioyjvb4v3b84", model.CatalogueFiles[0]); } diff --git a/tests/RepoBrowserContextExtensions.cs b/tests/RepoBrowserContextExtensions.cs index 40140f0..11f5db4 100644 --- a/tests/RepoBrowserContextExtensions.cs +++ b/tests/RepoBrowserContextExtensions.cs @@ -67,6 +67,7 @@ public static void SeedData(this RepoBrowserContext context) .RuleFor(m => m.FurtherInformation, f => f.Lorem.Sentence()) .RuleFor(m => m.ModelRepository, f => f.PickRandom(repositories)) .RuleFor(m => m.IsDependOnModelResult, _ => false) + .RuleFor(m => m.Title, f => f.Random.Words(5)) .RuleFor(m => m.CatalogueFiles, _ => new List()); Model SeededModel(int seed) => fakeModels.UseSeed(seed).Generate(); var models = modelRange.Select(SeededModel); From d5a612d18f88450cd4cb0ba8a9dca220d34c2bc2 Mon Sep 17 00:00:00 2001 From: MiraGeowerktstatt Date: Tue, 13 Sep 2022 16:41:15 +0200 Subject: [PATCH 2/2] Fix tests --- tests/SearchControllerTest.cs | 48 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tests/SearchControllerTest.cs b/tests/SearchControllerTest.cs index 199704b..5d2931c 100644 --- a/tests/SearchControllerTest.cs +++ b/tests/SearchControllerTest.cs @@ -64,7 +64,7 @@ public async Task SearchName() Assert.IsNotNull(searchResult); searchResult .GetAllModels() - .AssertCount(2) + .AssertCount(3) .AssertSingleItem(m => m.Id == 22, m => Assert.AreEqual("Kentucky", m.Name)); } @@ -110,17 +110,17 @@ public async Task SearchTag() Assert.IsNotNull(searchResult); searchResult .GetAllModels() - .AssertCount(3) + .AssertCount(4) .AssertSingleItem(m => m.Id == 23, m => m.Tags.AssertContains("Specialist")); // Tags must match exactly searchResult = await controller.Search("pecialist"); Assert.IsNotNull(searchResult); - searchResult.GetAllModels().AssertCount(2); + searchResult.GetAllModels().AssertCount(3); searchResult = await controller.Search("SpecialiST"); Assert.IsNotNull(searchResult); - searchResult.GetAllModels().AssertCount(2); + searchResult.GetAllModels().AssertCount(3); } [TestMethod] @@ -130,15 +130,15 @@ public async Task SearchDependsOnModel() Assert.IsNotNull(searchResult); var models = searchResult.GetAllModels(); models.Where(m => m.IsDependOnModelResult == true).AssertCount(2); - models.Where(m => m.IsDependOnModelResult == false).AssertCount(1); + models.Where(m => m.IsDependOnModelResult == false).AssertCount(4); models.AssertSingleItem(m => m.Id == 86, m => m.DependsOnModel.AssertContains("Home Loan Account")); // DependsOnModel must match exactly searchResult = await controller.Search("home loan account"); - searchResult!.GetAllModels().AssertCount(1); + searchResult!.GetAllModels().AssertCount(4); searchResult = await controller.Search("HOme Loan Account"); - searchResult!.GetAllModels().AssertCount(1); + searchResult!.GetAllModels().AssertCount(4); } [TestMethod] @@ -158,7 +158,7 @@ public async Task SearchWithWildcardsDisabled() { var searchResult = await controller.Search("Kentucky"); Assert.IsNotNull(searchResult); - searchResult.GetAllModels().AssertCount(2); + searchResult.GetAllModels().AssertCount(3); searchResult = await controller.Search("Kent_cky"); Assert.AreEqual(null, searchResult); @@ -188,20 +188,20 @@ public async Task SearchRepositoryTreeResult() var searchResult = await controller.Search("ga"); Assert.IsNotNull(searchResult); - searchResult.GetAllModels().AssertCount(11); + searchResult.GetAllModels().AssertCount(21); Assert.AreEqual("delores.com", searchResult.HostNameId); Assert.AreEqual(1, searchResult.Models.Count); searchResult.SubsidiarySites .AssertCount(5) - .AssertSingleItem("eldora.net", 1) - .AssertSingleItem("geovany.org", 1) + .AssertSingleItem("eldora.net", 2) + .AssertSingleItem("geovany.org", 2) .AssertSingleItem("valentine.net", 0, r => r - .AssertCount(5) + .AssertCount(7) .AssertSingleItem("arvel.name", 1) - .AssertSingleItem("breana.com", 1) - .AssertSingleItem("jaquelin.com", 2) - .AssertSingleItem("lenny.net", 1) + .AssertSingleItem("breana.com", 2) + .AssertSingleItem("jaquelin.com", 3) + .AssertSingleItem("lenny.net", 3) .AssertSingleItem("mack.info", 1)); } @@ -262,20 +262,34 @@ public async Task GetSearchSuggestions() CollectionAssert.AreEquivalent(new[] { "back-end_grey_JBOD", + "transition_vortals", "Iceland Krona_New Israeli Sheqel_matrix_Oklahoma", "Handcrafted Fresh Hat_metrics_invoice", "Handcrafted Rubber Tuna_Sudanese Pound_syndicate", "Iowa_Junctions", "Handcrafted Granite Ball_Associate_haptic_Money Market Account_Beauty", "bandwidth_auxiliary_Incredible", + "violet_Metal_calculating", + "maroon_synthesizing_Awesome", + "index_transmitting_generate_24/7_Run", "Virgin Islands, U.S._withdrawal_CFA Franc BCEAO_THX", "capability_Unbranded Granite Table_Intelligent Cotton Table_static", - "deposit", + "circuit_impactful_Organic", + "SSL_cutting-edge_Global_platforms", + "Interactions_convergence_static", "Via_West Virginia_withdrawal", - "back-end_benchmark_Legacy_Future_Crescent", + "deposit", + "Soft_Health_facilitate_Cotton", "bandwidth_Refined Fresh Shoes", + "back-end_benchmark_Legacy_Future_Crescent", + "North Dakota_bypass_Gorgeous Steel Keyboard", "full-range_Kenyan Shilling_experiences_Money Market Account_Officer", + "connecting_Distributed_Florida_mission-critical_Awesome Wooden Bacon", "Global_Licensed", + "Generic Plastic Cheese_Infrastructure_Intelligent_quantify", + "IB_Health_sky blue", + "Small_withdrawal_transition_Response_Response", + "initiatives_Customer_neural_Bedfordshire_integrate", }, suggestions.ToArray());