Update Bookings
This commit is contained in:
parent
5d62d2e3b9
commit
6822472102
@ -26,11 +26,17 @@ namespace PSTW_CentralSystem.Areas.Bookings.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DB-backed manager check (NO Identity roles here)
|
// DB-backed manager check (NO Identity roles here)
|
||||||
private Task<bool> IsManagerAsync()
|
private async Task<bool> IsManagerAsync()
|
||||||
{
|
{
|
||||||
var me = GetCurrentUserId();
|
var me = GetCurrentUserId();
|
||||||
if (me is null) return Task.FromResult(false);
|
if (me is null) return false;
|
||||||
return _db.BookingManager.AsNoTracking()
|
|
||||||
|
if (User.IsInRole("SuperAdmin") || User.IsInRole("SystemAdmin"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _db.BookingManager.AsNoTracking()
|
||||||
.AnyAsync(x => x.UserId == me.Value && x.IsActive);
|
.AnyAsync(x => x.UserId == me.Value && x.IsActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,8 @@ namespace PSTW_CentralSystem.Areas.Bookings.Models
|
|||||||
[Required]
|
[Required]
|
||||||
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
|
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
[ForeignKey("CreatedByUserId")]
|
||||||
public int? CreatedByUserId { get; set; }
|
public int? CreatedByUserId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -243,7 +243,8 @@
|
|||||||
box-shadow: 0 2px 6px rgba(0,0,0,.06);
|
box-shadow: 0 2px 6px rgba(0,0,0,.06);
|
||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden
|
overflow: hidden;
|
||||||
|
z-index: 2; /* Tambah baris ini supaya kotak berada DI ATAS garisan */
|
||||||
}
|
}
|
||||||
|
|
||||||
.booking .t {
|
.booking .t {
|
||||||
@ -387,59 +388,66 @@
|
|||||||
dowRow.dataset.done = "1";
|
dowRow.dataset.done = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Lookups (rooms + users) ---
|
// --- Lookups (rooms + users) ---
|
||||||
let userMap = new Map(), roomMap = new Map(), users = [], rooms = [];
|
let userMap = new Map(), roomMap = new Map(), users = [], rooms = [];
|
||||||
async function loadLookups() {
|
async function loadLookups() {
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`${api}?scope=${calendarScope}&lookups=1`);
|
const r = await fetch(`${api}?scope=${calendarScope}&lookups=1`);
|
||||||
if (!r.ok) throw new Error(`Lookups ${r.status} ${r.statusText}`);
|
if (!r.ok) throw new Error(`Lookups ${r.status} ${r.statusText}`);
|
||||||
const js = await r.json();
|
const js = await r.json();
|
||||||
rooms = js.rooms ?? [];
|
rooms = js.rooms ?? [];
|
||||||
users = js.users ?? [];
|
users = js.users ?? [];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alertMsg(e.message);
|
alertMsg(e.message);
|
||||||
rooms = [];
|
rooms = [];
|
||||||
users = [];
|
users = [];
|
||||||
}
|
|
||||||
|
|
||||||
// Fill selects
|
|
||||||
ddlRoom.innerHTML = '<option value="">All rooms</option>';
|
|
||||||
rooms.forEach(r => {
|
|
||||||
const id = r.roomId;
|
|
||||||
const name = r.roomName ?? `Room ${id}`;
|
|
||||||
if (id == null) return;
|
|
||||||
const opt = document.createElement("option");
|
|
||||||
opt.value = id;
|
|
||||||
opt.textContent = name;
|
|
||||||
ddlRoom.appendChild(opt);
|
|
||||||
});
|
|
||||||
|
|
||||||
ddlUser.innerHTML = '<option value="">All users</option>';
|
|
||||||
users.forEach(u => {
|
|
||||||
const id = u.Id ?? u.id;
|
|
||||||
const name = u.UserName ?? u.userName ?? "";
|
|
||||||
const email = u.Email ?? "";
|
|
||||||
const opt = document.createElement("option");
|
|
||||||
opt.value = id;
|
|
||||||
opt.textContent = email ? `${name} (${email})` : name;
|
|
||||||
ddlUser.appendChild(opt);
|
|
||||||
});
|
|
||||||
|
|
||||||
userMap = new Map(
|
|
||||||
users.map(u => [
|
|
||||||
Number(u.Id ?? u.id),
|
|
||||||
(u.UserName ?? u.userName ?? "") + (u.Email ? ` (${u.Email})` : "")
|
|
||||||
])
|
|
||||||
);
|
|
||||||
roomMap = new Map(
|
|
||||||
rooms.map(r => {
|
|
||||||
const id = Number(r.roomId ?? r.RoomId);
|
|
||||||
const name = r.roomName ?? r.Name ?? r.RoomName ?? `Room ${id}`;
|
|
||||||
return [id, name];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill selects
|
||||||
|
ddlRoom.innerHTML = '<option value="">All rooms</option>';
|
||||||
|
rooms.forEach(r => {
|
||||||
|
const id = r.roomId;
|
||||||
|
const name = r.roomName ?? `Room ${id}`;
|
||||||
|
if (id == null) return;
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = id;
|
||||||
|
opt.textContent = name;
|
||||||
|
ddlRoom.appendChild(opt);
|
||||||
|
});
|
||||||
|
|
||||||
|
ddlUser.innerHTML = '<option value="">All users</option>';
|
||||||
|
|
||||||
|
// Filter out the Admin
|
||||||
|
const nonAdminUsers = users.filter(u => {
|
||||||
|
const name = u.UserName ?? u.userName ?? "";
|
||||||
|
return name !== "MAAdmin" && name !== "SysAdmin";
|
||||||
|
});
|
||||||
|
|
||||||
|
nonAdminUsers.forEach(u => {
|
||||||
|
const id = u.Id ?? u.id;
|
||||||
|
const name = u.UserName ?? u.userName ?? "";
|
||||||
|
const email = u.Email ?? "";
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = id;
|
||||||
|
opt.textContent = email ? `${name} (${email})` : name;
|
||||||
|
ddlUser.appendChild(opt);
|
||||||
|
});
|
||||||
|
|
||||||
|
userMap = new Map(
|
||||||
|
users.map(u => [
|
||||||
|
Number(u.Id ?? u.id),
|
||||||
|
(u.UserName ?? u.userName ?? "") + (u.Email ? ` (${u.Email})` : "")
|
||||||
|
])
|
||||||
|
);
|
||||||
|
roomMap = new Map(
|
||||||
|
rooms.map(r => {
|
||||||
|
const id = Number(r.roomId ?? r.RoomId);
|
||||||
|
const name = r.roomName ?? r.Name ?? r.RoomName ?? `Room ${id}`;
|
||||||
|
return [id, name];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Data fetching for month grid ---
|
// --- Data fetching for month grid ---
|
||||||
let curMonth = startOfMonth(new Date()), currentData = [];
|
let curMonth = startOfMonth(new Date()), currentData = [];
|
||||||
async function fetchGridData(month) {
|
async function fetchGridData(month) {
|
||||||
@ -556,7 +564,7 @@
|
|||||||
function getUserId(b) { const v = [b.requestedByUserId, b.UserId, b.userId, b.targetUserId, b.TargetUserId, b.bookedByUserId, b.BookedByUserId, b.approvedByUserId, b.ApprovedByUserId].find(x => x != null); const n = Number(v); return Number.isNaN(n) ? null : n; }
|
function getUserId(b) { const v = [b.requestedByUserId, b.UserId, b.userId, b.targetUserId, b.TargetUserId, b.bookedByUserId, b.BookedByUserId, b.approvedByUserId, b.ApprovedByUserId].find(x => x != null); const n = Number(v); return Number.isNaN(n) ? null : n; }
|
||||||
|
|
||||||
function openDayBoard(dayDate) {
|
function openDayBoard(dayDate) {
|
||||||
boardTitle.textContent = `Schedule • ${dayDate.toLocaleDateString()}`;
|
boardTitle.textContent = `Schedule • ${dayDate.toLocaleDateString('en-GB')}`;
|
||||||
boardFilters.textContent = `Filters: ${ddlRoom.options[ddlRoom.selectedIndex]?.text || "All rooms"}`;
|
boardFilters.textContent = `Filters: ${ddlRoom.options[ddlRoom.selectedIndex]?.text || "All rooms"}`;
|
||||||
|
|
||||||
// Left time labels
|
// Left time labels
|
||||||
@ -592,7 +600,7 @@
|
|||||||
colsHead.appendChild(h);
|
colsHead.appendChild(h);
|
||||||
});
|
});
|
||||||
|
|
||||||
canvas.style.height = `${TOTAL_INTERVALS * SLOT_PX}px`;
|
canvas.style.height = `${(TOTAL_INTERVALS + 1) * SLOT_PX}px`;
|
||||||
|
|
||||||
// Build grid columns
|
// Build grid columns
|
||||||
colGrid.innerHTML = "";
|
colGrid.innerHTML = "";
|
||||||
|
|||||||
@ -352,7 +352,9 @@
|
|||||||
|
|
||||||
// ---------- Lookups ----------
|
// ---------- Lookups ----------
|
||||||
async function loadLookups(selectedRoomId, selectedUserId) {
|
async function loadLookups(selectedRoomId, selectedUserId) {
|
||||||
const res = await fetch(`${api}?lookups=1`);
|
|
||||||
|
const res = await fetch(`${api}?lookups=1&onlyActive=true`);
|
||||||
|
|
||||||
if (!res.ok) throw new Error(await res.text());
|
if (!res.ok) throw new Error(await res.text());
|
||||||
const { rooms = [], users = [] } = await res.json();
|
const { rooms = [], users = [] } = await res.json();
|
||||||
|
|
||||||
@ -388,7 +390,13 @@
|
|||||||
// Users
|
// Users
|
||||||
const userDdl = document.getElementById("RequestedByUserId");
|
const userDdl = document.getElementById("RequestedByUserId");
|
||||||
userDdl.innerHTML = '<option value="">-- Select User --</option>';
|
userDdl.innerHTML = '<option value="">-- Select User --</option>';
|
||||||
users.forEach(u => {
|
|
||||||
|
const nonAdminUsers = users.filter(u => {
|
||||||
|
const name = pick(u, "UserName", "userName") ?? "";
|
||||||
|
return name !== "MAAdmin" && name !== "SysAdmin";
|
||||||
|
});
|
||||||
|
|
||||||
|
nonAdminUsers.forEach(u => {
|
||||||
const id = pick(u, "Id", "id");
|
const id = pick(u, "Id", "id");
|
||||||
if (id == null) return;
|
if (id == null) return;
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,22 @@
|
|||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@using System.Security.Claims
|
@using System.Security.Claims
|
||||||
|
@inject PSTW_CentralSystem.DBContext.CentralSystemContext _db
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Bookings";
|
ViewData["Title"] = "Bookings";
|
||||||
Layout = "_Layout";
|
Layout = "_Layout";
|
||||||
|
|
||||||
var isMgr = User?.IsInRole("Manager") == true;
|
|
||||||
var idStr = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
var idStr = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||||
var meId = int.TryParse(idStr, out var tmp) ? tmp : 0;
|
var meId = int.TryParse(idStr, out var tmp) ? tmp : 0;
|
||||||
|
|
||||||
|
bool isAdmin = User?.IsInRole("SuperAdmin") == true || User?.IsInRole("SystemAdmin") == true;
|
||||||
|
|
||||||
|
bool isBookingManager = false;
|
||||||
|
if (meId > 0)
|
||||||
|
{
|
||||||
|
isBookingManager = _db.BookingManager.Any(x => x.UserId == meId && x.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isMgr = isAdmin || isBookingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -148,8 +158,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.col-actions {
|
.col-actions {
|
||||||
width: 150px;
|
width: 200px;
|
||||||
min-width: 150px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Long text cells */
|
/* Long text cells */
|
||||||
@ -500,29 +510,47 @@
|
|||||||
if (!res.ok) return;
|
if (!res.ok) return;
|
||||||
const { rooms = [], users = [] } = await res.json();
|
const { rooms = [], users = [] } = await res.json();
|
||||||
|
|
||||||
this.users = users; this.rooms = rooms;
|
const nonAdminUsers = users.filter(u => {
|
||||||
|
const name = u.UserName ?? u.userName ?? "";
|
||||||
|
return name !== "MAAdmin" && name !== "SysAdmin";
|
||||||
|
});
|
||||||
|
|
||||||
|
this.users = nonAdminUsers;
|
||||||
|
this.rooms = rooms;
|
||||||
|
|
||||||
const sel = document.getElementById("fltUser");
|
const sel = document.getElementById("fltUser");
|
||||||
if (sel) {
|
if (sel) {
|
||||||
const prev = sel.value ?? "";
|
const prev = sel.value ?? "";
|
||||||
sel.innerHTML = '<option value="">All users</option>';
|
sel.innerHTML = '<option value="">All users</option>';
|
||||||
users.forEach(u => {
|
|
||||||
const id = Number(u.Id ?? u.id); if (!id) return;
|
nonAdminUsers.forEach(u => {
|
||||||
|
const id = Number(u.Id ?? u.id);
|
||||||
|
if (!id) return;
|
||||||
const name = u.UserName ?? u.userName ?? "";
|
const name = u.UserName ?? u.userName ?? "";
|
||||||
|
|
||||||
const opt = document.createElement("option");
|
const opt = document.createElement("option");
|
||||||
opt.value = String(id); opt.textContent = name;
|
opt.value = String(id);
|
||||||
|
opt.textContent = name;
|
||||||
sel.appendChild(opt);
|
sel.appendChild(opt);
|
||||||
});
|
});
|
||||||
if (prev && [...sel.options].some(o => o.value === prev)) { sel.value = prev; this.fltUser = prev; }
|
|
||||||
|
if (prev && [...sel.options].some(o => o.value === prev)) {
|
||||||
|
sel.value = prev;
|
||||||
|
this.fltUser = prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.userMap = new Map(users.map(u => [Number(u.Id ?? u.id), (u.UserName ?? u.userName ?? "")]));
|
this.userMap = new Map(nonAdminUsers.map(u => [Number(u.Id ?? u.id), (u.UserName ?? u.userName ?? "")]));
|
||||||
|
|
||||||
this.roomMap = new Map(rooms.map(r => {
|
this.roomMap = new Map(rooms.map(r => {
|
||||||
const id = Number(r.roomId ?? r.RoomId);
|
const id = Number(r.roomId ?? r.RoomId);
|
||||||
const name = r.roomName ?? r.Name ?? r.RoomName ?? `Room ${id}`;
|
const name = r.roomName ?? r.Name ?? r.RoomName ?? `Room ${id}`;
|
||||||
return [id, name];
|
return [id, name];
|
||||||
}));
|
}));
|
||||||
} catch { }
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error loading lookups:", e);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async loadList() {
|
async loadList() {
|
||||||
|
|||||||
@ -166,7 +166,12 @@
|
|||||||
computed: {
|
computed: {
|
||||||
filteredUsers() {
|
filteredUsers() {
|
||||||
const k = (this.q || '').toLowerCase();
|
const k = (this.q || '').toLowerCase();
|
||||||
return !k ? this.users : this.users.filter(u =>
|
|
||||||
|
const nonAdminUsers = this.users.filter(u =>
|
||||||
|
u.name !== "MAAdmin" && u.name !== "SysAdmin"
|
||||||
|
);
|
||||||
|
|
||||||
|
return !k ? nonAdminUsers : nonAdminUsers.filter(u =>
|
||||||
(u.name || '').toLowerCase().includes(k) || (u.email || '').toLowerCase().includes(k)
|
(u.name || '').toLowerCase().includes(k) || (u.email || '').toLowerCase().includes(k)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -34,6 +34,12 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
{
|
{
|
||||||
var me = GetCurrentUserId();
|
var me = GetCurrentUserId();
|
||||||
if (me is null) return false;
|
if (me is null) return false;
|
||||||
|
|
||||||
|
if (User.IsInRole("SuperAdmin") || User.IsInRole("SystemAdmin"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Dynamic manager list (booking_managers)
|
// Dynamic manager list (booking_managers)
|
||||||
return _db.BookingManager.AsNoTracking()
|
return _db.BookingManager.AsNoTracking()
|
||||||
.Any(x => x.UserId == me.Value && x.IsActive);
|
.Any(x => x.UserId == me.Value && x.IsActive);
|
||||||
@ -183,19 +189,31 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
// Only an existing manager can edit the list (bootstrap by seeding one row)
|
// Only an existing manager can edit the list (bootstrap by seeding one row)
|
||||||
if (!IsManager()) return Unauthorized("Managers only.");
|
if (!IsManager()) return Unauthorized("Managers only.");
|
||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, AppTz);
|
||||||
var me = GetCurrentUserId();
|
var me = GetCurrentUserId();
|
||||||
|
|
||||||
// Soft-reset approach: mark all inactive then upsert selected as active
|
// Soft-reset approach: mark all inactive then upsert selected as active
|
||||||
var all = await _db.BookingManager.ToListAsync();
|
var all = await _db.BookingManager.ToListAsync();
|
||||||
foreach (var bm in all) bm.IsActive = false;
|
|
||||||
|
|
||||||
var selected = new HashSet<int>(dto.UserIds.Where(id => id > 0));
|
var selected = new HashSet<int>(dto.UserIds.Where(id => id > 0));
|
||||||
|
|
||||||
|
foreach (var existing in all)
|
||||||
|
{
|
||||||
|
bool shouldBeActive = selected.Contains(existing.UserId);
|
||||||
|
|
||||||
|
// If the status is changing
|
||||||
|
if (existing.IsActive != shouldBeActive)
|
||||||
|
{
|
||||||
|
existing.IsActive = shouldBeActive;
|
||||||
|
existing.CreatedUtc = now; // Update the timestamp
|
||||||
|
existing.CreatedByUserId = me; // Update who made the change
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var uid in selected)
|
foreach (var uid in selected)
|
||||||
{
|
{
|
||||||
var existing = all.FirstOrDefault(x => x.UserId == uid);
|
bool exists = all.Any(x => x.UserId == uid);
|
||||||
if (existing is null)
|
|
||||||
|
if (!exists)
|
||||||
{
|
{
|
||||||
_db.BookingManager.Add(new BookingManager
|
_db.BookingManager.Add(new BookingManager
|
||||||
{
|
{
|
||||||
@ -205,10 +223,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
CreatedByUserId = me
|
CreatedByUserId = me
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
existing.IsActive = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
await _db.SaveChangesAsync();
|
||||||
@ -242,7 +256,8 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
[FromQuery] int pageSize = 450,
|
[FromQuery] int pageSize = 450,
|
||||||
[FromQuery] int? userId = null,
|
[FromQuery] int? userId = null,
|
||||||
[FromQuery] int? companyId = null,
|
[FromQuery] int? companyId = null,
|
||||||
[FromQuery] int? departmentId = null
|
[FromQuery] int? departmentId = null,
|
||||||
|
[FromQuery] bool onlyActive = false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// ROOMS LIST (admin tooling / open to authenticated)
|
// ROOMS LIST (admin tooling / open to authenticated)
|
||||||
@ -270,7 +285,7 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
{
|
{
|
||||||
var roomsAll = await _db.Rooms
|
var roomsAll = await _db.Rooms
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(r => r.IsActive)
|
//.Where(r => r.IsActive)
|
||||||
.OrderBy(r => r.RoomName)
|
.OrderBy(r => r.RoomName)
|
||||||
.Select(r => new { roomId = r.RoomId, roomName = r.RoomName })
|
.Select(r => new { roomId = r.RoomId, roomName = r.RoomName })
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@ -337,9 +352,14 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
// LOOKUPS PACK
|
// LOOKUPS PACK
|
||||||
if (lookups == 1)
|
if (lookups == 1)
|
||||||
{
|
{
|
||||||
var rooms = await _db.Rooms
|
var roomsQuery = _db.Rooms.AsNoTracking();
|
||||||
.AsNoTracking()
|
|
||||||
.Where(r => r.IsActive)
|
if (onlyActive)
|
||||||
|
{
|
||||||
|
roomsQuery = roomsQuery.Where(r => r.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
var rooms = await roomsQuery
|
||||||
.OrderBy(r => r.RoomName)
|
.OrderBy(r => r.RoomName)
|
||||||
.Select(r => new { roomId = r.RoomId, roomName = r.RoomName })
|
.Select(r => new { roomId = r.RoomId, roomName = r.RoomName })
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@ -347,8 +367,7 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
object usersPayload;
|
object usersPayload;
|
||||||
if (IsManager())
|
if (IsManager())
|
||||||
{
|
{
|
||||||
usersPayload = await _db.Users
|
usersPayload = await _db.Users.AsNoTracking()
|
||||||
.AsNoTracking()
|
|
||||||
.OrderBy(u => u.FullName)
|
.OrderBy(u => u.FullName)
|
||||||
.Select(u => new { u.Id, UserName = u.FullName, u.Email })
|
.Select(u => new { u.Id, UserName = u.FullName, u.Email })
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|||||||
@ -4,6 +4,9 @@ namespace PSTW_CentralSystem.Models
|
|||||||
{
|
{
|
||||||
public class RoleModel : IdentityRole<int>
|
public class RoleModel : IdentityRole<int>
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? NormalizedName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user