update ga
This commit is contained in:
parent
ab0916aadd
commit
211d9b3446
|
@ -31,7 +31,7 @@
|
|||
"react-bootstrap": "^1.5.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-dropzone": "^11.3.2",
|
||||
"react-ga": "^3.3.0",
|
||||
"react-ga4": "^2.1.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-crop": "^8.6.9",
|
||||
"react-image-file-resizer": "^0.4.4",
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
// sync on initialization and cancel sync on de-initialization
|
||||
|
||||
import { Component } from "react";
|
||||
import { defaultTextOptions, revertSpelling, standardizePashto, Types as T } from "@lingdocs/ps-react";
|
||||
import {
|
||||
defaultTextOptions,
|
||||
revertSpelling,
|
||||
standardizePashto,
|
||||
Types as T,
|
||||
} from "@lingdocs/ps-react";
|
||||
import { withRouter, Route, RouteComponentProps, Link } from "react-router-dom";
|
||||
import Helmet from "react-helmet";
|
||||
import BottomNavItem from "./components/BottomNavItem";
|
||||
|
@ -32,36 +37,23 @@ import {
|
|||
readUser,
|
||||
} from "./lib/local-storage";
|
||||
import { allEntries, dictionary, pageSize } from "./lib/dictionary";
|
||||
import {
|
||||
optionsReducer,
|
||||
textOptionsReducer,
|
||||
} from "./lib/options-reducer";
|
||||
import { optionsReducer, textOptionsReducer } from "./lib/options-reducer";
|
||||
import hitBottom from "./lib/hitBottom";
|
||||
import getWordId from "./lib/get-word-id";
|
||||
import { CronJob } from "cron";
|
||||
import Mousetrap from "mousetrap";
|
||||
import {
|
||||
sendSubmissions,
|
||||
} from "./lib/submissions";
|
||||
import {
|
||||
getUser,
|
||||
} from "./lib/backend-calls";
|
||||
import {
|
||||
getWordlist,
|
||||
} from "./lib/wordlist-database";
|
||||
import { sendSubmissions } from "./lib/submissions";
|
||||
import { getUser } from "./lib/backend-calls";
|
||||
import { getWordlist } from "./lib/wordlist-database";
|
||||
import {
|
||||
startLocalDbs,
|
||||
stopLocalDbs,
|
||||
getAllDocsLocalDb,
|
||||
} from "./lib/pouch-dbs";
|
||||
import {
|
||||
forReview,
|
||||
} from "./lib/spaced-repetition";
|
||||
import {
|
||||
textBadge,
|
||||
} from "./lib/badges";
|
||||
import { forReview } from "./lib/spaced-repetition";
|
||||
import { textBadge } from "./lib/badges";
|
||||
import * as AT from "./types/account-types";
|
||||
import ReactGA from "react-ga";
|
||||
import ReactGA from "react-ga4";
|
||||
// tslint:disable-next-line
|
||||
import "@fortawesome/fontawesome-free/css/all.css";
|
||||
import "./custom-bootstrap.css";
|
||||
|
@ -78,31 +70,35 @@ import {
|
|||
} from "./types/dictionary-types";
|
||||
import PhraseBuilder from "./screens/PhraseBuilder";
|
||||
import { searchAllInflections } from "./lib/search-all-inflections";
|
||||
import {
|
||||
addToWordlist,
|
||||
} from "./lib/wordlist-database";
|
||||
import { addToWordlist } from "./lib/wordlist-database";
|
||||
import ScriptToPhonetics from "./screens/ScriptToPhonetics";
|
||||
|
||||
// to allow Moustrap key combos even when input fields are in focus
|
||||
Mousetrap.prototype.stopCallback = function () {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const prod = document.location.hostname === "dictionary.lingdocs.com";
|
||||
|
||||
if (prod) {
|
||||
// TODO: migrate to https://www.npmjs.com/package/react-ga4
|
||||
ReactGA.initialize("UA-196576671-1");
|
||||
ReactGA.initialize("386396674");
|
||||
ReactGA.set({ anonymizeIp: true });
|
||||
}
|
||||
|
||||
const possibleLandingPages = [
|
||||
"/", "/about", "/settings", "/word", "/account", "/new-entries", "/share-target", "/phrase-builder",
|
||||
"/privacy", "/script-to-phonetics"
|
||||
];
|
||||
const editorOnlyPages = [
|
||||
"/edit", "/review-tasks",
|
||||
"/",
|
||||
"/about",
|
||||
"/settings",
|
||||
"/word",
|
||||
"/account",
|
||||
"/new-entries",
|
||||
"/share-target",
|
||||
"/phrase-builder",
|
||||
"/privacy",
|
||||
"/script-to-phonetics",
|
||||
];
|
||||
const editorOnlyPages = ["/edit", "/review-tasks"];
|
||||
|
||||
class App extends Component<RouteComponentProps, State> {
|
||||
constructor(props: RouteComponentProps) {
|
||||
|
@ -112,11 +108,15 @@ class App extends Component<RouteComponentProps, State> {
|
|||
dictionaryStatus: "loading",
|
||||
dictionaryInfo: undefined,
|
||||
// TODO: Choose between the saved options and the options in the saved user
|
||||
options: savedOptions ? savedOptions : {
|
||||
options: savedOptions
|
||||
? savedOptions
|
||||
: {
|
||||
language: "Pashto",
|
||||
searchType: "fuzzy",
|
||||
searchBarStickyFocus: false,
|
||||
theme: (window.matchMedia?.("(prefers-color-scheme: dark)").matches) ? "dark" : "light",
|
||||
theme: window.matchMedia?.("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light",
|
||||
textOptionsRecord: {
|
||||
lastModified: Date.now() as AT.TimeStamp,
|
||||
textOptions: defaultTextOptions,
|
||||
|
@ -133,7 +133,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
wordlist: [],
|
||||
reviewTasks: [],
|
||||
user: readUser(),
|
||||
inflectionSearchResults: undefined
|
||||
inflectionSearchResults: undefined,
|
||||
};
|
||||
this.handleOptionsUpdate = this.handleOptionsUpdate.bind(this);
|
||||
this.handleTextOptionsUpdate = this.handleTextOptionsUpdate.bind(this);
|
||||
|
@ -153,10 +153,15 @@ class App extends Component<RouteComponentProps, State> {
|
|||
if (!possibleLandingPages.includes(this.props.location.pathname)) {
|
||||
this.props.history.replace("/");
|
||||
}
|
||||
if (prod && (!(this.state.user?.level === "editor"))) {
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
if (prod && !(this.state.user?.level === "editor")) {
|
||||
ReactGA.send({
|
||||
hitType: "pageview",
|
||||
page: window.location.pathname + window.location.search,
|
||||
});
|
||||
}
|
||||
dictionary.initialize().then((r) => {
|
||||
dictionary
|
||||
.initialize()
|
||||
.then((r) => {
|
||||
this.cronJob.start();
|
||||
this.setState({
|
||||
dictionaryStatus: "ready",
|
||||
|
@ -165,7 +170,10 @@ class App extends Component<RouteComponentProps, State> {
|
|||
this.handleLoadUser();
|
||||
// incase it took forever and timed out - might need to reinitialize the wordlist here ??
|
||||
if (this.state.user) {
|
||||
startLocalDbs(this.state.user, { wordlist: this.handleRefreshWordlist, reviewTasks: this.handleRefreshReviewTasks });
|
||||
startLocalDbs(this.state.user, {
|
||||
wordlist: this.handleRefreshWordlist,
|
||||
reviewTasks: this.handleRefreshReviewTasks,
|
||||
});
|
||||
}
|
||||
if (this.props.location.pathname === "/word") {
|
||||
const wordId = getWordId(this.props.location.search);
|
||||
|
@ -201,20 +209,28 @@ class App extends Component<RouteComponentProps, State> {
|
|||
if (r.response === "loaded from saved") {
|
||||
this.handleDictionaryUpdate();
|
||||
}
|
||||
}).catch((error) => {
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
this.setState({ dictionaryStatus: "error loading" });
|
||||
});
|
||||
document.documentElement.setAttribute("data-theme", this.state.options.theme);
|
||||
document.documentElement.setAttribute(
|
||||
"data-theme",
|
||||
this.state.options.theme
|
||||
);
|
||||
/* istanbul ignore if */
|
||||
if (window.matchMedia) {
|
||||
const prefersDarkQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const prefersDarkQuery = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
);
|
||||
prefersDarkQuery.addListener((e) => {
|
||||
if (e.matches) {
|
||||
this.handleOptionsUpdate({ type: "changeTheme", payload: "dark" });
|
||||
}
|
||||
});
|
||||
const prefersLightQuery = window.matchMedia("(prefers-color-scheme: light)");
|
||||
const prefersLightQuery = window.matchMedia(
|
||||
"(prefers-color-scheme: light)"
|
||||
);
|
||||
prefersLightQuery.addListener((e) => {
|
||||
if (e.matches) {
|
||||
this.handleOptionsUpdate({ type: "changeTheme", payload: "light" });
|
||||
|
@ -235,14 +251,17 @@ class App extends Component<RouteComponentProps, State> {
|
|||
return;
|
||||
}
|
||||
this.handleIsolateEntry(toIsolate.ts);
|
||||
})
|
||||
Mousetrap.bind(["ctrl+down", "ctrl+up", "command+down", "command+up"], (e) => {
|
||||
});
|
||||
Mousetrap.bind(
|
||||
["ctrl+down", "ctrl+up", "command+down", "command+up"],
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
if (e.repeat) {
|
||||
return;
|
||||
}
|
||||
this.handleOptionsUpdate({ type: "toggleLanguage" });
|
||||
});
|
||||
}
|
||||
);
|
||||
Mousetrap.bind(["ctrl+b", "command+b"], (e) => {
|
||||
e.preventDefault();
|
||||
if (e.repeat) {
|
||||
|
@ -304,8 +323,11 @@ class App extends Component<RouteComponentProps, State> {
|
|||
|
||||
public componentDidUpdate(prevProps: RouteComponentProps) {
|
||||
if (this.props.location.pathname !== prevProps.location.pathname) {
|
||||
if (prod && (!(this.state.user?.level === "editor"))) {
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
if (prod && !(this.state.user?.level === "editor")) {
|
||||
ReactGA.send({
|
||||
hitType: "pageview",
|
||||
page: window.location.pathname + window.location.search,
|
||||
});
|
||||
}
|
||||
if (this.props.location.pathname === "/") {
|
||||
this.handleSearchValueChange("");
|
||||
|
@ -316,20 +338,29 @@ class App extends Component<RouteComponentProps, State> {
|
|||
page: 1,
|
||||
});
|
||||
}
|
||||
if (editorOnlyPages.includes(this.props.location.pathname) && !(this.state.user?.level === "editor")) {
|
||||
if (
|
||||
editorOnlyPages.includes(this.props.location.pathname) &&
|
||||
!(this.state.user?.level === "editor")
|
||||
) {
|
||||
this.props.history.replace("/");
|
||||
}
|
||||
}
|
||||
if (getWordId(this.props.location.search) !== getWordId(prevProps.location.search)) {
|
||||
if (prod && ((this.state.user?.level !== "editor"))) {
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
if (
|
||||
getWordId(this.props.location.search) !==
|
||||
getWordId(prevProps.location.search)
|
||||
) {
|
||||
if (prod && this.state.user?.level !== "editor") {
|
||||
ReactGA.send({
|
||||
type: "pageview",
|
||||
page: window.location.pathname + window.location.search,
|
||||
});
|
||||
}
|
||||
const wordId = getWordId(this.props.location.search);
|
||||
/* istanbul ignore else */
|
||||
if (wordId) {
|
||||
this.handleIsolateEntry(wordId, true);
|
||||
} else {
|
||||
this.setState({ isolatedEntry: undefined })
|
||||
this.setState({ isolatedEntry: undefined });
|
||||
}
|
||||
}
|
||||
// if (!["/wordlist", "/settings", "/review-tasks"].includes(this.props.location.pathname)) {
|
||||
|
@ -356,12 +387,17 @@ class App extends Component<RouteComponentProps, State> {
|
|||
return;
|
||||
}
|
||||
if (!userObjIsEqual(prevUser, user)) {
|
||||
console.log("setting state user because something is different about the user")
|
||||
console.log(
|
||||
"setting state user because something is different about the user"
|
||||
);
|
||||
this.setState({ user });
|
||||
saveUser(user);
|
||||
}
|
||||
if (user) {
|
||||
startLocalDbs(user, { wordlist: this.handleRefreshWordlist, reviewTasks: this.handleRefreshReviewTasks });
|
||||
startLocalDbs(user, {
|
||||
wordlist: this.handleRefreshWordlist,
|
||||
reviewTasks: this.handleRefreshReviewTasks,
|
||||
});
|
||||
} else {
|
||||
stopLocalDbs();
|
||||
}
|
||||
|
@ -372,9 +408,11 @@ class App extends Component<RouteComponentProps, State> {
|
|||
|
||||
private handleDictionaryUpdate() {
|
||||
// TODO: fix - what the heck happened and what's going on here
|
||||
dictionary.update(() => {
|
||||
dictionary
|
||||
.update(() => {
|
||||
// this.setState({ dictionaryStatus: "updating" });
|
||||
}).then(({ dictionaryInfo }) => {
|
||||
})
|
||||
.then(({ dictionaryInfo }) => {
|
||||
//if (this.state.dictionaryInfo?.release !== dictionaryInfo?.release) {
|
||||
// to avoid unnecessary re-rendering that breaks things
|
||||
this.setState({
|
||||
|
@ -382,7 +420,8 @@ class App extends Component<RouteComponentProps, State> {
|
|||
dictionaryInfo,
|
||||
});
|
||||
//}
|
||||
}).catch(() => {
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({ dictionaryStatus: "error loading" });
|
||||
});
|
||||
}
|
||||
|
@ -394,9 +433,12 @@ class App extends Component<RouteComponentProps, State> {
|
|||
// TODO: use a seperate reducer for changing text options (otherwise you could just be updating the saved text options instead of the user text options that the program is going off of)
|
||||
const options = optionsReducer(this.state.options, action);
|
||||
saveOptions(options);
|
||||
if (action.type === "toggleLanguage" || action.type === "toggleSearchType") {
|
||||
if (
|
||||
action.type === "toggleLanguage" ||
|
||||
action.type === "toggleSearchType"
|
||||
) {
|
||||
if (this.props.location.pathname !== "/new-entries") {
|
||||
this.setState(prevState => ({
|
||||
this.setState((prevState) => ({
|
||||
options,
|
||||
page: 1,
|
||||
results: dictionary.search({ ...prevState, options }),
|
||||
|
@ -417,17 +459,20 @@ class App extends Component<RouteComponentProps, State> {
|
|||
lastModified,
|
||||
textOptions,
|
||||
};
|
||||
this.handleOptionsUpdate({ type: "updateTextOptionsRecord", payload: textOptionsRecord });
|
||||
this.handleOptionsUpdate({
|
||||
type: "updateTextOptionsRecord",
|
||||
payload: textOptionsRecord,
|
||||
});
|
||||
}
|
||||
|
||||
private handleSearchValueChange(searchValue: string) {
|
||||
if (searchValue === " ") {
|
||||
return;
|
||||
}
|
||||
const lastChar = searchValue[searchValue.length-1];
|
||||
const lastChar = searchValue[searchValue.length - 1];
|
||||
// don't let people type in a single digit (to allow for number shortcuts)
|
||||
// but do allow the whole thing to be numbers (to allow for pasting and searching for ts)
|
||||
if (lastChar >= '0' && lastChar <= '9' && !(/^\d+$/.test(searchValue))) {
|
||||
if (lastChar >= "0" && lastChar <= "9" && !/^\d+$/.test(searchValue)) {
|
||||
return;
|
||||
}
|
||||
if (this.state.dictionaryStatus !== "ready") {
|
||||
|
@ -445,7 +490,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
}
|
||||
return;
|
||||
}
|
||||
this.setState(prevState => ({
|
||||
this.setState((prevState) => ({
|
||||
searchValue,
|
||||
results: dictionary.search({ ...prevState, searchValue }),
|
||||
page: 1,
|
||||
|
@ -465,7 +510,11 @@ class App extends Component<RouteComponentProps, State> {
|
|||
return;
|
||||
}
|
||||
this.setState({ isolatedEntry });
|
||||
if (!onlyState && (this.props.location.pathname !== "/word" || (getWordId(this.props.location.search) !== ts))) {
|
||||
if (
|
||||
!onlyState &&
|
||||
(this.props.location.pathname !== "/word" ||
|
||||
getWordId(this.props.location.search) !== ts)
|
||||
) {
|
||||
this.props.history.push(`/word?id=${isolatedEntry.ts}`);
|
||||
}
|
||||
}
|
||||
|
@ -475,11 +524,15 @@ class App extends Component<RouteComponentProps, State> {
|
|||
private cronJob = new CronJob("1/10 * * * *", () => {
|
||||
this.handleDictionaryUpdate();
|
||||
this.handleLoadUser();
|
||||
})
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
private handleScroll() {
|
||||
if (hitBottom() && this.props.location.pathname === "/search" && this.state.results.length >= (pageSize * this.state.page)) {
|
||||
if (
|
||||
hitBottom() &&
|
||||
this.props.location.pathname === "/search" &&
|
||||
this.state.results.length >= pageSize * this.state.page
|
||||
) {
|
||||
const page = this.state.page + 1;
|
||||
const moreResults = dictionary.search({ ...this.state, page });
|
||||
if (moreResults.length > this.state.results.length) {
|
||||
|
@ -492,7 +545,10 @@ class App extends Component<RouteComponentProps, State> {
|
|||
}
|
||||
|
||||
private handleInflectionSearch() {
|
||||
function prepValueForSearch(searchValue: string, textOptions: T.TextOptions): string {
|
||||
function prepValueForSearch(
|
||||
searchValue: string,
|
||||
textOptions: T.TextOptions
|
||||
): string {
|
||||
const s = revertSpelling(searchValue, textOptions.spelling);
|
||||
return standardizePashto(s.trim());
|
||||
}
|
||||
|
@ -501,7 +557,10 @@ class App extends Component<RouteComponentProps, State> {
|
|||
setTimeout(() => {
|
||||
const inflectionSearchResults = searchAllInflections(
|
||||
allEntries(),
|
||||
prepValueForSearch(this.state.searchValue, this.state.options.textOptionsRecord.textOptions),
|
||||
prepValueForSearch(
|
||||
this.state.searchValue,
|
||||
this.state.options.textOptionsRecord.textOptions
|
||||
)
|
||||
);
|
||||
this.setState({ inflectionSearchResults });
|
||||
}, 20);
|
||||
|
@ -525,48 +584,75 @@ class App extends Component<RouteComponentProps, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <div style={{
|
||||
paddingTop: this.state.options.searchBarPosition === "top" ? "75px" : "7px",
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
paddingTop:
|
||||
this.state.options.searchBarPosition === "top" ? "75px" : "7px",
|
||||
paddingBottom: "60px",
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Helmet>
|
||||
<title>LingDocs Pashto Dictionary</title>
|
||||
</Helmet>
|
||||
{this.state.options.searchBarPosition === "top" && <SearchBar
|
||||
{this.state.options.searchBarPosition === "top" && (
|
||||
<SearchBar
|
||||
state={this.state}
|
||||
optionsDispatch={this.handleOptionsUpdate}
|
||||
handleSearchValueChange={this.handleSearchValueChange}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
<div className="container-fluid" data-testid="body">
|
||||
{this.state.dictionaryStatus !== "ready" ?
|
||||
{this.state.dictionaryStatus !== "ready" ? (
|
||||
<DictionaryStatusDisplay status={this.state.dictionaryStatus} />
|
||||
:
|
||||
) : (
|
||||
<>
|
||||
<Route path="/" exact={true}>
|
||||
<div className="text-center mt-4">
|
||||
<h4 className="font-weight-light p-3 mb-4">LingDocs Pashto Dictionary</h4>
|
||||
<h4 className="font-weight-light p-3 mb-4">
|
||||
LingDocs Pashto Dictionary
|
||||
</h4>
|
||||
<div className="mt-4 font-weight-light">
|
||||
<div className="mb-4 small">
|
||||
{this.state.options.searchType === "alphabetical"
|
||||
? <><span className="fa fa-book mr-2" /> Alphabetical browsing mode</>
|
||||
: <><span className="fa fa-bolt mr-2" /> Approximate search mode</>}
|
||||
{this.state.options.searchType === "alphabetical" ? (
|
||||
<>
|
||||
<span className="fa fa-book mr-2" /> Alphabetical
|
||||
browsing mode
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="fa fa-bolt mr-2" /> Approximate
|
||||
search mode
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{this.state.user?.level === "editor" && <div className="mt-4 font-weight-light">
|
||||
{this.state.user?.level === "editor" && (
|
||||
<div className="mt-4 font-weight-light">
|
||||
<div className="mb-3">Editor privileges active</div>
|
||||
<Link to="/edit">
|
||||
<button className="btn btn-secondary">New Entry</button>
|
||||
</Link>
|
||||
</div>}
|
||||
<Link to="/new-entries" className="plain-link font-weight-light">
|
||||
</div>
|
||||
)}
|
||||
<Link
|
||||
to="/new-entries"
|
||||
className="plain-link font-weight-light"
|
||||
>
|
||||
<div className="my-4">New words this month</div>
|
||||
</Link>
|
||||
<div className="mt-4 pt-3">
|
||||
<Link to="/phrase-builder" className="plain-link h5 font-weight-light">
|
||||
<Link
|
||||
to="/phrase-builder"
|
||||
className="plain-link h5 font-weight-light"
|
||||
>
|
||||
Phrase Builder
|
||||
</Link>
|
||||
<span className="mx-1"> • </span>
|
||||
<a href="https://grammar.lingdocs.com" className="plain-link h5 font-weight-light">
|
||||
<a
|
||||
href="https://grammar.lingdocs.com"
|
||||
className="plain-link h5 font-weight-light"
|
||||
>
|
||||
Grammar
|
||||
</a>
|
||||
</div>
|
||||
|
@ -601,18 +687,21 @@ class App extends Component<RouteComponentProps, State> {
|
|||
</Route>
|
||||
<Route path="/new-entries">
|
||||
<h4 className="mb-3">New Words This Month</h4>
|
||||
{this.state.results.length ?
|
||||
{this.state.results.length ? (
|
||||
<Results
|
||||
state={this.state}
|
||||
isolateEntry={this.handleIsolateEntry}
|
||||
handleInflectionSearch={this.handleInflectionSearch}
|
||||
/>
|
||||
:
|
||||
) : (
|
||||
<div>No new words added this month 😓</div>
|
||||
}
|
||||
)}
|
||||
</Route>
|
||||
<Route path="/account">
|
||||
<Account user={this.state.user} loadUser={this.handleLoadUser} />
|
||||
<Account
|
||||
user={this.state.user}
|
||||
loadUser={this.handleLoadUser}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/word">
|
||||
<IsolatedEntry
|
||||
|
@ -634,59 +723,101 @@ class App extends Component<RouteComponentProps, State> {
|
|||
<Route path="/script-to-phonetics">
|
||||
<ScriptToPhonetics />
|
||||
</Route>
|
||||
{this.state.user?.level === "editor" && <Route path="/edit">
|
||||
{this.state.user?.level === "editor" && (
|
||||
<Route path="/edit">
|
||||
<EntryEditor
|
||||
isolatedEntry={this.state.isolatedEntry}
|
||||
user={this.state.user}
|
||||
textOptions={getTextOptions(this.state)}
|
||||
dictionary={dictionary}
|
||||
searchParams={new URLSearchParams(this.props.history.location.search)}
|
||||
/>
|
||||
</Route>}
|
||||
{this.state.user?.level === "editor" && <Route path="/review-tasks">
|
||||
<ReviewTasks state={this.state} />
|
||||
</Route>}
|
||||
</>
|
||||
searchParams={
|
||||
new URLSearchParams(this.props.history.location.search)
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
)}
|
||||
{this.state.user?.level === "editor" && (
|
||||
<Route path="/review-tasks">
|
||||
<ReviewTasks state={this.state} />
|
||||
</Route>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<footer className={classNames(
|
||||
<footer
|
||||
className={classNames(
|
||||
"footer",
|
||||
{ "bg-white": !["/search", "/word"].includes(this.props.location.pathname) },
|
||||
{ "footer-thick": this.state.options.searchBarPosition === "bottom" && !["/search", "/word"].includes(this.props.location.pathname) },
|
||||
{ "wee-less-footer": this.state.options.searchBarPosition === "bottom" && ["/search", "/word"].includes(this.props.location.pathname) },
|
||||
)}>
|
||||
{
|
||||
"bg-white": !["/search", "/word"].includes(
|
||||
this.props.location.pathname
|
||||
),
|
||||
},
|
||||
{
|
||||
"footer-thick":
|
||||
this.state.options.searchBarPosition === "bottom" &&
|
||||
!["/search", "/word"].includes(this.props.location.pathname),
|
||||
},
|
||||
{
|
||||
"wee-less-footer":
|
||||
this.state.options.searchBarPosition === "bottom" &&
|
||||
["/search", "/word"].includes(this.props.location.pathname),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Route path="/" exact={true}>
|
||||
<div className="buttons-footer">
|
||||
<BottomNavItem label="About" icon="info-circle" page="/about" />
|
||||
<BottomNavItem label="Settings" icon="cog" page="/settings" />
|
||||
<BottomNavItem label={this.state.user ? "Account" : "Sign In"} icon="user" page="/account" />
|
||||
<BottomNavItem
|
||||
label={`Wordlist ${this.state.options.wordlistReviewBadge ? textBadge(forReview(this.state.wordlist).length) : ""}`}
|
||||
label={this.state.user ? "Account" : "Sign In"}
|
||||
icon="user"
|
||||
page="/account"
|
||||
/>
|
||||
<BottomNavItem
|
||||
label={`Wordlist ${
|
||||
this.state.options.wordlistReviewBadge
|
||||
? textBadge(forReview(this.state.wordlist).length)
|
||||
: ""
|
||||
}`}
|
||||
icon="list"
|
||||
page="/wordlist"
|
||||
/>
|
||||
{this.state.user?.level === "editor" &&
|
||||
{this.state.user?.level === "editor" && (
|
||||
<BottomNavItem
|
||||
label={`Tasks ${textBadge(this.state.reviewTasks.length)}`}
|
||||
icon="edit"
|
||||
page="/review-tasks"
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</Route>
|
||||
<Route path={["/about", "/settings", "/new-entries", "/account", "/wordlist", "/edit", "/review-tasks", "/phrase-builder"]}>
|
||||
<Route
|
||||
path={[
|
||||
"/about",
|
||||
"/settings",
|
||||
"/new-entries",
|
||||
"/account",
|
||||
"/wordlist",
|
||||
"/edit",
|
||||
"/review-tasks",
|
||||
"/phrase-builder",
|
||||
]}
|
||||
>
|
||||
<div className="buttons-footer">
|
||||
<BottomNavItem label="Home" icon="home" page="/" />
|
||||
</div>
|
||||
</Route>
|
||||
{this.state.options.searchBarPosition === "bottom" && <SearchBar
|
||||
{this.state.options.searchBarPosition === "bottom" && (
|
||||
<SearchBar
|
||||
state={this.state}
|
||||
optionsDispatch={this.handleOptionsUpdate}
|
||||
handleSearchValueChange={this.handleSearchValueChange}
|
||||
onBottom={true}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
</footer>
|
||||
</div>;
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11335,10 +11335,10 @@ react-fast-compare@^3.0.1, react-fast-compare@^3.1.1:
|
|||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-ga@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-3.3.0.tgz#c91f407198adcb3b49e2bc5c12b3fe460039b3ca"
|
||||
integrity sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==
|
||||
react-ga4@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-ga4/-/react-ga4-2.1.0.tgz#56601f59d95c08466ebd6edfbf8dede55c4678f9"
|
||||
integrity sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==
|
||||
|
||||
react-helmet@^6.1.0:
|
||||
version "6.1.0"
|
||||
|
|
Loading…
Reference in New Issue