Compare commits

...

4 Commits

Author SHA1 Message Date
Robbie Antenesse 0f1a7d2f09 Force local project database user/password setup 2019-05-17 12:52:20 -06:00
Robbie Antenesse 6a4d9be05a Get logging in mostly working;
Does not return user data for some reason.
2019-05-17 12:23:40 -06:00
Robbie Antenesse 90bdd804fe Fix watch-php script needing quotes 2019-05-17 12:22:11 -06:00
Robbie Antenesse 502065b08a Update sql types; Add html input maxlength 2019-05-17 11:45:37 -06:00
10 changed files with 116 additions and 45 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
node_modules/
.cache/
dist/
vendor/
vendor/
src/php/api/config.php

View File

@ -81,17 +81,17 @@
<div id="mobileWordFormShow">+</div>
<form id="wordForm">
<label>Word<span class="red">*</span><br>
<input id="wordName">
<input id="wordName" maxlength="200">
</label>
<label>Pronunciation<a class="label-button ipa-table-button">IPA Chart</a><br>
<input id="wordPronunciation" class="ipa-field"><br>
<input id="wordPronunciation" class="ipa-field" maxlength="200"><br>
<a class="label-help-button ipa-field-help-button">Field Help</a>
</label>
<label>Part of Speech<br>
<select id="wordPartOfSpeech" class="part-of-speech-select"></select>
</label>
<label>Definition<span class="red">*</span><br>
<input id="wordDefinition" placeholder="Equivalent words">
<input id="wordDefinition" maxlength="2500" placeholder="Equivalent words">
</label>
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
<textarea id="wordDetails" placeholder="Markdown formatting allowed"></textarea>
@ -193,10 +193,10 @@
</nav>
<section id="editDescriptionTab">
<label>Name<br>
<input id="editName">
<input id="editName" maxlength="50">
</label>
<label>Specification<br>
<input id="editSpecification">
<input id="editSpecification" maxlength="50">
</label>
<label>Description<a class="label-button maximize-button">Maximize</a><br>
<textarea id="editDescription"></textarea>
@ -205,7 +205,7 @@
<section id="editDetailsTab" style="display:none;">
<label>Parts of Speech <small>(Comma Separated List)</small><br>
<input id="editPartsOfSpeech">
<input id="editPartsOfSpeech" maxlength="2500" placeholder="Noun,Adjective,Verb">
</label>
<label>Alphabetical Order <small>(Comma Separated List. Include every letter!)</small><br>
<input id="editAlphabeticalOrder" disabled value="English Alphabet">
@ -215,7 +215,7 @@
<div>
<label>Consonants<br>
<small>(Space separated list)</small><br>
<input id="editConsonants" class="ipa-field" placeholder="p b m n t ..."><br>
<input id="editConsonants" class="ipa-field" maxlength="100" placeholder="p b m n t ..."><br>
<a class="label-help-button ipa-field-help-button">Field Help</a>
<a class="label-button ipa-table-button">IPA Chart</a>
</label>
@ -223,7 +223,7 @@
<div>
<label>Vowels<br>
<small>(Space separated list)</small><br>
<input id="editVowels" class="ipa-field" placeholder="æ u e ɪ ..."><br>
<input id="editVowels" class="ipa-field" maxlength="100" placeholder="æ u e ɪ ..."><br>
<a class="label-help-button ipa-field-help-button">Field Help</a>
<a class="label-button ipa-table-button">IPA Chart</a>
</label>
@ -231,7 +231,7 @@
<div>
<label>Polyphthongs&nbsp;/ Blends<br>
<small>(Space separated list)</small><br>
<input id="editBlends" class="ipa-field" placeholder="ai ou ue ..."><br>
<input id="editBlends" class="ipa-field" maxlength="100" placeholder="ai ou ue ..."><br>
<a class="label-help-button ipa-field-help-button">Field Help</a>
<a class="label-button ipa-table-button">IPA Chart</a>
</label>
@ -241,29 +241,32 @@
<div class="split three">
<div>
<label>Onset<br>
<input id="editOnset">
<small>(Comma separated list)</small><br>
<input id="editOnset" maxlength="100" placeholder="Consonants,Vowels">
</label>
</div>
<div>
<label>Nucleus<br>
<input id="editNucleus">
<small>(Comma separated list)</small><br>
<input id="editNucleus" maxlength="100" placeholder="Vowels,Blends">
</label>
</div>
<div>
<label>Coda<br>
<input id="editCoda">
<small>(Comma separated list)</small><br>
<input id="editCoda" maxlength="100" placeholder="Any">
</label>
</div>
</div>
<label>Exceptions<br>
<label>Exceptions <small>(Markdown-enabled)</small><br>
<textarea id="editExceptions"></textarea>
</label>
<h3>Orthography</h3>
<label>Notes<a class="label-button maximize-button">Maximize</a><br>
<label>Notes <small>(Markdown-enabled)</small><a class="label-button maximize-button">Maximize</a><br>
<textarea id="editOrthography"></textarea>
</label>
<h3>Grammar</h3>
<label>Notes<a class="label-button maximize-button">Maximize</a><br>
<label>Notes <small>(Markdown-enabled)</small><a class="label-button maximize-button">Maximize</a><br>
<textarea id="editGrammar"></textarea>
</label>
</section>

View File

@ -9,7 +9,7 @@
"scripts": {
"start": "concurrently \"npm run watch-js\" \"npm run watch-php\"",
"watch-js": "parcel watch index.html --public-url ./",
"watch-php": "cpx src/php/**/* dist -v -w",
"watch-php": "cpx \"src/php/**/*\" dist -v -w",
"bundle": "parcel build index.html && cpx src/php/**/* dist",
"serve-frontend-only": "parcel index.html",
"clear": "npm run clear-dist && npm run clear-cache",

View File

@ -1,5 +1,7 @@
import { request } from "./helpers";
import { addMessage } from "../utilities";
import { setupLogoutButton } from "./setupListeners";
import { renderAccountSettings } from "./render";
export function logIn() {
const email = document.getElementById('loginEmail').value.trim(),
@ -16,12 +18,24 @@ export function logIn() {
loginErrorMessages.innerHTML = errorHTML;
if (errorHTML !== '') {
if (errorHTML === '') {
request({
action: 'login',
email,
password,
});
}, successData => {
console.log(successData);
}, errorData => {
errorHTML += errorData;
}).then(() => {
createAccountErrorMessages.innerHTML = errorHTML;
if (errorHTML === '') {
const loginModal = document.getElementById('loginModal');
loginModal.parentElement.removeChild(loginModal);
triggerLoginChanges();
addMessage(`Welcome! You are logged in.`);
}
}).catch(err => console.error(err));
}
}
@ -79,6 +93,7 @@ export function createAccount() {
if (errorHTML === '') {
const loginModal = document.getElementById('loginModal');
loginModal.parentElement.removeChild(loginModal);
triggerLoginChanges();
addMessage('Account Created Successfully!');
addMessage(`Welcome${publicName !== '' ? ', ' + publicName : ''}! You are logged in.`);
}
@ -86,4 +101,17 @@ export function createAccount() {
}
}).catch(err => console.error(err));
}
}
export function triggerLoginChanges() {
const loginButton = document.getElementById('loginCreateAccountButton')
const logoutButton = document.createElement('a');
logoutButton.classList.add('button');
logoutButton.id = 'logoutButton';
logoutButton.innerHTML = 'Log Out';
loginButton.parentElement.appendChild(logoutButton);
loginButton.parentElement.removeChild(loginButton);
setupLogoutButton(logoutButton);
renderAccountSettings();
}

View File

@ -11,10 +11,10 @@ export function renderLoginForm() {
<div>
<h2>Log In</h2>
<label>Email<br>
<input type="email" required id="loginEmail">
<input type="email" required id="loginEmail" maxlength="100">
</label>
<label>Password<br>
<input type="password" required id="loginPassword">
<input type="password" required id="loginPassword" maxlength="100">
</label>
<section id="loginErrorMessages"></section>
<a id="loginSubmit" class="button">Log In</a><br>
@ -26,16 +26,16 @@ export function renderLoginForm() {
<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">
<input type="email" id="createNewEmail" maxlength="100">
</label>
<label>Password<br>
<input type="password" id="createNewPassword">
<input type="password" id="createNewPassword" maxlength="100">
</label>
<label>Confirm Password<br>
<input type="password" id="createNewConfirm">
<input type="password" id="createNewConfirm" maxlength="100">
</label>
<label>Public Name<br>
<input type="text" id="createNewPublicName">
<input type="text" id="createNewPublicName" maxlength="50">
</label>
<label>Allow Emails
<input type="checkbox" id="createNewAllowEmails">
@ -50,4 +50,27 @@ export function renderLoginForm() {
document.body.appendChild(loginModal);
setupLoginModal(loginModal);
}
export function renderAccountSettings() {
const accountSettingsColumn = document.getElementById('accountSettings');
const accountSettingsHTML = `<h3>Account Settings</h3>
<label>Email Address<br><input id="accountSettingsEmail" required maxlength="100"></label>
<label>Public Name<br><input id="accountSettingsPublicName" placeholder="Someone" maxlength="50"></label>
<label>Allow Emails <input type="checkbox" id="accountSettingsAllowEmails"></label>
<label>Change Dictionary<br><select id="accountSettingsChangeDictionary"></select></label>
<h4>Request Your Data</h4>
<p>
Per your <a href="https://www.eugdpr.org/" target="_blank">GDPR</a> rights in Articles 1315 and 20, we allow you to request any and all data we have stored about you. The only data we have about you personally is your email address and your Public Name, if you decided to set one. All other data (your Dictionary data) is visible and accessible via the Export button under your Dictionary's Settings. Send an email to help@lexicon.ga to request your information.
</p>
<h4>Delete Your Account</h4>
<p>
Per your <a href="https://www.eugdpr.org/" target="_blank">GDPR</a> rights in Articles 17, if you wish for your account to be deleted, please contact us at help@lexicon.ga, and we will delete your account and all associated dictionaries and words as quickly as possible. Note that you can delete dictionaries yourself via your Dictionary's Settings.
</p>
<p>
Anything that is deleted from our system is permanently and irretrievably removed from our system and cannot be restored, though search engines or internet archives may retain a cached version of your content (there is nothing we can do about this, and you will need to seek out removal of that information by directly contacting the services that are caching your data).
</p>
`;
accountSettingsColumn.innerHTML = accountSettingsHTML;
}

View File

@ -10,4 +10,13 @@ export function setupLoginModal(modal) {
document.getElementById('loginSubmit').addEventListener('click', logIn);
document.getElementById('createAccountSubmit').addEventListener('click', createAccount);
}
export function setupLogoutButton(logoutButton) {
logoutButton.addEventListener('click', () => {
const expire = new Date("November 1, 2015"),
path = window.location.pathname;
document.cookie = 'token=;expires=' + expire.toGMTString() + ';domain=' + document.domain + ';path=' + path; // + in front of `new Date` converts to a number
window.location.reload();
});
}

View File

@ -244,15 +244,15 @@ export function renderEditForm(wordId = false) {
const word = window.currentDictionary.words.find(w => w.wordId === wordId);
if (word) {
const ipaPronunciationField = `<label>Pronunciation<a class="label-button ipa-table-button">IPA Chart</a><br>
<input id="wordPronunciation_${wordId}" class="ipa-field" value="${word.pronunciation}"><br>
<input id="wordPronunciation_${wordId}" class="ipa-field" maxlength="200" value="${word.pronunciation}"><br>
<a class="label-help-button ipa-field-help-button">Field Help</a>
</label>`;
const plainPronunciationField = `<label>Pronunciation<br>
<input id="wordPronunciation_${wordId}" value="${word.pronunciation}">
<input id="wordPronunciation_${wordId}" maxlength="200" value="${word.pronunciation}">
</label>`;
const editForm = `<form id="editForm_${wordId}" class="edit-form">
<label>Word<span class="red">*</span><br>
<input id="wordName_${wordId}" value="${word.name}">
<input id="wordName_${wordId}" maxlength="200" value="${word.name}">
</label>
${window.settings.useIPAPronunciationField ? ipaPronunciationField : plainPronunciationField}
<label>Part of Speech<br>
@ -261,7 +261,7 @@ export function renderEditForm(wordId = false) {
</select>
</label>
<label>Definition<span class="red">*</span><br>
<input id="wordDefinition_${wordId}" value="${word.definition}" placeholder="Equivalent words">
<input id="wordDefinition_${wordId}" maxlength="2500" value="${word.definition}" placeholder="Equivalent words">
</label>
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
<textarea id="wordDetails_${wordId}" placeholder="Markdown formatting allowed">${word.details}</textarea>

View File

@ -1,9 +1,11 @@
<?php
require_once('./config.php');
class Db {
private $dbh;
public $last_error_info;
function __construct() {
$this->dbh = new PDO('mysql:host=localhost;dbname=lexiconga;charset=utf8', 'root', '');
$this->dbh = new PDO('mysql:host=localhost;dbname=lexiconga;charset=utf8', DB_USER, DB_PASSWORD);
$this->dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->last_error_info = null;
}

View File

@ -0,0 +1,4 @@
<?php
define('DB_USER', 'lexiconga_db_username');
define('DB_PASSWORD', 'user_password');

View File

@ -10,9 +10,9 @@ CREATE TABLE IF NOT EXISTS `deleted_words` (
CREATE TABLE IF NOT EXISTS `dictionaries` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user` int(11) NOT NULL,
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'New',
`specification` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Dictionary',
`description` text COLLATE utf8_unicode_ci NOT NULL DEFAULT 'A new dicitonary.' COMMENT 'Markdown',
`name` varchar(80) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'New',
`specification` varchar(80) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Dictionary',
`description` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Markdown. Default: "A new dictionary."',
`allow_duplicates` tinyint(1) NOT NULL DEFAULT 0,
`case_sensitive` tinyint(1) NOT NULL DEFAULT 0,
`sort_by_definition` tinyint(1) NOT NULL DEFAULT 0,
@ -33,16 +33,16 @@ DELIMITER ;
CREATE TABLE IF NOT EXISTS `dictionary_linguistics` (
`dictionary` int(11) NOT NULL,
`parts_of_speech` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`consonants` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`vowels` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`blends` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`onset` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`nucleus` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`coda` text NOT NULL DEFAULT '' COMMENT 'JSON array',
`exceptions` text NOT NULL DEFAULT '' COMMENT 'Markdown',
`orthography_notes` text NOT NULL DEFAULT '' COMMENT 'Markdown',
`grammar_notes` text NOT NULL DEFAULT '' COMMENT 'Markdown',
`parts_of_speech` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Comma-separated',
`consonants` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Space-separated',
`vowels` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Space-separated',
`blends` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Space-separated',
`onset` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Comma-separated',
`nucleus` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Comma-separated',
`coda` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Comma-separated',
`exceptions` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Markdown',
`orthography_notes` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Markdown',
`grammar_notes` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Markdown',
UNIQUE KEY `dictionary` (`dictionary`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ -80,8 +80,8 @@ CREATE TABLE IF NOT EXISTS `words` (
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`pronunciation` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`part_of_speech` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`definition` text COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`details` text COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'Markdown',
`definition` text COLLATE utf8_unicode_ci NOT NULL,
`details` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'Markdown',
`last_updated` int(11) DEFAULT NULL,
`created_on` int(11) NOT NULL,
UNIQUE KEY `unique_index` (`dictionary`,`word_id`)