Skip to content

Commit

Permalink
Added basic filtering for role and tag
Browse files Browse the repository at this point in the history
  • Loading branch information
clr-li committed Mar 30, 2024
1 parent d93ec3a commit 22b6f35
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 28 deletions.
7 changes: 3 additions & 4 deletions public/components/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,18 @@ export class Popup extends Component {
bottom: 0;
margin: auto;
min-width: 300px;
width: 30%;
width: fit-content;
max-width: var(--max-width);
aspect-ratio: 1/1;
min-height: 300px;
max-height: var(--max-width);
height: fit-content;
background-color: white;
text-align: center;
padding: 5px;
border: 8px solid ${borderColor};
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
padding: 1em;
}
:host:before {
Expand Down
2 changes: 1 addition & 1 deletion public/components/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class Table extends Component {
<label for="filtername">Name: </label>
<input type="text" id="filtername" name="filtername" placeholder="person name"><br>
<type-select label="Event Name:" name="eventName" id="filterEventName" placeholder="select/type event"></type-select>
<type-select label="Event Tags:" name="eventTags" id="filter-event-tags" placeholder="select/type event tag"></type-select>
<type-select label="Event Tag:" name="eventTags" id="filter-event-tags" placeholder="select/type event tag"></type-select>
<label for="filterstart">Start Date: </label>
<input type="date" id="filterstart" name="filterstart">
<label for="filterend">End Date: </label>
Expand Down
1 change: 1 addition & 0 deletions public/stats.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<section>
<h1>Stats</h1>
<type-select id="business-selector" name="businesses" label="Group:"></type-select>
<button id="show-filter" class="button" type="button"><i class="fa-solid fa-filter"></i>&nbsp;Filter</button>
<div class="scroll">
<table id="user-stats-table" class="calendar"></table>
</div>
Expand Down
82 changes: 72 additions & 10 deletions public/stats.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { requireLogin } from './util/Auth.js';
import { GET } from './util/Client.js';
import { initBusinessSelector } from './util/selectors.js';
import { initBusinessSelector, initEventSelector } from './util/selectors.js';
import { sanitizeText } from '../util/util.js';
import { Popup } from './components/Popup.js';
await requireLogin();

const { get: getBusinessId } = await initBusinessSelector('business-selector', async () => {
runMemberStatsTable();
const res = await GET(`/memberattendancedata?businessId=${getBusinessId()}&tag=&role=`);
const memberAttArr = await res.json();
const numRes = await GET(`/countAllEvents?businessId=${getBusinessId()}&tag=`);
const numPastEvents = (await numRes.json())['total_count'];
runMemberStatsTable(memberAttArr, numPastEvents);
});

async function runMemberStatsTable() {
const res = await GET(`/memberattendancedata?businessId=${getBusinessId()}`);
const memberAttArr = await res.json();
async function runMemberStatsTable(memberAttArr, numPastEvents) {
const uidToUserinfo = new Map();
const statuses = ['PRESENT', 'ABSENT', 'LATE', 'EXCUSED'];
const absentAliases = ['ABSENT(self-marked)', 'ABSENT'];

const numRes = await GET(`/countPastEvents?businessId=${getBusinessId()}`);
const numPastEvents = (await numRes.json())['total_count'];
for (let i = 0; i < memberAttArr.length; i++) {
if (!uidToUserinfo.has(memberAttArr[i].user_id)) {
uidToUserinfo.set(memberAttArr[i].user_id, {
Expand Down Expand Up @@ -52,15 +53,76 @@ async function runMemberStatsTable() {
html += `</td>`;

for (const status of statuses) {
html += `<td>${userinfo[status]}</td>`;
html += `<td class="cell">${userinfo[status]}</td>`;
}
html += `<td>${numPastEvents}</td></tr>`;
html += `<td class="cell">${numPastEvents}</td></tr>`;
}
const attendance = document.getElementById('user-stats-table');
attendance.innerHTML = html;
}

runMemberStatsTable();
document.getElementById('show-filter').onclick = async () => {
const filter = new Popup();
filter.innerHTML = /* html */ `
<form id="filterform" class="form" onsubmit="return false;">
<h1>Filter</h1>
<type-select label="Event Tag:" name="event-tag" id="filter-tag" placeholder="select/type event tag"></type-select>
<type-select label="Role:" name="role" id="filter-role" placeholder="select/type role"></type-select>
<!--<label for="filter-start">Start Date: </label>
<input type="date" id="filter-start" name="filter-start">
<label for="filter-end">End Date: </label>
<input type="date" id="filter-end" name="filter-end"><br>-->
<button type="button" value="Submit" id="submit-filterform" class="button">Apply</button>
</form>
`;
document.body.appendChild(filter);
const roleFilter = document.getElementById('filter-role');
const tagFilter = document.getElementById('filter-tag');
setTimeout(() => {
roleFilter.addOption('user', 'user');
roleFilter.addOption('admin', 'admin');
roleFilter.addOption('scanner', 'scanner');
roleFilter.addOption('owner', 'owner');
roleFilter.addOption('moderator', 'moderator');
});
const res = await GET(`/eventtags?businessId=${getBusinessId()}`);
const tags = await res.json();
let tagSet = new Set();
for (let tag of tags) {
tag = tag.tag;
tag.split(',').forEach(tag => {
if (!tagSet.has(tag)) {
tagFilter.addOption(tag, tag);
tagSet.add(tag);
}
});
}
let role = '';
let tag = '';
roleFilter.addEventListener('select', e => {
role = e.detail.value;
});
tagFilter.addEventListener('select', e => {
tag = e.detail.value;
});
document.getElementById('submit-filterform').onclick = async () => {
const start = document.getElementById('filter-start').value;
const end = document.getElementById('filter-end').value;
const res = await GET(
`/memberattendancedata?businessId=${getBusinessId()}&tag=${tag}&role=${role}&start=${start}&end=${end}`,
);
const memberAttArr = await res.json();
const numRes = await GET(`/countAllEvents?businessId=${getBusinessId()}&tag=${tag}`);
const numPastEvents = (await numRes.json())['total_count'];
runMemberStatsTable(memberAttArr, numPastEvents);
};
};

const res = await GET(`/memberattendancedata?businessId=${getBusinessId()}&tag=&role=`);
const memberAttArr = await res.json();
const numRes = await GET(`/countAllEvents?businessId=${getBusinessId()}&tag=`);
const numPastEvents = (await numRes.json())['total_count'];
runMemberStatsTable(memberAttArr, numPastEvents);

// smooth load (keep previous page visible until content loaded)
// requires the body to start with opacity: 0, and this should be the last script run.
Expand Down
27 changes: 19 additions & 8 deletions server/Attendance.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,11 @@ router.get('/memberattendancedata', async function (request, response) {
if (!uid) return;

const businessid = request.query.businessId;
// const starttimestamp = request.query.starttimestamp;
// const endtimestamp = request.query.endtimestamp;
// const role = request.query.role;
let tag = '%,' + request.query.tag + ',%';
const role = request.query.role;
// const start = request.query.start;
// const end = request.query.end;
if (tag === '%,,%') tag = '';
const memberAttendance = await asyncAll(
`
SELECT
Expand All @@ -325,30 +327,38 @@ router.get('/memberattendancedata', async function (request, response) {
AND Events.business_id = ?
AND Records.event_id = Events.id
AND Events.endtimestamp <= ?
AND (? = '' OR Members.role = ?)
AND (? = '' OR Events.tag LIKE ?)
GROUP BY
Records.user_id, Records.status
ORDER BY
Users.name ASC
`,
[businessid, businessid, businessid, Math.round(Date.now() / 1000)],
[businessid, businessid, businessid, Math.round(Date.now() / 1000), role, role, tag, tag],
);

response.send(
memberAttendance.concat(
await asyncAll(
`
SELECT Users.name, Users.id as user_id, Users.email, role, Members.custom_data FROM Members LEFT JOIN Users ON Members.user_id = Users.id WHERE business_id = ? ORDER BY Members.role`,
[businessid],
SELECT Users.name, Users.id as user_id, Users.email, role, Members.custom_data
FROM Members LEFT JOIN Users ON Members.user_id = Users.id
WHERE business_id = ? AND (? = '' OR Members.role = ?)
ORDER BY Members.role`,
[businessid, role, role],
),
),
);
});

router.get('/countPastEvents', async function (request, response) {
router.get('/countAllEvents', async function (request, response) {
const uid = await handleAuth(request, response, request.query.businessId, { read: true });
if (!uid) return;

const businessid = request.query.businessId;
let tag = '%,' + request.query.tag + ',%';
if (tag === '%,,%') tag = '';
console.log(tag);
const num = await asyncGet(
`
SELECT
Expand All @@ -358,8 +368,9 @@ router.get('/countPastEvents', async function (request, response) {
WHERE
business_id = ?
AND endtimestamp <= ?
AND (? = '' OR tag LIKE ?)
`,
[businessid, Math.round(Date.now() / 1000)],
[businessid, Math.round(Date.now() / 1000), tag, tag],
);
response.send(num);
});
Expand Down
9 changes: 4 additions & 5 deletions server/Event.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,11 +311,10 @@ router.get('/eventtags', async (request, response) => {
const uid = await handleAuth(request, response, request.query.businessId, { read: true });
if (!uid) return;

const tags = await asyncAll(`SELECT tag FROM Events WHERE business_id = ?`, [
request.query.businessId,
]);

console.log(tags);
const tags = await asyncAll(
`SELECT DISTINCT tag FROM Events WHERE business_id = ? AND tag <> ''`,
[request.query.businessId],
);
response.send(tags);
});

Expand Down

0 comments on commit 22b6f35

Please sign in to comment.