Added Roles, User Management, fixed bugs, added FlexTable component (should be renamed to GridTable), other table components and test code should be removed down the line, added admin function to fix broken data structures.
This commit is contained in:
191
imports/ui/Users.svelte
Normal file
191
imports/ui/Users.svelte
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
<script>
|
||||
import {Route, router, meta} from 'tinro';
|
||||
import {Meteor} from "meteor/meteor";
|
||||
import FlexTable from "./FlexTable.svelte";
|
||||
import {useTracker} from "meteor/rdb:svelte-meteor-data";
|
||||
import {writable} from "svelte/store";
|
||||
|
||||
const columns = [
|
||||
{
|
||||
key: "_id",
|
||||
title: "ID",
|
||||
value: v => v._id,
|
||||
minWidth: 20,
|
||||
weight: 1,
|
||||
cls: "id",
|
||||
}, {
|
||||
key: "name",
|
||||
title: "Name",
|
||||
value: v => v.profile.name,
|
||||
minWidth: 100,
|
||||
weight: 1,
|
||||
cls: "name",
|
||||
}, {
|
||||
key: "roles",
|
||||
title: "Roles",
|
||||
value: user => {
|
||||
return Roles.getRolesForUser(user, {anyScope: true});
|
||||
},
|
||||
minWidth: 150,
|
||||
weight: 2,
|
||||
cls: "roles",
|
||||
}
|
||||
];
|
||||
|
||||
const getRowKey = user => {return user._id;}
|
||||
|
||||
function changeColWidth() {
|
||||
columns[0].width = '200px';
|
||||
}
|
||||
|
||||
const editRow = (row) => {
|
||||
//TODO: Setup the editor for the given row.
|
||||
}
|
||||
let edited = writable(null);
|
||||
let editedPermissions = null;
|
||||
|
||||
$: rows = Meteor.users.find({});
|
||||
|
||||
edited.subscribe((value) => {
|
||||
if(value) {
|
||||
editedPermissions = {
|
||||
isAdmin: Roles.userIsInRole(value, "admin", {anyScope: true}),
|
||||
laptopManagement: Roles.userIsInRole(value, "laptop-management", {anyScope: true}),
|
||||
}
|
||||
}
|
||||
});
|
||||
const applyChanges = () => {
|
||||
let roles = [];
|
||||
|
||||
if(editedPermissions.isAdmin) {
|
||||
roles.push('admin');
|
||||
}
|
||||
else {
|
||||
if(editedPermissions.laptopManagement) {
|
||||
roles.push('laptop-management');
|
||||
}
|
||||
}
|
||||
|
||||
Meteor.call("users.setUserRoles", $edited._id, roles);
|
||||
edited.set(null);
|
||||
}
|
||||
const rejectChanges = () => {
|
||||
edited.set(null);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Route path="/" let:meta>
|
||||
<div class="container">
|
||||
<div class="row col-12 table">
|
||||
{#await Promise.all([Meteor.subscribe('allUsers'), Meteor.subscribe('allRoleAssignments')])}
|
||||
Loading...
|
||||
{:then allUsers}
|
||||
<FlexTable bind:rows={rows} columns="{columns}" rowKey="{getRowKey}" bind:edited="{edited}">
|
||||
{#if editedPermissions}
|
||||
<div class="editorContainer">
|
||||
<label style="grid-column: 1/4; font-weight: 800; border-bottom: 2px solid #888; margin-bottom: 0.5rem">{$edited.profile.name}</label>
|
||||
<label class="checkbox" style="grid-column: 1/4;"><input type="checkbox" bind:checked="{editedPermissions.isAdmin}" style="--form-control-color: black"/> Administrator</label>
|
||||
<div class="insetPermissions">
|
||||
<label class="checkbox"><input type="checkbox" disabled="{editedPermissions.isAdmin}" bind:checked="{editedPermissions.laptopManagement}" style="--form-control-color: black"/> Laptop Management</label>
|
||||
</div>
|
||||
<button type="button" style="grid-column: 2/2;" class="button accept-button" on:click={applyChanges}> </button>
|
||||
<button type="button" style="grid-column: 3/3;" class="button reject-button" on:click={rejectChanges}> </button>
|
||||
</div>
|
||||
{/if}
|
||||
</FlexTable>
|
||||
<button type="button" on:click="{changeColWidth}">Change Width</button>
|
||||
{:catch error}
|
||||
{error.message}
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
</Route>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--form-control-disabled: #959495;
|
||||
}
|
||||
.checkbox {
|
||||
display: grid;
|
||||
grid-template-columns: 1em auto;
|
||||
gap: 0.5em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
/* Add if not using autoprefixer */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
/* For iOS < 15 to remove gradient background */
|
||||
background-color: #fff;
|
||||
/* Not removed via appearance */
|
||||
margin: 0;
|
||||
font: inherit;
|
||||
color: currentColor;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
border: 0.15em solid currentColor;
|
||||
border-radius: 0.15em;
|
||||
/*transform: translateY(-0.075em);*/
|
||||
display: grid;
|
||||
place-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
input[type="checkbox"]::before {
|
||||
content: "";
|
||||
width: 0.65em;
|
||||
height: 0.65em;
|
||||
transform: scale(0);
|
||||
transition: 120ms transform ease-in-out;
|
||||
box-shadow: inset 1em 1em var(--form-control-color);
|
||||
/* Windows High Contrast Mode */
|
||||
background-color: CanvasText;
|
||||
/* Make it a check mark shape. */
|
||||
transform-origin: bottom left;
|
||||
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||
}
|
||||
input[type="checkbox"]:checked::before {
|
||||
transform: scale(1);
|
||||
}
|
||||
input[type="checkbox"]:focus {
|
||||
outline: max(2px, 0.15em) solid currentColor;
|
||||
outline-offset: max(2px, 0.15em);
|
||||
}
|
||||
input[type="checkbox"]:disabled {
|
||||
--form-control-color: var(--form-control-disabled);
|
||||
|
||||
color: var(--form-control-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.editorContainer {
|
||||
display: grid;
|
||||
grid-template-columns: auto 2em 2em;
|
||||
}
|
||||
.insetPermissions {
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 1.5rem;
|
||||
display: grid;
|
||||
grid-column: 1/4;
|
||||
}
|
||||
button.button {
|
||||
border: none;
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button.accept-button {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-color: black;
|
||||
clip-path: polygon(11% 69%, 31% 93%, 94% 8%, 73% 6%, 33% 62%, 12% 40%);
|
||||
}
|
||||
button.reject-button {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-color: black;
|
||||
clip-path: polygon(18% 90%, 37% 89%, 50% 64%, 62% 89%, 81% 88%, 59% 44%, 82% 13%, 62% 12%, 49% 35%, 28% 12%, 11% 12%, 37% 43%);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user