This commit is contained in:
parent
0ce7775093
commit
3e1d6d0cea
|
@ -79,9 +79,12 @@ const editor: AT.LingdocsUser = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
// @ts-ignore
|
||||||
|
const users: any = {
|
||||||
basic,
|
basic,
|
||||||
student,
|
student,
|
||||||
editor,
|
editor,
|
||||||
admin,
|
admin,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default users;
|
||||||
|
|
|
@ -20,6 +20,7 @@ export declare type EmailVerified = true | Hash | false;
|
||||||
export declare type ActionComplete = {
|
export declare type ActionComplete = {
|
||||||
ok: true;
|
ok: true;
|
||||||
message: string;
|
message: string;
|
||||||
|
tests?: TestResult[];
|
||||||
};
|
};
|
||||||
export declare type ActionError = {
|
export declare type ActionError = {
|
||||||
ok: false;
|
ok: false;
|
||||||
|
@ -48,6 +49,11 @@ export declare type UserTextOptionsRecord = {
|
||||||
lastModified: TimeStamp;
|
lastModified: TimeStamp;
|
||||||
userTextOptions: UserTextOptions;
|
userTextOptions: UserTextOptions;
|
||||||
};
|
};
|
||||||
|
export declare type TestResult = {
|
||||||
|
done: true;
|
||||||
|
time: TimeStamp;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
export declare type LingdocsUser = {
|
export declare type LingdocsUser = {
|
||||||
userId: UUID;
|
userId: UUID;
|
||||||
admin?: boolean;
|
admin?: boolean;
|
||||||
|
@ -63,7 +69,7 @@ export declare type LingdocsUser = {
|
||||||
requestedOn: TimeStamp;
|
requestedOn: TimeStamp;
|
||||||
};
|
};
|
||||||
upgradeToStudentRequest?: "waiting" | "denied";
|
upgradeToStudentRequest?: "waiting" | "denied";
|
||||||
tests: [];
|
tests: TestResult[];
|
||||||
lastLogin: TimeStamp;
|
lastLogin: TimeStamp;
|
||||||
lastActive: TimeStamp;
|
lastActive: TimeStamp;
|
||||||
userTextOptionsRecord: undefined | UserTextOptionsRecord;
|
userTextOptionsRecord: undefined | UserTextOptionsRecord;
|
||||||
|
@ -88,6 +94,14 @@ export declare type UpgradeUserResponse = {
|
||||||
message: "user already upgraded" | "user upgraded to student";
|
message: "user already upgraded" | "user upgraded to student";
|
||||||
user: LingdocsUser;
|
user: LingdocsUser;
|
||||||
};
|
};
|
||||||
|
export declare type PostTestResultsBody = {
|
||||||
|
tests: TestResult[];
|
||||||
|
};
|
||||||
|
export declare type PostTestResultsResponse = {
|
||||||
|
ok: true;
|
||||||
|
message: "posted test results";
|
||||||
|
tests: TestResult[];
|
||||||
|
};
|
||||||
export declare type UpdateUserTextOptionsRecordBody = {
|
export declare type UpdateUserTextOptionsRecordBody = {
|
||||||
userTextOptionsRecord: UserTextOptionsRecord;
|
userTextOptionsRecord: UserTextOptionsRecord;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as AT from "./website/src/types/account-types";
|
import * as AT from "./website/src/types/account-types";
|
||||||
import * as FT from "./website/src/types/functions-types";
|
import * as FT from "./website/src/types/functions-types";
|
||||||
|
import * as DT from "./website/src/types/dictionary-types";
|
||||||
import {
|
import {
|
||||||
getTimestamp,
|
getTimestamp,
|
||||||
} from "./account/src/lib/time-utils";
|
} from "./account/src/lib/time-utils";
|
||||||
|
@ -54,4 +55,5 @@ export {
|
||||||
// TYPES
|
// TYPES
|
||||||
AT,
|
AT,
|
||||||
FT,
|
FT,
|
||||||
|
DT,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/lingdocs-main",
|
"name": "@lingdocs/lingdocs-main",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"description": "types and functions for lingdocs stuff",
|
"description": "types and functions for lingdocs stuff",
|
||||||
"main": "dist/library.js",
|
"main": "dist/library.js",
|
||||||
"module": "dist/library.js",
|
"module": "dist/library.js",
|
||||||
|
|
|
@ -74,6 +74,12 @@ import classNames from "classnames";
|
||||||
import { getTextOptions } from "./lib/get-text-options";
|
import { getTextOptions } from "./lib/get-text-options";
|
||||||
import { getTextFromShareTarget } from "./lib/share-target";
|
import { getTextFromShareTarget } from "./lib/share-target";
|
||||||
import { objIsEqual, userObjIsEqual } from "./lib/misc-helpers";
|
import { objIsEqual, userObjIsEqual } from "./lib/misc-helpers";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
TextOptionsRecord,
|
||||||
|
TextOptionsAction,
|
||||||
|
OptionsAction,
|
||||||
|
} from "./types/dictionary-types";
|
||||||
|
|
||||||
// to allow Moustrap key combos even when input fields are in focus
|
// to allow Moustrap key combos even when input fields are in focus
|
||||||
Mousetrap.prototype.stopCallback = function () {
|
Mousetrap.prototype.stopCallback = function () {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
getAudioAttachment,
|
getAudioAttachment,
|
||||||
} from "../lib/wordlist-database";
|
} from "../lib/wordlist-database";
|
||||||
|
import { WordlistWord } from "../types/dictionary-types";
|
||||||
|
|
||||||
export function AudioPlayButton({ word }: { word: WordlistWord }) {
|
export function AudioPlayButton({ word }: { word: WordlistWord }) {
|
||||||
const [src, setSrc] = useState<string | undefined>(undefined);
|
const [src, setSrc] = useState<string | undefined>(undefined);
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DictionaryStatus } from "../types/dictionary-types";
|
||||||
|
|
||||||
function DictionaryStatusDisplay({ status }: { status: DictionaryStatus }) {
|
function DictionaryStatusDisplay({ status }: { status: DictionaryStatus }) {
|
||||||
if (status === "loading" || status === "updating") {
|
if (status === "loading" || status === "updating") {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
updateWordlistWord,
|
updateWordlistWord,
|
||||||
} from "../lib/wordlist-database";
|
} from "../lib/wordlist-database";
|
||||||
import WordlistImage from "./WordlistImage";
|
import WordlistImage from "./WordlistImage";
|
||||||
|
import { WordlistWord } from "../types/dictionary-types";
|
||||||
|
|
||||||
// TODO: !! remember to save the new dimensions whenever modifying the image
|
// TODO: !! remember to save the new dimensions whenever modifying the image
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ import {
|
||||||
displayFormResult,
|
displayFormResult,
|
||||||
displayPositionResult,
|
displayPositionResult,
|
||||||
} from "../lib/inflection-search-helpers";
|
} from "../lib/inflection-search-helpers";
|
||||||
|
import {
|
||||||
|
InflectionSearchResult,
|
||||||
|
InflectionName,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
function InflectionSearchResult(
|
function InflectionSearchResult(
|
||||||
{ result, textOptions, entry }:
|
{ result, textOptions, entry }:
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
import { State } from "../types/dictionary-types";
|
||||||
|
import {
|
||||||
|
OptionsAction,
|
||||||
|
Language,
|
||||||
|
SearchType,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
const SearchBar = ({ state, optionsDispatch, handleSearchValueChange, onBottom }: {
|
const SearchBar = ({ state, optionsDispatch, handleSearchValueChange, onBottom }: {
|
||||||
state: State
|
state: State
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { getImageAttachment } from "../lib/wordlist-database";
|
import { getImageAttachment } from "../lib/wordlist-database";
|
||||||
|
import { WordlistWord } from "../types/dictionary-types";
|
||||||
|
|
||||||
function WordlistImage({ word }: { word: WordlistWord }) {
|
function WordlistImage({ word }: { word: WordlistWord }) {
|
||||||
const [imgSrc, setImgSrc] = useState<string | undefined>(undefined);
|
const [imgSrc, setImgSrc] = useState<string | undefined>(undefined);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
updateWordlistWord,
|
updateWordlistWord,
|
||||||
hasAttachment,
|
hasAttachment,
|
||||||
} from "../lib/wordlist-database";
|
} from "../lib/wordlist-database";
|
||||||
|
import { WordlistWord } from "../types/dictionary-types";
|
||||||
|
|
||||||
const droppingStyle = {
|
const droppingStyle = {
|
||||||
boxShadow: "0 0 5px rgba(81, 203, 238, 1)",
|
boxShadow: "0 0 5px rgba(81, 203, 238, 1)",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Types as T } from "@lingdocs/pashto-inflector";
|
||||||
import { dictionary } from "../dictionary";
|
import { dictionary } from "../dictionary";
|
||||||
import { baseSupermemo } from "../spaced-repetition";
|
import { baseSupermemo } from "../spaced-repetition";
|
||||||
import { refreshWordlist } from "./pouch-dbs";
|
import { refreshWordlist } from "./pouch-dbs";
|
||||||
|
import { WordlistWord } from "../../types/dictionary-types";
|
||||||
|
|
||||||
let wordlistDb: {
|
let wordlistDb: {
|
||||||
name: string,
|
name: string,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
addToAttachmentObject,
|
addToAttachmentObject,
|
||||||
removeAttachmentFromObject,
|
removeAttachmentFromObject,
|
||||||
} from "./wordlist-database";
|
} from "./wordlist-database";
|
||||||
|
import { WordlistWord, WordlistWordWAttachments } from "../types/dictionary-types";
|
||||||
|
|
||||||
export function addAudioToWordlistWord(word: WordlistWord, file: File): WordlistWord {
|
export function addAudioToWordlistWord(word: WordlistWord, file: File): WordlistWord {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -21,6 +21,10 @@ import { fuzzifyPashto } from "./fuzzify-pashto/fuzzify-pashto";
|
||||||
import relevancy from "relevancy";
|
import relevancy from "relevancy";
|
||||||
import { makeAWeeBitFuzzy } from "./wee-bit-fuzzy";
|
import { makeAWeeBitFuzzy } from "./wee-bit-fuzzy";
|
||||||
import { getTextOptions } from "./get-text-options";
|
import { getTextOptions } from "./get-text-options";
|
||||||
|
import {
|
||||||
|
DictionaryAPI,
|
||||||
|
State,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
// const dictionaryBaseUrl = "https://storage.googleapis.com/lingdocs/";
|
// const dictionaryBaseUrl = "https://storage.googleapis.com/lingdocs/";
|
||||||
const dictionaryUrl = `https://storage.googleapis.com/lingdocs/dictionary`;
|
const dictionaryUrl = `https://storage.googleapis.com/lingdocs/dictionary`;
|
||||||
|
@ -31,22 +35,6 @@ const dictionaryCollectionName = "dictionary3";
|
||||||
// const dictionaryDatabaseName = "dictdb.db";
|
// const dictionaryDatabaseName = "dictdb.db";
|
||||||
export const pageSize = 35;
|
export const pageSize = 35;
|
||||||
|
|
||||||
export type DictionaryAPI = {
|
|
||||||
initialize: () => Promise<{
|
|
||||||
response: "loaded first time" | "loaded from saved",
|
|
||||||
dictionaryInfo: T.DictionaryInfo,
|
|
||||||
}>,
|
|
||||||
update: (updateComing: () => void) => Promise<{
|
|
||||||
response: "no need for update" | "updated" | "unable to check",
|
|
||||||
dictionaryInfo: T.DictionaryInfo,
|
|
||||||
}>,
|
|
||||||
search: (state: State) => T.DictionaryEntry[],
|
|
||||||
exactPashtoSearch: (search: string) => T.DictionaryEntry[],
|
|
||||||
getNewWordsThisMonth: () => T.DictionaryEntry[],
|
|
||||||
findOneByTs: (ts: number) => T.DictionaryEntry | undefined,
|
|
||||||
findRelatedEntries: (entry: T.DictionaryEntry) => T.DictionaryEntry[],
|
|
||||||
}
|
|
||||||
|
|
||||||
const relevancySorter = new relevancy.Sorter();
|
const relevancySorter = new relevancy.Sorter();
|
||||||
|
|
||||||
const db = indexedDB.open('inPrivate');
|
const db = indexedDB.open('inPrivate');
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { Types as T } from "@lingdocs/pashto-inflector";
|
import { Types as T } from "@lingdocs/pashto-inflector";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
export function getTextOptions(state: State): T.TextOptions {
|
export function getTextOptions(state: State): T.TextOptions {
|
||||||
return state.options.textOptionsRecord.textOptions;
|
return state.options.textOptionsRecord.textOptions;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Resizer from "react-image-file-resizer";
|
||||||
import {
|
import {
|
||||||
addToAttachmentObject, removeAttachmentFromObject,
|
addToAttachmentObject, removeAttachmentFromObject,
|
||||||
} from "./wordlist-database";
|
} from "./wordlist-database";
|
||||||
|
import { WordlistWord, WordlistWordWAttachments, AttachmentWithData } from "../types/dictionary-types";
|
||||||
|
|
||||||
const maxImgSize = {
|
const maxImgSize = {
|
||||||
width: 1200,
|
width: 1200,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as AT from "../types/account-types";
|
import * as AT from "../types/account-types";
|
||||||
|
import { Options } from "../types/dictionary-types";
|
||||||
|
|
||||||
export const optionsLocalStorageName = "options3";
|
export const optionsLocalStorageName = "options3";
|
||||||
export const userLocalStorageName = "user1";
|
export const userLocalStorageName = "user1";
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import { Types as IT } from "@lingdocs/pashto-inflector";
|
import { Types as IT } from "@lingdocs/pashto-inflector";
|
||||||
import * as AT from "../types/account-types";
|
import * as AT from "../types/account-types";
|
||||||
|
import {
|
||||||
|
Options,
|
||||||
|
OptionsAction,
|
||||||
|
TextOptionsAction,
|
||||||
|
TextOptionsRecord,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
export function optionsReducer(options: Options, action: OptionsAction): Options {
|
export function optionsReducer(options: Options, action: OptionsAction): Options {
|
||||||
if (action.type === "toggleLanguage") {
|
if (action.type === "toggleLanguage") {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import PouchDB from "pouchdb";
|
import PouchDB from "pouchdb";
|
||||||
import * as AT from "../types/account-types";
|
import * as AT from "../types/account-types";
|
||||||
import * as FT from "../types/functions-types";
|
import * as FT from "../types/functions-types";
|
||||||
|
import {
|
||||||
|
WordlistWord,
|
||||||
|
WordlistWordDoc,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
type LocalDbType = "submissions" | "wordlist" | "reviewTasks";
|
type LocalDbType = "submissions" | "wordlist" | "reviewTasks";
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ import {
|
||||||
getVerbInfo,
|
getVerbInfo,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { isPashtoScript } from "./is-pashto";
|
import { isPashtoScript } from "./is-pashto";
|
||||||
|
import {
|
||||||
|
InflectionSearchResult,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
// 1st iteration: Brute force make every single conjugation and check all - 5300ms
|
// 1st iteration: Brute force make every single conjugation and check all - 5300ms
|
||||||
// 2nd iteration: Check if it makes a big difference to search via function - 5100ms
|
// 2nd iteration: Check if it makes a big difference to search via function - 5100ms
|
||||||
|
|
|
@ -14,6 +14,11 @@ import {
|
||||||
isPluralInflectionSet,
|
isPluralInflectionSet,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { personFromVerbBlockPos } from "@lingdocs/pashto-inflector";
|
import { personFromVerbBlockPos } from "@lingdocs/pashto-inflector";
|
||||||
|
import {
|
||||||
|
InflectionName,
|
||||||
|
PluralInflectionName,
|
||||||
|
InflectionSearchResult,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
const inflectionNames: { inflections: InflectionName[], plural: PluralInflectionName[] } = {
|
const inflectionNames: { inflections: InflectionName[], plural: PluralInflectionName[] } = {
|
||||||
inflections: ["plain", "1st", "2nd"],
|
inflections: ["plain", "1st", "2nd"],
|
||||||
|
|
|
@ -15,6 +15,9 @@ import dayjs from "dayjs";
|
||||||
import {
|
import {
|
||||||
getMillisecondsPeriod,
|
getMillisecondsPeriod,
|
||||||
} from "./time-utils";
|
} from "./time-utils";
|
||||||
|
import {
|
||||||
|
WordlistWord,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
/* starting stage of review, based on Pimseleur intervals */
|
/* starting stage of review, based on Pimseleur intervals */
|
||||||
const warmupIntervals = [
|
const warmupIntervals = [
|
||||||
|
|
|
@ -26,6 +26,12 @@ import {
|
||||||
prepBase64,
|
prepBase64,
|
||||||
} from "./image-tools";
|
} from "./image-tools";
|
||||||
import { getMillisecondsPeriod } from "./time-utils";
|
import { getMillisecondsPeriod } from "./time-utils";
|
||||||
|
import {
|
||||||
|
WordlistWord,
|
||||||
|
AttachmentType,
|
||||||
|
Attachments,
|
||||||
|
AttachmentToPut,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
export async function addToWordlist({ entry, notes }: {
|
export async function addToWordlist({ entry, notes }: {
|
||||||
entry: T.DictionaryEntry,
|
entry: T.DictionaryEntry,
|
||||||
|
@ -79,6 +85,7 @@ export async function getWordlistCsv(sortType: "alphabetical" | "time"): Promise
|
||||||
[w.entry.p, w.entry.f, w.entry.c, w.entry.e]
|
[w.entry.p, w.entry.f, w.entry.c, w.entry.e]
|
||||||
));
|
));
|
||||||
if (sortType === "alphabetical") {
|
if (sortType === "alphabetical") {
|
||||||
|
// @ts-ignore
|
||||||
forCsv.sort((a, b) => a[0].localeCompare(b[0], "ps"));
|
forCsv.sort((a, b) => a[0].localeCompare(b[0], "ps"));
|
||||||
}
|
}
|
||||||
const csv = Papa.unparse(forCsv);
|
const csv = Papa.unparse(forCsv);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { State } from "../types/dictionary-types";
|
||||||
|
|
||||||
const About = ({ state } : { state: State }) => (
|
const About = ({ state } : { state: State }) => (
|
||||||
<div className="width-limiter">
|
<div className="width-limiter">
|
||||||
|
|
|
@ -11,7 +11,6 @@ import classNames from "classnames";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { VPExplorer } from "@lingdocs/pashto-inflector";
|
import { VPExplorer } from "@lingdocs/pashto-inflector";
|
||||||
import { entryFeeder } from "../lib/dictionary";
|
import { entryFeeder } from "../lib/dictionary";
|
||||||
import { DictionaryAPI } from "../lib/dictionary";
|
|
||||||
import {
|
import {
|
||||||
ConjugationViewer,
|
ConjugationViewer,
|
||||||
InflectionsTable,
|
InflectionsTable,
|
||||||
|
@ -30,6 +29,7 @@ import {
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { TextOptions } from "@lingdocs/pashto-inflector/dist/types";
|
import { TextOptions } from "@lingdocs/pashto-inflector/dist/types";
|
||||||
import * as AT from "../types/account-types";
|
import * as AT from "../types/account-types";
|
||||||
|
import { DictionaryAPI } from "../types/dictionary-types";
|
||||||
|
|
||||||
const textFields: {field: T.DictionaryEntryTextField, label: string}[] = [
|
const textFields: {field: T.DictionaryEntryTextField, label: string}[] = [
|
||||||
{ field: "p", label: "Pashto" },
|
{ field: "p", label: "Pashto" },
|
||||||
|
|
|
@ -35,8 +35,11 @@ import { Modal } from "react-bootstrap";
|
||||||
import { getTextOptions } from "../lib/get-text-options";
|
import { getTextOptions } from "../lib/get-text-options";
|
||||||
import {
|
import {
|
||||||
entryFeeder,
|
entryFeeder,
|
||||||
DictionaryAPI,
|
|
||||||
} from "../lib/dictionary";
|
} from "../lib/dictionary";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
DictionaryAPI,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
||||||
state: State,
|
state: State,
|
||||||
|
|
|
@ -11,6 +11,15 @@ import {
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { wordlistEnabled } from "../lib/level-management";
|
import { wordlistEnabled } from "../lib/level-management";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
Options,
|
||||||
|
PTextSize,
|
||||||
|
SearchBarPosition,
|
||||||
|
Theme,
|
||||||
|
OptionsAction,
|
||||||
|
TextOptionsAction,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
const fontSizeOptions: {
|
const fontSizeOptions: {
|
||||||
label: string,
|
label: string,
|
||||||
|
|
|
@ -21,9 +21,13 @@ import {
|
||||||
Types as T,
|
Types as T,
|
||||||
revertSpelling,
|
revertSpelling,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import InflectionSearchResult from "../components/InflectionSearchResult";
|
import InflectionSearchResultDisplay from "../components/InflectionSearchResult";
|
||||||
import { searchAllInflections } from "../lib/search-all-inflections";
|
import { searchAllInflections } from "../lib/search-all-inflections";
|
||||||
import { getTextOptions } from "../lib/get-text-options";
|
import { getTextOptions } from "../lib/get-text-options";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
InflectionSearchResult,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
const inflectionSearchIcon = "fas fa-search-plus";
|
const inflectionSearchIcon = "fas fa-search-plus";
|
||||||
|
|
||||||
|
@ -125,7 +129,7 @@ function Results({ state, isolateEntry }: {
|
||||||
/>
|
/>
|
||||||
<div className="mb-3 ml-2">
|
<div className="mb-3 ml-2">
|
||||||
{p.results.map((result: InflectionSearchResult, i) => (
|
{p.results.map((result: InflectionSearchResult, i) => (
|
||||||
<InflectionSearchResult
|
<InflectionSearchResultDisplay
|
||||||
key={"inf-result" + i}
|
key={"inf-result" + i}
|
||||||
textOptions={textOptions}
|
textOptions={textOptions}
|
||||||
result={result}
|
result={result}
|
||||||
|
|
|
@ -9,6 +9,9 @@ import {
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { getTextOptions } from "../lib/get-text-options";
|
import { getTextOptions } from "../lib/get-text-options";
|
||||||
|
import {
|
||||||
|
State,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
function ReviewTask({ reviewTask, textOptions }: { reviewTask: FT.ReviewTask, textOptions: T.TextOptions }) {
|
function ReviewTask({ reviewTask, textOptions }: { reviewTask: FT.ReviewTask, textOptions: T.TextOptions }) {
|
||||||
function handleDelete() {
|
function handleDelete() {
|
||||||
|
|
|
@ -44,6 +44,13 @@ import AudioPlayButton from "../components/AudioPlayButton";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import relativeTime from "dayjs/plugin/relativeTime.js";
|
import relativeTime from "dayjs/plugin/relativeTime.js";
|
||||||
import hitBottom from "../lib/hitBottom";
|
import hitBottom from "../lib/hitBottom";
|
||||||
|
import {
|
||||||
|
Options,
|
||||||
|
WordlistWord,
|
||||||
|
Language,
|
||||||
|
OptionsAction,
|
||||||
|
WordlistMode,
|
||||||
|
} from "../types/dictionary-types";
|
||||||
|
|
||||||
const cleanupIcon = "broom";
|
const cleanupIcon = "broom";
|
||||||
|
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2021 lingdocs.com
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
type DictionaryStatus = "loading" | "ready" | "updating" | "error loading";
|
|
||||||
type Language = "Pashto" | "English";
|
|
||||||
type SearchType = "alphabetical" | "fuzzy";
|
|
||||||
type Theme = "light" | "dark";
|
|
||||||
type PTextSize = "normal" | "larger" | "largest";
|
|
||||||
type Phonetics = "lingdocs" | "ipa" | "alalc" | "none";
|
|
||||||
type Dialect = "standard" | "peshawer" | "southern";
|
|
||||||
type SearchBarPosition = "top" | "bottom";
|
|
||||||
|
|
||||||
type WordlistMode = "browse" | "review";
|
|
||||||
|
|
||||||
type TextOptionsRecord = {
|
|
||||||
lastModified: import("./types/account-types").TimeStamp,
|
|
||||||
textOptions: import("@lingdocs/pashto-inflector").Types.TextOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Options = {
|
|
||||||
language: Language,
|
|
||||||
searchType: SearchType,
|
|
||||||
theme: Theme,
|
|
||||||
textOptionsRecord: TextOptionsRecord,
|
|
||||||
wordlistMode: WordlistMode,
|
|
||||||
wordlistReviewLanguage: Language,
|
|
||||||
wordlistReviewBadge: boolean,
|
|
||||||
searchBarPosition: SearchBarPosition,
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserLevel = "basic" | "student" | "editor";
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
dictionaryStatus: DictionaryStatus,
|
|
||||||
searchValue: string,
|
|
||||||
options: Options,
|
|
||||||
page: number,
|
|
||||||
isolatedEntry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry | undefined,
|
|
||||||
results: import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
|
||||||
wordlist: WordlistWord[],
|
|
||||||
reviewTasks: import("./types/functions-types").ReviewTask[],
|
|
||||||
dictionaryInfo: import("@lingdocs/pashto-inflector").Types.DictionaryInfo | undefined,
|
|
||||||
user: undefined | AT.LingdocsUser,
|
|
||||||
}
|
|
||||||
|
|
||||||
type OptionsAction = {
|
|
||||||
type: "toggleSearchType",
|
|
||||||
} | {
|
|
||||||
type: "toggleLanguage",
|
|
||||||
} | {
|
|
||||||
type: "changeTheme",
|
|
||||||
payload: Theme,
|
|
||||||
} | {
|
|
||||||
type: "changeSearchBarPosition",
|
|
||||||
payload: SearchBarPosition,
|
|
||||||
} | {
|
|
||||||
type: "changeUserLevel",
|
|
||||||
payload: UserLevel,
|
|
||||||
} | {
|
|
||||||
type: "changeWordlistMode",
|
|
||||||
payload: WordlistMode,
|
|
||||||
} | {
|
|
||||||
type: "changeWordlistReviewLanguage",
|
|
||||||
payload: Language,
|
|
||||||
} | {
|
|
||||||
type: "changeWordlistReviewBadge",
|
|
||||||
payload: boolean,
|
|
||||||
} | {
|
|
||||||
type: "updateTextOptionsRecord",
|
|
||||||
payload: TextOptionsRecord,
|
|
||||||
};
|
|
||||||
|
|
||||||
type TextOptionsAction = {
|
|
||||||
type: "changePTextSize",
|
|
||||||
payload: PTextSize,
|
|
||||||
} | {
|
|
||||||
type: "changeSpelling",
|
|
||||||
payload: import("@lingdocs/pashto-inflector").Types.Spelling,
|
|
||||||
} | {
|
|
||||||
type: "changePhonetics",
|
|
||||||
payload: import("@lingdocs/pashto-inflector").Types.Phonetics,
|
|
||||||
} | {
|
|
||||||
type: "changeDialect",
|
|
||||||
payload: import("@lingdocs/pashto-inflector").Types.Dialect,
|
|
||||||
} | {
|
|
||||||
type: "changeDiacritics",
|
|
||||||
payload: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
type AttachmentToPut = {
|
|
||||||
content_type: string,
|
|
||||||
data: string | blob,
|
|
||||||
}
|
|
||||||
|
|
||||||
type AttachmentWithData = {
|
|
||||||
content_type: string,
|
|
||||||
digest: string,
|
|
||||||
data: string | blob,
|
|
||||||
}
|
|
||||||
|
|
||||||
type AttachmentWOutData = {
|
|
||||||
content_type: string,
|
|
||||||
digest: string,
|
|
||||||
stub: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Attachment = AttachmentToPut | AttachmentWithData | AttachmentWOutData
|
|
||||||
type AttachmentType = "image" | "audio";
|
|
||||||
type Attachments = {
|
|
||||||
/* only allows one image and one audio attachment - max 2 values */
|
|
||||||
[filename: string]: Attachment,
|
|
||||||
};
|
|
||||||
|
|
||||||
type WordlistWordBase = {
|
|
||||||
_id: string,
|
|
||||||
/* a backup copy of the full dictionary entry in case it gets deleted from the dictionary */
|
|
||||||
entry: T.DictionaryEntry,
|
|
||||||
/* the notes/context provided by the user for the word in their wordlist */
|
|
||||||
notes: string,
|
|
||||||
supermemo: import("supermemo").SuperMemoItem,
|
|
||||||
/* rep/stage of warmup stage before moving into supermemo mode */
|
|
||||||
warmup: number | "done",
|
|
||||||
/* date due for review - ISO string */
|
|
||||||
dueDate: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
type WordlistAttachmentInfo = {
|
|
||||||
imgSize?: { height: number, width: number },
|
|
||||||
_attachments: Attachments,
|
|
||||||
}
|
|
||||||
|
|
||||||
type WordlistWordWAttachments = WordlistWordBase & WordlistAttachmentInfo;
|
|
||||||
|
|
||||||
type WordlistWord = WordlistWordBase | WordlistWordWAttachments;
|
|
||||||
|
|
||||||
type WordlistWordDoc = WordlistWord & { _rev: string, _id: string };
|
|
||||||
|
|
||||||
type InflectionName = "plain" | "1st" | "2nd";
|
|
||||||
|
|
||||||
type PluralInflectionName = "plural" | "2nd";
|
|
||||||
|
|
||||||
type InflectionSearchResult = {
|
|
||||||
form: string[],
|
|
||||||
matches: {
|
|
||||||
ps: T.PsString,
|
|
||||||
pos: InflectionName[] | import("@lingdocs/pashto-inflector").Types.Person[] | null,
|
|
||||||
}[],
|
|
||||||
};
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
export type DictionaryStatus = "loading" | "ready" | "updating" | "error loading";
|
||||||
|
|
||||||
|
export type State = {
|
||||||
|
dictionaryStatus: DictionaryStatus,
|
||||||
|
searchValue: string,
|
||||||
|
options: Options,
|
||||||
|
page: number,
|
||||||
|
isolatedEntry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry | undefined,
|
||||||
|
results: import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
||||||
|
wordlist: WordlistWord[],
|
||||||
|
reviewTasks: import("./functions-types").ReviewTask[],
|
||||||
|
dictionaryInfo: import("@lingdocs/pashto-inflector").Types.DictionaryInfo | undefined,
|
||||||
|
user: undefined | import("./account-types").LingdocsUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DictionaryAPI = {
|
||||||
|
initialize: () => Promise<{
|
||||||
|
response: "loaded first time" | "loaded from saved",
|
||||||
|
dictionaryInfo: import("@lingdocs/pashto-inflector").Types.DictionaryInfo,
|
||||||
|
}>,
|
||||||
|
update: (updateComing: () => void) => Promise<{
|
||||||
|
response: "no need for update" | "updated" | "unable to check",
|
||||||
|
dictionaryInfo: import("@lingdocs/pashto-inflector").Types.DictionaryInfo,
|
||||||
|
}>,
|
||||||
|
search: (state: State) => import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
||||||
|
exactPashtoSearch: (search: string) => import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
||||||
|
getNewWordsThisMonth: () => import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
||||||
|
findOneByTs: (ts: number) => import("@lingdocs/pashto-inflector").Types.DictionaryEntry | undefined,
|
||||||
|
findRelatedEntries: (entry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry) => import("@lingdocs/pashto-inflector").Types.DictionaryEntry[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WordlistWordBase = {
|
||||||
|
_id: string,
|
||||||
|
/* a backup copy of the full dictionary entry in case it gets deleted from the dictionary */
|
||||||
|
entry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry,
|
||||||
|
/* the notes/context provided by the user for the word in their wordlist */
|
||||||
|
notes: string,
|
||||||
|
supermemo: import("supermemo").SuperMemoItem,
|
||||||
|
/* rep/stage of warmup stage before moving into supermemo mode */
|
||||||
|
warmup: number | "done",
|
||||||
|
/* date due for review - ISO string */
|
||||||
|
dueDate: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WordlistAttachmentInfo = {
|
||||||
|
imgSize?: { height: number, width: number },
|
||||||
|
_attachments: Attachments,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WordlistWordWAttachments = WordlistWordBase & WordlistAttachmentInfo;
|
||||||
|
|
||||||
|
export type WordlistWord = WordlistWordBase | WordlistWordWAttachments;
|
||||||
|
|
||||||
|
export type Options = {
|
||||||
|
language: Language,
|
||||||
|
searchType: SearchType,
|
||||||
|
theme: Theme,
|
||||||
|
textOptionsRecord: TextOptionsRecord,
|
||||||
|
wordlistMode: WordlistMode,
|
||||||
|
wordlistReviewLanguage: Language,
|
||||||
|
wordlistReviewBadge: boolean,
|
||||||
|
searchBarPosition: SearchBarPosition,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Language = "Pashto" | "English";
|
||||||
|
export type SearchType = "alphabetical" | "fuzzy";
|
||||||
|
export type Theme = "light" | "dark";
|
||||||
|
export type PTextSize = "normal" | "larger" | "largest";
|
||||||
|
export type Phonetics = "lingdocs" | "ipa" | "alalc" | "none";
|
||||||
|
export type Dialect = "standard" | "peshawer" | "southern";
|
||||||
|
export type SearchBarPosition = "top" | "bottom";
|
||||||
|
|
||||||
|
export type WordlistMode = "browse" | "review";
|
||||||
|
|
||||||
|
export type TextOptionsRecord = {
|
||||||
|
lastModified: import("./account-types").TimeStamp,
|
||||||
|
textOptions: import("@lingdocs/pashto-inflector").Types.TextOptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserLevel = "basic" | "student" | "editor";
|
||||||
|
|
||||||
|
export type OptionsAction = {
|
||||||
|
type: "toggleSearchType",
|
||||||
|
} | {
|
||||||
|
type: "toggleLanguage",
|
||||||
|
} | {
|
||||||
|
type: "changeTheme",
|
||||||
|
payload: Theme,
|
||||||
|
} | {
|
||||||
|
type: "changeSearchBarPosition",
|
||||||
|
payload: SearchBarPosition,
|
||||||
|
} | {
|
||||||
|
type: "changeUserLevel",
|
||||||
|
payload: UserLevel,
|
||||||
|
} | {
|
||||||
|
type: "changeWordlistMode",
|
||||||
|
payload: WordlistMode,
|
||||||
|
} | {
|
||||||
|
type: "changeWordlistReviewLanguage",
|
||||||
|
payload: Language,
|
||||||
|
} | {
|
||||||
|
type: "changeWordlistReviewBadge",
|
||||||
|
payload: boolean,
|
||||||
|
} | {
|
||||||
|
type: "updateTextOptionsRecord",
|
||||||
|
payload: TextOptionsRecord,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TextOptionsAction = {
|
||||||
|
type: "changePTextSize",
|
||||||
|
payload: PTextSize,
|
||||||
|
} | {
|
||||||
|
type: "changeSpelling",
|
||||||
|
payload: import("@lingdocs/pashto-inflector").Types.Spelling,
|
||||||
|
} | {
|
||||||
|
type: "changePhonetics",
|
||||||
|
payload: "lingdocs" | "ipa" | "alalc" | "none",
|
||||||
|
} | {
|
||||||
|
type: "changeDialect",
|
||||||
|
payload: "standard" | "peshawer" | "southern",
|
||||||
|
} | {
|
||||||
|
type: "changeDiacritics",
|
||||||
|
payload: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AttachmentToPut = {
|
||||||
|
content_type: string,
|
||||||
|
data: string | Blob,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AttachmentWithData = {
|
||||||
|
content_type: string,
|
||||||
|
digest: string,
|
||||||
|
data: string | Blob,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AttachmentWOutData = {
|
||||||
|
content_type: string,
|
||||||
|
digest: string,
|
||||||
|
stub: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Attachment = AttachmentToPut | AttachmentWithData | AttachmentWOutData
|
||||||
|
export type AttachmentType = "image" | "audio";
|
||||||
|
export type Attachments = {
|
||||||
|
/* only allows one image and one audio attachment - max 2 values */
|
||||||
|
[filename: string]: Attachment,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WordlistWordDoc = WordlistWord & { _rev: string, _id: string };
|
||||||
|
|
||||||
|
export type InflectionName = "plain" | "1st" | "2nd";
|
||||||
|
|
||||||
|
export type PluralInflectionName = "plural" | "2nd";
|
||||||
|
|
||||||
|
export type InflectionSearchResult = {
|
||||||
|
form: string[],
|
||||||
|
matches: {
|
||||||
|
ps: import("@lingdocs/pashto-inflector").Types.PsString,
|
||||||
|
pos: InflectionName[] | import("@lingdocs/pashto-inflector").Types.Person[] | null,
|
||||||
|
}[],
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue