diff --git a/src/common/playlists/PlayList.jsx b/src/common/playlists/PlayList.jsx index 22e4d63c3..751c47293 100644 --- a/src/common/playlists/PlayList.jsx +++ b/src/common/playlists/PlayList.jsx @@ -8,6 +8,7 @@ import { useParams } from "react-router-dom"; import useGetPlays from 'common/hooks/useGetPlays' import "./playlist.css"; +import { toSanitized } from "common/services/string"; const PlayList = () => { const [loading, error, plays] = useGetPlays(); @@ -37,7 +38,7 @@ const PlayList = () => { { - all_plays[play.component ? play.component : play.title_name] && + all_plays[play.component ? play.component : toSanitized(play.title_name)] && } diff --git a/src/common/playlists/PlayMeta.jsx b/src/common/playlists/PlayMeta.jsx index eca01ddf0..1fc84f0df 100644 --- a/src/common/playlists/PlayMeta.jsx +++ b/src/common/playlists/PlayMeta.jsx @@ -4,8 +4,8 @@ import * as plays from "plays"; import { useParams } from "react-router-dom"; import { submit } from "common/services/request"; import Loader from "common/spinner/spinner"; -import { toTitleCase } from "common/services/string"; -import { FetchPlaysByNameAndUser } from "common/services/request/query/fetch-plays"; +import { toSanitized, toTitleCase, toTitleCaseTrimmed } from "common/services/string"; +import { FetchPlaysBySlugAndUser } from "common/services/request/query/fetch-plays"; import { PageNotFound } from "common"; function PlayMeta() { @@ -16,9 +16,10 @@ function PlayMeta() { const [metaImage, setMetaImage] = useState(); useEffect(() => { - submit(FetchPlaysByNameAndUser(decodeURI(playname), decodeURI(username))) + submit(FetchPlaysBySlugAndUser(decodeURI(playname), decodeURI(username))) .then((res) => { const play_obj = res[0]; + play_obj.title_name = toTitleCaseTrimmed(play_obj.name); setPlay(play_obj); setMetaImage(play_obj.cover); setLoading(false); @@ -38,7 +39,7 @@ function PlayMeta() { const renderPlayComponent = () => { const Comp = - plays[play.component || toTitleCase(play.name).replace(/ /g, "")]; + plays[play.component || toSanitized(play.title_name)] ; return ; }; diff --git a/src/common/playlists/PlayThumbnail.jsx b/src/common/playlists/PlayThumbnail.jsx index 18d95621a..6b8d60ec2 100644 --- a/src/common/playlists/PlayThumbnail.jsx +++ b/src/common/playlists/PlayThumbnail.jsx @@ -53,8 +53,7 @@ const PlayThumbnail = ({ play }) => { // if it is not passed as a meta data // check in the play folder for a cover image // with the name cover.png - const playFolder = play.path.split("/")[2]; - import(`plays/${playFolder}/cover.png`) + import(`plays/${play.slug}/cover.png`) .then((Cover) => { setCover(Cover.default); }) @@ -72,7 +71,7 @@ const PlayThumbnail = ({ play }) => { return (
  • diff --git a/src/common/services/plays.js b/src/common/services/plays.js index 357ac8036..f38950f2f 100644 --- a/src/common/services/plays.js +++ b/src/common/services/plays.js @@ -4,7 +4,7 @@ import { associatePlayWithTagQuery, createPlayQuery, } from "./request/query/play"; -import { toKebabCase } from "./string"; +import { toKebabCase, toSlug } from "./string"; import { Tags } from "./tags"; // Create a play @@ -25,6 +25,9 @@ const createPlay = (playObject) => { ? objectToSubmit.style.value : "css"; + // Prepare slug + objectToSubmit.slug = toSlug(objectToSubmit.name); + // Prepare level objectToSubmit.level_id = objectToSubmit.level.value; delete objectToSubmit.level; diff --git a/src/common/services/request/query/fetch-plays.js b/src/common/services/request/query/fetch-plays.js index 006b5aba2..dbd6eb69f 100644 --- a/src/common/services/request/query/fetch-plays.js +++ b/src/common/services/request/query/fetch-plays.js @@ -1,9 +1,9 @@ export function FetchPlaysSimple() { - return {...BasiFetchParam} + return { ...BasiFetchParam }; } export function FetchPlaysByID(id) { - const payload = { ...BasiFetchParam }; + const payload = { ...DetailedFetchParam }; payload.where = { clause: { @@ -19,17 +19,17 @@ export function FetchPlaysByID(id) { return payload; } -export function FetchPlaysByNameAndUser(playname, username) { - const payload = { ...BasiFetchParam }; +export function FetchPlaysBySlugAndUser(playslug, username) { + const payload = { ...DetailedFetchParam }; payload.where = { clause: { operator: "and", conditions: [ { - field: "name", + field: "slug", operator: "ilike", - value: playname, + value: playslug, type: "string", }, { @@ -50,23 +50,30 @@ const BasiFetchParam = { function: "plays", write: false, return: [ - "blog", "component", "cover", - "created_at", "description", "featured", "dev_mode", "github", - "id", "language", { play_like: ["liked", "play_id", "user_id"] }, - { level: ["name"] }, "name", - "path", - { play_tags: { tag: ["name"] } }, - "updated_at", + "slug", { user: ["id", "displayName", "avatarUrl"] }, - "video", ], }; + +const DetailedFetchParam = { + ...BasiFetchParam, + ...{ + return: [ + ...BasiFetchParam.return, + "blog", + "id", + { level: ["name"] }, + "video", + { play_tags: { tag: ["name"] } }, + ], + }, +}; diff --git a/src/common/services/string.js b/src/common/services/string.js index 52339f9b2..abcab5313 100644 --- a/src/common/services/string.js +++ b/src/common/services/string.js @@ -35,3 +35,17 @@ export const toTitleCaseTrimmed = (str) => { const titleCse = toTitleCase(str); return titleCse.replace(/\s/g, ""); }; + +export const toSlug = (str) => { + return toSanitized(str).toLowerCase(); +}; + +export const toSanitized = (str) => { + //replace all special characters | symbols with a space + str = str.replace(/[`~!@#$%^&*()_\-+=\[\]{};:'"\\|\/,.<>?\s]/g, " "); + // trim spaces at start and end of string + str = str.replace(/^\s+|\s+$/gm, ""); + // replace space with dash/hyphen + str = str.replace(/\s+/g, "-"); + return str; +};