Skip to content

Commit

Permalink
fix: Transcript Page feedback (#70)
Browse files Browse the repository at this point in the history
* fix: issues with nested list showing dark gray

* fix(tagsDetailed): added a new compute field to have name and slug
  • Loading branch information
0tuedon authored and Emmanuel-Develops committed Jan 8, 2025
1 parent 354f3ca commit b53c648
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 76 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
/public/topics-by-category-counts.json
/public/aliases.json
/public/topics-counts.json
/public/topics.json
/public/speaker-data.json
/public/source-count-data.json
/public/sources-data.json
Expand Down
110 changes: 74 additions & 36 deletions contentlayer.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import path from "path";
import * as fs from "fs";
import { createSlug, SpeakerData, TopicsData, unsluggify } from "./src/utils";
import {
ContentData,
createSlug,
SpeakerData,
TopicsData,
unsluggify,
} from "./src/utils";
import {
defineDocumentType,
defineNestedType,
Expand Down Expand Up @@ -30,10 +36,10 @@ export interface Topic {

// The full processed topic we use internally
interface ProcessedTopic {
name: string; // Display name (from topic.title or original tag)
slug: string; // Slugified identifier
count: number; // Number of occurrences
categories: string[]; // List of categories it belongs to
name: string; // Display name (from topic.title or original tag)
slug: string; // Slugified identifier
count: number; // Number of occurrences
categories: string[]; // List of categories it belongs to
}

interface TagInfo {
Expand All @@ -46,7 +52,6 @@ interface ContentTree {
[key: string]: ContentTree | ContentTranscriptType[];
}


const getTranscriptAliases = (allTranscripts: ContentTranscriptType[]) => {
const aliases: Record<string, string> = {};

Expand All @@ -69,20 +74,24 @@ const getTopics = () => {
return JSON.parse(fileContents);
};

function buildTopicsMap(transcripts: ContentTranscriptType[], topics: Topic[]): Map<string, ProcessedTopic> {

function buildTopicsMap(
transcripts: ContentTranscriptType[],
topics: Topic[]
): Map<string, ProcessedTopic> {
// Create topics lookup map (includes aliases)
const topicsLookup = new Map<string, Topic>();
topics.forEach(topic => {
topics.forEach((topic) => {
topicsLookup.set(topic.slug, topic);
topic.aliases?.forEach(alias => topicsLookup.set(alias, topic));
topic.aliases?.forEach((alias) => topicsLookup.set(alias, topic));
});

// Build the main topics map
const processedTopics = new Map<string, ProcessedTopic>();

// Process all transcripts
transcripts.forEach(transcript => {
transcript.tags?.forEach(tag => {
transcripts.forEach((transcript) => {
transcript.tags?.forEach((tag) => {
const slug = createSlug(tag);
const topic = topicsLookup.get(slug);

Expand All @@ -99,11 +108,12 @@ function buildTopicsMap(transcripts: ContentTranscriptType[], topics: Topic[]):
}
});
});

return processedTopics;
}

function generateAlphabeticalList(processedTopics: Map<string, ProcessedTopic>): TopicsData[] {
function generateAlphabeticalList(
processedTopics: Map<string, ProcessedTopic>
): TopicsData[] {
const result: TopicsData[] = [];
// The categories property is not needed for this list, so we drop it
for (const { name, slug, count } of processedTopics.values()) {
Expand All @@ -112,30 +122,35 @@ function generateAlphabeticalList(processedTopics: Map<string, ProcessedTopic>):
return result.sort((a, b) => a.name.localeCompare(b.name));
}

function generateCategorizedList(processedTopics: Map<string, ProcessedTopic>): Record<string, TopicsData[]> {
function generateCategorizedList(
processedTopics: Map<string, ProcessedTopic>
): Record<string, TopicsData[]> {
const categorizedTopics: Record<string, TopicsData[]> = {};

Array.from(processedTopics.values()).forEach(({ name, slug, count, categories }) => {
categories.forEach(category => {
if (!categorizedTopics[category]) {
categorizedTopics[category] = [];
}

// Check if topic name contains category name and ends with "(Miscellaneous)"
const modifiedName = name.includes(category) && name.endsWith("(Miscellaneous)")
? "Miscellaneous"
: name;

categorizedTopics[category].push({ name: modifiedName, slug, count });
});
});
Array.from(processedTopics.values()).forEach(
({ name, slug, count, categories }) => {
categories.forEach((category) => {
if (!categorizedTopics[category]) {
categorizedTopics[category] = [];
}

// Check if topic name contains category name and ends with "(Miscellaneous)"
const modifiedName =
name.includes(category) && name.endsWith("(Miscellaneous)")
? "Miscellaneous"
: name;

categorizedTopics[category].push({ name: modifiedName, slug, count });
});
}
);

// Sort topics within each category
Object.values(categorizedTopics).forEach(topics => {
Object.values(categorizedTopics).forEach((topics) => {
topics.sort((a, b) => {
if (a.name == "Miscellaneous") return 1;
if (b.name == "Miscellaneous") return -1;
return a.name.localeCompare(b.name)
return a.name.localeCompare(b.name);
});
});

Expand Down Expand Up @@ -331,7 +346,7 @@ function organizeContent(
fs.writeFileSync("./public/sources-data.json", JSON.stringify(tree, null, 2));
}

const getLanCode = /[.]\w{2}$/gi // Removes the last two characters if there's a dot
const getLanCode = /[.]\w{2}$/gi; // Removes the last two characters if there's a dot

export const Transcript = defineDocumentType(() => ({
name: "Transcript",
Expand Down Expand Up @@ -363,6 +378,32 @@ export const Transcript = defineDocumentType(() => ({
source_file: { type: "string" },
},
computedFields: {
tagsDetailed: {
type: "list",
resolve: (doc) => {
// doc?.tags doesn't give an array in contentLayer so we do _array to get it
const topicsStore = doc?.tags as any || [];
const topics = (topicsStore?._array as string[]) ?? [];

const topicsWithTitles = topics.map((topic) => {
const currentTopic = getTopics().find(
(topicData: ContentData) => topicData.slug === topic
);

if(currentTopic?.title && currentTopic?.title.includes("(Miscellaneous)")) {
return {
name: currentTopic?.title.replace("(Miscellaneous)",""),
slug: currentTopic.slug,
}
}
return {
name: currentTopic?.title || topic,
slug: currentTopic?.slug || topic,
};
});
return topicsWithTitles;
},
},
url: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
Expand All @@ -389,7 +430,7 @@ export const Transcript = defineDocumentType(() => ({
);

const lan = transcript?.match(getLanCode);
const languageCode = (lan?.[0] || "").replace(".", "")
const languageCode = (lan?.[0] || "").replace(".", "");

if (LanguageCodes.includes(languageCode)) {
return `/${languageCode}/${fullPathWithoutDot}`;
Expand All @@ -401,10 +442,7 @@ export const Transcript = defineDocumentType(() => ({
slugAsParams: {
type: "list",
resolve: (doc) => {
const pathWithoutDot = doc._raw.flattenedPath.replace(
getLanCode,
""
);
const pathWithoutDot = doc._raw.flattenedPath.replace(getLanCode, "");
return pathWithoutDot.split("/");
},
},
Expand Down
19 changes: 9 additions & 10 deletions src/components/common/TranscriptDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import Image from "next/image";
import { ContentTreeArray } from "@/utils/data";
import DateIcon from "/public/svgs/date-icon.svg";
import TagsIcon from "/public/svgs/tags-icon.svg";
import { createSlug, formatDate, unsluggify } from "@/utils";
import { ContentData, createSlug, formatDate, unsluggify } from "@/utils";
import { MicIcon } from "@bitcoin-dev-project/bdp-ui/icons";
import Pill from "./Pill";

const TranscriptDetailsCard = ({ data, slug }: { data: ContentTreeArray; slug: string[] }) => {
const { speakers, tags, summary, date, title, body, languageURL } = data;

const calculateRemaining = (data: string[]) => (data?.length && data.length > 3 ? data.length - 3 : 0);
const TranscriptDetailsCard = ({ data }: { data: ContentTreeArray; slug: string[] }) => {
const { speakers, tagsDetailed, summary, date, title, body, languageURL } = data;
const calculateRemaining = (data: ContentData[] | string[]) => (data?.length && data.length > 3 ? data.length - 3 : 0);

return (
<div className='border border-gray-custom-1200 rounded-lg p-4 md:p-5 2xl:p-6 flex flex-col gap-3 md:gap-4'>
Expand Down Expand Up @@ -57,20 +56,20 @@ const TranscriptDetailsCard = ({ data, slug }: { data: ContentTreeArray; slug: s
) : null}

<section className='flex gap-2 items-center max-md:gap-1'>
{tags?.length ? (
{tagsDetailed?.length ? (
<>
<span>
<Image src={TagsIcon} alt='date icon' className='w-5 md:w-6' />
</span>
<div className='flex gap-[9px] flex-wrap'>
<div className='flex flex-wrap gap-[9px] max-md:gap-2'>
{tags.slice(0, 3).map((tag, idx) => (
<Pill key={idx} name={tag} slug={`/tags/${createSlug(tag)}`} />
{tagsDetailed.slice(0, 3).map((tag, idx) => (
<Pill key={idx} name={tag.name} slug={`/tags/${tag.slug}`} />
))}

{calculateRemaining(tags) === 0 ? null : (
{calculateRemaining(tagsDetailed) === 0 ? null : (
<p className='py-[2px] px-5 rounded-[5px] bg-gray-custom-700 whitespace-nowrap text-nowrap max-md:px-3 lg:py-1 max-2xl:text-sm max-md:text-sm max-md:border max-md:border-gray-custom-300 max-md:leading-[100%]'>
+ {calculateRemaining(tags)} more
+ {calculateRemaining(tagsDetailed)} more
</p>
)}
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/components/common/TranscriptMetadataCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
MicIcon,
} from "@bitcoin-dev-project/bdp-ui/icons";
import Link from "next/link";
import { createSlug } from "@/utils";
import { ContentData, createSlug } from "@/utils";
import AiGeneratedIcon from "../svgs/AIGeneratedIcon";
import { format, isDate } from "date-fns";
import Pill from "./Pill";

interface ITranscriptMetadataComponent {
title: string;
date: string | Date;
topics: string[];
topics: ContentData[];
speakers: string[] | null;
transcriptBy: string | string[];
}
Expand All @@ -38,6 +38,7 @@ const TranscriptMetadataComponent = ({

const formattedDate = isDate(convertedDate) ? format(convertedDate, "d MMMM, yyyy") : "";


return (
<div className="border flex text-black flex-col rounded-2xl p-4 md:p-5 2xl:p-6 gap-4 w-full border-gray-custom-1200">
<div className="flex flex-col md:flex-row flex-wrap gap-4 justify-between ">
Expand Down Expand Up @@ -108,7 +109,7 @@ const TranscriptMetadataComponent = ({
<div className="flex flex-wrap gap-2">
{(topics && topics.length > 0) ?
topics.map((topic) => (
<Pill key={topic} name={topic} slug={`/tags/${createSlug(topic)}`} />
<Pill key={topic.slug} name={topic.name} slug={`/tags/${topic.slug}`} />
)):
<p className="pl-2.5 pt-1.5 text-xs md:text-sm lg:text-sm 2xl:text-base md:font-medium">Not available</p>
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/explore/TranscriptContentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const TranscriptContentPage: FC<ITranscriptContentPage> = ({
</div>
</div>

<div className="flex-col flex gap-10 pb-[calc(90vh-var(--header-height))]">
<div className="flex-col flex gap-10 pb-10">
{groupedData &&
type === "alphabet" &&
Object.entries(groupedData).map((arg, i) => (
Expand Down
4 changes: 2 additions & 2 deletions src/components/individual-transcript/IndividualTranscript.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ const IndividualTranscript = ({
<TranscriptMetadataComponent
title={transcript.title}
date={transcript.date || ""}
topics={transcript.tags || []}
topics={transcript.tagsDetailed || []}
speakers={transcript.speakers || []}
transcriptBy={transcript.transcript_by || ""}
/>
</div>

<div>
<div className="pt-4 md:pt-5 2xl:pt-6 pb-[var(--header-height)] xl:pb-[calc(60vh-var(--header-height))]">
<div className="pt-4 md:pt-5 2xl:pt-6 pb-10">
<Tabs
markdown={transcript.body.raw}
summary={transcript?.summary}
Expand Down
35 changes: 14 additions & 21 deletions src/components/individual-transcript/markdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,34 @@ span.code-line {
}

.wmde-markdown p {

margin-bottom: 8px;
color: #000;
font-size: 0.875rem;
font-weight: 400;
line-height: 2.1875rem;
}

.wmde-markdown ul li {
list-style-type: circle;
color: #000;
}

.wmde-markdown ul {
padding-left: 1em;
}

.wmde-markdown ol {
margin: 0px !important;
font-weight: 400;
}

.wmde-markdown a.anchor {
display: none !important;
}

@media (min-width: 1024px) {

.wmde-markdown h1, .wmde-markdown h2 {
/* margin: 0px !important; */
scroll-margin-top: 100px;
color: #000;
padding-top: 10px;
padding-bottom: 10px;
margin: 12px 0px !important;
Expand All @@ -63,26 +73,16 @@ span.code-line {
}

.wmde-markdown p {
margin: 0px !important;
color: #000;
font-weight: 400;
font-size: 1rem;
line-height: 2.1875rem;
}
.wmde-markdown ul,.wmde-markdown ol {
margin: 0px !important;
color: #000;
font-weight: 400;
font-size: 1rem;
line-height: 2.1875rem;
}
.wmde-markdown ul, .wmde-markdown li {
list-style-type: circle;
}

.wmde-markdown a.anchor {
display: none !important;
}
}

@media (min-width: 1536px) {
Expand All @@ -93,17 +93,10 @@ span.code-line {
}

.wmde-markdown h3,.wmde-markdown h4, .wmde-markdown h5, .wmde-markdown h6 {
color: #000;
font-size: 1rem;
}

.wmde-markdown p {
margin: 0px !important;
color: #000;
line-height: 2rem;
}

.wmde-markdown a.anchor {
display: none !important;
}
}
Loading

0 comments on commit b53c648

Please sign in to comment.