Skip to content

Commit

Permalink
Merge pull request funmusicplace#805 from funmusicplace/various-fixes
Browse files Browse the repository at this point in the history
feat: punt license feature
  • Loading branch information
simonv3 authored Aug 14, 2024
2 parents 51d4db0 + db1fe6c commit 1f252d1
Show file tree
Hide file tree
Showing 25 changed files with 414 additions and 51 deletions.
68 changes: 68 additions & 0 deletions client/src/components/Admin/AdminLicenses.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { css } from "@emotion/css";

import LicenseForm from "components/common/LicenseForm";
import Modal from "components/common/Modal";
import Table from "components/common/Table";
import React from "react";
import { Outlet, useNavigate } from "react-router-dom";
import api from "services/api";

export const AdminLicenses: React.FC = () => {
const navigate = useNavigate();
const [results, setResults] = React.useState<License[]>([]);
const [openModal, setOpenModal] = React.useState(false);

const callback = React.useCallback(async () => {
const { results } = await api.getMany<License>("licenses");
setResults(results);
}, []);

React.useEffect(() => {
callback();
}, []);

return (
<div
className={css`
flex-grow: 1;
`}
>
<h3>Licenses</h3>
<LicenseForm callback={callback} />
{results.length > 0 && (
<Table>
<thead>
<tr>
<th />
<th>Short</th>
<th>URL</th>
<th></th>
</tr>
</thead>
<tbody>
{results.map((license, index) => (
<tr key={license.short}>
<td>{index + 1}</td>

<td>{license.short}</td>
<td>{license.link}</td>
</tr>
))}
</tbody>
</Table>
)}
{/* <LoadingButton /> */}
<Modal
open={openModal}
onClose={() => {
setOpenModal(false);
navigate("/admin/trackgroups");
}}
>
<Outlet />
</Modal>
</div>
);
};

export default AdminLicenses;
7 changes: 3 additions & 4 deletions client/src/components/Home/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import { css } from "@emotion/css";
import { SectionHeader } from "./Home";
import WidthContainer from "components/common/WidthContainer";
import { useTranslation } from "react-i18next";
import PostCard from "components/Post/PostCard";
import { useQuery } from "@tanstack/react-query";
import { queryPosts } from "queries";
import PostGrid from "components/Post/PostGrid";

const Posts = () => {
const { t } = useTranslation("translation", { keyPrefix: "home" });
const { data: posts } = useQuery(queryPosts({ take: 3 }));

if (posts?.results?.length === 0) {
const response = useQuery(queryPosts({ take: 3 }));
const { data: posts } = response;
if (posts?.results?.length === 0 || posts === undefined) {
return null;
}

Expand Down
55 changes: 27 additions & 28 deletions client/src/components/ManageArtist/EditTrackRow.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { useForm, FormProvider } from "react-hook-form";
import { InputEl } from "components/common/Input";
import { FaEllipsisV, FaSave, FaTimes, FaUpload } from "react-icons/fa";
import { FaSave, FaTimes, FaUpload } from "react-icons/fa";
import { css } from "@emotion/css";
import { useTranslation } from "react-i18next";
import Tooltip from "components/common/Tooltip";
Expand All @@ -15,11 +15,13 @@ import useJobStatusCheck from "utils/useJobStatusCheck";
import LoadingSpinner from "components/common/LoadingSpinner";
import Button from "components/common/Button";
import { useAuthContext } from "state/AuthContext";
import ManageTrackLicense from "./ManageTrackLicense";

export interface FormData {
title: string;
status: "preview" | "must-own";
trackFile: FileList;
licenseId: number;
}

const EditTrackRow: React.FC<{
Expand All @@ -29,7 +31,6 @@ const EditTrackRow: React.FC<{
}> = ({ track, onCancelEditing: cancelEditing, reload }) => {
const [isSaving, setIsSaving] = React.useState(false);
const { t } = useTranslation("translation", { keyPrefix: "manageAlbum" });
const [showMoreDetails, setShowMoreDetails] = React.useState(false);
const { uploadJobs, setUploadJobs } = useJobStatusCheck({
reload: cancelEditing,
});
Expand All @@ -38,6 +39,7 @@ const EditTrackRow: React.FC<{
defaultValues: {
title: track.title,
status: track.isPreview ? "preview" : "must-own",
licenseId: track.licenseId,
},
});

Expand All @@ -51,17 +53,22 @@ const EditTrackRow: React.FC<{
reset({
title: track.title,
status: track.isPreview ? "preview" : "must-own",
licenseId: track.licenseId,
});
cancelEditing();
}, [reset, track, cancelEditing]);

const onSave = React.useCallback(
async (formData: FormData) => {
console.log("formData", formData);
try {
setIsSaving(true);
const packet = {
title: formData.title,
isPreview: formData.status === "preview",
licenseId: formData.licenseId
? Number(formData.licenseId)
: undefined,
};

await api.put<Partial<Track>, { track: Track }>(
Expand Down Expand Up @@ -187,34 +194,26 @@ const EditTrackRow: React.FC<{
: ""}
`}
/>
<Tooltip hoverText={t("moreTrackDetails")} underline={false}>
<Button
disabled={isSaving || isDisabled}
compact
variant="dashed"
startIcon={<FaEllipsisV />}
onClick={() => setShowMoreDetails((val) => !val)}
type="button"
/>
</Tooltip>
</td>
</tr>
{showMoreDetails && (
<tr>
<td colSpan={99}>
<div
className={css`
max-width: 600px;
max-height: 200px;
overflow: scroll;
`}
>
<strong>raw id3 tag: </strong>
{JSON.stringify(track.metadata, null, 2)}
</div>
</td>
</tr>
)}
<tr>
<td colSpan={2}>
<ManageTrackLicense />
</td>
<td />
<td colSpan={99}>
<div
className={css`
max-width: 600px;
max-height: 200px;
overflow: scroll;
`}
>
<strong>raw id3 tag: </strong>
{JSON.stringify(track.metadata, null, 2)}
</div>
</td>
</tr>
</FormProvider>
);
};
Expand Down
61 changes: 61 additions & 0 deletions client/src/components/ManageArtist/ManageTrackLicense.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useFormContext } from "react-hook-form";
import { SelectEl } from "components/common/Select";
import { queryLicenses } from "queries/licenses";
import { useQuery } from "@tanstack/react-query";
import FormComponent from "components/common/FormComponent";
import { useTranslation } from "react-i18next";
import Button from "components/common/Button";
import { css } from "@emotion/css";
import Modal from "components/common/Modal";
import React from "react";
import LicenseForm from "components/common/LicenseForm";

const ManageTrackLicense = () => {
const [isModalOpen, setIsModalOpen] = React.useState(false);
const { t } = useTranslation("translation", { keyPrefix: "manageAlbum" });
const methods = useFormContext();

const { data: licenses, refetch } = useQuery(queryLicenses());

return (
<>
<Modal
open={isModalOpen}
onClose={() => setIsModalOpen(false)}
title={t("addALicense")}
>
<LicenseForm callback={refetch} />
</Modal>
<FormComponent>
<label>{t("license")}</label>
<SelectEl {...methods.register("licenseId")}>
{licenses?.results.map((license) => (
<option value={license.id}>{license.short}</option>
))}
</SelectEl>
<small
className={css`
display: flex;
align-items: center;
`}
>
{t("dontSeeTheLicenseYouWant")}
<Button
variant="dashed"
onClick={() => setIsModalOpen(true)}
type="button"
compact
className={css`
margin-left: 0.25rem;
`}
>
{t("addIt")}
</Button>
</small>
<small>{t("whatMeanLicense")}</small>
</FormComponent>
</>
);
};

export default ManageTrackLicense;
58 changes: 58 additions & 0 deletions client/src/components/common/LicenseForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";
import Button from "./Button";
import { InputEl } from "./Input";
import { useForm } from "react-hook-form";
import api from "services/api";
import useErrorHandler from "services/useErrorHandler";
import FormComponent from "./FormComponent";
import { useTranslation } from "react-i18next";

interface FormData {
short: string;
link?: string;
name: string;
}

const LicenseForm: React.FC<{ callback: () => void }> = ({ callback }) => {
const methods = useForm<FormData>();
const errorHandler = useErrorHandler();
const { t } = useTranslation("translation", { keyPrefix: "manageLicense" });

const onSubmit = React.useCallback(async (data: FormData) => {
try {
await api.post(`licenses`, data);
await callback();
} catch (e) {
errorHandler(e);
}
}, []);

return (
<form onSubmit={methods.handleSubmit(onSubmit)}>
<FormComponent>
<label>{t("shortLabelForLicense")}</label>
<InputEl
{...methods.register("short")}
placeholder={t("egShort") ?? ""}
/>{" "}
</FormComponent>
<FormComponent>
<label>{t("longLabel")}</label>
<InputEl
{...methods.register("name")}
placeholder={t("egLong") ?? ""}
/>{" "}
</FormComponent>
<FormComponent>
<label>{t("urlForLabel")}</label>
<InputEl
{...methods.register("link")}
placeholder={t("egLink") ?? ""}
/>{" "}
</FormComponent>
<Button>{"add"}</Button>
</form>
);
};

export default LicenseForm;
2 changes: 1 addition & 1 deletion client/src/components/common/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const close = css`
export const Modal: React.FC<{
open: boolean;
children: React.ReactNode;
title?: string;
title?: string | null;
onClose: () => void;
size?: "small";
className?: string;
Expand Down
20 changes: 20 additions & 0 deletions client/src/components/common/TrackRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import TrackRowPlayControl from "./TrackRowPlayControl";
import { useAuthContext } from "state/AuthContext";
import { useTranslation } from "react-i18next";
import styled from "@emotion/styled";
import Tooltip from "./Tooltip";

const TR = styled.tr<{ canPlayTrack: boolean }>`
${(props) =>
Expand Down Expand Up @@ -210,6 +211,7 @@ const TrackRow: React.FC<{
</div>
</div>
</TrackTitleTD>

<td align="right">
<Button
compact
Expand All @@ -231,6 +233,24 @@ const TrackRow: React.FC<{
`}
></Button>
</td>
{track.license && track.license?.short !== "copyright" && (
<td>
<Tooltip hoverText={track.license.name}>
{track.license.link && (
<a
target="_blank"
href={track.license.link}
onClick={(e) => {
e.stopPropagation();
}}
>
{track.license.short}
</a>
)}
{!track.license.link && track.license.short}
</Tooltip>
</td>
)}
</TR>
);
};
Expand Down
19 changes: 19 additions & 0 deletions client/src/queries/licenses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { QueryFunction, queryOptions } from "@tanstack/react-query";
import * as api from "./fetch/fetchWrapper";
import { QUERY_KEY_TAGS } from "./queryKeys";

const fetchLicenses: QueryFunction<
{ results: License[]; total?: number },
["fetchLicenses", ...any]
> = ({ queryKey: [_, {}], signal }) => {
const params = new URLSearchParams();

return api.get(`v1/licenses?${params}`, { signal });
};

export function queryLicenses() {
return queryOptions({
queryKey: ["fetchLicenses", {}, QUERY_KEY_TAGS],
queryFn: fetchLicenses,
});
}
Loading

0 comments on commit 1f252d1

Please sign in to comment.