diff --git a/monkestation/code/datums/changelog/changelog.dm b/monkestation/code/datums/changelog/changelog.dm new file mode 100644 index 000000000000..8c4d2cfe0ae7 --- /dev/null +++ b/monkestation/code/datums/changelog/changelog.dm @@ -0,0 +1,40 @@ +/datum/changelog/ui_static_data() + . = ..() + for(var/datum/tgs_revision_information/test_merge/testmerge in world.TgsTestMerges()) + if(!testmerge.body || findtext(testmerge.title, @"[s]")) + continue + var/list/changes = parse_github_changelog(testmerge.body) + if(!length(changes)) + changes = list("unknown" = list("Changes are not documented. Ask the author ([testmerge.author]) to add a changelog to their PR!")) + var/list/testmerge_data = list( + "title" = "[testmerge.title]", + "number" = testmerge.number, + "author" = testmerge.author, + "link" = testmerge.url, + "changes" = changes, + ) + LAZYADD(.["testmerges"], list(testmerge_data)) + +/proc/parse_github_changelog(body) as /list + var/static/regex/cl_pattern = new(@"(:cl:|🆑)([\S \t]*)$") + var/static/regex/entry_pattern = new(@"(\w+): (.+)") + var/static/regex/end_pattern = new(@"^/(:cl:|🆑)") + var/static/regex/newline_pattern = new(@"(\r\n|\r|\n)") + + var/started = FALSE + var/list/lines = splittext_char(trimtext(body), newline_pattern) + + for (var/line in lines) + line = trimtext(line) + if(findtext_char(line, end_pattern)) + break + if(started) + if (findtext_char(line, entry_pattern)) + var/change_type = trimtext(entry_pattern.group[1]) + var/change_desc = trimtext(entry_pattern.group[2]) + if(!change_type || !change_desc) + continue + LAZYADDASSOCLIST(., change_type, change_desc) + else + if(findtext_char(line, cl_pattern)) + started = TRUE diff --git a/tgstation.dme b/tgstation.dme index e0e8ae09a567..7e749e93cd6e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5715,6 +5715,7 @@ #include "monkestation\code\datums\announcers\duke.dm" #include "monkestation\code\datums\brain_damage\magic.dm" #include "monkestation\code\datums\brain_damage\phobia.dm" +#include "monkestation\code\datums\changelog\changelog.dm" #include "monkestation\code\datums\components\carbon_sprint.dm" #include "monkestation\code\datums\components\crafting.dm" #include "monkestation\code\datums\components\irradiated.dm" diff --git a/tgui/packages/tgui/interfaces/Changelog.js b/tgui/packages/tgui/interfaces/Changelog.js deleted file mode 100644 index 9ee1a7b49719..000000000000 --- a/tgui/packages/tgui/interfaces/Changelog.js +++ /dev/null @@ -1,346 +0,0 @@ -import { classes } from 'common/react'; -import { useBackend } from '../backend'; -import { Component, Fragment } from 'inferno'; -import { Box, Button, Dropdown, Icon, Section, Stack, Table } from '../components'; -import { Window } from '../layouts'; -import { resolveAsset } from '../assets'; -import dateformat from 'dateformat'; -import yaml from 'js-yaml'; - -const icons = { - bugfix: { icon: 'bug', color: 'green' }, - wip: { icon: 'hammer', color: 'orange' }, - qol: { icon: 'hand-holding-heart', color: 'green' }, - soundadd: { icon: 'tg-sound-plus', color: 'green' }, - sounddel: { icon: 'tg-sound-minus', color: 'red' }, - add: { icon: 'check-circle', color: 'green' }, - expansion: { icon: 'check-circle', color: 'green' }, - rscadd: { icon: 'check-circle', color: 'green' }, - rscdel: { icon: 'times-circle', color: 'red' }, - imageadd: { icon: 'tg-image-plus', color: 'green' }, - imagedel: { icon: 'tg-image-minus', color: 'red' }, - spellcheck: { icon: 'spell-check', color: 'green' }, - experiment: { icon: 'radiation', color: 'yellow' }, - balance: { icon: 'balance-scale-right', color: 'yellow' }, - code_imp: { icon: 'code', color: 'green' }, - refactor: { icon: 'tools', color: 'green' }, - config: { icon: 'cogs', color: 'purple' }, - admin: { icon: 'user-shield', color: 'purple' }, - server: { icon: 'server', color: 'purple' }, - tgs: { icon: 'toolbox', color: 'purple' }, - tweak: { icon: 'wrench', color: 'green' }, - unknown: { icon: 'info-circle', color: 'label' }, -}; - -export class Changelog extends Component { - constructor() { - super(); - this.state = { - data: 'Loading changelog data...', - selectedDate: '', - selectedIndex: 0, - }; - this.dateChoices = []; - } - - setData(data) { - this.setState({ data }); - } - - setSelectedDate(selectedDate) { - this.setState({ selectedDate }); - } - - setSelectedIndex(selectedIndex) { - this.setState({ selectedIndex }); - } - - getData = (date, attemptNumber = 1) => { - const { act } = useBackend(this.context); - const self = this; - const maxAttempts = 6; - - if (attemptNumber > maxAttempts) { - return this.setData( - 'Failed to load data after ' + maxAttempts + ' attempts' - ); - } - - act('get_month', { date }); - - fetch(resolveAsset(date + '.yml')).then(async (changelogData) => { - const result = await changelogData.text(); - const errorRegex = /^Cannot find/; - - if (errorRegex.test(result)) { - const timeout = 50 + attemptNumber * 50; - - self.setData('Loading changelog data' + '.'.repeat(attemptNumber + 3)); - setTimeout(() => { - self.getData(date, attemptNumber + 1); - }, timeout); - } else { - self.setData(yaml.load(result, { schema: yaml.CORE_SCHEMA })); - } - }); - }; - - componentDidMount() { - const { - data: { dates = [] }, - } = useBackend(this.context); - - if (dates) { - dates.forEach((date) => - this.dateChoices.push(dateformat(date, 'mmmm yyyy', true)) - ); - this.setSelectedDate(this.dateChoices[0]); - this.getData(dates[0]); - } - } - - render() { - const { data, selectedDate, selectedIndex } = this.state; - const { - data: { dates }, - } = useBackend(this.context); - const { dateChoices } = this; - - const dateDropdown = dateChoices.length > 0 && ( - - -