Skip to content

Commit

Permalink
✨ Create vote result pages and svg
Browse files Browse the repository at this point in the history
  • Loading branch information
ebullient committed Mar 8, 2024
1 parent cfea2be commit 0a77a52
Show file tree
Hide file tree
Showing 17 changed files with 958 additions and 155 deletions.
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ indent_style = space
indent_size = 2
trim_trailing_whitespace = false

[*.java]
[*.{java,ts,js}]
indent_size = 4

[*.{yml,yaml,html,js,rb,css,xml,scss,vto}]
[*.{yml,yaml,html,rb,css,xml,scss,vto}]
indent_size = 2
279 changes: 164 additions & 115 deletions .github/activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,86 +2,124 @@ import { ensureDirSync } from "https://deno.land/std@0.114.0/fs/mod.ts";
import { join } from "https://deno.land/std@0.114.0/path/mod.ts";
import { safeLoad, safeDump } from "https://deno.land/x/js_yaml_port@3.14.0/js-yaml.js";

interface Problem {
path: string[];
explanation: string;
}
interface Error {
message: string;
extensions?: {
"value": string;
"problems": Problem[];
},
locations?: {
line: number;
column: number;
}[];
}
interface Label {
name: string;
name: string;
}
interface Author {
login: string;
url: string;
avatarUrl: string;
login: string;
url: string;
avatarUrl: string;
}
interface ItemWithAuthor {
id: string;
title: string;
number: number;
author: Author;
labels: {
nodes: Label[];
};
url: string;
body: string;
createdAt: string;
updatedAt: string;
closed: boolean;
closedAt: string;
locked: boolean;
activeLockReason: string;
category?: {
name: string;
};
isAnswered?: boolean;
answerChosenAt?: string;
id: string;
title: string;
number: number;
author: Author;
labels: {
nodes: Label[];
};
url: string;
body: string;
createdAt: string;
updatedAt: string;
closed: boolean;
closedAt: string;
locked: boolean;
activeLockReason: string;
category?: {
name: string;
};
isAnswered?: boolean;
answerChosenAt?: string;
}
interface DiscussionsData {
data: {
repository: {
discussions: {
nodes: ItemWithAuthor[];
};
errors?: Error[];
data: {
repository: {
discussions: {
nodes: ItemWithAuthor[];
};
};
};
};
}
interface PullRequestData {
data: {
repository: {
pullRequests: {
nodes: ItemWithAuthor[];
};
errors?: Error[];
data: {
repository: {
pullRequests: {
nodes: ItemWithAuthor[];
};
};
};
};
}
interface PinnedItem {
discussion: {
id: string;
};
discussion: {
id: string;
};
}
interface PinnedItemData {
data: {
repository: {
pinnedDiscussions: {
nodes: PinnedItem[];
};
errors?: Error[];
data: {
repository: {
pinnedDiscussions: {
nodes: PinnedItem[];
};
};
};
};
}

const prefixMap: Record<string, string> = {
announcements: '[📣 ]',
reviews: '[🗳️ ]',
announcements: '[📣 ]',
reviews: '[🗳️ ]',
};

const pins: PinnedItemData = JSON.parse(Deno.readTextFileSync('./site/activity/activity-pinned.json'));
const pinnedIds = pins.data.repository.pinnedDiscussions.nodes
.map((node) => node.discussion.id);
// Get last commit date for a file
function runGraphQL(filePath: string): string {
const command = new Deno.Command('gh', {
args: [
'api', 'graphql',
'-F', "owner=commonhaus",
'-F', "name=foundation-draft",
'-F', `query=@${filePath}`,
]
});

const { code, stdout, stderr } = command.outputSync();
const output = new TextDecoder().decode(stdout).trim();
console.log(code, filePath, new TextDecoder().decode(stderr));
console.assert(code === 0);
return output;
}

const pins: PinnedItemData = JSON.parse(runGraphQL('.github/graphql/query.pinned.graphql'));
if (pins.errors || !pins.data) {
console.error(pins);
Deno.exit(1);
}

const pinnedIds = pins.data.repository.pinnedDiscussions.nodes.map((node) => node.discussion.id);

function generateContent(item: ItemWithAuthor, id: string, type: string): string {
const title = item.title.replace(/"/g, '\\"')
const prefix = item.category
? prefixMap[item.category.name.toLowerCase()]
: '';
let status = '';
let data = `---
const title = item.title.replace(/"/g, '\\"')
const prefix = item.category
? prefixMap[item.category.name.toLowerCase()]
: '';
let data = `---
title: "${title}"
rss-title: "${prefix}${title}"
github: "${item.url}"
Expand All @@ -93,83 +131,94 @@ url: "/activity/${id}.html"
type: ${type}
tags:
- post`;
if (item.category) {
data += `\n- ${item.category.name.toLowerCase()}`;
}
if (item.closed) {
data += `\nclosedAt: ${item.closedAt}`
}
if (item.locked) {
data += `\nlockReason: "${item.activeLockReason}"`
}
if (item.isAnswered) {
data += `\nansweredAt: ${item.answerChosenAt}`;
}
if (pinnedIds.includes(item.id)) {
data += `\npinned: true`;
}
data += `\n---\n${item.body}\n`;
// console.log(data);
return data;
if (item.category) {
data += `\n- ${item.category.name.toLowerCase()}`;
}
if (item.closed) {
data += `\nclosedAt: ${item.closedAt}`
}
if (item.locked) {
data += `\nlockReason: "${item.activeLockReason}"`
}
if (item.isAnswered) {
data += `\nansweredAt: ${item.answerChosenAt}`;
}
if (pinnedIds.includes(item.id)) {
data += `\npinned: true`;
}
data += `\n---\n${item.body}\n`;
// console.log(data);
return data;
}

function writeItemsToFiles(items: ItemWithAuthor[], outputDir: string, type: string): void {
ensureDirSync(outputDir);
for (const item of items) {
const id = item.number.toString();
// const slug = id + slugifyTitle(discussion.title);
const content = generateContent(item, id, type);
const filePath = join(outputDir, `${id}.md`);
Deno.writeTextFileSync(filePath, content);
}
ensureDirSync(outputDir);
for (const item of items) {
const id = item.number.toString();
const content = generateContent(item, id, type);
const filePath = join(outputDir, `${id}.md`);
Deno.writeTextFileSync(filePath, content);
}
}

function updateAuthors(items: ItemWithAuthor[]): void {
const authorsPath = './site/_data/authors.yml';
const authorsYaml = Deno.readTextFileSync(authorsPath);
const authors = safeLoad(authorsYaml) || {};
for (const item of items) {
const author = item.author;
if (!authors[author.login]) {
authors[author.login] = {
login: author.login,
url: author.url,
avatar: author.avatarUrl,
};
const authorsPath = './site/_data/authors.yml';
const authorsYaml = Deno.readTextFileSync(authorsPath);
const authors = safeLoad(authorsYaml) || {};
for (const item of items) {
const author = item.author;
if (!authors[author.login]) {
authors[author.login] = {
login: author.login,
url: author.url,
avatar: author.avatarUrl,
};
}
}
}
Deno.writeTextFileSync(authorsPath, safeDump(authors));
Deno.writeTextFileSync(authorsPath, safeDump(authors));
}

function updateDiscussions(data: DiscussionsData) {
// Filter discussions by category (Announcements) or label (Notice),
const discussions = data.data.repository.discussions.nodes
.filter((discussion: ItemWithAuthor) =>
(discussion.category && prefixMap[discussion.category.name.toLowerCase()])
|| discussion.labels.nodes.some((label: Label) => label.name.toLowerCase() === 'notice')
);
writeItemsToFiles(discussions, `./site/activity`, "discussion");
// Update authors.yml (add/update author of last 10 discussions)
updateAuthors(discussions);
// Filter discussions by category (Announcements) or label (Notice),
const discussions = data.data.repository.discussions.nodes
.filter((discussion: ItemWithAuthor) =>
(discussion.category && prefixMap[discussion.category.name.toLowerCase()])
|| discussion.labels.nodes.some((label: Label) => label.name.toLowerCase() === 'notice')
);

writeItemsToFiles(discussions, `./site/activity`, "discussion");

// Update authors.yml (add/update author of last 10 discussions)
updateAuthors(discussions);
}

function updatePullRequests(data: PullRequestData) {
// Filter discussions by label (Notice),
const prs = data.data.repository.pullRequests.nodes
.filter((pr: ItemWithAuthor) =>
pr.labels.nodes.some((label: Label) => label.name.toLowerCase() === 'notice')
);
prs.forEach((pr: ItemWithAuthor) => pr.category = { name: 'reviews' });
writeItemsToFiles(prs, `./site/activity`, "pullRequest");
// Update authors.yml (add/update author of last 10 discussions)
updateAuthors(prs);
// Filter discussions by label (Notice),
const prs = data.data.repository.pullRequests.nodes
.filter((pr: ItemWithAuthor) =>
pr.labels.nodes.some((label: Label) => label.name.toLowerCase() === 'notice')
);

prs.forEach((pr: ItemWithAuthor) => pr.category = { name: 'reviews' });
writeItemsToFiles(prs, `./site/activity`, "pullRequest");

// Update authors.yml (add/update author of last 10 discussions)
updateAuthors(prs);
}

// Usage:
// First, use a deno task to download the last 10 discussions from GitHub > discussions.json
// Parse the discussions.json file
const discuss: DiscussionsData = JSON.parse(Deno.readTextFileSync('./site/activity/activity-discussions.json'));
const discuss: DiscussionsData = JSON.parse(runGraphQL('.github/graphql/query.discussions.graphql'));
if (discuss.errors || !discuss.data) {
console.error(discuss);
Deno.exit(1);
}
updateDiscussions(discuss);

const prs: PullRequestData = JSON.parse(Deno.readTextFileSync('./site/activity/activity-prs.json'));
const prs: PullRequestData = JSON.parse(runGraphQL('.github/graphql/query.pullrequests.graphql'));
if (prs.errors || !prs.data) {
console.error(prs);
Deno.exit(1);
}
updatePullRequests(prs);
51 changes: 51 additions & 0 deletions .github/graphql/query.comment.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
query($commentId: ID!) {
node(id: $commentId) {
... on IssueComment {
issue {
id
closed
closedAt
number
labels(first: 10) {
nodes {
name
}
}
repository {
nameWithOwner
}
title
url
}
body
createdAt
id
updatedAt
url
}
... on DiscussionComment {
id
discussion {
id
closed
closedAt
number
labels(first: 10) {
nodes {
name
}
}
repository {
nameWithOwner
}
title
url
}
body
createdAt
id
updatedAt
url
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 0a77a52

Please sign in to comment.