Remove more unused code
This commit is contained in:
parent
60b27d639e
commit
932579ead3
7 changed files with 6 additions and 344 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,6 +17,7 @@ __pycache__/
|
||||||
build/
|
build/
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
|
front-end/dist/
|
||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
import define from '../utils/define.js';
|
|
||||||
import config from "../../config.js";
|
|
||||||
|
|
||||||
const template = () => /*html*/`
|
|
||||||
<form>
|
|
||||||
<h5>Login</h5>
|
|
||||||
<div>
|
|
||||||
<label for="login-email-or-username">Email or Username</label>
|
|
||||||
<div>
|
|
||||||
<input class="form-control" type="text" id="login-email-or-username" autocomplete="email" required="" minlength="3">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="login-password">Password</label>
|
|
||||||
<div>
|
|
||||||
<input type="password" id="login-password" autocomplete="current-password" required="" maxlength="60">
|
|
||||||
<button type="button" disabled="" title="You will not be able to reset your password without an email.">forgot password</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button class="btn btn-secondary" type="submit">Login</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default define('login', class extends HTMLElement {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.loginForm = null;
|
|
||||||
this.emailOrUsernameInput = null;
|
|
||||||
this.passwordInput = null;
|
|
||||||
this.__setup();
|
|
||||||
this.__events();
|
|
||||||
}
|
|
||||||
|
|
||||||
__setup() {
|
|
||||||
this.innerHTML = template();
|
|
||||||
this.loginForm = this.querySelector('form');
|
|
||||||
this.emailOrUsernameInput = this.querySelector('#login-email-or-username');
|
|
||||||
this.passwordInput = this.querySelector('#login-password');
|
|
||||||
}
|
|
||||||
|
|
||||||
__events() {
|
|
||||||
this.loginForm.addEventListener('submit', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.__handleLogin(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
__handleLogin = async () => {
|
|
||||||
const response = await fetch(`${config.publicApiURL}user/login`, {
|
|
||||||
method: 'POST',
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {'Content-Type': 'application/json'},
|
|
||||||
body: JSON.stringify({
|
|
||||||
"username_or_email": this.emailOrUsernameInput.value,
|
|
||||||
"password": this.passwordInput.value,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
if (response.status === 200) {
|
|
||||||
const loginData = await response.json();
|
|
||||||
console.log("Login data", loginData);
|
|
||||||
document.cookie = `jwt=${loginData["jwt"]}; SameSite=Strict`;
|
|
||||||
console.log("Login success");
|
|
||||||
} else {
|
|
||||||
console.log("Login error", response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,184 +0,0 @@
|
||||||
import define from '../../utils/define.js';
|
|
||||||
import config from '../../../config.js';
|
|
||||||
import { globalBus } from '../../utils/events.js';
|
|
||||||
import debounce from '../../utils/debounce.js'
|
|
||||||
|
|
||||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion)').matches;
|
|
||||||
|
|
||||||
const template = () => /*html*/`
|
|
||||||
<form class="search-bar">
|
|
||||||
<i class="ph-magnifying-glass-bold"></i>
|
|
||||||
<input
|
|
||||||
type='search'
|
|
||||||
class='search-bar-input'
|
|
||||||
placeholder='Search on mwmbl...'
|
|
||||||
title='Use "CTRL+K" or "/" to focus.'
|
|
||||||
autocomplete='off'
|
|
||||||
>
|
|
||||||
</form>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default define('search-bar', class extends HTMLElement {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.searchInput = null;
|
|
||||||
this.searchForm = null;
|
|
||||||
this.abortController = new AbortController();
|
|
||||||
this.__setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
__setup() {
|
|
||||||
this.innerHTML = template();
|
|
||||||
this.searchInput = this.querySelector('input');
|
|
||||||
this.searchForm = this.querySelector('form');
|
|
||||||
this.__events();
|
|
||||||
}
|
|
||||||
|
|
||||||
__dispatchSearch({ results = null, error = null }) {
|
|
||||||
const searchEvent = new CustomEvent('search', {
|
|
||||||
detail: {
|
|
||||||
results,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
globalBus.dispatch(searchEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the overall layout of the page.
|
|
||||||
*
|
|
||||||
* `home` centers the search bar on the page.
|
|
||||||
* `compact` raises it to the top and makes room for displaying results.
|
|
||||||
*
|
|
||||||
* @param {'compact' | 'home'} mode
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
__setDisplayMode(mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case 'compact': {
|
|
||||||
document.body.style.paddingTop = '25px';
|
|
||||||
document.querySelector('.search-menu').classList.add('compact');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'home': {
|
|
||||||
document.body.style.paddingTop = '30vh';
|
|
||||||
document.querySelector('.search-menu').classList.remove('compact');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async __executeSearch() {
|
|
||||||
this.abortController.abort();
|
|
||||||
this.abortController = new AbortController();
|
|
||||||
// Get response from API
|
|
||||||
const response = await fetch(`${config.publicApiURL}search?s=${encodeURIComponent(this.searchInput.value)}`, {
|
|
||||||
signal: this.abortController.signal
|
|
||||||
});
|
|
||||||
// Getting results from API
|
|
||||||
const search = await (response).json();
|
|
||||||
return search;
|
|
||||||
}
|
|
||||||
|
|
||||||
__handleSearch = async () => {
|
|
||||||
// Update page title
|
|
||||||
document.title = `MWMBL - ${this.searchInput.value || "Search"}`;
|
|
||||||
|
|
||||||
// Update query params
|
|
||||||
const queryParams = new URLSearchParams(document.location.search);
|
|
||||||
// Sets query param if search value is not empty
|
|
||||||
if (this.searchInput.value) queryParams.set(config.searchQueryParam, this.searchInput.value);
|
|
||||||
else queryParams.delete(config.searchQueryParam);
|
|
||||||
// New URL with query params
|
|
||||||
const newURL =
|
|
||||||
document.location.protocol
|
|
||||||
+ "//"
|
|
||||||
+ document.location.host
|
|
||||||
+ document.location.pathname
|
|
||||||
+ (this.searchInput.value ? '?' : '')
|
|
||||||
+ queryParams.toString();
|
|
||||||
// Replace history state
|
|
||||||
window.history.replaceState({ path: newURL }, '', newURL);
|
|
||||||
|
|
||||||
if (this.searchInput.value) {
|
|
||||||
this.__setDisplayMode('compact')
|
|
||||||
|
|
||||||
try {
|
|
||||||
const search = await this.__executeSearch()
|
|
||||||
// This is a guess at an explanation
|
|
||||||
// Check the searcInput.value before setting the results to prevent
|
|
||||||
// race condition where the user has cleared the search input after
|
|
||||||
// submitting an original search but before the search results have
|
|
||||||
// come back from the API
|
|
||||||
this.__dispatchSearch({ results: this.searchInput.value ? search : null });
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
this.__dispatchSearch({ error })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.__setDisplayMode('home')
|
|
||||||
this.__dispatchSearch({ results: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__events() {
|
|
||||||
/**
|
|
||||||
* Always add the submit event, it makes things feel faster if
|
|
||||||
* someone does not prefer reduced motion and reflexively hits
|
|
||||||
* return once they've finished typing.
|
|
||||||
*/
|
|
||||||
this.searchForm.addEventListener('submit', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.__handleSearch(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only add the "real time" search behavior when the client does
|
|
||||||
* not prefer reduced motion; this prevents the page from changing
|
|
||||||
* while the user is still typing their query.
|
|
||||||
*/
|
|
||||||
if (!prefersReducedMotion) {
|
|
||||||
this.searchInput.addEventListener('input', debounce(this.__handleSearch, 500))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus search bar when pressing `ctrl + k` or `/`
|
|
||||||
document.addEventListener('keydown', (e) => {
|
|
||||||
if ((e.key === 'k' && e.ctrlKey) || e.key === 'Escape') {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Remove the modal if it's visible
|
|
||||||
document.querySelector('.modal').style.display = 'none';
|
|
||||||
|
|
||||||
this.searchInput.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Focus first result when pressing down arrow
|
|
||||||
this.addEventListener('keydown', (e) => {
|
|
||||||
if (e.key === 'ArrowDown' && this.searchInput.value) {
|
|
||||||
e.preventDefault();
|
|
||||||
const focusResultEvent = new CustomEvent('focus-result');
|
|
||||||
globalBus.dispatch(focusResultEvent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
globalBus.on('focus-search', (e) => {
|
|
||||||
this.searchInput.focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
// Focus search input when component is connected
|
|
||||||
this.searchInput.focus();
|
|
||||||
|
|
||||||
const searchQuery = new URLSearchParams(document.location.search).get(config.searchQueryParam);
|
|
||||||
this.searchInput.value = searchQuery;
|
|
||||||
/**
|
|
||||||
* Trigger search handling to coordinate the value pulled from the query string
|
|
||||||
* across the rest of the UI and to actually retrieve the results if the search
|
|
||||||
* value is now non-empty.
|
|
||||||
*/
|
|
||||||
this.__handleSearch();
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,84 +0,0 @@
|
||||||
import define from '../utils/define.js';
|
|
||||||
import config from "../../config.js";
|
|
||||||
|
|
||||||
const template = () => /*html*/`
|
|
||||||
<form>
|
|
||||||
<h5>Register</h5>
|
|
||||||
<div>
|
|
||||||
<label for="register-email">Email</label>
|
|
||||||
<div>
|
|
||||||
<input class="form-control" type="text" id="register-email" autocomplete="email" required="" minlength="3">
|
|
||||||
</div>
|
|
||||||
<label for="register-username">Username</label>
|
|
||||||
<div>
|
|
||||||
<input class="form-control" type="text" id="register-username" autocomplete="username" required="" minlength="3">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="register-password">Password</label>
|
|
||||||
<div>
|
|
||||||
<input type="password" id="register-password" autocomplete="password" required="" maxlength="60">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="register-password">Confirm password</label>
|
|
||||||
<div>
|
|
||||||
<input type="password" id="register-password-verify" autocomplete="confirm password" required="" maxlength="60">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button class="btn btn-secondary" type="submit">Register</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default define('register', class extends HTMLElement {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.registerForm = null;
|
|
||||||
this.emailInput = null;
|
|
||||||
this.usernameInput = null;
|
|
||||||
this.passwordInput = null;
|
|
||||||
this.passwordVerifyInput = null;
|
|
||||||
this.__setup();
|
|
||||||
this.__events();
|
|
||||||
}
|
|
||||||
|
|
||||||
__setup() {
|
|
||||||
this.innerHTML = template();
|
|
||||||
this.registerForm = this.querySelector('form');
|
|
||||||
this.emailInput = this.querySelector('#register-email');
|
|
||||||
this.usernameInput = this.querySelector('#register-username');
|
|
||||||
this.passwordInput = this.querySelector('#register-password');
|
|
||||||
this.passwordVerifyInput = this.querySelector('#register-password-verify');
|
|
||||||
}
|
|
||||||
|
|
||||||
__events() {
|
|
||||||
this.registerForm.addEventListener('submit', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.__handleRegister(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
__handleRegister = async () => {
|
|
||||||
const response = await fetch(`${config.publicApiURL}user/register`, {
|
|
||||||
method: 'POST',
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {'Content-Type': 'application/json'},
|
|
||||||
body: JSON.stringify({
|
|
||||||
"username": this.usernameInput.value,
|
|
||||||
"email": this.emailInput.value,
|
|
||||||
"password": this.passwordInput.value,
|
|
||||||
"password_verify": this.passwordVerifyInput.value,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
if (response.status === 200) {
|
|
||||||
const registerData = await response.json();
|
|
||||||
console.log("Register data", registerData);
|
|
||||||
document.cookie = `jwt=${registerData["jwt"]}; SameSite=Strict`;
|
|
||||||
console.log("Register success");
|
|
||||||
} else {
|
|
||||||
console.log("Register error", response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -53,7 +53,7 @@
|
||||||
<main class="noscript">
|
<main class="noscript">
|
||||||
<img class="brand-icon" src="/static/images/logo.svg" width="40" height="40" alt="mwmbl logo">
|
<img class="brand-icon" src="/static/images/logo.svg" width="40" height="40" alt="mwmbl logo">
|
||||||
<h1>
|
<h1>
|
||||||
Welcome to mwmbl, the free, open-source and non-profit search engine.
|
Welcome to Mwmbl, the free, open-source and non-profit search engine.
|
||||||
</h1>
|
</h1>
|
||||||
<p>This website requires you to support/enable scripts.</p>
|
<p>This website requires you to support/enable scripts.</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -72,10 +72,10 @@
|
||||||
|
|
||||||
<main class="jsonly">
|
<main class="jsonly">
|
||||||
<header class="search-menu">
|
<header class="search-menu">
|
||||||
<ul>
|
<!-- <ul>
|
||||||
<li is="${save}"></li>
|
<li is="${save}"></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div><a href="/accounts/login/">Login</a> <a href="/accounts/signup/">Sign up</a> </div>
|
<div><a href="/accounts/login/">Login</a> <a href="/accounts/signup/">Sign up</a> </div> -->
|
||||||
<div class="branding">
|
<div class="branding">
|
||||||
<img class="brand-icon" src="/static/images/logo.svg" width="40" height="40" alt="mwmbl logo">
|
<img class="brand-icon" src="/static/images/logo.svg" width="40" height="40" alt="mwmbl logo">
|
||||||
<span class="brand-title">MWMBL</span>
|
<span class="brand-title">MWMBL</span>
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
|
|
||||||
if (!redirected) {
|
if (!redirected) {
|
||||||
// Load components only after redirects are checked.
|
// Load components only after redirects are checked.
|
||||||
import('./components/login.js');
|
|
||||||
import('./components/register.js');
|
|
||||||
import("./components/organisms/search-bar.js");
|
|
||||||
import("./components/organisms/results.js");
|
import("./components/organisms/results.js");
|
||||||
import("./components/organisms/footer.js");
|
import("./components/organisms/footer.js");
|
||||||
import("./components/organisms/save.js");
|
import("./components/organisms/save.js");
|
||||||
|
|
|
@ -5,7 +5,8 @@ export default {
|
||||||
base: '/static',
|
base: '/static',
|
||||||
publicDir: '../assets',
|
publicDir: '../assets',
|
||||||
build: {
|
build: {
|
||||||
outDir: '../dist'
|
outDir: '../dist',
|
||||||
|
minify: false
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
legacy({
|
legacy({
|
||||||
|
|
Loading…
Reference in a new issue