mirror of
https://github.com/fulpstation/fulpstation.git
synced 2025-12-10 18:11:47 +00:00
Adds a Fulpstation Changelog (#1345)
* Commits a highly incomplete version of a Fulpstation changelog. * Further develops a basic, copied version of /tg/'s changelog. * Makes the changelog actually semi-functional. * Finalizes a few things...
This commit is contained in:
committed by
GitHub
parent
5a63a340bf
commit
16aeb51d7b
@@ -249,6 +249,11 @@ GLOBAL_PROTECT(tracy_init_reason)
|
|||||||
var/latest_changelog = file("[global.config.directory]/../html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
|
var/latest_changelog = file("[global.config.directory]/../html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
|
||||||
GLOB.changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently
|
GLOB.changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently
|
||||||
|
|
||||||
|
// FULP EDIT //
|
||||||
|
var/latest_fulp_changelog = file("[global.config.directory]/../fulp_modules/data/html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
|
||||||
|
GLOB.fulp_changelog_hash = fexists(latest_fulp_changelog) ? md5(latest_fulp_changelog) : 0
|
||||||
|
// FULP EDIT END //
|
||||||
|
|
||||||
if(GLOB.round_id)
|
if(GLOB.round_id)
|
||||||
log_game("Round ID: [GLOB.round_id]")
|
log_game("Round ID: [GLOB.round_id]")
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
|||||||
/// Cached changelog size, to detect new changelogs since last join
|
/// Cached changelog size, to detect new changelogs since last join
|
||||||
var/lastchangelog = ""
|
var/lastchangelog = ""
|
||||||
|
|
||||||
|
/// FULP EDIT ///
|
||||||
|
/// Same as var above but for Fulpstation's changelog.
|
||||||
|
var/last_fulp_changelog = ""
|
||||||
|
/// FULP EDIT END ///
|
||||||
|
|
||||||
/// List of ROLE_X that the client wants to be eligible for
|
/// List of ROLE_X that the client wants to be eligible for
|
||||||
var/list/be_special = list() //Special role selection
|
var/list/be_special = list() //Special role selection
|
||||||
|
|
||||||
|
|||||||
88
fulp_modules/data/html/changelogs/fulp_changelog.dm
Normal file
88
fulp_modules/data/html/changelogs/fulp_changelog.dm
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
//-----------------------------------------//
|
||||||
|
// Fulpstation's Changelog //
|
||||||
|
//-----------------------------------------//
|
||||||
|
|
||||||
|
/***
|
||||||
|
* This file contains all DM code related to Fulpstation's changelog.
|
||||||
|
*
|
||||||
|
* Most of this is just a very rough copying of existing /tg/ code with "fulp" appended to it,
|
||||||
|
* so credit for all of it goes to the various people who made /tg/'s changelog.
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/// FULP CHANGELOG DATUM ///
|
||||||
|
|
||||||
|
GLOBAL_DATUM(fulp_changelog_tgui, /datum/fulp_changelog)
|
||||||
|
GLOBAL_VAR_INIT(fulp_changelog_hash, "")
|
||||||
|
|
||||||
|
/datum/fulp_changelog
|
||||||
|
var/static/list/fulp_changelog_items = list()
|
||||||
|
|
||||||
|
/datum/fulp_changelog/ui_state()
|
||||||
|
return GLOB.always_state
|
||||||
|
|
||||||
|
/datum/fulp_changelog/ui_interact(mob/user, datum/tgui/ui)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if (!ui)
|
||||||
|
ui = new(user, src, "FulpChangelog")
|
||||||
|
ui.open()
|
||||||
|
|
||||||
|
/datum/fulp_changelog/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
return
|
||||||
|
if(action == "get_month")
|
||||||
|
var/datum/asset/fulp_changelog_item/fulp_changelog_item = fulp_changelog_items[params["date"]]
|
||||||
|
if (!fulp_changelog_item)
|
||||||
|
fulp_changelog_item = new /datum/asset/fulp_changelog_item(params["date"])
|
||||||
|
fulp_changelog_items[params["date"]] = fulp_changelog_item
|
||||||
|
return ui.send_asset(fulp_changelog_item)
|
||||||
|
|
||||||
|
/datum/fulp_changelog/ui_static_data()
|
||||||
|
var/list/data = list( "dates" = list() )
|
||||||
|
var/regex/ymlRegex = regex(@"\.yml", "g")
|
||||||
|
|
||||||
|
for(var/archive_file in sort_list(flist("fulp_modules/data/html/changelogs/archive/")))
|
||||||
|
var/archive_date = ymlRegex.Replace(archive_file, "")
|
||||||
|
data["dates"] = list(archive_date) + data["dates"]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
/// CHANGELOG VERB ///
|
||||||
|
|
||||||
|
/client/verb/fulp_changelog()
|
||||||
|
set name = "Changelog"
|
||||||
|
set category = "OOC"
|
||||||
|
if(!GLOB.fulp_changelog_tgui)
|
||||||
|
GLOB.fulp_changelog_tgui = new /datum/fulp_changelog()
|
||||||
|
|
||||||
|
GLOB.fulp_changelog_tgui.ui_interact(mob)
|
||||||
|
if(prefs.last_fulp_changelog != GLOB.fulp_changelog_hash)
|
||||||
|
prefs.last_fulp_changelog = GLOB.fulp_changelog_hash
|
||||||
|
prefs.save_preferences()
|
||||||
|
winset(src, "infowindow.changelog", "font-style=;")
|
||||||
|
|
||||||
|
|
||||||
|
/// FULP CHANGELOG ITEM ASSET ///
|
||||||
|
|
||||||
|
/datum/asset/fulp_changelog_item
|
||||||
|
_abstract = /datum/asset/fulp_changelog_item
|
||||||
|
var/item_filename
|
||||||
|
|
||||||
|
/datum/asset/fulp_changelog_item/New(date)
|
||||||
|
item_filename = SANITIZE_FILENAME("[date].yml")
|
||||||
|
SSassets.transport.register_asset(item_filename, file("fulp_modules/data/html/changelogs/archive/" + item_filename))
|
||||||
|
|
||||||
|
/datum/asset/fulp_changelog_item/send(client)
|
||||||
|
if (!item_filename)
|
||||||
|
return
|
||||||
|
. = SSassets.transport.send_assets(client, item_filename)
|
||||||
|
|
||||||
|
/datum/asset/fulp_changelog_item/get_url_mappings()
|
||||||
|
if (!item_filename)
|
||||||
|
return
|
||||||
|
. = list("[item_filename]" = SSassets.transport.get_asset_url(item_filename))
|
||||||
|
|
||||||
|
|
||||||
|
// See 'world.dm' for a changelog-related Fulp edit. //
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
## List of all TG edits:
|
## List of all TG edits:
|
||||||
|
|
||||||
- .github/workflows/compile_changelogs.yml > Same as above.
|
|
||||||
|
|
||||||
- code/datums/greyscale/_greyscale_config.dm > Adds our greyscales folder to the sanity check
|
- code/datums/greyscale/_greyscale_config.dm > Adds our greyscales folder to the sanity check
|
||||||
|
|
||||||
- code/game/area/areas/shuttles.dm > Plays ApproachingFulp instead of ApproachingTG
|
- code/game/area/areas/shuttles.dm > Plays ApproachingFulp instead of ApproachingTG
|
||||||
@@ -18,6 +16,14 @@
|
|||||||
|
|
||||||
- tools/pull_request_hooks/autoChangelog.js > Changes changelog folder to fulp_modules/data/html/changelogs, to preserve them across TGUs.
|
- tools/pull_request_hooks/autoChangelog.js > Changes changelog folder to fulp_modules/data/html/changelogs, to preserve them across TGUs.
|
||||||
|
|
||||||
|
- .github\workflows\compile_changelogs.yml > Same as above.
|
||||||
|
|
||||||
|
- code\game\world.dm > Marked by a "FULP EDIT" comment; copies a bit of code to make 'GLOB.fulp_changelog_hash' functional.
|
||||||
|
|
||||||
|
- code\modules\client\preferences.dm > Marked by a "FULP EDIT" comment; gives clients the 'last_fulp_changelog' var.
|
||||||
|
|
||||||
|
- interface\interface.dm > Changes the value of 'name' on '/client/verb/changelog' to "/TG/ Changelog"
|
||||||
|
|
||||||
## All Fulp files not contained within /fulp_modules/
|
## All Fulp files not contained within /fulp_modules/
|
||||||
|
|
||||||
- code/__DEFINES/fulp_defines > Contains all of our defines
|
- code/__DEFINES/fulp_defines > Contains all of our defines
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/client/verb/changelog()
|
/client/verb/changelog()
|
||||||
set name = "Changelog"
|
set name = "/TG/ Changelog"
|
||||||
set category = "OOC"
|
set category = "OOC"
|
||||||
if(!GLOB.changelog_tgui)
|
if(!GLOB.changelog_tgui)
|
||||||
GLOB.changelog_tgui = new /datum/changelog()
|
GLOB.changelog_tgui = new /datum/changelog()
|
||||||
|
|||||||
@@ -6526,6 +6526,7 @@
|
|||||||
#include "fulp_modules\_signals\bloodsuckers.dm"
|
#include "fulp_modules\_signals\bloodsuckers.dm"
|
||||||
#include "fulp_modules\_signals\misc.dm"
|
#include "fulp_modules\_signals\misc.dm"
|
||||||
#include "fulp_modules\_signals\nanites.dm"
|
#include "fulp_modules\_signals\nanites.dm"
|
||||||
|
#include "fulp_modules\data\html\changelogs\fulp_changelog.dm"
|
||||||
#include "fulp_modules\features\admin_chicanery\smites\catification.dm"
|
#include "fulp_modules\features\admin_chicanery\smites\catification.dm"
|
||||||
#include "fulp_modules\features\antagonists\antag_tips\antag_tip_integration.dm"
|
#include "fulp_modules\features\antagonists\antag_tips\antag_tip_integration.dm"
|
||||||
#include "fulp_modules\features\antagonists\antag_tips\preference.dm"
|
#include "fulp_modules\features\antagonists\antag_tips\preference.dm"
|
||||||
|
|||||||
371
tgui/packages/fulpui-patches/FulpChangelog.jsx
Normal file
371
tgui/packages/fulpui-patches/FulpChangelog.jsx
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
import dateformat from 'dateformat';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
import { Component, Fragment } from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Dropdown,
|
||||||
|
Icon,
|
||||||
|
Section,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
} from '../tgui/components';
|
||||||
|
import { classes } from 'common/react';
|
||||||
|
|
||||||
|
import { resolveAsset } from '../tgui/assets';
|
||||||
|
import { useBackend } from '../tgui/backend';
|
||||||
|
import { Window } from '../tgui/layouts';
|
||||||
|
|
||||||
|
const icons = {
|
||||||
|
add: { icon: 'check-circle', color: 'green' },
|
||||||
|
admin: { icon: 'user-shield', color: 'purple' },
|
||||||
|
balance: { icon: 'balance-scale-right', color: 'yellow' },
|
||||||
|
bugfix: { icon: 'bug', color: 'green' },
|
||||||
|
code_imp: { icon: 'code', color: 'green' },
|
||||||
|
config: { icon: 'cogs', color: 'purple' },
|
||||||
|
expansion: { icon: 'check-circle', color: 'green' },
|
||||||
|
experiment: { icon: 'radiation', color: 'yellow' },
|
||||||
|
image: { icon: 'image', color: 'green' },
|
||||||
|
imageadd: { icon: 'tg-image-plus', color: 'green' },
|
||||||
|
imagedel: { icon: 'tg-image-minus', color: 'red' },
|
||||||
|
qol: { icon: 'hand-holding-heart', color: 'green' },
|
||||||
|
refactor: { icon: 'tools', color: 'green' },
|
||||||
|
rscadd: { icon: 'check-circle', color: 'green' },
|
||||||
|
rscdel: { icon: 'times-circle', color: 'red' },
|
||||||
|
server: { icon: 'server', color: 'purple' },
|
||||||
|
sound: { icon: 'volume-high', color: 'green' },
|
||||||
|
soundadd: { icon: 'tg-sound-plus', color: 'green' },
|
||||||
|
sounddel: { icon: 'tg-sound-minus', color: 'red' },
|
||||||
|
spellcheck: { icon: 'spell-check', color: 'green' },
|
||||||
|
map: { icon: 'map', color: 'green' },
|
||||||
|
tgs: { icon: 'toolbox', color: 'purple' },
|
||||||
|
tweak: { icon: 'wrench', color: 'green' },
|
||||||
|
unknown: { icon: 'info-circle', color: 'label' },
|
||||||
|
wip: { icon: 'hammer', color: 'orange' },
|
||||||
|
};
|
||||||
|
|
||||||
|
export class FulpChangelog extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
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();
|
||||||
|
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();
|
||||||
|
|
||||||
|
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();
|
||||||
|
const { dateChoices } = this;
|
||||||
|
|
||||||
|
const dateDropdown = dateChoices.length > 0 && (
|
||||||
|
<Stack mb={1}>
|
||||||
|
<Stack.Item>
|
||||||
|
<Button
|
||||||
|
className="Changelog__Button"
|
||||||
|
disabled={selectedIndex === 0}
|
||||||
|
icon={'chevron-left'}
|
||||||
|
onClick={() => {
|
||||||
|
const index = selectedIndex - 1;
|
||||||
|
|
||||||
|
this.setData('Loading changelog data...');
|
||||||
|
this.setSelectedIndex(index);
|
||||||
|
this.setSelectedDate(dateChoices[index]);
|
||||||
|
window.scrollTo(
|
||||||
|
0,
|
||||||
|
document.body.scrollHeight ||
|
||||||
|
document.documentElement.scrollHeight,
|
||||||
|
);
|
||||||
|
return this.getData(dates[index]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item>
|
||||||
|
<Dropdown
|
||||||
|
autoScroll={false}
|
||||||
|
options={dateChoices}
|
||||||
|
onSelected={(value) => {
|
||||||
|
const index = dateChoices.indexOf(value);
|
||||||
|
|
||||||
|
this.setData('Loading changelog data...');
|
||||||
|
this.setSelectedIndex(index);
|
||||||
|
this.setSelectedDate(value);
|
||||||
|
window.scrollTo(
|
||||||
|
0,
|
||||||
|
document.body.scrollHeight ||
|
||||||
|
document.documentElement.scrollHeight,
|
||||||
|
);
|
||||||
|
return this.getData(dates[index]);
|
||||||
|
}}
|
||||||
|
selected={selectedDate}
|
||||||
|
width="150px"
|
||||||
|
/>
|
||||||
|
</Stack.Item>
|
||||||
|
<Stack.Item>
|
||||||
|
<Button
|
||||||
|
className="Changelog__Button"
|
||||||
|
disabled={selectedIndex === dateChoices.length - 1}
|
||||||
|
icon={'chevron-right'}
|
||||||
|
onClick={() => {
|
||||||
|
const index = selectedIndex + 1;
|
||||||
|
|
||||||
|
this.setData('Loading changelog data...');
|
||||||
|
this.setSelectedIndex(index);
|
||||||
|
this.setSelectedDate(dateChoices[index]);
|
||||||
|
window.scrollTo(
|
||||||
|
0,
|
||||||
|
document.body.scrollHeight ||
|
||||||
|
document.documentElement.scrollHeight,
|
||||||
|
);
|
||||||
|
return this.getData(dates[index]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack.Item>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
|
||||||
|
const header = (
|
||||||
|
<Section>
|
||||||
|
<h1>Fulpstation</h1>
|
||||||
|
<p>
|
||||||
|
<b>Please note: </b>
|
||||||
|
this changelog would not be possible without the groundwork laid by
|
||||||
|
/tg/station's contributors and so many others. Aside from its logged
|
||||||
|
content, this changelog is an almost identical copy of /tg/station's,
|
||||||
|
which can currently be found in the OOC tab under the "/TG/ Changelog"
|
||||||
|
verb.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Thanks to: </b>
|
||||||
|
/tg/station, Baystation 12, /vg/station, NTstation, CDK Station devs,
|
||||||
|
FacepunchStation, GoonStation devs, the original Space Station 13
|
||||||
|
developers, GitHub user celotajstg for adapting this changelog into
|
||||||
|
TGUI, and countless others who have contributed to the game, issue
|
||||||
|
tracker or wiki over the years.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{'Recent GitHub contributors can be found '}
|
||||||
|
<a href="https://github.com/fulpstation/fulpstation/pulse/monthly">
|
||||||
|
here
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
'You can also find a link to our discord at the front page of our wiki'
|
||||||
|
}
|
||||||
|
<a href="https://wiki.fulp.gg/"> here</a>.
|
||||||
|
</p>
|
||||||
|
{dateDropdown}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
|
||||||
|
const footer = (
|
||||||
|
<Section>
|
||||||
|
{dateDropdown}
|
||||||
|
<h3>GoonStation 13 Development Team</h3>
|
||||||
|
<p>
|
||||||
|
<b>Coders: </b>
|
||||||
|
Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob,
|
||||||
|
Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Spriters: </b>
|
||||||
|
Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said
|
||||||
|
No
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Traditional Games Space Station 13 is thankful to the GoonStation 13
|
||||||
|
Development Team for its work on the game up to the
|
||||||
|
{' r4407 release. The changelog for changes up to r4407 can be seen '}
|
||||||
|
<a href="https://wiki.ss13.co/Pre-2016_Changelog#April_2010">here</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{'Except where otherwise noted, Goon Station 13 is licensed under a '}
|
||||||
|
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">
|
||||||
|
Creative Commons Attribution-Noncommercial-Share Alike 3.0 License
|
||||||
|
</a>
|
||||||
|
{'. Rights are currently extended to '}
|
||||||
|
<a href="http://forums.somethingawful.com/">SomethingAwful Goons</a>
|
||||||
|
{' only.'}
|
||||||
|
</p>
|
||||||
|
<h3>Traditional Games Space Station 13 License</h3>
|
||||||
|
<p>
|
||||||
|
{'All code after '}
|
||||||
|
<a
|
||||||
|
href={
|
||||||
|
'https://github.com/tgstation/tgstation/commit/' +
|
||||||
|
'333c566b88108de218d882840e61928a9b759d8f'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at
|
||||||
|
4:38 PM PST
|
||||||
|
</a>
|
||||||
|
{' is licensed under '}
|
||||||
|
<a href="https://www.gnu.org/licenses/agpl-3.0.html">GNU AGPL v3</a>
|
||||||
|
{'. All code before that commit is licensed under '}
|
||||||
|
<a href="https://www.gnu.org/licenses/gpl-3.0.html">GNU GPL v3</a>
|
||||||
|
{', including tools unless their readme specifies otherwise. See '}
|
||||||
|
<a href="https://github.com/tgstation/tgstation/blob/master/LICENSE">
|
||||||
|
LICENSE
|
||||||
|
</a>
|
||||||
|
{' and '}
|
||||||
|
<a href="https://github.com/tgstation/tgstation/blob/master/GPLv3.txt">
|
||||||
|
GPLv3.txt
|
||||||
|
</a>
|
||||||
|
{' for more details.'}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The TGS DMAPI API is licensed as a subproject under the MIT license.
|
||||||
|
{' See the footer of '}
|
||||||
|
<a
|
||||||
|
href={
|
||||||
|
'https://github.com/tgstation/tgstation/blob/master' +
|
||||||
|
'/code/__DEFINES/tgs.dm'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
code/__DEFINES/tgs.dm
|
||||||
|
</a>
|
||||||
|
{' and '}
|
||||||
|
<a
|
||||||
|
href={
|
||||||
|
'https://github.com/tgstation/tgstation/blob/master' +
|
||||||
|
'/code/modules/tgs/LICENSE'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
code/modules/tgs/LICENSE
|
||||||
|
</a>
|
||||||
|
{' for the MIT license.'}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{'All assets including icons and sound are under a '}
|
||||||
|
<a href="https://creativecommons.org/licenses/by-sa/3.0/">
|
||||||
|
Creative Commons 3.0 BY-SA license
|
||||||
|
</a>
|
||||||
|
{' unless otherwise indicated.'}
|
||||||
|
</p>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
|
||||||
|
const changes =
|
||||||
|
typeof data === 'object' &&
|
||||||
|
Object.keys(data).length > 0 &&
|
||||||
|
Object.entries(data)
|
||||||
|
.reverse()
|
||||||
|
.map(([date, authors]) => (
|
||||||
|
<Section key={date} title={dateformat(date, 'd mmmm yyyy', true)}>
|
||||||
|
<Box ml={3}>
|
||||||
|
{Object.entries(authors).map(([name, changes]) => (
|
||||||
|
<Fragment key={name}>
|
||||||
|
<h4>{name} changed:</h4>
|
||||||
|
<Box ml={3}>
|
||||||
|
<Table>
|
||||||
|
{changes.map((change) => {
|
||||||
|
const changeType = Object.keys(change)[0];
|
||||||
|
return (
|
||||||
|
<Table.Row key={changeType + change[changeType]}>
|
||||||
|
<Table.Cell
|
||||||
|
className={classes([
|
||||||
|
'Changelog__Cell',
|
||||||
|
'Changelog__Cell--Icon',
|
||||||
|
])}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
color={
|
||||||
|
icons[changeType]
|
||||||
|
? icons[changeType].color
|
||||||
|
: icons['unknown'].color
|
||||||
|
}
|
||||||
|
name={
|
||||||
|
icons[changeType]
|
||||||
|
? icons[changeType].icon
|
||||||
|
: icons['unknown'].icon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell className="Changelog__Cell">
|
||||||
|
{change[changeType]}
|
||||||
|
</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Table>
|
||||||
|
</Box>
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Section>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Window title="Changelog" width={675} height={650}>
|
||||||
|
<Window.Content scrollable>
|
||||||
|
{header}
|
||||||
|
{changes}
|
||||||
|
{typeof data === 'string' && <p>{data}</p>}
|
||||||
|
{footer}
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user