Skip to content

Commit 5a8c672

Browse files
committed
feat: add logic to collapse supporting member tags
1 parent bb5c7d2 commit 5a8c672

3 files changed

Lines changed: 115 additions & 6 deletions

File tree

SgfDevs.sln

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 17
44
VisualStudioVersion = 17.8.34309.116
@@ -16,16 +16,42 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1616
Dockerfile = Dockerfile
1717
EndProjectSection
1818
EndProject
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SgfDevs.Tests", "SgfDevs.Tests\SgfDevs.Tests.csproj", "{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}"
20+
EndProject
1921
Global
2022
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2123
Debug|Any CPU = Debug|Any CPU
24+
Debug|x64 = Debug|x64
25+
Debug|x86 = Debug|x86
2226
Release|Any CPU = Release|Any CPU
27+
Release|x64 = Release|x64
28+
Release|x86 = Release|x86
2329
EndGlobalSection
2430
GlobalSection(ProjectConfigurationPlatforms) = postSolution
2531
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
2632
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|Any CPU.Build.0 = Debug|Any CPU
33+
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|x64.ActiveCfg = Debug|Any CPU
34+
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|x64.Build.0 = Debug|Any CPU
35+
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|x86.ActiveCfg = Debug|Any CPU
36+
{D6F118F7-657E-4262-8D78-F2329883480B}.Debug|x86.Build.0 = Debug|Any CPU
2737
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|Any CPU.ActiveCfg = Release|Any CPU
2838
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|Any CPU.Build.0 = Release|Any CPU
39+
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|x64.ActiveCfg = Release|Any CPU
40+
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|x64.Build.0 = Release|Any CPU
41+
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|x86.ActiveCfg = Release|Any CPU
42+
{D6F118F7-657E-4262-8D78-F2329883480B}.Release|x86.Build.0 = Release|Any CPU
43+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|x64.ActiveCfg = Debug|Any CPU
46+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|x64.Build.0 = Debug|Any CPU
47+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|x86.ActiveCfg = Debug|Any CPU
48+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Debug|x86.Build.0 = Debug|Any CPU
49+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|Any CPU.ActiveCfg = Release|Any CPU
50+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|x64.ActiveCfg = Release|Any CPU
52+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|x64.Build.0 = Release|Any CPU
53+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|x86.ActiveCfg = Release|Any CPU
54+
{0C5B6447-5DCE-4E13-9EFB-7778084DAD04}.Release|x86.Build.0 = Release|Any CPU
2955
EndGlobalSection
3056
GlobalSection(SolutionProperties) = preSolution
3157
HideSolutionNode = FALSE
Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Text.RegularExpressions;
45
using Umbraco.Cms.Web.Common.PublishedModels;
56

67
namespace SgfDevs.Dev;
78

89
public class MemberTagDisplayService
910
{
11+
private static readonly Regex SupportingMemberRegex = new("^(\\d{4})\\s+Supporting Member$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
12+
1013
public IReadOnlyList<string> GetDisplayMemberTags(Member member)
1114
{
1215
var tags = member?.MemberTags?.OfType<Tag>() ?? [];
@@ -15,15 +18,92 @@ public IReadOnlyList<string> GetDisplayMemberTags(Member member)
1518

1619
public IReadOnlyList<string> GetDisplayMemberTags(IEnumerable<Tag> tags)
1720
{
18-
return (tags ?? [])
19-
.Select(GetDisplayName)
20-
.Where(tagName => !string.IsNullOrWhiteSpace(tagName))
21-
.Distinct(StringComparer.OrdinalIgnoreCase)
22-
.ToList();
21+
return FormatDisplayMemberTags((tags ?? []).Select(GetDisplayName));
22+
}
23+
24+
internal IReadOnlyList<string> FormatDisplayMemberTags(IEnumerable<string> tagNames)
25+
{
26+
var displayTags = new List<string>();
27+
var supportingYears = new SortedSet<int>();
28+
int? supportingInsertIndex = null;
29+
30+
foreach (var tagName in tagNames ?? [])
31+
{
32+
if (string.IsNullOrWhiteSpace(tagName))
33+
{
34+
continue;
35+
}
36+
37+
var supportingYear = GetSupportingMemberYear(tagName);
38+
if (supportingYear.HasValue)
39+
{
40+
supportingInsertIndex ??= displayTags.Count;
41+
supportingYears.Add(supportingYear.Value);
42+
continue;
43+
}
44+
45+
if (!displayTags.Contains(tagName, StringComparer.OrdinalIgnoreCase))
46+
{
47+
displayTags.Add(tagName);
48+
}
49+
}
50+
51+
if (supportingYears.Count > 0)
52+
{
53+
var combinedSupportingMemberTag = $"{FormatSupportingMemberYears(supportingYears)} Supporting Member";
54+
displayTags.Insert(supportingInsertIndex ?? displayTags.Count, combinedSupportingMemberTag);
55+
}
56+
57+
return displayTags;
2358
}
2459

2560
private static string GetDisplayName(Tag tag)
2661
{
2762
return !string.IsNullOrWhiteSpace(tag?.DisplayName) ? tag.DisplayName : tag?.Name;
2863
}
64+
65+
private static int? GetSupportingMemberYear(string tagName)
66+
{
67+
var match = SupportingMemberRegex.Match(tagName);
68+
return match.Success ? int.Parse(match.Groups[1].Value) : null;
69+
}
70+
71+
private static string FormatSupportingMemberYears(IEnumerable<int> years)
72+
{
73+
var ranges = new List<string>();
74+
int? rangeStart = null;
75+
int? previousYear = null;
76+
77+
foreach (var year in years)
78+
{
79+
if (!rangeStart.HasValue)
80+
{
81+
rangeStart = year;
82+
previousYear = year;
83+
continue;
84+
}
85+
86+
if (year == previousYear + 1)
87+
{
88+
previousYear = year;
89+
continue;
90+
}
91+
92+
ranges.Add(FormatRange(rangeStart.Value, previousYear!.Value));
93+
rangeStart = year;
94+
previousYear = year;
95+
}
96+
97+
if (rangeStart.HasValue && previousYear.HasValue)
98+
{
99+
ranges.Add(FormatRange(rangeStart.Value, previousYear.Value));
100+
}
101+
102+
return string.Join(", ", ranges);
103+
}
104+
105+
private static string FormatRange(int startYear, int endYear)
106+
{
107+
return startYear == endYear ? startYear.ToString() : $"{startYear}-{endYear}";
108+
}
29109
}

SgfDevs/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("SgfDevs.Tests")]

0 commit comments

Comments
 (0)