Compare commits

...

4 Commits

12 changed files with 190 additions and 8 deletions

View File

@ -69,7 +69,11 @@
</div>
</section>
<a id="settingsButton" class="button">Settings</a>
<div id="headerMenu">
<a id="settingsButton" class="button">Settings</a>
<a id="loginCreateAccountButton" class="button">Log In&nbsp;/ Create Account</a>
</div>
<div style="clear:both;"></div>
</header>
<main>
@ -314,6 +318,10 @@
</p>
</div>
</div>
<p>
<a class="red button" id="deleteDictionaryButton">Delete Dictionary</a><br>
<small>This will permanently delete your current dictionary, and it will not be possible to return it if you have not backed it up!</small>
</p>
</section>
<footer>

21
src/js/account/helpers.js Normal file
View File

@ -0,0 +1,21 @@
export function request (data = {}, success = () => {}, error = () => {}, fail = () => {}) {
fetch('./account/', {
method: 'POST', // or 'PUT'
body: JSON.stringify(data), // data can be `string` or {object}!
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
}).then(res => res.json())
.then(response => {
console.log('Success:', JSON.stringify(response));
if (response.error) {
error(response);
}
success(response);
})
.catch(err => {
console.error('Request Error:', err);
fail(err);
});
}

7
src/js/account/index.js Normal file
View File

@ -0,0 +1,7 @@
import '../../scss/Account/main.scss';
import { renderLoginForm } from "./render";
export function showLoginForm() {
renderLoginForm();
}

25
src/js/account/login.js Normal file
View File

@ -0,0 +1,25 @@
import { request } from "./helpers";
export function logIn() {
const email = document.getElementById('loginEmail').value.trim(),
password = document.getElementById('loginPassword').value.trim();
const loginErrorMessages = document.getElementById('loginErrorMessages');
let errorHTML = '';
if (email === '') {
errorHTML += '<p class="bold red">Please enter your email address.</p>';
}
if (password === '') {
errorHTML += '<p class="bold red">Please enter your password.</p>';
}
loginErrorMessages.innerHTML = errorHTML;
if (errorHTML !== '') {
request({
action: 'login',
email,
password,
});
}
}

52
src/js/account/render.js Normal file
View File

@ -0,0 +1,52 @@
import { setupLoginModal } from "./setupListeners";
export function renderLoginForm() {
const loginModal = document.createElement('section');
loginModal.classList.add('modal');
loginModal.id = 'loginModal';
loginModal.innerHTML = `<div class="modal-background"></div>
<div class="modal-content"><a class="close-button">&times;&#xFE0E;</a>
<section>
<div class="split two">
<div>
<h2>Log In</h2>
<label>Email<br>
<input type="email" required id="loginEmail">
</label>
<label>Password<br>
<input type="password" required id="loginPassword">
</label>
<section id="loginErrorMessages"></section>
<a id="loginSubmit" class="button">Log In</a><br>
<a id="forgotPasswordButton" class="small button">Forgot Password?</a>
</div>
<div>
<h2>Create a New Account</h2>
<p>Creating an account allows you to save and switch between as many dictionaries as you need and access them from any device for free! If you have a dictionary you've been working on loaded already, it will automatically be uploaded to your account when you log in for the first time.</p>
<p>Plus if you allow us to send you emails, we'll make sure that you're the first to hear about any new features that get added or if any of our policies change for any reason. We'll never spam you or sell your information.</p>
<p>By creating an account, you are indicating that you agree to the Terms of Service and that you understand Lexiconga's Privacy Policy.</p>
<label>Email<br>
<input type="email" id="createNewEmail">
</label>
<label>Password<br>
<input type="password" id="createNewPassword">
</label>
<label>Confirm Password<br>
<input type="password" id="createNewConfirm">
</label>
<label>Public Name<br>
<input type="text" id="createNewPublicName">
</label>
<label>Allow Emails
<input type="checkbox" id="createNewAllowEmails">
</label>
<a id="createAccountSubmit" class="button">Create Account</a>
</div>
</div>
</section>
</div>`;
document.body.appendChild(loginModal);
setupLoginModal(loginModal);
}

View File

@ -0,0 +1,12 @@
import { logIn } from "./login";
export function setupLoginModal(modal) {
const closeElements = modal.querySelectorAll('.modal-background, .close-button');
Array.from(closeElements).forEach(close => {
close.addEventListener('click', () => {
modal.parentElement.removeChild(modal);
});
});
document.getElementById('loginSubmit').addEventListener('click', logIn);
}

View File

@ -94,6 +94,26 @@ export function clearDictionary() {
window.currentDictionary = cloneObject(DEFAULT_DICTIONARY);
}
export function deleteDictionary() {
clearDictionary();
saveDictionary();
addMessage('Dictionary Deleted!');
renderAll();
}
export function confirmDeleteDictionary() {
if (confirm(`Are you sure you want to delete your ${window.currentDictionary.name} ${window.currentDictionary.specification}?\n\nThis cannot be undone!`)) {
const input = prompt(`If you really want to delete your ${window.currentDictionary.name} ${window.currentDictionary.specification} please type DELETE in the text box.\n\nAfter you confirm, cour dicitonary will be PERMANENTLY AND IRRETRIEVABLY DESTROYED!`);
console.log(input);
if (input === 'DELETE') {
deleteDictionary();
document.getElementById('editModal').style.display = 'none';
} else {
alert('Your dictionary was NOT deleted');
}
}
}
export function importDictionary() {
const importDictionaryField = document.getElementById('importDictionaryFile');

View File

@ -1,7 +1,7 @@
import {showSection, hideDetailsPanel} from './displayToggles';
import { renderWords, renderEditForm, renderMaximizedTextbox, renderInfoModal, renderIPATable } from './render';
import { confirmEditWord, cancelEditWord, confirmDeleteWord, submitWordForm } from './wordManagement';
import { openEditModal, saveEditModal, saveAndCloseEditModal, exportDictionary, exportWords, importDictionary, importWords } from './dictionaryManagement';
import { openEditModal, saveEditModal, saveAndCloseEditModal, exportDictionary, exportWords, importDictionary, importWords, confirmDeleteDictionary } from './dictionaryManagement';
import { goToNextPage, goToPreviousPage, goToPage } from './pagination';
import { insertAtCursor, getInputSelection, setSelectionRange } from './StackOverflow/inputCursorManagement';
import { usePhondueDigraphs } from './KeyboardFire/phondue/ipaField';
@ -11,8 +11,7 @@ import { showSearchModal, clearSearchText } from './search';
export default function setupListeners() {
setupDetailsTabs();
setupSearchBar();
setupSettingsModal();
setupHeaderButtons();
setupWordForm();
setupMobileWordFormButton();
setupInfoButtons();
@ -21,6 +20,17 @@ export default function setupListeners() {
}
}
export function setupHeaderButtons() {
setupSearchBar();
setupSettingsModal();
document.getElementById('loginCreateAccountButton').addEventListener('click', () => {
import('./account/index.js').then(account => {
account.showLoginForm();
});
});
}
function setupDetailsTabs() {
const tabs = document.querySelectorAll('#detailsSection nav li');
tabs.forEach(tab => {
@ -80,12 +90,13 @@ function setupEditFormInteractions() {
}
function setupEditFormButtons() {
document.getElementById('editSave').addEventListener('click', () => saveEditModal());
document.getElementById('editSaveAndClose').addEventListener('click', () => saveAndCloseEditModal());
document.getElementById('editSave').addEventListener('click', saveEditModal);
document.getElementById('editSaveAndClose').addEventListener('click', saveAndCloseEditModal);
document.getElementById('importDictionaryFile').addEventListener('change', importDictionary);
document.getElementById('importWordsCSV').addEventListener('change', importWords);
document.getElementById('exportDictionaryButton').addEventListener('click', exportDictionary);
document.getElementById('exportWordsButton').addEventListener('click', exportWords);
document.getElementById('deleteDictionaryButton').addEventListener('click', confirmDeleteDictionary);
setupMaximizeButtons();
}

View File

@ -0,0 +1,16 @@
#loginModal {
.modal-content {
padding: $general-padding;
width: 1000px;
section {
overflow-y: auto;
height: 100%;
p {
font-size: 10pt;
line-height: 12pt;
}
}
}
}

View File

@ -0,0 +1,3 @@
@import '../variables';
@import './structure';

View File

@ -77,8 +77,14 @@
}
}
#settingsButton {
#headerMenu {
display: block;
float: right;
a {
display: inline-block;
margin-left: 5px;
}
}
}
@ -290,7 +296,7 @@ $nav-font-height: 16px;
.maximize-modal {
section {
top: ($general-padding * 2) + $nav-font-height + 13px;;
top: ($general-padding * 2) + $nav-font-height + 15px;
bottom: ($general-padding * 2) + $nav-font-height + 10px;
overflow: hidden;
padding: 0;

View File

@ -8,6 +8,7 @@
#openSearchModal {
width: 40%;
margin-bottom: 10px;
}
#searchModal {