diff --git a/components/ArchiveSummaries.tsx b/components/ArchiveSummaries.tsx
index a53c0c3..f9b97b9 100644
--- a/components/ArchiveSummaries.tsx
+++ b/components/ArchiveSummaries.tsx
@@ -22,6 +22,7 @@ const ArchiveSummaries = () => {
useEffect(() => {
setRenderedMarkdown(formData.meetingSummary);
+ console.log(formData.meetingSummary)
}, [formData.meetingSummary]);
useEffect(() => {
diff --git a/components/SummaryAgendaItems.tsx b/components/SummaryAgendaItems.tsx
index 8cdafd0..15cc76f 100644
--- a/components/SummaryAgendaItems.tsx
+++ b/components/SummaryAgendaItems.tsx
@@ -250,7 +250,7 @@ const getHeading = (itemType: any, workgroup: any) => {
isEnabled: (template: any) => template?.townHallSummary === 1,
render: (item: any, agendaIndex: any) => (
<>
-
Town Hall Summary
+ Town Hall Summary (Optional)
- = ({ workgroup, onUp
transcriptLink = '',
mediaLink = '',
workingDocs = [{ title: '', link: '' }],
- timestampedVideo = { url: '', intro: '', timestamps: [{ title: '', timestamp: '' }] }
+ timestampedVideo = { url: '', intro: '', timestamps: '' }
} = myVariable?.summary?.meetingInfo || {};
// Set the local meetingInfo state with the values from myVariable.summary.meetingInfo
@@ -354,7 +354,7 @@ const SummaryMeetingInfo: React.FC = ({ workgroup, onUp
)}
{myVariable.workgroup?.preferred_template?.meetingInfo?.googleSlides == 1 && (<>
{
const currentOrder = myVariable.agendaItemOrder ? myVariable.agendaItemOrder[myVariable.workgroup?.workgroup] : undefined;
async function generatePdf(markdown: any) {
+ const embedRegex = /\{% embed url="([^"]+)" %\}/g;
+ const updatedMarkdown = markdown.replace(embedRegex, (match, url) => {
+ // Check if the URL is a YouTube video
+ if (url.includes("youtube.com") || url.includes("youtu.be")) {
+ return `[Watch Video](${url})`; // Replace with a descriptive text for videos
+ } else if (url.includes("google.slides.com") || url.includes("docs.google.com/presentation")) {
+ return `[View Slides](${url})`; // Replace with a descriptive text for slides
+ } else {
+ return `[Link](${url})`; // A generic replacement for other URLs
+ }
+ });
+ markdown = updatedMarkdown;
try {
//console.log(formData.meetingInfo?.date, myVariable.summary?.date)
const additionalLines = `# Meeting Summary for ${myVariable.workgroup?.workgroup}\n` +
diff --git a/components/TimestampedVideo.tsx b/components/TimestampedVideo.tsx
index e81c6f0..4464f8e 100644
--- a/components/TimestampedVideo.tsx
+++ b/components/TimestampedVideo.tsx
@@ -2,48 +2,26 @@ import { useState, useEffect } from 'react';
import styles from '../styles/timestampedVideo.module.css';
type TimestampedVideoProps = {
- onUpdate: (videoData: any) => void;
- initialData?: {
- url: string;
- intro: string;
- timestamps: { title: string; timestamp: string }[];
- };
+ onUpdate: (videoData: any) => void;
+ initialData?: {
+ url: string;
+ intro: string;
+ timestamps: string;
};
-
+};
const TimestampedVideo: React.FC = ({ onUpdate, initialData }) => {
const [videoData, setVideoData] = useState({
url: initialData?.url || '',
intro: initialData?.intro || '',
- timestamps: initialData?.timestamps || [{ title: '', timestamp: '' }],
+ timestamps: initialData?.timestamps || '',
});
- const handleChange = (e: React.ChangeEvent, index: number | null) => {
+ const handleChange = (e: React.ChangeEvent) => {
const { name, value } = e.target;
- if (index !== null) {
- // Handle change for timestamps
- const updatedTimestamps = [...videoData.timestamps];
- updatedTimestamps[index] = { ...updatedTimestamps[index], [name]: value };
- setVideoData({ ...videoData, timestamps: updatedTimestamps });
- } else {
- // Handle change for URL and Intro
- setVideoData({ ...videoData, [name]: value });
- }
- };
-
- const addTimestamp = () => {
- setVideoData({
- ...videoData,
- timestamps: [...videoData.timestamps, { title: '', timestamp: '' }],
- });
+ setVideoData({ ...videoData, [name]: value });
};
- const removeTimestamp = (index: number) => {
- const filteredTimestamps = videoData.timestamps.filter((_, i) => i !== index);
- setVideoData({ ...videoData, timestamps: filteredTimestamps });
- };
-
- // useEffect hook to call onUpdate whenever videoData changes
useEffect(() => {
onUpdate(videoData); // Call onUpdate with the current state of videoData
}, [videoData, onUpdate]); // Add videoData and onUpdate to the dependency array
@@ -57,45 +35,28 @@ const TimestampedVideo: React.FC = ({ onUpdate, initialDa
type="text"
name="url"
value={videoData.url}
- onChange={(e) => handleChange(e, null)}
+ onChange={handleChange}
+ />
+
+
+
+
-
-
+
+
-
- {videoData.timestamps.map((item, index) => (
-
- handleChange(e, index)}
- />
- handleChange(e, index)}
- pattern="(?:\d{1,2}:)?[0-5]?\d:[0-5]\d|\d{1,2}"
- title="Timestamp format: ss or mm:ss or hh:mm:ss"
- />
-
-
- ))}
-
+
);
};
diff --git a/pages/submit-meeting-summary/index.tsx b/pages/submit-meeting-summary/index.tsx
index af9b8da..9549b31 100644
--- a/pages/submit-meeting-summary/index.tsx
+++ b/pages/submit-meeting-summary/index.tsx
@@ -268,9 +268,10 @@ useEffect(() => {
title="Defaults to latest meeting, only change this when you want to use a previous meeting as template">
{meetings.map((meeting: any) => (
))}
diff --git a/utils/generateMarkdown.js b/utils/generateMarkdown.js
index 1c1742e..10d1da2 100644
--- a/utils/generateMarkdown.js
+++ b/utils/generateMarkdown.js
@@ -20,6 +20,13 @@
* - Rich markdown formatting for clear and readable output.
*/
+function capitalize(text) {
+ return text
+ .split(' ')
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
+ .join(' ');
+}
+
export function generateMarkdown(summary, order) {
let markdown = "";
@@ -42,11 +49,11 @@ export function generateMarkdown(summary, order) {
}
if (purpose) markdown += `- Purpose: ${purpose}\n`;
if (townHallNumber) markdown += `- Town Hall Number: ${townHallNumber}\n`; //townHallNumber
- if (meetingVideoLink) markdown += `- Meeting video: ${meetingVideoLink}\n`;
- if (mediaLink) markdown += `- Media link: ${mediaLink}\n`;
- if (miroBoardLink) markdown += `- Miro board: ${miroBoardLink}\n`;
- if (transcriptLink) markdown += `- Transcript: ${transcriptLink}\n`;
- if (otherMediaLink) markdown += `- Other media: ${otherMediaLink}\n`;
+ if (meetingVideoLink) markdown += `- Meeting video: [Link](${meetingVideoLink})\n`;
+ if (mediaLink) markdown += `- Media link: [Link](${mediaLink})\n`;
+ if (miroBoardLink) markdown += `- Miro board: [Link](${miroBoardLink})\n`;
+ if (transcriptLink) markdown += `- Transcript: [Link](${transcriptLink})\n`;
+ if (otherMediaLink) markdown += `- Other media: [Link](${otherMediaLink})\n`;
//markdown += '\n';
// Process workingDocs
@@ -60,37 +67,32 @@ export function generateMarkdown(summary, order) {
markdown += `\n`
}
- if (timestampedVideo && Array.isArray(timestampedVideo.timestamps) && timestampedVideo.timestamps.length > 0) {
- const { url, intro, timestamps } = timestampedVideo;
+ // Process timestampedVideo if it's a string
+ if (timestampedVideo && typeof timestampedVideo.timestamps === 'string') {
+ const { url, intro } = timestampedVideo;
markdown += `\n#### Timestamped video:\n`;
- // Embed video URL
- markdown += `{% embed url="${url}" %}\n\n`;
-
- // Add intro text
- if (intro) {
- markdown += `${intro}\n\n`;
- }
-
- // Add timestamps
- timestamps.forEach(({ title, timestamp }) => {
- // Split timestamp and reverse to process seconds, minutes, and optionally hours
- const parts = timestamp.split(':').reverse().map(t => parseInt(t, 10));
- let totalSeconds = 0;
-
- // Calculate total seconds based on the presence of hours, minutes, and seconds
- if (parts.length === 3) { // hh:mm:ss format
- totalSeconds = parts[0] + parts[1] * 60 + parts[2] * 3600;
- } else if (parts.length === 2) { // mm:ss format
- totalSeconds = parts[0] + parts[1] * 60;
- } else if (parts.length === 1) { // ss format
- totalSeconds = parts[0];
+ if (url) markdown += `{% embed url="${url}" %}\n\n`;
+ if (intro) markdown += `${intro}\n\n`;
+
+ // Parse the timestamps string and convert each to a link
+ const lines = timestampedVideo.timestamps.split('\n');
+ lines.forEach(line => {
+ const [time, title] = line.split(/(?<=^\S+)\s/); // Splits at the first space after a non-whitespace sequence
+ if (time && title) {
+ const parts = time.split(':').map(t => parseInt(t, 10));
+ let totalSeconds = 0;
+ if (parts.length === 3) {
+ totalSeconds = parts[2] + parts[1] * 60 + parts[0] * 3600;
+ } else if (parts.length === 2) {
+ totalSeconds = parts[1] + parts[0] * 60;
+ } else if (parts.length === 1) {
+ totalSeconds = parts[0];
+ }
+ markdown += `[${time}](${url}\\&t=${totalSeconds}s) ${capitalize(title)}\n`;
}
-
- markdown += `[${timestamp}](${url}\\&t=${totalSeconds}s) ${title}\n`;
});
-
markdown += `\n`;
- }
+ }
if (googleSlides) {
markdown += `\n#### Slides:\n`;
diff --git a/utils/sendDiscordMessage.js b/utils/sendDiscordMessage.js
index 9804eb4..ae929d5 100644
--- a/utils/sendDiscordMessage.js
+++ b/utils/sendDiscordMessage.js
@@ -154,10 +154,13 @@ export async function sendDiscordMessage(myVariable, markdown) {
const workgroup = myVariable.summary.workgroup;
const username = myVariable.summary.meetingInfo.documenter;
const archivist = myVariable.currentUser;
- const date = myVariable.summary.meetingInfo.date;
-
+ const dateObj = new Date(myVariable.summary.meetingInfo.date);
+ // Format the date to "24 January 2024" format
+ const formattedDate = dateObj.toLocaleDateString('en-GB', {
+ day: 'numeric', month: 'long', year: 'numeric'
+ });
// Use the new function to create embeds
- const title = `${workgroup} -> ${date} meeting summary`;
+ const title = `${workgroup} -> ${formattedDate} meeting summary`;
const footerText = `Summary created by ${username} and archived by ${archivist}`;
const embeds = createDiscordEmbeds(markdown, title, footerText);