diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm
index 018d6a7449e..02cdbd11be5 100644
--- a/code/controllers/subsystem/jobs.dm
+++ b/code/controllers/subsystem/jobs.dm
@@ -621,6 +621,8 @@ SUBSYSTEM_DEF(jobs)
for(var/datum/job/job in occupations)
if(tgtcard.assignment && tgtcard.assignment == job.title)
jobs_to_formats[job.title] = "green" // the job they already have is pre-selected
+ else if(tgtcard.assignment == "Demoted" || tgtcard.assignment == "Terminated")
+ jobs_to_formats[job.title] = "grey"
else if(!job.would_accept_job_transfer_from_player(M))
jobs_to_formats[job.title] = "grey" // jobs which are karma-locked and not unlocked for this player are discouraged
else if((job.title in GLOB.command_positions) && istype(M) && M.client && job.available_in_playtime(M.client))
@@ -629,12 +631,21 @@ SUBSYSTEM_DEF(jobs)
jobs_to_formats[job.title] = "teal" // jobs with nobody doing them at all are encouraged
else if(job.total_positions >= 0 && job.current_positions >= job.total_positions)
jobs_to_formats[job.title] = "grey" // jobs that are full (no free positions) are discouraged
+ if(tgtcard.assignment == "Demoted" || tgtcard.assignment == "Terminated")
+ jobs_to_formats["Custom"] = "grey"
return jobs_to_formats
-/datum/controller/subsystem/jobs/proc/log_job_transfer(transferee, oldvalue, newvalue, whodidit)
- id_change_records["[id_change_counter]"] = list("transferee" = transferee, "oldvalue" = oldvalue, "newvalue" = newvalue, "whodidit" = whodidit, "timestamp" = station_time_timestamp())
+/datum/controller/subsystem/jobs/proc/log_job_transfer(transferee, oldvalue, newvalue, whodidit, reason)
+ id_change_records["[id_change_counter]"] = list(
+ "transferee" = transferee,
+ "oldvalue" = oldvalue,
+ "newvalue" = newvalue,
+ "whodidit" = whodidit,
+ "timestamp" = station_time_timestamp(),
+ "reason" = reason
+ )
id_change_counter++
/datum/controller/subsystem/jobs/proc/slot_job_transfer(oldtitle, newtitle)
@@ -667,43 +678,6 @@ SUBSYSTEM_DEF(jobs)
PM.notify("Automated Notification: \"[antext]\" (Unable to Reply)")
-/datum/controller/subsystem/jobs/proc/fetch_transfer_record_html(var/centcom)
- var/record_html = "
"
-
- var/table_headers = list("Crewman", "Old Rank", "New Rank", "Authorized By", "Time")
- var/hidden_fields = list("deletedby")
- if(centcom)
- table_headers += "Deleted By"
- record_html += ""
- for(var/thisheader in table_headers)
- record_html += "| [thisheader] | "
- record_html += "
"
-
- var/visible_record_count = 0
- for(var/thisid in id_change_records)
- var/thisrecord = id_change_records[thisid]
-
- if(thisrecord["deletedby"] && !centcom)
- continue
-
- record_html += ""
- for(var/lkey in thisrecord)
- if(lkey in hidden_fields)
- if(centcom)
- record_html += "| [thisrecord[lkey]] | "
- else
- continue
- else
- record_html += "[thisrecord[lkey]] | "
- record_html += "
"
- visible_record_count++
-
- record_html += "
"
-
- if(!visible_record_count)
- return "No records on file yet."
- return record_html
-
/datum/controller/subsystem/jobs/proc/format_job_change_records(centcom)
var/list/formatted = list()
for(var/thisid in id_change_records)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 089cea4212a..76f2b18eaf9 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -292,13 +292,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
// RECORDS
if(is_authenticated(user))
data["records"] = SSjobs.format_job_change_records(data["iscentcom"])
- if(4)
- // WIP REMOTE DEMOTE FUNCTION -- TODO
- var/list/titles_supervised = get_subordinates(scan.assignment, FALSE)
- data["mypeople"] = list()
- for(var/datum/data/record/R in GLOB.data_core.security)
- if(R.fields["rank"] in titles_supervised)
- data["mypeople"] += R.fields["name"]
return data
/obj/machinery/computer/card/proc/regenerate_id_name()
@@ -387,9 +380,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/temp_t = sanitize(reject_bad_name(copytext(input("Enter a custom job assignment.", "Assignment"), 1, MAX_MESSAGE_LEN), TRUE))
//let custom jobs function as an impromptu alt title, mainly for sechuds
if(temp_t && scan && modify)
- SSjobs.log_job_transfer(modify.registered_name, modify.getRankAndAssignment(), temp_t, scan.registered_name)
+ var/oldrank = modify.getRankAndAssignment()
+ SSjobs.log_job_transfer(modify.registered_name, oldrank, temp_t, scan.registered_name, null)
modify.assignment = temp_t
- log_game("[key_name(usr)] has given \"[modify.registered_name]\" the custom job title \"[temp_t]\".")
+ log_game("[key_name(usr)] has reassigned \"[modify.registered_name]\" from \"[oldrank]\" to \"[temp_t]\".")
+ SSjobs.notify_dept_head(modify.rank, "[scan.registered_name] has transferred \"[modify.registered_name]\" the \"[oldrank]\" to \"[temp_t]\".")
else
var/list/access = list()
if(is_centcom() && islist(get_centcom_access(t1)))
@@ -412,7 +407,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(t1 == "Civilian")
message_admins("[key_name_admin(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
- SSjobs.log_job_transfer(modify.registered_name, jobnamedata, t1, scan.registered_name)
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, t1, scan.registered_name, null)
+ SSjobs.notify_dept_head(t1, "[scan.registered_name] has transferred \"[modify.registered_name]\" the \"[jobnamedata]\" to \"[t1]\".")
if(modify.owner_uid)
SSjobs.slot_job_transfer(modify.rank, t1)
@@ -448,13 +444,14 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" [m_ckey_text] to \"Civilian (Demoted)\" for: \"[reason]\".")
message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" [m_ckey_text] to \"Civilian (Demoted)\" for: \"[reason]\".")
usr.create_log(MISC_LOG, "demoted \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\"")
- SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Demoted", scan.registered_name)
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Demoted", scan.registered_name, reason)
SSjobs.notify_dept_head(modify.rank, "[scan.registered_name] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" for \"[reason]\".")
modify.access = access
modify.rank = "Civilian"
modify.assignment = "Demoted"
modify.icon_state = "id"
regenerate_id_name()
+ return
if("make_job_available")
// MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS
if(is_authenticated(usr))
@@ -467,7 +464,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
to_chat(usr, "Job does not exist")
return 0
if(can_open_job(j) != 1)
- to_chat(usr, "Job cannot be opened. [retcode]")
+ to_chat(usr, "Job cannot be opened.")
return 0
if(opened_positions[edit_job_target] >= 0)
GLOB.time_last_changed_position = world.time / 10
@@ -475,7 +472,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
opened_positions[edit_job_target]++
log_game("[key_name(usr)] has opened a job slot for job \"[j]\".")
message_admins("[key_name_admin(usr)] has opened a job slot for job \"[j.title]\".")
-
+ return
if("make_job_unavailable")
// MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS
var/edit_job_target = params["job"]
@@ -493,6 +490,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
opened_positions[edit_job_target]--
log_game("[key_name(usr)] has closed a job slot for job \"[j]\".")
message_admins("[key_name_admin(usr)] has closed a job slot for job \"[j.title]\".")
+ return
// Everything below here requires a full ID computer (dept consoles do not qualify)
if(target_dept)
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
@@ -587,7 +585,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\" for: \"[reason]\".")
message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\" for: \"[reason]\".")
usr.create_log(MISC_LOG, "terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\"")
- SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Terminated", scan.registered_name)
+ SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Terminated", scan.registered_name, reason)
SSjobs.notify_dept_head(modify.rank, "[scan.registered_name] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\" for \"[reason]\".")
modify.assignment = "Terminated"
modify.access = list()
diff --git a/tgui/packages/tgui/interfaces/CardComputer.js b/tgui/packages/tgui/interfaces/CardComputer.js
index 53b8db7cd6e..f939a762cf7 100644
--- a/tgui/packages/tgui/interfaces/CardComputer.js
+++ b/tgui/packages/tgui/interfaces/CardComputer.js
@@ -93,10 +93,18 @@ export const CardComputer = (props, context) => {
onClick={() => act("assign", { assign_target: v })} />
))}
+
+
@@ -109,14 +117,18 @@ export const CardComputer = (props, context) => {
-
+
+
+
+
+ Title
+ Used Slots
+ Total Slots
+ Free Slots
+ Close Slot
+ Open Slot
+ Priority
+
{data.job_slots.map(slotData => (
-
- {slotData.current_positions}/{slotData.total_positions}
- act("make_job_unavailable",
- { job: slotData.title })} />
- act("make_job_available",
- { job: slotData.title })} />
- {data.target_dept && (
-
- { data.priority_jobs.indexOf(slotData.title) > -1
- ? "Priorized Job"
- : ""}
-
- ) || (
+
+ {slotData.title}
+ {slotData.current_positions}
+ {slotData.total_positions}
+
+ {slotData.total_positions > slotData.current_positions && (
+
+ {slotData.total_positions - slotData.current_positions}
+
+ ) || (
+
+ 0
+
+ )}
+
+
-1
- }
- disabled={
- data.cooldown_time || !slotData.can_prioritize
- }
- onClick={() => act("prioritize_job",
+ content="-"
+ disabled={data.cooldown_time || !slotData.can_close}
+ onClick={() => act("make_job_unavailable",
{ job: slotData.title })} />
- )}
-
+
+
+ act("make_job_available",
+ { job: slotData.title })} />
+
+
+ {data.target_dept && (
+
+ {data.priority_jobs.indexOf(slotData.title) > -1
+ ? "Yes"
+ : ""}
+
+ ) || (
+ -1
+ }
+ disabled={
+ data.cooldown_time || !slotData.can_prioritize
+ }
+ onClick={() => act("prioritize_job",
+ { job: slotData.title })} />
+ )}
+
+
))}
-
+
);
@@ -312,7 +354,7 @@ export const CardComputer = (props, context) => {
);
} else if (!data.modify_name) {
bodyBlock = (
-
+
);
@@ -342,6 +384,12 @@ export const CardComputer = (props, context) => {
Not logged in.
);
+ } else if (!data.records.length) {
+ bodyBlock = (
+
+ );
} else {
bodyBlock = (
{
New Rank
Authorized By
Time
+ Reason
{!!data.iscentcom && (
Deleted By
@@ -373,6 +422,7 @@ export const CardComputer = (props, context) => {
{record.newvalue}
{record.whodidit}
{record.timestamp}
+ {record.reason}
{!!data.iscentcom && (
{record.deletedby}