Enable creating new dictionaries from frontend

Also change how dictionaries are created, i.e. set random unique id
so exposing them without hashing is ok.
This is to allow displaying public dictionaries the same way
This commit is contained in:
Robbie Antenesse 2018-07-01 16:08:01 -06:00
parent e6878fd9ec
commit e6916f0f24
7 changed files with 70 additions and 13 deletions

View File

@ -26,22 +26,33 @@ class Dictionary {
);
}
private function checkIfIdExists ($id) {
$query = "SELECT id FROM dictionaries WHERE id=?";
$results = $this->db->query($query, array($id))->fetchAll();
return count($results) > 0;
}
public function create ($user) {
$insert_dictionary_query = "INSERT INTO dictionaries (user, created_on) VALUES (?, ?)";
$insert_dictionary = $this->db->execute($insert_dictionary_query, array($user, time()));
$new_id = mt_rand(1000, 999999999);
$id_exists = $this->checkIfIdExists($new_id);
while ($id_exists) {
$new_id = mt_rand(1000, 999999999);
$id_exists = $this->checkIfIdExists($new_id);
}
$insert_dictionary_query = "INSERT INTO dictionaries (id, user, created_on) VALUES (?, ?, ?)";
$insert_dictionary = $this->db->execute($insert_dictionary_query, array($new_id, $user, time()));
if ($insert_dictionary === true) {
$new_dictionary_id = $this->db->lastInsertId();
$insert_linguistics_query = "INSERT INTO dictionary_linguistics (dictionary, parts_of_speech, phonology)
VALUES ($new_dictionary_id, ?, ?)";
VALUES ($new_id, ?, ?)";
$insert_linguistics = $this->db->execute($insert_linguistics_query, array(
json_encode($this->defaults['partsOfSpeech']),
json_encode($this->defaults['phonology']),
));
if ($insert_linguistics === true) {
return $this->changeCurrent($user, $new_dictionary_id);
return $this->changeCurrent($user, $new_id);
} else {
return array(
'error' => '"INSERT INTO dictionary_linguistics" failed: ' . $this->db->last_error_info[2],
@ -69,7 +80,7 @@ VALUES ($new_dictionary_id, ?, ?)";
if ($results) {
return array_map(function($result) {
return array(
'id' => $this->token->hash($result['id']),
'id' => $result['id'],
'name' => $result['name'] . ' ' . $result['specification'],
);
}, $results);
@ -86,7 +97,7 @@ VALUES ($new_dictionary_id, ?, ?)";
$phonology = $result['phonology'] !== '' ? json_decode($result['phonology']) : $this->defaults['phonology'];
return array(
'id' => $this->token->hash($result['id']),
'id' => $result['id'],
'name' => $result['name'],
'specification' => $result['specification'],
'description' => $result['description'],

View File

@ -115,9 +115,10 @@ VALUES (?, ?, ?, ?, ?)';
$id = $user_data->id;
$new_dictionary = $this->dictionary->create($id);
if (!isset($new_dictionary['error'])) {
$new_token = $this->generateUserToken($id, $new_dictionary);
return array(
'token' => $this->generateUserToken($id, $new_dictionary),
'dictionary' => $this->getCurrentDictionary($token),
'token' => $new_token,
'dictionary' => $this->getCurrentDictionary($new_token),
);
} else {
return $new_dictionary;

View File

@ -11,6 +11,7 @@ export class MyAccount extends Component {
publicName: PropTypes.string.isRequired,
allowEmails: PropTypes.bool.isRequired,
userDictionaries: PropTypes.array.isRequired,
dictionary: PropTypes.object,
sendUserData: PropTypes.func,
changeDictionary: PropTypes.func,
}, props, 'prop', 'MyAccount');
@ -136,15 +137,23 @@ export class MyAccount extends Component {
<div className='column'>
<h2 className='title'>Account Actions</h2>
<div className='field'>
<div className='control'>
<button class="button" onClick={ () => this.props.dictionary.createNew() }>
Create New Dictionary
</button>
</div>
</div>
<div className='field'>
<label className='label is-unselectable'>
<span>Change Dictionary</span>
</label>
<div className='control'>
<div className='select'>
<select>
<select value={ this.props.dictionary.id }>
{this.props.userDictionaries.map(item => {
return <option value={item.id}>{item.name}</option>;
return <option value={item.id}>{item.name}{item.id === this.props.dictionary.id && ' (Current)'}</option>;
})}
</select>
</div>

View File

@ -17,6 +17,7 @@ export class AccountManager extends Component {
PropTypes.checkPropTypes({
updater: PropTypes.object.isRequired,
dictionary: PropTypes.object,
}, props, 'prop', 'AccountManager');
const userData = store.get('LexicongaUserData');
@ -163,6 +164,7 @@ export class AccountManager extends Component {
publicName={ userData.publicName }
allowEmails={ userData.allowEmails }
userDictionaries={ this.state.userDictionaries }
dictionary={ this.props.dictionary }
sendUserData={ this.sendUserData.bind(this) }
changeDictionary={ () => {} } />
</Modal>

View File

@ -17,6 +17,7 @@ export class Header extends Component {
partsOfSpeech: PropTypes.array.isRequired,
search: PropTypes.func.isRequired,
updater: PropTypes.object.isRequired,
dictionary: PropTypes.object,
}, props, 'prop', 'Header');
this.state = {
@ -49,7 +50,9 @@ export class Header extends Component {
<div className={`navbar-menu${ this.state.displayNavMenu ? ' is-active' : '' }`}>
<div className='navbar-end'>
<span className='navbar-item has-text-right-touch'>
<AccountManager updater={ this.props.updater } />
<AccountManager
updater={ this.props.updater }
dictionary={ this.props.dictionary } />
</span>
<span className='navbar-item has-text-right-touch'>
<Modal buttonText='Help' title='Lexiconga Help'>

View File

@ -209,6 +209,7 @@ class App extends Component {
partsOfSpeech={ this.state.partsOfSpeech }
search={ (searchConfig) => this.search(searchConfig) }
updater={ this.updater }
dictionary={ dictionary }
/>
<MainDisplay

View File

@ -3,6 +3,7 @@ import store from 'store';
import wordDb from './WordDatabase';
import idManager from './IDManager';
import { DEFAULT_DICTIONARY } from '../Constants';
import { request } from "../Helpers";
class DictionaryData {
constructor () {
@ -39,6 +40,11 @@ class DictionaryData {
store.set('Lexiconga', updatedValues);
}
get id () {
return this.storedData.id
|| null;
}
get name () {
return this.storedData.name
|| DEFAULT_DICTIONARY.name;
@ -346,6 +352,30 @@ class DictionaryData {
As such, searches on `details` will only allow "contains".
*/
}
reset(dictionaryDetails = DEFAULT_DICTIONARY) {
this.storedData = dictionaryDetails;
wordDb.delete().then(() => {
window.location.reload();
}).catch(err => {
console.error('Could not delete words db: ', err);
});
}
createNew () {
request('create-new-dictionary', {
token: store.get('LexicongaToken'),
}, response => {
const {data, error} = response;
if (error) {
console.error(data);
} else {
console.log(data);
store.set('LexicongaToken', data.token);
this.reset(data.dictionary.details);
}
});
}
}
export default new DictionaryData;