Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include tags to plugins #11

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions PluginBuilder/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public async Task<IActionResult> Register(RegisterViewModel model, string? retur
[HttpGet("/plugins/create")]
public IActionResult CreatePlugin()
{
return View();
return View(new CreatePluginViewModel());
}

[HttpPost("/plugins/create")]
Expand All @@ -163,14 +163,25 @@ public async Task<IActionResult> CreatePlugin(CreatePluginViewModel model)
ModelState.AddModelError(nameof(model.PluginSlug), "Invalid plug slug, it should only contains latin letter in lowercase or numbers or '-' (example: my-awesome-plugin)");
return View(model);
}

if (!model.Tags.Any())
{
ModelState.AddModelError(nameof(model.Tags), "Please select minimum of one tag to create a plugin");
return View(model);
}
await using var conn = await ConnectionFactory.Open();
if (!await conn.NewPlugin(pluginSlug))
{
ModelState.AddModelError(nameof(model.PluginSlug), "This slug already exists");
return View(model);
}
await conn.AddUserPlugin(pluginSlug, UserManager.GetUserId(User)!);

var pluginTags = model.Tags.Select(c => new Tag
{
Id = (int)c,
Name = c.ToString()
}).ToList();
await conn.SetSettings(pluginSlug, new PluginSettings { PluginTags = pluginTags });
return RedirectToAction(nameof(PluginController.Dashboard), "Plugin", new { pluginSlug = pluginSlug.ToString() });
}

Expand Down
4 changes: 4 additions & 0 deletions PluginBuilder/Controllers/PluginController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public async Task<IActionResult> Settings(
{
ModelState.AddModelError(nameof(settings.GitRepository), "Git repository should be an absolute URL");
}
if (settings.PluginTags == null || !settings.PluginTags.Any())
{
ModelState.AddModelError(nameof(settings.PluginTags), "Please select minimum of one tag to update the plugin settings");
}
if (!ModelState.IsValid)
return View(settings);
await using var conn = await ConnectionFactory.Open();
Expand Down
10 changes: 8 additions & 2 deletions PluginBuilder/PluginSettings.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#nullable disable
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;

namespace PluginBuilder
{
Expand All @@ -13,7 +12,7 @@ public class PluginSettings
[MaxLength(200)]
[Display(Name = "Git repository")]
public string GitRepository { get; set; }

[MaxLength(200)]
[Display(Name = "Git branch or tag")]
public string GitRef { get; set; }
Expand All @@ -25,5 +24,12 @@ public class PluginSettings
[MaxLength(200)]
[Display(Name = "Dotnet build configuration ")]
public string BuildConfig { get; set; }
public List<Tag> PluginTags { get; set; }
}

public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
}
}
2 changes: 2 additions & 0 deletions PluginBuilder/ViewModels/CreatePluginViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable disable
using System.ComponentModel.DataAnnotations;
using PluginBuilder.Views.Enums;

namespace PluginBuilder.ViewModels
{
Expand All @@ -10,5 +11,6 @@ public class CreatePluginViewModel
[MaxLength(30)]
[MinLength(4)]
public string PluginSlug { get; set; }
public List<PluginTags> Tags { get; set; } = new List<PluginTags>();
}
}
12 changes: 12 additions & 0 deletions PluginBuilder/Views/Enums/PluginTags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace PluginBuilder.Views.Enums
{
public enum PluginTags
{
System,
Payment,
Security,
Analytics,
Scheduling,
Community
}
}
54 changes: 52 additions & 2 deletions PluginBuilder/Views/Home/CreatePlugin.cshtml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
@using PluginBuilder.Views.Enums
@model PluginBuilder.ViewModels.CreatePluginViewModel
@{
Layout = "_Layout";
ViewData["Title"] = "Create a new plugin";
Layout = "_Layout";
ViewData["Title"] = "Create a new plugin";
}

<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
Expand All @@ -14,9 +15,58 @@
<input asp-for="PluginSlug" class="form-control" placeholder="my-awesome-plugin" required />
<span asp-validation-for="PluginSlug" class="text-danger"></span>
</div>

<div class="form-group">
<label class="form-label">Select Tags</label>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
Select tags
</button>
<ul class="dropdown-menu p-3" aria-labelledby="dropdownMenuButton">
@foreach (var tag in Enum.GetValues(typeof(PluginTags)).Cast<PluginTags>())
{
<li class="form-check">
<input type="checkbox" class="form-check-input category-checkbox" value="@((int)tag)" id="tag@(tag)"
name="Tags" @(Model.Tags != null && Model.Tags.Contains(tag) ? "checked" : "")>
<label class="form-check-label" for="tag@(tag)">@tag</label>
</li>
}
</ul>
</div>
<span asp-validation-for="Tags" class="text-danger"></span>
<input type="hidden" name="SelectedCategories" id="SelectedCategories">
</div>

<div class="form-group mt-4">
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
</div>
</form>
</div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function () {
var checkboxes = document.querySelectorAll('.category-checkbox');
var selectedCategoriesInput = document.getElementById('SelectedCategories');
var dropdownButton = document.getElementById('dropdownMenuButton');
function updateButtonLabel() {
var selectedCategories = [];
checkboxes.forEach(function (cb) {
if (cb.checked) {
selectedCategories.push(cb.value);
}
});
selectedCategoriesInput.value = selectedCategories.join(',');

if (selectedCategories.length > 0) {
dropdownButton.textContent = selectedCategories.length + ' tag' + (selectedCategories.length > 1 ? 's' : '') + ' selected';
} else {
dropdownButton.textContent = 'Select tags';
}
}
checkboxes.forEach(function (checkbox) {
checkbox.addEventListener('change', updateButtonLabel);
});
updateButtonLabel();
});
</script>
50 changes: 50 additions & 0 deletions PluginBuilder/Views/Plugin/Settings.cshtml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@using PluginBuilder.Views.Enums
@model PluginBuilder.PluginSettings
@{
Layout = "_Layout";
Expand Down Expand Up @@ -33,10 +34,59 @@
<label asp-for="BuildConfig" class="form-label"></label>
<input asp-for="BuildConfig" class="form-control" placeholder="Release" />
<span asp-validation-for="BuildConfig" class="text-danger"></span>
</div>
<div class="form-group">
<label class="form-label">Select Tags</label>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
Select Tags
</button>
<ul class="dropdown-menu p-3" aria-labelledby="dropdownMenuButton">
@foreach (var tag in Enum.GetValues(typeof(PluginTags)).Cast<PluginTags>())
{
<li class="form-check">
<input type="checkbox" class="form-check-input category-checkbox" value="@((int)tag)" id="tag@(tag)"
name="Tags" @(Model.PluginTags != null && Model.PluginTags.Any(t => t.Name == tag.ToString()) ? "checked" : "")>
<label class="form-check-label" for="tag@(tag)">@tag</label>
</li>
}
</ul>
</div>
<span asp-validation-for="PluginTags" class="text-danger"></span>
<input type="hidden" name="SelectedCategories" id="SelectedCategories">
</div>

<div class="form-group mt-4">
<input type="submit" value="Update" class="btn btn-primary" id="Update" />
</div>
</form>
</div>
</div>


<script>
document.addEventListener('DOMContentLoaded', function () {
var checkboxes = document.querySelectorAll('.category-checkbox');
var selectedCategoriesInput = document.getElementById('SelectedCategories');
var dropdownButton = document.getElementById('dropdownMenuButton');
function updateButtonLabel() {
var selectedCategories = [];
checkboxes.forEach(function (cb) {
if (cb.checked) {
selectedCategories.push(cb.value);
}
});
selectedCategoriesInput.value = selectedCategories.join(',');

if (selectedCategories.length > 0) {
dropdownButton.textContent = selectedCategories.length + ' tag' + (selectedCategories.length > 1 ? 's' : '') + ' selected';
} else {
dropdownButton.textContent = 'Select tags';
}
}
checkboxes.forEach(function (checkbox) {
checkbox.addEventListener('change', updateButtonLabel);
});
updateButtonLabel();
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put this in a separate JS file to avoid duplication. You could also encapsulate the view part above in a view component and eliminate that duplication too this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to remove that, and use just input for tags using tom-select.

You can go ahead and review

</script>