Skip to content

Commit 6089e5d

Browse files
committed
feat: add support for copying poll data and visual representation in discussions
1 parent a78ebd6 commit 6089e5d

File tree

1 file changed

+80
-5
lines changed

1 file changed

+80
-5
lines changed

scripts/copy-discussions.js

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
// Note: This script copies discussion content, comments, replies, and basic metadata.
2121
// Reactions and other advanced interactions are not copied.
2222
// Attachments (images and files) will not copy over - they need manual handling.
23-
//
24-
// TODO: Polls don't copy options
23+
24+
// Configuration
25+
const INCLUDE_POLL_MERMAID_CHART = true; // Set to false to disable Mermaid pie chart for polls
2526

2627
const { Octokit } = require("octokit");
2728

@@ -89,6 +90,55 @@ async function rateLimitSleep(seconds = 2) {
8990
await sleep(seconds);
9091
}
9192

93+
function formatPollData(poll) {
94+
if (!poll || !poll.options || poll.options.nodes.length === 0) {
95+
return '';
96+
}
97+
98+
const options = poll.options.nodes;
99+
const totalVotes = poll.totalVoteCount || 0;
100+
101+
let pollMarkdown = '\n\n---\n\n### 📊 Poll Results (from source discussion)\n\n';
102+
pollMarkdown += `**${poll.question}**\n\n`;
103+
104+
// Create table
105+
pollMarkdown += '| Option | Votes | Percentage |\n';
106+
pollMarkdown += '|--------|-------|------------|\n';
107+
108+
options.forEach(option => {
109+
const votes = option.totalVoteCount || 0;
110+
const percentage = totalVotes > 0 ? ((votes / totalVotes) * 100).toFixed(1) : '0.0';
111+
pollMarkdown += `| ${option.option} | ${votes} | ${percentage}% |\n`;
112+
});
113+
114+
pollMarkdown += `\n**Total votes:** ${totalVotes}\n`;
115+
116+
// Add Mermaid pie chart if enabled
117+
if (INCLUDE_POLL_MERMAID_CHART && totalVotes > 0) {
118+
pollMarkdown += '\n<details>\n<summary><i>Visual representation</i></summary>\n\n';
119+
pollMarkdown += '```mermaid\n';
120+
pollMarkdown += '%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}}}%%\n';
121+
pollMarkdown += 'pie showData\n';
122+
pollMarkdown += ` title ${poll.question}\n`;
123+
124+
options.forEach(option => {
125+
const votes = option.totalVoteCount || 0;
126+
if (votes > 0) {
127+
// Escape quotes in option text for Mermaid
128+
const escapedOption = option.option.replace(/"/g, '\\"');
129+
pollMarkdown += ` "${escapedOption}" : ${votes}\n`;
130+
}
131+
});
132+
133+
pollMarkdown += '```\n\n';
134+
pollMarkdown += '</details>\n';
135+
}
136+
137+
pollMarkdown += '\n_Note: This is a static snapshot of poll results from the source discussion. Voting is not available in copied discussions._\n';
138+
139+
return pollMarkdown;
140+
}
141+
92142
// GraphQL Queries and Mutations
93143
const CHECK_DISCUSSIONS_ENABLED_QUERY = `
94144
query($owner: String!, $repo: String!) {
@@ -169,6 +219,16 @@ const FETCH_DISCUSSIONS_QUERY = `
169219
upvoteCount
170220
url
171221
number
222+
poll {
223+
question
224+
totalVoteCount
225+
options(first: 100) {
226+
nodes {
227+
option
228+
totalVoteCount
229+
}
230+
}
231+
}
172232
}
173233
}
174234
}
@@ -492,8 +552,17 @@ async function addLabelsToDiscussion(octokit, discussionId, labelIds) {
492552
}
493553
}
494554

495-
async function createDiscussion(octokit, repositoryId, categoryId, title, body, sourceUrl, sourceAuthor, sourceCreated) {
496-
const enhancedBody = `${body}\n\n---\n<details>\n<summary><i>Original discussion metadata</i></summary>\n\n_Original discussion by @${sourceAuthor} on ${sourceCreated}_\n_Source: ${sourceUrl}_\n</details>`;
555+
async function createDiscussion(octokit, repositoryId, categoryId, title, body, sourceUrl, sourceAuthor, sourceCreated, poll = null) {
556+
let enhancedBody = body;
557+
558+
// Add poll data if present
559+
if (poll) {
560+
const pollMarkdown = formatPollData(poll);
561+
enhancedBody += pollMarkdown;
562+
}
563+
564+
// Add metadata
565+
enhancedBody += `\n\n---\n<details>\n<summary><i>Original discussion metadata</i></summary>\n\n_Original discussion by @${sourceAuthor} on ${sourceCreated}_\n_Source: ${sourceUrl}_\n</details>`;
497566

498567
log(`Creating discussion: '${title}'`);
499568

@@ -730,12 +799,18 @@ async function processDiscussionsPage(sourceOctokit, targetOctokit, owner, repo,
730799
discussion.body || "",
731800
discussion.url,
732801
discussion.author?.login || "unknown",
733-
discussion.createdAt
802+
discussion.createdAt,
803+
discussion.poll || null
734804
);
735805

736806
createdDiscussions++;
737807
log(`✓ Created discussion #${discussion.number}: '${discussion.title}'`);
738808

809+
// Log poll info if present
810+
if (discussion.poll && discussion.poll.options?.nodes?.length > 0) {
811+
log(` ℹ️ Poll included with ${discussion.poll.options.nodes.length} options (${discussion.poll.totalVoteCount} total votes)`);
812+
}
813+
739814
// Process labels
740815
if (discussion.labels.nodes.length > 0) {
741816
const labelIds = [];

0 commit comments

Comments
 (0)