diff --git a/docs/Dependencies.png b/docs/Dependencies.png index e4504f9..05ca9cd 100644 Binary files a/docs/Dependencies.png and b/docs/Dependencies.png differ diff --git a/src/TUI/Dashboards/DependencyDashboard.cs b/src/TUI/Dashboards/DependencyDashboard.cs index a294960..d3ebd9e 100644 --- a/src/TUI/Dashboards/DependencyDashboard.cs +++ b/src/TUI/Dashboards/DependencyDashboard.cs @@ -1,9 +1,11 @@ -using System.Drawing; +using System.Diagnostics; +using System.Net; using System.Text; using System.Text.Json; using Pastel; using TUI.Controls; using TUI.Domain; +using TUI.Settings; using TUI.UserInterface; @@ -11,12 +13,10 @@ namespace TUI.Dashboards; public class DependencyDashboard : IControl { - private int _selectedRowNumber = 0; - - private const int TitleWidth = 35; + private const int TitleWidth = 25; private const int ColumnWidth = 10; - private Table _table = new(); + private readonly Table _table = new(); public void Render(Project project, Position position) { @@ -39,68 +39,87 @@ public class DependencyDashboard : IControl var actualDependencies = GetDependencies(project.Sources[rowId], project.Dependencies); _table.RenderRow(rowId + 1, rows[rowId] + actualDependencies); } - - // Panel.RenderRows(project.Sources.ToArray(), _selectedRowNumber); } - private string GetDependencies(Source source, IEnumerable conventionDependencies) + private static string GetDependencies(SourceDto sourceDto, IEnumerable conventionDependencies) { try { - var package = DownloadPackage(source); + var package = DownloadPackage(sourceDto); return string.Join("", conventionDependencies .Select(package.Dependencies.GetVersion) - .Select(GetCurrentVersion)); + .Select(RenderCurrentVersion)); } - catch + catch (HttpRequestException exception) { + switch (exception.StatusCode) + { + case HttpStatusCode.BadRequest: + return " Request have errors.".Pastel(Palette.ErrorColor); + case HttpStatusCode.Forbidden: + return " Not enough rights.".Pastel(Palette.ErrorColor); + case HttpStatusCode.NotFound: + return " Repository not found.".Pastel(Palette.ErrorColor); + } + + throw; + } + catch (Exception exception) + { + Debugger.Break(); return "󰋔 We tried to send a request but couldn't. Check your configuration.".Pastel(Palette.ErrorColor); } } private readonly static Dictionary Packages = new(); - private static Package DownloadPackage(Source source) + private static Package DownloadPackage(SourceDto sourceDto) { - if (Packages.TryGetValue(source.Repo, out var downloadPackage)) + if (Packages.TryGetValue(sourceDto.Repo, out var downloadPackage)) { return downloadPackage; } using HttpClient client = new(); - var endpoint = source.Tags.Have("gitlab") ? GetGitlabEndpoint(source) : source.Repo; + var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); var package = JsonSerializer.Deserialize(json); - Packages.Add(source.Repo, package); + Packages.Add(sourceDto.Repo, package); return package; } - private static string GetGitlabEndpoint(Source source) + private static string GetGitlabEndpoint(SourceDto sourceDto) { var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); - return $"{source.Repo}/api/v4/projects/{source.ProjectId}/repository/files/package.json/raw?" + + return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" + $"private_token={token}&ref=master"; } - - private static string GetConventionVersion(Dependency dependency) + + private static string GetConventionVersion(DependencyDto dependencyDto) { - return dependency.Icon.Pastel(dependency.Color) + dependency.Version.Primary(); + return dependencyDto.Icon.Pastel(dependencyDto.Color) + dependencyDto.Version.Primary(); } - private static string GetCurrentVersion(string version) + private static string RenderCurrentVersion(string version) { - return ' '.Repeat(ColumnWidth - version.Width()) + version; + var versionWidth = version.Width(); + if (versionWidth == 0) + { + return ' '.Repeat(ColumnWidth - 1) + "".Hint(); + } + + return ' '.Repeat(ColumnWidth - versionWidth) + version; } - private static string GetTitle(Source source) + private static string GetTitle(SourceDto sourceDto) { var rowText = new StringBuilder(); RenderPadding(rowText); - RenderTags(rowText, source); - rowText.Append(source.Name); + RenderTags(rowText, sourceDto); + rowText.Append(sourceDto.Name); RenderPadding(rowText); var text = rowText.ToString(); return $"{text}{' '.Repeat(TitleWidth - text.Width())}"; @@ -111,32 +130,32 @@ public class DependencyDashboard : IControl rowText.Append(new string(' ', Theme.Padding)); } - private static void RenderTags(StringBuilder rowText, Source source) + private static void RenderTags(StringBuilder rowText, SourceDto sourceDto) { - rowText.Append(GetGitApplication(source)); - rowText.Append(source.Tags.Have("public") + rowText.Append(GetGitApplication(sourceDto)); + rowText.Append(sourceDto.Tags.Have("public") ? GetIcon("󰞉", "00FFFF") : GetIcon("󰕑", "AFE1AF")); - rowText.Append(GetIcon("󰚩", "4285F4", source.Tags.Have("seo"))); - rowText.Append(GetIcon("", "FFD700", source.Tags.Have("auth"))); - rowText.Append(GetApplicationType(source)); + rowText.Append(GetIcon("󰚩", "4285F4", sourceDto.Tags.Have("seo"))); + rowText.Append(GetIcon("", "FFD700", sourceDto.Tags.Have("auth"))); + rowText.Append(GetApplicationType(sourceDto)); } - private static string GetApplicationType(Source source) + private static string GetApplicationType(SourceDto sourceDto) { - if (source.Tags.Have("site")) + if (sourceDto.Tags.Have("site")) return GetIcon("", "BF40BF"); - if (source.Tags.Have("api")) + if (sourceDto.Tags.Have("api")) return GetIcon("", "7F52FF"); - if (source.Tags.Have("package")) + if (sourceDto.Tags.Have("package")) return GetIcon("", "CB0000"); - if (source.Tags.Have("image")) + if (sourceDto.Tags.Have("image")) return GetIcon("󰡨", "086DD7"); return GetIcon("", "CB0000"); } - private static string GetGitApplication(Source source) => source.Repo switch + private static string GetGitApplication(SourceDto sourceDto) => sourceDto.Repo switch { { } url when url.Contains("gitlab") => GetIcon("", "E24329"), { } url when url.Contains("github") => GetIcon("", "ADBAC7"), diff --git a/src/TUI/Domain/Dependency.cs b/src/TUI/Domain/Dependency.cs deleted file mode 100644 index e1e3961..0000000 --- a/src/TUI/Domain/Dependency.cs +++ /dev/null @@ -1,26 +0,0 @@ -using YamlDotNet.Serialization; - - -namespace TUI.Domain; - -[YamlSerializable] -public class Dependency -{ - private string _icon; - - [YamlMember] - public string Name { get; set; } - - [YamlMember] - public string Icon - { - get => $" {_icon} "; - set => _icon = value; - } - - [YamlMember] - public string Version { get; set; } - - [YamlMember] - public string Color { get; set; } -} \ No newline at end of file diff --git a/src/TUI/Domain/Package.cs b/src/TUI/Domain/Package.cs index 88218f9..edd87c1 100644 --- a/src/TUI/Domain/Package.cs +++ b/src/TUI/Domain/Package.cs @@ -1,3 +1,4 @@ +using System.Text.Json.Nodes; using System.Text.Json.Serialization; @@ -6,21 +7,5 @@ namespace TUI.Domain; public class Package { [JsonPropertyName("dependencies")] - public Dependencies Dependencies { get; set; } -} - -public class Dependencies -{ - [JsonPropertyName("react")] - public string React { get; set; } - - [JsonPropertyName("typesciprt")] - public string TypeScript { get; set; } - - public string GetVersion(Dependency dependency) => dependency.Name.ToLower() switch - { - "react" => React, - "typescipt" => TypeScript, - _ => "-" - }; + public JsonObject Dependencies { get; set; } } \ No newline at end of file diff --git a/src/TUI/Domain/Project.cs b/src/TUI/Domain/Project.cs index 12a06c1..6e068fb 100644 --- a/src/TUI/Domain/Project.cs +++ b/src/TUI/Domain/Project.cs @@ -1,4 +1,5 @@ using System.Runtime.CompilerServices; +using TUI.Settings; using YamlDotNet.Serialization; @@ -14,8 +15,8 @@ public class Project public string Name { get; set; } [YamlMember] - public Dependency[] Dependencies { get; set; } + public DependencyDto[] Dependencies { get; set; } [YamlMember] - public IList Sources { get; set; } + public IList Sources { get; set; } } \ No newline at end of file diff --git a/src/TUI/Extensions.cs b/src/TUI/Extensions.cs index a24d1c7..ec15125 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI/Extensions.cs @@ -1,4 +1,8 @@ +using System.Text.Json.Nodes; using System.Text.RegularExpressions; +using TUI.Domain; +using TUI.Settings; +using TUI.UserInterface; namespace TUI; @@ -17,8 +21,53 @@ public static class Extensions public static int Width(this string text) { + if (string.IsNullOrEmpty(text)) + { + return 0; + } + var clearText = Regex.Replace(text, @"\S\[(\d{0,3}[;m][_]?){0,5}", ""); var stringInfo = new System.Globalization.StringInfo(clearText); return stringInfo.LengthInTextElements; } + + public static string GetVersion(this JsonObject dependencies, DependencyDto dependencyDto) + { + dependencies.TryGetPropertyValue(dependencyDto.Name.ToLower(), out var version); + var currentVersion = version?.GetValue().ToVersion(); + if (currentVersion == null) + { + return "".Hint(); + } + + var conventionVersion = dependencyDto.Version.ToVersion(); + + if (currentVersion > conventionVersion) + { + return currentVersion.ToString().Info(); + } + + if (currentVersion < conventionVersion) + { + if (currentVersion.Major == conventionVersion.Major) + { + return currentVersion.ToString().Warning(); + } + + return currentVersion.ToString().Error(); + } + + return currentVersion.ToString().Primary(); + } + + private static Version? ToVersion(this string textVersion) + { + var version = textVersion.Replace("^", "").Replace("~", "").Split("."); + if (version.Length != 3) + return null; + var major = Convert.ToInt32(version[0]); + var minor = Convert.ToInt32(version[1]); + var patch = Convert.ToInt32(version[2].Split('-')[0]); + return new Version(major, minor, patch); + } } \ No newline at end of file diff --git a/src/TUI/Settings/DependencyDto.cs b/src/TUI/Settings/DependencyDto.cs new file mode 100644 index 0000000..53d770c --- /dev/null +++ b/src/TUI/Settings/DependencyDto.cs @@ -0,0 +1,32 @@ +using System.Runtime.Serialization; +using YamlDotNet.Serialization; + + +namespace TUI.Settings; + +[DataContract] +[YamlSerializable] +public class DependencyDto +{ + private string _icon; + + [DataMember] + [YamlMember] + public string? Name { get; set; } + + [DataMember] + [YamlMember] + public string? Icon + { + get => $" {_icon} "; + set => _icon = value; + } + + [DataMember] + [YamlMember] + public string? Version { get; set; } + + [DataMember] + [YamlMember] + public string? Color { get; set; } +} \ No newline at end of file diff --git a/src/TUI/Domain/Source.cs b/src/TUI/Settings/SourceDto.cs similarity index 76% rename from src/TUI/Domain/Source.cs rename to src/TUI/Settings/SourceDto.cs index 351a83a..100db53 100644 --- a/src/TUI/Domain/Source.cs +++ b/src/TUI/Settings/SourceDto.cs @@ -1,10 +1,10 @@ using YamlDotNet.Serialization; -namespace TUI.Domain; +namespace TUI.Settings; [YamlSerializable] -public class Source +public class SourceDto { [YamlMember] public string[] Tags { get; set; } @@ -13,7 +13,6 @@ public class Source public string Name { get; set; } [YamlMember] - // [YamlMember(Alias = "project_id")] public int ProjectId { get; set; } = 0; [YamlMember] diff --git a/src/TUI/UserInterface/Header.cs b/src/TUI/UserInterface/Header.cs index b547e97..8023102 100644 --- a/src/TUI/UserInterface/Header.cs +++ b/src/TUI/UserInterface/Header.cs @@ -17,9 +17,32 @@ public class Header : IControl Console.WriteLine(new string(' ', Console.WindowWidth - LogoWidth)); } + RenderHints(); + RenderHotkeys(); RenderLogo(); } + private void RenderHotkeys() + { + Console.SetCursorPosition(30, Theme.Padding); + Console.Write("󰬌 toggle header".Hint()); + Console.SetCursorPosition(30, Theme.Padding + 1); + Console.Write("󰬘 quit".Hint()); + Console.SetCursorPosition(30, Theme.Padding + 2); + Console.Write(" select previous".Hint()); + Console.SetCursorPosition(30, Theme.Padding + 3); + Console.Write(" select next".Hint()); + } + + private void RenderHints() + { + Console.SetCursorPosition(0, Theme.Padding); + Console.WriteLine(' '.Repeat(Theme.Padding) + "󰎔 Too new: ".Hint() + "1.20.0".Info()); + Console.WriteLine(' '.Repeat(Theme.Padding) + " So good: ".Hint() + "1.20.0".Primary()); + Console.WriteLine(' '.Repeat(Theme.Padding) + " Be nice: ".Hint() + "1.20.0".Warning()); + Console.WriteLine(' '.Repeat(Theme.Padding) + "󰬟 Too old: ".Hint() + "1.20.0".Error()); + } + private void RenderLogo() { Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 0); diff --git a/src/TUI/UserInterface/Palette.cs b/src/TUI/UserInterface/Palette.cs index e2c868b..4ec5e56 100644 --- a/src/TUI/UserInterface/Palette.cs +++ b/src/TUI/UserInterface/Palette.cs @@ -9,8 +9,14 @@ public static class Palette public const string HoverColor = "292928"; public const string PrimaryColor = "84BA64"; public const string HintColor = "71797E"; - public const string ErrorColor = "D3B3AC"; + public const string ErrorColor = "CA3433"; + public const string WarningColor = "EC9706"; + public const string InfoColor = "0E4D92"; public static string Primary(this string currentText) => currentText.Pastel(PrimaryColor); public static string Hint(this string currentText) => currentText.Pastel(HintColor); + public static string Warning(this string currentText) => currentText.Pastel(WarningColor); + public static string Error(this string currentText) => currentText.Pastel(ErrorColor); + public static string Info(this string currentText) => currentText.Pastel(InfoColor); + } \ No newline at end of file diff --git a/src/TUI/UserInterface/Panel.cs b/src/TUI/UserInterface/Panel.cs index d1813ac..5b5be1a 100644 --- a/src/TUI/UserInterface/Panel.cs +++ b/src/TUI/UserInterface/Panel.cs @@ -2,6 +2,7 @@ using System.Text; using System.Text.Json; using Pastel; using TUI.Domain; +using TUI.Settings; namespace TUI.UserInterface; @@ -14,7 +15,7 @@ public static class Panel private const int TagCount = 5; private const int TagWidth = 2; - public static void RenderRows(Source[] sources, int selectedRowNumber) + public static void RenderRows(SourceDto[] sources, int selectedRowNumber) { for (var index = 0; index < sources.Length; index++) {