mirror of
				https://github.com/Alamantus/Lexiconga.git
				synced 2025-11-04 02:07:05 +01:00 
			
		
		
		
	Only split out html/md files;Fix page load problem
This commit is contained in:
		
							parent
							
								
									11167a639b
								
							
						
					
					
						commit
						b4d9635d15
					
				
					 10 changed files with 128 additions and 136 deletions
				
			
		
							
								
								
									
										39
									
								
								index.html
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								index.html
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -372,30 +372,25 @@
 | 
			
		|||
  <script src="//cdnjs.cloudflare.com/ajax/libs/UpUp/1.1.0/upup.min.js"></script>
 | 
			
		||||
  <script>
 | 
			
		||||
  window.onload = (function (oldLoad) {
 | 
			
		||||
    return function () {
 | 
			
		||||
      oldLoad && oldLoad();
 | 
			
		||||
      if (UpUp) {
 | 
			
		||||
        UpUp.start({
 | 
			
		||||
          'cache-version': '2.0.0',
 | 
			
		||||
          'content-url': 'offline.html',
 | 
			
		||||
          'assets': [
 | 
			
		||||
            'src.8d47de22.js',
 | 
			
		||||
            'main.3381ca43.css',
 | 
			
		||||
            'help.ecc721dc.html',
 | 
			
		||||
            'privacy.5cbf7ea0.html',
 | 
			
		||||
            'terms.bcb4cecc.html',
 | 
			
		||||
            'usage.4a51122f.html',
 | 
			
		||||
            'ads.f4e0c99c.js',
 | 
			
		||||
            'favicon.5d013634.png',
 | 
			
		||||
            'ipa-table.6c5cf939.html',
 | 
			
		||||
            'papaparse.min.dab93fe4.js',
 | 
			
		||||
          ],
 | 
			
		||||
          'service-worker-url': 'upup.sw.min.js',
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    oldLoad && oldLoad();
 | 
			
		||||
    if (UpUp) {
 | 
			
		||||
      UpUp.start({
 | 
			
		||||
        'cache-version': '2.0.0',
 | 
			
		||||
        'content-url': 'offline.html',
 | 
			
		||||
        'assets': [
 | 
			
		||||
          'src.c95c2dcd.js',
 | 
			
		||||
          'main.3381ca43.css',
 | 
			
		||||
          'help.ecc721dc.html',
 | 
			
		||||
          'privacy.5cbf7ea0.html',
 | 
			
		||||
          'terms.bcb4cecc.html',
 | 
			
		||||
          'usage.4a51122f.html',
 | 
			
		||||
          'ipa-table.6c5cf939.html',
 | 
			
		||||
          'favicon.5d013634.png',
 | 
			
		||||
        ],
 | 
			
		||||
        'service-worker-url': 'upup.sw.min.js',
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  })(window.onload);
 | 
			
		||||
    
 | 
			
		||||
  </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -20,12 +20,11 @@ function initialize() {
 | 
			
		|||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setupAds().then(() => renderAll());
 | 
			
		||||
  setupAds();
 | 
			
		||||
  renderAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window.onload = (function (oldLoad) {
 | 
			
		||||
  return function () {
 | 
			
		||||
    oldLoad && oldLoad();
 | 
			
		||||
    initialize();
 | 
			
		||||
  }
 | 
			
		||||
  oldLoad && oldLoad();
 | 
			
		||||
  initialize();
 | 
			
		||||
})(window.onload);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
import { setupInfoModal } from "../setupListeners";
 | 
			
		||||
import { request } from "./helpers";
 | 
			
		||||
 | 
			
		||||
export function renderForgotPasswordForm() {
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +23,15 @@ export function renderForgotPasswordForm() {
 | 
			
		|||
  setupInfoModal(modal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setupInfoModal(modal) {
 | 
			
		||||
  const closeElements = modal.querySelectorAll('.modal-background, .close-button');
 | 
			
		||||
  Array.from(closeElements).forEach(close => {
 | 
			
		||||
    close.addEventListener('click', () => {
 | 
			
		||||
      modal.parentElement.removeChild(modal);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setupStartResetForm() {
 | 
			
		||||
  document.getElementById('forgotPasswordSubmit').addEventListener('click', startPasswordReset);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +67,10 @@ function startPasswordReset() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function setupPasswordResetForm() {
 | 
			
		||||
  document.getElementById('newPasswordSubmit').addEventListener('click', submitPasswordReset);
 | 
			
		||||
  const submitButton = document.getElementById('newPasswordSubmit');
 | 
			
		||||
  if (submitButton) {
 | 
			
		||||
    submitButton.addEventListener('click', submitPasswordReset);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function submitPasswordReset() {
 | 
			
		||||
| 
						 | 
				
			
			@ -97,8 +108,6 @@ function submitPasswordReset() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
window.onload = (function (oldLoad) {
 | 
			
		||||
  return function () {
 | 
			
		||||
    oldLoad && oldLoad();
 | 
			
		||||
    setupPasswordResetForm();
 | 
			
		||||
  }
 | 
			
		||||
  oldLoad && oldLoad();
 | 
			
		||||
  setupPasswordResetForm();
 | 
			
		||||
})(window.onload);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,11 @@
 | 
			
		|||
import { DISPLAY_AD_EVERY } from '../constants.js';
 | 
			
		||||
import ads from '../../ads.json';
 | 
			
		||||
 | 
			
		||||
export function setupAds() {
 | 
			
		||||
  return import('../../ads.json').then(ads => {
 | 
			
		||||
    const shuffle = (a, b) => Math.random() > 0.5 ? 1 : -1;
 | 
			
		||||
    const priority = ads.filter(ad => isActive(ad) && ad.isPriority).sort(shuffle);
 | 
			
		||||
    const regular = ads.filter(ad => isActive(ad) && !ad.isPriority).sort(shuffle);
 | 
			
		||||
    window.ads = [...priority, ...regular];
 | 
			
		||||
  });
 | 
			
		||||
  const shuffle = (a, b) => Math.random() > 0.5 ? 1 : -1;
 | 
			
		||||
  const priority = ads.filter(ad => isActive(ad) && ad.isPriority).sort(shuffle);
 | 
			
		||||
  const regular = ads.filter(ad => isActive(ad) && !ad.isPriority).sort(shuffle);
 | 
			
		||||
  window.ads = [...priority, ...regular];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isActive(ad) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
import papa from 'papaparse';
 | 
			
		||||
import { renderDictionaryDetails, renderPartsOfSpeech, renderAll, renderTheme } from "./render";
 | 
			
		||||
import { removeTags, cloneObject, getTimestampInSeconds, download, slugify } from "../helpers";
 | 
			
		||||
import { LOCAL_STORAGE_KEY, DEFAULT_DICTIONARY, MIGRATE_VERSION } from "../constants";
 | 
			
		||||
| 
						 | 
				
			
			@ -203,50 +204,48 @@ export function importWords() {
 | 
			
		|||
  if (importWordsField.files.length === 1) {
 | 
			
		||||
    if (confirm('Importing a CSV file with words will add all of the words in the file to your dictionary regardless of duplication!\nDo you want to continue?')) {
 | 
			
		||||
      addMessage('Importing words...');
 | 
			
		||||
      import('papaparse').then(papa => {
 | 
			
		||||
        const importedWords = [];
 | 
			
		||||
        papa.parse(importWordsField.files[0], {
 | 
			
		||||
          header: true,
 | 
			
		||||
          encoding: "utf-8",
 | 
			
		||||
          step: results => {
 | 
			
		||||
            if (results.errors.length > 0) {
 | 
			
		||||
              results.errors.forEach(err => {
 | 
			
		||||
                addMessage('Error Importing Word: ' + err, undefined, 'error');
 | 
			
		||||
                console.error('Error Importing Word: ', err)
 | 
			
		||||
              });
 | 
			
		||||
            } else {
 | 
			
		||||
              const row = results.data[0];
 | 
			
		||||
              const importedWord = addWord({
 | 
			
		||||
                name: removeTags(row.word).trim(),
 | 
			
		||||
                pronunciation: removeTags(row.pronunciation).trim(),
 | 
			
		||||
                partOfSpeech: removeTags(row['part of speech']).trim(),
 | 
			
		||||
                definition: removeTags(row.definition).trim(),
 | 
			
		||||
                details: removeTags(row.explanation).trim(),
 | 
			
		||||
                wordId: getNextId(),
 | 
			
		||||
              }, false, false, false);
 | 
			
		||||
      const importedWords = [];
 | 
			
		||||
      papa.parse(importWordsField.files[0], {
 | 
			
		||||
        header: true,
 | 
			
		||||
        encoding: "utf-8",
 | 
			
		||||
        step: results => {
 | 
			
		||||
          if (results.errors.length > 0) {
 | 
			
		||||
            results.errors.forEach(err => {
 | 
			
		||||
              addMessage('Error Importing Word: ' + err, undefined, 'error');
 | 
			
		||||
              console.error('Error Importing Word: ', err)
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            const row = results.data[0];
 | 
			
		||||
            const importedWord = addWord({
 | 
			
		||||
              name: removeTags(row.word).trim(),
 | 
			
		||||
              pronunciation: removeTags(row.pronunciation).trim(),
 | 
			
		||||
              partOfSpeech: removeTags(row['part of speech']).trim(),
 | 
			
		||||
              definition: removeTags(row.definition).trim(),
 | 
			
		||||
              details: removeTags(row.explanation).trim(),
 | 
			
		||||
              wordId: getNextId(),
 | 
			
		||||
            }, false, false, false);
 | 
			
		||||
 | 
			
		||||
              importedWords.push(importedWord);
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          complete: () => {
 | 
			
		||||
            saveDictionary(false);
 | 
			
		||||
            renderAll();
 | 
			
		||||
            importWordsField.value = '';
 | 
			
		||||
            document.getElementById('editModal').style.display = 'none';
 | 
			
		||||
            addMessage(`Done Importing ${importedWords.length} Words`);
 | 
			
		||||
            importedWords.push(importedWord);
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        complete: () => {
 | 
			
		||||
          saveDictionary(false);
 | 
			
		||||
          renderAll();
 | 
			
		||||
          importWordsField.value = '';
 | 
			
		||||
          document.getElementById('editModal').style.display = 'none';
 | 
			
		||||
          addMessage(`Done Importing ${importedWords.length} Words`);
 | 
			
		||||
 | 
			
		||||
            if (hasToken()) {
 | 
			
		||||
              import('./account/index.js').then(account => {
 | 
			
		||||
                account.syncImportedWords(importedWords);
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          error: err => {
 | 
			
		||||
            addMessage('Error Importing Words: ' + err, undefined, 'error');
 | 
			
		||||
            console.error('Error Importing Words: ', err);
 | 
			
		||||
          },
 | 
			
		||||
          skipEmptyLines: true,
 | 
			
		||||
        });
 | 
			
		||||
          if (hasToken()) {
 | 
			
		||||
            import('./account/index.js').then(account => {
 | 
			
		||||
              account.syncImportedWords(importedWords);
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        error: err => {
 | 
			
		||||
          addMessage('Error Importing Words: ' + err, undefined, 'error');
 | 
			
		||||
          console.error('Error Importing Words: ', err);
 | 
			
		||||
        },
 | 
			
		||||
        skipEmptyLines: true,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -269,23 +268,21 @@ export function exportWords() {
 | 
			
		|||
  addMessage('Exporting Words...');
 | 
			
		||||
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    import('papaparse').then(papa => {
 | 
			
		||||
      const { name, specification } = window.currentDictionary;
 | 
			
		||||
      
 | 
			
		||||
      const fileName = slugify(name + '_' + specification) + '_words.csv';
 | 
			
		||||
      
 | 
			
		||||
      const words = window.currentDictionary.words.map(word => {
 | 
			
		||||
        return {
 | 
			
		||||
          word: word.name,
 | 
			
		||||
          pronunciation: word.pronunciation,
 | 
			
		||||
          'part of speech': word.partOfSpeech,
 | 
			
		||||
          definition: word.definition,
 | 
			
		||||
          explanation: word.details,
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      const csv = papa.unparse(words, { quotes: true });
 | 
			
		||||
      download(csv, fileName, 'text/csv;charset=utf-8');
 | 
			
		||||
    const { name, specification } = window.currentDictionary;
 | 
			
		||||
    
 | 
			
		||||
    const fileName = slugify(name + '_' + specification) + '_words.csv';
 | 
			
		||||
    
 | 
			
		||||
    const words = window.currentDictionary.words.map(word => {
 | 
			
		||||
      return {
 | 
			
		||||
        word: word.name,
 | 
			
		||||
        pronunciation: word.pronunciation,
 | 
			
		||||
        'part of speech': word.partOfSpeech,
 | 
			
		||||
        definition: word.definition,
 | 
			
		||||
        explanation: word.details,
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    const csv = papa.unparse(words, { quotes: true });
 | 
			
		||||
    download(csv, fileName, 'text/csv;charset=utf-8');
 | 
			
		||||
  }, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import { showSearchModal, clearSearchText } from "./search";
 | 
			
		|||
import { saveAndCloseSettingsModal, openSettingsModal, saveSettings } from "./settings";
 | 
			
		||||
import { saveAndCloseEditModal, openEditModal } from "./dictionaryManagement";
 | 
			
		||||
import { addMessage, hideAllModals } from "./utilities";
 | 
			
		||||
import helpFile from '../markdown/help.md';
 | 
			
		||||
 | 
			
		||||
export function enableHotKeys() {
 | 
			
		||||
  document.addEventListener('keydown', hotKeyActions);
 | 
			
		||||
| 
						 | 
				
			
			@ -102,9 +103,7 @@ function submitWord() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function showHelpModal() {
 | 
			
		||||
  import('../markdown/help.md').then(html => {
 | 
			
		||||
    renderInfoModal(html);
 | 
			
		||||
  });
 | 
			
		||||
  renderInfoModal(helpFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function maximizeTextarea() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ import {
 | 
			
		|||
import { getPaginationData } from './pagination';
 | 
			
		||||
import { getOpenEditForms, parseReferences } from './wordManagement';
 | 
			
		||||
import { renderAd } from './ads';
 | 
			
		||||
import ipaTableFile from './KeyboardFire/phondue/ipa-table.html';
 | 
			
		||||
 | 
			
		||||
export function renderAll() {
 | 
			
		||||
  renderTheme();
 | 
			
		||||
| 
						 | 
				
			
			@ -311,24 +312,22 @@ export function renderIPATable(ipaTableButton) {
 | 
			
		|||
  ipaTableButton = typeof ipaTableButton.target === 'undefined' || ipaTableButton.target === '' ? ipaTableButton : ipaTableButton.target;
 | 
			
		||||
  const label = ipaTableButton.parentElement.innerText.replace(/(Field Help|IPA Chart)/g, '').trim();
 | 
			
		||||
  const textBox = ipaTableButton.parentElement.querySelector('input');
 | 
			
		||||
  import('./KeyboardFire/phondue/ipa-table.html').then(html => {
 | 
			
		||||
    const modalElement = document.createElement('section');
 | 
			
		||||
    modalElement.classList.add('modal', 'ipa-table-modal');
 | 
			
		||||
    modalElement.innerHTML = `<div class="modal-background"></div>
 | 
			
		||||
    <div class="modal-content">
 | 
			
		||||
      <a class="close-button">×︎</a>
 | 
			
		||||
      <header><label>${label} <input value="${textBox.value}" class="ipa-field"></label></header>
 | 
			
		||||
      <section>
 | 
			
		||||
        ${html}
 | 
			
		||||
      </section>
 | 
			
		||||
      <footer><a class="button done-button">Done</a></footer>
 | 
			
		||||
    </div>`;
 | 
			
		||||
  const modalElement = document.createElement('section');
 | 
			
		||||
  modalElement.classList.add('modal', 'ipa-table-modal');
 | 
			
		||||
  modalElement.innerHTML = `<div class="modal-background"></div>
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
    <a class="close-button">×︎</a>
 | 
			
		||||
    <header><label>${label} <input value="${textBox.value}" class="ipa-field"></label></header>
 | 
			
		||||
    <section>
 | 
			
		||||
      ${ipaTableFile}
 | 
			
		||||
    </section>
 | 
			
		||||
    <footer><a class="button done-button">Done</a></footer>
 | 
			
		||||
  </div>`;
 | 
			
		||||
 | 
			
		||||
  document.body.appendChild(modalElement);
 | 
			
		||||
  
 | 
			
		||||
    document.body.appendChild(modalElement);
 | 
			
		||||
    
 | 
			
		||||
    setupIPAFields();
 | 
			
		||||
    setupIPATable(modalElement, textBox);
 | 
			
		||||
  });
 | 
			
		||||
  setupIPAFields();
 | 
			
		||||
  setupIPATable(modalElement, textBox);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function renderMaximizedTextbox(maximizeButton) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,9 @@ import { usePhondueDigraphs } from './KeyboardFire/phondue/ipaField';
 | 
			
		|||
import { openSettingsModal, saveSettingsModal, saveAndCloseSettingsModal } from './settings';
 | 
			
		||||
import { enableHotKeys } from './hotkeys';
 | 
			
		||||
import { showSearchModal, clearSearchText, checkAllPartsOfSpeechFilters, uncheckAllPartsOfSpeechFilters } from './search';
 | 
			
		||||
import helpFile from '../markdown/help.md';
 | 
			
		||||
import termsFile from '../markdown/terms.md';
 | 
			
		||||
import privacyFile from '../markdown/privacy.md';
 | 
			
		||||
 | 
			
		||||
export default function setupListeners() {
 | 
			
		||||
  setupDetailsTabs();
 | 
			
		||||
| 
						 | 
				
			
			@ -357,19 +360,13 @@ export function setupMaximizeModal(modal, textBox) {
 | 
			
		|||
 | 
			
		||||
export function setupInfoButtons() {
 | 
			
		||||
  document.getElementById('helpInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../markdown/help.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(helpFile);
 | 
			
		||||
  });
 | 
			
		||||
  document.getElementById('termsInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../markdown/terms.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(termsFile);
 | 
			
		||||
  });
 | 
			
		||||
  document.getElementById('privacyInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../markdown/privacy.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(privacyFile);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,8 @@ import setupListeners from './setupListeners';
 | 
			
		|||
import { setupAds } from '../ads';
 | 
			
		||||
 | 
			
		||||
function initialize() {
 | 
			
		||||
  setupAds().then(() => renderAll());
 | 
			
		||||
  setupAds();
 | 
			
		||||
  renderAll();
 | 
			
		||||
  setupListeners();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,9 @@
 | 
			
		|||
import {showSection, hideDetailsPanel} from './displayToggles';
 | 
			
		||||
import { showSearchModal, clearSearchText, checkAllPartsOfSpeechFilters, uncheckAllPartsOfSpeechFilters } from './search';
 | 
			
		||||
import { renderWords, renderInfoModal } from './render';
 | 
			
		||||
import helpFile from '../../markdown/help.md';
 | 
			
		||||
import termsFile from '../../markdown/terms.md';
 | 
			
		||||
import privacyFile from '../../markdown/privacy.md';
 | 
			
		||||
 | 
			
		||||
export default function setupListeners() {
 | 
			
		||||
  setupDetailsTabs();
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +82,13 @@ export function setupSearchFilters() {
 | 
			
		|||
 | 
			
		||||
export function setupInfoButtons() {
 | 
			
		||||
  document.getElementById('helpInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../../markdown/help.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(helpFile);
 | 
			
		||||
  });
 | 
			
		||||
  document.getElementById('termsInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../../markdown/terms.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(termsFile);
 | 
			
		||||
  });
 | 
			
		||||
  document.getElementById('privacyInfoButton').addEventListener('click', () => {
 | 
			
		||||
    import('../../markdown/privacy.md').then(html => {
 | 
			
		||||
      renderInfoModal(html);
 | 
			
		||||
    });
 | 
			
		||||
    renderInfoModal(privacyFile);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue