First commit

This commit is contained in:
2025-12-25 11:16:59 +01:00
commit 0c5ca09a63
720 changed files with 329234 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import checkbox from "/elements/checkbox.js"
import user from "/user/user.js"
import tools from "/unify/tools.js"
export default class customCheckbox extends checkbox{
async create() {
var selected = await this.checkSelected();
this.customElement.checked = selected;
}
debug = "true"
node async checkSelected() {
var editUser = this.parents("editUser");
var collection = editUser.selectedUsers;
collection.sync();
var id = this.parent.id;
tools.log("check selected??", id);
var v = collection.rowExists( id );
console.log(v);
return v;
}
async change() {
this.value = this.customElement.checked;
await this.changeCollection( this.value );
var editUser = this.parent.parent.parent.parent;
editUser.showSelectedUser.sync();
}
node async changeCollection( checked ) {
var editUser = this.parents("editUser");
var collection = editUser.selectedUsers;
var userObject = this.parent;
tools.log(userObject );
if( checked ) {
collection.add( userObject );
} else {
collection.remove( userObject );
}
return 1234;
}
}

View File

@@ -0,0 +1,25 @@
import groups from '/user/group/user.group.permission.js';
import renderCollection from "/unify/renderCollection.js";
export default class checkRenderCollection extends renderCollection{
debug = true;
display = "table"
permission() {
this.allow( groups.admin, "WRITE" );
this.allow( groups.member, "READ" );
this.allow( groups.admin, "READ" );
this.allow( groups.visitor, "READ" );
}
}

View File

@@ -0,0 +1,19 @@
import label from '/elements/label.js';
import checkRenderCollection from "./edit.user.checkbox.renderCollection.js";
import checkbox from "./edit.user.checkbox.tableRow.js";
import user from "/user/user.js";
import collection from "/unify/collection.js";
export default class checkboxRow{
label = new label("Select users");
renderCollection = new checkRenderCollection( checkbox , new collection( user ) );
}

View File

@@ -0,0 +1,37 @@
import checkbox from './edit.user.checkbox.js';
import radio from '/elements/radioButton.js';
import label from '/elements/label.js';
import user from "/user/user.js";
export default class customCheckbox extends user{
setup() {
console.log("customCheckbox", this);
this.label.text = this.username.value;
this.checkbox.id = this.id;
}
label = new label();
checkbox = new checkbox();
value = false;
layers = 1;
parseTable = false;
display = "table-row";
layers = 1;
}

View File

@@ -0,0 +1,73 @@
import user from "/user/user.js";
import groups from '/user/group/user.group.permission.js';
import label from '/elements/label.js';
import header from '/elements/header.js';
import usernameRow from "./edit.username.row.js";
import saveButtonRow from "./user.edit.button.row.js";
import page from "/elements/page.js";
import checkboxRow from "./edit.user.checkbox.row.js";
import selectRow from "./edit.user.select.row.js";
import option from "./edit.user.select.option.js";
import renderCollection from "./edit.user.select.renderCollection.js";
export default class editUser extends user, page{
padding = 20;
debug = true;
flexDirection = "column"
header = new header("Edit user");
usernameRow = new usernameRow();
selectRow = new selectRow();
checkboxRow = new checkboxRow();
showSelectedUser = new renderCollection( option, this.selectedUsers );
saveButtonRow = new saveButtonRow();
create() {
this.selectRow.renderCollection.sync();
this.checkboxRow.renderCollection.sync();
this.showSelectedUser.sync();
}
permission() {
this.allow( groups.admin, "WRITE" );
this.allow( groups.member, "READ" );
this.allow( groups.admin, "READ" );
this.allow( groups.visitor, "READ" );
}
}

View File

@@ -0,0 +1,19 @@
import option from "/elements/option.js";
import user from "/user/user.js";
export default class customOption extends option, user{
setup() {
// use username as label
this.customElement.innerHTML = this.username.value;
// username as value
this.customElement.value = this.id;
}
}

View File

@@ -0,0 +1,198 @@
import renderCollection from "/unify/renderCollection.js";
import groups from '/user/group/user.group.permission.js';
import document from "/unify/document.js";
export default class customSelect extends renderCollection{
customElement = document.createElement("select");
useCustomElement = true;
debug = true;
#ifdef MACOS
width = "70%";
#ifdef LIGHT
borderBottom = "1px solid #dedede"
background = "#f7f7f7";
color = "black";
opaqueBackgroundColor = "#f7f7f7";
focusBackgroundColor = "#f7f7f7";
focusBorderBottom = "1px solid #dedede";
blurBackgroundColor = "#F7FAFC";
blurBorderBottom = "1px solid #E5E5E5";
color = "#b1b1b1";
#endif
#ifdef DARK
background = "rgb(255 255 255 / 3%)";
color = "white";
opaqueBackgroundColor = "rgb(255 255 255 / 3%)";
focusBackgroundColor = "rgb(255 255 255 / 3%)";
focusBorderBottom = "";
blurBackgroundColor = "#fbfbfb";
blurBorderBottom = "";
#endif
padding = 6;
margin = 6;
marginRight = 20;
height = "fit-content";
borderRadius = 0;
fontWeight = "bold";
fontSize = 10;
border = "1px solid rgb(255 255 255 / 18%)";
padding = 12;
fontSize = "";
borderRadius = 6;
borderBottom = "none";
width = "auto"
#endif
#ifdef WINDOWS
borderBottom = "2px solid #868686"
borderRadius = 6;
padding = 8;
margin = 12;
#ifdef LIGHT
background = "#F7FAFC";
border = "1px solid #E5E5E5";
opaqueBackgroundColor = "#F7FAFC";
focusBackgroundColor = "white";
focusBorderBottom = "2px solid #4CC2FF";
blurBackgroundColor = "#F7FAFC";
blurBorderBottom = "1px solid #E5E5E5";
#endif
#ifdef DARK
background = "#2D2D2D!important"
webkitBoxShadow = "0 0 0px 30px #2D2D2D inset!important";
webkitTextFillColor = "white";
color = "white"
transition = "background-color 5000s ease-in-out 0s";
border = "1px solid #303030";
borderBottom = "2px solid #9A9A9A";
color = "WHITE";
opaqueBackgroundColor = "#2D2D2D!important";
focusBackgroundColor = "#1F1F1F";
focusBorderBottom = "2px solid #0067C0";
blurBackgroundColor = "#fbfbfb";
blurBorderBottom = "1px solid #9A9A9A";
#endif
#endif
permission() {
this.allow( groups.admin, "WRITE" );
this.allow( groups.member, "READ" );
this.allow( groups.admin, "READ" );
this.allow( groups.visitor, "READ" );
}
}

View File

@@ -0,0 +1,19 @@
import label from '/elements/label.js';
import collection from "/unify/collection.js";
import user from "/user/user.js";
import option from "./edit.user.select.option.js";
import renderCollection from "./edit.user.select.renderCollection.js";
export default class optionRow{
label = new label("Select user");
renderCollection = new renderCollection( option , new collection( user ) );
}

View File

@@ -0,0 +1,10 @@
import username from "../user.username.js";
import input from "/elements/input.js";
export default class editUsername extends username, input{
}

View File

@@ -0,0 +1,14 @@
import label from '/elements/label.js';
import editUsername from "./edit.username.js";
export default class usernameRow{
label = new label("Username");
username = new editUsername();
}

View File

@@ -0,0 +1,13 @@
import button from '/elements/button.js';
export default class userEditButton extends button {
label = "Save";
async click( event, object ){
await this.parent.parent.save();
}
}

View File

@@ -0,0 +1,13 @@
import empty from '/elements/empty.js';
import userEditButton from "./user.edit.button.js";
export default class saveButtonRow{
empty = new empty();
userEditButton = new userEditButton();
}

View File

@@ -0,0 +1,24 @@
import option from '/elements/option.js';
import datatype from '/unify/datatype.js';
export default class admin extends option {
value = 1.0;
label = "Admin";
type = "userGroup";
constructor() {
super();
}
}

View File

@@ -0,0 +1,137 @@
import collection from "/unify/collection.js";
import datatype from '/unify/datatype.js';
import option from '/elements/option.js';
class visitor extends option{
value = 2.0;
label = "Visitor";
type = "userGroup";
constructor() {
super();
}
}
class member extends option{
value = 0.0;
ander = 0.0;
label = "Member";
type = "userGroup";
constructor() {
super();
}
}
class admin extends option {
value = 1.0;
label = "Admin";
type = "userGroup";
constructor() {
super();
}
}
export default class groups {
datatype = 'TEXT';
value = 2.0;
enabled = false;
type = "column"
change() {
var children = this.getChildren();
for(var c = 0; c<children.length; c++) {
var child = children[ c ];
if( child.customElement.selected ) {
this.value = child.customElement.value;
}
}
}
create() {
this.customElement.value = parseFloat( this.value );
// the code here under is redundant, There is still an error, bug that needs to be resolved.
/*
var children = this.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i];
if( child.type == "userGroup" ) {
var childValue = child.value
// todo bug this should be 0.0 but is false
if(! childValue ) {
childValue = 0.0
}
console.log(childValue,parseFloat( this.value ), childValue==parseFloat( this.value ) );
if( childValue == parseFloat( this.value ) ) {
console.log(child.customElement);
child.customElement.setAttribute("selected", "true")
}
}
}
*/
}
member = new member();
admin = new admin();
visitor = new visitor();
}

View File

@@ -0,0 +1,4 @@
import groups from './user.group.js';
export default new groups();

View File

@@ -0,0 +1,22 @@
import option from '/elements/option.js';
export default class visitor extends option{
value = 2.0;
label = "Member";
color = "black";
type = "userGroup";
constructor() {
super();
}
}

View File

@@ -0,0 +1,87 @@
import button from '/elements/button.js';
export default class signinFormButton extends button {
text = "Signin";
float = "right";
marginLeft = 20;
#ifdef ANDROID
//display = "none";
#endif
async click() {
var signin = this.parents("signin");
var username = signin.query("signinUsername").value;
var password = signin.query("signinPassword").value;
var user = await this.parents("signin").signin( username, password );
if( user ) {
if( user.error ) {
user.error = false;
return false;
}
if( user.status == "success" ) {
this.parents("application").minimizeButton.open();
//alert("mooi");
var core = this.getCore();
localStorage.setItem( "username", user.username.value );
localStorage.setItem( "sessionKey", user.sessionKey.value );
core.updatePermissions( user.permissionObjects );
core.setUser( user );
#ifdef ANDROID
#else
//this.parent.hide();
#endif
setTimeout(function() {
//alert("You are now signed in");
});
}
}
}
}

View File

@@ -0,0 +1,26 @@
import button from '/elements/button.js';
export default class cancelButton extends button {
text = "Cancel";
float = "left";
#ifdef ANDROID
#else
display = "none";
#endif
}

View File

@@ -0,0 +1,26 @@
import password from '../user.password.js';
import input from '/elements/input.js';
export default class signinPassword extends password{
scope = "public";
placeholder = "Password";
minLength = 2;
marginLeft = 20;
//keyup() {
// this.parents("signin").signinButton.click();
// console.log(this.parents("signin"));
//}
}

View File

@@ -0,0 +1,25 @@
import username from '../user.username.js';
import input from '/elements/input.js';
export default class signinUsername extends username, input {
placeholder = "Username";
marginLeft = 20;
marginTop = 50;
//keyup() {
//this.parent.signinButton.click();
//}
}

View File

@@ -0,0 +1,309 @@
import user from '/user/user.js';
import label from '/elements/label.js';
import username from './signin.username.js';
import password from './signin.password.js';
import signinButton from './signin.button.js';
import userManager from '/server/userManager.js';
import document from '/unify/document.js';
import unify from '/unify/unify.js';
import groups from '/user/group/user.group.permission.js';
import querySQL from '/unify/querySQL.js';
import header from '/elements/header.js';
import cancelButton from './signin.cancel.button.js';
import page from '/elements/page.js';
import collection from "/unify/collection.js";
import IS from '/unify/sql/IS.js';
#ifdef SERVER
import crypto from "node:crypto";
#endif
class tussenObject{
password = new password();
width = "100%"
}
class buttons{
#ifdef ANDROID
width = "100vw";
position = "absolute"
bottom = "0";
#endif
cancelButton = new cancelButton();
signinButton = new signinButton();
}
class hint{
text = "Hint: You can sign in with username: admin, password: admin."
color = "white"
marginLeft = 22;
fontWeight = "bold"
marginTop = 20;
padding = 20;
background = "#221f1f4f";
borderRadius = 4;
}
export default class signin extends user, page {
_hint = new hint();
padding = 10;
paddingTop = 20;
color = "black";
//paddingTop = "0";
flexDirection = "column";
height = "400px";
layers = 1;
debug = true;
customElement = document.createElement("form");
useCustomElement = true;
display = "flex";
autocomplete = false;
_header = new header("Signin");
//userLabel = new label("Username");
username = new username();
//passwordLabel = new label("Password");
tussenObject = new tussenObject();
buttons = new buttons();
boxMargin;
enableREAD() {
this.hide();
}
createVisitor( client ) {
var table = new user();
table.username.value = "Visitor";
table.id = 0;
table.permissionObjects = userManager.getPermissions( table, client );
return table;
}
node async signin( username, password, sessionKey ) {
var client = this.client;
client.user = this.createVisitor( client );
client.user.error = false;
if( username ) {
var users = new collection( user );
var filter = users.getFilter();
filter.search = IS( filter.username, username );
users.sync();
var currentUser = users.get();
if( currentUser ) {
var hash = currentUser.hash.value;
console.log("password", password);
console.log("try to sign in hash", hash);
if( !password ) {
client.user.error = "password required";
}
if( !hash ) {
client.user.error = "user does not have an hash";
}
var signedIn = false;
var loginMethod = false;
console.log(sessionKey);
if( sessionKey ) {
signedIn = sessionKey === currentUser.sessionKey.value;
loginMethod = "session"
console.log( "signin with sessionKey:", sessionKey, currentUser.sessionKey.value, signedIn );
}
if( password ) {
var encryptHash = await crypto.pbkdf2Sync( password, currentUser.salt.value, 100, 64,'SHA256' ).toString('hex');
if( !signedIn ) {
signedIn = encryptHash === hash;
loginMethod = "password"
console.log( "signin with Password:", encryptHash, hash, signedIn );
}
}
if( signedIn ) {
if( loginMethod != "session" ) {
currentUser.sessionKey.value = crypto.randomBytes( 32 ).toString('base64');
currentUser.save();
currentUser.sessionKey.scope = "public"
}
currentUser.permissionObjects = userManager.getPermissions( currentUser, client );
currentUser.error = false;
client.user = currentUser;
client.user.status = "success";
} else {
client.user.status = "failed";
client.user.error = "password";
}
} else {
client.user.status = "failed";
client.user.error = "username";
}
} else {
client.user.error = "password";
}
global.core.setUserObjects( client.user, client );
global.core.parse( client.user, client );
return client.user;
}
async afterLoad() {
var username = localStorage.getItem( "username" );
var sessionKey = localStorage.getItem( "sessionKey" );
var user = await this.signin( username, false, sessionKey );
console.log("signin ",user);
var core = this.getCore();
core.updatePermissions( user.permissionObjects );
core.setUser( user );
}
permission() {
this.allow( groups.visitor , "PROCESS" );
this.allow( groups.member , "PROCESS" );
this.allow( groups.admin , "PROCESS" );
this.allow( groups.member , "READ" );
this.allow( groups.admin , "READ" );
}
}

View File

@@ -0,0 +1,86 @@
import button from '/elements/button.js';
import tools from '/unify/tools.js';
import document from '/unify/document.js';
export default class signupButton extends button {
text = "Signup";
margin = 6;
async click( event, object ){
var signup = this.parent;
/*
if( !signin.username.isValid() ) {
signin.username.focus();
signin.username.showError( "please fill in a valid username." );
return false;
}
if( !signin.password.isValid() ) {
signin.password.showError("please fill in a valid password.");
signin.password.focus();
return false;
}
if( !signin.passwordAgain.isValid() ) {
signin.passwordAgain.showError("please fill in a valid password check.");
signin.passwordAgain.focus();
return false;
}
*/
var username = signup.username.value;
var password = signup.password.value;
var passwordAgain = signup.passwordAgain.value;
var user = await signup.registerUser( username, password, passwordAgain );
if( user ) {
switch( user.status ) {
case "created_user":
alert("user created you can now sign in.");
break;
case "user_exists":
alert("user already exists.");
break;
}
}
}
}

View File

@@ -0,0 +1,14 @@
import label from '/elements/label.js';
export default class customLabel extends label{
textAlign = "right";
alignItems = "end";
flexDirection = "column";
}

View File

@@ -0,0 +1,11 @@
import inputPassword from '/elements/inputPassword.js';
export default class signupPassword extends inputPassword{
minLength = 7;
useCustomElement = true;
}

View File

@@ -0,0 +1,32 @@
import inputPassword from '/elements/inputPassword.js';
export default class signupPasswordCheck extends inputPassword{
useCustomElement = true;
async keyup( event ){
this.value = event.target.value;
if( this.value == this.parent.password.value ) {
this.border = "#28a745";
this.color = "#495057";
this.shadow = "0px 0px 4px 2px #28a745";
} else {
this.border = "1px solid #dc3545";
this.color = "black";
this.shadow = "0px 0px 4px 2px #dc3545";
}
}
}

View File

@@ -0,0 +1,14 @@
import username from '../user.username.js';
import input from '/elements/input.js';
export default class signUpUsername extends username, input {
propegateEvent = false;
}

View File

@@ -0,0 +1,176 @@
import user from '../user.js';
import username from './signup.username.js';
import password from './signup.password.js';
import passwordCheck from './signup.passwordCheck.js';
import signUpButton from './signup.button.js';
import document from '/unify/document.js';
import groups from '/user/group/user.group.permission.js';
import querySQL from '/unify/querySQL.js';
import adminGroup from '/user/group/user.group.admin.js';
import header from '/elements/header.js';
import page from '/elements/page.js';
import customLabel from "./signup.customLabel.js";
#ifdef SERVER
//import bcrypt from "bcryptjs";
import crypto from "node:crypto";
#endif
export default class signup extends user, page{
layers = 1;
customElement = document.createElement("form");
useCustomElement = true;
debug = true;
gridTemplate = ` "header header " 100px
"userLabel username " 60px
"passwordLabel password " 60px
"passwordAgainLabel passwordAgain " 60px
"empty signUpButton " 60px
`;
paddingRight = 30;
height = "300px";
header = new header("Signup");
// Children
userLabel = new customLabel("Username");
username = new username();
passwordLabel = new customLabel("Password");
password = new password();
passwordAgainLabel = new customLabel("Password again");
passwordAgain = new passwordCheck();
signUpButton = new signUpButton();
flexDirection = "column";
display = "grid";
pbkdf2Async(password, salt, iterations, keylen, digest) {
return new Promise( (res, rej) => {
crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, key) => {
err ? rej(err) : res(key);
});
});
}
node async registerUser( username, password, passwordAgain ) {
/*
// Validation
if( !this.username.isValid() ) {
object.status = "error";
object.error = "please fill in a valid username." ;
return object;
}
*/
var table = this.table;
var users = this.find( "username", username );
var saltRounds = 10;
//var salt = bcrypt.genSaltSync( saltRounds );
//var hash = bcrypt.hashSync( password, salt );
var salt = crypto.randomBytes(32).toString('base64');
var iterations = 100;
if( !password ) {
return false;
}
if( password != passwordAgain ) {
return false;
}
var hash = await crypto.pbkdf2Sync( password, salt, iterations, 64,'SHA256' );
console.log("hash", hash.toString('hex'));
console.log("salt", salt);
if( users.length > 0 ) {
table.status = "user_exists";
return table;
}
table.username.value = username;
table.hash.value = await hash.toString('hex');
table.salt.value = salt;
table.signed.value = true;
table.groups.value = 1;
table.createInstance();
table.save();
table.status = "created_user";
return table;
}
permission() {
this.allow( groups.visitor , "PROCESS" );
this.allow( groups.member , "PROCESS" );
this.allow( groups.admin , "PROCESS" );
}
}

View File

@@ -0,0 +1,10 @@
import column from '/unify/column.js';
export default class email extends column {
}

View File

@@ -0,0 +1,16 @@
import datatype from '/unify/datatype.js';
export default class hash {
datatype = datatype.VARCHAR;
scope = "private";
display = "none";
}

40
application/user/user.js Normal file
View File

@@ -0,0 +1,40 @@
import username from './user.username.js';
import salt from './user.salt.js';
import hash from './user.hash.js';
import sessionKey from './user.sessionKey.js';
import groups from './group/user.group.js';
import table from '/unify/table.js';
import email from './user.email.js';
import collection from "/unify/collection.js";
export default class user extends table {
username = new username();
salt = new salt();
hash = new hash();
sessionKey = new sessionKey();
// Every user needs to have an groups field, This is for the permissions.
groups = new groups();
email = new email();
selectedUsers = new collection( user );
}

View File

@@ -0,0 +1,15 @@
import datatype from '/unify/datatype.js';
import inputPassword from '../elements/inputPassword.js';
export default class password extends inputPassword {
scope = "private";
}

View File

@@ -0,0 +1,12 @@
import datatype from '/unify/datatype.js';
export default class publicKey{
datatype = datatype.VARCHAR;
display = "none";
renderToDOM = false;
}

View File

@@ -0,0 +1,19 @@
import input from '../elements/input.js';
import datatype from '/unify/datatype.js';
export default class salt {
datatype = datatype.VARCHAR;
scope = "private";
value = "";
display = "none";
}

View File

@@ -0,0 +1,16 @@
import datatype from '/unify/datatype.js';
export default class sessionKey {
datatype = datatype.VARCHAR;
scope = "private";
display = "none";
}

View File

@@ -0,0 +1,12 @@
import column from '/unify/column.js';
export default class username extends column {
}

View File

@@ -0,0 +1,29 @@
import groups from '/user/group/user.group.permission.js';
import gridViewColumn from '/elements/gridView/gridView.header.row.column.js';
export default class userListHeaderActions extends gridViewColumn {
text = "Actions";
enableDELETE() {
this.show();
}
disableDELETE() {
this.hide();
}
permission() {
this.allow( groups.admin, "DELETE" );
}
}

View File

@@ -0,0 +1,18 @@
import user from '/user/user.js';
import username from './user.userList.header.username.js';
import actions from './user.userList.header.actions.js';
import gridViewRow from '/elements/gridView/gridView.header.row.js';
export default class userListHeader extends user, gridViewRow {
username = new username();
actions = new actions();
}

View File

@@ -0,0 +1,10 @@
import gridViewColumn from '/elements/gridView/gridView.header.row.column.js';
export default class userListHeaderUsername extends gridViewColumn{
text = "Username";
}

View File

@@ -0,0 +1,32 @@
import button from "/elements/button.js";
import groups from '/user/group/user.group.permission.js';
export default class deleteButton extends button {
text = "Delete";
propegateEvent = false;
async click() {
var sure = confirm("Are you sure you want to delete this item");
if( sure ) {
await this.parent.parent.delete();
this.parent.parent.remove();
}
}
permission() {
this.allow( groups.admin, "DELETE" );
}
}

View File

@@ -0,0 +1,23 @@
import gridViewColumn from '/elements/gridView/gridView.body.row.column.js';
import deleteButton from "./user.userList.item.actions.deleteButton.js"
export default class userListItemActions extends gridViewColumn, gridViewColumn{
useCustomElement = false;
padding = 20;
display = "table-cell";
layers = 1;
paddingLeft = 30;
borderRadius;
deleteButton = new deleteButton();
}

View File

@@ -0,0 +1,96 @@
import user from '/user/user.js';
import username from './user.userList.item.username.js';
import actions from './user.userList.item.actions.js';
import groups from '/user/group/user.group.permission.js';
import gridViewRow from '/elements/gridView/gridView.body.row.js';
export default class userListItem extends user, gridViewRow {
username = new username();
actions = new actions();
cursor = "pointer";
background;
#ifdef MACOS
fontSize = 14;
#endif
#ifdef DARK
mouseHoverColor = "#363333";
#endif
#ifdef LIGHT
mouseHoverColor = "rgb(255 255 255 / 95%)";
#endif
async click() {
this.stateMachine.composeState( "User", this.id );
await this.loadPage( this.id );
}
state async loadPage( id ) {
var rightSide = this.parents("rightSide");
rightSide.hideChildren();
var editUser = rightSide.editUser;
editUser.id = this.id;
editUser.show();
await editUser.sync();
}
mouseover() {
this.background = this.mouseHoverColor;
}
mouseleave() {
this.background = "none";
}
enableDELETE() {
this.actions.show();
}
disableDELETE() {
this.actions.hide();
}
permission() {
this.allow( groups.admin, "DELETE" );
}
}

View File

@@ -0,0 +1,12 @@
import userName from '/user/user.username.js';
import gridViewColumn from '/elements/gridView/gridView.body.row.column.js';
export default class userListItemTitle extends userName, gridViewColumn{
}

View File

@@ -0,0 +1,31 @@
import input from "/elements/input.js";
export default class searchBar extends input {
placeholder = "Search."
placeholderColor = "#8e8e8e"
webkitTextFillColor = "none";
async keyup( event ) {
this.value = this.customElement.value;
var value = this.value;
console.log("search input", value);
var newsItems = this.parent.userTable.body;
newsItems.value = value;
newsItems.sync();
}
}

View File

@@ -0,0 +1,24 @@
import header from '/elements/header.js';
import userTable from './user.userList.table.js';
import search from './search.js';
import page from '/elements/page.js';
export default class editPage extends page {
header = new header("Users");
search = new search();
userTable = new userTable();
flexDirection = "column"
}

View File

@@ -0,0 +1,50 @@
import renderCollection from '/unify/renderCollection.js';
import groups from '/user/group/user.group.permission.js';
import gridViewBody from '/elements/gridView/gridView.body.js';
import OR from '/unify/sql/OR.js';
import AND from '/unify/sql/AND.js';
import LIKE from '/unify/sql/LIKE.js';
export default class userListTableBody extends renderCollection, gridViewBody {
debug = true;
async create() {
await this.sync();
}
preprocess( object ) {
var filter = object.getFilter();
filter.search = LIKE( filter.username, this.value );
//filter.search = OR( LIKE( filter.title, this.value ), LIKE( filter.body, this.value ) );
filter.direction = "desc";
}
permission() {
this.allow( groups.visitor, "READ" );
this.allow( groups.member, "READ" );
this.allow( groups.admin, "READ" );
}
}

View File

@@ -0,0 +1,13 @@
import userListHeaderRow from "./header/user.userList.header.js";
import document from '/unify/document.js';
import gridViewHeader from '/elements/gridView/gridView.header.js';
export default class userListTableHeader extends gridViewHeader {
userListHeaderRow = new userListHeaderRow();
}

View File

@@ -0,0 +1,23 @@
import userListTableHeader from "./user.userList.table.header.js";
import userListTableBody from "./user.userList.table.body.js";
import collection from '/unify/collection.js';
import userListItem from '../userList/item/user.userList.item.js';
import user from '/user/user.js';
import gridView from '/elements/gridView/gridView.js';
export default class userListTable extends gridView{
header = new userListTableHeader();
body = new userListTableBody( userListItem, new collection( user ) );
}