Skip to content

Commit

Permalink
Merge pull request #405 from Yooooomi/release/1.11.0
Browse files Browse the repository at this point in the history
Release/1.11.0
  • Loading branch information
Yooooomi authored Aug 25, 2024
2 parents 7f7f884 + 144eb47 commit 01b9fba
Show file tree
Hide file tree
Showing 44 changed files with 2,325 additions and 1,963 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ It's composed of a web server which polls the Spotify API every now and then and
Follow the [docker-compose-example.yml](https://github.com/Yooooomi/your_spotify/blob/master/docker-compose-example.yml) to host your application through docker.

```yml
version: "3"

services:
server:
image: yooooomi/your_spotify_server
Expand Down Expand Up @@ -94,7 +92,7 @@ You can follow the instructions [here](https://github.com/Yooooomi/your_spotify/
| TIMEZONE | Europe/Paris | The timezone of your stats, only affects read requests since data is saved with UTC time |
| MONGO_ENDPOINT | mongodb://mongo:27017/your_spotify | The endpoint of the Mongo database, where **mongo** is the name of your service in the compose file |
| LOG_LEVEL | info | The log level, debug is useful if you encouter any bugs |
| CORS | _not defined_ | List of comma-separated origin allowed |
| CORS | _not defined_ | List of comma-separated origin allowed (defaults to CLIENT_ENDPOINT) |
| COOKIE_VALIDITY_MS | 1h | Validity time of the authentication cookie, following [this pattern](https://github.com/vercel/ms) |
| MAX_IMPORT_CACHE_SIZE | Infinite | The maximum element in the cache when importing data from an outside source, more cache means less requests to Spotify, resulting in faster imports |
| MONGO_NO_ADMIN_RIGHTS | false | Do not ask for admin right on the Mongo database |
Expand Down
33 changes: 16 additions & 17 deletions apps/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@your_spotify/client",
"version": "1.10.1",
"version": "1.11.0",
"private": true,
"scripts": {
"start": "DISABLE_ESLINT_PLUGIN=true react-scripts start",
Expand All @@ -11,31 +11,30 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.0",
"@mui/icons-material": "5.15.12",
"@mui/material": "5.15.12",
"@mui/system": "5.15.12",
"@mui/x-date-pickers": "6.19.6",
"@reduxjs/toolkit": "2.2.1",
"axios": "1.6.7",
"clsx": "2.1.0",
"date-fns": "3.4.0",
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@mui/icons-material": "5.16.7",
"@mui/material": "5.16.7",
"@mui/system": "5.16.7",
"@mui/x-date-pickers": "7.14.0",
"@reduxjs/toolkit": "2.2.7",
"axios": "1.7.5",
"clsx": "2.1.1",
"date-fns": "3.6.0",
"react": "^18.2.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.2.0",
"react-infinite-scroll-component": "^6.1.0",
"react-redux": "9.1.0",
"react-router-dom": "6.22.3",
"recharts": "2.12.2",
"redux": "5.0.1",
"web-vitals": "3.5.2"
"react-redux": "9.1.2",
"react-router-dom": "6.26.1",
"recharts": "2.12.7",
"redux": "5.0.1"
},
"devDependencies": {
"@types/node": "20.11.26",
"@types/react-copy-to-clipboard": "5.0.7",
"@types/react-date-range": "1.4.9",
"@types/react-dom": "18.2.21",
"@types/react-dom": "18.3.0",
"@your_spotify/dev": "*",
"react-scripts": "^5.0.1"
},
Expand Down
2 changes: 1 addition & 1 deletion apps/client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" crossorigin="use-credentials" />
<script src="%PUBLIC_URL%/variables.js"></script>

<title>Your Spotify</title>
Expand Down
7 changes: 6 additions & 1 deletion apps/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import CollaborativeSongs from "./scenes/Collaborative/Affinity/Songs";
import CollaborativeAlbums from "./scenes/Collaborative/Affinity/Albums";
import CollaborativeArtists from "./scenes/Collaborative/Affinity/Artists";
import "./App.css";
import RegistrationsDisabled from "./scenes/RegistrationsDisabled";
import RegistrationsDisabled from "./scenes/Error/RegistrationsDisabled";
import Affinity from "./scenes/Collaborative/Affinity";
import { useTheme } from "./services/theme";
import { selectDarkMode } from "./services/redux/modules/user/selector";
Expand All @@ -29,6 +29,7 @@ import TrackStats from "./scenes/TrackStats";
import LongestSessions from "./scenes/LongestSessions";
import AlbumStats from "./scenes/AlbumStats";
import Benchmarks from "./scenes/Benchmarks";
import ApiEndpointSetToFronted from "./scenes/Error/ApiEndpointSetToFronted";

function App() {
const dark = useSelector(selectDarkMode);
Expand Down Expand Up @@ -82,6 +83,10 @@ function App() {
path="/registrations-disabled"
element={<RegistrationsDisabled />}
/>
<Route
path="/oauth/spotify" // Error page when someone accidentally configures their API_ENDPOINT to point to the frontend instead of the backend
element={<ApiEndpointSetToFronted />}
/>
<Route
path="/top/songs"
element={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import React, {
PureComponent,
useCallback,
useMemo,
useRef,
useState,
} from "react";
import { PureComponent, useCallback, useMemo, useRef, useState } from "react";
import { useSelector } from "react-redux";
import { Tooltip as MuiTooltip } from "@mui/material";
import { Link } from "react-router-dom";
Expand Down
6 changes: 0 additions & 6 deletions apps/client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import store from "./services/redux";

const element = document.getElementById("root");
Expand All @@ -13,8 +12,3 @@ root.render(
<App />
</Provider>,
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
15 changes: 0 additions & 15 deletions apps/client/src/reportWebVitals.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Text from "../../../components/Text";
import s from "../index.module.css";
import { getApiEndpoint } from "../../../services/tools";

export default function ApiEndpointSetToFrontend() {
return (
<div className={s.root}>
<Text element="h1">API Endpoint is not set up correctly</Text>
<Text className={s.explain}>
This request should have reached the backend, but was handled by the
frontend instead.
<p />
This is usually because your &nbsp;<code>API_ENDPOINT</code>&nbsp;
variable points to the frontend instead of the backend. Please
double-check your configuration.
<p />
The current configuration is: <br />
<code>API_ENDPOINT={getApiEndpoint()}</code>
</Text>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./ApiEndpointSetToFrontend";
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Text from "../../components/Text";
import s from "./index.module.css";
import Text from "../../../components/Text";
import s from "../index.module.css";

export default function RegistrationsDisabled() {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export default function FullPrivacy() {
</label>
{files &&
Array.from(Array(files.length).keys()).map(i => (
<div key={i}>{files.item(i)?.name}</div>
<Text key={i} element="div">
{files.item(i)?.name}
</Text>
))}
{wrongFiles && (
<Text className={s.alert}>
Expand Down
6 changes: 4 additions & 2 deletions apps/client/src/scenes/Settings/Importer/Privacy/Privacy.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from "react";
import { useCallback, useMemo, useState } from "react";
import { Button, CircularProgress } from "@mui/material";
import { startImportPrivacy } from "../../../../services/redux/modules/import/thunk";
import Text from "../../../../components/Text";
Expand Down Expand Up @@ -57,7 +57,9 @@ export default function Privacy() {
</label>
{files &&
Array.from(Array(files.length).keys()).map(i => (
<div key={i}>{files.item(i)?.name}</div>
<Text key={i} element="div">
{files.item(i)?.name}
</Text>
))}
{wrongFiles && (
<Text className={s.alert}>
Expand Down
16 changes: 14 additions & 2 deletions apps/client/src/scenes/Settings/PublicToken/PublicToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import Text from "../../../components/Text";
import TitleCard from "../../../components/TitleCard";
import { alertMessage } from "../../../services/redux/modules/message/reducer";
import { selectUser } from "../../../services/redux/modules/user/selector";
import { generateNewPublicToken } from "../../../services/redux/modules/user/thunk";
import {
deletePublicToken,
generateNewPublicToken,
} from "../../../services/redux/modules/user/thunk";
import { useAppDispatch } from "../../../services/redux/tools";
import SettingLine from "../SettingLine";
import s from "./index.module.css";
Expand All @@ -20,6 +23,10 @@ export default function PublicToken() {
dispatch(generateNewPublicToken());
}, [dispatch]);

const deleteToken = useCallback(() => {
dispatch(deletePublicToken());
}, [dispatch]);

const onCopy = useCallback(() => {
dispatch(
alertMessage({
Expand Down Expand Up @@ -60,7 +67,12 @@ export default function PublicToken() {
/>
<SettingLine
left="Regenerate"
right={<Button onClick={generate}>Generate</Button>}
right={
<div className={s.row}>
<Button onClick={generate}>Generate</Button>
<Button onClick={deleteToken}>Delete Token</Button>
</div>
}
/>
</TitleCard>
);
Expand Down
7 changes: 7 additions & 0 deletions apps/client/src/scenes/Settings/PublicToken/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@
.link {
cursor: pointer;
}

.row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
}
2 changes: 2 additions & 0 deletions apps/client/src/scenes/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import SetAdmin from "./SetAdmin";
import SpotifyAccountInfos from "./SpotifyAccountInfos";
import Timezone from "./Timezone";
import DateFormat from "./DateFormat";
import { StatMeasurement } from "./StatMeasurement";

export default function Settings() {
const settings = useSelector(selectSettings);
Expand Down Expand Up @@ -109,6 +110,7 @@ export default function Settings() {
{!isPublic && <BlacklistArtist />}
{!isPublic && <Timezone />}
{!isPublic && <DateFormat />}
{!isPublic && <StatMeasurement />}
</Masonry>
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Select, MenuItem } from "@mui/material";
import { useCallback } from "react";
import { useSelector } from "react-redux";
import Text from "../../../components/Text";
import TitleCard from "../../../components/TitleCard";
import { changeStatUnit } from "../../../services/redux/modules/settings/thunk";
import { selectStatMeasurement } from "../../../services/redux/modules/user/selector";
import { useAppDispatch } from "../../../services/redux/tools";
import SettingLine from "../SettingLine";
import s from "./index.module.css";

const units = [
{ name: "Count", value: "number" },
{ name: "Duration", value: "duration" },
];

export function StatMeasurement() {
const dispatch = useAppDispatch();
const statMeasurement = useSelector(selectStatMeasurement);

const handleChangeStatMeasurement = useCallback(
(newStatUnit: string | null | undefined) => {
if (newStatUnit !== "number" && newStatUnit !== "duration") {
return;
}
dispatch(changeStatUnit(newStatUnit ?? "number")).catch(console.error);
},
[dispatch],
);

return (
<TitleCard title="Stat measurement used">
<Text element="span" className={s.marginbottom}>
Measurement used to compute most listened elements.
</Text>
<SettingLine
left="Stat measurement"
right={
<Select
variant="standard"
value={statMeasurement}
onChange={ev => handleChangeStatMeasurement(ev.target.value)}>
{units.map(unit => (
<MenuItem key={unit.value} value={unit.value}>
{unit.name}
</MenuItem>
))}
</Select>
}
/>
</TitleCard>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.marginbottom {
display: block;
margin-bottom: 8px;
}
1 change: 1 addition & 0 deletions apps/client/src/scenes/Settings/StatMeasurement/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./StatMeasurement";
2 changes: 1 addition & 1 deletion apps/client/src/scenes/Tops/Songs/Songs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import s from "./index.module.css";

export default function Songs() {
const { interval } = useSelector(selectRawIntervalDetail);

const { items, hasMore, onNext } = useInfiniteScroll(
interval,
api.getBestSongs,
Expand Down Expand Up @@ -55,7 +56,6 @@ export default function Songs() {
{items.map(item => (
<Track
playable
// eslint-disable-next-line react/no-array-index-key
key={item.track.id}
track={item.track}
album={item.album}
Expand Down
13 changes: 9 additions & 4 deletions apps/client/src/scenes/Tops/Songs/Track/TrackHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useTrackGrid } from "./TrackGrid";

export default function TrackHeader() {
const [isMobile, isTablet] = useMobile();

const trackGrid = useTrackGrid();

const columns = useMemo<ColumnDescription[]>(
Expand All @@ -29,14 +30,18 @@ export default function TrackHeader() {
},
{
...trackGrid.count,
node: <Text element="div">Count</Text>,
node: (
<div className={s.count}>
<Text element="div">Count</Text>
</div>
),
},
{
...trackGrid.total,
node: (
<Text element="div" className="center">
Total
</Text>
<div className={s.total}>
<Text element="div">Total</Text>
</div>
),
},
{
Expand Down
Loading

0 comments on commit 01b9fba

Please sign in to comment.