added an autocomplete component and implemented in permission grid

This commit is contained in:
Shaun Walker 2023-01-04 14:50:05 -05:00
parent 39dc288f9c
commit 6a213561f6
3 changed files with 180 additions and 30 deletions

View File

@ -0,0 +1,153 @@
@namespace Oqtane.Modules.Controls
@inherits LocalizableComponent
<div class="app-autocomplete">
<input class="form-control" value="@Value" @oninput="OnInput" @onkeyup="OnKeyUp" placeholder="@Placeholder" autocomplete="off" />
@if (_results != null)
{
<select class="form-select" style="position: relative;" value="@Value" size="@Rows" @onkeyup="OnKeyUp" @onchange="(e => OnChange(e))">
@if (_results.Any())
{
@foreach (var result in _results)
{
if (result.Value == Value)
{
<option selected>@result.Value</option>
}
else
{
<option>@result.Value</option>
}
}
}
else
{
<option disabled>No Results</option>
}
</select>
}
</div>
@code {
Dictionary<string, string> _results;
[Parameter]
public Func<string, Task<Dictionary<string, string>>> OnSearch { get; set; } // required - an async delegate method which accepts a filter string parameter and returns a dictionary
[Parameter]
public int Characters { get; set; } = 3; // optional - number of characters before search is initiated
[Parameter]
public int Rows { get; set; } = 3; // optional - number of result rows to display
[Parameter]
public string Placeholder { get; set; } // optional - placeholder input text
[Parameter]
public string Value { get; set; } // value of item selected
[Parameter]
public string Key { get; set; } // key of item selected
private async Task OnInput(ChangeEventArgs e)
{
Value = e.Value?.ToString();
if (Value?.Length >= Characters)
{
_results = await OnSearch?.Invoke(Value);
}
else
{
_results = null;
}
SetKey();
}
private async Task OnKeyUp(KeyboardEventArgs e)
{
var index = -1;
switch (e.Key)
{
case "ArrowDown":
if (_results == null)
{
if (Value?.Length >= Characters)
{
_results = await OnSearch?.Invoke(Value);
}
}
else
{
index = GetIndex();
if (index < _results.Count - 1)
{
Value = _results.ElementAt(index + 1).Value;
Key = _results.ElementAt(index + 1).Key;
}
}
break;
case "ArrowUp":
index = GetIndex();
if (index > 0)
{
Value = _results.ElementAt(index - 1).Value;
Key = _results.ElementAt(index - 1).Key;
}
break;
case "ArrowRight":
case "Tab":
_results = null;
break;
case "Enter": // note within a form the enter key submits the entire form
case "NumpadEnter":
_results = null;
break;
case "Escape":
Value = "";
_results = null;
break;
}
}
private void OnChange(ChangeEventArgs e)
{
Value = (string)e.Value;
SetKey();
_results = null;
}
private int GetIndex()
{
if (_results != null)
{
for (int index = 0; index < _results.Count; index++)
{
if (_results.ElementAt(index).Value == Value)
{
return index;
}
}
}
return -1;
}
private void SetKey()
{
var index = GetIndex();
if (index != -1)
{
Key = _results.ElementAt(index).Key;
}
else
{
Key = "";
}
}
public void Clear()
{
Value = "";
Key = "";
_results = null;
}
}

View File

@ -2,6 +2,7 @@
@inherits ModuleControlBase @inherits ModuleControlBase
@inject IRoleService RoleService @inject IRoleService RoleService
@inject IUserService UserService @inject IUserService UserService
@inject IUserRoleService UserRoleService
@inject IStringLocalizer<PermissionGrid> Localizer @inject IStringLocalizer<PermissionGrid> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer @inject IStringLocalizer<SharedResources> SharedLocalizer
@ -77,23 +78,16 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col"> <div class="col-11">
<table class="table table-borderless"> <AutoComplete OnSearch="GetUsers" Placeholder="@Localizer["Username.Enter"]" @ref="_user" />
<tbody> </div>
<tr> <div class="col-1">
<td class="input-group"> <button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
<input type="text" name="Username" class="form-control" placeholder="@Localizer["Username.Enter"]" @bind="@_username" />
<button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
</td>
</tr>
</tbody>
</table>
<br />
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<ModuleMessage Type="MessageType.Error" Message="@_message" /> <ModuleMessage Type="MessageType.Warning" Message="@_message" />
</div> </div>
</div> </div>
</div> </div>
@ -104,7 +98,7 @@
private List<Role> _roles; private List<Role> _roles;
private List<PermissionString> _permissions; private List<PermissionString> _permissions;
private List<User> _users = new List<User>(); private List<User> _users = new List<User>();
private string _username = string.Empty; private AutoComplete _user;
private string _message = string.Empty; private string _message = string.Empty;
[Parameter] [Parameter]
@ -191,25 +185,28 @@
private bool GetPermissionDisabled(string roleName) private bool GetPermissionDisabled(string roleName)
=> (roleName == RoleNames.Admin && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) ? true : false; => (roleName == RoleNames.Admin && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) ? true : false;
private async Task<Dictionary<string, string>> GetUsers(string filter)
{
var users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
return users.Where(item => item.User.DisplayName.Contains(filter, StringComparison.OrdinalIgnoreCase))
.ToDictionary(item => item.UserId.ToString(), item => item.User.DisplayName);
}
private async Task AddUser() private async Task AddUser()
{ {
if (_users.Where(item => item.Username == _username).FirstOrDefault() == null) if (!string.IsNullOrEmpty(_user.Key))
{ {
try var user = await UserService.GetUserAsync(int.Parse(_user.Key), ModuleState.SiteId);
if (user != null && !_users.Any(item => item.UserId == user.UserId))
{ {
var user = await UserService.GetUserAsync(_username, ModuleState.SiteId); _users.Add(user);
if (user != null)
{
_users.Add(user);
}
}
catch
{
_message = Localizer["Message.Username.DontExist"];
} }
} }
else
_username = string.Empty; {
_message = Localizer["Message.Username.DontExist"];
}
_user.Clear();
} }
private void PermissionChanged(bool? value, string permissionName, string securityId) private void PermissionChanged(bool? value, string permissionName, string securityId)

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
@ -124,9 +124,9 @@
<value>User</value> <value>User</value>
</data> </data>
<data name="Username.Enter" xml:space="preserve"> <data name="Username.Enter" xml:space="preserve">
<value>Enter Username</value> <value>Enter User's Name</value>
</data> </data>
<data name="Message.Username.DontExist" xml:space="preserve"> <data name="Message.Username.DontExist" xml:space="preserve">
<value>Username Does Not Exist</value> <value>User Does Not Exist With Name Specified</value>
</data> </data>
</root> </root>