fix voting
Seto Elkahfi committed
Aug 3, 2024 at 00:38 UTC
af895e57eae26b513ac774be9a9dcfeb7f3325be
7 files changed
+61
-46
frontend/splitfire-desktop/app/_src/lib/requestSplitService.ts
+2
-2
@@ -1,8 +1,8 @@
1
import { AudioFile } from "../components/player/models/AudioFile"
2
import axios from "./axios"
3
4
-export default function requestSplitService(providerId: string, accessToken: string): Promise<any> {
5
- return axios.post(`/split`, { provider_id: providerId },
4
+export default function requestSplitService(songProviderId: number, accessToken: string): Promise<any> {
5
+ return axios.post(`/split`, { provider_id: songProviderId },
6
{
7
headers: {
8
'Content-Type': 'application/json',
frontend/splitfire-desktop/app/_src/models/SongResponse.tsx
+1
-1
@@ -10,7 +10,7 @@ export interface SongResponse {
10
}
11
12
export interface SongProvider {
13
- id: string,
13
+ id: number,
14
name: string,
15
provider_id: string,
16
provider_type: ProviderType,
frontend/splitfire-desktop/app/split/_components/button-split.tsx
+10
-10
@@ -18,21 +18,21 @@ enum State {
18
ERROR,
19
}
20
21
-export default function ButtonGenerateBackingTracks(props: {
22
- providerId: string;
21
+export default function ButtonGenerateBackingTracks({
22
+ songProviderId,
23
+ audioFile,
24
+ aggregateVotes
25
+}: {
26
+ songProviderId: number;
27
audioFile: AudioFile | null;
28
aggregateVotes: number;
29
}) {
30
+
31
const [state, setState] = useState(State.LOADED);
32
const { user } = useContext(UserContext);
33
const [goToLogin, setGoToLogin] = useState(false);
29
- const [audioFile, setAudioFile] = useState<AudioFile | null>(null);
34
const router = useRouter();
35
32
- useState(() => {
33
- setAudioFile(props.audioFile);
34
- });
35
-
36
const splitRequest = () => {
37
if (!user || !user.accessToken) {
38
setGoToLogin(true);
@@ -40,12 +40,12 @@ export default function ButtonGenerateBackingTracks(props: {
40
}
41
42
setState(State.LOADING);
43
- requestSplitService(props.providerId, user.accessToken)
43
+ requestSplitService(songProviderId, user.accessToken)
44
.then((res) => {
45
console.log(res);
46
const response: SplitResponse = res.data;
47
if (response.code === HTTPStatusCode.OK) {
48
- setAudioFile(response.audio_file);
48
+ audioFile = response.audio_file;
49
setState(State.LOADED);
50
} else {
51
setState(State.ERROR);
@@ -67,7 +67,7 @@ export default function ButtonGenerateBackingTracks(props: {
67
audioFile &&
68
(audioFile.status === Status.SPLITTING ||
69
audioFile.status === Status.DOWNLOADING);
70
- const isReadyToSplit = props.aggregateVotes > splitTreshold;
70
+ const isReadyToSplit = aggregateVotes > splitTreshold;
71
72
if (goToLogin) {
73
router.push("/login");
frontend/splitfire-desktop/app/split/_components/votes-view.tsx
+9
-8
@@ -20,6 +20,8 @@ import LetsPlayView from "./lets-play";
20
import { invoke } from "@tauri-apps/api";
21
import { TAURI_CONTENT_SONG_BRIDGE_VOTE } from "@/app/_src/lib/tauriHandler";
22
import { useLogger } from "@/app/_src/lib/logger";
23
+import { SongProviderResponse } from "@/models/content";
24
+import { TauriResponse } from "@/models/shared";
25
26
enum State {
27
LOADING,
@@ -41,7 +43,7 @@ export interface VoteState {
43
}
44
45
type VotePayload = {
44
- songProviderId: string;
46
+ songProviderId: number;
47
voteType: string;
48
accessToken: string;
49
}
@@ -51,7 +53,7 @@ export default function UpDownVotesView({
53
votes,
54
audioFile,
55
}: {
54
- songProviderId: string;
56
+ songProviderId: number;
57
votes: SongProviderVote[];
58
audioFile: AudioFile | null;
59
}) {
@@ -132,9 +134,8 @@ export default function UpDownVotesView({
134
voteType: type,
135
accessToken: user.accessToken,
136
};
135
- const response = await invoke<SongBridgeResponse>(TAURI_CONTENT_SONG_BRIDGE_VOTE, payload);
136
- log.debug(response.votes);
137
- if (response.code === HTTPStatusCode.OK) {
137
+ const response = await invoke<SongProviderResponse>(TAURI_CONTENT_SONG_BRIDGE_VOTE, payload);
138
+ if (response.status === TauriResponse.SUCCESS) {
139
setVoteState({
140
aggregate: calculateVotes(response.votes),
141
buttonUpStyle: buttonStyle(response.votes, VoteType.UP),
@@ -146,11 +147,11 @@ export default function UpDownVotesView({
147
});
148
setState(State.LOADED);
149
} else {
149
- console.log("error");
150
+ log.error("Error voting", response);
151
setState(State.ERROR);
152
}
153
} catch (error) {
153
- console.log(error);
154
+ log.error(error);
155
setState(State.ERROR);
156
}
157
}
@@ -184,7 +185,7 @@ export default function UpDownVotesView({
185
);
186
const mainButton = (
187
<ButtonGenerateBackingTracks
187
- providerId={songProviderId}
188
+ songProviderId={songProviderId}
189
audioFile={audioFile}
190
aggregateVotes={voteState.aggregate}
191
/>
frontend/splitfire-desktop/models/content.ts
+8
@@ -1,5 +1,6 @@
1
import { SongProvider } from "@/app/_src/models/SongResponse";
2
import { TauriResponse } from "./shared";
3
+import { SongProviderVote } from "@/app/_src/models/SongVotesDetailResponse";
4
5
// Need to be renamed into more generic name
6
export interface ContentCarouselResponse {
@@ -18,4 +19,11 @@ export interface PlayerPrepareResponse {
19
status: TauriResponse,
20
message: string,
21
audio_file_name?: string,
22
+}
23
+
24
+export interface SongProviderResponse {
25
+ status: TauriResponse,
26
+ message: string,
27
+ song_provider: SongProvider
28
+ votes: SongProviderVote[]
29
}
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/models/content.rs
+3
-3
@@ -39,8 +39,8 @@ pub enum ProviderType {
39
40
#[derive(Serialize)]
41
#[derive(Debug)]
42
-pub struct ContentSongBridgeResponse {
43
- pub code: TauriResponse,
42
+pub struct ContentSongProviderResponse {
43
+ pub status: TauriResponse,
44
pub message: String,
45
pub song_provider: Option<SongProvider>,
46
pub votes: Vec<SongProviderVote>
@@ -48,7 +48,7 @@ pub struct ContentSongBridgeResponse {
48
49
#[derive(Serialize, Deserialize)]
50
#[derive(Debug)]
51
-pub struct SongBridgeResponse {
51
+pub struct SongProviderResponse {
52
pub code: i32, // API response code
53
pub message: String,
54
pub error: Option<String>,
frontend/splitfire-desktop/src-tauri/src/rest/content.rs
+28
-22
@@ -5,8 +5,8 @@ use crate::{
5
},
6
models::{
7
content::{
8
- CarouselResponse, ContentCarouselResponse, ContentSongBridgeResponse,
9
- SongBridgeResponse, VoteType,
8
+ CarouselResponse, ContentCarouselResponse, ContentSongProviderResponse,
9
+ SongProviderResponse, VoteType,
10
},
11
player::TauriResponse,
12
},
@@ -91,7 +91,10 @@ pub async fn content_ready_to_play() -> ContentCarouselResponse {
91
}
92
93
#[tauri::command]
94
-pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSongBridgeResponse {
94
+pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSongProviderResponse {
95
+ // song_provider_id is a string because it is comes from a nextjs query parameter.
96
+ // When we get it from the server, it actually is a number.
97
+ // It is Rails id convention.
98
debug!("Song provider id: {:?}", song_provider_id);
99
let url =
100
content_url_builder(PATH_SONG_BRIDGE_DETAIL).replace("{providerId}", &song_provider_id);
@@ -101,8 +104,8 @@ pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSong
104
Ok(response) => response,
105
Err(e) => {
106
error!("Failed to get response: {:?}", e);
104
- return ContentSongBridgeResponse {
105
- code: TauriResponse::Error,
107
+ return ContentSongProviderResponse {
108
+ status: TauriResponse::Error,
109
message: e.to_string(),
110
song_provider: None,
111
votes: vec![],
@@ -110,12 +113,12 @@ pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSong
113
}
114
};
115
113
- let res: SongBridgeResponse = match response.json().await {
116
+ let res: SongProviderResponse = match response.json().await {
117
Ok(json) => json,
118
Err(e) => {
119
error!("Failed to parse response: {:?}", e);
117
- return ContentSongBridgeResponse {
118
- code: TauriResponse::Error,
120
+ return ContentSongProviderResponse {
121
+ status: TauriResponse::Error,
122
message: e.to_string(),
123
song_provider: None,
124
votes: vec![],
@@ -130,8 +133,8 @@ pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSong
133
None => vec![],
134
};
135
133
- ContentSongBridgeResponse {
134
- code: TauriResponse::Success,
136
+ ContentSongProviderResponse {
137
+ status: TauriResponse::Success,
138
message: res.message,
139
song_provider: res.song_provider,
140
votes,
@@ -177,16 +180,19 @@ pub async fn content_top_voted() -> ContentCarouselResponse {
180
181
#[tauri::command]
182
pub async fn content_song_bridge_vote(
180
- song_provider_id: String,
183
+ song_provider_id: i32,
184
vote_type: VoteType,
185
access_token: String,
183
-) -> ContentSongBridgeResponse {
186
+) -> ContentSongProviderResponse {
187
debug!("Song provider id: {:?}", song_provider_id);
185
- let url = content_url_builder(PATH_SONG_BRIDGE_VOTE).replace("{providerId}", &song_provider_id);
186
- let body = json!({ "vote_type": vote_type, "provider_id": song_provider_id }).to_string();
188
+ let url = content_url_builder(PATH_SONG_BRIDGE_VOTE).replace("{providerId}", &song_provider_id.to_string());
189
+ let body = json!({
190
+ "vote_type": vote_type,
191
+ "provider_id": song_provider_id
192
+ });
193
let response: Result<reqwest::Response, reqwest::Error> = Client::new()
194
.post(url)
189
- .body(body)
195
+ .json(&body)
196
.header("Authorization", format!("Bearer {}", access_token))
197
.send()
198
.await;
@@ -195,8 +201,8 @@ pub async fn content_song_bridge_vote(
201
Ok(response) => response,
202
Err(e) => {
203
error!("Failed to get response: {:?}", e);
198
- return ContentSongBridgeResponse {
199
- code: TauriResponse::Error,
204
+ return ContentSongProviderResponse {
205
+ status: TauriResponse::Error,
206
message: e.to_string(),
207
song_provider: None,
208
votes: vec![],
@@ -204,12 +210,12 @@ pub async fn content_song_bridge_vote(
210
}
211
};
212
207
- let res: SongBridgeResponse = match response.json().await {
213
+ let res: SongProviderResponse = match response.json().await {
214
Ok(json) => json,
215
Err(e) => {
216
error!("Failed to parse response: {:?}", e);
211
- return ContentSongBridgeResponse {
212
- code: TauriResponse::Error,
217
+ return ContentSongProviderResponse {
218
+ status: TauriResponse::Error,
219
message: e.to_string(),
220
song_provider: None,
221
votes: vec![],
@@ -224,8 +230,8 @@ pub async fn content_song_bridge_vote(
230
None => vec![],
231
};
232
227
- ContentSongBridgeResponse {
228
- code: TauriResponse::Success,
233
+ ContentSongProviderResponse {
234
+ status: TauriResponse::Success,
235
message: res.message,
236
song_provider: res.song_provider,
237
votes,