Commit c7632c96 authored by Geovanny's avatar Geovanny

MyHouse Page almost done

parent f83bb449
......@@ -122,7 +122,7 @@ model.acceptRequest = async(user_id, house_id) => {
await db.con.query('COMMIT;');
}
model.refuseRequest = async(user_id) => {
model.rejectRequest = async(user_id) => {
const sql_text = 'DELETE FROM house_requests WHERE user_id = ?;';
await db.con.query(sql_text, [user_id]);
......@@ -140,4 +140,42 @@ model.leaveHouse = async(user_id) => {
await db.con.query(sql_text, [user_id]);
}
model.getMembers = async(house_id) => {
const sql_text = `SELECT u.id, u.username, u.leadership, hr.lk_name as house_role, hr.lk_key
FROM users as u
LEFT JOIN house_role_lk as hr ON hr.lk_key = u.lk_house_role
WHERE u.house_id = ?;`;
const data = await db.con.query(sql_text, [house_id]);
return data;
}
model.modifyMemberRole = async(member_id, role) => {
const sql_text = 'UPDATE users SET lk_house_role = ? WHERE id = ?;';
await db.con.query(sql_text, [role, member_id]);
}
model.changeHouseLiege = async(liege_id, member_id) => {
const sql_text = `UPDATE users SET lk_house_role = 'kng' WHERE id = ?;`;
const sql_text2 = `UPDATE users SET lk_house_role = 'lg' WHERE id = ?;`;
await db.con.query('START TRANSACTION;')
await db.con.query(sql_text, [liege_id]);
await db.con.query(sql_text2, [member_id]);
await db.con.query('COMMIT;');
}
model.getMemberUnits = async(member_id) => {
const sql_txt = `SELECT u.*, uu.unit_level, uu.elite_flg
FROM users as us
LEFT JOIN users_units as uu ON us.id = uu.user_id
LEFT JOIN units as u ON uu.unit_id = u.id
WHERE us.id = ? ORDER BY u.name ASC;`
const data = await db.con.query(sql_txt, [member_id]);
return data;
}
module.exports = model;
\ No newline at end of file
const Koa = require('koa');
const Router = require('@koa/router');
const Koa = require('koa');
const Router = require('@koa/router');
const router = new Router();
const authRouter = new Router();
const houseModel = require('./model');
const router = new Router();
const authRouter = new Router();
const houseModel = require('./model');
const userModel = require('../user/model')
const HOUSE_ROLES = {
LIEGE: 0,
SEN: 1,
MAR: 2,
NOB: 3,
TRE: 4,
KNG: 5
lg: 0,
sen: 1,
mar: 2,
nob: 3,
tre: 4,
kng: 5
}
function checkPermissions(context, ROLE){
......@@ -19,6 +21,10 @@ function checkPermissions(context, ROLE){
context.throw(403, "No Permissions")
}
}
function checkPermissionsNoThrow(context, ROLE){
return ROLE >= context.user.lk_permission_level;
}
function checkHouse(context){
const house_id = context.user.house_id ? context.user.house_id : context.request.body.house_id;
......@@ -26,6 +32,11 @@ function checkHouse(context){
context.throw(403, "Not your House");
}
}
function hasHouse(context){
if(!context.user.house_id){
context.throw(400, 'No house');
}
}
router.get('/all', async (context, next) => {
try{
......@@ -38,6 +49,80 @@ router.get('/all', async (context, next) => {
}
});
authRouter.get('/members', async(context, next) => {
hasHouse(context);
try{
const data = await houseModel.getMembers(context.user.house_id);
context.response.status = 200;
context.response.body = data;
}catch(error){
console.log(error);
context.throw(400, "Failed to get members")
}
});
authRouter.get('/member-units/:member_id', async(context, next) => {
checkPermissions(context, HOUSE_ROLES.sen);
try{
const data = await houseModel.getMemberUnits(context.params.member_id);
context.response.status = 200;
context.response.body = data;
}catch(error){
console.log(error);
context.throw('Failed to get Member Units');
}
});
authRouter.post('/modify-role', async(context, next) => {
hasHouse(context);
const body = context.request.body;
if(!body || !body.member_id || !body.role){
context.throw(400, 'Missing parameters')
}
try{
const member = await userModel.getUserFullFromId(body.member_id);
if(!member){
throw Error('Member does not exists');
}
if(member.house_id !== context.user.house_id){
throw Error('Not on the same house');
}
if(member.lk_permission_level <= context.user.lk_permission_level){
throw Error("Member permission level is high")
}
if(checkPermissionsNoThrow(context, HOUSE_ROLES.lg)){
if(body.role === 'lg'){
await houseModel.changeHouseLiege(context.user.id, member.id);
}else{
await houseModel.modifyMemberRole(member.id, body.role);
}
}else{
if(context.user.lk_house_role < HOUSE_ROLES[body.role]){
await houseModel.modifyHouse(member.id, body.role);
}else{
throw Error("Can't modify to the same level");
}
}
context.response.status = 204;
}catch(error){
console.log(error);
context.throw(400, 'Failed to modify role')
}
})
authRouter.get('/my-permission', async(context, next) => {
if(!context.user.house_id || context.user.lk_permission_level === undefined){
context.throw(400, 'No house');
}
try{
context.response.status = 200;
context.response.body = context.user.lk_permission_level;
}catch(error){
console.log(error);
context.throw(400, 'ERROR');
}
});
authRouter.get('/has-house', async (context, next) => {
try{
if(context.user.house_id){
......@@ -82,9 +167,9 @@ authRouter.delete('/request', async (context, next) => {
}
});
authRouter.get('/requests/:house_id', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.SEN);
authRouter.get('/requests', async (context, next) => {
// checkHouse(context);
checkPermissions(context, HOUSE_ROLES.sen);
try{
const data = await houseModel.getHouseRequests(context.user.house_id);
context.response.status = 200;
......@@ -97,12 +182,13 @@ authRouter.get('/requests/:house_id', async (context, next) => {
authRouter.post('/accept-request', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.SEN);
checkPermissions(context, HOUSE_ROLES.sen);
try{
const body = context.request.body;
if(!body || !body.user_id){
throw Error("No user to accept");
}
console.log(body.user_id);
await houseModel.acceptRequest(body.user_id, context.user.house_id);
context.response.status = 204;
}catch(error){
......@@ -111,28 +197,38 @@ authRouter.post('/accept-request', async (context, next) => {
}
});
authRouter.delete('/refuse-request', async (context, next) => {
authRouter.delete('/reject-request/:user_id', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.SEN);
checkPermissions(context, HOUSE_ROLES.sen);
try{
const body = context.request.body;
if(!body || !body.user_id){
if(!context.params.user_id){
throw Error("No user to refuse");
}
await houseModel.refuseRequest(body.user_id);
await houseModel.rejectRequest(context.params.user_id);
context.response.status = 204;
}catch(error){
console.log(error);
context.throw(400, 'Unable to Accept Request')
context.throw(400, 'Unable to reject Request')
}
});
authRouter.delete('/delete-member/:user_id', async (context, next) => {
checkPermissions(context, HOUSE_ROLES.SEN);
checkPermissions(context, HOUSE_ROLES.sen);
if(context.params.user_id===context.session.user_id){
context.throw(400, "Can't delete yourself");
}
try{
const member = await userModel.getUserFullFromId(context.params.user_id);
if(!member){
throw Error('Member does not exists');
}
if(member.house_id !== context.user.house_id){
throw Error('Not on the same house');
}
if(member.lk_permission_level <= context.user.lk_permission_level){
throw Error("Member permission level is high")
}
await houseModel.deleteMember(context.params.user_id);
context.response.status = 204;
}catch(error){
......@@ -144,7 +240,6 @@ authRouter.delete('/delete-member/:user_id', async (context, next) => {
authRouter.delete('/leave-house', async (context, next) => {
if(context.user.lk_house_role==='lg'){
try{
console.log('asd')
await houseModel.deleteHouse(context.user.house_id, context.session.user_id);
context.response.status = 204;
}catch(error){
......
......@@ -16,7 +16,7 @@
<script src="/navbar/navbar.js"></script>
<content-body>
<table-wrapper class="house_table">
<div class="tab" style="display:none">
<div class="table_header" style="display:none">
<button class="request_house">Send House Request</button>
</div>
<table id="data_table" class="display"></table>
......
......@@ -13,7 +13,7 @@ class HousesView extends EventTarget{
constructor(){
super();
this.request_tab = document.querySelector('.tab');
this.request_tab = document.querySelector('.table_header');
this.request_button = this.request_tab.querySelector('.request_house');
this.houses_table_view = new TableView($('table-wrapper'), house_columns);
......
......@@ -13,7 +13,7 @@
<script src="/navbar/navbar.js"></script>
<content-body>
<center-div>
<div class="tab">
<div class="table_header">
<button class="tablinks active" onclick="changeTab(event, 'Login')">Login</button>
<button class="tablinks" onclick="changeTab(event, 'Register')">Register</button>
</div>
......
import Sync from "./sync.js";
class MyHouseController{
constructor(view){
this.view = view;
this.sync = new Sync();
this.permission_level = 1000;
this.members = [];
this.requests = [];
this.view.addEventListener("participation_attemp", (event) => this.attempParticipate(event.detail));
this.view.addEventListener("member_select", (event) => this.selectMember(event.detail));
this.view.addEventListener("modify_member_role", (event) => this.modifyMemberRole(event.detail.member_id, event.detail.role));
this.view.addEventListener("kick_member", (event) => this.kickMember(event.detail));
this.view.addEventListener("request_select", (event) => this.selectRequest(event.detail));
this.view.addEventListener("accept_request", (event) => this.acceptRequest(event.detail));
this.view.addEventListener("reject_request", (event) => this.rejectRequest(event.detail));
this.refresh();
setInterval(() => {
this.refresh();
}, 10000);
}
async modifyMemberRole(member_id, role){
try{
await this.sync.modifyMemberRole(member_id, role);
alert('Role Modified');
this.refresh();
}catch(error){
console.log(error);
alert('Failed to modify role')
}
}
async kickMember(member_id){
try{
await this.sync.kickMember(member_id);
alert('Member Kicked');
this.refresh();
}catch(error){
console.log(error);
alert('Failed to Kick Member');
}
}
async refresh(){
this.getMembers();
this.getPermissionLevel();
this.getRequests();
}
async acceptRequest(user_id){
try{
await this.sync.acceptRequest(user_id);
alert('Request Accepted');
this.refresh();
}catch(error){
console.log(error);
alert('Failed to Accept Request')
}
}
async rejectRequest(user_id){
try{
await this.sync.rejectRequest(user_id);
alert('Request Refused');
this.refresh();
}catch(error){
console.log(error);
alert('Failed to Refuse Request')
}
}
selectRequest(index){
this.view.selectRequest(this.requests[index]);
}
async selectMember(index){
const member = this.members[index];
try{
const units = await this.sync.getMemberUnits(member.id);
this.view.drawMemberUnitsTable(units);
this.view.selectMember(member);
}catch(error){
console.log(error);
alert('Failed at Selecting Member');
}
}
async getRequests(){
this.requests = [];
try{
this.requests = await this.sync.getRequests();
}catch(error){
console.log(error);
}
this.view.drawRequestsTable(this.requests);
}
async getMembers(){
this.members = [];
try{
this.members = await this.sync.getMembers();
}catch(error){
console.log(error);
// alert('Failed to get Members');
}
this.view.drawMembersTable(this.members);
}
async attempParticipate(decision){
console.log(decision)
}
async getPermissionLevel(){
try{
const permission_level = await this.sync.getPermissionLevel();
if(this.getPermissionLevel !== permission_level){
this.permission_level = permission_level;
this.view.updatePermissions(this.permission_level);
}
}catch(error){
console.log(error);
}
}
}
export default MyHouseController;
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf8"/>
<script src="sugar.js"></script>
<script>Sugar.extend()</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
<script src="./myhouse/module.js" type="module"></script>
<link rel="stylesheet" href="./stylesheets/main.css"/>
</head>
<body>
<nav-placeholder></nav-placeholder>
<script src="/navbar/navbar.js"></script>
<content-body id="my_house">
<div id="area_1">
<war-participation>
<table-wrapper>
<div class="table_header">
<span>Participation:</span>
<button id="yes">Yes</button>
<button id="no">No</button>
<button id="maybe">Maybe</button>
</div>
<table id="data_table" class="display"></table>
</table-wrapper>
</war-participation>
<members-area>
<table-detail style="display: initial;">
<table-wrapper>
<div class="table_header">
<p>Members</p>
</div>
<table id="data_table" class="display"></table>
</table-wrapper>
<detail style="display: none;">
<image class="weapon_img"></image>
<div class="detail_name">
---
</div>
<div>
<label for="roles">Roles:</label>
<select id="role">
</select>
</div>
<div class="detail_buttons">
<button class="delete_button">Kick</button>
<button class="modify_button">Update</button>
</div>
</detail>
</table-detail>
</members-area>
</div>
<div id="area_2">
<requests-area style="display: none;">
<div class="table_header">
<div class="title"><span>House</span></div>
<button id="reject">Reject</button>
<button id="accept">Accept</button>
</div>
<table id="data_table" class="display"></table>
</requests-area>
<member-units style="display: none;">
<div class="table_header">
<div class="title"><span>Units</span></div>
</div>
<table id="data_table" class="display"></table>
</member-units>
</div>
</content-body>
</body>
</html>
const role_options = [
{value: 'lg', text: 'Liege'},
{value: 'sen', text: 'Seneschal'},
{value: 'mar', text: 'Marshall'},
{value: 'nob', text: 'Noble'},
{value: 'tre', text: 'Treasurer'},
{value: 'kng', text: 'Knight'}
]
class MemberDetailView extends EventTarget{
constructor(element){
super();
this.element = element;
this.member = {};
this.fields = {
weapon_img: this.element.querySelector('weapon_img'),
name: this.element.querySelector('.detail_name'),
role_selector: this.element.querySelector('#role'),
update_button: this.element.querySelector('.modify_button'),
delete_button: this.element.querySelector('.delete_button')
}
this.fields.update_button.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("modify_member_role", {detail:{member_id: this.member.id, role: this.fields.role_selector.value}}))
});
this.fields.delete_button.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("kick_member", {detail: this.member.id}));
});
this.disable();
}
updatePermissions(perission_level){
if(perission_level===0){
this.changeRolesOptions(-1);
}else{
this.changeRolesOptions(perission_level);
}
}
changeRolesOptions(start){
var i, L = this.fields.role_selector.options.length - 1;
for(i = L; i >= 0; i--) {
this.fields.role_selector.remove(i);
}
for(var i = start + 1; i<role_options.length; i++){
const opt = document.createElement("option");
opt.value = role_options[i].value;
opt.text = role_options[i].text;
this.fields.role_selector.add(opt);
}
}
show(){
this.element.style.display = ""
}
hide(){
this.element.style.display = "none";
}
selectMember(member){
this.member = member;
if(!this.member){
this.disable();
}else{
this.enable();
this.refresh();
}
}
refresh(){
if(this.member.weapon_img){
this.fields.weapon_img.src = this.member.weapon_img;
}
this.fields.name.innerText = this.member.username;
this.fields.role_selector.value = this.member.lk_key;
}
clear(){
this.fields.weapon_img.src = "";
this.fields.name.innerText = "---";
}
enable(){
this.fields.role_selector.disabled = false;
this.fields.update_button.disabled = false;
this.fields.delete_button.disabled = false;
}
disable(){
this.fields.role_selector.disabled = true;
this.fields.update_button.disabled = true;
this.fields.delete_button.disabled = true;
}
}
export default MemberDetailView;
\ No newline at end of file
import TableView from "../views/table_view.js";
const units_columns = [
{title: 'ID', term: 'id'},
{title: 'Name', term: 'name'},
{title: 'Type', term: 'unit_type'},
{title: 'Level', term: 'unit_level'},
{title: 'Elite', term: 'elit_flg'}
]
class MemberUnitsView extends EventTarget{
constructor(element){
super();
this.element = element;
this.table_view = new TableView(this.element, units_columns);
}
drawTable(data){
console.log(data)
this.table_view.drawTable(data);
}
show(){
this.element.style.display = "";
}
hide(){
this.element.style.display = "none"
}
}
export default MemberUnitsView;
\ No newline at end of file
import TableView from "../views/table_view.js"
import MemberDetailView from "./member_detail_view.js";
const members_columns = [
{title: "ID", term: "id"},
{title: "Name", term: "username"},
{title: "Leadership", term: "leadership"},
{title: "House Role", term: "house_role"}
]
class MembersView extends EventTarget{
constructor(element){
super();
this.element = element;
this.table_detail = this.element.querySelector('table-detail');
this.table_view = new TableView(this.table_detail, members_columns, true);
this.member_detail_view = new MemberDetailView(this.element.querySelector('detail'));
this.table_view.addEventListener("row_click", (event) => {
this.dispatchEvent(new CustomEvent("member_select", {detail: event.detail}));
});
this.member_detail_view.addEventListener("modify_member_role", (event) =>{
this.dispatchEvent(new CustomEvent("modify_member_role", {detail: event.detail}));
});
this.member_detail_view.addEventListener("kick_member", (event) =>{
this.dispatchEvent(new CustomEvent("kick_member", {detail: event.detail}));
});
}
selectMember(member){
this.member_detail_view.selectMember(member);
}
drawTable(data){
this.table_view.drawTable(data);
}
updatePermissions(permission_level){
if(permission_level < 2){
this.member_detail_view.show();
this.table_detail.style.display = "grid"
}else{
this.member_detail_view.hide();
this.table_detail.style.display = "initial";
}
this.member_detail_view.updatePermissions(permission_level);
}
}
export default MembersView
\ No newline at end of file
import MyHouseController from "./controller.js"
import MyHouseView from "./view.js";
if(!document.cookie){
location.replace("/login")
}else{
new MyHouseController(new MyHouseView())
}
\ No newline at end of file
import TableView from "../views/table_view.js";
const participation_column = [
{title: "Name", term: "username"},
{title: "Decision", term: "decision"}
];
class ParticipationView extends EventTarget{