Skip to content

Commit

Permalink
Move js from .html to separate .js files
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisveness committed Jan 2, 2020
1 parent a5043f0 commit b4f11be
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 268 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ Then open a browser and go to `http://www.localhost:3000` to run the app.
│ │ ├── admin.css
│ │ ├── base.css
│ │ └── www.css
│ ├── js
│ │ ├── .eslintrc.json
│ │ ├── dev-logs.js
│ │ ├── members-edit.js
│ │ ├── password-reset.js
│ │ └── teams-edit.js
│ ├── favicon.ico
│ └── robots.txt
├── test
Expand Down
33 changes: 1 addition & 32 deletions app-admin/templates/dev-logs-access.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,7 @@
td.status4xx { color: #cc3333; }
td.status5xx { color: #cc3333; font-weight: bold; }
</style>
<script>
'use strict';
document.addEventListener('DOMContentLoaded', async function() {
document.querySelectorAll('input,select').forEach(el => el.onchange = function() {
this.form.submit(); // autosubmit form on change
});

document.querySelectorAll('td[data-pathfull]').forEach(el => el.onclick = function() {
// swap displayed text and data-pathfull
const tmp = this.textContent;
this.textContent = this.dataset.pathfull;
this.dataset.pathfull = tmp;
});

// replace ip addresses with domains (asynchronously)
document.querySelectorAll('td.ip-domain').forEach(td => td.style.cursor = 'wait');
const Ips = Array.from(document.querySelectorAll('td.ip-domain')).map(td => td.title);
const IpsDistinct = [ ...new Set(Ips) ];
for (const ip of IpsDistinct) {
const headers = { Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch(`/dev/ajax/ip-domain/${ip}`, { method: 'GET', headers, credentials });
if (response.ok) {
const body = await response.json();
document.querySelectorAll(`td.ip-domain[title="${ip}"]`).forEach(td => td.style.cursor = 'default');
document.querySelectorAll(`td.ip-domain[title="${ip}"]`).forEach(td => td.title = body.domain);
} else {
alert(response.statusText);
}
}
});
</script>
<script src="/js/dev-logs.js"></script>
</head>
<body>

Expand Down
39 changes: 1 addition & 38 deletions app-admin/templates/dev-logs-error.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,7 @@
.toggle { color: #999999; cursor: pointer; }
td.status5xx { color: #cc3333; font-weight: bold; }
</style>
<script>
'use strict';
document.addEventListener('DOMContentLoaded', async function() {
document.querySelectorAll('input,select').forEach(el => el.onchange = function() {
this.form.submit(); // autosubmit form on change
});

document.querySelectorAll('td[data-pathfull]').forEach(el => el.onclick = function() {
// swap displayed text and data-pathfull
const tmp = this.textContent;
this.textContent = this.dataset.pathfull;
this.dataset.pathfull = tmp;
});

// toggle stack trace displays
document.querySelectorAll('.toggle').forEach(el => el.onclick = function() {
this.parentElement.nextElementSibling.classList.toggle('hide');
this.textContent = this.textContent=='▼' ? '▲' : '▼';
});

// replace ip addresses with domains (asynchronously)
document.querySelectorAll('td.ip-domain').forEach(td => td.style.cursor = 'wait');
const Ips = Array.from(document.querySelectorAll('td.ip-domain')).map(td => td.title);
const IpsDistinct = [ ...new Set(Ips) ];
for (const ip of IpsDistinct) {
const headers = { Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch(`/dev/ajax/ip-domain/${ip}`, { method: 'GET', headers, credentials });
if (response.ok) {
const body = await response.json();
document.querySelectorAll(`td.ip-domain[title="${ip}"]`).forEach(td => td.style.cursor = 'default');
document.querySelectorAll(`td.ip-domain[title="${ip}"]`).forEach(td => td.title = body.domain);
} else {
alert(response.statusText);
}
}
});
</script>
<script src="/js/dev-logs.js"></script>
</head>
<body>

Expand Down
122 changes: 26 additions & 96 deletions app-admin/templates/members-edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,79 +12,9 @@
table button { background: none; border: none; padding: 0; }
table button:hover { cursor: pointer; }
</style>
<script src="/js/members-edit.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async function() {
'use strict';
var doc = document; doc.qrySel = doc.querySelector; doc.qrySelAll = doc.querySelectorAll;

doc.qrySel('button.add-membership').onclick = function() {
const select = doc.qrySel('select.add-membership');
select.classList.toggle('hide');
select.focus();
};

doc.qrySel('select.add-membership').onchange = addMembership;

doc.qrySelAll('button.delete-membership').forEach(button => button.onclick = deleteMembership);

async function addMembership(event) {
const select = event.target;
var values = JSON.stringify({
MemberId: {{MemberId}},
TeamId: this.value,
JoinedOn: new Date().toISOString().replace('T',' ').split('.')[0],
});
const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch('/ajax/team-members', { method: 'POST', body: values, headers, credentials });
if (response.ok) {
// add new row (cloned from 1st membership row), remove entry from select
const body = await response.json();
const thisRow = select.closest('tr');
if (thisRow.nextElementSibling) {
const newRow = thisRow.nextElementSibling.cloneNode(true);
newRow.id = select.value;
newRow.children[0].textContent = select.options[select.selectedIndex].label;
newRow.querySelector('button').value = body.TeamMemberId;
newRow.querySelector('button').onclick = deleteMembership; // onclick doesn't get cloned
thisRow.insertAdjacentElement('afterend', newRow);
select.remove(select.selectedIndex);
select.classList.add('hide');
} else {
// no tr to clone - cop out & reload page for now...
window.location.reload();
}
} else {
alert(response.statusText)
}
};

async function deleteMembership(event) {
const button = event.target;
const teamMembershipId = button.value;
const headers = { Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch('/ajax/team-members/'+teamMembershipId, { method: 'DELETE', headers, credentials });
if (response.ok) {
const thisRow = button.closest('tr');
const teamId = thisRow.id;
const teamName = thisRow.children[0].textContent;
const selector = button.closest('table').querySelector('select');
const opt = document.createElement('option');
opt.value = teamId;
opt.text = teamName;
selector.add(opt);
thisRow.remove();
} else {
alert(response.statusText)
}
}

// escape will hide 'add-membership' select if it is displayed
document.onkeyup = function(event) {
if (event.key == 'Escape') doc.qrySel('select.add-membership').classList.add('hide');
}
});
const memberId = {{MemberId}};
</script>
</head>
<body>
Expand All @@ -99,30 +29,30 @@ <h1>Edit member</h1>

{{>errpartial}}

<form method="post">
<ul>
<li>
<label for="Firstname">First name</label>
<input name="Firstname" id="Firstname" value="{{Firstname}}" autofocus>
</li>
<li>
<label for="Lastname">Last name</label>
<input name="Lastname" id="Lastname" value="{{Lastname}}">
</li>
<li>
<label for="Email">E-mail</label>
<input name="Email" id="Email" type="email" value="{{Email}}" required>
</li>
<li>
<label for="Active">Active</label>
<input name="Active" id="Active" type="checkbox" {{#if Active}}checked{{/if}}>
</li>
<li>
<label></label>
<button type="submit" class="fa fa-check-square-o green" title="Update"></button>
</li>
</ul>
</form>
<form method="post">
<ul>
<li>
<label for="Firstname">First name</label>
<input name="Firstname" id="Firstname" value="{{Firstname}}" autofocus>
</li>
<li>
<label for="Lastname">Last name</label>
<input name="Lastname" id="Lastname" value="{{Lastname}}">
</li>
<li>
<label for="Email">E-mail</label>
<input name="Email" id="Email" type="email" value="{{Email}}" required>
</li>
<li>
<label for="Active">Active</label>
<input name="Active" id="Active" type="checkbox" {{#if Active}}checked{{/if}}>
</li>
<li>
<label></label>
<button type="submit" class="fa fa-check-square-o green" title="Update"></button>
</li>
</ul>
</form>

<h2>Teams</h2>

Expand Down
21 changes: 3 additions & 18 deletions app-admin/templates/password-reset.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,7 @@
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="/css/admin.css">
<script>
'use strict';
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#password').onsubmit = validatePwMatch(this);
document.querySelector('#password-confirm').onsubmit = validatePwMatch(this);
});

function validatePwMatch(input) {
if (input.setCustomValidity == undefined) return;
var err = 'Passwords must match';
var ok = input.form.password.value == input.form.passwordConfirm.value;
input.form.password.setCustomValidity(''); // reset default
input.form.passwordConfirm.setCustomValidity(''); // reset default
input.setCustomValidity(ok ? '' : err); // confirm match
}
</script>
<script src="/js/password-reset.js"></script>
</head>
<body>

Expand All @@ -47,11 +32,11 @@ <h1>Password Reset</h1>
<ul>
<li>
<label for="password">New password</label>
<input name="password" id="password" type="password" autofocus class="w16" oninput="validatePwMatch(this)">
<input name="password" id="password" type="password" autofocus class="w16">
</li>
<li>
<label for="passwordConfirm">Confirm password</label>
<input name="passwordConfirm" id="passwordConfirm" type="password" class="w16" oninput="validatePwMatch(this)">
<input name="passwordConfirm" id="passwordConfirm" type="password" class="w16">
</li>
<li>
<label></label>
Expand Down
98 changes: 14 additions & 84 deletions app-admin/templates/teams-edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,79 +12,9 @@
table button { background: none; border: none; padding: 0; }
table button:hover { cursor: pointer; }
</style>
<script src="/js/teams-edit.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async function() {
'use strict';
var doc = document; doc.qrySel = doc.querySelector; doc.qrySelAll = doc.querySelectorAll;

doc.qrySel('button.add-membership').onclick = function() {
const select = doc.qrySel('select.add-membership');
select.classList.toggle('hide');
select.focus();
};

doc.qrySel('select.add-membership').onchange = addMembership;

doc.qrySelAll('button.delete-membership').forEach(button => button.onclick = deleteMembership);

async function addMembership(event) {
const select = event.target;
var values = JSON.stringify({
TeamId: {{TeamId}},
MemberId: this.value,
JoinedOn: new Date().toISOString().replace('T',' ').split('.')[0],
});
const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch('/ajax/team-members', { method: 'POST', body: values, headers, credentials });
if (response.ok) {
// add new row (cloned from 1st membership row), remove entry from select
const body = await response.json();
const thisRow = select.closest('tr');
if (thisRow.nextElementSibling) {
const newRow = thisRow.nextElementSibling.cloneNode(true);
newRow.id = select.value;
newRow.children[0].textContent = select.options[select.selectedIndex].label;
newRow.querySelector('button').value = body.TeamMemberId;
newRow.querySelector('button').onclick = deleteMembership; // onclick doesn't get cloned
thisRow.insertAdjacentElement('afterend', newRow);
select.remove(select.selectedIndex);
select.classList.add('hide');
} else {
// no tr to clone - cop out & reload page for now...
window.location.reload();
}
} else {
alert(response.statusText)
}
};

async function deleteMembership(event) {
const button = event.target;
const teamMembershipId = button.value;
const headers = { Accept: 'application/json' };
const credentials = 'same-origin';
const response = await fetch('/ajax/team-members/'+teamMembershipId, { method: 'DELETE', headers, credentials });
if (response.ok) {
const thisRow = button.closest('tr');
const memberId = thisRow.id;
const memberName = thisRow.children[0].textContent;
const selector = button.closest('table').querySelector('select');
const opt = document.createElement('option');
opt.value = memberId;
opt.text = memberName;
selector.add(opt);
thisRow.remove();
} else {
alert(response.statusText)
}
}

// escape will hide 'add-membership' select if it is displayed
document.onkeyup = function(event) {
if (event.key == 'Escape') doc.qrySel('select.add-membership').classList.add('hide');
}
});
const teamId = {{TeamId}};
</script>
</head>
<body>
Expand All @@ -99,18 +29,18 @@ <h1>Edit team</h1>

{{>errpartial}}

<form method="post">
<ul>
<li>
<label for="Name">Name</label>
<input name="Name" id="Name" value="{{Name}}" required autofocus>
</li>
<li>
<label></label>
<button type="submit" class="fa fa-check-square-o green" title="Update"></button>
</li>
</ul>
</form>
<form method="post">
<ul>
<li>
<label for="Name">Name</label>
<input name="Name" id="Name" value="{{Name}}" required autofocus>
</li>
<li>
<label></label>
<button type="submit" class="fa fa-check-square-o green" title="Update"></button>
</li>
</ul>
</form>

<h2>Members</h2>

Expand Down
8 changes: 8 additions & 0 deletions public/js/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"env": {
"browser": true
},
"parserOptions": {
"sourceType": "script"
}
}
Loading

0 comments on commit b4f11be

Please sign in to comment.