Merge pull request #13888 from Kyep/tgui_apc

[TGUI] APCs
This commit is contained in:
AffectedArc07
2020-09-14 22:22:28 +01:00
committed by GitHub
5 changed files with 371 additions and 362 deletions
+113 -162
View File
@@ -25,6 +25,11 @@
#define APC_UPDATE_ICON_COOLDOWN 200 // 20 seconds
// main_status var
#define APC_EXTERNAL_POWER_NOTCONNECTED 0
#define APC_EXTERNAL_POWER_NOENERGY 1
#define APC_EXTERNAL_POWER_GOOD 2
// APC malf status
#define APC_MALF_NOT_HACKED 1
#define APC_MALF_HACKED 2 // APC hacked by user, and user is in its core.
@@ -75,7 +80,7 @@
var/lastused_equip = 0
var/lastused_environ = 0
var/lastused_total = 0
var/main_status = 0
var/main_status = APC_EXTERNAL_POWER_NOTCONNECTED
powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
var/mob/living/silicon/ai/malfai = null //See above --NeoFite
@@ -213,7 +218,7 @@
if(isarea(A))
area = A
// no-op, keep the name
else if(isarea(A) && src.areastring == null)
else if(isarea(A) && !areastring)
area = A
name = "\improper [area.name] APC"
else
@@ -429,8 +434,8 @@
//attack with an item - open/close cover, insert cell, or (un)lock interface
/obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params)
if(issilicon(user) && get_dist(src,user)>1)
return src.attack_hand(user)
if(issilicon(user) && get_dist(src, user) > 1)
return attack_hand(user)
else if (istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
if(cell)
@@ -445,7 +450,7 @@
W.forceMove(src)
cell = W
user.visible_message(\
"[user.name] has inserted the power cell to [src.name]!",\
"[user.name] has inserted the power cell to [name]!",\
"<span class='notice'>You insert the power cell.</span>")
chargecount = 0
update_icon()
@@ -474,7 +479,7 @@
return
user.visible_message("[user.name] adds cables to the APC frame.", \
"<span class='notice'>You start adding cables to the APC frame...</span>")
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(do_after(user, 20, target = src))
if(C.get_amount() < 10 || !C)
return
@@ -499,10 +504,10 @@
user.visible_message("[user.name] inserts the power control board into [src].", \
"<span class='notice'>You start to insert the power control board into the frame...</span>")
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(do_after(user, 10, target = src))
if(has_electronics==0)
has_electronics = 1
if(!has_electronics)
has_electronics = TRUE
locked = FALSE
to_chat(user, "<span class='notice'>You place the power control board inside the frame.</span>")
qdel(W)
@@ -549,11 +554,11 @@
return
to_chat(user, "<span class='notice'>You are trying to remove the power control board...</span>" )
if(I.use_tool(src, user, 50, volume = I.tool_volume))
if(has_electronics==1)
has_electronics = 0
if(has_electronics)
has_electronics = FALSE
if(stat & BROKEN)
user.visible_message(\
"[user.name] has broken the power control board inside [src.name]!",
"[user.name] has broken the power control board inside [name]!",
"<span class='notice'>You break the charred power control board and remove the remains.</span>",
"<span class='italics'>You hear a crack.</span>")
return
@@ -561,19 +566,19 @@
else if(emagged) // We emag board, not APC's frame
emagged = FALSE
user.visible_message(
"[user.name] has discarded emaged power control board from [src.name]!",
"<span class='notice'>You discarded shorten board.</span>")
"[user.name] has discarded the shorted power control board from [name]!",
"<span class='notice'>You discarded the shorted board.</span>")
return
else if(malfhack) // AI hacks board, not APC's frame
user.visible_message(\
"[user.name] has discarded strangely programmed power control board from [src.name]!",
"<span class='notice'>You discarded strangely programmed board.</span>")
"[user.name] has discarded strangely the programmed power control board from [name]!",
"<span class='notice'>You discarded the strangely programmed board.</span>")
malfai = null
malfhack = 0
return
else
user.visible_message(\
"[user.name] has removed the power control board from [src.name]!",
"[user.name] has removed the power control board from [name]!",
"<span class='notice'>You remove the power control board.</span>")
new /obj/item/apc_electronics(loc)
return
@@ -711,36 +716,29 @@
// attack with hand - remove cell (if cover open) or interact with the APC
/obj/machinery/power/apc/attack_hand(mob/user)
// if(!can_use(user)) This already gets called in interact() and in topic()
// return
if(!user)
return
src.add_fingerprint(user)
add_fingerprint(user)
if(usr == user && opened && (!issilicon(user)))
if(usr == user && opened && !issilicon(user))
if(cell)
if(issilicon(user))
cell.loc=src.loc // Drop it, whoops.
else
user.put_in_hands(cell)
user.put_in_hands(cell)
cell.add_fingerprint(user)
cell.update_icon()
src.cell = null
user.visible_message("<span class='warning'>[user.name] removes the power cell from [src.name]!", "You remove the power cell.</span>")
// to_chat(user, "You remove the power cell.")
charging = 0
src.update_icon()
cell = null
user.visible_message("<span class='warning'>[user.name] removes [cell] from [src]!", "You remove the [cell].</span>")
charging = FALSE
update_icon()
return
if(stat & (BROKEN|MAINT))
return
src.interact(user)
interact(user)
/obj/machinery/power/apc/attack_ghost(mob/user)
if(panel_open)
wires.Interact(user)
return ui_interact(user)
return tgui_interact(user)
/obj/machinery/power/apc/interact(mob/user)
if(!user)
@@ -749,7 +747,7 @@
if(panel_open)
wires.Interact(user)
return ui_interact(user)
return tgui_interact(user)
/obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf)
@@ -770,22 +768,16 @@
else
return APC_MALF_NOT_HACKED
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(!user)
return
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/power/apc/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// the ui does not exist, so we'll create a new one
ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 510, issilicon(user) ? 535 : 460)
ui = new(user, src, ui_key, "APC", name, 510, 460, master_ui, state)
ui.open()
// Auto update every Master Controller tick
ui.set_auto_update(1)
/obj/machinery/power/apc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
var/data[0]
/obj/machinery/power/apc/tgui_data(mob/user)
var/list/data = list()
data["locked"] = is_locked(user)
data["normallyLocked"] = locked
data["isOperating"] = operating
data["externalPower"] = main_status
data["powerCellStatus"] = cell ? cell.percent() : null
@@ -862,7 +854,7 @@
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
if( \
src.aidisabled || \
aidisabled || \
malfhack && istype(malfai) && \
( \
(istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
@@ -873,21 +865,21 @@
to_chat(user, "<span class='danger'>\The [src] has AI control disabled!</span>")
user << browse(null, "window=apc")
user.unset_machine()
return 0
return FALSE
else
if((!in_range(src, user) || !istype(src.loc, /turf)))
return 0
if((!in_range(src, user) || !istype(loc, /turf)))
return FALSE
var/mob/living/carbon/human/H = user
if(istype(H))
if(H.getBrainLoss() >= 60)
for(var/mob/M in viewers(src, null))
to_chat(M, "<span class='danger'>[H] stares cluelessly at [src] and drools.</span>")
return 0
return FALSE
else if(prob(H.getBrainLoss()))
to_chat(user, "<span class='danger'>You momentarily forget how to use [src].</span>")
return 0
return 1
return FALSE
return TRUE
/obj/machinery/power/apc/proc/is_authenticated(mob/user as mob)
if(user.can_admin_interact())
@@ -905,104 +897,59 @@
else
return locked
/obj/machinery/power/apc/Topic(href, href_list, var/usingUI = 1)
if(..())
return 1
if(!can_use(usr, 1))
return 1
if(href_list["lock"])
if(!is_authenticated(usr))
return
coverlocked = !coverlocked
else if(href_list["breaker"])
if(!is_authenticated(usr))
return
toggle_breaker()
else if(href_list["toggle_nightshift"])
if(!is_authenticated(usr))
return
if(last_nightshift_switch > world.time + 100) // don't spam...
to_chat(usr, "<span class='warning'>[src]'s night lighting circuit breaker is still cycling!</span>")
return
last_nightshift_switch = world.time
set_nightshift(!nightshift_lights)
else if(href_list["cmode"])
if(!is_authenticated(usr))
return
chargemode = !chargemode
if(!chargemode)
charging = 0
update_icon()
else if(href_list["eqp"])
if(!is_authenticated(usr))
return
var/val = text2num(href_list["eqp"])
equipment = setsubsystem(val)
update_icon()
update()
else if(href_list["lgt"])
if(!is_authenticated(usr))
return
var/val = text2num(href_list["lgt"])
lighting = setsubsystem(val)
update_icon()
update()
else if(href_list["env"])
if(!is_authenticated(usr))
return
var/val = text2num(href_list["env"])
environ = setsubsystem(val)
update_icon()
update()
else if( href_list["close"] )
SSnanoui.close_user_uis(usr, src)
return 0
else if(href_list["close2"])
usr << browse(null, "window=apcwires")
return 0
else if(href_list["overload"])
if(issilicon(usr) && !aidisabled)
overload_lighting()
else if(href_list["malfhack"])
if(get_malf_status(usr))
malfhack(usr)
else if(href_list["occupyapc"])
if(get_malf_status(usr))
malfoccupy(usr)
else if(href_list["deoccupyapc"])
if(get_malf_status(usr))
malfvacate()
else if(href_list["toggleaccess"])
if(istype(usr, /mob/living/silicon))
if(emagged || aidisabled || (stat & (BROKEN|MAINT)))
to_chat(usr, "The APC does not respond to the command.")
/obj/machinery/power/apc/tgui_act(action, params)
if(..() || !can_use(usr, TRUE) || (locked && !usr.has_unlimited_silicon_privilege && (action != "toggle_nightshift") && !usr.can_admin_interact()))
return
. = TRUE
switch(action)
if("lock")
if(usr.has_unlimited_silicon_privilege)
if(emagged || stat & BROKEN)
to_chat(usr, "<span class='warning'>The APC does not respond to the command!</span>")
return FALSE
else
locked = !locked
update_icon()
else
locked = !locked
to_chat(usr, "<span class='warning'>Access Denied!</span>")
return FALSE
if("cover")
coverlocked = !coverlocked
if("breaker")
toggle_breaker(usr)
if("toggle_nightshift")
if(last_nightshift_switch > world.time + 100) // don't spam...
to_chat(usr, "<span class='warning'>[src]'s night lighting circuit breaker is still cycling!</span>")
return FALSE
last_nightshift_switch = world.time
set_nightshift(!nightshift_lights)
if("charge")
chargemode = !chargemode
if("channel")
if(params["eqp"])
equipment = setsubsystem(text2num(params["eqp"]))
update_icon()
return 0
update()
else if(params["lgt"])
lighting = setsubsystem(text2num(params["lgt"]))
update_icon()
update()
else if(params["env"])
environ = setsubsystem(text2num(params["env"]))
update_icon()
update()
if("overload")
if(usr.has_unlimited_silicon_privilege)
overload_lighting()
if("hack")
if(get_malf_status(usr))
malfhack(usr)
if("occupy")
if(get_malf_status(usr))
malfoccupy(usr)
if("deoccupy")
if(get_malf_status(usr))
malfvacate()
/obj/machinery/power/apc/proc/toggle_breaker()
operating = !operating
@@ -1033,7 +980,7 @@
if(!malf.can_shunt)
to_chat(malf, "<span class='warning'>You cannot shunt!</span>")
return
if(!is_station_level(src.z))
if(!is_station_level(z))
return
occupier = new /mob/living/silicon/ai(src,malf.laws,null,1)
occupier.adjustOxyLoss(malf.getOxyLoss())
@@ -1080,21 +1027,21 @@
/obj/machinery/power/apc/proc/ion_act()
//intended to be exactly the same as an AI malf attack
if(!src.malfhack && is_station_level(src.z))
if(!malfhack && is_station_level(z))
if(prob(3))
src.locked = 1
if(src.cell.charge > 0)
src.cell.charge = 0
locked = TRUE
if(cell.charge > 0)
cell.charge = 0
cell.corrupt()
src.malfhack = 1
malfhack = TRUE
update_icon()
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(3, 0, src.loc)
smoke.set_up(3, 0, loc)
smoke.attach(src)
smoke.start()
do_sparks(3, 1, src)
for(var/mob/M in viewers(src))
M.show_message("<span class='danger'>The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "<span class='danger'>You hear sizzling electronics.</span>", 2)
M.show_message("<span class='danger'>The [name] suddenly lets out a blast of smoke and some sparks!", 3, "<span class='danger'>You hear sizzling electronics.</span>", 2)
/obj/machinery/power/apc/surplus()
@@ -1137,12 +1084,12 @@
var/excess = surplus()
if(!src.avail())
main_status = 0
if(!avail())
main_status = APC_EXTERNAL_POWER_NOTCONNECTED
else if(excess < 0)
main_status = 1
main_status = APC_EXTERNAL_POWER_NOENERGY
else
main_status = 2
main_status = APC_EXTERNAL_POWER_GOOD
if(debug)
log_debug("Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]")
@@ -1257,7 +1204,7 @@
if(shock_mobs.len)
var/mob/living/L = pick(shock_mobs)
L.electrocute_act(rand(5, 25), "electrical arc")
playsound(get_turf(L), 'sound/effects/eleczap.ogg', 75, 1)
playsound(get_turf(L), 'sound/effects/eleczap.ogg', 75, TRUE)
Beam(L, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5)
else // no cell, switch everything off
@@ -1383,3 +1330,7 @@
updateDialog()
#undef APC_UPDATE_ICON_COOLDOWN
#undef APC_EXTERNAL_POWER_NOTCONNECTED
#undef APC_EXTERNAL_POWER_NOENERGY
#undef APC_EXTERNAL_POWER_GOOD
-197
View File
@@ -1,197 +0,0 @@
<div class='notice'>
{{if data.siliconUser}}
<div class="itemContentSmall">
Interface Lock:
</div>
<div class="itemContentFull">
{{:helper.link('Engaged', 'lock', {'toggleaccess' : 1}, data.siliconLock ? 'selected' : null)}}{{:helper.link('Disengaged', 'unlock', {'toggleaccess' : 1}, data.malfStatus >= 2 ? 'linkOff' : (data.siliconLock ? null : 'selected'))}}
</div>
<div class="clearBoth"></div>
{{else}}
{{if data.locked}}
Swipe an ID card to unlock this interface
{{else}}
Swipe an ID card to lock this interface
{{/if}}
{{/if}}
</div>
<div style="min-width: 480px">
<h3>Power Status</h3>
<div class="item">
<div class="itemLabel">
Main Breaker:
</div>
<div class="itemContent">
{{if data.locked && !data.siliconUser}}
{{if data.isOperating}}
<span class='good'>On</span>
{{else}}
<span class='bad'>Off</span>
{{/if}}
{{else}}
{{:helper.link('On', 'power-off', {'breaker' : 1}, data.isOperating ? 'selected' : null)}}{{:helper.link('Off', 'close', {'breaker' : 1}, data.isOperating ? null : 'selected')}}
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
External Power:
</div>
<div class="itemContent">
{{if data.externalPower == 2}}
<span class='good'>Good</span>
{{else data.externalPower == 1}}
<span class='average'>Low</span>
{{else}}
<span class='bad'>None</span>
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Power Cell:
</div>
{{if data.powerCellStatus == null}}
<div class="itemContent bad">
Power cell removed.
</div>
{{else}}
{{:helper.displayBar(data.powerCellStatus, 0, 100, (data.powerCellStatus >= 50) ? 'good' : (data.powerCellStatus >= 25) ? 'average' : 'bad')}}
<div class="itemContent" style="width: 60px">
{{:helper.smoothRound(data.powerCellStatus, 1)}}%
</div>
{{/if}}
</div>
{{if data.powerCellStatus != null}}
<div class="item">
<div class="itemLabel">
Charge Mode:
</div>
<div class="itemContent">
{{if data.locked && !data.siliconUser}}
{{if data.chargeMode}}
<span class='good'>Auto</span>
{{else}}
<span class='bad'>Off</span>
{{/if}}
{{else}}
{{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}}
{{/if}}
&nbsp;
{{if data.chargingStatus > 1}}
[<span class='good'>Fully Charged</span>]
{{else data.chargingStatus == 1}}
[<span class='average'>Charging</span>]
{{else}}
[<span class='bad'>Not Charging</span>]
{{/if}}
</div>
</div>
{{/if}}
<h3>Power Channels</h3>
{{for data.powerChannels}}
<div class="item">
<div class="itemLabel">
{{:value.title}}:
</div>
<div class="itemContent" style="width: 70px; text-align: right">
{{:helper.smoothRound(value.powerLoad)}} W
</div>
<div class="itemContent" style="width: 105px">
&nbsp;&nbsp;
{{if value.status <= 1}}
<span class='bad'>Off</span>
{{else value.status >= 2}}
<span class='good'>On</span>
{{/if}}
{{if data.locked}}
{{if value.status == 1 || value.status == 3}}
&nbsp;&nbsp;Auto
{{else}}
&nbsp;&nbsp;Manual
{{/if}}
{{/if}}
</div>
{{if !data.locked || data.siliconUser}}
<div class="itemContentFull">
{{:helper.link('Auto', 'refresh', value.topicParams.auto, (value.status == 1 || value.status == 3) ? 'selected' : null)}}
{{:helper.link('On', 'power-off', value.topicParams.on, (value.status == 2) ? 'selected' : null)}}
{{:helper.link('Off', 'close', value.topicParams.off, (value.status == 0) ? 'selected' : null)}}
</div>
{{/if}}
</div>
{{/for}}
<div class="item" style="font-weight: bold">
<div class="itemLabel">
Total Load:
</div>
<div class="itemContent" style="width: 70px; text-align: right">
{{:helper.smoothRound(data.totalLoad)}} W
</div>
</div>
<div class="item">&nbsp;</div>
<div class="item">
<div class="itemLabel">
Cover Lock:
</div>
<div class="itemContent">
{{if data.locked && !data.siliconUser}}
{{if data.coverLocked}}
<span class='good'>Engaged</span>
{{else}}
<span class='bad'>Disengaged</span>
{{/if}}
{{else}}
{{:helper.link('Engaged', 'lock', {'lock' : 1}, data.coverLocked ? 'selected' : null)}}{{:helper.link('Disengaged', 'unlock', {'lock' : 1}, data.coverLocked ? null : 'selected')}}
{{/if}}
</div>
</div>
{{if data.siliconUser}}
<h3>System Overrides</h3>
<div class="item">
{{:helper.link('Overload Lighting Circuit', 'lightbulb-o', {'overload' : 1})}}
{{if data.malfStatus == 1}}
{{:helper.link('Override Programming', 'file-text', {'malfhack' : 1})}}
{{else data.malfStatus == 2}}
{{:helper.link('Shunt Core Processes', 'arrow-down', {'occupyapc' : 1})}}
{{else data.malfStatus == 3}}
{{:helper.link('Return to Main Core', 'arrow-left', {'deoccupyapc' : 1})}}
{{else data.malfStatus == 4}}
{{:helper.link('Shunt Core Processes', 'arrow-down', {'occupyapc' : 1}, 'linkOff')}}
{{/if}}
</div>
{{/if}}
<div class="item">
<div class="itemLabel">
Night Shift Lighting:
</div>
<div class="itemContent">
{{if data.locked}}
{{if data.nightshiftLights}}
<span class='good'>On</span>
{{else}}
<span class='bad'>Off</span>
{{/if}}
{{else}}
{{:helper.link('Enabled', 'lightbulb-o', {'toggle_nightshift' : 1}, data.nightshiftLights ? 'selected' : null)}}{{:helper.link('Disabled', 'lightbulb-o', {'toggle_nightshift' : 1}, data.nightshiftLights ? null : 'selected')}}
{{/if}}
</div>
</div>
</div>
+195
View File
@@ -0,0 +1,195 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox';
export const APC = (props, context) => {
return (
<Window>
<Window.Content>
<ApcContent />
</Window.Content>
</Window>
);
};
const powerStatusMap = {
2: {
color: 'good',
externalPowerText: 'External Power',
chargingText: 'Fully Charged',
},
1: {
color: 'average',
externalPowerText: 'Low External Power',
chargingText: 'Charging',
},
0: {
color: 'bad',
externalPowerText: 'No External Power',
chargingText: 'Not Charging',
},
};
const malfMap = {
1: {
icon: 'terminal',
content: 'Override Programming',
action: 'hack',
},
2: {
icon: 'caret-square-down',
content: 'Shunt Core Process',
action: 'occupy',
},
3: {
icon: 'caret-square-left',
content: 'Return to Main Core',
action: 'deoccupy',
},
4: {
icon: 'caret-square-down',
content: 'Shunt Core Process',
action: 'occupy',
},
};
const ApcContent = (props, context) => {
const { act, data } = useBackend(context);
const locked = data.locked && !data.siliconUser;
const normallyLocked = data.normallyLocked;
const externalPowerStatus = powerStatusMap[data.externalPower]
|| powerStatusMap[0];
const chargingStatus = powerStatusMap[data.chargingStatus]
|| powerStatusMap[0];
const channelArray = data.powerChannels || [];
const malfStatus = malfMap[data.malfStatus] || malfMap[0];
const adjustedCellChange = data.powerCellStatus / 100;
return (
<Fragment>
<InterfaceLockNoticeBox />
<Section title="Power Status">
<LabeledList>
<LabeledList.Item
label="Main Breaker"
color={externalPowerStatus.color}
buttons={(
<Button
icon={data.isOperating ? 'power-off' : 'times'}
content={data.isOperating ? 'On' : 'Off'}
selected={data.isOperating && !locked}
color={data.isOperating ? "" : "bad"}
disabled={locked}
onClick={() => act('breaker')} />
)}>
[ {externalPowerStatus.externalPowerText} ]
</LabeledList.Item>
<LabeledList.Item label="Power Cell">
<ProgressBar
color="good"
value={adjustedCellChange} />
</LabeledList.Item>
<LabeledList.Item
label="Charge Mode"
color={chargingStatus.color}
buttons={(
<Button
icon={data.chargeMode ? 'sync' : 'times'}
content={data.chargeMode ? 'Auto' : 'Off'}
selected={data.chargeMode}
disabled={locked}
onClick={() => act('charge')} />
)}>
[ {chargingStatus.chargingText} ]
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Power Channels">
<LabeledList>
{channelArray.map(channel => {
const { topicParams } = channel;
return (
<LabeledList.Item
key={channel.title}
label={channel.title}
buttons={(
<Fragment>
<Box inline mx={2}
color={channel.status >= 2 ? 'good' : 'bad'}>
{channel.status >= 2 ? 'On' : 'Off'}
</Box>
<Button
icon="sync"
content="Auto"
selected={!locked && (
channel.status === 1 || channel.status === 3
)}
disabled={locked}
onClick={() => act('channel', topicParams.auto)} />
<Button
icon="power-off"
content="On"
selected={!locked && channel.status === 2}
disabled={locked}
onClick={() => act('channel', topicParams.on)} />
<Button
icon="times"
content="Off"
selected={!locked && channel.status === 0}
disabled={locked}
onClick={() => act('channel', topicParams.off)} />
</Fragment>
)}>
{channel.powerLoad} W
</LabeledList.Item>
);
})}
<LabeledList.Item label="Total Load">
<b>{data.totalLoad} W</b>
</LabeledList.Item>
</LabeledList>
</Section>
<Section
title="Misc"
buttons={!!data.siliconUser && (
<Fragment>
{!!data.malfStatus && (
<Button
icon={malfStatus.icon}
content={malfStatus.content}
color="bad"
onClick={() => act(malfStatus.action)} />
)}
<Button
icon="lightbulb-o"
content="Overload"
onClick={() => act('overload')} />
</Fragment>
)}>
<LabeledList>
<LabeledList.Item
label="Cover Lock"
buttons={(
<Button
icon={data.coverLocked ? 'lock' : 'unlock'}
content={data.coverLocked ? 'Engaged' : 'Disengaged'}
selected={data.coverLocked}
disabled={locked}
onClick={() => act('cover')} />
)} />
<LabeledList.Item
label="Night Shift Lighting"
buttons={(
<Button
icon="lightbulb-o"
content={data.nightshiftLights ? 'Enabled' : 'Disabled'}
selected={data.nightshiftLights}
onClick={() => act('toggle_nightshift')} />
)} />
</LabeledList>
</Section>
</Fragment>
);
};
@@ -0,0 +1,60 @@
import { useBackend } from '../../backend';
import { Button, Flex, NoticeBox } from '../../components';
/**
* This component by expects the following fields to be returned
* from ui_data:
*
* - siliconUser: boolean
* - locked: boolean
* - normallyLocked: boolean
*
* And expects the following ui_act action to be implemented:
*
* - lock - for toggling the lock as a silicon user.
*
* All props can be redefined if you want custom behavior, but
* it's preferred to stick to defaults.
*/
export const InterfaceLockNoticeBox = (props, context) => {
const { act, data } = useBackend(context);
const {
siliconUser = data.siliconUser,
locked = data.locked,
normallyLocked = data.normallyLocked,
onLockStatusChange = () => act('lock'),
accessText = 'an ID card',
} = props;
// For silicon users
if (siliconUser) {
return (
<NoticeBox color={siliconUser && 'grey'}>
<Flex align="center">
<Flex.Item>
Interface lock status:
</Flex.Item>
<Flex.Item grow="1" />
<Flex.Item>
<Button
m="0"
color={normallyLocked ? 'red' : 'green'}
icon={normallyLocked ? 'lock' : 'unlock'}
content={normallyLocked ? 'Locked' : 'Unlocked'}
onClick={() => {
if (onLockStatusChange) {
onLockStatusChange(!locked);
}
}} />
</Flex.Item>
</Flex>
</NoticeBox>
);
}
// For everyone else
return (
<NoticeBox>
Swipe {accessText}{' '}
to {locked ? 'unlock' : 'lock'} this interface.
</NoticeBox>
);
};
File diff suppressed because one or more lines are too long