From 543554fc5604f3dfac0a872689b1436ea83897fe Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 30 May 2021 03:31:05 -0400 Subject: [PATCH] add rudimentary firehose (doesn't poll) --- vocodes/src/v1/api/ApiConfig.ts | 3 + vocodes/src/v2/NewVocodesContainer.tsx | 5 +- vocodes/src/v2/firehose/FirehoseComponent.tsx | 160 ---------- .../src/v2/firehose/FirehoseEventListFc.tsx | 281 ++++++++++++++++++ 4 files changed, 286 insertions(+), 163 deletions(-) delete mode 100644 vocodes/src/v2/firehose/FirehoseComponent.tsx create mode 100644 vocodes/src/v2/firehose/FirehoseEventListFc.tsx diff --git a/vocodes/src/v1/api/ApiConfig.ts b/vocodes/src/v1/api/ApiConfig.ts index d8b1364219..58cd78fab7 100644 --- a/vocodes/src/v1/api/ApiConfig.ts +++ b/vocodes/src/v1/api/ApiConfig.ts @@ -77,6 +77,9 @@ class ApiConfig { return `${this.getScheme()}://${this.getNewApiHost()}/user/${username}/w2l_results`; } + firehoseEvents() : string { + return `${this.getScheme()}://${this.getNewApiHost()}/events`; + } private getScheme() : string { return this.isLocalDev ? "http" : "https"; diff --git a/vocodes/src/v2/NewVocodesContainer.tsx b/vocodes/src/v2/NewVocodesContainer.tsx index 932be6ac5d..35c5442fd8 100644 --- a/vocodes/src/v2/NewVocodesContainer.tsx +++ b/vocodes/src/v2/NewVocodesContainer.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { FirehoseComponent } from './firehose/FirehoseComponent'; import { LoginFc } from './login/LoginFc'; import { NewTopNavFc } from './NewTopNavFc'; import { ProfileDataFc } from './profile_data/ProfileDataFc'; @@ -17,6 +16,7 @@ import { W2lTemplateListFc } from './w2l_template_list/W2lTemplateListFc'; import { W2lTemplateViewFc } from './w2l_template_view/W2lTemplateViewFc'; import { ProfileFc } from './profile/ProfileFc'; import { W2lResultViewFc } from './w2l_result_view/W2lResultViewFc'; +import { FirehoseEventListFc } from './firehose/FirehoseEventListFc'; interface Props { sessionWrapper: SessionWrapper, @@ -50,8 +50,7 @@ class NewVocodesContainer extends React.Component { - {}} + diff --git a/vocodes/src/v2/firehose/FirehoseComponent.tsx b/vocodes/src/v2/firehose/FirehoseComponent.tsx deleted file mode 100644 index 894b6636af..0000000000 --- a/vocodes/src/v2/firehose/FirehoseComponent.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import React from 'react'; -import { ApiConfig } from '../../v1/api/ApiConfig'; -import { Mode } from '../../AppMode'; -import { SessionWrapper } from '../../session/SessionWrapper'; - -enum FieldTriState { - EMPTY_FALSE, - FALSE, - TRUE, -} - -interface Props { - sessionWrapper: SessionWrapper, - querySessionCallback : () => void, - switchModeCallback?: (mode: Mode) => void, -} - -interface State { - usernameOrEmail: string, - usernameOrEmailValid: FieldTriState, - usernameOrEmailInvalidReason: string, - - password: string, - passwordValid: FieldTriState, - passwordInvalidReason: string, -} - -class FirehoseComponent extends React.Component { - - constructor(props: Props) { - super(props); - this.state = { - usernameOrEmail: "", - usernameOrEmailValid: FieldTriState.EMPTY_FALSE, - usernameOrEmailInvalidReason: "", - - password: "", - passwordValid: FieldTriState.EMPTY_FALSE, - passwordInvalidReason: "", - }; - } - - handleUsernameOrEmailChange = (ev: React.FormEvent) => { - ev.preventDefault(); - - const usernameOrEmail = (ev.target as HTMLInputElement).value; - - this.setState({ - usernameOrEmail: usernameOrEmail, - }) - - return false; - } - - handlePasswordChange = (ev: React.FormEvent) => { - ev.preventDefault(); - - const password = (ev.target as HTMLInputElement).value; - - this.setState({ - password: password, - }) - - return false; - } - - handleFormSubmit = (ev: React.FormEvent) : boolean => { - ev.preventDefault(); - - const api = new ApiConfig(); - const endpointUrl = api.login(); - - const request = { - username_or_email: this.state.usernameOrEmail, - password: this.state.password, - } - - fetch(endpointUrl, { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - credentials: 'include', - body: JSON.stringify(request), - }) - .then(res => res.json()) - .then(res => { - console.log('login response', res) - if (res.success) { - console.log('querying new session'); - this.props.querySessionCallback(); - - if (this.props.switchModeCallback !== undefined) { - this.props.switchModeCallback(Mode.SPEAK_MODE); - } - return; - } - }) - .catch(e => { - //this.props.onSpeakErrorCallback(); - }); - - return false; - } - - public render() { - if (this.props.sessionWrapper.isLoggedIn()) { - return
Invalid view for logged in users.
; - } - - return ( -
-

Login

- -

- -
-
- -
- - - - - - - -
- {/*

*/} -
- -
- -
- - - - - - - -
- {/*

*/} -
- -
- -
-
- -
-
-
-
- ) - } -} - -export { FirehoseComponent }; \ No newline at end of file diff --git a/vocodes/src/v2/firehose/FirehoseEventListFc.tsx b/vocodes/src/v2/firehose/FirehoseEventListFc.tsx new file mode 100644 index 0000000000..a8b5ff04f8 --- /dev/null +++ b/vocodes/src/v2/firehose/FirehoseEventListFc.tsx @@ -0,0 +1,281 @@ +import React, { useState, useEffect } from 'react'; +import { ApiConfig } from '../../v1/api/ApiConfig'; +import { SessionWrapper } from '../../session/SessionWrapper'; +import { Link } from "react-router-dom"; +import { getRandomInt } from '../../Utils'; +import { GravatarFc } from '../common/GravatarFc'; + +interface FirehoseEventListResponsePayload { + success: boolean, + events: Array, +} + +/* +event_token "EV:YR8HA4VCVYX9JMH5AMDFHTNRGSYGD" +event_type "w2l_template_upload_completed" +maybe_target_user_token "U:WNZCXKV1AN7XD" +maybe_target_username "brandon" +maybe_target_display_name "brandon" +maybe_target_entity_token "W2L_TPL:MJZ2SMCXX9DRNZ249VK70TWJ" +created_at "2021-05-30T06:42:39Z" +updated_at "2021-05-30T06:42:39Z" +*/ +interface FirehoseEvent { + event_token: string, + event_type: string, + maybe_target_user_token?: string, + maybe_target_username?: string, + maybe_target_display_name?: string, + maybe_target_user_gravatar_hash?: string, + maybe_target_entity_token?: string, + created_at: string, + updated_at: string, +} + +interface Props { + sessionWrapper: SessionWrapper, +} + +function FirehoseEventListFc(props: Props) { + const [firehoseEvents, setFirehoseEvents] = useState>([]); + + useEffect(() => { + const api = new ApiConfig(); + const endpointUrl = api.firehoseEvents(); + + fetch(endpointUrl, { + method: 'GET', + headers: { + 'Accept': 'application/json', + }, + credentials: 'include', + }) + .then(res => res.json()) + .then(res => { + console.log('list', res); + const firehoseResponse : FirehoseEventListResponsePayload = res; + if (!firehoseResponse.success) { + return; + } + + setFirehoseEvents(firehoseResponse.events) + }) + .catch(e => { + // ignored + }); + }, []); // NB: Empty array dependency sets to run ONLY on mount + + let eventItems : Array = []; + + firehoseEvents.forEach(event => { + let inner = ; + let userLink = undefined; + let gravatar = undefined; + + if (event.maybe_target_username !== undefined) { + let link = `/profile/${event.maybe_target_username}`; + userLink = ( + + {event.maybe_target_display_name} + + ); + gravatar = ( + + ); + } + + switch (event.event_type) { + case 'user_sign_up': + inner = ( + + {gravatar} +   + {userLink} +   + signed up for vo.codes! + + ); + break; + case 'tts_model_upload_started': + inner = ( + + {gravatar} +   + {userLink} +   + started TTS model upload + + ); + break; + case 'tts_model_upload_completed': + inner = ( + + {gravatar} +   + {userLink} +   + completed TTS model upload + + ); + break; + case 'tts_inference_started': + inner = ( + + {gravatar} +   + {userLink} +   + started TTS + + ); + break; + case 'tts_inference_completed': + inner = ( + + {gravatar} +   + {userLink} +   + completed TTS + + ); + break; + case 'w2l_template_upload_started': + inner = ( + + {gravatar} +   + {userLink} +   + started uploading a lipsync template. + + ); + break; + case 'w2l_template_upload_completed': + inner = ( + + {gravatar} +   + {userLink} +   + finished uploading a lipsync template. + + ); + break; + case 'w2l_inference_started': + inner = ( + + {gravatar} +   + {userLink} +   + started a W2L lipsync video + + ); + break; + case 'w2l_inference_completed': + inner = ( + + {gravatar} +   + {userLink} +   + completed a W2L lipsync video + + ); + break; + case 'twitter_mention': + inner = ( + + {gravatar} +   + {userLink} +   + mentioned us on twitter! + + ); + break; + case 'twitter_retweet': + inner = ( + + {gravatar} +   + {userLink} +   + retweeted us! + + ); + break; + case 'discord_join': + inner = ( + + {gravatar} +   + {userLink} +   + joined discord! + + ); + break; + case 'discord_message': + inner = ( + + {gravatar} +   + {userLink} +   + sent a discord message + + ); + break; + case 'twitch_subscribe': + inner = ( + + {gravatar} +   + {userLink} +   + subscribed to us on twitch! + + ); + break; + case 'twitch_follow': + inner = ( + + {gravatar} +   + {userLink} +   + followed us on twitch! + + ); + break; + default: + return; + } + + eventItems.push(( +
  • {inner}
  • + )); + }); + + + return ( +
    +

    Firehose events

    + +
    +
      + {eventItems} +
    +
    + +
    + ) +} + +export { FirehoseEventListFc };