1
0
mirror of https://github.com/mgerb/go-discord-bot synced 2026-01-10 09:02:49 +00:00

feat: add favorites - update dependencies

This commit is contained in:
2020-06-11 22:41:02 -05:00
parent b7d13ee5fd
commit 58170df201
18 changed files with 3040 additions and 2307 deletions

View File

@@ -1,19 +1,18 @@
import React from 'react';
import { SoundService } from '../../services';
import { SoundListType, SoundType } from '../../model';
interface IProps {
sound: SoundType;
type: 'sounds' | 'clips';
showDiscordPlay?: boolean;
type: SoundListType;
hasModPermissions: boolean;
showFavorite?: boolean;
onFavorite?: () => void;
onPlayBrowser: (sound: SoundType) => void;
onPlayDiscord: (sound: SoundType) => void;
}
interface IState {}
export interface SoundType {
extension: string;
name: string;
}
export class ClipPlayerControl extends React.Component<IProps, IState> {
checkExtension(extension: string) {
switch (extension) {
@@ -28,22 +27,21 @@ export class ClipPlayerControl extends React.Component<IProps, IState> {
}
}
handlePlayAudioInBrowser(sound: SoundType, type: string) {
const url = `/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension;
const audio = new Audio(url);
audio.play();
}
onPlayDiscord = (sound: SoundType) => {
SoundService.playSound(sound);
};
render() {
const { sound, showDiscordPlay, type } = this.props;
const { onPlayBrowser, onPlayDiscord, sound, hasModPermissions, showFavorite, type } = this.props;
return (
this.checkExtension(sound.extension) && (
<div className="flex flex--center">
{showFavorite && hasModPermissions && (
<i
title="Favorite"
className={'fa link fa-lg ' + (type === 'favorites' ? 'fa-trash' : 'fa-heart color__red')}
aria-hidden="true"
style={{ paddingRight: '5px' }}
onClick={() => !this.props.onFavorite || this.props.onFavorite()}
/>
)}
<a
href={`/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension}
download
@@ -56,15 +54,15 @@ export class ClipPlayerControl extends React.Component<IProps, IState> {
className="fa fa-play link"
aria-hidden="true"
style={{ paddingLeft: '15px' }}
onClick={() => this.handlePlayAudioInBrowser(sound, type)}
onClick={() => onPlayBrowser(sound)}
/>
{showDiscordPlay && (
{hasModPermissions && (
<i
title="Play in discord"
className="fa fa-play-circle link fa-lg"
aria-hidden="true"
style={{ paddingLeft: '10px' }}
onClick={() => this.onPlayDiscord(sound)}
onClick={() => onPlayDiscord(sound)}
/>
)}
</div>

View File

@@ -1,25 +1,23 @@
import React from 'react';
import { SoundListType, SoundType } from '../../model';
import { SoundService } from '../../services';
import { ClipPlayerControl } from '../clip-player-control/clip-player-control';
import './sound-list.scss';
interface Props {
soundList: SoundType[];
type: 'sounds' | 'clips';
type: SoundListType;
title: string;
onPlayDiscord?: (sound: SoundType) => void;
showDiscordPlay?: boolean;
hasModPermissions: boolean;
onFavorite?: (sound: SoundType) => void;
deleteFavorite?: (sound: SoundType) => void;
}
interface State {
showAudioControls: boolean[];
}
export interface SoundType {
extension: string;
name: string;
prefix?: string;
}
export class SoundList extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
@@ -41,14 +39,8 @@ export class SoundList extends React.Component<Props, State> {
}
}
handlePlayAudioInBrowser(sound: SoundType, type: string) {
const url = `/public/${type.toLowerCase()}/` + sound.name + '.' + sound.extension;
const audio = new Audio(url);
audio.play();
}
render() {
const { showDiscordPlay, soundList, title, type } = this.props;
const { hasModPermissions, onFavorite, soundList, title, type } = this.props;
return (
<div className="card">
@@ -66,10 +58,18 @@ export class SoundList extends React.Component<Props, State> {
return (
<div key={index} className="sound-list__item">
<div className="text-wrap">
{(type === 'sounds' && sound.prefix ? sound.prefix : '') + sound.name}
{((type === 'sounds' || type === 'favorites') && sound.prefix ? sound.prefix : '') + sound.name}
</div>
<ClipPlayerControl showDiscordPlay={showDiscordPlay} sound={sound} type={type} />
<ClipPlayerControl
showFavorite={type !== 'clips'}
onFavorite={() => !onFavorite || onFavorite(sound)}
hasModPermissions={hasModPermissions}
sound={sound}
type={type}
onPlayBrowser={(sound) => SoundService.playAudioInBrowser(sound, type)}
onPlayDiscord={SoundService.playSound}
/>
</div>
);
})

View File

@@ -1,5 +1,14 @@
import { IUser } from './user';
export type SoundListType = 'sounds' | 'clips' | 'favorites';
export interface SoundType {
extension: string;
name: string;
prefix?: string;
}
// sound from database
export interface ISound {
created_at: string;
deleted_at?: string;

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { SoundList, SoundType } from '../../components';
import { SoundList } from '../../components';
import { SoundType } from '../../model';
import { axios } from '../../services';
interface Props {}
@@ -23,7 +24,7 @@ export class Clips extends React.Component<Props, State> {
private getClipList() {
axios
.get('/api/cliplist')
.then(response => {
.then((response) => {
this.setState({
clipList: response.data,
});
@@ -37,7 +38,8 @@ export class Clips extends React.Component<Props, State> {
return (
<div className="content">
<div className="column">
<SoundList soundList={this.state.clipList} type="clips" title="Clips" />
{/* no need for permissions on this component - set false */}
<SoundList soundList={this.state.clipList} type="clips" title="Clips" hasModPermissions={false} />
</div>
</div>
);

View File

@@ -13,7 +13,7 @@ export class Oauth extends React.Component<Props, State> {
}
componentDidMount() {
const params = queryString.parse(this.props.location.search);
const params: any = queryString.parse(this.props.location.search);
if (params['code']) {
// do stuff here

View File

@@ -1,6 +1,7 @@
import { inject, observer } from 'mobx-react';
import React from 'react';
import { SoundList, SoundType, Uploader } from '../../components';
import { SoundList, Uploader } from '../../components';
import { SoundType } from '../../model';
import { axios, SoundService } from '../../services';
import { AppStore } from '../../stores';
import './soundboard.scss';
@@ -39,7 +40,7 @@ export class Soundboard extends React.Component<Props, State> {
if (!this.soundListCache) {
axios
.get('/api/soundlist')
.then(response => {
.then((response) => {
this.soundListCache = response.data;
this.setState({
soundList: response.data,
@@ -64,18 +65,42 @@ export class Soundboard extends React.Component<Props, State> {
SoundService.playSound(sound);
};
onFavorite = (sound: SoundType) => {
this.props.appStore?.addFavorite(sound);
};
onDeleteFavorite = (sound: SoundType) => {
this.props.appStore?.removeFavorite(sound);
};
render() {
const { soundList } = this.state;
const { appStore } = this.props;
if (!this.props.appStore) {
return null;
}
const { hasModPermissions, getFavorites } = this.props.appStore;
return (
<div className="content">
<Uploader onComplete={this.onUploadComplete} />
{((hasModPermissions && getFavorites().length) || 0 > 0) && (
<SoundList
soundList={getFavorites()}
title="Favorites"
type="favorites"
onPlayDiscord={this.onPlayDiscord}
hasModPermissions={hasModPermissions()}
onFavorite={this.onDeleteFavorite}
/>
)}
<SoundList
soundList={soundList}
title="Sounds"
type="sounds"
onPlayDiscord={this.onPlayDiscord}
showDiscordPlay={appStore!.hasModPermissions()}
hasModPermissions={hasModPermissions()}
onFavorite={this.onFavorite}
/>
</div>
);

View File

@@ -26,12 +26,12 @@ export class UploadHistory extends React.Component<IProps, IState> {
}
componentDidMount() {
SoundService.getSounds().then(sounds => {
SoundService.getSounds().then((sounds) => {
this.setState({ sounds });
});
}
renderUploadHistory = (sounds: ISound[], showDiscordPlay: boolean) => {
renderUploadHistory = (sounds: ISound[], hasModPermissions: boolean) => {
const sortedSounds = orderBy(sounds, 'created_at', 'desc');
return (
<div className="card">
@@ -63,7 +63,13 @@ export class UploadHistory extends React.Component<IProps, IState> {
{s.user.email}
</td>
<td>
<ClipPlayerControl showDiscordPlay={showDiscordPlay} sound={s} type="sounds"></ClipPlayerControl>
<ClipPlayerControl
onPlayBrowser={(sound) => SoundService.playAudioInBrowser(sound, 'sounds')}
onPlayDiscord={SoundService.playSound}
hasModPermissions={hasModPermissions}
sound={s}
type="sounds"
></ClipPlayerControl>
</td>
</tr>
);

View File

@@ -1,5 +1,4 @@
import { SoundType } from '../components/sound-list/sound-list';
import { ISound } from '../model';
import { ISound, SoundListType, SoundType } from '../model';
import { axios } from './axios.service';
const playSound = (sound: SoundType): Promise<any> => {
@@ -11,7 +10,15 @@ const getSounds = async (): Promise<ISound[]> => {
return res.data.data;
};
export const playAudioInBrowser = (sound: SoundType, type: SoundListType) => {
const t = type === 'favorites' ? 'sounds' : type;
const url = `/public/${t.toLowerCase()}/` + sound.name + '.' + sound.extension;
const audio = new Audio(url);
audio.play();
};
export const SoundService = {
getSounds,
playSound,
playAudioInBrowser,
};

View File

@@ -1,3 +1,5 @@
import { SoundType } from '../model';
const clear = () => {
localStorage.clear();
};
@@ -10,8 +12,19 @@ const getJWT = (): string | null => {
return localStorage.getItem('jwt');
};
const getFavorites = (): SoundType[] => {
const f = localStorage.getItem('favorites');
return f ? JSON.parse(f) : [];
};
const setFavorites = (f: SoundType[]): void => {
localStorage.setItem('favorites', JSON.stringify(f));
};
export const StorageService = {
clear,
getJWT,
setJWT,
getFavorites,
setFavorites,
};

View File

@@ -1,6 +1,7 @@
import jwt_decode from 'jwt-decode';
import { filter, uniqBy } from 'lodash';
import { action, observable } from 'mobx';
import { IClaims, Permissions } from '../model';
import { IClaims, Permissions, SoundType } from '../model';
import { axios, StorageService } from '../services';
import { Util } from '../util';
@@ -11,9 +12,12 @@ export class AppStore {
public jwt?: string;
@observable
public claims?: IClaims;
@observable
private favorites: SoundType[] = [];
constructor() {
const jwt = StorageService.getJWT();
this.favorites = StorageService.getFavorites();
this.setJWT(jwt as string);
this.initNavbar();
}
@@ -24,7 +28,7 @@ export class AppStore {
}
}
private setJWT(jwt?: string) {
private setJWT = (jwt?: string) => {
if (!jwt) {
return;
}
@@ -34,7 +38,21 @@ export class AppStore {
if (claims) {
this.claims = claims as IClaims;
}
}
};
public getFavorites = (): SoundType[] => {
return this.favorites;
};
public addFavorite = (f: SoundType): void => {
this.favorites = uniqBy([...this.favorites, f], 'name');
StorageService.setFavorites(this.favorites);
};
public removeFavorite = (f: SoundType): void => {
this.favorites = filter(this.favorites, (fa) => fa.name !== f.name);
StorageService.setFavorites(this.favorites);
};
@action
public toggleNavbar = () => {

View File

@@ -7,7 +7,7 @@ import './wrapper.scss';
export const Wrapper = inject('appStore')(
withRouter(
observer(({ appStore, children }) => {
observer(({ appStore, children }: any) => {
const openClass = appStore.navbarOpen ? 'wrapper--open' : '';
const onNavClick = () => {
if (Util.isMobileScreen()) {