mirror of
https://github.com/quotefox/Hyper-Station-13.git
synced 2026-08-29 07:36:16 +01:00
messy reimplementation of missing Ntos modules
for some reason we were missing a bunch of .js files for various Ntos apps. i painstakingly readded and refactored them by copying them over from the tgstation codebase and editing them.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
usage_flags = PROGRAM_CONSOLE
|
||||
transfer_access = ACCESS_HEADS
|
||||
available_on_ntnet = 1
|
||||
tgui_id = "ntos_ai_restorer"
|
||||
tgui_id = "NtosAiRestorer"
|
||||
ui_x = 600
|
||||
ui_y = 400
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = 1
|
||||
network_destination = "alarm monitoring network"
|
||||
size = 5
|
||||
tgui_id = "ntos_station_alert"
|
||||
tgui_id = "NtosStationAlertConsole"
|
||||
ui_x = 315
|
||||
ui_y = 500
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = 1
|
||||
available_on_ntnet = 0
|
||||
available_on_syndinet = 1
|
||||
tgui_id = "ntos_net_dos"
|
||||
tgui_id = "NtosNetDos"
|
||||
ui_style = "syndicate"
|
||||
ui_x = 400
|
||||
ui_y = 250
|
||||
@@ -80,17 +80,8 @@
|
||||
else if(target && executed)
|
||||
data["target"] = 1
|
||||
data["speed"] = dos_speed
|
||||
|
||||
// This is mostly visual, generate some strings of 1s and 0s
|
||||
// Probability of 1 is equal of completion percentage of DoS attack on this relay.
|
||||
// Combined with UI updates this adds quite nice effect to the UI
|
||||
var/percentage = target.dos_overload * 100 / target.dos_capacity
|
||||
data["dos_strings"] = list()
|
||||
for(var/j, j<10, j++)
|
||||
var/string = ""
|
||||
for(var/i, i<20, i++)
|
||||
string = "[string][prob(percentage)]"
|
||||
data["dos_strings"] += list(list("nums" = string))
|
||||
data["overload"] = target.dos_overload
|
||||
data["capacity"] = target.dos_capacity
|
||||
else
|
||||
data["relays"] = list()
|
||||
for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = 0
|
||||
available_on_ntnet = 0
|
||||
available_on_syndinet = 1
|
||||
tgui_id = "ntos_revelation"
|
||||
tgui_id = "NtosRevelation"
|
||||
ui_style = "syndicate"
|
||||
ui_x = 400
|
||||
ui_y = 250
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
transfer_access = ACCESS_HEADS
|
||||
requires_ntnet = 0
|
||||
size = 8
|
||||
tgui_id = "ntos_card"
|
||||
tgui_id = "NtosCard"
|
||||
ui_x = 600
|
||||
ui_y = 700
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/show_assignments = 0
|
||||
var/minor = 0
|
||||
var/authenticated = 0
|
||||
var/list/reg_ids = list()
|
||||
var/reg_ids = 1
|
||||
var/list/region_access = null
|
||||
var/list/head_subordinates = null
|
||||
var/target_dept = 0 //Which department this computer has access to. 0=all departments
|
||||
@@ -94,6 +94,134 @@
|
||||
|
||||
return formatted
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
var/obj/item/computer_hardware/printer/printer
|
||||
|
||||
if(computer)
|
||||
card_slot = computer.all_components[MC_CARD]
|
||||
printer = computer.all_components[MC_PRINT]
|
||||
|
||||
data["mmode"] = mod_mode
|
||||
|
||||
var/authed = 0
|
||||
if(computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/auth_card = card_slot.stored_card2
|
||||
data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
|
||||
authed = authorized()
|
||||
|
||||
|
||||
if(mod_mode == 2)
|
||||
data["slots"] = list()
|
||||
var/list/pos = list()
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(job.title in blacklisted)
|
||||
continue
|
||||
|
||||
var/list/status_open = build_manage(job,1)
|
||||
var/list/status_close = build_manage(job,0)
|
||||
|
||||
pos.Add(list(list(
|
||||
"title" = job.title,
|
||||
"current" = job.current_positions,
|
||||
"total" = job.total_positions,
|
||||
"status_open" = (authed && !minor) ? status_open["enable"]: 0,
|
||||
"status_close" = (authed && !minor) ? status_close["enable"] : 0,
|
||||
"desc_open" = status_open["desc"],
|
||||
"desc_close" = status_close["desc"])))
|
||||
data["slots"] = pos
|
||||
|
||||
data["src"] = "[REF(src)]"
|
||||
|
||||
|
||||
if(!mod_mode)
|
||||
data["manifest"] = list()
|
||||
var/list/crew = list()
|
||||
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
|
||||
crew.Add(list(list(
|
||||
"name" = t.fields["name"],
|
||||
"rank" = t.fields["rank"])))
|
||||
|
||||
data["manifest"] = crew
|
||||
data["assignments"] = show_assignments
|
||||
if(computer)
|
||||
data["have_id_slot"] = !!card_slot
|
||||
data["have_printer"] = !!printer
|
||||
if(!card_slot && mod_mode == 1)
|
||||
mod_mode = 0 //We can't modify IDs when there is no card reader
|
||||
else
|
||||
data["have_id_slot"] = 0
|
||||
data["have_printer"] = 0
|
||||
|
||||
data["authenticated"] = authed
|
||||
|
||||
if(mod_mode == 1 && computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
|
||||
data["has_id"] = !!id_card
|
||||
data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned"
|
||||
data["id_owner"] = id_card && id_card.registered_name ? html_encode(id_card.registered_name) : "-----"
|
||||
data["id_name"] = id_card ? strip_html_simple(id_card.name) : "-----"
|
||||
|
||||
if(card_slot.stored_card)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
|
||||
if(is_centcom)
|
||||
var/list/all_centcom_access = list()
|
||||
for(var/access in get_all_centcom_access())
|
||||
all_centcom_access.Add(list(list(
|
||||
"desc" = replacetext(get_centcom_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
data["all_centcom_access"] = all_centcom_access
|
||||
else
|
||||
var/list/accesses = list()
|
||||
for(var/access in get_region_accesses(reg_ids))
|
||||
if (get_access_desc(access))
|
||||
accesses.Add(list(list(
|
||||
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
|
||||
var/list/regions = list()
|
||||
for(var/i = 1; i <= 7; i++)
|
||||
if((minor || target_dept) && !(i in region_access))
|
||||
continue
|
||||
|
||||
regions.Add(list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"selected" = (reg_ids == i) ? 1 : null,
|
||||
"accesses" = (reg_ids == i) ? accesses : null)))
|
||||
data["regions"] = regions
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["station_name"] = station_name()
|
||||
data["centcom_access"] = is_centcom
|
||||
data["minor"] = target_dept || minor ? TRUE : FALSE
|
||||
|
||||
if(authenticated)
|
||||
data["engineering_jobs"] = format_jobs(GLOB.engineering_positions)
|
||||
data["medical_jobs"] = format_jobs(GLOB.medical_positions)
|
||||
data["science_jobs"] = format_jobs(GLOB.science_positions)
|
||||
data["security_jobs"] = format_jobs(GLOB.security_positions)
|
||||
data["cargo_jobs"] = format_jobs(GLOB.supply_positions)
|
||||
data["civilian_jobs"] = format_jobs(GLOB.civilian_positions)
|
||||
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
@@ -127,11 +255,6 @@
|
||||
mod_mode = 0
|
||||
else if (params["target"] == "manage")
|
||||
mod_mode = 2
|
||||
if("PRG_togglea")
|
||||
if(show_assignments)
|
||||
show_assignments = 0
|
||||
else
|
||||
show_assignments = 1
|
||||
if("PRG_print")
|
||||
if(computer && printer) //This option should never be called if there is no printer
|
||||
if(mod_mode)
|
||||
@@ -270,13 +393,8 @@
|
||||
j.total_positions--
|
||||
opened_positions[edit_job_target]--
|
||||
if("PRG_regsel")
|
||||
if(!reg_ids)
|
||||
reg_ids = list()
|
||||
var/regsel = text2num(params["region"])
|
||||
if(regsel in reg_ids)
|
||||
reg_ids -= regsel
|
||||
else
|
||||
reg_ids += regsel
|
||||
reg_ids = regsel
|
||||
|
||||
if(id_card)
|
||||
id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])")
|
||||
@@ -290,133 +408,6 @@
|
||||
/datum/computer_file/program/card_mod/proc/apply_access(obj/item/card/id/id_card, list/accesses)
|
||||
id_card.access |= accesses
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_data(mob/user)
|
||||
|
||||
var/list/data = get_header_data()
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
var/obj/item/computer_hardware/printer/printer
|
||||
|
||||
if(computer)
|
||||
card_slot = computer.all_components[MC_CARD]
|
||||
printer = computer.all_components[MC_PRINT]
|
||||
|
||||
data["mmode"] = mod_mode
|
||||
|
||||
var/authed = 0
|
||||
if(computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/auth_card = card_slot.stored_card2
|
||||
data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
|
||||
authed = authorized()
|
||||
|
||||
|
||||
if(mod_mode == 2)
|
||||
data["slots"] = list()
|
||||
var/list/pos = list()
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(job.title in blacklisted)
|
||||
continue
|
||||
|
||||
var/list/status_open = build_manage(job,1)
|
||||
var/list/status_close = build_manage(job,0)
|
||||
|
||||
pos.Add(list(list(
|
||||
"title" = job.title,
|
||||
"current" = job.current_positions,
|
||||
"total" = job.total_positions,
|
||||
"status_open" = (authed && !minor) ? status_open["enable"]: 0,
|
||||
"status_close" = (authed && !minor) ? status_close["enable"] : 0,
|
||||
"desc_open" = status_open["desc"],
|
||||
"desc_close" = status_close["desc"])))
|
||||
data["slots"] = pos
|
||||
|
||||
data["src"] = "[REF(src)]"
|
||||
data["station_name"] = station_name()
|
||||
|
||||
|
||||
if(!mod_mode)
|
||||
data["manifest"] = list()
|
||||
var/list/crew = list()
|
||||
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
|
||||
crew.Add(list(list(
|
||||
"name" = t.fields["name"],
|
||||
"rank" = t.fields["rank"])))
|
||||
|
||||
data["manifest"] = crew
|
||||
data["assignments"] = show_assignments
|
||||
if(computer)
|
||||
data["have_id_slot"] = !!card_slot
|
||||
data["have_printer"] = !!printer
|
||||
if(!card_slot && mod_mode == 1)
|
||||
mod_mode = 0 //We can't modify IDs when there is no card reader
|
||||
else
|
||||
data["have_id_slot"] = 0
|
||||
data["have_printer"] = 0
|
||||
|
||||
data["centcom_access"] = is_centcom
|
||||
|
||||
|
||||
data["authenticated"] = authed
|
||||
|
||||
|
||||
if(mod_mode == 1 && computer)
|
||||
if(card_slot)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
|
||||
data["has_id"] = !!id_card
|
||||
data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned"
|
||||
data["id_owner"] = id_card && id_card.registered_name ? html_encode(id_card.registered_name) : "-----"
|
||||
data["id_name"] = id_card ? strip_html_simple(id_card.name) : "-----"
|
||||
|
||||
if(show_assignments)
|
||||
data["engineering_jobs"] = format_jobs(GLOB.engineering_positions)
|
||||
data["medical_jobs"] = format_jobs(GLOB.medical_positions)
|
||||
data["science_jobs"] = format_jobs(GLOB.science_positions)
|
||||
data["security_jobs"] = format_jobs(GLOB.security_positions)
|
||||
data["cargo_jobs"] = format_jobs(GLOB.supply_positions)
|
||||
data["civilian_jobs"] = format_jobs(GLOB.civilian_positions)
|
||||
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
|
||||
|
||||
|
||||
if(card_slot.stored_card)
|
||||
var/obj/item/card/id/id_card = card_slot.stored_card
|
||||
if(is_centcom)
|
||||
var/list/all_centcom_access = list()
|
||||
for(var/access in get_all_centcom_access())
|
||||
all_centcom_access.Add(list(list(
|
||||
"desc" = replacetext(get_centcom_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
data["all_centcom_access"] = all_centcom_access
|
||||
else
|
||||
var/list/regions = list()
|
||||
for(var/i = 1; i <= 7; i++)
|
||||
if((minor || target_dept) && !(i in region_access))
|
||||
continue
|
||||
|
||||
var/list/accesses = list()
|
||||
if(i in reg_ids)
|
||||
for(var/access in get_region_accesses(i))
|
||||
if (get_access_desc(access))
|
||||
accesses.Add(list(list(
|
||||
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||
|
||||
regions.Add(list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"selected" = (i in reg_ids) ? 1 : null,
|
||||
"accesses" = accesses)))
|
||||
data["regions"] = regions
|
||||
|
||||
data["minor"] = target_dept || minor ? 1 : 0
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/datum/computer_file/program/card_mod/proc/build_manage(datum/job,open = FALSE)
|
||||
var/out = "Denied"
|
||||
var/can_change= 0
|
||||
|
||||
@@ -7,10 +7,7 @@
|
||||
requires_ntnet = 0
|
||||
available_on_ntnet = 0
|
||||
undeletable = 1
|
||||
tgui_id = "ntos_file_manager"
|
||||
|
||||
var/open_file
|
||||
var/error
|
||||
tgui_id = "NtosFileManager"
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_act(action, params)
|
||||
if(..())
|
||||
@@ -18,23 +15,8 @@
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/hard_drive/RHDD = computer.all_components[MC_SDD]
|
||||
var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
|
||||
|
||||
switch(action)
|
||||
if("PRG_openfile")
|
||||
. = 1
|
||||
open_file = params["name"]
|
||||
if("PRG_newtextfile")
|
||||
. = 1
|
||||
var/newname = stripped_input(usr, "Enter file name or leave blank to cancel:", "File rename", max_length=50)
|
||||
if(!newname)
|
||||
return 1
|
||||
if(!HDD)
|
||||
return 1
|
||||
var/datum/computer_file/data/F = new/datum/computer_file/data()
|
||||
F.filename = newname
|
||||
F.filetype = "TXT"
|
||||
HDD.store_file(F)
|
||||
if("PRG_deletefile")
|
||||
. = 1
|
||||
if(!HDD)
|
||||
@@ -51,19 +33,6 @@
|
||||
if(!file || file.undeletable)
|
||||
return 1
|
||||
RHDD.remove_file(file)
|
||||
if("PRG_closefile")
|
||||
. = 1
|
||||
open_file = null
|
||||
error = null
|
||||
if("PRG_clone")
|
||||
. = 1
|
||||
if(!HDD)
|
||||
return 1
|
||||
var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
var/datum/computer_file/C = F.clone(1)
|
||||
HDD.store_file(C)
|
||||
if("PRG_rename")
|
||||
. = 1
|
||||
if(!HDD)
|
||||
@@ -74,47 +43,15 @@
|
||||
var/newname = stripped_input(usr, "Enter new file name:", "File rename", file.filename, max_length=50)
|
||||
if(file && newname)
|
||||
file.filename = newname
|
||||
if("PRG_edit")
|
||||
. = 1
|
||||
if(!open_file)
|
||||
if("PRG_usbrenamefile")
|
||||
if(!RHDD)
|
||||
return 1
|
||||
if(!HDD)
|
||||
return 1
|
||||
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
if(F.do_not_edit && (alert("WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", "No", "Yes") == "No"))
|
||||
return 1
|
||||
// 16384 is the limit for file length in characters. Currently, papers have value of 2048 so this is 8 times as long, since we can't edit parts of the file independently.
|
||||
var/newtext = stripped_multiline_input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", html_decode(F.stored_data), 16384, TRUE)
|
||||
if(!newtext)
|
||||
return
|
||||
if(F)
|
||||
var/datum/computer_file/data/backup = F.clone()
|
||||
HDD.remove_file(F)
|
||||
F.stored_data = newtext
|
||||
F.calculate_size()
|
||||
// We can't store the updated file, it's probably too large. Print an error and restore backed up version.
|
||||
// This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
|
||||
// They will be able to copy-paste the text from error screen and store it in notepad or something.
|
||||
if(!HDD.store_file(F))
|
||||
error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:<br><br>[F.stored_data]<br><br>"
|
||||
HDD.store_file(backup)
|
||||
if("PRG_printfile")
|
||||
. = 1
|
||||
if(!open_file)
|
||||
return 1
|
||||
if(!HDD)
|
||||
return 1
|
||||
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
if(!printer)
|
||||
error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
|
||||
return 1
|
||||
if(!printer.print_text("<font face=\"[(computer.obj_flags & EMAGGED) ? CRAYON_FONT : PRINTER_FONT]\">" + prepare_printjob(F.stored_data) + "</font>", open_file))
|
||||
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
|
||||
var/datum/computer_file/file = RHDD.find_file_by_name(params["name"])
|
||||
if(!file || !istype(file))
|
||||
return 1
|
||||
var/newname = stripped_input(usr, "Enter new file name:", "File rename", file.filename, max_length=50)
|
||||
if(file && newname)
|
||||
file.filename = newname
|
||||
if("PRG_copytousb")
|
||||
. = 1
|
||||
if(!HDD || !RHDD)
|
||||
@@ -190,43 +127,29 @@
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD]
|
||||
if(error)
|
||||
data["error"] = error
|
||||
if(open_file)
|
||||
var/datum/computer_file/data/file
|
||||
|
||||
if(!computer || !HDD)
|
||||
data["error"] = "I/O ERROR: Unable to access hard drive."
|
||||
else
|
||||
file = HDD.find_file_by_name(open_file)
|
||||
if(!istype(file))
|
||||
data["error"] = "I/O ERROR: Unable to open file."
|
||||
else
|
||||
data["filedata"] = parse_tags(file.stored_data)
|
||||
data["filename"] = "[file.filename].[file.filetype]"
|
||||
if(!computer || !HDD)
|
||||
data["error"] = "I/O ERROR: Unable to access hard drive."
|
||||
else
|
||||
if(!computer || !HDD)
|
||||
data["error"] = "I/O ERROR: Unable to access hard drive."
|
||||
else
|
||||
var/list/files[0]
|
||||
for(var/datum/computer_file/F in HDD.stored_files)
|
||||
files.Add(list(list(
|
||||
var/list/files[0]
|
||||
for(var/datum/computer_file/F in HDD.stored_files)
|
||||
files.Add(list(list(
|
||||
"name" = F.filename,
|
||||
"type" = F.filetype,
|
||||
"size" = F.size,
|
||||
"undeletable" = F.undeletable
|
||||
)))
|
||||
data["files"] = files
|
||||
if(RHDD)
|
||||
data["usbconnected"] = TRUE
|
||||
var/list/usbfiles[0]
|
||||
for(var/datum/computer_file/F in RHDD.stored_files)
|
||||
usbfiles.Add(list(list(
|
||||
"name" = F.filename,
|
||||
"type" = F.filetype,
|
||||
"size" = F.size,
|
||||
"undeletable" = F.undeletable
|
||||
)))
|
||||
data["files"] = files
|
||||
if(RHDD)
|
||||
data["usbconnected"] = 1
|
||||
var/list/usbfiles[0]
|
||||
for(var/datum/computer_file/F in RHDD.stored_files)
|
||||
usbfiles.Add(list(list(
|
||||
"name" = F.filename,
|
||||
"type" = F.filetype,
|
||||
"size" = F.size,
|
||||
"undeletable" = F.undeletable
|
||||
)))
|
||||
data["usbfiles"] = usbfiles
|
||||
data["usbfiles"] = usbfiles
|
||||
|
||||
return data
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = 1
|
||||
required_access = ACCESS_NETWORK //NETWORK CONTROL IS A MORE SECURE PROGRAM.
|
||||
available_on_ntnet = 1
|
||||
tgui_id = "ntos_net_monitor"
|
||||
tgui_id = "NtosNetMonitor"
|
||||
|
||||
/datum/computer_file/program/ntnetmonitor/ui_act(action, params)
|
||||
if(..())
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
requires_ntnet_feature = NTNET_PEERTOPEER
|
||||
network_destination = "other device via P2P tunnel"
|
||||
available_on_ntnet = 1
|
||||
tgui_id = "ntos_net_transfer"
|
||||
tgui_id = "NtosNetTransfer"
|
||||
|
||||
var/error = "" // Error screen
|
||||
var/server_password = "" // Optional password to download the file.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, NoticeBox, ProgressBar, Section, Table } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosAiRestorer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
restoring,
|
||||
error,
|
||||
name,
|
||||
nocard,
|
||||
isDead,
|
||||
health,
|
||||
no_ai,
|
||||
ai_laws = [],
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<NtosWindow>
|
||||
<NtosWindow.Content scrollable>
|
||||
<Section title="Insert AI">
|
||||
<Box>
|
||||
Inserted AI:
|
||||
</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content={nocard ? "---" : name}
|
||||
onClick={() => act('PRG_eject')}
|
||||
disabled={nocard} />
|
||||
</Section>
|
||||
{!!restoring && (
|
||||
<NoticeBox>
|
||||
Reconstruction in progress!
|
||||
</NoticeBox>
|
||||
)}
|
||||
{!!error && (
|
||||
<NoticeBox>
|
||||
ERROR: {error}
|
||||
</NoticeBox>
|
||||
) || (
|
||||
<Section title="System Status">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="AI Name">
|
||||
{name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Status">
|
||||
{isDead ? "Non-functional" : "Functional"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="System Integrity">
|
||||
<ProgressBar
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
value={health}
|
||||
ranges={{
|
||||
good: [70, Infinity],
|
||||
average: [50, 70],
|
||||
bad: [-Infinity, 50],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Active Laws" />
|
||||
{ai_laws.length > 0 && (ai_laws.map((law, index) => (
|
||||
<LabeledList.Item className="candystripe" key={'law_' + index.toString()}>
|
||||
{law}
|
||||
</LabeledList.Item>
|
||||
))
|
||||
) || (
|
||||
<LabeledList.Item>
|
||||
<NoticeBox danger>
|
||||
No laws found.
|
||||
</NoticeBox>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item
|
||||
label="Operations">
|
||||
<Button
|
||||
icon="plus"
|
||||
disabled={restoring}
|
||||
onClick={() => act('PRG_beginReconstruction')} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
)}
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,461 @@
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import { Box, Button, Collapsible, Flex, NoticeBox, Section, Table, Tabs } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
|
||||
export const NtosCard = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
have_id_slot,
|
||||
manifest,
|
||||
slots,
|
||||
has_id,
|
||||
authenticated,
|
||||
all_centcom_access,
|
||||
station_name,
|
||||
regions,
|
||||
id_name,
|
||||
auth_name,
|
||||
minor,
|
||||
centcom_access,
|
||||
id_owner,
|
||||
id_rank,
|
||||
} = data;
|
||||
|
||||
const [tab, setTab] = useLocalState(context, 'tab', 0);
|
||||
|
||||
return (
|
||||
<NtosWindow>
|
||||
<NtosWindow.Content scrollable>
|
||||
<Tabs>
|
||||
{!!have_id_slot && (
|
||||
<Tabs.Tab
|
||||
icon="folder-open"
|
||||
selected={tab===0}
|
||||
onClick={() => {
|
||||
setTab(0);
|
||||
act('PRG_switchm', { target: 'mod' });
|
||||
}}>
|
||||
Access Modification
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
<Tabs.Tab
|
||||
icon="folder-open"
|
||||
selected={tab===1}
|
||||
onClick={() => {
|
||||
setTab(1);
|
||||
act('PRG_switchm', { target: 'manage' });
|
||||
}}>
|
||||
Job Management
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
icon="folder-open"
|
||||
selected={tab===2}
|
||||
onClick={() => {
|
||||
setTab(2);
|
||||
act('PRG_switchm', { target: 'manifest' });
|
||||
}}>
|
||||
Crew Manifest
|
||||
</Tabs.Tab>
|
||||
<Button
|
||||
icon="print"
|
||||
content="Print"
|
||||
disabled={tab===1 || (tab===0 && !has_id)}
|
||||
onClick={() => act('PRG_print')} />
|
||||
</Tabs>
|
||||
|
||||
{tab === 0 && (
|
||||
<Section title="Access Modification">
|
||||
<NtosCardAccessAuth id_name={id_name} auth_name={auth_name} />
|
||||
{authenticated && has_id && (
|
||||
<>
|
||||
<NtosCardAccessDetails
|
||||
minor={minor}
|
||||
id_owner={id_owner}
|
||||
id_rank={id_rank}
|
||||
act={act} />
|
||||
<NtosCardAccessAssignments centcom_access={centcom_access} />
|
||||
<NtosCardAccessRegions
|
||||
centcom_access={centcom_access}
|
||||
all_centcom_access={all_centcom_access}
|
||||
station_name={station_name}
|
||||
regions={regions}
|
||||
act={act} />
|
||||
</>
|
||||
) || null}
|
||||
</Section>
|
||||
)}
|
||||
{tab === 1 && (
|
||||
<Section title="Job Management">
|
||||
<NtosCardJobManagement slots={slots} act={act} />
|
||||
</Section>
|
||||
)}
|
||||
{tab === 2 && (
|
||||
<Section title="Crew Manifest">
|
||||
<NoticeBox>
|
||||
Please use a <b>security records console</b> to modify entries.
|
||||
</NoticeBox>
|
||||
<Box>
|
||||
{manifest && manifest.map(crewmember => (
|
||||
<><b>{crewmember.name}</b> - {crewmember.rank}</>
|
||||
))}
|
||||
</Box>
|
||||
</Section>
|
||||
)}
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const NtosCardAccessRegions = (props, context) => {
|
||||
const {
|
||||
centcom_access,
|
||||
all_centcom_access,
|
||||
station_name,
|
||||
regions = [],
|
||||
act,
|
||||
} = props;
|
||||
|
||||
const [regionTab, setRegionTab] = useLocalState(context, 'regionTab', 0);
|
||||
|
||||
if (centcom_access) {
|
||||
return (
|
||||
<Section title="Central Command" level={2}>
|
||||
{all_centcom_access && all_centcom_access.map(access => (
|
||||
<Button.Checkbox
|
||||
key={access.desc}
|
||||
content={access.desc}
|
||||
checked={access.allowed}
|
||||
onClick={() => act('PRG_access', {
|
||||
access_target: access.ref,
|
||||
allowed: access.allowed,
|
||||
})} />
|
||||
))}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
else {
|
||||
const activeRegion = regions[regionTab];
|
||||
|
||||
return (
|
||||
<Section title={station_name} level={2}>
|
||||
<Tabs>
|
||||
{regions.map(region => (
|
||||
<Tabs.Tab
|
||||
key={region.regid}
|
||||
selected={region.selected}
|
||||
onClick={() => {
|
||||
act('PRG_regsel', { region: region.regid });
|
||||
setRegionTab(region.regid-1);
|
||||
}}>
|
||||
{region.name}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
{activeRegion.accesses && (
|
||||
<Box>
|
||||
{activeRegion.accesses.map(access => (
|
||||
<Button.Checkbox
|
||||
key={access.desc}
|
||||
content={access.desc}
|
||||
checked={access.allowed}
|
||||
onClick={() => act('PRG_access', {
|
||||
access_target: access.ref,
|
||||
allowed: access.allowed,
|
||||
})} />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const NtosCardJobManagement = (props, context) => {
|
||||
const { slots, act } = props;
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>Job</Table.Cell>
|
||||
<Table.Cell>Slots</Table.Cell>
|
||||
<Table.Cell>Open Job</Table.Cell>
|
||||
<Table.Cell>Close Job</Table.Cell>
|
||||
</Table.Row>
|
||||
{!!slots && slots.map(slot => (
|
||||
<Table.Row key={slot.title}>
|
||||
<Table.Cell>{slot.title}</Table.Cell>
|
||||
<Table.Cell>{slot.current}/{slot.total}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
content={slot.desc_open}
|
||||
disabled={!slot.status_open}
|
||||
onClick={() => act('PRG_open_job', {
|
||||
target: slot.title,
|
||||
})} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
content={slot.desc_close}
|
||||
disabled={!slot.status_close}
|
||||
onClick={() => act('PRG_close_job', {
|
||||
target: slot.title,
|
||||
})} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const NtosCardAccessAuth = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
id_name,
|
||||
auth_name,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<NoticeBox>
|
||||
Please insert the ID into the terminal to proceed.
|
||||
</NoticeBox>
|
||||
<Flex justify="space-between" direction="row" wrap="wrap">
|
||||
<Flex.Item>
|
||||
<Box>Target Identity:</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content={id_name}
|
||||
onClick={() => act('PRG_eject', { target: 'id' })} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Box>Auth Identity:</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content={auth_name}
|
||||
onClick={() => act('PRG_eject', { target: 'auth' })} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const NtosCardAccessDetails = (props, context) => {
|
||||
const {
|
||||
minor,
|
||||
id_owner,
|
||||
id_rank,
|
||||
act,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Details"
|
||||
level={2}>
|
||||
{!!minor && (
|
||||
<>
|
||||
<Box>
|
||||
<b>Registered Name:</b> {id_owner}
|
||||
</Box>
|
||||
<Box>
|
||||
<b>Rank:</b> {id_rank}
|
||||
</Box>
|
||||
<Box>
|
||||
<Button
|
||||
icon="gear"
|
||||
onClick={() => act('PRG_terminate')}
|
||||
disabled={id_rank === 'Unassigned'}
|
||||
label={"Demote " + id_owner} />
|
||||
</Box>
|
||||
</>
|
||||
) || (
|
||||
<Box>
|
||||
Registered Name:
|
||||
<Button
|
||||
content={id_owner.trim()}
|
||||
icon="pencil-alt"
|
||||
onClick={() => act('PRG_edit', { name: true })} />
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const NtosCardAccessAssignments = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const { centcom_access } = props;
|
||||
const {
|
||||
engineering_jobs = [],
|
||||
medical_jobs = [],
|
||||
science_jobs = [],
|
||||
security_jobs = [],
|
||||
cargo_jobs = [],
|
||||
civilian_jobs = [],
|
||||
centcom_jobs = [],
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Assigments"
|
||||
level={2}>
|
||||
<Collapsible title="Job Presets">
|
||||
<Table>
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Special
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<NtosCardAssignButton
|
||||
selectable
|
||||
icon="pencil-alt"
|
||||
assignJob={{
|
||||
display_name: 'Custom Job Title',
|
||||
job: 'Custom',
|
||||
}} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Command
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<NtosCardAssignButton selectable assignJob={{
|
||||
display_name: 'Captain',
|
||||
job: 'Captain',
|
||||
}} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{!!engineering_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Engineering
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{engineering_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!medical_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Medical
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{medical_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!science_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Science
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{science_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!security_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Security
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{security_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!cargo_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Cargo
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{cargo_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!civilian_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Civilian
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{civilian_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{!!centcom_access && !!centcom_jobs && (
|
||||
<Table.Row>
|
||||
<Table.Cell header>
|
||||
Centcom
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{centcom_jobs.map(target => (
|
||||
<NtosCardAssignButton
|
||||
key={target.display_name}
|
||||
selectable
|
||||
assignJob={target} />
|
||||
))}
|
||||
</Table.Cell>
|
||||
{/* {JSON.stringify(centcom_jobs)} */}
|
||||
</Table.Row>
|
||||
) || null}
|
||||
</Table>
|
||||
</Collapsible>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const NtosCardAssignButton = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { id_rank } = data;
|
||||
const { assignJob, selectable, icon } = props;
|
||||
const { display_name, job } = assignJob;
|
||||
|
||||
return (
|
||||
<Button
|
||||
content={display_name}
|
||||
icon={icon}
|
||||
selected={selectable && id_rank === job}
|
||||
onClick={() => act('PRG_assign', {
|
||||
assign_target: job,
|
||||
})} />
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Divider, NoticeBox, Section, Table } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosFileManager = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
error,
|
||||
usbconnected,
|
||||
files = [],
|
||||
usbfiles = [],
|
||||
} = data;
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<NtosWindow>
|
||||
<NtosWindow.Content scrollable>
|
||||
<NoticeBox danger>
|
||||
{error}
|
||||
<br />
|
||||
<i>Please try again. If the problem persists contact your system administrator for assistance.</i>
|
||||
</NoticeBox>
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NtosWindow>
|
||||
<NtosWindow.Content scrollable>
|
||||
<Section title="Available files (local)">
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>File name</Table.Cell>
|
||||
<Table.Cell>File type</Table.Cell>
|
||||
<Table.Cell>File size (GQ)</Table.Cell>
|
||||
<Table.Cell>Operations</Table.Cell>
|
||||
</Table.Row>
|
||||
{files.map(file => (
|
||||
<Table.Row key={file.name}>
|
||||
<Table.Cell>{file.name}</Table.Cell>
|
||||
<Table.Cell>.{file.type}</Table.Cell>
|
||||
<Table.Cell>{file.size}GQ</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
content="DELETE"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_deletefile', { name: file.name })} />
|
||||
<Button
|
||||
content="RENAME"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_rename', { name: file.name })} />
|
||||
{!!usbconnected && (
|
||||
<Button
|
||||
content="EXPORT"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_copytousb', { name: file.name })} />
|
||||
)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
</Section>
|
||||
{usbconnected && (
|
||||
<Section title="Available files (portable device)">
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>File name</Table.Cell>
|
||||
<Table.Cell>File type</Table.Cell>
|
||||
<Table.Cell>File size (GQ)</Table.Cell>
|
||||
<Table.Cell>Operations</Table.Cell>
|
||||
</Table.Row>
|
||||
{usbfiles.map(file => (
|
||||
<Table.Row key={file.name}>
|
||||
<Table.Cell>{file.name}</Table.Cell>
|
||||
<Table.Cell>.{file.type}</Table.Cell>
|
||||
<Table.Cell>{file.size}GQ</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
content="DELETE"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_usbdeletefile', { name: file.name })} />
|
||||
<Button
|
||||
content="RENAME"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_usbrenamefile', { name: file.name })} />
|
||||
<Button
|
||||
content="IMPORT"
|
||||
disabled={file.undeletable}
|
||||
onClick={() => act('PRG_copyfromusb', { name: file.name })} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
</Section>
|
||||
)}
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, NoticeBox, Section } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosNetDos = (props, context) => {
|
||||
return (
|
||||
<NtosWindow
|
||||
width={400}
|
||||
height={250}
|
||||
theme="syndicate">
|
||||
<NtosWindow.Content>
|
||||
<NtosNetDosContent />
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
|
||||
export const NtosNetDosContent = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
relays = [],
|
||||
focus,
|
||||
target,
|
||||
speed,
|
||||
overload,
|
||||
capacity,
|
||||
error,
|
||||
} = data;
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<>
|
||||
<NoticeBox>
|
||||
{error}
|
||||
</NoticeBox>
|
||||
<Button
|
||||
fluid
|
||||
content="Reset"
|
||||
textAlign="center"
|
||||
onClick={() => act('PRG_reset')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const generate10String = length => {
|
||||
let outString = "";
|
||||
const factor = (overload / capacity);
|
||||
while (outString.length < length) {
|
||||
if (Math.random() > factor) {
|
||||
outString += "0";
|
||||
} else {
|
||||
outString += "1";
|
||||
}
|
||||
}
|
||||
return outString;
|
||||
};
|
||||
|
||||
const lineLength = 45;
|
||||
|
||||
if (target) {
|
||||
return (
|
||||
<Section fontFamily="monospace" textAlign="center">
|
||||
<Box>
|
||||
CURRENT SPEED: {speed} GQ/s
|
||||
</Box>
|
||||
<Box>
|
||||
{/* I don't care anymore */}
|
||||
{generate10String(lineLength)}
|
||||
</Box>
|
||||
<Box>
|
||||
{generate10String(lineLength)}
|
||||
</Box>
|
||||
<Box>
|
||||
{generate10String(lineLength)}
|
||||
</Box>
|
||||
<Box>
|
||||
{generate10String(lineLength)}
|
||||
</Box>
|
||||
<Box>
|
||||
{generate10String(lineLength)}
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Target">
|
||||
{relays.map(relay => (
|
||||
<Button
|
||||
key={relay.id}
|
||||
content={relay.id}
|
||||
selected={focus === relay.id}
|
||||
onClick={() => act('PRG_target_relay', {
|
||||
targid: relay.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
<Button
|
||||
fluid
|
||||
bold
|
||||
content="EXECUTE"
|
||||
color="bad"
|
||||
textAlign="center"
|
||||
disabled={!focus}
|
||||
mt={1}
|
||||
onClick={() => act('PRG_execute')}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, NoticeBox, NumberInput, Section } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosNetMonitor = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
ntnetrelays,
|
||||
ntnetstatus,
|
||||
idsalarm,
|
||||
idsstatus,
|
||||
|
||||
config_softwaredownload,
|
||||
config_peertopeer,
|
||||
config_communication,
|
||||
config_systemcontrol,
|
||||
|
||||
ntnetlogs = [],
|
||||
ntnetmaxlogs,
|
||||
} = data;
|
||||
return (
|
||||
<NtosWindow>
|
||||
<NtosWindow.Content scrollable>
|
||||
<NoticeBox>
|
||||
WARNING: Disabling wireless transmitters when using
|
||||
a wireless device may prevent you from reenabling them!
|
||||
</NoticeBox>
|
||||
<Section
|
||||
title="Wireless Connectivity"
|
||||
buttons={(
|
||||
<Button.Confirm
|
||||
icon={ntnetstatus ? 'power-off' : 'times'}
|
||||
content={ntnetstatus ? 'ENABLED' : 'DISABLED'}
|
||||
selected={ntnetstatus}
|
||||
onClick={() => act('toggleWireless')} />
|
||||
)}>
|
||||
{ntnetrelays ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Active NTNet Relays">
|
||||
{ntnetrelays}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : "No Relays Connected"}
|
||||
</Section>
|
||||
<Section title="Firewall Configuration">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Software Downloads"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={config_softwaredownload ? 'power-off' : 'times'}
|
||||
content={config_softwaredownload ? 'ENABLED' : 'DISABLED'}
|
||||
selected={config_softwaredownload}
|
||||
onClick={() => act('toggle_function', { id: "1" })} />
|
||||
)} />
|
||||
<LabeledList.Item
|
||||
label="Peer to Peer Traffic"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={config_peertopeer ? 'power-off' : 'times'}
|
||||
content={config_peertopeer ? 'ENABLED' : 'DISABLED'}
|
||||
selected={config_peertopeer}
|
||||
onClick={() => act('toggle_function', { id: "2" })} />
|
||||
)} />
|
||||
<LabeledList.Item
|
||||
label="Communication Systems"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={config_communication ? 'power-off' : 'times'}
|
||||
content={config_communication ? 'ENABLED' : 'DISABLED'}
|
||||
selected={config_communication}
|
||||
onClick={() => act('toggle_function', { id: "3" })} />
|
||||
)} />
|
||||
<LabeledList.Item
|
||||
label="Remote System Control"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={config_systemcontrol ? 'power-off' : 'times'}
|
||||
content={config_systemcontrol ? 'ENABLED' : 'DISABLED'}
|
||||
selected={config_systemcontrol}
|
||||
onClick={() => act('toggle_function', { id: "4" })} />
|
||||
)} />
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Security Systems">
|
||||
{!!idsalarm && (
|
||||
<>
|
||||
<NoticeBox>
|
||||
NETWORK INCURSION DETECTED
|
||||
</NoticeBox>
|
||||
<Box italics>
|
||||
Abnormal activity has been detected in the network.
|
||||
Check system logs for more information
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="IDS Status"
|
||||
buttons={(
|
||||
<>
|
||||
<Button
|
||||
icon={idsstatus ? 'power-off' : 'times'}
|
||||
content={idsstatus ? 'ENABLED' : 'DISABLED'}
|
||||
selected={idsstatus}
|
||||
onClick={() => act('toggleIDS')} />
|
||||
<Button
|
||||
icon="sync"
|
||||
content="Reset"
|
||||
color="bad"
|
||||
onClick={() => act('resetIDS')} />
|
||||
</>
|
||||
)} />
|
||||
<LabeledList.Item
|
||||
label="Max Log Count"
|
||||
buttons={(
|
||||
<Button
|
||||
value={ntnetmaxlogs}
|
||||
width="39px"
|
||||
onClick={() => act('updatemaxlogs')} />
|
||||
)} />
|
||||
</LabeledList>
|
||||
<Section
|
||||
title="System Log"
|
||||
level={2}
|
||||
buttons={(
|
||||
<Button.Confirm
|
||||
icon="trash"
|
||||
content="Clear Logs"
|
||||
onClick={() => act('purgelogs')} />
|
||||
)}>
|
||||
{ntnetlogs.map(log => (
|
||||
<Box key={log.entry} className="candystripe">
|
||||
{log.entry}
|
||||
</Box>
|
||||
))}
|
||||
</Section>
|
||||
</Section>
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Box, LabeledList, ProgressBar, Section, Icon } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosNetTransfer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
error,
|
||||
downloading,
|
||||
uploading,
|
||||
upload_filelist = [],
|
||||
} = data;
|
||||
|
||||
let body = <P2PAvailable />;
|
||||
|
||||
if (error) {
|
||||
body = <P2PError />;
|
||||
} else if (downloading) {
|
||||
body = <P2PDownload />;
|
||||
} else if (uploading) {
|
||||
body = <P2PUpload />;
|
||||
} else if (upload_filelist.length) {
|
||||
body = <P2PUploadServer />;
|
||||
}
|
||||
|
||||
return (
|
||||
<NtosWindow width={575} height={700} resizable>
|
||||
<NtosWindow.Content scrollable>
|
||||
{body}
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
|
||||
const P2PError = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
error,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="An error has occured during operation." buttons={
|
||||
<Button
|
||||
icon="undo"
|
||||
onClick={() => act("PRG_reset")}>
|
||||
Reset
|
||||
</Button>
|
||||
}>
|
||||
Additional Information: {error}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const P2PDownload = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
download_name,
|
||||
download_progress,
|
||||
download_size,
|
||||
download_netspeed,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Download in progress">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Downloaded File">
|
||||
{download_name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Progress">
|
||||
<ProgressBar
|
||||
value={download_progress}
|
||||
maxValue={download_size}>
|
||||
{download_progress} / {download_size} GQ
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Transfer Speed">
|
||||
{download_netspeed} GQ/s
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Controls">
|
||||
<Button
|
||||
icon="ban"
|
||||
onClick={() => act("PRG_reset")}>
|
||||
Cancel Download
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const P2PUpload = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
upload_clients,
|
||||
upload_filename,
|
||||
upload_haspassword,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Server enabled">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Clients Connected">
|
||||
{upload_clients}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Provided file">
|
||||
{upload_filename}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Server Password">
|
||||
{upload_haspassword ? "Enabled" : "Disabled"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Commands">
|
||||
<Button
|
||||
icon="lock"
|
||||
onClick={() => act("PRG_setpassword")}>
|
||||
Set Password
|
||||
</Button>
|
||||
<Button
|
||||
icon="ban"
|
||||
onClick={() => act("PRG_reset")}>
|
||||
Cancel Upload
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const P2PUploadServer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
upload_filelist,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="File transfer server ready." buttons={
|
||||
<Button
|
||||
icon="undo"
|
||||
onClick={() => act("PRG_reset")}>
|
||||
Cancel
|
||||
</Button>
|
||||
}>
|
||||
<Button
|
||||
fluid
|
||||
icon="lock"
|
||||
onClick={() => act("PRG_setpassword")}>
|
||||
Set Password
|
||||
</Button>
|
||||
<Section title="Pick file to serve." level={2}>
|
||||
{upload_filelist.map(file => (
|
||||
<Button
|
||||
key={file.uid}
|
||||
fluid
|
||||
icon="upload"
|
||||
onClick={() => act("PRG_uploadfile", { id: file.uid })}>
|
||||
{file.filename} ({file.size}GQ)
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const P2PAvailable = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
servers,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Available Files" buttons={
|
||||
<Button
|
||||
icon="upload"
|
||||
onClick={() => act("PRG_uploadmenu")}>
|
||||
Send File
|
||||
</Button>
|
||||
}>
|
||||
{servers.length && (
|
||||
<LabeledList>
|
||||
{servers.map(server => (
|
||||
<LabeledList.Item label={server.uid} key={server.uid}>
|
||||
{!!server.haspassword && <Icon name="lock" mr={1} />}
|
||||
{server.filename}
|
||||
({server.size}GQ)
|
||||
<Button
|
||||
icon="download"
|
||||
onClick={() => act("PRG_downloadfile", { uid: server.uid })}>
|
||||
Download
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
) || (
|
||||
<Box>
|
||||
No upload servers found.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Section, Button, LabeledList } from '../components';
|
||||
import { useBackend } from '../backend';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
export const NtosRevelation = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<NtosWindow
|
||||
width={400}
|
||||
height={250}
|
||||
theme="syndicate">
|
||||
<NtosWindow.Content>
|
||||
<Section>
|
||||
<Button.Input
|
||||
fluid
|
||||
content="Obfuscate Name..."
|
||||
onCommit={(e, value) => act('PRG_obfuscate', {
|
||||
new_name: value,
|
||||
})}
|
||||
mb={1} />
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Payload Status"
|
||||
buttons={(
|
||||
<Button
|
||||
content={data.armed ? 'ARMED' : 'DISARMED'}
|
||||
color={data.armed ? 'bad' : 'average'}
|
||||
onClick={() => act('PRG_arm')} />
|
||||
)} />
|
||||
</LabeledList>
|
||||
<Button
|
||||
fluid
|
||||
bold
|
||||
icon="radiation"
|
||||
content="ACTIVATE"
|
||||
textAlign="center"
|
||||
color="bad"
|
||||
disabled={!data.armed}
|
||||
onClick={() => act('PRG_activate')} />
|
||||
</Section>
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import { NtosWindow } from '../layouts';
|
||||
import { StationAlertConsoleContent } from './StationAlertConsole';
|
||||
|
||||
export const NtosStationAlertConsole = () => {
|
||||
return (
|
||||
<NtosWindow
|
||||
width={335}
|
||||
height={587}>
|
||||
<NtosWindow.Content scrollable>
|
||||
<StationAlertConsoleContent />
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -1,59 +1,70 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const StationAlertConsole = (props, context) => {
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content scrollable>
|
||||
<StationAlertConsoleContent />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export const StationAlertConsoleContent = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const categories = data.alarms || [];
|
||||
const fire = categories['Fire'] || [];
|
||||
const atmos = categories['Atmosphere'] || [];
|
||||
const power = categories['Power'] || [];
|
||||
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content scrollable>
|
||||
<Section title="Fire Alarms">
|
||||
<ul>
|
||||
{fire.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{fire.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
<Section title="Atmospherics Alarms">
|
||||
<ul>
|
||||
{atmos.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{atmos.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
<Section title="Power Alarms">
|
||||
<ul>
|
||||
{power.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{power.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
<Fragment>
|
||||
<Section title="Fire Alarms">
|
||||
<ul>
|
||||
{fire.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{fire.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
<Section title="Atmospherics Alarms">
|
||||
<ul>
|
||||
{atmos.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{atmos.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
<Section title="Power Alarms">
|
||||
<ul>
|
||||
{power.length === 0 && (
|
||||
<li className="color-good">
|
||||
Systems Nominal
|
||||
</li>
|
||||
)}
|
||||
{power.map(alert => (
|
||||
<li key={alert} className="color-average">
|
||||
{alert}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
import { sortBy } from 'common/collections';
|
||||
import { useSharedState } from '../../backend';
|
||||
import { Button, Flex, Section, Tabs } from '../../components';
|
||||
|
||||
export const AccessList = (props, context) => {
|
||||
const {
|
||||
accesses = [],
|
||||
wildcardSlots = {},
|
||||
selectedList = [],
|
||||
accessMod,
|
||||
trimAccess = [],
|
||||
accessFlags = {},
|
||||
accessFlagNames = {},
|
||||
wildcardFlags = {},
|
||||
extraButtons,
|
||||
showBasic,
|
||||
} = props;
|
||||
|
||||
const [
|
||||
wildcardTab,
|
||||
setWildcardTab,
|
||||
] = useSharedState(context, "wildcardSelected", showBasic ? "None" : Object.keys(wildcardSlots)[0]);
|
||||
|
||||
let selectedWildcard;
|
||||
|
||||
if ((wildcardTab !== "None") && !wildcardSlots[wildcardTab]) {
|
||||
selectedWildcard = showBasic ? "None" : Object.keys(wildcardSlots)[0];
|
||||
setWildcardTab(selectedWildcard);
|
||||
}
|
||||
else {
|
||||
selectedWildcard = wildcardTab;
|
||||
}
|
||||
|
||||
const parsedRegions = [];
|
||||
const selectedTrimAccess = [];
|
||||
accesses.forEach(region => {
|
||||
const regionName = region.name;
|
||||
const regionAccess = region.accesses;
|
||||
const parsedRegion = {
|
||||
name: regionName,
|
||||
accesses: [],
|
||||
hasSelected: false,
|
||||
allSelected: true,
|
||||
};
|
||||
|
||||
// If we're showing the basic accesses included as part of the trim,
|
||||
// we want to figure out how many are selected for later formatting
|
||||
// logic.
|
||||
if (showBasic) {
|
||||
regionAccess.forEach(access => {
|
||||
if (trimAccess.includes(access.ref)
|
||||
&& selectedList.includes(access.ref)
|
||||
&& !selectedTrimAccess.includes(access.ref)
|
||||
) {
|
||||
selectedTrimAccess.push(access.ref);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If there's no wildcard selected, grab accesses in
|
||||
// the trimAccess list as they require no wildcard.
|
||||
if (selectedWildcard === "None") {
|
||||
regionAccess.forEach(access => {
|
||||
if (!trimAccess.includes(access.ref)) {
|
||||
return;
|
||||
}
|
||||
parsedRegion.accesses.push(access);
|
||||
if (selectedList.includes(access.ref)) {
|
||||
parsedRegion.hasSelected = true;
|
||||
}
|
||||
else {
|
||||
parsedRegion.allSelected = false;
|
||||
}
|
||||
});
|
||||
if (parsedRegion.accesses.length) {
|
||||
parsedRegions.push(parsedRegion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Otherwise, a trim is selected. We want to grab all
|
||||
// accesses not in trimAccess that are compatible with
|
||||
// the given wildcard.
|
||||
regionAccess.forEach(access => {
|
||||
if (trimAccess.includes(access.ref)) {
|
||||
return;
|
||||
}
|
||||
if (accessFlags[access.ref] & wildcardFlags[selectedWildcard]) {
|
||||
parsedRegion.accesses.push(access);
|
||||
if (selectedList.includes(access.ref)) {
|
||||
parsedRegion.hasSelected = true;
|
||||
}
|
||||
else {
|
||||
parsedRegion.allSelected = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (parsedRegion.accesses.length) {
|
||||
parsedRegions.push(parsedRegion);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Access"
|
||||
buttons={extraButtons} >
|
||||
<Flex wrap="wrap">
|
||||
<Flex.Item width="100%">
|
||||
<FormatWildcards
|
||||
wildcardSlots={wildcardSlots}
|
||||
selectedList={selectedList}
|
||||
showBasic={showBasic}
|
||||
basicUsed={selectedTrimAccess.length}
|
||||
basicMax={trimAccess.length} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<RegionTabList
|
||||
accesses={parsedRegions} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1}>
|
||||
<RegionAccessList
|
||||
accesses={parsedRegions}
|
||||
selectedList={selectedList}
|
||||
accessMod={accessMod}
|
||||
trimAccess={trimAccess}
|
||||
accessFlags={accessFlags}
|
||||
accessFlagNames={accessFlagNames}
|
||||
wildcardSlots={wildcardSlots}
|
||||
showBasic={showBasic} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const FormatWildcards = (props, context) => {
|
||||
const {
|
||||
wildcardSlots = {},
|
||||
showBasic,
|
||||
basicUsed = 0,
|
||||
basicMax = 0,
|
||||
} = props;
|
||||
|
||||
const [
|
||||
wildcardTab,
|
||||
setWildcardTab,
|
||||
] = useSharedState(context, "wildcardSelected", showBasic ? "None" : Object.keys(wildcardSlots)[0]);
|
||||
|
||||
let selectedWildcard;
|
||||
|
||||
if ((wildcardTab !== "None") && !wildcardSlots[wildcardTab]) {
|
||||
selectedWildcard = showBasic ? "None" : Object.keys(wildcardSlots)[0];
|
||||
setWildcardTab(selectedWildcard);
|
||||
}
|
||||
else {
|
||||
selectedWildcard = wildcardTab;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tabs>
|
||||
{showBasic && (
|
||||
<Tabs.Tab
|
||||
selected={selectedWildcard === "None"}
|
||||
onClick={() => setWildcardTab("None")} >
|
||||
Trim:<br />{basicUsed + "/" + basicMax}
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
|
||||
{Object.keys(wildcardSlots).map(wildcard => {
|
||||
const wcObj = wildcardSlots[wildcard];
|
||||
let wcLimit = wcObj.limit;
|
||||
const wcUsage = wcObj.usage.length;
|
||||
const wcLeft = wcLimit - wcUsage;
|
||||
if (wcLeft < 0) {
|
||||
wcLimit = "∞";
|
||||
}
|
||||
const wcLeftStr = `${wcUsage}/${wcLimit}`;
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={wildcard}
|
||||
selected={selectedWildcard === wildcard}
|
||||
onClick={() => setWildcardTab(wildcard)} >
|
||||
{wildcard + ":"}<br />{wcLeftStr}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
const RegionTabList = (props, context) => {
|
||||
const {
|
||||
accesses = [],
|
||||
} = props;
|
||||
|
||||
const [
|
||||
selectedAccessName,
|
||||
setSelectedAccessName,
|
||||
] = useSharedState(context, 'accessName', accesses[0]?.name);
|
||||
|
||||
return (
|
||||
<Tabs vertical>
|
||||
{accesses.map(access => {
|
||||
const icon = (access.allSelected && "check")
|
||||
|| (access.hasSelected && "minus")
|
||||
|| "times";
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={access.name}
|
||||
icon={icon}
|
||||
minWidth={"100%"}
|
||||
altSelection
|
||||
selected={access.name === selectedAccessName}
|
||||
onClick={() => setSelectedAccessName(access.name)}>
|
||||
{access.name}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
const RegionAccessList = (props, context) => {
|
||||
const {
|
||||
accesses = [],
|
||||
selectedList = [],
|
||||
accessMod,
|
||||
trimAccess = [],
|
||||
accessFlags = {},
|
||||
accessFlagNames = {},
|
||||
wildcardSlots = {},
|
||||
showBasic,
|
||||
} = props;
|
||||
|
||||
const [
|
||||
wildcardTab,
|
||||
setWildcardTab,
|
||||
] = useSharedState(context, "wildcardSelected", showBasic ? "None" : Object.keys(wildcardSlots)[0]);
|
||||
|
||||
let selWildcard;
|
||||
|
||||
if ((wildcardTab !== "None") && !wildcardSlots[wildcardTab]) {
|
||||
selWildcard = showBasic ? "None" : Object.keys(wildcardSlots)[0];
|
||||
setWildcardTab(selWildcard);
|
||||
}
|
||||
else {
|
||||
selWildcard = wildcardTab;
|
||||
}
|
||||
|
||||
const [
|
||||
selectedAccessName,
|
||||
] = useSharedState(context, 'accessName', accesses[0]?.name);
|
||||
|
||||
const selectedAccess = accesses
|
||||
.find(access => access.name === selectedAccessName);
|
||||
const selectedAccessEntries = sortBy(
|
||||
entry => entry.desc,
|
||||
)(selectedAccess?.accesses || []);
|
||||
|
||||
const allWildcards = Object.keys(wildcardSlots);
|
||||
let wcAccess = {};
|
||||
allWildcards.forEach(wildcard => {
|
||||
wildcardSlots[wildcard].usage.forEach(access => {
|
||||
wcAccess[access] = wildcard;
|
||||
});
|
||||
});
|
||||
|
||||
const wildcard = wildcardSlots[selWildcard];
|
||||
// If there's no wildcard, -1 limit as there's infinite basic slots.
|
||||
const wcLimit = wildcard ? wildcard.limit : -1;
|
||||
const wcUsage = wildcard ? wildcard.usage.length : 0;
|
||||
const wcAvail = wcLimit - wcUsage;
|
||||
|
||||
return (
|
||||
selectedAccessEntries.map(entry => {
|
||||
const id = entry.ref;
|
||||
const disableButton = (
|
||||
((wcAvail === 0) && (wcAccess[id] !== selWildcard))
|
||||
|| ((wcAvail > 0) && wcAccess[id] && wcAccess[id] !== selWildcard));
|
||||
const entryName = (!wcAccess[id] && trimAccess.includes(id))
|
||||
? entry.desc
|
||||
: entry.desc + " (" + accessFlagNames[accessFlags[id]] + ")";
|
||||
|
||||
return (
|
||||
<Button.Checkbox
|
||||
ml={1}
|
||||
fluid
|
||||
key={entry.desc}
|
||||
content={entryName}
|
||||
disabled={disableButton}
|
||||
checked={selectedList.includes(entry.ref)}
|
||||
onClick={() => accessMod(
|
||||
entry.ref,
|
||||
(selWildcard === "None") ? null : selWildcard)} />
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user