account details view
Some checks failed
gitea.arg.rip/vassago/pipeline/head There was a failure building this commit

lineage summary doesn't work
This commit is contained in:
adam 2025-03-17 23:38:16 -04:00
parent d22faae2f6
commit 488a89614a
6 changed files with 230 additions and 57 deletions

View File

@ -0,0 +1,35 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using vassago.Models;
using vassago.WebInterface.Models;
namespace vassago.WebInterface.Controllers;
public class AccountsController(ChattingContext db) : Controller
{
private ChattingContext Database => db;
public async Task<IActionResult> Index()
{
return Database.Accounts != null ?
View(await Database.Accounts.ToListAsync()) :
Problem("Entity set '_db.Accounts' is null.");
}
public async Task<IActionResult> Details(Guid id)
{
var account = await Database.Accounts
.Include(a => a.IsUser)
.Include(a => a.SeenInChannel)
.FirstAsync(a => a.Id == id);
return Database.Accounts != null ?
View(account) :
Problem("Entity set '_db.Accounts' is null.");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorPageViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}

View File

@ -163,7 +163,7 @@ public class HomeController : Controller
}
private void serializeAccount(ref StringBuilder sb, Account currentAccount)
{
sb.Append($"{{\"text\": \"{currentAccount.DisplayName}\"}}");
sb.Append($"{{\"text\": \"<a href=\\\"{Url.ActionLink(action: "Details", controller: "Accounts", values: new {id = currentAccount.Id})}\\\">{currentAccount.DisplayName}</a>\"}}");
}
private void serializeUser(ref StringBuilder sb, ref List<Account> allAccounts, User currentUser)
{

View File

@ -0,0 +1,40 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using vassago.Models;
using vassago.ProtocolInterfaces.DiscordInterface;
namespace vassago.Controllers.api;
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly ILogger<ChannelsController> _logger;
public UsersController(ILogger<ChannelsController> logger)
{
_logger = logger;
}
[HttpPatch]
[Produces("application/json")]
public IActionResult Patch([FromBody] User user)
{
var fromDb = Rememberer.SearchUser(u => u.Id == user.Id);
if (fromDb == null)
{
_logger.LogError($"attempt to update user {user.Id}, not found");
return NotFound();
}
else
{
_logger.LogDebug($"patching {user.DisplayName} (id: {user.Id})");
}
//TODO: settable values: display name
//fromDb.DisplayName = user.DisplayName;
Rememberer.RememberUser(fromDb);
return Ok(fromDb);
}
}

View File

@ -0,0 +1,66 @@
@model Account
@using Newtonsoft.Json
@using System.Text
@{
ViewData["Title"] = "Account details";
}
<table class="table">
<tbody>
<tr>
<th scope="row">belongs to user</th>
<td>@Model.IsUser.DisplayName</td>
<td><button alt="to do" disabled>separate</button></td>
</tr>
<tr>
<th scope="row">Seen in channel</th>
<td><div class="protocol-icon">&nbsp;</div>@Model.SeenInChannel.LineageSummary<a href="/Channels/Details/@Model.SeenInChannel.Id">@Model.SeenInChannel.DisplayName</a></td>
</tr>
<tr>
<th scope="row">Permission Tags</th>
<td>
<div id="tagsTree"></div>
</td>
</tr>
</tbody>
</table>
@section Scripts{
<script type="text/javascript">
@{
var accountAsString = JsonConvert.SerializeObject(Model, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
const userOnLoad = @Html.Raw(accountAsString);
function jsonifyUser() {
var userNow = structuredClone(userOnLoad);
userNow.Accounts = null;
userNow.DisplayName = document.querySelector("#displayName").value;
console.log(userNow);
return userNow;
}
function getTagsTree() {
@{
var sb = new StringBuilder();
sb.Append("[{text: \"permission tags\", \"expanded\":true, nodes: [");
var first = true;
for (int i = 0; i < 1; i++)
{
if (!first)
sb.Append(',');
sb.Append($"{{text: \"<input type=\\\"checkbox\\\" > is goated (w/ sauce)</input>\"}}");
first = false;
}
sb.Append("]}]");
}
console.log(@Html.Raw(sb.ToString()));
var tree = @Html.Raw(sb.ToString());
return tree;
}
$('#tagsTree').bstreeview({ data: getTagsTree() });
document.querySelectorAll("input[type=checkbox]").forEach(node => { node.onchange = () => { patchModel(jsonifyUser(), '/api/Users/') } });
</script>
}

View File

@ -1,5 +1,6 @@
@using System.ComponentModel
@using Newtonsoft.Json
@using System.Text;
@model Tuple<Channel, Enumerations.LewdnessFilterLevel, Enumerations.MeannessFilterLevel>
@{
var ThisChannel = Model.Item1;
@ -91,7 +92,16 @@
</tr>
<tr>
<th scope="row">Accounts</th>
<td>@(ThisChannel.Users?.Count ?? 0)</td>
<td>
@if((ThisChannel.Users?.Count ?? 0) > 0)
{
@Html.Raw("<div id=\"accountsTree\"></div>");
}
else
{
@Html.Raw("none")
}
</td>
</tr>
<tr>
<td colspan="2">
@ -105,9 +115,9 @@
<script type="text/javascript">
@{
var modelAsString = JsonConvert.SerializeObject(ThisChannel, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
const channelOnLoad = @Html.Raw(modelAsString);
function jsonifyChannel() {
@ -133,7 +143,27 @@
var tree = @Html.Raw(ViewData["channelsTree"]);
return tree;
}
function accountsTree() {
@{
var sb = new StringBuilder();
sb.Append("[{text: \"accounts\", \"expanded\":true, nodes: [");
var first = true;
foreach (var acc in ThisChannel.Users.OrderBy(a => a.SeenInChannel.LineageSummary))
{
if(!first)
sb.Append(',');
sb.Append($"{{text: \"<div class=\\\"account {acc.Protocol}\\\"><div class=\\\"protocol-icon\\\">&nbsp;</div>{acc.SeenInChannel.LineageSummary}/<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a>\"}}");
first=false;
}
sb.Append("]}]");
}
//console.log(@Html.Raw(sb.ToString()));
var tree = @Html.Raw(sb.ToString());
return tree;
}
$('#channelsTree').bstreeview({ data: channelsTree() });
$('#accountsTree').bstreeview({ data: accountsTree() });
</script>
}

View File

@ -5,35 +5,37 @@
ViewData["Title"] = "User details";
}
<table class="table">
<tbody>
<tr>
<td><input type="text" id="displayName" value="@Model.DisplayName"></input> <button onclick="patchModel(jsonifyUser(), @Html.Raw("'/api/Users/'"))">update</button></td>
</tr>
<tr>
<td>
<div id="accountsTree"></div>
</td>
</tr>
<tr>
<td>
<div id="tagsTree"></div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<th scope="row">Display Name (here)</th>
<td><input type="text" id="displayName" value="@Model.DisplayName"></input> <button
onclick="patchModel(jsonifyUser(), @Html.Raw("'/api/Users/'"))" disabled alt"todo">update</button></td>
</tr>
<tr>
<th scope="row">Accounts</th>
<td>
<div id="accountsTree"></div>
</td>
</tr>
<tr>
<th scope="row">Permission Tags</th>
<td>
<div id="tagsTree"></div>
</td>
</tr>
</tbody>
</table>
<a asp-controller="Accounts" asp-action="Details" asp-route-id="1">placeholderlink</a>
@section Scripts{
<script type="text/javascript">
@{
var userAsString = JsonConvert.SerializeObject(Model, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
const userOnLoad = @Html.Raw(userAsString);
@{
var userAsString = JsonConvert.SerializeObject(Model, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
const userOnLoad = @Html.Raw(userAsString);
function jsonifyUser() {
var userNow = structuredClone(userOnLoad);
userNow.Accounts = null;
@ -43,44 +45,44 @@
return userNow;
}
function getAccountsTree() {
@{
var sb = new StringBuilder();
sb.Append("[{text: \"accounts\", \"expanded\":true, nodes: [");
var first = true;
foreach (var acc in Model.Accounts)
{
if(!first)
sb.Append(',');
sb.Append($"{{text: \"<div class=\\\"account {acc.Protocol}\\\"><div class=\\\"protocol-icon\\\">&nbsp;</div>{acc.SeenInChannel.LineageSummary}/<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a>\"}}");
first=false;
}
sb.Append("]}]");
@{
var sb = new StringBuilder();
sb.Append("[{text: \"accounts\", \"expanded\":true, nodes: [");
var first = true;
foreach (var acc in Model.Accounts.OrderBy(a => a.SeenInChannel.LineageSummary))
{
if (!first)
sb.Append(',');
sb.Append($"{{text: \"<div class=\\\"account {acc.Protocol}\\\"><div class=\\\"protocol-icon\\\">&nbsp;</div>{acc.SeenInChannel.LineageSummary}/<a href=\\\"/Accounts/Details/{acc.Id}\\\">{acc.DisplayName}</a>\"}}");
first = false;
}
console.log(@Html.Raw(sb.ToString()));
sb.Append("]}]");
}
console.log(@Html.Raw(sb.ToString()));
var tree = @Html.Raw(sb.ToString());
return tree;
}
function getTagsTree() {
@{
sb = new StringBuilder();
sb.Append("[{text: \"permission tags\", \"expanded\":true, nodes: [");
first = true;
for(int i = 0; i < 1; i++)
{
if(!first)
sb.Append(',');
sb.Append($"{{text: \"<input type=\\\"checkbox\\\" > is goated (w/ sauce)</input>\"}}");
first=false;
}
sb.Append("]}]");
@{
sb = new StringBuilder();
sb.Append("[{text: \"permission tags\", \"expanded\":true, nodes: [");
first = true;
for (int i = 0; i < 1; i++)
{
if (!first)
sb.Append(',');
sb.Append($"{{text: \"<input type=\\\"checkbox\\\" > is goated (w/ sauce)</input>\"}}");
first = false;
}
console.log(@Html.Raw(sb.ToString()));
sb.Append("]}]");
}
console.log(@Html.Raw(sb.ToString()));
var tree = @Html.Raw(sb.ToString());
return tree;
}
$('#accountsTree').bstreeview({ data: getAccountsTree() });
$('#tagsTree').bstreeview({ data: getTagsTree() });
document.querySelectorAll("input[type=checkbox]").forEach(node => {node.onchange = () => {patchModel(jsonifyUser(), '/api/Users/')}});
document.querySelectorAll("input[type=checkbox]").forEach(node => { node.onchange = () => { patchModel(jsonifyUser(), '/api/Users/') } });
</script>
}