Sync words on load
This commit is contained in:
		
							parent
							
								
									9f80071b1c
								
							
						
					
					
						commit
						3fa0ac2a81
					
				
					 4 changed files with 80 additions and 17 deletions
				
			
		| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
import { addMessage } from "../utilities";
 | 
					import { addMessage } from "../utilities";
 | 
				
			||||||
import { saveDictionary } from "../dictionaryManagement";
 | 
					import { saveDictionary, clearDictionary } from "../dictionaryManagement";
 | 
				
			||||||
import { request, saveToken } from "./helpers";
 | 
					import { request, saveToken } from "./helpers";
 | 
				
			||||||
 | 
					import { renderAll } from "../render";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Outline for syncing
 | 
					/* Outline for syncing
 | 
				
			||||||
login
 | 
					login
 | 
				
			||||||
| 
						 | 
					@ -8,12 +9,12 @@ login
 | 
				
			||||||
  (DONE!) ? no id
 | 
					  (DONE!) ? no id
 | 
				
			||||||
    -> upload dictionary
 | 
					    -> upload dictionary
 | 
				
			||||||
    -> make new dictionary current
 | 
					    -> make new dictionary current
 | 
				
			||||||
  ? mismatched id
 | 
					  (Canceled) ? mismatched id
 | 
				
			||||||
    -> sync local dictionary (see 'same id' below)
 | 
					    -> sync local dictionary (see 'same id' below)
 | 
				
			||||||
      -> if no matching remote id, ignore (assume deleted)
 | 
					      -> if no matching remote id, ignore (assume deleted)
 | 
				
			||||||
    -> clear local dictionary
 | 
					    -> clear local dictionary
 | 
				
			||||||
    -> insert downloaded dictionary
 | 
					    -> insert downloaded dictionary
 | 
				
			||||||
  ? same id
 | 
					  (DONE!) ? same id
 | 
				
			||||||
    -> compare detail last updated timestamp
 | 
					    -> compare detail last updated timestamp
 | 
				
			||||||
      ? downloaded details are newer
 | 
					      ? downloaded details are newer
 | 
				
			||||||
        -> replace local details
 | 
					        -> replace local details
 | 
				
			||||||
| 
						 | 
					@ -37,15 +38,27 @@ export function syncDictionary() {
 | 
				
			||||||
    request({
 | 
					    request({
 | 
				
			||||||
      action: 'get-current-dictionary',
 | 
					      action: 'get-current-dictionary',
 | 
				
			||||||
    }, remote => {
 | 
					    }, remote => {
 | 
				
			||||||
      console.log(remote);
 | 
					      // console.log(remote);
 | 
				
			||||||
 | 
					      if (remote.details.externalId !== window.currentDictionary.externalId) {
 | 
				
			||||||
 | 
					        clearDictionary();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      const detailsSynced = syncDetails(remote.details);
 | 
					      const detailsSynced = syncDetails(remote.details);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (detailsSynced === false) {
 | 
					      if (detailsSynced === false) {
 | 
				
			||||||
        addMessage('Could not sync');
 | 
					        addMessage('Could not sync');
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        detailsSynced.then(success => {
 | 
					        detailsSynced.then(success => {
 | 
				
			||||||
 | 
					          renderAll();
 | 
				
			||||||
          if (success) {
 | 
					          if (success) {
 | 
				
			||||||
            console.log('Do a word comparison!');
 | 
					            syncWords(remote.words, remote.deletedWords).then(success => {
 | 
				
			||||||
 | 
					              if (success) {
 | 
				
			||||||
 | 
					                renderAll();
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                console.error('word sync failed');
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            console.error('details sync failed');
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -91,7 +104,17 @@ export function uploadWholeDictionary(asNew = false) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function syncDetails(remoteDetails = false) {
 | 
					export function syncDetails(remoteDetails = false) {
 | 
				
			||||||
  if (remoteDetails === false || remoteDetails.lastUpdated < window.currentDictionary.lastUpdated) {
 | 
					  let direction;  // This is if/else if tree the only way I can think to correctly prioritize this when to upload vs download.
 | 
				
			||||||
 | 
					  if (remoteDetails === false) {
 | 
				
			||||||
 | 
					    direction = 'up';
 | 
				
			||||||
 | 
					  } else if (!window.currentDictionary.hasOwnProperty('externalId')) { // If mismatched id, dictionary will be cleared, allowing it to be overwritten
 | 
				
			||||||
 | 
					    direction = 'down';
 | 
				
			||||||
 | 
					  } else if (remoteDetails.lastUpdated < window.currentDictionary.lastUpdated) {
 | 
				
			||||||
 | 
					    direction = 'up';
 | 
				
			||||||
 | 
					  } else if (remoteDetails.lastUpdated > window.currentDictionary.lastUpdated) {
 | 
				
			||||||
 | 
					    direction = 'down';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (direction === 'up') {
 | 
				
			||||||
    const details = Object.assign({}, window.currentDictionary);
 | 
					    const details = Object.assign({}, window.currentDictionary);
 | 
				
			||||||
    delete details.words;
 | 
					    delete details.words;
 | 
				
			||||||
    return request({
 | 
					    return request({
 | 
				
			||||||
| 
						 | 
					@ -105,12 +128,12 @@ export function syncDetails(remoteDetails = false) {
 | 
				
			||||||
      addMessage('Could not sync dictionary');
 | 
					      addMessage('Could not sync dictionary');
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  } else if (remoteDetails.lastUpdated > window.currentDictionary.lastUpdated) {
 | 
					  } else if (direction === 'down') {
 | 
				
			||||||
    window.currentDictionary = Object.assign(window.currentDictionary, remoteDetails);
 | 
					    window.currentDictionary = Object.assign(window.currentDictionary, remoteDetails);
 | 
				
			||||||
    saveDictionary();
 | 
					    saveDictionary();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  addMessage('Dictionary details synchronized');
 | 
					  addMessage('Dictionary details synchronized');
 | 
				
			||||||
  return Promise.resolve();
 | 
					  return Promise.resolve(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function syncWords(remoteWords, deletedWords) {
 | 
					export function syncWords(remoteWords, deletedWords) {
 | 
				
			||||||
| 
						 | 
					@ -121,14 +144,44 @@ export function syncWords(remoteWords, deletedWords) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  const newLocalWords = words.filter(word => {
 | 
					  const localWordsToUpload = words.filter(word => {
 | 
				
			||||||
 | 
					    // Find words that don't exist in remote words after clearing deleted words
 | 
				
			||||||
    const remote = remoteWords.find(remoteWord => remoteWord.id === word.wordId);
 | 
					    const remote = remoteWords.find(remoteWord => remoteWord.id === word.wordId);
 | 
				
			||||||
    return typeof remote === 'undefined';
 | 
					    return typeof remote === 'undefined';
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  remoteWords.forEach(remoteWord => {
 | 
					  remoteWords.forEach(remoteWord => {
 | 
				
			||||||
    const localWord = words.find(word => word.wordId === remoteWord.wordId);
 | 
					    const localWord = words.find(word => word.wordId === remoteWord.wordId);
 | 
				
			||||||
    if (localWord) {
 | 
					    if (localWord) {
 | 
				
			||||||
 | 
					      if (localWord.lastUpdated < remoteWord.lastUpdated) {
 | 
				
			||||||
 | 
					        localWord = remoteWord;
 | 
				
			||||||
 | 
					      } else if (localWord.lastUpdated > remoteWord.lastUpdated) {
 | 
				
			||||||
 | 
					        // Add more-recently-updated words to upload
 | 
				
			||||||
 | 
					        localWordsToUpload.push(localWord);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // If word not found, add it to words
 | 
				
			||||||
 | 
					      words.push(remoteWord);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  window.currentDictionary.words = words;
 | 
				
			||||||
 | 
					  saveDictionary();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (localWordsToUpload.length > 0) {
 | 
				
			||||||
 | 
					    return request({
 | 
				
			||||||
 | 
					      action: 'set-dictionary-words',
 | 
				
			||||||
 | 
					      words,
 | 
				
			||||||
 | 
					    }, successful => {
 | 
				
			||||||
 | 
					      addMessage('Saved Words to Server');
 | 
				
			||||||
 | 
					      return successful;
 | 
				
			||||||
 | 
					    }, error => {
 | 
				
			||||||
 | 
					      console.error(error);
 | 
				
			||||||
 | 
					      addMessage('Could not sync words');
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  addMessage('Words synchronized');
 | 
				
			||||||
 | 
					  return Promise.resolve(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -197,7 +197,6 @@ WHERE dictionary=$dictionary";
 | 
				
			||||||
    if ($results) {
 | 
					    if ($results) {
 | 
				
			||||||
      return array_map(function ($row) {
 | 
					      return array_map(function ($row) {
 | 
				
			||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
          'id' => intval($row['word_id']),
 | 
					 | 
				
			||||||
          'name' => $row['name'],
 | 
					          'name' => $row['name'],
 | 
				
			||||||
          'pronunciation' => $row['pronunciation'],
 | 
					          'pronunciation' => $row['pronunciation'],
 | 
				
			||||||
          'partOfSpeech' => $row['part_of_speech'],
 | 
					          'partOfSpeech' => $row['part_of_speech'],
 | 
				
			||||||
| 
						 | 
					@ -205,6 +204,7 @@ WHERE dictionary=$dictionary";
 | 
				
			||||||
          'details' => $row['details'],
 | 
					          'details' => $row['details'],
 | 
				
			||||||
          'lastUpdated' => is_null($row['last_updated']) ? null : intval($row['last_updated']),
 | 
					          'lastUpdated' => is_null($row['last_updated']) ? null : intval($row['last_updated']),
 | 
				
			||||||
          'createdOn' => intval($row['created_on']),
 | 
					          'createdOn' => intval($row['created_on']),
 | 
				
			||||||
 | 
					          'wordId' => intval($row['word_id']),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      }, $results);
 | 
					      }, $results);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -239,10 +239,10 @@ WHERE dictionary=$dictionary";
 | 
				
			||||||
      if ($most_recent_word_update < $last_updated) {
 | 
					      if ($most_recent_word_update < $last_updated) {
 | 
				
			||||||
        $most_recent_word_update = $last_updated;
 | 
					        $most_recent_word_update = $last_updated;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      $word_ids[] = $word['id'];
 | 
					      $word_ids[] = $word['wordId'];
 | 
				
			||||||
      $query .= "(?, ?, ?, ?, ?, ?, ?, ?, ?), ";
 | 
					      $query .= "(?, ?, ?, ?, ?, ?, ?, ?, ?), ";
 | 
				
			||||||
      $params[] = $dictionary;
 | 
					      $params[] = $dictionary;
 | 
				
			||||||
      $params[] = $word['id'];
 | 
					      $params[] = $word['wordId'];
 | 
				
			||||||
      $params[] = $word['name'];
 | 
					      $params[] = $word['name'];
 | 
				
			||||||
      $params[] = $word['pronunciation'];
 | 
					      $params[] = $word['pronunciation'];
 | 
				
			||||||
      $params[] = $word['partOfSpeech'];
 | 
					      $params[] = $word['partOfSpeech'];
 | 
				
			||||||
| 
						 | 
					@ -257,7 +257,8 @@ pronunciation=VALUES(pronunciation),
 | 
				
			||||||
part_of_speech=VALUES(part_of_speech),
 | 
					part_of_speech=VALUES(part_of_speech),
 | 
				
			||||||
definition=VALUES(definition),
 | 
					definition=VALUES(definition),
 | 
				
			||||||
details=VALUES(details),
 | 
					details=VALUES(details),
 | 
				
			||||||
last_updated=VALUES(last_updated)';
 | 
					last_updated=VALUES(last_updated),
 | 
				
			||||||
 | 
					created_on=VALUES(created_on)';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    $results = $this->db->execute($query, $params);
 | 
					    $results = $this->db->execute($query, $params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,9 +212,12 @@ VALUES (?, ?, ?, ?, ?)';
 | 
				
			||||||
      $dictionary = $user_data->dictionary;
 | 
					      $dictionary = $user_data->dictionary;
 | 
				
			||||||
      $user = $user_data->id;
 | 
					      $user = $user_data->id;
 | 
				
			||||||
      $updated_words = $this->dictionary->setWords($user, $dictionary, $words);
 | 
					      $updated_words = $this->dictionary->setWords($user, $dictionary, $words);
 | 
				
			||||||
      if ($updated_words) {
 | 
					      if ($updated_words === true) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      return array(
 | 
				
			||||||
 | 
					        'error' => $updated_words,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,12 +249,18 @@ switch ($action) {
 | 
				
			||||||
    if ($token !== false && isset($request['words'])) {
 | 
					    if ($token !== false && isset($request['words'])) {
 | 
				
			||||||
      $user = new User();
 | 
					      $user = new User();
 | 
				
			||||||
      $update_words_success = $user->updateOrAddWordsToCurrentDictionary($token, $request['words']);
 | 
					      $update_words_success = $user->updateOrAddWordsToCurrentDictionary($token, $request['words']);
 | 
				
			||||||
      if ($update_words_success !== false) {
 | 
					      if ($update_words_success === true) {
 | 
				
			||||||
        return Response::json(array(
 | 
					        return Response::json(array(
 | 
				
			||||||
          'data' => 'Updated successfully',
 | 
					          'data' => $update_words_success,
 | 
				
			||||||
          'error' => false,
 | 
					          'error' => false,
 | 
				
			||||||
        ), 200);
 | 
					        ), 200);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      if (isset($update_words_success['error'])) {
 | 
				
			||||||
 | 
					        return Response::json(array(
 | 
				
			||||||
 | 
					          'data' => $update_words_success['error'],
 | 
				
			||||||
 | 
					          'error' => true,
 | 
				
			||||||
 | 
					        ), 500);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      return Response::json(array(
 | 
					      return Response::json(array(
 | 
				
			||||||
        'data' => 'Could not set words: invalid token',
 | 
					        'data' => 'Could not set words: invalid token',
 | 
				
			||||||
        'error' => true,
 | 
					        'error' => true,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue