mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-24 17:11:22 +00:00
Welcome Screen (#535)
The idea is to consolidate all of the spam that you see on the lower right panel into one concrete, semi-persistent pop-up window. Utilizing bootstrap, it'll show you a neat welcome screen, the message of the day, staff memos (if accessible), and a personalized set of notifications. The system is set up for easy future expansion, as well.
This commit is contained in:
@@ -277,6 +277,8 @@ CREATE TABLE `ss13_player_preferences` (
|
|||||||
`UI_style_alpha` int(11) NOT NULL,
|
`UI_style_alpha` int(11) NOT NULL,
|
||||||
`be_special` int(11) NOT NULL,
|
`be_special` int(11) NOT NULL,
|
||||||
`asfx_togs` int(11) NOT NULL,
|
`asfx_togs` int(11) NOT NULL,
|
||||||
|
`lastmotd` text NOT NULL,
|
||||||
|
`lastmemo` text NOT NULL,
|
||||||
PRIMARY KEY (`ckey`),
|
PRIMARY KEY (`ckey`),
|
||||||
CONSTRAINT `player_preferences_fk_ckey` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON DELETE CASCADE ON UPDATE CASCADE
|
CONSTRAINT `player_preferences_fk_ckey` FOREIGN KEY (`ckey`) REFERENCES `ss13_player` (`ckey`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|||||||
@@ -134,6 +134,7 @@
|
|||||||
#include "code\datums\modules.dm"
|
#include "code\datums\modules.dm"
|
||||||
#include "code\datums\organs.dm"
|
#include "code\datums\organs.dm"
|
||||||
#include "code\datums\recipe.dm"
|
#include "code\datums\recipe.dm"
|
||||||
|
#include "code\datums\server_greeting.dm"
|
||||||
#include "code\datums\sun.dm"
|
#include "code\datums\sun.dm"
|
||||||
#include "code\datums\supplypacks.dm"
|
#include "code\datums\supplypacks.dm"
|
||||||
#include "code\datums\diseases\appendicitis.dm"
|
#include "code\datums\diseases\appendicitis.dm"
|
||||||
@@ -811,8 +812,8 @@
|
|||||||
#include "code\modules\admin\admin.dm"
|
#include "code\modules\admin\admin.dm"
|
||||||
#include "code\modules\admin\admin_attack_log.dm"
|
#include "code\modules\admin\admin_attack_log.dm"
|
||||||
#include "code\modules\admin\admin_investigate.dm"
|
#include "code\modules\admin\admin_investigate.dm"
|
||||||
#include "code\modules\admin\admin_memo.dm"
|
|
||||||
#include "code\modules\admin\admin_ranks.dm"
|
#include "code\modules\admin\admin_ranks.dm"
|
||||||
|
#include "code\modules\admin\admin_server_greeting.dm"
|
||||||
#include "code\modules\admin\admin_verbs.dm"
|
#include "code\modules\admin\admin_verbs.dm"
|
||||||
#include "code\modules\admin\banjob.dm"
|
#include "code\modules\admin\banjob.dm"
|
||||||
#include "code\modules\admin\create_mob.dm"
|
#include "code\modules\admin\create_mob.dm"
|
||||||
@@ -896,6 +897,7 @@
|
|||||||
#include "code\modules\client\preferences_ambience.dm"
|
#include "code\modules\client\preferences_ambience.dm"
|
||||||
#include "code\modules\client\preferences_factions.dm"
|
#include "code\modules\client\preferences_factions.dm"
|
||||||
#include "code\modules\client\preferences_gear.dm"
|
#include "code\modules\client\preferences_gear.dm"
|
||||||
|
#include "code\modules\client\preferences_notification.dm"
|
||||||
#include "code\modules\client\preferences_save_migration.dm"
|
#include "code\modules\client\preferences_save_migration.dm"
|
||||||
#include "code\modules\client\preferences_savefile.dm"
|
#include "code\modules\client\preferences_savefile.dm"
|
||||||
#include "code\modules\client\preferences_spawnpoints.dm"
|
#include "code\modules\client\preferences_spawnpoints.dm"
|
||||||
|
|||||||
209
code/datums/server_greeting.dm
Normal file
209
code/datums/server_greeting.dm
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Server greeting datum.
|
||||||
|
* Contains the following information:
|
||||||
|
* - hashes for the message of the day and staff memos
|
||||||
|
* - the current message of the day and staff memos
|
||||||
|
* - the fully parsed welcome screen HTML data
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MEMOFILE "data/greeting.sav"
|
||||||
|
|
||||||
|
#define OUTDATED_MOTD 1
|
||||||
|
#define OUTDATED_MEMO 2
|
||||||
|
#define OUTDATED_NOTE 4
|
||||||
|
|
||||||
|
/datum/server_greeting
|
||||||
|
// Hashes to figure out if we need to display the greeting message.
|
||||||
|
// These correspond to motd_hash and memo_hash on /datum/preferences for each client.
|
||||||
|
var/motd_hash = ""
|
||||||
|
var/memo_hash = ""
|
||||||
|
|
||||||
|
// The stored strings of general subcomponents.
|
||||||
|
var/motd = ""
|
||||||
|
var/memo_list[] = list()
|
||||||
|
var/memo = ""
|
||||||
|
|
||||||
|
var/raw_data_user = ""
|
||||||
|
var/raw_data_staff = ""
|
||||||
|
// The near-final string to be displayed.
|
||||||
|
// Only one placeholder remains: <!--notifications-->.
|
||||||
|
var/user_data = ""
|
||||||
|
var/staff_data = ""
|
||||||
|
|
||||||
|
/datum/server_greeting/New()
|
||||||
|
..()
|
||||||
|
|
||||||
|
load_from_file()
|
||||||
|
|
||||||
|
prepare_data()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Populates variables from save file, and loads the raw HTML data.
|
||||||
|
* Needs to be called at least once for successful initialization.
|
||||||
|
*/
|
||||||
|
/datum/server_greeting/proc/load_from_file()
|
||||||
|
var/savefile/F = new(MEMOFILE)
|
||||||
|
if (F)
|
||||||
|
if (F["motd"])
|
||||||
|
F["motd"] >> motd
|
||||||
|
|
||||||
|
if (F["memo"])
|
||||||
|
F["memo"] >> memo_list
|
||||||
|
|
||||||
|
raw_data_staff = file2text('html/templates/welcome_screen.html')
|
||||||
|
|
||||||
|
// This is a lazy way, but it disables the user from being able to see the memo button.
|
||||||
|
var/staff_button = "<li role=\"presentation\"><a href=\"#memo\" aria-controls=\"memo\" role=\"tab\" data-toggle=\"tab\">Staff Memos</a></li>"
|
||||||
|
raw_data_user = replacetextEx(raw_data_staff, staff_button, "")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generates hashes, placeholders, and reparses var/memo.
|
||||||
|
* Then updates staff_data and user_data with the new contents.
|
||||||
|
* To be called after load_from_file or update_value.
|
||||||
|
*/
|
||||||
|
/datum/server_greeting/proc/prepare_data()
|
||||||
|
if (!motd)
|
||||||
|
motd = "<center>No new announcements to showcase.</center>"
|
||||||
|
motd_hash = ""
|
||||||
|
else
|
||||||
|
motd_hash = md5(motd)
|
||||||
|
|
||||||
|
memo = ""
|
||||||
|
|
||||||
|
if (memo_list.len)
|
||||||
|
for (var/ckey in memo_list)
|
||||||
|
var/data = {"
|
||||||
|
<p><b>[ckey]</b> wrote on [memo_list[ckey]["date"]]:<br>
|
||||||
|
[memo_list[ckey]["content"]]</p>
|
||||||
|
"}
|
||||||
|
|
||||||
|
memo += data
|
||||||
|
|
||||||
|
memo_hash = md5(memo)
|
||||||
|
else
|
||||||
|
memo = "<center>No memos have been posted.</center>"
|
||||||
|
memo_hash = ""
|
||||||
|
|
||||||
|
var/html_one = raw_data_staff
|
||||||
|
html_one = replacetextEx(html_one, "<!--motd-->", motd)
|
||||||
|
html_one = replacetextEx(html_one, "<!--memo-->", memo)
|
||||||
|
staff_data = html_one
|
||||||
|
|
||||||
|
var/html_two = raw_data_user
|
||||||
|
html_two = replacetextEx(html_two, "<!--motd-->", motd)
|
||||||
|
user_data = html_two
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to update the MoTD or memo contents.
|
||||||
|
* Args:
|
||||||
|
* - var/change string
|
||||||
|
* - var/new_value mixed
|
||||||
|
* Returns:
|
||||||
|
* - 1 upon success
|
||||||
|
* - 0 upon failure
|
||||||
|
*/
|
||||||
|
/datum/server_greeting/proc/update_value(var/change, var/new_value)
|
||||||
|
if (!change || !new_value)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
switch (change)
|
||||||
|
if ("motd")
|
||||||
|
motd = new_value
|
||||||
|
motd_hash = md5(new_value)
|
||||||
|
|
||||||
|
if ("memo_write")
|
||||||
|
memo_list[new_value[1]] = list("date" = time2text(world.realtime, "DD-MMM-YYYY"), "content" = new_value[2])
|
||||||
|
|
||||||
|
if ("memo_delete")
|
||||||
|
if (memo_list[new_value])
|
||||||
|
memo_list -= new_value
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var/savefile/F = new(MEMOFILE)
|
||||||
|
F["motd"] << motd
|
||||||
|
F["memo"] << memo_list
|
||||||
|
|
||||||
|
prepare_data()
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper proc to determine whether or not we need to show the greeting window to a user.
|
||||||
|
* Args:
|
||||||
|
* - var/user client
|
||||||
|
* Returns:
|
||||||
|
* - int
|
||||||
|
*/
|
||||||
|
/datum/server_greeting/proc/find_outdated_info(var/client/user)
|
||||||
|
if (!user || !user.prefs)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var/outdated_info = 0
|
||||||
|
|
||||||
|
if (motd_hash && user.prefs.motd_hash != motd_hash)
|
||||||
|
outdated_info |= OUTDATED_MOTD
|
||||||
|
|
||||||
|
if (user.holder && memo_hash && user.prefs.memo_hash != memo_hash)
|
||||||
|
outdated_info |= OUTDATED_MEMO
|
||||||
|
|
||||||
|
if (user.prefs.notifications.len)
|
||||||
|
outdated_info |= OUTDATED_NOTE
|
||||||
|
|
||||||
|
return outdated_info
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Composes the final message and displays it to the user.
|
||||||
|
* Also clears the user's notifications, should he have any.
|
||||||
|
*/
|
||||||
|
/datum/server_greeting/proc/display_to_client(var/client/user, var/outdated_info = 0)
|
||||||
|
if (!user)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/notifications = "<div class=\"row\"><div class=\"alert alert-info\">You do not have any notifications to show.</div></div>"
|
||||||
|
var/list/outdated_tabs = list()
|
||||||
|
var/save_prefs = 0
|
||||||
|
|
||||||
|
if (outdated_info & OUTDATED_NOTE)
|
||||||
|
outdated_tabs += "#note-tab"
|
||||||
|
|
||||||
|
notifications = ""
|
||||||
|
for (var/datum/client_notification/a in user.prefs.notifications)
|
||||||
|
notifications += a.get_html()
|
||||||
|
|
||||||
|
if (outdated_info & OUTDATED_MEMO)
|
||||||
|
outdated_tabs += "#memo-tab"
|
||||||
|
user.prefs.memo_hash = memo_hash
|
||||||
|
save_prefs = 1
|
||||||
|
|
||||||
|
if (outdated_info & OUTDATED_MOTD)
|
||||||
|
outdated_tabs += "#motd-tab"
|
||||||
|
user.prefs.motd_hash = motd_hash
|
||||||
|
save_prefs = 1
|
||||||
|
|
||||||
|
var/data = user_data
|
||||||
|
|
||||||
|
if (user.holder)
|
||||||
|
data = staff_data
|
||||||
|
|
||||||
|
data = replacetextEx(data, "<!--note-->", notifications)
|
||||||
|
|
||||||
|
if (outdated_tabs.len)
|
||||||
|
var/tab_string = json_encode(outdated_tabs)
|
||||||
|
data = replacetextEx(data, "var updated_tabs = \[\]", "var updated_tabs = [tab_string]")
|
||||||
|
|
||||||
|
user << browse(data, "window=welcome_screen;size=640x500")
|
||||||
|
|
||||||
|
if (save_prefs)
|
||||||
|
user.prefs.handle_preferences_save(user)
|
||||||
|
|
||||||
|
#undef OUTDATED_NOTE
|
||||||
|
#undef OUTDATED_MEMO
|
||||||
|
#undef OUTDATED_MOTD
|
||||||
|
|
||||||
|
#undef MEMOFILE
|
||||||
@@ -179,7 +179,7 @@ var/datum/moduletypes/mods = new()
|
|||||||
var/wavesecret = 0
|
var/wavesecret = 0
|
||||||
var/gravity_is_on = 1
|
var/gravity_is_on = 1
|
||||||
|
|
||||||
var/join_motd = null
|
var/datum/server_greeting/server_greeting = null
|
||||||
var/forceblob = 0
|
var/forceblob = 0
|
||||||
|
|
||||||
var/datum/nanomanager/nanomanager = new() // NanoManager, the manager for Nano UIs.
|
var/datum/nanomanager/nanomanager = new() // NanoManager, the manager for Nano UIs.
|
||||||
|
|||||||
@@ -113,8 +113,6 @@
|
|||||||
var/DBQuery/query = dbcon.NewQuery("SELECT ban_mirror_id, player_ckey, ban_mirror_ip, ban_mirror_computerid, date(ban_mirror_datetime) as datetime FROM ss13_ban_mirrors WHERE ban_id = :ban_id")
|
var/DBQuery/query = dbcon.NewQuery("SELECT ban_mirror_id, player_ckey, ban_mirror_ip, ban_mirror_computerid, date(ban_mirror_datetime) as datetime FROM ss13_ban_mirrors WHERE ban_id = :ban_id")
|
||||||
query.Execute(list(":ban_id" = ban_id))
|
query.Execute(list(":ban_id" = ban_id))
|
||||||
|
|
||||||
testing("Ban ID: [ban_id]")
|
|
||||||
|
|
||||||
var/mirrors[] = list()
|
var/mirrors[] = list()
|
||||||
while (query.NextRow())
|
while (query.NextRow())
|
||||||
var/items[] = list()
|
var/items[] = list()
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
#define MEMOFILE "data/memo.sav" //where the memos are saved
|
|
||||||
#define ENABLE_MEMOS 1 //using a define because screw making a config variable for it. This is more efficient and purty.
|
|
||||||
|
|
||||||
//switch verb so we don't spam up the verb lists with like, 3 verbs for this feature.
|
|
||||||
/client/proc/admin_memo(task in list("write","show","delete"))
|
|
||||||
set name = "Memo"
|
|
||||||
set category = "Server"
|
|
||||||
if(!ENABLE_MEMOS) return
|
|
||||||
if(!check_rights(0)) return
|
|
||||||
switch(task)
|
|
||||||
if("write") admin_memo_write()
|
|
||||||
if("show") admin_memo_show()
|
|
||||||
if("delete") admin_memo_delete()
|
|
||||||
|
|
||||||
//write a message
|
|
||||||
/client/proc/admin_memo_write()
|
|
||||||
var/savefile/F = new(MEMOFILE)
|
|
||||||
if(F)
|
|
||||||
var/memo = sanitize(input(src,"Type your memo\n(Leaving it blank will delete your current memo):","Write Memo",null) as null|message, extra = 0)
|
|
||||||
switch(memo)
|
|
||||||
if(null)
|
|
||||||
return
|
|
||||||
if("")
|
|
||||||
F.dir.Remove(ckey)
|
|
||||||
src << "<b>Memo removed</b>"
|
|
||||||
return
|
|
||||||
if( findtext(memo,"<script",1,0) )
|
|
||||||
return
|
|
||||||
F[ckey] << "[key] on [time2text(world.realtime,"(DDD) DD MMM hh:mm")]<br>[memo]"
|
|
||||||
message_admins("[key] set an admin memo:<br>[memo]")
|
|
||||||
|
|
||||||
//show all memos
|
|
||||||
/client/proc/admin_memo_show()
|
|
||||||
if(ENABLE_MEMOS)
|
|
||||||
var/savefile/F = new(MEMOFILE)
|
|
||||||
if(F)
|
|
||||||
for(var/ckey in F.dir)
|
|
||||||
src << "<center><span class='motd'><b>Admin Memo</b><i> by [F[ckey]]</i></span></center>"
|
|
||||||
|
|
||||||
//delete your own or somebody else's memo
|
|
||||||
/client/proc/admin_memo_delete()
|
|
||||||
var/savefile/F = new(MEMOFILE)
|
|
||||||
if(F)
|
|
||||||
var/ckey
|
|
||||||
if(check_rights(R_SERVER,0)) //high ranking admins can delete other admin's memos
|
|
||||||
ckey = input(src,"Whose memo shall we remove?","Remove Memo",null) as null|anything in F.dir
|
|
||||||
else
|
|
||||||
ckey = src.ckey
|
|
||||||
if(ckey)
|
|
||||||
F.dir.Remove(ckey)
|
|
||||||
src << "<b>Removed Memo created by [ckey].</b>"
|
|
||||||
|
|
||||||
#undef MEMOFILE
|
|
||||||
#undef ENABLE_MEMOS
|
|
||||||
80
code/modules/admin/admin_server_greeting.dm
Normal file
80
code/modules/admin/admin_server_greeting.dm
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* A file containing the admin commands for interfacing with the server_greeting datum.
|
||||||
|
*/
|
||||||
|
/client/proc/admin_edit_motd()
|
||||||
|
set name = "Edit MotD"
|
||||||
|
set category = "Server"
|
||||||
|
|
||||||
|
if (!check_rights(R_SERVER))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/new_message = input(usr, "Please edit the Message of the Day as necessary.", "Message of the Day", server_greeting.motd) as message
|
||||||
|
|
||||||
|
if (!new_message)
|
||||||
|
new_message = "<center>This is a palceholder. Pester your staff to change it!</center>"
|
||||||
|
|
||||||
|
server_greeting.update_value("motd", new_message)
|
||||||
|
message_admins("[ckey] has edited the message of the day:<br>[html_encode(new_message)]")
|
||||||
|
|
||||||
|
/client/proc/admin_memo_control(task in list("write", "delete"))
|
||||||
|
set name = "Edit Memos"
|
||||||
|
set category = "Server"
|
||||||
|
|
||||||
|
if (!check_rights(R_ADMIN))
|
||||||
|
return
|
||||||
|
|
||||||
|
switch (task)
|
||||||
|
if ("write")
|
||||||
|
admin_memo_write()
|
||||||
|
if ("delete")
|
||||||
|
admin_memo_delete()
|
||||||
|
|
||||||
|
/client/proc/admin_memo_write()
|
||||||
|
var/current_memo = ""
|
||||||
|
if (server_greeting.memo_list.len && server_greeting.memo_list[ckey])
|
||||||
|
current_memo = server_greeting.memo_list[ckey]
|
||||||
|
|
||||||
|
var/new_memo = input(usr, "Please write your memo.", "Memo", current_memo) as message
|
||||||
|
|
||||||
|
if (server_greeting.update_value("memo_write", list(ckey, new_memo)))
|
||||||
|
src << "<span class='notice'>Operation carried out successfully.</span>"
|
||||||
|
message_admins("[ckey] wrote a new memo:<br>[html_encode(new_memo)]")
|
||||||
|
else
|
||||||
|
src << "<span class='danger'>Error carrying out desired operation.</span>"
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
/client/proc/admin_memo_delete()
|
||||||
|
if (!server_greeting.memo_list.len)
|
||||||
|
src << "<span class='notice'>No memos are currently saved.</span>"
|
||||||
|
return
|
||||||
|
|
||||||
|
if (!check_rights(R_SERVER))
|
||||||
|
if (!server_greeting.memo_list[ckey])
|
||||||
|
src << "<span class='warning'>You do not have a memo saved. Cancelling.</span>"
|
||||||
|
|
||||||
|
else if (alert("Do you wish to delete your own memo, written on [server_greeting.memo_list[ckey]["date"]]?", "Choices", "Yes", "No") == "Yes")
|
||||||
|
if (server_greeting.update_value("memo_delete", ckey))
|
||||||
|
src << "<span class='notice'>Operation carried out successfully.</span>"
|
||||||
|
message_admins("[ckey] has deleted their own memo.")
|
||||||
|
else
|
||||||
|
src << "<span class='danger'>Error carrying out desired operation.</span>"
|
||||||
|
|
||||||
|
else
|
||||||
|
src << "<span class='notice'>Cancelled.</span>"
|
||||||
|
|
||||||
|
return
|
||||||
|
else
|
||||||
|
var/input = input(usr, "Whose memo shall we delete?", "Remove Memo", null) as null|anything in server_greeting.memo_list
|
||||||
|
|
||||||
|
if (!input)
|
||||||
|
src << "<span class='notice'>Cancelled.</span>"
|
||||||
|
return
|
||||||
|
|
||||||
|
if (server_greeting.update_value("memo_delete", input))
|
||||||
|
src << "<span class='notice'>Operation carried out successfully.</span>"
|
||||||
|
message_admins("[ckey] has deleted the memo of [input].")
|
||||||
|
else
|
||||||
|
src << "<span class='danger'>Error carrying out desired operation.</span>"
|
||||||
|
|
||||||
|
return
|
||||||
@@ -50,7 +50,7 @@ var/list/admin_verbs_admin = list(
|
|||||||
/client/proc/rename_silicon, /*properly renames silicons*/
|
/client/proc/rename_silicon, /*properly renames silicons*/
|
||||||
/client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */
|
/client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */
|
||||||
/client/proc/check_antagonists,
|
/client/proc/check_antagonists,
|
||||||
/client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
|
/client/proc/admin_memo_control, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
|
||||||
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
|
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
|
||||||
/client/proc/toggleprayers, /*toggles prayers on/off*/
|
/client/proc/toggleprayers, /*toggles prayers on/off*/
|
||||||
// /client/proc/toggle_hear_deadcast, /*toggles whether we hear deadchat*/
|
// /client/proc/toggle_hear_deadcast, /*toggles whether we hear deadchat*/
|
||||||
@@ -155,7 +155,8 @@ var/list/admin_verbs_server = list(
|
|||||||
/datum/admins/proc/toggle_space_ninja,
|
/datum/admins/proc/toggle_space_ninja,
|
||||||
/client/proc/toggle_random_events,
|
/client/proc/toggle_random_events,
|
||||||
/client/proc/check_customitem_activity,
|
/client/proc/check_customitem_activity,
|
||||||
/client/proc/nanomapgen_DumpImage
|
/client/proc/nanomapgen_DumpImage,
|
||||||
|
/client/proc/admin_edit_motd
|
||||||
)
|
)
|
||||||
var/list/admin_verbs_debug = list(
|
var/list/admin_verbs_debug = list(
|
||||||
/client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/
|
/client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/
|
||||||
|
|||||||
@@ -183,11 +183,10 @@
|
|||||||
warnings_check()
|
warnings_check()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A proc to alert you if you have unacknowledged warnings.
|
* A proc to gather notifications regarding your warnings.
|
||||||
* Called in /client/New (client procs.dm)
|
* Called by /datum/preferences/proc/gather_notifications() in preferences.dm
|
||||||
*/
|
*/
|
||||||
|
/client/proc/warnings_gather()
|
||||||
/client/proc/warnings_alert()
|
|
||||||
var/count = 0
|
var/count = 0
|
||||||
var/count_expire = 0
|
var/count_expire = 0
|
||||||
|
|
||||||
@@ -210,12 +209,13 @@
|
|||||||
while (query.NextRow())
|
while (query.NextRow())
|
||||||
count++
|
count++
|
||||||
|
|
||||||
|
var/list/data = list("unread" = "", "expired" = "")
|
||||||
if (count)
|
if (count)
|
||||||
src << "<br>"
|
data["unread"] = "You have <b>[count] unread [count > 1 ? "warnings" : "warning"]!</b> Click <a href='?JSlink=warnings;notification=:src_ref'>here</a> to review and acknowledge them!"
|
||||||
src << "<font color=red><b>You have [count] unread [count > 1 ? "warnings" : "warning"]! Click <a href='byond://?src=\ref[src];warnview=1'>here</a> to review and acknowledge them!</b></font>"
|
|
||||||
if (count_expire)
|
if (count_expire)
|
||||||
src << "<br>"
|
data["expired"] = "[count_expire] of your warnings have expired."
|
||||||
src << "<font color=blue><b>[count_expire] of your warnings expired.</b></font>"
|
|
||||||
|
return data
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A proc for an admin/moderator to look up a member's warnings.
|
* A proc for an admin/moderator to look up a member's warnings.
|
||||||
|
|||||||
@@ -135,6 +135,36 @@
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
// JSlink switch.
|
||||||
|
if (href_list["JSlink"])
|
||||||
|
switch (href_list["JSlink"])
|
||||||
|
if ("warnings")
|
||||||
|
src.warnings_check()
|
||||||
|
|
||||||
|
if ("linking")
|
||||||
|
src.check_linking_requests()
|
||||||
|
|
||||||
|
if ("dismiss")
|
||||||
|
if (href_list["notification"])
|
||||||
|
var/datum/client_notification/a = locate(href_list["notification"])
|
||||||
|
if (a && isnull(a.gcDestroyed))
|
||||||
|
a.dismiss()
|
||||||
|
|
||||||
|
if ("github")
|
||||||
|
if (!config.githuburl)
|
||||||
|
src << "<span class='danger'>Github URL not set in the config. Unable to open the site.</span>"
|
||||||
|
else if (alert("This will open the issue tracker in your browser. Are you sure?",, "Yes", "No") == "Yes")
|
||||||
|
src << link(config.githuburl)
|
||||||
|
|
||||||
|
if ("forums")
|
||||||
|
src.forum()
|
||||||
|
|
||||||
|
if ("wiki")
|
||||||
|
src.wiki()
|
||||||
|
|
||||||
|
if ("webint")
|
||||||
|
src.open_webint()
|
||||||
|
|
||||||
..() //redirect to hsrc.()
|
..() //redirect to hsrc.()
|
||||||
|
|
||||||
/client/proc/handle_spam_prevention(var/message, var/mute_type)
|
/client/proc/handle_spam_prevention(var/message, var/mute_type)
|
||||||
@@ -207,6 +237,8 @@
|
|||||||
if(!prefs)
|
if(!prefs)
|
||||||
prefs = new /datum/preferences(src)
|
prefs = new /datum/preferences(src)
|
||||||
preferences_datums[ckey] = prefs
|
preferences_datums[ckey] = prefs
|
||||||
|
|
||||||
|
prefs.gather_notifications(src)
|
||||||
prefs.last_ip = address //these are gonna be used for banning
|
prefs.last_ip = address //these are gonna be used for banning
|
||||||
prefs.last_id = computer_id //these are gonna be used for banning
|
prefs.last_id = computer_id //these are gonna be used for banning
|
||||||
|
|
||||||
@@ -223,18 +255,6 @@
|
|||||||
else
|
else
|
||||||
del(src)
|
del(src)
|
||||||
return 0
|
return 0
|
||||||
else if (byond_version < config.client_warn_version)
|
|
||||||
src << "<span class='danger'><b>Your version of BYOND may be out of date!</b></span>"
|
|
||||||
src << config.client_warn_message
|
|
||||||
src << "Your version: [byond_version]."
|
|
||||||
src << "Required version to remove this message: [config.client_warn_version] or later."
|
|
||||||
src << "Visit http://www.byond.com/download/ to get the latest version of BYOND."
|
|
||||||
|
|
||||||
if(custom_event_msg && custom_event_msg != "")
|
|
||||||
src << "<h1 class='alert'>Custom Event</h1>"
|
|
||||||
src << "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>"
|
|
||||||
src << "<span class='alert'>[custom_event_msg]</span>"
|
|
||||||
src << "<br>"
|
|
||||||
|
|
||||||
if( (world.address == address || !address) && !host )
|
if( (world.address == address || !address) && !host )
|
||||||
host = key
|
host = key
|
||||||
@@ -242,7 +262,6 @@
|
|||||||
|
|
||||||
if(holder)
|
if(holder)
|
||||||
add_admin_verbs()
|
add_admin_verbs()
|
||||||
admin_memo_show()
|
|
||||||
|
|
||||||
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
|
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
|
||||||
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
|
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
|
||||||
@@ -252,20 +271,13 @@
|
|||||||
sleep(2) // wait a bit more, possibly fixes hardware mode not re-activating right
|
sleep(2) // wait a bit more, possibly fixes hardware mode not re-activating right
|
||||||
winset(src, null, "command=\".configure graphics-hwmode on\"")
|
winset(src, null, "command=\".configure graphics-hwmode on\"")
|
||||||
|
|
||||||
warnings_alert()
|
|
||||||
|
|
||||||
check_linking_requests()
|
|
||||||
|
|
||||||
send_resources()
|
send_resources()
|
||||||
nanomanager.send_resources(src)
|
nanomanager.send_resources(src)
|
||||||
|
|
||||||
if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates.
|
var/outdated_greeting_info = server_greeting.find_outdated_info(src)
|
||||||
src << "<span class='info'>You have unread updates in the changelog.</span>"
|
|
||||||
winset(src, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
|
|
||||||
if(config.aggressive_changelog)
|
|
||||||
src.changes()
|
|
||||||
|
|
||||||
|
|
||||||
|
if (outdated_greeting_info)
|
||||||
|
server_greeting.display_to_client(src, outdated_greeting_info)
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
//DISCONNECT//
|
//DISCONNECT//
|
||||||
@@ -384,6 +396,11 @@
|
|||||||
'html/images/loading.gif',
|
'html/images/loading.gif',
|
||||||
'html/images/ntlogo.png',
|
'html/images/ntlogo.png',
|
||||||
'html/images/talisman.png',
|
'html/images/talisman.png',
|
||||||
|
'html/bootstrap/css/bootstrap.min.css',
|
||||||
|
'html/bootstrap/js/bootstrap.min.js',
|
||||||
|
'html/bootstrap/js/html5shiv.min.js',
|
||||||
|
'html/bootstrap/js/respond.min.js',
|
||||||
|
'html/jquery/jquery-2.0.0.min.js',
|
||||||
'icons/pda_icons/pda_atmos.png',
|
'icons/pda_icons/pda_atmos.png',
|
||||||
'icons/pda_icons/pda_back.png',
|
'icons/pda_icons/pda_back.png',
|
||||||
'icons/pda_icons/pda_bell.png',
|
'icons/pda_icons/pda_bell.png',
|
||||||
@@ -424,7 +441,6 @@
|
|||||||
'icons/spideros_icons/sos_14.png'
|
'icons/spideros_icons/sos_14.png'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/mob/proc/MayRespawn()
|
/mob/proc/MayRespawn()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -481,6 +497,23 @@
|
|||||||
src << browse(dat, "window=LinkingRequests")
|
src << browse(dat, "window=LinkingRequests")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/client/proc/gather_linking_requests()
|
||||||
|
if (!config.webint_url || !config.sql_enabled)
|
||||||
|
return
|
||||||
|
|
||||||
|
establish_db_connection(dbcon)
|
||||||
|
if (!dbcon.IsConnected())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/DBQuery/select_query = dbcon.NewQuery("SELECT COUNT(*) AS request_count FROM ss13_player_linking WHERE status = 'new' AND player_ckey = :ckey AND deleted_at IS NULL")
|
||||||
|
select_query.Execute(list(":ckey" = ckey))
|
||||||
|
|
||||||
|
if (select_query.NextRow())
|
||||||
|
if (text2num(select_query.item[1]) > 0)
|
||||||
|
return "You have [select_query.item[1]] account linking requests pending review. Click <a href='?JSlink=linking;notification=:src_ref'>here</a> to see them!"
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
/client/proc/process_webint_link(var/route, var/attributes)
|
/client/proc/process_webint_link(var/route, var/attributes)
|
||||||
if (!route)
|
if (!route)
|
||||||
return
|
return
|
||||||
@@ -523,3 +556,9 @@
|
|||||||
|
|
||||||
src << link(linkURL)
|
src << link(linkURL)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/client/verb/show_greeting()
|
||||||
|
set name = "Open Greeting"
|
||||||
|
set category = "OOC"
|
||||||
|
|
||||||
|
server_greeting.display_to_client(src, server_greeting.find_outdated_info(src))
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ datum/preferences
|
|||||||
var/muted = 0
|
var/muted = 0
|
||||||
var/last_ip
|
var/last_ip
|
||||||
var/last_id
|
var/last_id
|
||||||
|
var/list/notifications = list() //A list of datums, for the dynamic server greeting window.
|
||||||
|
|
||||||
//game-preferences
|
//game-preferences
|
||||||
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
||||||
@@ -50,6 +51,8 @@ datum/preferences
|
|||||||
var/asfx_togs = ASFX_DEFAULT
|
var/asfx_togs = ASFX_DEFAULT
|
||||||
var/UI_style_color = "#ffffff"
|
var/UI_style_color = "#ffffff"
|
||||||
var/UI_style_alpha = 255
|
var/UI_style_alpha = 255
|
||||||
|
var/motd_hash = "" //Hashes for the new server greeting window.
|
||||||
|
var/memo_hash = ""
|
||||||
|
|
||||||
//character preferences
|
//character preferences
|
||||||
var/real_name //our character's name
|
var/real_name //our character's name
|
||||||
|
|||||||
198
code/modules/client/preferences_notification.dm
Normal file
198
code/modules/client/preferences_notification.dm
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* A simple datum for storing notifications for dispaly.
|
||||||
|
*/
|
||||||
|
/datum/client_notification
|
||||||
|
var/datum/preferences/owner = null
|
||||||
|
|
||||||
|
var/list/note_wrapper = list()
|
||||||
|
var/note_text = ""
|
||||||
|
|
||||||
|
var/proc_src = null
|
||||||
|
var/proc_name = ""
|
||||||
|
var/proc_args = null
|
||||||
|
|
||||||
|
var/persistent = 0
|
||||||
|
|
||||||
|
/datum/client_notification/New(var/datum/preferences/prefs, var/list/new_wrapper, var/new_text, var/new_persistence)
|
||||||
|
if (!prefs)
|
||||||
|
qdel(src)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (!new_wrapper || new_wrapper.len != 2)
|
||||||
|
qdel(src)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (!new_text)
|
||||||
|
qdel(src)
|
||||||
|
return
|
||||||
|
|
||||||
|
owner = prefs
|
||||||
|
|
||||||
|
note_wrapper = new_wrapper
|
||||||
|
note_text = new_text
|
||||||
|
|
||||||
|
note_text = replacetextEx(note_text, ":src_ref", "\ref[src]")
|
||||||
|
note_wrapper[1] = replacetextEx(note_wrapper[1], ":src_ref", "\ref[src]")
|
||||||
|
|
||||||
|
if (new_persistence)
|
||||||
|
persistent = new_persistence
|
||||||
|
|
||||||
|
/datum/client_notification/Destroy()
|
||||||
|
if (owner)
|
||||||
|
owner.notifications -= src
|
||||||
|
owner = null
|
||||||
|
|
||||||
|
..()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Associates a callback to be executed whenever a notification is dismissed.
|
||||||
|
*/
|
||||||
|
/datum/client_notification/proc/tie_callback(var/dismiss_proc_src, var/dismiss_proc, var/dismiss_proc_args)
|
||||||
|
if (!dismiss_proc_src || !dismiss_proc)
|
||||||
|
return
|
||||||
|
|
||||||
|
proc_src = dismiss_proc_src
|
||||||
|
proc_name = dismiss_proc
|
||||||
|
|
||||||
|
if (dismiss_proc_args)
|
||||||
|
proc_args = dismiss_proc_args
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the HTML required to display this alert.
|
||||||
|
*/
|
||||||
|
/datum/client_notification/proc/get_html()
|
||||||
|
var/html = "<div class=\"row\">[note_wrapper[1]]\n"
|
||||||
|
|
||||||
|
if (!persistent)
|
||||||
|
html += "<a href=\"#\" class=\"close\" data-dismiss=\"alert\" aria-label=\"close\">×</a>\n"
|
||||||
|
|
||||||
|
html += note_text
|
||||||
|
html += "\n[note_wrapper[2]]</div>"
|
||||||
|
|
||||||
|
return html
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dismisses the notification, executing the proc that was set up as necessary.
|
||||||
|
*/
|
||||||
|
/datum/client_notification/proc/dismiss()
|
||||||
|
if (proc_src && proc_name)
|
||||||
|
call(proc_src, proc_name)(proc_args)
|
||||||
|
|
||||||
|
if (!persistent)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds a new notification datum for later processing.
|
||||||
|
*/
|
||||||
|
/datum/preferences/proc/new_notification(var/type, var/text, var/persistent, var/callback_src, var/callback_proc, var/callback_args)
|
||||||
|
if (!text)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/list/wrapper
|
||||||
|
switch (type)
|
||||||
|
if ("success")
|
||||||
|
wrapper = list("<div class=\"alert alert-success\" notification=\":src_ref\">", "</div>")
|
||||||
|
if ("info")
|
||||||
|
wrapper = list("<div class=\"alert alert-info\" notification=\":src_ref\">", "</div>")
|
||||||
|
if ("warning")
|
||||||
|
wrapper = list("<div class=\"alert alert-warning\" notification=\":src_ref\">", "</div>")
|
||||||
|
if ("danger")
|
||||||
|
wrapper = list("<div class=\"alert alert-danger\" notification=\":src_ref\">", "</div>")
|
||||||
|
else
|
||||||
|
wrapper = list("<div class=\"alert alert-info\" notification=\":src_ref\">", "</div>")
|
||||||
|
|
||||||
|
var/datum/client_notification/note = new(src, wrapper, text, persistent)
|
||||||
|
|
||||||
|
if (callback_src && callback_proc)
|
||||||
|
note.tie_callback(callback_src, callback_proc, callback_args)
|
||||||
|
|
||||||
|
notifications += note
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gathers all notifications relevant to the client.
|
||||||
|
*/
|
||||||
|
/datum/preferences/proc/gather_notifications(var/client/user)
|
||||||
|
if (!user)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (user.byond_version < config.client_warn_version)
|
||||||
|
var/version_warn = ""
|
||||||
|
version_warn += "<b>Your version of BYOND may be out of date!</b><br>"
|
||||||
|
version_warn += config.client_warn_message
|
||||||
|
version_warn += "Your version: [user.byond_version].<br>"
|
||||||
|
version_warn += "Required version to remove this message: [config.client_warn_version] or later.<br>"
|
||||||
|
version_warn += "Visit http://www.byond.com/download/ to get the latest version of BYOND."
|
||||||
|
|
||||||
|
new_notification("danger", version_warn)
|
||||||
|
|
||||||
|
if (custom_event_msg && custom_event_msg != "")
|
||||||
|
var/custom_event_warn = "<b><center>A custom event is taking place!</center></b><br>"
|
||||||
|
custom_event_warn += "<b>OOC Info:</b><br>[custom_event_msg]"
|
||||||
|
|
||||||
|
new_notification("danger", custom_event_warn)
|
||||||
|
|
||||||
|
if (lastchangelog != changelog_hash)
|
||||||
|
winset(user, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
|
||||||
|
if (config.aggressive_changelog)
|
||||||
|
new_notification("info", "You have unread updates in the changelog.", callback_src = user, callback_proc = "changes")
|
||||||
|
else
|
||||||
|
new_notification("info", "You have unread updates in the changelog.")
|
||||||
|
|
||||||
|
if (config.sql_enabled)
|
||||||
|
|
||||||
|
var/list/warnings = user.warnings_gather()
|
||||||
|
if (warnings["unread"])
|
||||||
|
new_notification("danger", warnings["unread"], 1)
|
||||||
|
if (warnings["expired"])
|
||||||
|
new_notification("info", warnings["expired"])
|
||||||
|
|
||||||
|
var/linking = user.gather_linking_requests()
|
||||||
|
if (linking)
|
||||||
|
new_notification("info", linking, callback_src = user, callback_proc = "check_linking_requests")
|
||||||
|
|
||||||
|
var/cciaa_actions = count_ccia_actions(user)
|
||||||
|
if (cciaa_actions)
|
||||||
|
new_notification("info", cciaa_actions)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper proc for getting a count of active CCIA actions against the player's character.
|
||||||
|
*/
|
||||||
|
/datum/preferences/proc/count_ccia_actions(var/client/user)
|
||||||
|
if (!user)
|
||||||
|
return null
|
||||||
|
|
||||||
|
if (!establish_db_connection(dbcon))
|
||||||
|
error("Error initiatlizing database connection while counting CCIA actions.")
|
||||||
|
return null
|
||||||
|
|
||||||
|
var/DBQuery/prep_query = dbcon.NewQuery("SELECT id FROM ss13_characters WHERE ckey = :ckey")
|
||||||
|
prep_query.Execute(list(":ckey" = user.ckey))
|
||||||
|
var/list/chars = list()
|
||||||
|
|
||||||
|
while (prep_query.NextRow())
|
||||||
|
chars += text2num(prep_query.item[1])
|
||||||
|
|
||||||
|
if (!chars.len)
|
||||||
|
return null
|
||||||
|
|
||||||
|
var/DBQuery/query = dbcon.NewQuery({"SELECT
|
||||||
|
COUNT(act_chr.action_id) AS action_count
|
||||||
|
FROM ss13_ccia_action_char act_chr
|
||||||
|
JOIN ss13_characters chr ON act_chr.char_id = chr.id
|
||||||
|
JOIN ss13_ccia_actions act ON act_chr.action_id = act.id
|
||||||
|
WHERE
|
||||||
|
act_chr.char_id IN :char_id AND
|
||||||
|
(act.expires_at IS NULL OR act.expires_at >= CURRENT_DATE()) AND
|
||||||
|
act.deleted_at IS NULL;"})
|
||||||
|
query.Execute(list(":char_id" = chars))
|
||||||
|
|
||||||
|
if (query.NextRow())
|
||||||
|
var/action_count = text2num(query.item[1])
|
||||||
|
|
||||||
|
if (action_count == 0)
|
||||||
|
return null
|
||||||
|
|
||||||
|
var/string = "There are [action_count] active CCIA actions currently active against your character(s)."
|
||||||
|
return string
|
||||||
|
|
||||||
|
return null
|
||||||
@@ -57,10 +57,14 @@
|
|||||||
S["UI_style_color"] >> UI_style_color
|
S["UI_style_color"] >> UI_style_color
|
||||||
S["UI_style_alpha"] >> UI_style_alpha
|
S["UI_style_alpha"] >> UI_style_alpha
|
||||||
S["asfx_togs"] >> asfx_togs
|
S["asfx_togs"] >> asfx_togs
|
||||||
|
S["motd_hash"] >> motd_hash
|
||||||
|
S["memo_hash"] >> memo_hash
|
||||||
|
|
||||||
//Sanitize
|
//Sanitize
|
||||||
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
||||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||||
|
motd_hash = sanitize_text(motd_hash, initial(motd_hash))
|
||||||
|
memo_hash = sanitize_text(memo_hash, initial(memo_hash))
|
||||||
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
|
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
|
||||||
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
|
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
|
||||||
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
|
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
|
||||||
@@ -87,6 +91,8 @@
|
|||||||
S["default_slot"] << default_slot
|
S["default_slot"] << default_slot
|
||||||
S["toggles"] << toggles
|
S["toggles"] << toggles
|
||||||
S["asfx_togs"] << asfx_togs
|
S["asfx_togs"] << asfx_togs
|
||||||
|
S["motd_hash"] << motd_hash
|
||||||
|
S["memo_hash"] << memo_hash
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
UI_style_color,
|
UI_style_color,
|
||||||
UI_style_alpha,
|
UI_style_alpha,
|
||||||
be_special,
|
be_special,
|
||||||
asfx_togs
|
asfx_togs,
|
||||||
|
motd_hash,
|
||||||
|
memo_hash
|
||||||
FROM ss13_player_preferences
|
FROM ss13_player_preferences
|
||||||
WHERE ckey = :ckey"})
|
WHERE ckey = :ckey"})
|
||||||
query.Execute(list(":ckey" = C.ckey))
|
query.Execute(list(":ckey" = C.ckey))
|
||||||
@@ -28,10 +30,14 @@
|
|||||||
UI_style_alpha = text2num(query.item[7])
|
UI_style_alpha = text2num(query.item[7])
|
||||||
be_special = text2num(query.item[8])
|
be_special = text2num(query.item[8])
|
||||||
asfx_togs = text2num(query.item[9])
|
asfx_togs = text2num(query.item[9])
|
||||||
|
motd_hash = query.item[10]
|
||||||
|
memo_hash = query.item[11]
|
||||||
|
|
||||||
//Sanitize
|
//Sanitize
|
||||||
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
||||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||||
|
motd_hash = sanitize_text(motd_hash, initial(motd_hash))
|
||||||
|
memo_hash = sanitize_text(memo_hash, initial(memo_hash))
|
||||||
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
|
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
|
||||||
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
|
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
|
||||||
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
|
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
|
||||||
@@ -61,7 +67,9 @@
|
|||||||
UI_style_color = :ui_color,
|
UI_style_color = :ui_color,
|
||||||
UI_style_alpha = :ui_alpha,
|
UI_style_alpha = :ui_alpha,
|
||||||
be_special = :be_special,
|
be_special = :be_special,
|
||||||
asfx_togs = :asfx_togs
|
asfx_togs = :asfx_togs,
|
||||||
|
motd_hash = :motd_hash,
|
||||||
|
memo_hash = :memo_hash
|
||||||
WHERE ckey = :ckey"})
|
WHERE ckey = :ckey"})
|
||||||
update_query.Execute(get_prefs_update_insert_params(C))
|
update_query.Execute(get_prefs_update_insert_params(C))
|
||||||
|
|
||||||
@@ -71,8 +79,8 @@
|
|||||||
if (!C)
|
if (!C)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
var/DBQuery/query = dbcon.NewQuery({"INSERT INTO ss13_player_preferences (ckey, ooccolor, lastchangelog, UI_style, current_character, toggles, UI_style_color, UI_style_alpha, be_special, asfx_togs)
|
var/DBQuery/query = dbcon.NewQuery({"INSERT INTO ss13_player_preferences (ckey, ooccolor, lastchangelog, UI_style, current_character, toggles, UI_style_color, UI_style_alpha, be_special, asfx_togs, motd_hash, memo_hash)
|
||||||
VALUES (:ckey, :ooccolor, :lastchangelog, :ui_style, :current_character, :toggles, :ui_color, :ui_alpha, :be_special, :asfx_togs);"})
|
VALUES (:ckey, :ooccolor, :lastchangelog, :ui_style, :current_character, :toggles, :ui_color, :ui_alpha, :be_special, :asfx_togs, :motd_hash, :memo_hash);"})
|
||||||
query.Execute(get_prefs_update_insert_params(C))
|
query.Execute(get_prefs_update_insert_params(C))
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
@@ -92,6 +100,8 @@
|
|||||||
params[":ui_alpha"] = UI_style_alpha
|
params[":ui_alpha"] = UI_style_alpha
|
||||||
params[":be_special"] = be_special
|
params[":be_special"] = be_special
|
||||||
params[":asfx_togs"] = asfx_togs
|
params[":asfx_togs"] = asfx_togs
|
||||||
|
params[":motd_hash"] = motd_hash
|
||||||
|
params[":memo_hash"] = memo_hash
|
||||||
|
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/mob/new_player/Login()
|
/mob/new_player/Login()
|
||||||
update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying
|
update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying
|
||||||
if(join_motd)
|
|
||||||
src << "<div class=\"motd\">[join_motd]</div>"
|
|
||||||
|
|
||||||
if(!mind)
|
if(!mind)
|
||||||
mind = new /datum/mind(key)
|
mind = new /datum/mind(key)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* /proc/webint_start_singlesignon()
|
* /proc/webint_start_singlesignon()
|
||||||
* Used to insert a token into the web_sso database and to enable a user to navigate to a page on the website and be automatically logged in. Hashes the user's save file for a unique token. Additional security managed on the website's end.
|
* Used to insert a token into the web_sso database and to enable a user to navigate to a page on the website and be automatically logged in. Generates a hash algorithmically. Additional security managed on the website's end.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* - var/user - Must be a mob or a client. The player object that's going to be using the request.
|
* - var/user - Must be a mob or a client. The player object that's going to be using the request.
|
||||||
|
|||||||
@@ -522,12 +522,12 @@ var/world_topic_spam_protect_time = world.timeofday
|
|||||||
F << the_mode
|
F << the_mode
|
||||||
|
|
||||||
|
|
||||||
/hook/startup/proc/loadMOTD()
|
/hook/startup/proc/initialize_greeting()
|
||||||
world.load_motd()
|
world.initialize_greeting()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
/world/proc/load_motd()
|
/world/proc/initialize_greeting()
|
||||||
join_motd = file2text("config/motd.txt")
|
server_greeting = new()
|
||||||
|
|
||||||
|
|
||||||
/proc/load_configuration()
|
/proc/load_configuration()
|
||||||
|
|||||||
6
html/bootstrap/css/bootstrap-theme.min.css
vendored
Normal file
6
html/bootstrap/css/bootstrap-theme.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
html/bootstrap/css/bootstrap.min.css
vendored
Normal file
6
html/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
html/bootstrap/js/bootstrap.min.js
vendored
Normal file
7
html/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
html/bootstrap/js/html5shiv.min.js
vendored
Normal file
4
html/bootstrap/js/html5shiv.min.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||||
|
*/
|
||||||
|
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);
|
||||||
5
html/bootstrap/js/respond.min.js
vendored
Normal file
5
html/bootstrap/js/respond.min.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||||
|
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||||
|
* */
|
||||||
|
|
||||||
|
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||||
13
html/changelogs/skull132-greeting.yml
Normal file
13
html/changelogs/skull132-greeting.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
author: Skull132
|
||||||
|
|
||||||
|
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||||
|
delete-after: True
|
||||||
|
|
||||||
|
# Any changes you've made. See valid prefix list above.
|
||||||
|
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||||
|
# SCREW THIS UP AND IT WON'T WORK.
|
||||||
|
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||||
|
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||||
|
changes:
|
||||||
|
- rscadd: "Added a new \"Server Greeting\" system to replace the massive garbled dump of info people get in the lower right panel. Coloured tabs indicated things that need attention. The window can be opened from the OOC tab as well, via the \"Open Greeting\" button."
|
||||||
|
- rscadd: "Admins (with R_SERVER flag) can now edit the message of the day from within the game, with the \"Edit MotD\" button in the Server tab. Memos can be edited by any admin from the \"Edit Memo\" button in the same tab."
|
||||||
6
html/jquery/jquery-2.0.0.min.js
vendored
Normal file
6
html/jquery/jquery-2.0.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
99
html/templates/welcome_screen.html
Normal file
99
html/templates/welcome_screen.html
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Aurorastation Welcome Screen</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- Bootstrap -->
|
||||||
|
<link href="bootstrap.min.css" rel="stylesheet" media="screen">
|
||||||
|
<style media="screen">
|
||||||
|
.nav-tabs>li.updated>a, .nav-tabs>li.updated>a:hover, .nav-tabs>li.updated>a:focus {
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<nav>
|
||||||
|
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||||
|
<li role="presentation" class="active" id="home-tab"><a href="#home" aria-controls="home" role="tab" data-toggle="tab">Home</a></li>
|
||||||
|
<li role="presentation" id="motd-tab"><a href="#motd" aria-controls="motd" role="tab" data-toggle="tab">Announcements</a></li>
|
||||||
|
<li role="presentation" id="memo-tab"><a href="#memo" aria-controls="memo" role="tab" data-toggle="tab">Staff Memos</a></li>
|
||||||
|
<li role="presentation" id="note-tab"><a href="#note" aria-controls="note" role="tab" data-toggle="tab">Notifications</a></li>
|
||||||
|
<li role="presentation"><a href="#webint">My Profile</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="tab-content">
|
||||||
|
<div role="tabpanel" class="tab-pane active" id="home">
|
||||||
|
<!-- Don't forget to update the JSlink switch in client/Topic if you edit this! -->
|
||||||
|
<center>
|
||||||
|
<h1>Welcome to Aurorastation!</h1>
|
||||||
|
</center>
|
||||||
|
<p>
|
||||||
|
Aurorastation is a SS13 heavy roleplay server with antagonists enabled, that's been running since 2013. We utilize a customized build of the Baystation12 codebase, which can be found <a href="?JSlink=github">here, on Github.</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
New players should take care to read <a href="?JSlink=rules">the rules.</a> Specially if you're new to roleplay. Should any questions arise, you are expected to adminhelp (F1) them and ask!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Further information about the server can be found at the following places:
|
||||||
|
<br>
|
||||||
|
<ul>
|
||||||
|
<li><a href="?JSlink=forums">The forums</a> - For whitelist applications, announcements, general discussion, etcetera.</li>
|
||||||
|
<li><a href="?JSlink=wiki">The wiki</a> - Primarily for lore reference, and gameplay guides. Note that the Baystation12 wiki linked there can be referenced for general mechanics.</li>
|
||||||
|
<li><a href="?JSlink=webint">The web-interface</a> - A custom website which adds additional functionality to the game. Anything from syndicate contracts, to reviewing your whitelists, bans, etcetera.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="motd"><!--motd--></div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="memo"><!--memo--></div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="note"><!--note--></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script src="jquery-2.0.0.min.js"></script>
|
||||||
|
<script src="bootstrap.min.js"></script>
|
||||||
|
<script src="html5shiv.min.js"></script>
|
||||||
|
<script src="respond.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
// Deal with updating the tabs if any need an updated marker.
|
||||||
|
var updated_tabs = [];
|
||||||
|
|
||||||
|
if (updated_tabs.length > 0) {
|
||||||
|
var changes_needed = updated_tabs.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < changes_needed; i++) {
|
||||||
|
$(updated_tabs[i]).addClass('updated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle tabs (mostly bootstrap).
|
||||||
|
$('#myTab a').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// One special exception for the web interface.
|
||||||
|
if ($(this).attr('href') == '#webint') {
|
||||||
|
window.location = '?routeWebInt=interface/login/sso_server;routeAttributes=location=user_dashboard;';
|
||||||
|
} else {
|
||||||
|
$(this).tab('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle clicking of updated classes.
|
||||||
|
if ($(this).parent().hasClass('updated') == 1) {
|
||||||
|
$(this).parent().removeClass('updated');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Dismiss an alert properly.
|
||||||
|
$('.alert').on('close.bs.alert', function () {
|
||||||
|
var command = '?JSlink=dismiss;notification=' + $(this).attr('notification');
|
||||||
|
window.location = command;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user