diff --git a/vocodes/package-lock.json b/vocodes/package-lock.json
index 614853e60d..6f5f275509 100644
--- a/vocodes/package-lock.json
+++ b/vocodes/package-lock.json
@@ -1674,6 +1674,12 @@
"@types/node": "*"
}
},
+ "@types/history": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz",
+ "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
+ "dev": true
+ },
"@types/howler": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.1.2.tgz",
@@ -1756,6 +1762,27 @@
"@types/react": "*"
}
},
+ "@types/react-router": {
+ "version": "5.1.14",
+ "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.14.tgz",
+ "integrity": "sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw==",
+ "dev": true,
+ "requires": {
+ "@types/history": "*",
+ "@types/react": "*"
+ }
+ },
+ "@types/react-router-dom": {
+ "version": "5.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz",
+ "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==",
+ "dev": true,
+ "requires": {
+ "@types/history": "*",
+ "@types/react": "*",
+ "@types/react-router": "*"
+ }
+ },
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
@@ -6457,6 +6484,19 @@
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
},
+ "history": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
+ "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "loose-envify": "^1.2.0",
+ "resolve-pathname": "^3.0.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0",
+ "value-equal": "^1.0.1"
+ }
+ },
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -6467,6 +6507,14 @@
"minimalistic-crypto-utils": "^1.0.1"
}
},
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
"hosted-git-info": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
@@ -8530,6 +8578,25 @@
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
},
+ "mini-create-react-context": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
+ "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
+ "requires": {
+ "@babel/runtime": "^7.12.1",
+ "tiny-warning": "^1.0.3"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
+ "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ }
+ }
+ },
"mini-css-extract-plugin": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
@@ -11172,6 +11239,52 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "react-router": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
+ "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "history": "^4.9.0",
+ "hoist-non-react-statics": "^3.1.0",
+ "loose-envify": "^1.3.1",
+ "mini-create-react-context": "^0.4.0",
+ "path-to-regexp": "^1.7.0",
+ "prop-types": "^15.6.2",
+ "react-is": "^16.6.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ },
+ "path-to-regexp": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+ "requires": {
+ "isarray": "0.0.1"
+ }
+ }
+ }
+ },
+ "react-router-dom": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
+ "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "history": "^4.9.0",
+ "loose-envify": "^1.3.1",
+ "prop-types": "^15.6.2",
+ "react-router": "5.2.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0"
+ }
+ },
"react-scripts": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz",
@@ -11590,6 +11703,11 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
},
+ "resolve-pathname": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
+ "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
+ },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -13116,6 +13234,16 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
+ "tiny-invariant": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
+ "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
+ },
+ "tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -13505,6 +13633,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "value-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
+ "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
+ },
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
diff --git a/vocodes/package.json b/vocodes/package.json
index b60d3e41ee..f572046cac 100644
--- a/vocodes/package.json
+++ b/vocodes/package.json
@@ -21,6 +21,7 @@
"node-sass": "^4.14.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
+ "react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"typescript": "^3.7.5",
"uuid": "^8.3.2"
@@ -49,5 +50,7 @@
"last 1 safari version"
]
},
- "devDependencies": {}
+ "devDependencies": {
+ "@types/react-router-dom": "^5.1.7"
+ }
}
diff --git a/vocodes/src/App.test.tsx b/vocodes/src/App.test.tsx
index 94b791479e..ed89b05963 100644
--- a/vocodes/src/App.test.tsx
+++ b/vocodes/src/App.test.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react';
-import App from './migration/OldVocodesContainer';
+import App from './v1/OldVocodesContainer';
test('renders learn react link', () => {
const { getByText } = render();
diff --git a/vocodes/src/App.tsx b/vocodes/src/App.tsx
index 116c847dc6..b05ce14662 100644
--- a/vocodes/src/App.tsx
+++ b/vocodes/src/App.tsx
@@ -2,11 +2,12 @@ import 'bulma/css/bulma.css'
import './App.scss';
import React from 'react';
-import { NewOldVocodesSwitch } from './migration/NewOldVocodesSwitch';
-import { OldVocodesContainer } from './migration/OldVocodesContainer';
-import { NewVocodesContainer } from './migration/NewVocodesContainer';
-import { ApiConfig } from './api/ApiConfig';
-import { SessionStateResponse } from './api/SessionState';
+import { MigrationTopNav } from './migration/MigrationTopNav';
+import { OldVocodesContainer } from './v1/OldVocodesContainer';
+import { NewVocodesContainer } from './v2/NewVocodesContainer';
+import { ApiConfig } from './v1/api/ApiConfig';
+import { SessionStateResponse } from './v1/api/SessionState';
+import { SessionWrapper } from './session/SessionWrapper';
enum MigrationMode {
NEW_VOCODES,
@@ -27,8 +28,7 @@ interface State {
// Rollout of vocodes 2.0
enableAlpha: boolean,
- loggedIn: boolean,
- sessionState?: SessionStateResponse,
+ sessionWrapper: SessionWrapper,
}
class App extends React.Component {
@@ -43,7 +43,7 @@ class App extends React.Component {
this.state = {
enableAlpha: enableAlpha,
migrationMode: migrationMode,
- loggedIn: false,
+ sessionWrapper: SessionWrapper.emptySession(),
}
}
@@ -71,14 +71,16 @@ class App extends React.Component {
})
.then(res => res.json())
.then(response => {
- const session : SessionStateResponse = response;
+ const sessionResponse : SessionStateResponse = response;
- if (session !== undefined) {
- this.setState({
- sessionState : session,
- loggedIn: session.logged_in,
- });
+ if (sessionResponse === undefined) {
+ return; // Endpoint error?
}
+
+ const sessionWrapper = SessionWrapper.wrapResponse(sessionResponse);
+ this.setState({
+ sessionWrapper: sessionWrapper,
+ });
})
.catch(e => { /* Ignore. */ });
}
@@ -115,9 +117,9 @@ class App extends React.Component {
case MigrationMode.NEW_VOCODES:
innerComponent = (
-
+ />*/}
);
break;
@@ -136,16 +138,16 @@ class App extends React.Component {
return (
-
-
- {innerComponent}
-
+
+ {innerComponent}
+
diff --git a/vocodes/src/migration/MigrationTopNav.tsx b/vocodes/src/migration/MigrationTopNav.tsx
new file mode 100644
index 0000000000..96d20d57dd
--- /dev/null
+++ b/vocodes/src/migration/MigrationTopNav.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { MigrationMode } from '../App'
+import { MigrationTopNav_Session } from './MigrationTopNav_Session';
+import { MigrationTopNav_VersionSwitch } from './MigrationTopNav_VersionSwitch';
+import { SessionWrapper } from '../session/SessionWrapper';
+
+interface Props {
+ sessionWrapper: SessionWrapper,
+ enableAlpha: boolean,
+ migrationMode: MigrationMode,
+ setMigrationModeCallback: (mode: MigrationMode) => void,
+}
+
+function MigrationTopNav(props: Props) {
+ if (!props.enableAlpha) {
+ return
+ }
+
+ return (
+
+ )
+}
+
+export { MigrationTopNav };
diff --git a/vocodes/src/migration/MigrationTopNav_Session.tsx b/vocodes/src/migration/MigrationTopNav_Session.tsx
new file mode 100644
index 0000000000..ea94c9e628
--- /dev/null
+++ b/vocodes/src/migration/MigrationTopNav_Session.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { MigrationMode } from '../App'
+import { SessionWrapper } from '../session/SessionWrapper';
+
+interface Props {
+ sessionWrapper: SessionWrapper,
+ enableAlpha: boolean,
+ migrationMode: MigrationMode,
+ setMigrationModeCallback: (mode: MigrationMode) => void,
+}
+
+function MigrationTopNav_Session(props: Props) {
+ if (!props.enableAlpha) {
+ return
+ }
+
+ let loggedIn = props.sessionWrapper.isLoggedIn();
+ let displayName = props.sessionWrapper.getDisplayName();
+
+ if (displayName === 'undefined') {
+ displayName = 'My Account';
+ }
+
+ let sessionLink = ;
+
+ if (loggedIn) {
+ sessionLink =
+ } else {
+ sessionLink =
+ }
+
+ return sessionLink;
+}
+
+export { MigrationTopNav_Session };
diff --git a/vocodes/src/migration/MigrationTopNav_VersionSwitch.tsx b/vocodes/src/migration/MigrationTopNav_VersionSwitch.tsx
new file mode 100644
index 0000000000..8845faab85
--- /dev/null
+++ b/vocodes/src/migration/MigrationTopNav_VersionSwitch.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import { MigrationMode } from '../App'
+import { SessionWrapper } from '../session/SessionWrapper';
+
+interface Props {
+ sessionWrapper: SessionWrapper,
+ enableAlpha: boolean,
+ migrationMode: MigrationMode,
+ setMigrationModeCallback: (mode: MigrationMode) => void,
+}
+
+function MigrationTopNav_VersionSwitch(props: Props) {
+ if (!props.enableAlpha) {
+ return
+ }
+
+ let loggedIn = props.sessionWrapper.isLoggedIn();
+ let displayName = props.sessionWrapper.getDisplayName();
+
+ if (displayName === 'undefined') {
+ displayName = 'My Account';
+ }
+
+ let switchLink = ;
+
+ switch (props.migrationMode) {
+ case MigrationMode.NEW_VOCODES:
+ switchLink =
+ break;
+ case MigrationMode.OLD_VOCODES:
+ switchLink =
+ break;
+ }
+
+ return switchLink;
+}
+
+export { MigrationTopNav_VersionSwitch };
diff --git a/vocodes/src/migration/NewOldVocodesSwitch.tsx b/vocodes/src/migration/NewOldVocodesSwitch.tsx
deleted file mode 100644
index d3a6ba385a..0000000000
--- a/vocodes/src/migration/NewOldVocodesSwitch.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from 'react';
-import { MigrationMode } from '../App'
-import { SessionStateResponse } from '../api/SessionState';
-
-interface Props {
- sessionState?: SessionStateResponse,
- enableAlpha: boolean,
- migrationMode: MigrationMode,
- setMigrationModeCallback: (mode: MigrationMode) => void,
-}
-
-function NewOldVocodesSwitch(props: Props) {
- if (!props.enableAlpha) {
- return
- }
-
- let loggedIn = false;
- let displayName = "My Account";
-
- if (props.sessionState !== undefined) {
- console.log('sessionstate', props.sessionState);
- loggedIn = props.sessionState.logged_in;
- if (props.sessionState.user !== undefined &&
- props.sessionState.user !== null) {
- displayName = props.sessionState.user.display_name;
- }
- }
-
- let switchLink = ;
- let sessionLink = ;
-
- switch (props.migrationMode) {
- case MigrationMode.NEW_VOCODES:
- switchLink =
- break;
- case MigrationMode.OLD_VOCODES:
- switchLink =
- break;
- }
-
- if (loggedIn) {
- sessionLink =
- } else {
- sessionLink =
- }
-
- return (
-
- )
-}
-
-export { NewOldVocodesSwitch };
diff --git a/vocodes/src/api/SessionState.ts b/vocodes/src/session/SessionState.ts
similarity index 100%
rename from vocodes/src/api/SessionState.ts
rename to vocodes/src/session/SessionState.ts
diff --git a/vocodes/src/session/SessionWrapper.ts b/vocodes/src/session/SessionWrapper.ts
new file mode 100644
index 0000000000..eb4fbe0012
--- /dev/null
+++ b/vocodes/src/session/SessionWrapper.ts
@@ -0,0 +1,32 @@
+import { SessionStateResponse } from "./SessionState";
+
+export class SessionWrapper {
+ sessionStateResponse?: SessionStateResponse;
+
+ private constructor(sessionStateResponse?: SessionStateResponse) {
+ this.sessionStateResponse = sessionStateResponse;
+ }
+
+ public static emptySession() : SessionWrapper {
+ return new SessionWrapper();
+ }
+
+ public static wrapResponse(sessionStateResponse: SessionStateResponse) : SessionWrapper {
+ return new SessionWrapper(sessionStateResponse);
+ }
+
+ public isLoggedIn() : boolean {
+ if (this.sessionStateResponse === undefined) {
+ return false;
+ }
+ return this.sessionStateResponse.logged_in;
+ }
+
+ public getUsername() : string | undefined {
+ return this.sessionStateResponse?.user?.username;
+ }
+
+ public getDisplayName() : string | undefined {
+ return this.sessionStateResponse?.user?.display_name;
+ }
+}
diff --git a/vocodes/src/migration/OldVocodesContainer.tsx b/vocodes/src/v1/OldVocodesContainer.tsx
similarity index 91%
rename from vocodes/src/migration/OldVocodesContainer.tsx
rename to vocodes/src/v1/OldVocodesContainer.tsx
index d9cce95f9e..b5e4b7af77 100644
--- a/vocodes/src/migration/OldVocodesContainer.tsx
+++ b/vocodes/src/v1/OldVocodesContainer.tsx
@@ -1,25 +1,25 @@
import React from 'react';
-import { AboutComponent } from '../modes/about/AboutComponent';
-import { ExtrasMode } from '../modes/speak/SpeakComponent';
-import { Footer } from '../navigation/Footer';
-import { HistoryComponent } from '../modes/history/HistoryComponent';
+import { AboutComponent } from './modes/about/AboutComponent';
+import { ExtrasMode } from './modes/speak/SpeakComponent';
+import { Footer } from './navigation/Footer';
+import { HistoryComponent } from './modes/history/HistoryComponent';
import { Mode } from '../AppMode';
-import { SpeakComponent } from '../modes/speak/SpeakComponent';
-import { Speaker, SpeakerCategory, SPEAKERS, SPEAKER_CATEGORIES, CATEGORY_ALL_BY_NAME, SPEAKERS_BY_CATEGORY } from '../model/Speakers';
-import { Spectrogram } from '../modes/speak/extras/Spectrogram';
-import { TermsComponent } from '../modes/terms/TermsComponent';
-import { TopNav } from '../navigation/TopNav';
-import { Utterance } from '../model/utterance';
-import { VideoComponent } from '../modes/video/VideoComponent';
-import { VideoJob, VideoJobStatus } from '../modes/video/VideoJob';
-import { VideoJobPoller } from '../modes/video/VideoJobPoller';
-import { VideoQueuePoller } from '../modes/video/VideoQueuePoller';
-import { VideoQueueStats } from '../modes/video/VideoQueueStats';
-import { SignupComponent } from '../modes/signup/SignupComponent';
-import { ApiConfig } from '../api/ApiConfig';
-import { SessionStateResponse } from '../api/SessionState';
-import { LoginComponent } from '../modes/login/LoginComponent';
-import { UploadComponent } from '../modes/upload/UploadComponent';
+import { SpeakComponent } from './modes/speak/SpeakComponent';
+import { Speaker, SpeakerCategory, SPEAKERS, SPEAKER_CATEGORIES, CATEGORY_ALL_BY_NAME, SPEAKERS_BY_CATEGORY } from './model/Speakers';
+import { Spectrogram } from './modes/speak/extras/Spectrogram';
+import { TermsComponent } from './modes/terms/TermsComponent';
+import { TopNav } from './navigation/TopNav';
+import { Utterance } from './model/utterance';
+import { VideoComponent } from './modes/video/VideoComponent';
+import { VideoJob, VideoJobStatus } from './modes/video/VideoJob';
+import { VideoJobPoller } from './modes/video/VideoJobPoller';
+import { VideoQueuePoller } from './modes/video/VideoQueuePoller';
+import { VideoQueueStats } from './modes/video/VideoQueueStats';
+import { SignupComponent } from './modes/signup/SignupComponent';
+import { ApiConfig } from './api/ApiConfig';
+import { SessionStateResponse } from './api/SessionState';
+import { LoginComponent } from './modes/login/LoginComponent';
+import { UploadComponent } from './modes/upload/UploadComponent';
interface Props {
// Certan browsers (iPhone) have pitiful support for drawing APIs. Worse yet,
diff --git a/vocodes/src/api/ApiConfig.ts b/vocodes/src/v1/api/ApiConfig.ts
similarity index 100%
rename from vocodes/src/api/ApiConfig.ts
rename to vocodes/src/v1/api/ApiConfig.ts
diff --git a/vocodes/src/v1/api/SessionState.ts b/vocodes/src/v1/api/SessionState.ts
new file mode 100644
index 0000000000..e8dd47584f
--- /dev/null
+++ b/vocodes/src/v1/api/SessionState.ts
@@ -0,0 +1,18 @@
+
+// Responses from the `/sessions` endpoint.
+export interface SessionStateResponse {
+ // API call was successful
+ success: boolean,
+
+ // Whether the user is logged in
+ logged_in: boolean,
+
+ // Extended user details (only if logged in)
+ user?: UserInfo,
+}
+
+export interface UserInfo {
+ user_token: string,
+ username: string,
+ display_name: string,
+}
diff --git a/vocodes/src/extra_colormaps/colormap-afmhot.ts b/vocodes/src/v1/extra_colormaps/colormap-afmhot.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-afmhot.ts
rename to vocodes/src/v1/extra_colormaps/colormap-afmhot.ts
diff --git a/vocodes/src/extra_colormaps/colormap-bone.ts b/vocodes/src/v1/extra_colormaps/colormap-bone.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-bone.ts
rename to vocodes/src/v1/extra_colormaps/colormap-bone.ts
diff --git a/vocodes/src/extra_colormaps/colormap-cool.ts b/vocodes/src/v1/extra_colormaps/colormap-cool.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-cool.ts
rename to vocodes/src/v1/extra_colormaps/colormap-cool.ts
diff --git a/vocodes/src/extra_colormaps/colormap-copper.ts b/vocodes/src/v1/extra_colormaps/colormap-copper.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-copper.ts
rename to vocodes/src/v1/extra_colormaps/colormap-copper.ts
diff --git a/vocodes/src/extra_colormaps/colormap-gist_heat.ts b/vocodes/src/v1/extra_colormaps/colormap-gist_heat.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-gist_heat.ts
rename to vocodes/src/v1/extra_colormaps/colormap-gist_heat.ts
diff --git a/vocodes/src/extra_colormaps/colormap-jet.ts b/vocodes/src/v1/extra_colormaps/colormap-jet.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-jet.ts
rename to vocodes/src/v1/extra_colormaps/colormap-jet.ts
diff --git a/vocodes/src/extra_colormaps/colormap-pink.ts b/vocodes/src/v1/extra_colormaps/colormap-pink.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-pink.ts
rename to vocodes/src/v1/extra_colormaps/colormap-pink.ts
diff --git a/vocodes/src/extra_colormaps/colormap-rdbu.ts b/vocodes/src/v1/extra_colormaps/colormap-rdbu.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-rdbu.ts
rename to vocodes/src/v1/extra_colormaps/colormap-rdbu.ts
diff --git a/vocodes/src/extra_colormaps/colormap-rdgy.ts b/vocodes/src/v1/extra_colormaps/colormap-rdgy.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-rdgy.ts
rename to vocodes/src/v1/extra_colormaps/colormap-rdgy.ts
diff --git a/vocodes/src/extra_colormaps/colormap-spring.ts b/vocodes/src/v1/extra_colormaps/colormap-spring.ts
similarity index 100%
rename from vocodes/src/extra_colormaps/colormap-spring.ts
rename to vocodes/src/v1/extra_colormaps/colormap-spring.ts
diff --git a/vocodes/src/model/Speakers.ts b/vocodes/src/v1/model/Speakers.ts
similarity index 100%
rename from vocodes/src/model/Speakers.ts
rename to vocodes/src/v1/model/Speakers.ts
diff --git a/vocodes/src/model/utterance.ts b/vocodes/src/v1/model/utterance.ts
similarity index 100%
rename from vocodes/src/model/utterance.ts
rename to vocodes/src/v1/model/utterance.ts
diff --git a/vocodes/src/modes/about/AboutComponent.tsx b/vocodes/src/v1/modes/about/AboutComponent.tsx
similarity index 100%
rename from vocodes/src/modes/about/AboutComponent.tsx
rename to vocodes/src/v1/modes/about/AboutComponent.tsx
diff --git a/vocodes/src/modes/history/HistoryComponent.tsx b/vocodes/src/v1/modes/history/HistoryComponent.tsx
similarity index 100%
rename from vocodes/src/modes/history/HistoryComponent.tsx
rename to vocodes/src/v1/modes/history/HistoryComponent.tsx
diff --git a/vocodes/src/modes/history/MiniAvatar.tsx b/vocodes/src/v1/modes/history/MiniAvatar.tsx
similarity index 100%
rename from vocodes/src/modes/history/MiniAvatar.tsx
rename to vocodes/src/v1/modes/history/MiniAvatar.tsx
diff --git a/vocodes/src/modes/history/PastUtterance.tsx b/vocodes/src/v1/modes/history/PastUtterance.tsx
similarity index 100%
rename from vocodes/src/modes/history/PastUtterance.tsx
rename to vocodes/src/v1/modes/history/PastUtterance.tsx
diff --git a/vocodes/src/modes/login/LoginComponent.tsx b/vocodes/src/v1/modes/login/LoginComponent.tsx
similarity index 99%
rename from vocodes/src/modes/login/LoginComponent.tsx
rename to vocodes/src/v1/modes/login/LoginComponent.tsx
index 86ee32d39f..e3d425a853 100644
--- a/vocodes/src/modes/login/LoginComponent.tsx
+++ b/vocodes/src/v1/modes/login/LoginComponent.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { ApiConfig } from '../../api/ApiConfig';
-import { Mode } from '../../AppMode';
+import { Mode } from '../../../AppMode';
enum FieldTriState {
EMPTY_FALSE,
diff --git a/vocodes/src/modes/signup/SignupComponent.tsx b/vocodes/src/v1/modes/signup/SignupComponent.tsx
similarity index 99%
rename from vocodes/src/modes/signup/SignupComponent.tsx
rename to vocodes/src/v1/modes/signup/SignupComponent.tsx
index 3ccde15d38..fc7ec56744 100644
--- a/vocodes/src/modes/signup/SignupComponent.tsx
+++ b/vocodes/src/v1/modes/signup/SignupComponent.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { ApiConfig } from '../../api/ApiConfig';
-import { Mode } from '../../AppMode';
+import { Mode } from '../../../AppMode';
enum FieldTriState {
EMPTY_FALSE,
diff --git a/vocodes/src/modes/speak/Form.tsx b/vocodes/src/v1/modes/speak/Form.tsx
similarity index 100%
rename from vocodes/src/modes/speak/Form.tsx
rename to vocodes/src/v1/modes/speak/Form.tsx
diff --git a/vocodes/src/modes/speak/NewsNotice.tsx b/vocodes/src/v1/modes/speak/NewsNotice.tsx
similarity index 100%
rename from vocodes/src/modes/speak/NewsNotice.tsx
rename to vocodes/src/v1/modes/speak/NewsNotice.tsx
diff --git a/vocodes/src/modes/speak/SpeakComponent.tsx b/vocodes/src/v1/modes/speak/SpeakComponent.tsx
similarity index 98%
rename from vocodes/src/modes/speak/SpeakComponent.tsx
rename to vocodes/src/v1/modes/speak/SpeakComponent.tsx
index 50e73693c4..c1ce02ed0c 100644
--- a/vocodes/src/modes/speak/SpeakComponent.tsx
+++ b/vocodes/src/v1/modes/speak/SpeakComponent.tsx
@@ -6,10 +6,10 @@ import { SpeakerDropdown } from './dropdowns/SpeakerDropdown';
import { SpeakerInfo } from './extras/SpeakerInfo';
import { Spectrogram } from './extras/Spectrogram';
import { SpectrogramComponent } from './extras/SpectrogramComponent';
-import { SpectrogramMode } from '../../migration/OldVocodesContainer';
+import { SpectrogramMode } from '../../OldVocodesContainer';
import { StatusText } from './StatusText';
import { Utterance } from '../../model/utterance';
-import { getRandomInt } from '../../Utils';
+import { getRandomInt } from '../../../Utils';
import { NewsNotice } from './NewsNotice';
enum StatusState {
diff --git a/vocodes/src/modes/speak/SpeakRequest.ts b/vocodes/src/v1/modes/speak/SpeakRequest.ts
similarity index 100%
rename from vocodes/src/modes/speak/SpeakRequest.ts
rename to vocodes/src/v1/modes/speak/SpeakRequest.ts
diff --git a/vocodes/src/modes/speak/StatusText.tsx b/vocodes/src/v1/modes/speak/StatusText.tsx
similarity index 100%
rename from vocodes/src/modes/speak/StatusText.tsx
rename to vocodes/src/v1/modes/speak/StatusText.tsx
diff --git a/vocodes/src/modes/speak/dropdowns/CategoryDropdown.tsx b/vocodes/src/v1/modes/speak/dropdowns/CategoryDropdown.tsx
similarity index 100%
rename from vocodes/src/modes/speak/dropdowns/CategoryDropdown.tsx
rename to vocodes/src/v1/modes/speak/dropdowns/CategoryDropdown.tsx
diff --git a/vocodes/src/modes/speak/dropdowns/SpeakerDropdown.tsx b/vocodes/src/v1/modes/speak/dropdowns/SpeakerDropdown.tsx
similarity index 100%
rename from vocodes/src/modes/speak/dropdowns/SpeakerDropdown.tsx
rename to vocodes/src/v1/modes/speak/dropdowns/SpeakerDropdown.tsx
diff --git a/vocodes/src/modes/speak/extras/Avatar.tsx b/vocodes/src/v1/modes/speak/extras/Avatar.tsx
similarity index 100%
rename from vocodes/src/modes/speak/extras/Avatar.tsx
rename to vocodes/src/v1/modes/speak/extras/Avatar.tsx
diff --git a/vocodes/src/modes/speak/extras/SpeakerInfo.tsx b/vocodes/src/v1/modes/speak/extras/SpeakerInfo.tsx
similarity index 100%
rename from vocodes/src/modes/speak/extras/SpeakerInfo.tsx
rename to vocodes/src/v1/modes/speak/extras/SpeakerInfo.tsx
diff --git a/vocodes/src/modes/speak/extras/Spectrogram.ts b/vocodes/src/v1/modes/speak/extras/Spectrogram.ts
similarity index 97%
rename from vocodes/src/modes/speak/extras/Spectrogram.ts
rename to vocodes/src/v1/modes/speak/extras/Spectrogram.ts
index 286aa0fe52..c528010482 100644
--- a/vocodes/src/modes/speak/extras/Spectrogram.ts
+++ b/vocodes/src/v1/modes/speak/extras/Spectrogram.ts
@@ -1,5 +1,5 @@
import { ColorMap, createColorMap, linearScale, RGBColor } from "@colormap/core";
-import { SpectrogramMode } from "../../../migration/OldVocodesContainer";
+import { SpectrogramMode } from "../../../OldVocodesContainer";
import { VIRIDIS, INFERNO, MAGMA, BLACK_WHITE, CIVIDIS, PLASMA, } from "@colormap/presets";
import { BONE } from "../../../extra_colormaps/colormap-bone";
import { COPPER } from "../../../extra_colormaps/colormap-copper";
diff --git a/vocodes/src/modes/speak/extras/SpectrogramComponent.tsx b/vocodes/src/v1/modes/speak/extras/SpectrogramComponent.tsx
similarity index 97%
rename from vocodes/src/modes/speak/extras/SpectrogramComponent.tsx
rename to vocodes/src/v1/modes/speak/extras/SpectrogramComponent.tsx
index badf27efa3..4ad73b2877 100644
--- a/vocodes/src/modes/speak/extras/SpectrogramComponent.tsx
+++ b/vocodes/src/v1/modes/speak/extras/SpectrogramComponent.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { Spectrogram, nextSpectrogramMode } from './Spectrogram';
-import { SpectrogramMode } from '../../../migration/OldVocodesContainer';
+import { SpectrogramMode } from '../../../OldVocodesContainer';
interface Props {
currentSpectrogram?: Spectrogram,
diff --git a/vocodes/src/modes/terms/TermsComponent.tsx b/vocodes/src/v1/modes/terms/TermsComponent.tsx
similarity index 100%
rename from vocodes/src/modes/terms/TermsComponent.tsx
rename to vocodes/src/v1/modes/terms/TermsComponent.tsx
diff --git a/vocodes/src/modes/upload/UploadComponent.tsx b/vocodes/src/v1/modes/upload/UploadComponent.tsx
similarity index 99%
rename from vocodes/src/modes/upload/UploadComponent.tsx
rename to vocodes/src/v1/modes/upload/UploadComponent.tsx
index 88d5e01803..ff688ed934 100644
--- a/vocodes/src/modes/upload/UploadComponent.tsx
+++ b/vocodes/src/v1/modes/upload/UploadComponent.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { ApiConfig } from '../../api/ApiConfig';
-import { Mode } from '../../AppMode';
+import { Mode } from '../../../AppMode';
import { v4 } from 'uuid';
enum UploadType {
diff --git a/vocodes/src/modes/video/ImageTemplates.ts b/vocodes/src/v1/modes/video/ImageTemplates.ts
similarity index 100%
rename from vocodes/src/modes/video/ImageTemplates.ts
rename to vocodes/src/v1/modes/video/ImageTemplates.ts
diff --git a/vocodes/src/modes/video/VideoComponent.tsx b/vocodes/src/v1/modes/video/VideoComponent.tsx
similarity index 100%
rename from vocodes/src/modes/video/VideoComponent.tsx
rename to vocodes/src/v1/modes/video/VideoComponent.tsx
diff --git a/vocodes/src/modes/video/VideoJob.ts b/vocodes/src/v1/modes/video/VideoJob.ts
similarity index 100%
rename from vocodes/src/modes/video/VideoJob.ts
rename to vocodes/src/v1/modes/video/VideoJob.ts
diff --git a/vocodes/src/modes/video/VideoJobPoller.ts b/vocodes/src/v1/modes/video/VideoJobPoller.ts
similarity index 100%
rename from vocodes/src/modes/video/VideoJobPoller.ts
rename to vocodes/src/v1/modes/video/VideoJobPoller.ts
diff --git a/vocodes/src/modes/video/VideoQueuePoller.ts b/vocodes/src/v1/modes/video/VideoQueuePoller.ts
similarity index 100%
rename from vocodes/src/modes/video/VideoQueuePoller.ts
rename to vocodes/src/v1/modes/video/VideoQueuePoller.ts
diff --git a/vocodes/src/modes/video/VideoQueueStats.ts b/vocodes/src/v1/modes/video/VideoQueueStats.ts
similarity index 100%
rename from vocodes/src/modes/video/VideoQueueStats.ts
rename to vocodes/src/v1/modes/video/VideoQueueStats.ts
diff --git a/vocodes/src/modes/video/VideoTemplates.ts b/vocodes/src/v1/modes/video/VideoTemplates.ts
similarity index 100%
rename from vocodes/src/modes/video/VideoTemplates.ts
rename to vocodes/src/v1/modes/video/VideoTemplates.ts
diff --git a/vocodes/src/navigation/Footer.tsx b/vocodes/src/v1/navigation/Footer.tsx
similarity index 97%
rename from vocodes/src/navigation/Footer.tsx
rename to vocodes/src/v1/navigation/Footer.tsx
index b64f9aded9..b29ab1a295 100644
--- a/vocodes/src/navigation/Footer.tsx
+++ b/vocodes/src/v1/navigation/Footer.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Mode } from '../AppMode'
+import { Mode } from '../../AppMode'
interface Props {
mode: Mode,
diff --git a/vocodes/src/navigation/NewTopNav.tsx b/vocodes/src/v1/navigation/NewTopNav.tsx
similarity index 97%
rename from vocodes/src/navigation/NewTopNav.tsx
rename to vocodes/src/v1/navigation/NewTopNav.tsx
index e27cb256bf..8239a62a73 100644
--- a/vocodes/src/navigation/NewTopNav.tsx
+++ b/vocodes/src/v1/navigation/NewTopNav.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { NewMode } from '../migration/NewVocodesContainer'
+import { NewMode } from '../../v2/NewVocodesContainer'
import { SessionStateResponse } from '../api/SessionState';
interface Props {
@@ -55,7 +55,7 @@ function NewTopNav(props: Props) {
+ >Firehose
);
} else {
diff --git a/vocodes/src/navigation/TopNav.tsx b/vocodes/src/v1/navigation/TopNav.tsx
similarity index 98%
rename from vocodes/src/navigation/TopNav.tsx
rename to vocodes/src/v1/navigation/TopNav.tsx
index c59f84d5a3..10dca8d305 100644
--- a/vocodes/src/navigation/TopNav.tsx
+++ b/vocodes/src/v1/navigation/TopNav.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Mode } from '../AppMode'
+import { Mode } from '../../AppMode'
import { SessionStateResponse } from '../api/SessionState';
interface Props {
diff --git a/vocodes/src/poller/AbstractPoller.ts b/vocodes/src/v1/poller/AbstractPoller.ts
similarity index 100%
rename from vocodes/src/poller/AbstractPoller.ts
rename to vocodes/src/v1/poller/AbstractPoller.ts
diff --git a/vocodes/src/migration/NewVocodesContainer.tsx b/vocodes/src/v2/NewVocodesContainer.tsx
similarity index 88%
rename from vocodes/src/migration/NewVocodesContainer.tsx
rename to vocodes/src/v2/NewVocodesContainer.tsx
index bae85c294d..579c67fb05 100644
--- a/vocodes/src/migration/NewVocodesContainer.tsx
+++ b/vocodes/src/v2/NewVocodesContainer.tsx
@@ -1,8 +1,8 @@
import React from 'react';
-import { NewTopNav } from '../navigation/NewTopNav';
-import { SessionStateResponse } from '../api/SessionState';
-import { LoginComponent } from '../modes/login/LoginComponent';
-import { SignupComponent } from '../modes/signup/SignupComponent';
+import { NewTopNav } from '../v1/navigation/NewTopNav';
+import { SessionStateResponse } from '../v1/api/SessionState';
+import { LoginComponent } from '../v1/modes/login/LoginComponent';
+import { SignupComponent } from '../v1/modes/signup/SignupComponent';
enum NewMode {