initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
assets/* binary
|
||||
@@ -0,0 +1,2 @@
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2016 Bjorn Neergaard (neersighted), tgui contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
|
||||
|
||||
- [tgui](#tgui)
|
||||
- [Concepts](#concepts)
|
||||
- [Using It](#using-it)
|
||||
- [Copypasta](#copypasta)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
# tgui
|
||||
tgui is the user interface library of /tg/station. It is rendered clientside, based on JSON data sent from the server. Clicks are processed on the server, in a similar method to native BYOND `Topic()`.
|
||||
|
||||
Basic tgui consists of defining a few procs. In these procs you will handle a request to open or update a UI (typically by updating a UI if it exists or setting up and opening it if it does not), a request for data, in which you build a list to be passed as JSON to the UI, and an action handler, which handles any user input. In addition, you will write a HTML template file which renders your data and provides actionable inputs.
|
||||
|
||||
tgui is very different from most UIs you will encounter in BYOND programming, and is heavily reliant of Javascript and web technologies as opposed to DM. However, if you are familiar with NanoUI (a library which can be found on almost every other SS13 codebase), tgui should be fairly easy to pick up.
|
||||
|
||||
tgui is a fork of NanoUI. The server-side code (DM) is similar and derived from NanoUI, while the clientside is a wholly new project with no code in common.
|
||||
|
||||
## Concepts
|
||||
tgui is loosely based a MVVM architecture. MVVM stands for model, view, view model.
|
||||
- A model is the object that a UI represents. This is the atom a UI corresponds to in the game world in most cases, and is known as the `src_object` in tgui.
|
||||
- The view model is how data is represented in terms of the view. In tgui, this is the `ui_data` proc which munges whatever complex data your `src_object` has into a list.
|
||||
- The view is how the data is rendered. This is the template, a HTML (plus mustaches and other goodies) file which is compiled into the tgui blob that the browser executes.
|
||||
|
||||
Not included in the MVVM model are other important concepts:
|
||||
- The action/topic handler, `ui_act`, is what recieves input from the user and acts on it.
|
||||
- The request/update proc, `ui_interact` is where you open your UI and set options like title, size, autoupdate, theme, and more.
|
||||
- Finally, `ui_state`s (set in `ui_interact`) dictate under what conditions a UI may be interacted with. This may be the standard checks that check if you are in range and conscious, or more.
|
||||
|
||||
States are easy to write and extend, and what make tgui interactions so powerful. Because states can over overridden from other procs, you can build powerful interactions for embedded objects or remote access.
|
||||
|
||||
## Using It
|
||||
All these examples and abstracts sound great, you might say. But you also might say, "How do I use it?"
|
||||
|
||||
Examples can be as simple or as complex as you would like. Let's start with a very basic hello world.
|
||||
|
||||
```DM
|
||||
/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state)
|
||||
ui.open()
|
||||
```
|
||||
|
||||
This is the proc that defines our interface. There's a bit going on here, so let's break it down. First, we override the ui_interact proc on our object. This will be called by `interact` for you, which is in turn called by `attack_hand` (or `attack_self` for items). `ui_interact` is also called to update a UI (hence the `try_update_ui`), so we accept an existing UI to update. The `state` is a default argument so that a caller can overload it with named arguments (`ui_interact(state = overloaded_state)`) if needed.
|
||||
|
||||
Inside the `if(!ui)` block (which means we are creating a new UI), we choose our template, title, and size; we can also set various options like `style` (for themes), or autoupdate. These options will be elaborated on later (as will `ui_state`s).
|
||||
|
||||
After `ui_interact`, we need to define `ui_data`. This just returns a list of data for our object to use. Let's imagine our object has a few vars:
|
||||
|
||||
```DM
|
||||
/obj/machinery/my_machine/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["health"] = health
|
||||
data["color"] = color
|
||||
|
||||
return data
|
||||
```
|
||||
|
||||
The `ui_data` proc is what people often find the hardest about tgui, but its really quite simple! You just need to represent your object as numbers, strings, and lists, instead of atoms and datums.
|
||||
|
||||
Finally, the `ui_act` proc is called by the interface whenever the user used an input. The input's `action` and `params` are passed to the proc.
|
||||
|
||||
```DM
|
||||
/obj/machinery/my_machine/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("change_color")
|
||||
var/new_color = params["color"]
|
||||
if(!(color in allowed_coors))
|
||||
return
|
||||
color = new_color
|
||||
. = TRUE
|
||||
update_icon()
|
||||
```
|
||||
|
||||
The `..()` (parent call) is very important here, as it is how we check that the user is allowed to use this interface (to avoid so-called href exploits). It is also very important to clamp and sanitize all input here. Always assume the user is attempting to exploit the game.
|
||||
|
||||
Also note the use of `. = TRUE` (or `FALSE`), which is used to notify the UI that this input caused an update. This is especially important for UIs that do not auto-update, as otherwise the user will never see their change.
|
||||
|
||||
Finally, you have a template. This is also a source of confusion for many new users. Some basic HTML knowledge will get you a long way, however.
|
||||
|
||||
A template is regular HTML, with mustache for logic and built-in components to quickly build UIs. Here's how we might show some data (components will be elaborated on later).
|
||||
|
||||
In a template there are a few special values. `config` is always the same and is part of core tgui (it will be explained later), `data` is the data returned from `ui_data`, and `adata` is the same, but with certain values (numbers at this time) interpolated in order to allow animation.
|
||||
|
||||
```html
|
||||
<ui-display>
|
||||
<ui-section label='Health'>
|
||||
<span>{{data.health}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Color'>
|
||||
<span>{{data.color}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
```
|
||||
|
||||
Templates can be very confusing at first, as ternary operators, computed properties, and iterators are used quite a bit in more complex interfaces. Start with the basics, and work your way up. Much of the complexity stems from performance concerns. If in doubt, take the simpler approach and refactor if performance becomes an issue.
|
||||
|
||||
## Copypasta
|
||||
We all do it, even the best of us. If you just want to make a tgui **fast**, here's what you need (note that you'll probably be forced to clean your shit up upon code review):
|
||||
|
||||
```DM
|
||||
/obj/copypasta/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) // Remember to use the appropriate state.
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "copypasta", name, 300, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/copypasta/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["var"] = var
|
||||
|
||||
return data
|
||||
|
||||
/obj/copypasta/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("copypasta")
|
||||
var/newvar = params["var"]
|
||||
var = Clamp(newvar, min_val, max_val) // Just a demo of proper input sanitation.
|
||||
. = TRUE
|
||||
update_icon() // Not applicable to all objects.
|
||||
```
|
||||
|
||||
And the template:
|
||||
|
||||
```html
|
||||
<ui-display title='My Copypasta Section'>
|
||||
<ui-section label='Var'>
|
||||
<span>{{data.var}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Animated Var'>
|
||||
<span>{{adata.var}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
#RUN THIS IN THE tgui/ folder
|
||||
set -e
|
||||
export NODE_VERSION=4
|
||||
|
||||
if [ ! -d "/tmp/nvm" ]; then
|
||||
rm -rf /tmp/nvm && git clone https://github.com/creationix/nvm.git /tmp/nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source /tmp/nvm/nvm.sh && nvm install $NODE_VERSION
|
||||
fi
|
||||
|
||||
source /tmp/nvm/nvm.sh
|
||||
gulp --min
|
||||
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
echo node.js and all dependencies must be installed for this script to work.
|
||||
echo If this script fails try installing dependencies again.
|
||||
REM Build minified assets
|
||||
cmd /c gulp --min
|
||||
pause
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as f from './flags'
|
||||
import { gulp as g, postcss as s } from './plugins'
|
||||
|
||||
const entry = 'tgui.styl'
|
||||
|
||||
import gulp from 'gulp'
|
||||
export function css () {
|
||||
return gulp.src(`${f.src}/${entry}`)
|
||||
.pipe(g.if(f.debug, g.sourcemaps.init({loadMaps: true})))
|
||||
.pipe(g.stylus({
|
||||
url: 'data-url',
|
||||
paths: [ f.src ]
|
||||
}))
|
||||
.pipe(g.postcss([
|
||||
s.autoprefixer({ browsers: ['last 2 versions', 'ie >= 8'] }),
|
||||
s.gradient,
|
||||
s.opacity,
|
||||
s.rgba({oldie: true}),
|
||||
s.plsfilters({oldIE: true}),
|
||||
s.fontweights
|
||||
]))
|
||||
.pipe(g.bytediff.start())
|
||||
.pipe(g.if(f.min, g.cssnano({autoprefixer: false})))
|
||||
.pipe(g.if(f.debug, g.sourcemaps.write()))
|
||||
.pipe(g.bytediff.stop())
|
||||
.pipe(gulp.dest(f.dest))
|
||||
}
|
||||
export function watch_css () {
|
||||
gulp.watch(`${f.src}/**/*.styl`, css)
|
||||
return css()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
const flags = require('minimist')(process.argv.slice(2))
|
||||
|
||||
export const src = flags.src || 'src'
|
||||
export const dest = flags.dest || 'assets'
|
||||
|
||||
export const debug = flags.debug || flags.d
|
||||
export const min = flags.min || flags.m
|
||||
@@ -0,0 +1,62 @@
|
||||
import * as f from './flags'
|
||||
import { browserify as b, gulp as g } from './plugins'
|
||||
|
||||
const entry = 'tgui.js'
|
||||
|
||||
import { transform as babel } from 'babel-core'
|
||||
import { readFileSync as read } from 'fs'
|
||||
b.componentify.compilers['text/javascript'] = function (source, file) {
|
||||
const config = { sourceMaps: true }
|
||||
Object.assign(config, JSON.parse(read(`${f.src}/.babelrc`, 'utf8')))
|
||||
const compiled = babel(source, config)
|
||||
|
||||
return { source: compiled.code, map: compiled.map }
|
||||
}
|
||||
import { render as stylus } from 'stylus'
|
||||
b.componentify.compilers['text/stylus'] = function (source, file) {
|
||||
const config = { filename: file }
|
||||
const compiled = stylus(source, config)
|
||||
|
||||
return { source: compiled }
|
||||
}
|
||||
|
||||
import browserify from 'browserify'
|
||||
const bundle = browserify(`${f.src}/${entry}`, {
|
||||
debug: f.debug,
|
||||
cache: {},
|
||||
packageCache: {},
|
||||
extensions: [ '.js', '.ract' ],
|
||||
paths: [ f.src ]
|
||||
})
|
||||
if (f.min) bundle.plugin(b.collapse)
|
||||
bundle
|
||||
.transform(b.babelify)
|
||||
.plugin(b.helpers)
|
||||
.transform(b.componentify)
|
||||
.transform(b.globify)
|
||||
.transform(b.es3ify)
|
||||
|
||||
import buffer from 'vinyl-buffer'
|
||||
import gulp from 'gulp'
|
||||
import source from 'vinyl-source-stream'
|
||||
export function js () {
|
||||
return bundle.bundle()
|
||||
.pipe(source(entry))
|
||||
.pipe(buffer())
|
||||
.pipe(g.if(f.debug, g.sourcemaps.init({loadMaps: true})))
|
||||
.pipe(g.bytediff.start())
|
||||
.pipe(g.if(f.min, g.uglify({mangle: true, compress: {unsafe: true}})))
|
||||
.pipe(g.if(f.debug, g.sourcemaps.write()))
|
||||
.pipe(g.bytediff.stop())
|
||||
.pipe(gulp.dest(f.dest))
|
||||
}
|
||||
import gulplog from 'gulplog'
|
||||
export function watch_js () {
|
||||
bundle.plugin(b.watchify)
|
||||
bundle.on('update', js)
|
||||
bundle.on('error', err => {
|
||||
gulplog.error(err.toString())
|
||||
this.emit('end')
|
||||
})
|
||||
return js()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export const browserify = {
|
||||
babelify: require('babelify'),
|
||||
collapse: require('bundle-collapser/plugin'),
|
||||
componentify: require('ractive-componentify'),
|
||||
es3ify: require('es3ify'),
|
||||
globify: require('require-globify'),
|
||||
helpers: require('babelify-external-helpers'),
|
||||
watchify: require('watchify')
|
||||
}
|
||||
|
||||
export const gulp = require('gulp-load-plugins')({ replaceString: /^gulp(-|\.)|-/g })
|
||||
|
||||
export const postcss = {
|
||||
autoprefixer: require('autoprefixer'),
|
||||
fontweights: require('postcss-font-weights'),
|
||||
gradient: require('postcss-filter-gradient'),
|
||||
opacity: require('postcss-opacity'),
|
||||
plsfilters: require('pleeease-filters'),
|
||||
rgba: require('postcss-color-rgba-fallback')
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
const out = 'assets'
|
||||
|
||||
import { exec } from 'child_process'
|
||||
export function reload () {
|
||||
return exec('reload.bat')
|
||||
}
|
||||
import gulp from 'gulp'
|
||||
export function watch_reload () {
|
||||
gulp.watch(`${out}/**`, reload)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { gulp as g } from './plugins'
|
||||
|
||||
const out = 'assets'
|
||||
|
||||
import gulp from 'gulp'
|
||||
export function size () {
|
||||
return gulp.src(`${out}/**`)
|
||||
.pipe(g.size())
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import gulp from 'gulp'
|
||||
|
||||
import { css, watch_css } from './gulp/css'
|
||||
import { js, watch_js } from './gulp/js'
|
||||
import { reload, watch_reload } from './gulp/reload'
|
||||
import { size } from './gulp/size'
|
||||
|
||||
gulp.task(reload)
|
||||
gulp.task(size)
|
||||
|
||||
gulp.task('default', gulp.series(gulp.parallel(css, js), size))
|
||||
gulp.task('watch', gulp.parallel(watch_css, watch_js, watch_reload))
|
||||
@@ -0,0 +1,14 @@
|
||||
@echo off
|
||||
echo node.js 5.3.0 or newer must be installed for this script to work.
|
||||
echo If this script fails, try closing editors and running it again first.
|
||||
echo Any warnings about optional dependencies can be safely ignored.
|
||||
pause
|
||||
REM Install Gulp
|
||||
cmd /c npm install gulp-cli -g
|
||||
REM Install tgui dependencies
|
||||
cmd /c npm install
|
||||
REM Flatten dependency tree
|
||||
cmd /c npm dedupe
|
||||
REM Clean dependency tree
|
||||
cmd /c npm prune
|
||||
pause
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "tgui",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"autoprefixer": "6.3.3",
|
||||
"babel-core": "6.5.2",
|
||||
"babel-plugin-external-helpers": "6.5.0",
|
||||
"babel-polyfill": "6.5.0",
|
||||
"babel-preset-es2015": "6.5.0",
|
||||
"babel-preset-es2015-loose": "7.0.0",
|
||||
"babel-register": "6.5.2",
|
||||
"babelify": "7.2.0",
|
||||
"babelify-external-helpers": "1.1.0",
|
||||
"browserify": "13.0.0",
|
||||
"bulkify": "1.1.1",
|
||||
"bundle-collapser": "1.2.1",
|
||||
"dom4": "1.7.0",
|
||||
"es3ify": "0.2.1",
|
||||
"fg-loadcss": "1.0.0-0",
|
||||
"fontfaceobserver": "1.6.3",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-bytediff": "1.0.0",
|
||||
"gulp-cssnano": "2.1.1",
|
||||
"gulp-if": "2.0.0",
|
||||
"gulp-load-plugins": "1.2.0",
|
||||
"gulp-postcss": "6.1.0",
|
||||
"gulp-size": "2.0.0",
|
||||
"gulp-sourcemaps": "1.6.0",
|
||||
"gulp-stylus": "2.3.0",
|
||||
"gulp-uglify": "1.5.2",
|
||||
"gulplog": "1.0.0",
|
||||
"html5shiv": "3.7.3",
|
||||
"ie8": "0.3.2",
|
||||
"minimist": "1.2.0",
|
||||
"paths-js": "0.4.2",
|
||||
"pleeease-filters": "2.0.0",
|
||||
"postcss": "5.0.16",
|
||||
"postcss-color-rgba-fallback": "2.2.0",
|
||||
"postcss-filter-gradient": "0.2.2",
|
||||
"postcss-font-weights": "2.0.1",
|
||||
"postcss-opacity": "3.0.0",
|
||||
"ractive": "0.7.3",
|
||||
"ractive-componentify": "0.2.4",
|
||||
"ractive-events-keys": "0.2.1",
|
||||
"ractive-transitions-fade": "0.3.1",
|
||||
"require-globify": "1.3.0",
|
||||
"stylus": "0.53.0",
|
||||
"vinyl-buffer": "1.0.0",
|
||||
"vinyl-source-stream": "1.1.0",
|
||||
"watchify": "3.7.0"
|
||||
},
|
||||
"browser": {
|
||||
"ractive": "ractive/ractive-legacy.runtime"
|
||||
},
|
||||
"require-globify": {
|
||||
"appliesTo": {
|
||||
"includeExtensions": [
|
||||
".js",
|
||||
".ract"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
REM Get the documents folder from the registry.
|
||||
for /f "tokens=3* delims= " %%a in (
|
||||
'reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Personal"'
|
||||
) do (
|
||||
set documents=%%a
|
||||
)
|
||||
REM Copy assets to the BYOND cache
|
||||
cmd /c copy assets\* "%documents%\BYOND\cache" /y
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015-loose"
|
||||
],
|
||||
"plugins": [
|
||||
"external-helpers"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
oninit () {
|
||||
this.observe('value', (newkey, oldkey, keypath) => {
|
||||
const { min, max } = this.get()
|
||||
const value = Math.clamp(min, max, newkey)
|
||||
this.animate('percentage', Math.round((value - min) / (max - min) * 100))
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class='bar'>
|
||||
<div class='barFill {{state}}' style='width: {{percentage}}%'></div>
|
||||
<span class='barText'>{{yield}}</span>
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
context = selector()
|
||||
|
||||
.bar
|
||||
display: inline-block
|
||||
position: relative
|
||||
vertical-align: middle
|
||||
width: 100%
|
||||
height: 20px
|
||||
line-height: @height - 3px
|
||||
padding: 1px
|
||||
|
||||
border: 1px solid bar-color-border
|
||||
background: bar-color-background
|
||||
|
||||
.barText
|
||||
@extend {context} $fontReset
|
||||
position: absolute
|
||||
top: 0
|
||||
right: 3px
|
||||
|
||||
.barFill
|
||||
display: block
|
||||
height: 100%
|
||||
|
||||
transition: background-color 1s
|
||||
background-color: bar-color-normal
|
||||
&.good
|
||||
background-color: bar-color-good
|
||||
&.average
|
||||
background-color: bar-color-average
|
||||
&.bad
|
||||
background-color: bar-color-bad
|
||||
@@ -0,0 +1,59 @@
|
||||
<script>
|
||||
import { UI_INTERACTIVE } from 'util/constants'
|
||||
import { act } from 'util/byond'
|
||||
|
||||
component.exports = {
|
||||
computed: {
|
||||
clickable () {
|
||||
if (this.get('enabled') && !this.get('state')) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
enabled () {
|
||||
if (this.get('config.status') === UI_INTERACTIVE) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
styles () {
|
||||
let extra = ''
|
||||
if (this.get('tooltip-side'))
|
||||
extra = ` tooltip-${this.get('tooltip-side')}`
|
||||
if (this.get('grid'))
|
||||
extra += ' gridable'
|
||||
if (this.get('enabled')) {
|
||||
const state = this.get('state')
|
||||
const style = this.get('style')
|
||||
if (!state) {
|
||||
return `active normal ${style} ${extra}`
|
||||
} else {
|
||||
return `inactive ${state} ${extra}`
|
||||
}
|
||||
} else {
|
||||
return `inactive disabled ${extra}`
|
||||
}
|
||||
}
|
||||
},
|
||||
oninit () {
|
||||
this.on('press', (event) => {
|
||||
const { action, params } = this.get()
|
||||
act(this.get('config.ref'), action, params)
|
||||
event.node.blur()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<span class='button {{styles}}'
|
||||
unselectable='on'
|
||||
{{#clickable}}tabindex='0'{{/}}
|
||||
data-tooltip='{{tooltip}}'
|
||||
on-mouseover-mousemove='hover'
|
||||
on-mouseleave='unhover'
|
||||
on-click-enter='{{#clickable}}press{{/}}'>
|
||||
{{#if icon}}
|
||||
<i class='fa fa-{{icon}}'></i>
|
||||
{{/if}}
|
||||
{{yield}}
|
||||
</span>
|
||||
@@ -0,0 +1,41 @@
|
||||
context = selector()
|
||||
|
||||
buttoncolor(selector, color)
|
||||
&.{selector}
|
||||
transition: background-color 0.5s
|
||||
background-color: color
|
||||
&.{selector}.active:hover,
|
||||
&.{selector}.active:focus
|
||||
transition: background-color 0.25s
|
||||
background-color: lighten(color, button-lighten-hover)
|
||||
outline: 0
|
||||
|
||||
span.button
|
||||
@extend {context} $fontReset
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
height: 20px
|
||||
line-height: @height - 3px
|
||||
padding: 0 5px
|
||||
white-space: nowrap
|
||||
|
||||
border: 1px solid button-color-border
|
||||
|
||||
.fa
|
||||
padding-right: 2px
|
||||
|
||||
buttoncolor(normal, button-color-normal)
|
||||
buttoncolor(disabled, button-color-disabled)
|
||||
buttoncolor(selected, button-color-selected)
|
||||
buttoncolor(caution, button-color-caution)
|
||||
buttoncolor(danger, button-color-danger)
|
||||
|
||||
&.gridable
|
||||
width: 125px
|
||||
margin: 2px 0
|
||||
|
||||
span:not(.button) + span.button
|
||||
margin-left: 5px
|
||||
|
||||
span.button + span:not(.button)
|
||||
margin-left: 5px
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class='display'>
|
||||
{{#if title}}
|
||||
<header>
|
||||
<h3>{{title}}</h3>
|
||||
{{#if button}}
|
||||
<div class='buttonRight'>{{yield button}}</div>
|
||||
{{/if}}
|
||||
</header>
|
||||
{{/if}}
|
||||
<article>
|
||||
{{yield}}
|
||||
</article>
|
||||
</div>
|
||||
@@ -0,0 +1,29 @@
|
||||
div.display
|
||||
width: 100%
|
||||
padding: 4px
|
||||
margin: 6px 0
|
||||
|
||||
background-color: display-color-background // Transparent background.
|
||||
box-shadow: inset 0 0 5px display-color-shadow
|
||||
|
||||
header
|
||||
display: block
|
||||
position: relative
|
||||
width: 100%
|
||||
padding: 0 4px
|
||||
margin-bottom: 6px
|
||||
|
||||
color: display-color-title
|
||||
|
||||
border-bottom: rule-size solid rule-color-normal
|
||||
|
||||
.buttonRight
|
||||
position: absolute
|
||||
bottom: 6px
|
||||
right: 4px
|
||||
|
||||
article
|
||||
display: table
|
||||
width: 100%
|
||||
|
||||
border-collapse: collapse;
|
||||
@@ -0,0 +1,13 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
oninit () {
|
||||
this.on('clear', () => {
|
||||
this.set('value', '')
|
||||
this.find('input').focus()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<input type='text' value='{{value}}' placeholder='{{placeholder}}'/>
|
||||
<ui-button icon='refresh' on-press='clear'/>
|
||||
@@ -0,0 +1,16 @@
|
||||
input
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
height: 20px
|
||||
line-height: @height - 3px
|
||||
padding: 0 5px
|
||||
white-space: nowrap
|
||||
|
||||
color: input-color-text
|
||||
background-color: input-color-background
|
||||
border: 1px solid input-color-border
|
||||
|
||||
&::placeholder
|
||||
color: input-color-placeholder
|
||||
&::-ms-clear
|
||||
display: none
|
||||
@@ -0,0 +1,88 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
data: {
|
||||
graph: require('paths-js/smooth-line'),
|
||||
xaccessor: point => point.x,
|
||||
yaccessor: point => point.y
|
||||
},
|
||||
computed: {
|
||||
size () {
|
||||
const points = this.get('points')
|
||||
return points[0].length
|
||||
},
|
||||
scale () {
|
||||
const points = this.get('points')
|
||||
return Math.max(...Array.map(points, a => Math.max(...Array.map(a, p => p.y))))
|
||||
},
|
||||
xaxis () {
|
||||
const xinc = this.get('xinc')
|
||||
const size = this.get('size')
|
||||
return Array.from(Array(size).keys()).filter(num => num && num % xinc == 0)
|
||||
},
|
||||
yaxis () {
|
||||
const yinc = this.get('yinc')
|
||||
const scale = this.get('scale')
|
||||
return Array.from(Array(yinc).keys()).map(num => Math.round((scale * (++num / 100)) * 10))
|
||||
}
|
||||
},
|
||||
oninit () {
|
||||
this.on({
|
||||
enter (event) {
|
||||
this.set('selected', event.index.count)
|
||||
},
|
||||
exit (event) {
|
||||
this.set('selected')
|
||||
}
|
||||
})
|
||||
window.addEventListener('resize', (event) => {
|
||||
this.set('width', this.el.clientWidth)
|
||||
})
|
||||
},
|
||||
onrender () {
|
||||
this.set('width', this.el.clientWidth)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svg class='linegraph' width='100%' height='{{height + 10}}'>
|
||||
<g transform='translate(0, 5)'>
|
||||
{{#graph({data: points, xaccessor: xaccessor, yaccessor: yaccessor, width: width, height: height})}}
|
||||
{{#each xaxis}}
|
||||
<line x1='{{xscale(.)}}' x2='{{xscale(.)}}' y1='0' y2='{{height}}' stroke='darkgray'/>
|
||||
{{#if @index % 2 == 0}}
|
||||
<text x='{{xscale(.)}}' y='{{height - 5}}' text-anchor='middle' fill='white'>{{(size - .) * xfactor}} {{xunit}}</text>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{#each yaxis}}
|
||||
<line x1='0' x2='{{width}}' y1='{{yscale(.)}}' y2='{{yscale(.)}}' stroke='darkgray'/>
|
||||
<text x='0' y='{{yscale(.) - 5}}' text-anchor='begin' fill='white'>{{. * yfactor}} {{yunit}}</text>
|
||||
{{/each}}
|
||||
{{#each curves:curve}}
|
||||
<path d='{{area.path.print()}}' fill='{{colors[curve]}}' opacity='0.1'/>
|
||||
{{/each}}
|
||||
{{#each curves:curve}}
|
||||
<path d='{{line.path.print()}}' stroke='{{colors[curve]}}' fill='none'/>
|
||||
{{/each}}
|
||||
{{#each curves:curve}}
|
||||
{{#each line.path.points():count}}
|
||||
<circle transform='translate({{.}})' r='{{selected == count ? 10 : 4}}' fill='{{colors[curve]}}' on-mouseenter='enter' on-mouseleave='exit'/>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
{{#each curves:curve}}
|
||||
{{#each line.path.points():count}}
|
||||
{{#if selected == count }}
|
||||
<text transform='translate({{.}}) {{count <= size / 2 ? "translate(15, 4)" : "translate(-15, 4)"}}' text-anchor='{{count <= size / 2 ? "start" : "end"}}' fill='white'>
|
||||
{{item[count].y * yfactor}} {{yunit}} @ {{(size - item[count].x) * xfactor}} {{xunit}}
|
||||
</text>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
{{#each curves:curve}}
|
||||
<g transform='translate({{(width / (curves.length + 1)) * (@index + 1)}}, 10)'>
|
||||
<circle r='4' fill='{{colors[curve]}}'/>
|
||||
<text x='8' y='4' fill='white'>{{legend[curve]}}</text>
|
||||
</g>
|
||||
{{/each}}
|
||||
{{/graph}}
|
||||
</g>
|
||||
</svg>
|
||||
@@ -0,0 +1,2 @@
|
||||
svg.linegraph
|
||||
overflow: hidden
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class='notice'>
|
||||
{{yield}}
|
||||
</div>
|
||||
@@ -0,0 +1,27 @@
|
||||
div.notice
|
||||
margin: 8px 0
|
||||
padding: 4px
|
||||
|
||||
box-shadow: none
|
||||
|
||||
color: text-color-inverse
|
||||
font-weight: bold
|
||||
font-style: italic
|
||||
|
||||
background-color: notice-color-first
|
||||
background-image: repeating-linear-gradient(
|
||||
-45deg,
|
||||
notice-color-first,
|
||||
notice-color-first 10px,
|
||||
notice-color-second 10px,
|
||||
notice-color-second 20px
|
||||
)
|
||||
|
||||
.label
|
||||
color: text-color-inverse
|
||||
|
||||
.content:only-of-type
|
||||
padding: 0
|
||||
|
||||
hr
|
||||
background-color: rule-color-dark
|
||||
@@ -0,0 +1,29 @@
|
||||
<script>
|
||||
import { winset } from 'util/byond'
|
||||
import { resize } from 'util/dragresize'
|
||||
|
||||
component.exports = {
|
||||
oninit () {
|
||||
const onresize = resize.bind(this)
|
||||
const onrelease = () => this.set({ resize: false, x: null, y: null })
|
||||
|
||||
this.observe('config.fancy', (newkey, oldkey, keypath) => {
|
||||
winset(this.get('config.window'), 'can-resize', !newkey)
|
||||
|
||||
if (newkey) {
|
||||
document.addEventListener('mousemove', onresize)
|
||||
document.addEventListener('mouseup', onrelease)
|
||||
} else {
|
||||
document.removeEventListener('mousemove', onresize)
|
||||
document.removeEventListener('mouseup', onrelease)
|
||||
}
|
||||
})
|
||||
|
||||
this.on('resize', () => this.toggle('resize'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{{#if config.fancy}}
|
||||
<div class='resize' on-mousedown='resize'></div>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,12 @@
|
||||
div.resize
|
||||
position: fixed
|
||||
bottom: 0
|
||||
right: 0
|
||||
width: 0
|
||||
height: 0
|
||||
|
||||
border-style: solid;
|
||||
border-width: 0 0 45px 45px;
|
||||
border-color: transparent transparent resize-color transparent
|
||||
|
||||
transform: rotate(360deg)
|
||||
@@ -0,0 +1,12 @@
|
||||
<section class='{{#candystripe}}candystripe{{/candystripe}}'>
|
||||
{{#if label}}
|
||||
<span class='label' style='{{#labelcolor}}color:{{labelcolor}}{{/labelcolor}}'>{{label}}:</span>
|
||||
{{/if}}
|
||||
{{#if nowrap}}
|
||||
{{yield}}
|
||||
{{else}}
|
||||
<div class='content' style='{{#right}}float:right;{{/right}}'>
|
||||
{{yield}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
@@ -0,0 +1,33 @@
|
||||
/$cell
|
||||
display: table-cell
|
||||
margin: 0
|
||||
text-align: left
|
||||
vertical-align: middle
|
||||
padding: 3px 2px
|
||||
|
||||
section
|
||||
display: table-row
|
||||
width: 100%
|
||||
|
||||
&:not(:first-child)
|
||||
padding-top: 4px
|
||||
|
||||
&.candystripe:nth-child(even)
|
||||
background-color: section-color-candystripe
|
||||
|
||||
.label
|
||||
@extend $cell
|
||||
width: 1%
|
||||
padding-right: 32px
|
||||
white-space: nowrap
|
||||
|
||||
color: section-color-label
|
||||
|
||||
.content
|
||||
@extend $cell
|
||||
&:not(:last-child)
|
||||
padding-right: 16px
|
||||
|
||||
.line
|
||||
@extend $cell
|
||||
width: 100%
|
||||
@@ -0,0 +1,11 @@
|
||||
<div class='subdisplay'>
|
||||
{{#if title}}
|
||||
<header>
|
||||
<h4>{{title}}</h4>
|
||||
{{#if button}}{{yield button}}{{/if}}
|
||||
</header>
|
||||
{{/if}}
|
||||
<article>
|
||||
{{yield}}
|
||||
</article>
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
context = selector()
|
||||
|
||||
div.subdisplay
|
||||
width: 100%
|
||||
margin: 0
|
||||
|
||||
header
|
||||
@extend {context} div.display header
|
||||
|
||||
article
|
||||
@extend {context} div.display article
|
||||
@@ -0,0 +1,27 @@
|
||||
<link rel='ractive' href='components/tabs/tab.ract'>
|
||||
|
||||
<script>
|
||||
component.exports = {
|
||||
oninit () {
|
||||
this.set('active', this.findComponent('tab').get('name'))
|
||||
this.on('switch', event => {
|
||||
this.set('active', event.node.textContent.trim()) // Hack but it works...
|
||||
})
|
||||
|
||||
this.observe('active', (newkey, oldkey, path) => {
|
||||
for (let tab of this.findAllComponents('tab')) {
|
||||
tab.set('shown', (tab.get('name') === newkey))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<header>
|
||||
{{#each tabs}}
|
||||
<ui-button pane='{{.}}' on-press='switch'>{{.}}</ui-button>
|
||||
{{/each}}
|
||||
</header>
|
||||
<ui-display>
|
||||
{{>content}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,3 @@
|
||||
{{#if shown}}
|
||||
{{yield}}
|
||||
{{/if}}
|
||||
@@ -0,0 +1,56 @@
|
||||
<script>
|
||||
import { UI_INTERACTIVE, UI_UPDATE, UI_DISABLED } from 'util/constants'
|
||||
import { href, winset } from 'util/byond'
|
||||
import { drag } from 'util/dragresize'
|
||||
|
||||
component.exports = {
|
||||
computed: {
|
||||
visualStatus () {
|
||||
switch (this.get('config.status')) {
|
||||
case UI_INTERACTIVE: return 'good'
|
||||
case UI_UPDATE: return 'average'
|
||||
case UI_DISABLED: return 'bad'
|
||||
default: return 'bad'
|
||||
}
|
||||
}
|
||||
},
|
||||
oninit () {
|
||||
const ondrag = drag.bind(this)
|
||||
const onrelease = (event) => this.set({ drag: false, x: null, y: null })
|
||||
|
||||
this.observe('config.fancy', (newkey, oldkey, keypath) => {
|
||||
winset(this.get('config.window'), 'titlebar', !newkey)
|
||||
|
||||
if (newkey) {
|
||||
document.addEventListener('mousemove', ondrag)
|
||||
document.addEventListener('mouseup', onrelease)
|
||||
} else {
|
||||
document.removeEventListener('mousemove', ondrag)
|
||||
document.removeEventListener('mouseup', onrelease)
|
||||
}
|
||||
})
|
||||
|
||||
this.on({
|
||||
drag () {
|
||||
this.toggle('drag')
|
||||
},
|
||||
close () {
|
||||
winset(this.get('config.window'), 'is-visible', false)
|
||||
window.location.href = href({command: `uiclose ${this.get('config.ref')}`}, 'winset')
|
||||
},
|
||||
minimize () {
|
||||
winset(this.get('config.window'), 'is-minimized', true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<header class='titlebar' on-mousedown='drag'>
|
||||
<i class='statusicon fa fa-eye fa-2x {{visualStatus}}'></i>
|
||||
<span class='title'>{{yield}}</span>
|
||||
{{#if config.fancy}}
|
||||
<i class='minimize fa fa-minus fa-2x' on-click='minimize'></i>
|
||||
<i class='close fa fa-close fa-2x' on-click='close'></i>
|
||||
{{/if}}
|
||||
</header>
|
||||
@@ -0,0 +1,65 @@
|
||||
context = selector()
|
||||
|
||||
$titleButton
|
||||
display: inline-block
|
||||
position: relative
|
||||
padding: 7px // To make a bigger clickable area.
|
||||
margin: -7px
|
||||
|
||||
color: titlebar-color-button;
|
||||
|
||||
&:hover
|
||||
color: lighten(titlebar-color-button, button-lighten-hover)
|
||||
|
||||
header.titlebar
|
||||
position: fixed;
|
||||
z-index: 1
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
|
||||
background-color: titlebar-color-background
|
||||
border-bottom: 1px solid titlebar-color-coreshadow
|
||||
box-shadow: 0 3px 3px titlebar-color-shadow
|
||||
|
||||
.statusicon
|
||||
position: absolute
|
||||
top: 4px
|
||||
left: 12px
|
||||
transition: color 0.5s
|
||||
|
||||
.title
|
||||
position: absolute
|
||||
top: 6px
|
||||
left: 46px
|
||||
|
||||
color: titlebar-color-text
|
||||
font-size: 16px
|
||||
white-space: nowrap
|
||||
|
||||
.minimize
|
||||
@extend {context} $titleButton
|
||||
position: absolute
|
||||
top: 6px
|
||||
right: 46px
|
||||
.close
|
||||
@extend {context} $titleButton
|
||||
position: absolute
|
||||
top: 4px
|
||||
right: 12px
|
||||
|
||||
/.no-icons header.titlebar
|
||||
.statusicon
|
||||
font-size: 20px
|
||||
&::after
|
||||
content: "O"
|
||||
.minimize
|
||||
top: -2px
|
||||
font-size: 20px
|
||||
&::after
|
||||
content: "—"
|
||||
.close
|
||||
font-size: 20px
|
||||
&::after
|
||||
content: "X"
|
||||
@@ -0,0 +1,47 @@
|
||||
<script>
|
||||
const versions = [11, 10, 9, 8]
|
||||
|
||||
component.exports = {
|
||||
data: {
|
||||
userAgent: navigator.userAgent
|
||||
},
|
||||
computed: {
|
||||
ie () {
|
||||
if (document.documentMode) return document.documentMode
|
||||
for (let version in versions) {
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = `<!--[if IE ${version}]><span></span><![endif]-->`
|
||||
if (div.getElementsByTagName('span').length) return version
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
oninit () {
|
||||
this.on('debug', () => this.toggle('debug'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
{{#if config.fancy && ie && ie < 11}}
|
||||
<ui-notice>
|
||||
<span>You have an old (IE{{ie}}), end-of-life (click 'EOL Info' for more information) version of Internet Explorer installed.</span><br/>
|
||||
<span>To upgrade, click 'Upgrade IE' to download IE11 from Microsoft.</span><br/>
|
||||
<span>If you are unable to upgrade directly, click 'IE VMs' to download a VM with IE11 or Edge from Microsoft.</span><br/>
|
||||
<span>Otherwise, click 'No Frills' below to disable potentially incompatible features (and this message).</span>
|
||||
<hr/>
|
||||
<ui-button icon='close' action='tgui:nofrills'>No Frills</ui-button>
|
||||
<ui-button icon='internet-explorer' action='tgui:link' params='{"url": "http://windows.microsoft.com/en-us/internet-explorer/download-ie"}'>
|
||||
Upgrade IE</ui-button>
|
||||
<ui-button icon='edge' action='tgui:link' params='{"url": "https://dev.windows.com/en-us/microsoft-edge/tools/vms"}'>
|
||||
IE VMs</ui-button>
|
||||
<ui-button icon='info' action='tgui:link' params='{"url": "https://support.microsoft.com/en-us/lifecycle#gp/Microsoft-Internet-Explorer"}'>
|
||||
EOL Info</ui-button>
|
||||
<ui-button icon='bug' on-press='debug'>Debug Info</ui-button>
|
||||
{{#if debug}}
|
||||
<hr/>
|
||||
<span>Detected: IE{{ie}}</span><br/>
|
||||
<span>User Agent: {{userAgent}}</span>
|
||||
{{/if}}
|
||||
</ui-notice>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 425 200" opacity=".33">
|
||||
<path d="m 178.00399,0.03869 -71.20393,0 a 6.7613422,6.0255495 0 0 0 -6.76134,6.02555 l 0,187.87147 a 6.7613422,6.0255495 0 0 0 6.76134,6.02554 l 53.1072,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-101.544018 72.21628,104.699398 a 6.7613422,6.0255495 0 0 0 5.76015,2.87016 l 73.55487,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-187.87147 a 6.7613422,6.0255495 0 0 0 -6.76135,-6.02555 l -54.71644,0 a 6.7613422,6.0255495 0 0 0 -6.76133,6.02555 l 0,102.61935 L 183.76413,2.90886 a 6.7613422,6.0255495 0 0 0 -5.76014,-2.87017 z" />
|
||||
<path d="M 4.8446333,22.10875 A 13.412039,12.501842 0 0 1 13.477588,0.03924 l 66.118315,0 a 5.3648158,5.000737 0 0 1 5.364823,5.00073 l 0,79.87931 z" />
|
||||
<path d="m 420.15535,177.89119 a 13.412038,12.501842 0 0 1 -8.63295,22.06951 l -66.11832,0 a 5.3648152,5.000737 0 0 1 -5.36482,-5.00074 l 0,-79.87931 z" />
|
||||
</svg>
|
||||
<!-- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. -->
|
||||
<!-- http://creativecommons.org/licenses/by-sa/4.0/ -->
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 200 289.742" opacity=".33">
|
||||
<path d="m 93.537677,0 c -18.113125,0 -34.220133,3.11164 -48.323484,9.33437 -13.965092,6.22167 -24.612442,15.07114 -31.940651,26.5471 -7.1899398,11.33789 -10.3012266,24.74911 -10.3012266,40.23478 0,10.64662 2.7250026,20.46465 8.1751116,29.45258 5.615277,8.98686 14.038277,17.35204 25.268821,25.09436 11.230544,7.60531 26.507421,15.41835 45.830514,23.43782 19.983748,8.29557 34.848848,15.55471 44.592998,21.77638 9.74414,6.22273 16.7617,12.8585 21.05572,19.90951 4.29404,7.05208 6.44193,15.76408 6.44193,26.13459 0,16.17702 -5.20196,28.48222 -15.60673,36.91682 -10.2396,8.4347 -25.02203,12.6523 -44.345169,12.6523 -14.038171,0 -25.515247,-1.6594 -34.433618,-4.9777 -8.91837,-3.4566 -16.185572,-8.7113 -21.800839,-15.7633 -5.615277,-7.0521 -10.074795,-16.66088 -13.377899,-28.82812 l -24.7731626293945,0 0,56.82632 C 33.856769,286.07601 63.74904,289.74201 89.678383,289.74201 c 16.020027,0 30.719787,-1.3827 44.097337,-4.1479 13.54272,-2.9043 25.1041,-7.4676 34.68309,-13.6893 9.74413,-6.3597 17.34042,-14.5195 22.79052,-24.4748 5.4501,-10.09332 8.17511,-22.39959 8.17511,-36.91682 0,-12.99764 -3.3021,-24.33539 -9.90829,-34.0146 -6.44105,-9.81725 -15.52545,-18.52707 -27.25146,-26.13133 -11.56085,-7.60427 -27.91083,-15.83142 -49.05066,-24.68022 -17.50644,-7.19012 -30.719668,-13.68948 -39.638038,-19.49701 -8.918371,-5.80752 -18.607474,-12.43409 -24.096524,-18.87417 -5.426043,-6.36616 -9.658826,-15.07003 -9.658826,-24.88729 0,-9.26401 2.075414,-17.21345 6.223454,-23.85033 11.098298,-14.39748 41.286638,-1.79507 45.075609,24.34762 4.839392,6.77491 8.84935,16.24729 12.029515,28.4156 l 20.53234,0 0,-55.99967 c -4.47825,-5.92448 -9.95488,-10.63222 -15.90837,-14.37411 1.64055,0.47905 3.19039,1.02376 4.63865,1.64024 6.49861,2.62607 12.16793,7.32747 17.0073,14.10345 4.83939,6.77491 8.84935,16.24567 12.02952,28.41397 0,0 8.48128,-0.12894 8.48978,-0.002 0.41776,6.41494 -1.75339,9.45286 -4.12342,12.56104 -2.4174,3.16978 -5.14486,6.78973 -4.00278,13.0029 1.50786,8.20318 10.18354,10.59642 14.62194,9.31154 -3.31842,-0.49911 -5.31855,-1.74948 -5.31855,-1.74948 0,0 1.87646,0.99868 5.65117,-1.35981 -3.27695,0.95571 -10.70529,-0.79738 -11.80125,-6.76313 -0.95752,-5.20861 0.94654,-7.29514 3.40113,-10.51482 2.45462,-3.21968 5.28426,-6.95831 4.6843,-14.48824 l 0.003,0.002 8.92676,0 0,-55.99967 c -15.07125,-3.87168 -27.65314,-6.36042 -37.74671,-7.46586 -9.95531,-1.10755 -20.18823,-1.65981 -30.696613,-1.65981 z m 70.321603,17.30893 0.23805,40.3049 c 1.31808,1.22666 2.43965,2.27815 3.34081,3.10602 4.83939,6.77491 8.84934,16.24566 12.02951,28.41397 l 20.53234,0 0,-55.99967 c -6.67731,-4.59381 -19.83643,-10.47309 -36.14071,-15.82522 z m -28.12049,5.60551 8.56479,17.71655 c -11.97037,-6.46697 -13.84678,-9.71726 -8.56479,-17.71655 z m 22.79705,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m 15.22195,24.00848 8.56479,17.71655 c -11.97038,-6.46697 -13.84679,-9.71726 -8.56479,-17.71655 z m 22.79704,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m -99.11384,2.20764 8.56479,17.71655 c -11.970382,-6.46697 -13.846782,-9.71726 -8.56479,-17.71655 z m 22.79542,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z" />
|
||||
</svg>
|
||||
<!-- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. -->
|
||||
<!-- http://creativecommons.org/licenses/by-sa/4.0/ -->
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,51 @@
|
||||
<link rel='ractive' href='./airalarm/scrubbers.ract'>
|
||||
<link rel='ractive' href='./airalarm/status.ract'>
|
||||
<link rel='ractive' href='./airalarm/thresholds.ract'>
|
||||
<link rel='ractive' href='./airalarm/modes.ract'>
|
||||
<link rel='ractive' href='./airalarm/vents.ract'>
|
||||
|
||||
<ui-notice>
|
||||
{{#if data.siliconUser}}
|
||||
<ui-section label='Interface Lock'>
|
||||
<ui-button icon='{{data.locked ? "lock" : "unlock"}}' action='lock'>{{data.locked ? "Engaged" : "Disengaged"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span>Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface.</span>
|
||||
{{/if}}
|
||||
</ui-notice>
|
||||
<status/>
|
||||
{{#if !data.locked || data.siliconUser}}
|
||||
{{#if config.screen == "home"}}
|
||||
<ui-display title='Air Controls'>
|
||||
<ui-section>
|
||||
<ui-button icon='{{data.atmos_alarm ? "exclamation-triangle" : "exclamation"}}' style='{{data.atmos_alarm ? "caution" : null}}'
|
||||
action='{{data.atmos_alarm ? "reset" : "alarm"}}'>Area Atmosphere Alarm</ui-button>
|
||||
</ui-section>
|
||||
<ui-section>
|
||||
<ui-button icon='{{data.mode == 3 ? "exclamation-triangle" : "exclamation"}}' style='{{data.mode == 3 ? "danger" : null}}'
|
||||
action='mode' params='{"mode": {{data.mode == 3 ? 1 : 3}}}'>Panic Siphon</ui-button>
|
||||
</ui-section>
|
||||
<br/>
|
||||
<ui-section>
|
||||
<ui-button icon='sign-out' action='tgui:view' params='{"screen": "vents"}'>Vent Controls</ui-button>
|
||||
</ui-section>
|
||||
<ui-section>
|
||||
<ui-button icon='filter' action='tgui:view' params='{"screen": "scrubbers"}'>Scrubber Controls</ui-button>
|
||||
</ui-section>
|
||||
<ui-section>
|
||||
<ui-button icon='cog' action='tgui:view' params='{"screen": "modes"}'>Operating Mode</ui-button>
|
||||
</ui-section>
|
||||
<ui-section>
|
||||
<ui-button icon='bar-chart' action='tgui:view' params='{"screen": "thresholds"}'>Alarm Thresholds</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{elseif config.screen == "vents"}}
|
||||
<vents/>
|
||||
{{elseif config.screen == "scrubbers"}}
|
||||
<scrubbers/>
|
||||
{{elseif config.screen == "modes"}}
|
||||
<modes/>
|
||||
{{elseif config.screen == "thresholds"}}
|
||||
<thresholds/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@@ -0,0 +1 @@
|
||||
<ui-button icon='arrow-left' action='tgui:view' params='{"screen": "home"}'>Back</ui-button>
|
||||
@@ -0,0 +1,14 @@
|
||||
<link rel='ractive' href='./back.ract'>
|
||||
|
||||
<ui-display title='Operating Modes' button>
|
||||
{{#partial button}}
|
||||
<back/>
|
||||
{{/partial}}
|
||||
{{#each data.modes}}
|
||||
<ui-section>
|
||||
<ui-button icon='{{selected ? "check-square-o" : "square-o"}}'
|
||||
state='{{selected ? danger ? "danger" : "selected" : null}}'
|
||||
action='mode' params='{"mode": {{mode}}}'>{{name}}</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,35 @@
|
||||
<link rel='ractive' href='./back.ract'>
|
||||
|
||||
<ui-display title='Scrubber Controls' button>
|
||||
{{#partial button}}
|
||||
<back/>
|
||||
{{/partial}}
|
||||
{{#each data.scrubbers}}
|
||||
<ui-subdisplay title='{{long_name}}'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{power ? "power-off" : "close"}}' style='{{power ? "selected" : null}}'
|
||||
action='power' params='{"id_tag": "{{id_tag}}", "val": {{+!power}}}'>{{power ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Mode'>
|
||||
<ui-button icon='{{scrubbing ? "filter" : "sign-in"}}' style='{{scrubbing ? null : "danger"}}'
|
||||
action='scrubbing' params='{"id_tag": "{{id_tag}}", "val": {{+!scrubbing}}}'>{{scrubbing ? "Scrubbing" : "Siphoning"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Range'>
|
||||
<ui-button icon='{{widenet ? "expand" : "compress"}}' style='{{widenet ? "selected" : null}}'
|
||||
action='widenet' params='{"id_tag": "{{id_tag}}", "val": {{+!widenet}}}'>{{widenet ? "Expanded" : "Normal"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Filters'>
|
||||
<ui-button icon='{{filter_co2 ? "check-square-o" : "square-o"}}' style='{{filter_co2 ? "selected" : null}}'
|
||||
action='co2_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_co2}}}'>CO2</ui-button>
|
||||
<ui-button icon='{{filter_n2o ? "check-square-o" : "square-o"}}' style='{{filter_n2o ? "selected" : null}}'
|
||||
action='n2o_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_n2o}}}'>N2O</ui-button>
|
||||
<ui-button icon='{{filter_toxins ? "check-square-o" : "square-o"}}' style='{{filter_toxins ? "selected" : null}}'
|
||||
action='tox_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_toxins}}}'>Plasma</ui-button>
|
||||
<ui-button icon='{{filter_bz ? "check-square-o" : "square-o"}}' style='{{filter_bz ? "selected" : null}}'
|
||||
action='bz_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_bz}}}'>BZ</ui-button>
|
||||
</ui-section>
|
||||
</ui-subdisplay>
|
||||
{{else}}
|
||||
<span class='bad'>Error: No scrubbers connected.</span>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,30 @@
|
||||
<ui-display title='Air Status'>
|
||||
{{#if data.environment_data}}
|
||||
{{#each adata.environment_data}}
|
||||
<ui-section label='{{name}}'>
|
||||
<span class='{{danger_level == 2 ? "bad" : danger_level == 1 ? "average" : "good"}}'>
|
||||
{{Math.fixed(value, 2)}}{{unit}}
|
||||
</span>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
<ui-section label='Local Status'>
|
||||
<span class='{{data.danger_level == 2 ? "bad bold" : data.danger_level == 1 ? "average bold" : "good"}}'>
|
||||
{{data.danger_level == 2 ? "Danger (Internals Required)" : data.danger_level == 1 ? "Caution" : "Optimal"}}
|
||||
</span>
|
||||
</ui-section>
|
||||
<ui-section label='Area Status'>
|
||||
<span class='{{data.atmos_alarm || data.fire_alarm ? "bad bold" : "good"}}'>
|
||||
{{data.atmos_alarm ? "Atmosphere Alarm" : fire_alarm ? "Fire Alarm" : "Nominal"}}
|
||||
</span>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section label='Warning'>
|
||||
<span class='bad bold'>Cannot obtain air sample for analysis.</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if data.emagged}}
|
||||
<ui-section label='Warning'>
|
||||
<span class='bad bold'>Safety measures offline. Device may exhibit abnormal behavior.</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,31 @@
|
||||
<link rel='ractive' href='./back.ract'>
|
||||
|
||||
<ui-display title='Alarm Thresholds' button>
|
||||
{{#partial button}}
|
||||
<back/>
|
||||
{{/partial}}
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th></th>
|
||||
<th><span class="bad">min2</span></th>
|
||||
<th><span class="average">min1</span></th>
|
||||
<th><span class="average">max1</span></th>
|
||||
<th><span class="bad">max2</span></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{{#each data.thresholds}}<tr>
|
||||
<th>{{{name}}}</th>
|
||||
{{#each settings}}<td>
|
||||
<ui-button action='threshold' params='{"env": "{{env}}", "var": "{{val}}"}'>{{Math.fixed(selected, 2)}}</ui-button>
|
||||
</td>{{/each}}
|
||||
</tr>{{/each}}
|
||||
</tbody>
|
||||
<table>
|
||||
</ui-display>
|
||||
|
||||
<style>
|
||||
th, td {
|
||||
padding-right: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
<link rel='ractive' href='./back.ract'>
|
||||
|
||||
<ui-display title='Vent Controls' button>
|
||||
{{#partial button}}
|
||||
<back/>
|
||||
{{/partial}}
|
||||
{{#each data.vents}}
|
||||
<ui-subdisplay title='{{long_name}}'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{power ? "power-off" : "close"}}' style='{{power ? "selected" : null}}'
|
||||
action='power' params='{"id_tag": "{{id_tag}}", "val": {{+!power}}}'>{{power ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Mode'>
|
||||
<span>{{direction == "release" ? "Pressurizing" : "Siphoning"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Pressure Regulator'>
|
||||
<ui-button icon='sign-in' style='{{incheck ? "selected" : null}}'
|
||||
action='incheck' params='{"id_tag": "{{id_tag}}", "val": {{checks}}}'>Internal</ui-button>
|
||||
<ui-button icon='sign-out' style='{{excheck ? "selected" : null}}'
|
||||
action='excheck' params='{"id_tag": "{{id_tag}}", "val": {{checks}}}'>External</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Target Pressure'>
|
||||
<ui-button icon='pencil' action='set_external_pressure'
|
||||
params='{"id_tag": "{{id_tag}}"}'>{{Math.fixed(external)}}</ui-button>
|
||||
<ui-button icon='refresh' state='{{extdefault ? "disabled" : null}}' action='reset_external_pressure'
|
||||
params='{"id_tag": "{{id_tag}}"}'>Reset</ui-button>
|
||||
</ui-section>
|
||||
</ui-subdisplay>
|
||||
{{else}}
|
||||
<span class='bad'>Error: No vents connected.</span>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,39 @@
|
||||
<ui-display>
|
||||
<ui-section>
|
||||
<ui-button icon='{{data.oneAccess ? "unlock" : "lock"}}' action='one_access'>{{data.oneAccess ? "One" : "All"}} Required</ui-button>
|
||||
<ui-button icon='refresh' action='clear'>Clear</ui-button>
|
||||
</ui-section>
|
||||
<hr/>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>{{#each data.regions}}
|
||||
<th><span class='highlight bold'>{{name}}</span></th>
|
||||
{{/each}}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>{{#each data.regions}}
|
||||
<td>{{#each accesses}}
|
||||
<ui-button icon='{{req ? "check-square-o" : "square-o"}}' style='{{req ? "selected" : null}}'
|
||||
action='set' params='{"access": "{{id}}"}'>{{name}}</ui-button>
|
||||
<br/>
|
||||
{{/each}}</td>
|
||||
{{/each}}</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ui-display>
|
||||
|
||||
<style>
|
||||
table {
|
||||
width: 100%;
|
||||
border-spacing: 2px;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
td .button {
|
||||
margin-top: 4px
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
data: {
|
||||
powerState (status) {
|
||||
switch (status) {
|
||||
case 2: return 'good'
|
||||
case 1: return 'average'
|
||||
default: return 'bad'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
malfAction () {
|
||||
switch (this.get('data.malfStatus')) {
|
||||
case 1: return 'hack'
|
||||
case 2: return 'occupy'
|
||||
case 3: return 'deoccupy'
|
||||
}
|
||||
},
|
||||
malfButton () {
|
||||
switch (this.get('data.malfStatus')) {
|
||||
case 1: return 'Override Programming'
|
||||
case 2:
|
||||
case 4: return 'Shunt Core Process'
|
||||
case 3: return 'Return to Main Core'
|
||||
}
|
||||
},
|
||||
malfIcon () {
|
||||
switch (this.get('data.malfStatus')) {
|
||||
case 1: return 'terminal'
|
||||
case 2:
|
||||
case 4: return 'caret-square-o-down'
|
||||
case 3: return 'caret-square-o-left'
|
||||
}
|
||||
},
|
||||
powerCellStatusState () {
|
||||
const status = this.get('data.powerCellStatus')
|
||||
if (status > 50) return 'good'
|
||||
else if (status > 25) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-notice>
|
||||
{{#if data.siliconUser}}
|
||||
<ui-section label='Interface Lock'>
|
||||
<ui-button icon='{{data.locked ? "lock" : "unlock"}}' action='lock'>{{data.locked ? "Engaged" : "Disengaged"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span>Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface.</span>
|
||||
{{/if}}
|
||||
</ui-notice>
|
||||
<ui-display title='Power Status'>
|
||||
<ui-section label='Main Breaker'>
|
||||
{{#if data.locked && !data.siliconUser}}
|
||||
<span class='{{data.isOperating ? "good" : "bad"}}'>{{data.isOperating ? "On" : "Off"}}</span>
|
||||
{{else}}
|
||||
<ui-button icon='{{data.isOperating ? "power-off" : "close"}}' style='{{data.isOperating ? "selected" : null}}'
|
||||
action='breaker'>{{data.isOperating ? "On" : "Off"}}</ui-button>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
<ui-section label='External Power'>
|
||||
<span class='{{powerState(data.externalPower)}}'>{{data.externalPower == 2 ? "Good" : data.externalPower == 1 ? "Low" : "None"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Power Cell'>
|
||||
{{#if data.powerCellStatus != null}}
|
||||
<ui-bar min='0' max='100' value='{{data.powerCellStatus}}' state='{{powerCellStatusState}}'>{{Math.fixed(adata.powerCellStatus)}}%</ui-bar>
|
||||
{{else}}
|
||||
<span class='bad'>Removed</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
{{#if data.powerCellStatus != null}}
|
||||
<ui-section label='Charge Mode'>
|
||||
{{#if data.locked && !data.siliconUser}}
|
||||
<span class='{{data.chargeMode ? "good" : "bad"}}'>{{data.chargeMode ? "Auto" : "Off"}}</span>
|
||||
{{else}}
|
||||
<ui-button icon='{{data.chargeMode ? "refresh" : "close"}}' style='{{data.chargeMode ? "selected" : null}}'
|
||||
action='charge'>{{data.chargeMode ? "Auto" : "Off"}}</ui-button>
|
||||
{{/if}}
|
||||
|
||||
[<span class='{{powerState(data.chargingStatus)}}'>{{data.chargingStatus == 2 ? "Fully Charged" : data.chargingStatus == 1 ? "Charging" : "Not Charging"}}</span>]
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Power Channels'>
|
||||
{{#each data.powerChannels}}
|
||||
<ui-section label='{{title}}' nowrap>
|
||||
<div class='content'>{{Math.round(adata.powerChannels[@index].powerLoad)}} W</div>
|
||||
<div class='content'><span class='{{status >= 2 ? "good" : "bad"}}'>{{status >= 2 ? "On" : "Off"}}</span></div>
|
||||
<div class='content'>[<span>{{status == 1 || status == 3 ? "Auto" : "Manual"}}</span>]</div>
|
||||
<div class='content' style='float:right'>
|
||||
{{#if !data.locked || data.siliconUser}}
|
||||
<ui-button icon='refresh' state='{{status == 1 || status == 3 ? "selected" : null}}'
|
||||
action='channel' params='{{topicParams.auto}}'>Auto</ui-button>
|
||||
<ui-button icon='power-off' state='{{status == 2 ? "selected" : null}}' action='channel'
|
||||
params='{{topicParams.on}}'>On</ui-button>
|
||||
<ui-button icon='close' state='{{status == 0 ? "selected" : null}}' action='channel'
|
||||
params='{{topicParams.off}}'>Off</ui-button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
<ui-section label='Total Load'>
|
||||
<span class='bold'>{{Math.round(adata.totalLoad)}} W</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{#if data.siliconUser}}
|
||||
<ui-display title='System Overrides'>
|
||||
<ui-button icon='lightbulb-o' action='overload'>Overload</ui-button>
|
||||
{{#if data.malfStatus}}
|
||||
<ui-button icon='{{malfIcon}}' state='{{data.malfStatus == 4 ? "disabled" : null}}' action='{{malfAction}}'>{{malfButton}}</ui-button>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
<ui-notice>
|
||||
<ui-section label='Cover Lock'>
|
||||
{{#if data.locked && !data.siliconUser}}
|
||||
<span>{{data.coverLocked ? "Engaged" : "Disengaged"}}</span>
|
||||
{{else}}
|
||||
<ui-button icon='{{data.coverLocked ? "lock" : "unlock"}}' action='cover'>{{data.coverLocked ? "Engaged" : "Disengaged"}}</ui-button>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-notice>
|
||||
@@ -0,0 +1,14 @@
|
||||
<ui-display title='Alarms'>
|
||||
<ul>
|
||||
{{#each data.priority}}
|
||||
<li><ui-button icon='close' style='danger' action='clear' params='{"zone": "{{.}}"}'>{{.}}</ui-button></li>
|
||||
{{else}}
|
||||
<li><span class='good'>No Priority Alerts</span></li>
|
||||
{{/each}}
|
||||
{{#each data.minor}}
|
||||
<li><ui-button icon='close' style='caution' action='clear' params='{"zone": "{{.}}"}'>{{.}}</ui-button></li>
|
||||
{{else}}
|
||||
<li><span class='good'>No Minor Alerts</span></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,40 @@
|
||||
<ui-display title='{{data.tank ? data.sensors[0].long_name : null}}'>
|
||||
{{#each adata.sensors}}
|
||||
<ui-subdisplay title='{{!data.tank ? long_name : null}}'>
|
||||
<ui-section label='Pressure'>
|
||||
<span>{{Math.fixed(pressure, 2)}} kPa</span>
|
||||
</ui-section>
|
||||
{{#if temperature}}
|
||||
<ui-section label='Temperature'>
|
||||
<span>{{Math.fixed(temperature, 2)}} K</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#each gases:id}}
|
||||
<ui-section label='{{id}}'>
|
||||
<span>{{Math.fixed(., 2)}}%</span>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-subdisplay>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
{{#if data.tank}}
|
||||
<ui-display title='Controls' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='refresh' action='reconnect'>Reconnect</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Input Injector'>
|
||||
<ui-button icon='{{data.inputting ? "power-off" : "close"}}' style='{{data.inputting ? "selected" : null}}' action='input'>
|
||||
{{data.inputting ? "Injecting": "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Input Rate'>
|
||||
<span>{{Math.fixed(adata.inputRate)}} L/s</span>
|
||||
</ui-section>
|
||||
<ui-section label='Output Regulator'>
|
||||
<ui-button icon='{{data.outputting ? "power-off" : "close"}}' style='{{data.outputting ? "selected" : null}}' action='output'>
|
||||
{{data.outputting ? "Open": "Closed"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Output Pressure'>
|
||||
<ui-button icon='pencil' action='pressure'>{{Math.round(adata.outputPressure)}} kPa</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,27 @@
|
||||
<ui-display>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}' style='{{data.on ? "selected" : null}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Output Pressure'>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.pressure == data.max_pressure ? "disabled" : null}}' action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
<span>{{Math.round(adata.pressure)}} kPa</span>
|
||||
</ui-section>
|
||||
<ui-section label='Filter'>
|
||||
<ui-button state='{{data.filter_type == "" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": ""}'>Nothing</ui-button>
|
||||
<ui-button state='{{data.filter_type == "plasma" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "plasma"}'>Plasma</ui-button>
|
||||
<ui-button state='{{data.filter_type == "o2" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "o2"}'>O2</ui-button>
|
||||
<ui-button state='{{data.filter_type == "n2" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "n2"}'>N2</ui-button>
|
||||
<ui-button state='{{data.filter_type == "co2" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "co2"}'>CO2</ui-button>
|
||||
<ui-button state='{{data.filter_type == "n2o" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "n2o"}'>N2O</ui-button>
|
||||
<ui-button state='{{data.filter_type == "bz" ? "selected" : null}}'
|
||||
action='filter' params='{"mode": "bz"}'>BZ</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,33 @@
|
||||
<ui-display>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}' style='{{data.on ? "selected" : null}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Output Pressure'>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.set_pressure == data.max_pressure ? "disabled" : null}}' action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
<span>{{Math.round(adata.set_pressure)}} kPa</span>
|
||||
</ui-section>
|
||||
<ui-section label='Node 1'>
|
||||
<ui-button icon='fast-backward' state='{{data.node1_concentration == 0 ? "disabled" : null}}'
|
||||
action='node1' params='{"concentration": -0.1}'/>
|
||||
<ui-button icon='backward' state='{{data.node1_concentration == 0 ? "disabled" : null}}'
|
||||
action='node1' params='{"concentration": -0.01}'/>
|
||||
<ui-button icon='forward' state='{{data.node1_concentration == 100 ? "disabled" : null}}'
|
||||
action='node1' params='{"concentration": 0.01}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.node1_concentration == 100 ? "disabled" : null}}'
|
||||
action='node1' params='{"concentration": 0.1}'/>
|
||||
<span>{{Math.round(adata.node1_concentration)}}%</span>
|
||||
</ui-section>
|
||||
<ui-section label='Node 2'>
|
||||
<ui-button icon='fast-backward' state='{{data.node2_concentration == 0 ? "disabled" : null}}'
|
||||
action='node2' params='{"concentration": -0.1}'/>
|
||||
<ui-button icon='backward' state='{{data.node2_concentration == 0 ? "disabled" : null}}'
|
||||
action='node2' params='{"concentration": -0.01}'/>
|
||||
<ui-button icon='forward' state='{{data.node2_concentration == 100 ? "disabled" : null}}'
|
||||
action='node2' params='{"concentration": 0.01}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.node2_concentration == 100 ? "disabled" : null}}'
|
||||
action='node2' params='{"concentration": 0.1}'/>
|
||||
<span>{{Math.round(adata.node2_concentration)}}%</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,19 @@
|
||||
<ui-display>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}' style='{{data.on ? "selected" : null}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
{{#if data.max_rate}}
|
||||
<ui-section label='Transfer Rate'>
|
||||
<ui-button icon='pencil' action='rate' params='{"rate": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.rate == data.max_rate ? "disabled" : null}}' action='transfer' params='{"rate": "max"}'>Max</ui-button>
|
||||
<span>{{Math.round(adata.rate)}} L/s</span>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section label='Output Pressure'>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.pressure == data.max_pressure ? "disabled" : null}}' action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
<span>{{Math.round(adata.pressure)}} kPa</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,18 @@
|
||||
<ui-display title='Cell Timer' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='clock-o' style='{{data.timing ? "selected" : null}}' action='{{data.timing ? "stop" : "start"}}'>{{data.timing ? "Stop" : "Start"}}</ui-button>
|
||||
<ui-button icon='lightbulb-o' action='flash' style='{{data.flash_charging ? "disabled" : null}}'>{{data.flash_charging ? "Recharging" : "Flash"}}</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section>
|
||||
<ui-button icon='fast-backward' action='time' params='{"adjust": -600}'></ui-button>
|
||||
<ui-button icon='backward' action='time' params='{"adjust": -100}'></ui-button>
|
||||
<span>{{text.zeroPad(data.minutes, 2)}}:{{text.zeroPad(data.seconds, 2)}}</span>
|
||||
<ui-button icon='forward' action='time' params='{"adjust": 100}'></ui-button>
|
||||
<ui-button icon='fast-forward' action='time' params='{"adjust": 600}'></ui-button>
|
||||
</ui-section>
|
||||
<ui-section>
|
||||
<ui-button icon='hourglass-start' action='preset' params='{"preset": "short"}'>Short</ui-button>
|
||||
<ui-button icon='hourglass-start' action='preset' params='{"preset": "medium"}'>Medium</ui-button>
|
||||
<ui-button icon='hourglass-start' action='preset' params='{"preset": "long"}'>Long</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,53 @@
|
||||
<ui-notice>
|
||||
<span>The regulator {{data.hasHoldingTank ? "is" : "is not"}} connected to a tank.</span>
|
||||
</ui-notice>
|
||||
<ui-display title='Canister' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='pencil' action='relabel'>Relabel</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Pressure'>
|
||||
<span>{{Math.round(adata.tankPressure)}} kPa</span>
|
||||
</ui-section>
|
||||
<ui-section label='Port'>
|
||||
<span class='{{data.portConnected ? "good" : "average"}}'>{{data.portConnected ? "Connected" : "Not Connected"}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Valve'>
|
||||
<ui-section label='Release Pressure'>
|
||||
<ui-bar min='{{data.minReleasePressure}}' max='{{data.maxReleasePressure}}'
|
||||
value='{{data.releasePressure}}'>{{Math.round(adata.releasePressure)}} kPa</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Pressure Regulator'>
|
||||
<ui-button icon='refresh' state='{{data.releasePressure != data.defaultReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "reset"}'>Reset</ui-button>
|
||||
<ui-button icon='minus' state='{{data.releasePressure > data.minReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "min"}'>Min</ui-button>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.releasePressure < data.maxReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Valve'>
|
||||
<ui-button icon='{{data.valveOpen ? "unlock" : "lock"}}'
|
||||
style='{{data.valveOpen ? data.hasHoldingTank ? "caution" : "danger" : null}}'
|
||||
action='valve'>{{data.valveOpen ? "Open" : "Closed"}}</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Holding Tank' button>
|
||||
{{#partial button}}
|
||||
{{#if data.hasHoldingTank}}
|
||||
<ui-button icon='eject' style='{{data.valveOpen ? "danger" : null}}' action='eject'>Eject</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
{{#if data.hasHoldingTank}}
|
||||
<ui-section label='Label'>
|
||||
{{data.holdingTank.name}}
|
||||
</ui-section>
|
||||
<ui-section label='Pressure'>
|
||||
{{Math.round(adata.holdingTank.tankPressure)}} kPa
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section>
|
||||
<span class='average'>No Holding Tank</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,88 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
tabs () {
|
||||
return Object.keys(this.get('data.supplies'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Cargo'>
|
||||
<ui-section label='Shuttle'>
|
||||
{{#if data.docked && !data.requestonly}}
|
||||
<ui-button action='send'>{{data.location}}</ui-button>
|
||||
{{else}}
|
||||
<span>{{data.location}}</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
<ui-section label='Credits'>
|
||||
<span>{{Math.floor(adata.points)}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Centcom Message'>
|
||||
<span>{{data.message}}</span>
|
||||
</ui-section>
|
||||
{{#if data.loan && !data.requestonly}}
|
||||
<ui-section label='Loan'>
|
||||
{{#if !data.loan_dispatched}}
|
||||
<ui-button action='loan'>Loan Shuttle</ui-button>
|
||||
{{else}}
|
||||
<span class='bad'>Loaned to Centcom</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
{{#if !data.requestonly}}
|
||||
<ui-display title='Cart' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='close' state='{{data.cart.length ? null : "disabled"}}' action='clear'>Clear</ui-button>
|
||||
{{/partial}}
|
||||
{{#each data.cart}}
|
||||
<ui-section candystripe nowrap>
|
||||
<div class='content'>#{{id}}</div>
|
||||
<div class='content'>{{object}}</div>
|
||||
<div class='content'>{{cost}} Credits</div>
|
||||
<div class='content'>
|
||||
<ui-button icon='minus' action='remove' params='{"id": "{{id}}"}'/>
|
||||
</div>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span>Nothing in Cart</span>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
<ui-display title='Requests' button>
|
||||
{{#partial button}}
|
||||
{{#if !data.requestonly}}
|
||||
<ui-button icon='close' state='{{data.requests.length ? null : "disabled"}}' action='denyall'>Clear</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
{{#each data.requests}}
|
||||
<ui-section candystripe nowrap>
|
||||
<div class='content'>#{{id}}</div>
|
||||
<div class='content'>{{object}}</div>
|
||||
<div class='content'>{{cost}} Credits</div>
|
||||
<div class='content'>By {{orderer}}</div>
|
||||
<div class='content'>Comment: {{reason}}</div>
|
||||
{{#if !data.requestonly}}
|
||||
<div class='content'>
|
||||
<ui-button icon='check' action='approve' params='{"id": "{{id}}"}'/>
|
||||
<ui-button icon='close' action='deny' params='{"id": "{{id}}"}'/>
|
||||
</div>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span>No Requests</span>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
<ui-tabs tabs='{{tabs}}'>
|
||||
{{#each data.supplies}}
|
||||
<tab name='{{name}}'>
|
||||
{{#each packs}}
|
||||
<ui-section label='{{name}}' candystripe right>
|
||||
<ui-button action='add' params='{"id": "{{id}}"}'>{{cost}} Credits</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</tab>
|
||||
{{/each}}
|
||||
</ui-tabs>
|
||||
@@ -0,0 +1,30 @@
|
||||
<ui-display title="Cellular Emporium" button>
|
||||
<ui-button icon='refresh' state='{{data.can_readapt ? null : "disabled"}}'
|
||||
action='readapt'>Readapt</ui-button>
|
||||
<ui-section label='Genetic Points Remaining' right>
|
||||
{{data.genetic_points_remaining}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display>
|
||||
{{#each data.abilities}}
|
||||
<ui-section label='{{name}}' candystripe right>
|
||||
<span>{{desc}}</span>
|
||||
<span>{{helptext}}</span>
|
||||
<span>Cost: {{dna_cost}}</span>
|
||||
|
||||
{{#if required_absorbtions}}
|
||||
<span>Required Absorbtions: {{required_absorbtions}}
|
||||
{{/if}}
|
||||
|
||||
<ui-button
|
||||
state='{{owned ? "selected" : can_purchase ? null : "disabled"}}'
|
||||
action='evolve'
|
||||
params='{"name": "{{name}}"}'>
|
||||
{{owned ? "Evolved" : "Evolve"}}
|
||||
</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
{{^data.abilities}}
|
||||
<span class='warning'>No abilities availible.</span>
|
||||
{{/data.abilities}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,38 @@
|
||||
<ui-display title='Status'>
|
||||
<ui-section label='Energy'>
|
||||
<ui-bar min='0' max='{{data.maxEnergy}}' value='{{data.energy}}'>{{Math.fixed(adata.energy)}} Units</ui-bar>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Dispense' button>
|
||||
{{#partial button}}
|
||||
{{#each data.beakerTransferAmounts}}
|
||||
<ui-button icon='plus' state='{{data.amount == . ? "selected" : null}}' action='amount' params='{"target": {{.}}}'>{{.}}</ui-button>
|
||||
{{/each}}
|
||||
{{/partial}}
|
||||
<ui-section>
|
||||
{{#each data.chemicals}}
|
||||
<ui-button grid icon='tint' action='dispense' params='{"reagent": "{{id}}"}'>{{title}}</ui-button>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Beaker' button>
|
||||
{{#partial button}}
|
||||
{{#each data.beakerTransferAmounts}}
|
||||
<ui-button icon='minus' action='remove' params='{"amount": {{.}}}'>{{.}}</ui-button>
|
||||
{{/each}}
|
||||
<ui-button icon='eject' state='{{data.isBeakerLoaded ? null : "disabled"}}' action='eject'>Eject</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Contents'>
|
||||
{{#if data.isBeakerLoaded}}
|
||||
<span>{{Math.round(adata.beakerCurrentVolume)}}/{{data.beakerMaxVolume}} Units</span>
|
||||
<br/>
|
||||
{{#each adata.beakerContents}}
|
||||
<span class='highlight' intro-outro='fade'>{{Math.fixed(volume, 2)}} units of {{name}}</span><br/>
|
||||
{{else}}
|
||||
<span class='bad'>Beaker Empty</span>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<span class='average'>No Beaker</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,29 @@
|
||||
<ui-display title='Thermostat'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.isActive ? "power-off" : "close"}}'
|
||||
style='{{data.isActive ? "selected" : null}}'
|
||||
state='{{data.isBeakerLoaded ? null : "disabled"}}'
|
||||
action='power'>{{data.isActive ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Target'>
|
||||
<ui-button icon='pencil' action='temperature' params='{"target": "input"}'>{{Math.round(adata.targetTemp)}} K</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Beaker' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='eject' state='{{data.isBeakerLoaded ? null : "disabled"}}' action='eject'>Eject</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Contents'>
|
||||
{{#if data.isBeakerLoaded}}
|
||||
<span>Temperature: {{Math.round(adata.currentTemp)}} K</span>
|
||||
<br />
|
||||
{{#each adata.beakerContents}}
|
||||
<span class='highlight' intro-outro='fade'>{{Math.fixed(volume, 2)}} units of {{name}}</span><br/>
|
||||
{{else}}
|
||||
<span class='bad'>Beaker Empty</span>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<span class='average'>No Beaker</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,107 @@
|
||||
{{#if data.screen == "home"}}
|
||||
<ui-display title='Beaker' button>
|
||||
<ui-button icon='{{data.isBeakerLoaded ? "Eject" : "close"}}'
|
||||
style='{{data.isBeakerLoaded ? "selected" : null}}'
|
||||
state='{{data.isBeakerLoaded ? null : "disabled"}}'
|
||||
action='eject'
|
||||
>{{data.isBeakerLoaded ? "Eject and Clear Buffer" : "No beaker"}}
|
||||
</ui-button>
|
||||
|
||||
<ui-section>
|
||||
{{#if data.isBeakerLoaded}}
|
||||
{{#each data.beakerContents}}
|
||||
<ui-section label='{{Math.fixed(volume, 2)}} units of {{name}}' nowrap>
|
||||
<div class='content' style='float:right'>
|
||||
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 1}'>1</ui-button>
|
||||
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 5}'>5</ui-button>
|
||||
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 10}'>10</ui-button>
|
||||
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 1000}'>All</ui-button>
|
||||
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": -1}'>Custom</ui-button>
|
||||
<ui-button action='analyze' params='{"id": "{{id}}"}'>Analyze</ui-button>
|
||||
</div>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span class='bad'>Beaker Empty</span>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<span class='average'>No Beaker</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
|
||||
<ui-display title='Buffer'>
|
||||
<ui-button action='toggleMode' state='{{data.mode ? null : "selected"}}'>Destroy</ui-button>
|
||||
<ui-button action='toggleMode' state='{{data.mode ? "selected" : null}}'>Transfer to Beaker</ui-button>
|
||||
<ui-section>
|
||||
{{#each data.bufferContents}}
|
||||
<ui-section label='{{Math.fixed(volume, 2)}} units of {{name}}' nowrap>
|
||||
<div class='content' style='float:right'>
|
||||
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 1}'>1</ui-button>
|
||||
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 5}'>5</ui-button>
|
||||
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 10}'>10</ui-button>
|
||||
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 1000}'>All</ui-button>
|
||||
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": -1}'>Custom</ui-button>
|
||||
<ui-button action='analyze' params='{"id": "{{id}}"}'>Analyze</ui-button>
|
||||
</div>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
|
||||
{{#if !data.condi}}
|
||||
<ui-display title='Pills, Bottles and Patches' >
|
||||
{{#if data.isPillBottleLoaded}}
|
||||
<ui-button action='ejectp' state='{{data.isPillBottleLoaded ? null : "disabled"}}'>{{data.isPillBottleLoaded ? "Eject" : "No Pill bottle loaded"}}</ui-button>
|
||||
<span class='content'>{{data.pillBotContent}}/{{data.pillBotMaxContent}}</span>
|
||||
{{else}}
|
||||
<span class='average'>No Pillbottle</span>
|
||||
{{/if}}
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<ui-button action='createPill' params='{"many": 0}' state='{{data.bufferContents ? null : "disabled"}}' >Create Pill (max 50µ)</ui-button>
|
||||
<br/>
|
||||
<ui-button action='createPill' params='{"many": 1}' state='{{data.bufferContents ? null : "disabled"}}' >Create Multiple Pills</ui-button>
|
||||
<br/>
|
||||
<br/>
|
||||
<ui-button action='createPatch' params='{"many": 0}' state='{{data.bufferContents ? null : "disabled"}}' >Create Patch (max 50µ)</ui-button>
|
||||
<br/>
|
||||
<ui-button action='createPatch' params='{"many": 1}' state='{{data.bufferContents ? null : "disabled"}}' >Create Multiple Patches</ui-button>
|
||||
<br/>
|
||||
<br/>
|
||||
<ui-button action='createBottle' state='{{data.bufferContents ? null : "disabled"}}' >Create Bottle (max 30µ)</ui-button>
|
||||
</ui-display>
|
||||
|
||||
{{else}}
|
||||
<ui-display title='Condiments bottles and packs' >
|
||||
<ui-button action='createPill' params='{"many": 0}' state='{{data.bufferContents ? null : "disabled"}}' >Create Pack (max 10µ)</ui-button>
|
||||
<br/>
|
||||
<br/>
|
||||
<ui-button action='createBottle' state='{{data.bufferContents ? null : "disabled"}}' >Create Bottle (max 50µ)</ui-button>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
{{elseif data.screen == "analyze"}}
|
||||
<ui-display title={{data.analyzeVars.name}} >
|
||||
<span class='highlight'>Description: </span>
|
||||
<span class='content' style='float:center'>{{data.analyzeVars.description}}</span>
|
||||
<br/>
|
||||
<span class='highlight'>Color: </span>
|
||||
<span style='color: {{data.analyzeVars.color}}; background-color: {{data.analyzeVars.color}}'>{{data.analyzeVars.color}}</span>
|
||||
<br/>
|
||||
<span class='highlight'>State: </span>
|
||||
<span class='content'>{{data.analyzeVars.state}}</span>
|
||||
<br/>
|
||||
<span class='highlight'>Metabolization Rate: </span>
|
||||
<span class='content'>{{data.analyzeVars.metaRate}}µ/minute</span>
|
||||
<br/>
|
||||
<span class='highlight'>Overdose Threshold: </span>
|
||||
<span class='content'>{{data.analyzeVars.overD}}</span>
|
||||
<br/>
|
||||
<span class='highlight'>Addiction Threshold: </span>
|
||||
<span class='content'>{{data.analyzeVars.addicD}}</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<ui-button action='goScreen' params='{"screen": "home"}'>Back</ui-button>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{{#if data.has_cap}}
|
||||
<ui-display>
|
||||
<ui-section label='Cap'>
|
||||
<ui-button icon='{{data.is_capped ? "power-off" : "close"}}' style='{{data.is_capped ? null : "selected"}}'
|
||||
action='toggle_cap'>
|
||||
{{data.is_capped ? "On": "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
<ui-display>
|
||||
{{!<ui-section label='Current Colour'>{{{current_colour}</span>
|
||||
</ui-section>}}
|
||||
{{#if data.can_change_colour}}
|
||||
<ui-section>
|
||||
<ui-button action='select_colour'>Select New Colour</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Stencil'>
|
||||
{{#each data.drawables}}
|
||||
<ui-section label='{{name}}'>
|
||||
{{#each items}}
|
||||
<ui-button action='select_stencil' params='{"item":"{{item}}"}'
|
||||
style='{{item == data.selected_stencil ? "selected" : null}}'>
|
||||
{{item}}
|
||||
</ui-button>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
<ui-display title="Text Mode">
|
||||
<ui-section label='Current Buffer'>{{text_buffer}}
|
||||
</ui-section>
|
||||
<ui-section><ui-button action='enter_text'>New Text</ui-button></ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,74 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
data: {
|
||||
temperatureStatus (temp) {
|
||||
if (temp < 225) return 'good'
|
||||
else if (temp < 273.15) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
occupantStatState () {
|
||||
switch (this.get('data.occupant.stat')) {
|
||||
case 0: return 'good'
|
||||
case 1: return 'average'
|
||||
default: return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Occupant'>
|
||||
<ui-section label='Occupant'>
|
||||
<span>{{data.occupant.name ? data.occupant.name : "No Occupant"}}</span>
|
||||
</ui-section>
|
||||
{{#if data.hasOccupant}}
|
||||
<ui-section label='State'>
|
||||
<span class='{{occupantStatState}}'>{{data.occupant.stat == 0 ? "Conscious" : data.occupant.stat == 1 ? "Unconcious" : "Dead"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Temperature'>
|
||||
<span class='{{temperatureStatus(adata.occupant.bodyTemperature)}}'>{{Math.round(adata.occupant.bodyTemperature)}} K</span>
|
||||
</ui-section>
|
||||
<ui-section label='Health'>
|
||||
<ui-bar min='{{data.occupant.minHealth}}' max='{{data.occupant.maxHealth}}' value='{{data.occupant.health}}'
|
||||
state='{{data.occupant.health >= 0 ? "good" : "average"}}'>{{Math.round(adata.occupant.health)}}</ui-bar>
|
||||
</ui-section>
|
||||
{{#each [{label: "Brute", type: "bruteLoss"}, {label: "Respiratory", type: "oxyLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Burn", type: "fireLoss"}]}}
|
||||
<ui-section label='{{label}}'>
|
||||
<ui-bar min='0' max='{{data.occupant.maxHealth}}' value='{{data.occupant[type]}}' state='bad'>{{Math.round(adata.occupant[type])}}</ui-bar>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Cell'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.isOperating ? "power-off" : "close"}}'
|
||||
style='{{data.isOperating ? "selected" : null}}'
|
||||
state='{{data.isOpen ? "disabled" : null}}'
|
||||
action='power'>{{data.isOperating ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Temperature'>
|
||||
<span class='{{temperatureStatus(adata.cellTemperature)}}'>{{Math.round(adata.cellTemperature)}} K</span>
|
||||
</ui-section>
|
||||
<ui-section label='Door'>
|
||||
<ui-button icon='{{data.isOpen ? "unlock" : "lock"}}' action='door'>{{data.isOpen ? "Open" : "Closed"}}</ui-button>
|
||||
<ui-button icon='{{data.autoEject ? "sign-out" : "sign-in"}}' action='autoeject'>{{data.autoEject ? "Auto" : "Manual"}}</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Beaker' button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='eject' state='{{data.isBeakerLoaded ? null : "disabled"}}' action='ejectbeaker'>Eject</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Contents'>
|
||||
{{#if data.isBeakerLoaded}}
|
||||
{{#each adata.beakerContents}}
|
||||
<span class='highlight' intro-outro='fade'>{{Math.fixed(volume, 2)}} units of {{name}}</span><br/>
|
||||
{{else}}
|
||||
<span class='bad'>Beaker Empty</span>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<span class='average'>No Beaker</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,30 @@
|
||||
<ui-notice>
|
||||
<span>Time Until Launch: {{data.timer_str}}</span>
|
||||
</ui-notice>
|
||||
<ui-notice>
|
||||
<span>Engines: {{data.engines_started ? 'Online' : 'Idle'}}</span>
|
||||
</ui-notice>
|
||||
<ui-display title='Early Launch'>
|
||||
<span>Authorizations Remaining:
|
||||
{{data.emagged ? "ERROR" : data.authorizations_remaining}}</span>
|
||||
<ui-button icon="exclamation-triangle" action='authorize'
|
||||
style='danger'
|
||||
state='{{data.enabled ? null : 'disabled'}}'>
|
||||
AUTHORIZE
|
||||
</ui-button>
|
||||
<ui-button icon="minus" action='repeal'
|
||||
state='{{data.enabled ? null : 'disabled'}}'>
|
||||
Repeal
|
||||
</ui-button>
|
||||
<ui-button icon="close" action='abort'
|
||||
state='{{data.enabled ? null : 'disabled'}}'>
|
||||
Repeal All
|
||||
</ui-button>
|
||||
</ui-display>
|
||||
<ui-display title='Authorizations'>
|
||||
{{#each data.authorizations}}
|
||||
<ui-section candystripe nowrap>{{name}} ({{job}})</ui-section>
|
||||
{{else}}
|
||||
<ui-section candystripe nowrap>No authorizations.</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,3 @@
|
||||
<ui-notice>
|
||||
<span>The requested interface ({{config.interface}}) was not found. Does it exist?</span>
|
||||
</ui-notice>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
seclevelState () {
|
||||
switch (this.get('data.seclevel')) {
|
||||
case 'blue': return 'average'
|
||||
case 'red': return 'bad'
|
||||
case 'delta': return 'bad bold'
|
||||
default: return 'good'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display>
|
||||
<ui-section label='Alert Level'>
|
||||
<span class='{{seclevelState}}'>{{text.titleCase(data.seclevel)}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Controls'>
|
||||
<ui-button icon='{{data.alarm ? "close" : "bell-o"}}' action='{{data.alarm ? "reset" : "alarm"}}'>
|
||||
{{data.alarm ? "Reset" : "Activate"}}</ui-button>
|
||||
</ui-section>
|
||||
{{#if data.emagged}}
|
||||
<ui-section label='Warning'>
|
||||
<span class='bad bold'>Safety measures offline. Device may exhibit abnormal behavior.</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,49 @@
|
||||
<ui-display title='Labor Camp Teleporter'>
|
||||
<ui-section label='Teleporter Status'>
|
||||
<span class='{{data.teleporter ? "good" : "bad"}}'>{{data.teleporter ? "Connected" : "Not connected"}}</span>
|
||||
</ui-section>
|
||||
{{#if data.teleporter}}
|
||||
<ui-section label='Location'>
|
||||
<span>{{data.teleporter_location}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Locked status'>
|
||||
<ui-button icon='{{data.teleporter_lock ? "lock" : "unlock"}}' action="teleporter_lock">{{data.teleporter_lock ? "Locked" : "Unlocked"}}</ui-button>
|
||||
<ui-button action='toggle_open'>{{data.teleporter_state_open ? "Open" : "Closed"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span><ui-button action="scan_teleporter">Scan Teleporter</ui-button></span>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Labor Camp Beacon'>
|
||||
<ui-section label='Beacon Status'>
|
||||
<span class='{{data.beacon ? "good" : "bad"}}'>{{data.beacon ? "Connected" : "Not connected"}}</span>
|
||||
</ui-section>
|
||||
{{#if data.beacon}}
|
||||
<ui-section label='Location'>
|
||||
<span>{{data.beacon_location}}</span>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span><ui-button action="scan_beacon">Scan Beacon</ui-button></span>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Prisoner details'>
|
||||
<ui-section label='Prisoner ID'>
|
||||
<ui-button action="handle_id">{{data.id ? data.id_name : "-------------"}}</ui-button>
|
||||
</ui-section>
|
||||
{{#if data.id}}
|
||||
<ui-section label='Set ID goal'>
|
||||
<ui-button action="set_goal">{{data.goal}}</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
<ui-section label='Occupant'>
|
||||
<span>{{data.prisoner.name ? data.prisoner.name : "No Occupant"}}</span>
|
||||
</ui-section>
|
||||
{{#if data.prisoner}}
|
||||
<ui-section label='Criminal Status'>
|
||||
<span>{{data.prisoner.crimstat}}</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display>
|
||||
<center><ui-button action="teleport" state={{data.can_teleport ? null : 'disabled'}}>Process Prisoner</ui-button></center>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,10 @@
|
||||
<ui-display>
|
||||
<center><ui-button action="handle_id">{{data.id ? data.id.name : "-------------"}}</ui-button></center>
|
||||
</ui-display>
|
||||
<ui-display title='Stored Items'>
|
||||
{{#each data.mobs}}
|
||||
<ui-section label='{{name}}'>
|
||||
<ui-button action="release_items" params='{"mobref":{{mob}}}' state={{data.can_reclaim ? null : 'disabled'}}>Drop Items</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,42 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
healthState () {
|
||||
const health = this.get('data.health')
|
||||
if (health > 70) return 'good'
|
||||
else if (health > 50) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{{#if data.wiping}}
|
||||
<ui-notice>
|
||||
<span>Wipe in progress!</span>
|
||||
</ui-notice>
|
||||
{{/if}}
|
||||
<ui-display title={{data.name || "Empty Card"}} button>
|
||||
{{#partial button}}
|
||||
{{#if data.name}}
|
||||
<ui-button icon='trash' state='{{data.wiping || data.isDead ? "disabled" : null}}' action='wipe'>Wipe AI</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
{{#if data.name}}
|
||||
<ui-section label='Status'>
|
||||
<span class='{{data.isDead || data.isBraindead ? "bad" : "good"}}'>{{data.isDead || data.isBraindead ? "Offline" : "Operational"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Software Integrity'>
|
||||
<ui-bar min='0' max='100' value='{{data.health}}' state='{{healthState}}'>{{Math.round(adata.health)}}%</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Laws'>
|
||||
{{#each data.laws}}
|
||||
<span class='highlight'>{{.}}</span><br/>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
<ui-section label='Settings'>
|
||||
<ui-button icon='signal' style='{{data.wireless ? "selected" : null}}' action="wireless">Wireless Activity</ui-button>
|
||||
<ui-button icon='microphone' style='{{data.radio ? "selected" : null}}' action="radio">Subspace Radio</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,16 @@
|
||||
{{#if data.waiting}}
|
||||
<ui-notice>
|
||||
<span>Waiting for another device to confirm your request...</span>
|
||||
</ui-notice>
|
||||
{{else}}
|
||||
<ui-display>
|
||||
<ui-section>
|
||||
{{#if data.auth_required}}
|
||||
<ui-button icon='check' action='auth_swipe'>Authorize {{data.auth_required}}</ui-button>
|
||||
{{else}}
|
||||
<ui-button icon='warning' state='{{data.red_alert ? 'disabled' : null}}' action='red_alert'>Red Alert</ui-button>
|
||||
<ui-button icon='wrench' state='{{data.emergency_maint ? 'disabled' : null}}' action='emergency_maint'>Emergency Maintenance Access</ui-button>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,29 @@
|
||||
<ui-display title='Ore values'>
|
||||
{{#each data.ores}}
|
||||
<ui-section label='{{ore}}'>
|
||||
<span>{{value}}</span>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
<ui-display title='Points'>
|
||||
<ui-section label='ID'>
|
||||
<ui-button action="handle_id">{{data.id ? data.id_name : "-------------"}}</ui-button>
|
||||
</ui-section>
|
||||
{{#if data.id}}
|
||||
<ui-section label='Points collected'>
|
||||
<span>{{data.points}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Goal'>
|
||||
<span>{{data.goal}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Unclaimed points'>
|
||||
<span>{{data.unclaimed_points}}</span>
|
||||
<ui-button action="claim_points" state={{data.unclaimed_points ? null : 'disabled'}}>Claim points</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display>
|
||||
<center>
|
||||
<ui-button action="move_shuttle" state={{data.can_go_home ? null : 'disabled'}}>Move shuttle</ui-button>
|
||||
</center>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,44 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
data: {
|
||||
mechChargeState(charge) {
|
||||
let maxcharge = this.get('data.recharge_port.mech.cell.maxcharge')
|
||||
if(charge >= (maxcharge/1.5)) return 'good'
|
||||
else if(charge >= (maxcharge/3)) return 'average'
|
||||
else return 'bad'
|
||||
},
|
||||
mechHealthState(health) {
|
||||
let maxhealth = this.get('data.recharge_port.mech.maxhealth')
|
||||
if(health > (maxhealth/1.5)) return 'good'
|
||||
else if(health > (maxhealth/3)) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Mech Status'>
|
||||
{{#if data.recharge_port}}
|
||||
{{#if data.recharge_port.mech}}
|
||||
<ui-section label='Integrity'>
|
||||
<ui-bar min='0' max='{{adata.recharge_port.mech.maxhealth}}' value='{{adata.recharge_port.mech.health}}'state='{{mechHealthState(adata.recharge_port.mech.health)}}'>{{Math.round(adata.recharge_port.mech.health)}}/{{adata.recharge_port.mech.maxhealth}}</ui-bar>
|
||||
</ui-section>
|
||||
{{#if data.recharge_port.mech.cell}}
|
||||
{{#if data.recharge_port.mech.cell.critfail}}
|
||||
<ui-section label='Power'><span class='bad'>Cell Critical Failure</span></ui-section>
|
||||
{{else}}
|
||||
<ui-section label='Power'>
|
||||
<ui-bar min='0' max='{{adata.recharge_port.mech.cell.maxcharge}}' value='{{adata.recharge_port.mech.cell.charge}}'state='{{mechChargeState(adata.recharge_port.mech.cell.charge)}}'>{{Math.round(adata.recharge_port.mech.cell.charge)}}/{{Math.round(adata.recharge_port.mech.cell.maxcharge)}}</ui-bar>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<ui-section label='Power'><span class='bad'>Cell Missing</span></ui-section>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<ui-section>Mech Not Found</ui-section>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<ui-section>Recharging Port Not Found</ui-section>
|
||||
<ui-button icon='refresh' action='reconnect'>Reconnect</ui-button>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,60 @@
|
||||
<ui-notice>
|
||||
{{#if data.siliconUser}}
|
||||
<ui-section label='Interface Lock'>
|
||||
<ui-button icon='{{data.locked ? "lock" : "unlock"}}' action='lock'>{{data.locked ? "Engaged" : "Disengaged"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<span>Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface.</span>
|
||||
{{/if}}
|
||||
</ui-notice>
|
||||
<ui-display title='Status'>
|
||||
<ui-section label='Power'>
|
||||
{{#if !data.locked || data.siliconUser }}
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}' style='{{data.on ? "selected" : null}}' action="power">{{data.on ? "On" : "Off"}}</ui-button>
|
||||
{{else}}
|
||||
<span class='{{data.on ? "good" : "bad"}}' state='{{data.cell ? null : "disabled"}}'>{{data.on ? "On" : "Off"}}</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
<ui-section label='Cell'>
|
||||
<span class='{{data.cell ? null : "bad"}}'>{{data.cell ? data.cellPercent + "%" : "No Cell"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Mode'>
|
||||
<span class='{{data.modeStatus}}'>{{data.mode}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Load'>
|
||||
<span class='{{data.load ? "good" : "average"}}'>{{data.load ? data.load : "None"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Destination'>
|
||||
<span class='{{data.destination ? "good": "average"}}'>{{data.destination ? data.destination : "None"}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{#if !data.locked || data.siliconUser}}
|
||||
<ui-display title='Controls' button>
|
||||
{{#partial button}}
|
||||
{{#if data.load}}
|
||||
<ui-button icon='eject' action='unload'>Unload</ui-button>
|
||||
{{/if}}
|
||||
{{#if data.haspai}}
|
||||
<ui-button icon='eject' action='ejectpai'>Eject PAI</ui-button>
|
||||
{{/if}}
|
||||
<ui-button icon='pencil' action='setid'>Set ID</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Destination'>
|
||||
<ui-button icon='pencil' action='destination'>Set Destination</ui-button>
|
||||
<ui-button icon='stop' action='stop'>Stop</ui-button>
|
||||
<ui-button icon='play' action='go'>Go</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Home'>
|
||||
<ui-button icon='home' action='home'>Go Home</ui-button>
|
||||
<ui-button icon='pencil' action='sethome'>Set Home</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Settings'>
|
||||
<ui-button icon='{{data.autoReturn ? "check-square-o" : "square-o"}}' style='{{data.autoReturn ? "selected" : null}}' action='autoret'>
|
||||
Auto-Return Home</ui-button>
|
||||
<ui-button icon='{{data.autoPickup ? "check-square-o" : "square-o"}}' style='{{data.autoPickup ? "selected" : null}}' action='autopick'>
|
||||
Auto-Pickup Crate</ui-button>
|
||||
<ui-button icon='{{data.reportDelivery ? "check-square-o" : "square-o"}}' style='{{data.reportDelivery ? "selected" : null}}' action='report'>
|
||||
Report Deliveries</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,88 @@
|
||||
<script>
|
||||
import { filterMulti } from 'util/filter'
|
||||
component.exports = {
|
||||
data: {
|
||||
filter: ''
|
||||
},
|
||||
oninit () {
|
||||
this.observe('filter', (newkey, oldkey, keypath) => {
|
||||
const categories = this.findAll('.display:not(:first-child)')
|
||||
filterMulti(categories, this.get('filter').toLowerCase())
|
||||
}, { init: false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='{{data.category}}'>
|
||||
{{#if data.busy}}
|
||||
<ui-section>
|
||||
Crafting... <i class='fa-spin fa fa-spinner'></i>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section>
|
||||
<ui-button icon='arrow-left' action ='backwardCat'>
|
||||
{{data.prev_cat}}
|
||||
</ui-button>
|
||||
<ui-button icon='arrow-right' action='forwardCat'>
|
||||
{{data.next_cat}}
|
||||
</ui-button>
|
||||
{{#if data.display_craftable_only}}
|
||||
<ui-button icon='lock' action='toggle_recipes'>
|
||||
Showing Craftable Recipes
|
||||
</ui-button>
|
||||
{{else}}
|
||||
<ui-button icon='unlock' action='toggle_recipes'>
|
||||
Showing All Recipes
|
||||
</ui-button>
|
||||
{{/if}}
|
||||
{{#if config.fancy}}
|
||||
<ui-input value='{{filter}}' placeholder='Filter..'/>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
{{#each data.can_craft}}
|
||||
<ui-display title='{{name}}'>
|
||||
{{#if req_text}}
|
||||
<ui-section label='Requirements'>
|
||||
{{req_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if catalyst_text}}
|
||||
<ui-section label='Catalysts'>
|
||||
{{catalyst_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if tool_text}}
|
||||
<ui-section label='Tools'>
|
||||
{{tool_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
<ui-section>
|
||||
<ui-button icon='gears' action='make' params='{"recipe": "{{ref}}"}'>
|
||||
Craft
|
||||
</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{/each}}
|
||||
{{^data.display_craftable_only}}
|
||||
{{#each data.cant_craft}}
|
||||
<ui-display title='{{name}}'>
|
||||
{{#if req_text}}
|
||||
<ui-section label='Requirements'>
|
||||
{{req_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if catalyst_text}}
|
||||
<ui-section label='Catalysts'>
|
||||
{{catalyst_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if tool_text}}
|
||||
<ui-section label='Tools'>
|
||||
{{tool_text}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
{{/each}}
|
||||
{{/data.display_craftable_only}}
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,54 @@
|
||||
<ui-notice>
|
||||
<span>The regulator {{data.holding ? "is" : "is not"}} connected to a tank.</span>
|
||||
</ui-notice>
|
||||
<ui-display title='Status' button>
|
||||
<ui-section label='Pressure'>
|
||||
<span>{{Math.round(adata.pressure)}} kPa</span>
|
||||
</ui-section>
|
||||
<ui-section label='Port'>
|
||||
<span class='{{data.connected ? "good" : "average"}}'>{{data.connected ? "Connected" : "Not Connected"}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Pump'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}'
|
||||
style='{{data.on ? "selected" : "null"}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Direction'>
|
||||
<ui-button icon='{{data.direction == "out" ? "sign-out" : "sign-in"}}'
|
||||
action='direction'>{{data.direction == "out" ? "Out" : "In"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Target Pressure'>
|
||||
<ui-bar min='{{data.min_pressure}}' max='{{data.max_pressure}}'
|
||||
value='{{data.target_pressure}}'>{{Math.round(adata.target_pressure)}} kPa</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Pressure Regulator'>
|
||||
<ui-button icon='refresh' state='{{data.target_pressure != data.default_pressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "reset"}'>Reset</ui-button>
|
||||
<ui-button icon='minus' state='{{data.target_pressure > data.min_pressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "min"}'>Min</ui-button>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.target_pressure < data.max_pressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Holding Tank' button>
|
||||
{{#partial button}}
|
||||
{{#if data.holding}}
|
||||
<ui-button icon='eject' style='{{data.on ? "danger" : null}}' action='eject'>Eject</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
{{#if data.holding}}
|
||||
<ui-section label='Label'>
|
||||
{{data.holding.name}}
|
||||
</ui-section>
|
||||
<ui-section label='Pressure'>
|
||||
{{Math.round(adata.holding.pressure)}} kPa
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section>
|
||||
<span class='average'>No Holding Tank</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,37 @@
|
||||
<ui-notice>
|
||||
<span>The regulator {{data.holding ? "is" : "is not"}} connected to a tank.</span>
|
||||
</ui-notice>
|
||||
<ui-display title='Status' button>
|
||||
<ui-section label='Pressure'>
|
||||
<span>{{Math.round(adata.pressure)}} kPa</span>
|
||||
</ui-section>
|
||||
<ui-section label='Port'>
|
||||
<span class='{{data.connected ? "good" : "average"}}'>{{data.connected ? "Connected" : "Not Connected"}}</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Filter'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}'
|
||||
style='{{data.on ? "selected" : "null"}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Holding Tank' button>
|
||||
{{#partial button}}
|
||||
{{#if data.holding}}
|
||||
<ui-button icon='eject' style='{{data.on ? "danger" : null}}' action='eject'>Eject</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
{{#if data.holding}}
|
||||
<ui-section label='Label'>
|
||||
{{data.holding.name}}
|
||||
</ui-section>
|
||||
<ui-section label='Pressure'>
|
||||
{{Math.round(adata.holding.pressure)}} kPa
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section>
|
||||
<span class='average'>No Holding Tank</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,77 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
data: {
|
||||
chargingState (status) {
|
||||
switch (status) {
|
||||
case 2: return 'good'
|
||||
case 1: return 'average'
|
||||
default: return 'bad'
|
||||
}
|
||||
},
|
||||
chargingMode (status) {
|
||||
if (status == 2) return 'Full'
|
||||
else if (status == 1) return 'Charging'
|
||||
else return 'Draining'
|
||||
},
|
||||
channelState (status) {
|
||||
if (status >= 2) return 'good'
|
||||
else return 'bad'
|
||||
},
|
||||
channelPower (status) {
|
||||
if (status >= 2) return 'On'
|
||||
else return 'Off'
|
||||
},
|
||||
channelMode (status) {
|
||||
if (status == 1 || status == 3) return 'Auto'
|
||||
else return 'Manual'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
graphData () {
|
||||
const history = this.get('data.history')
|
||||
return Object.keys(history).map(key => {
|
||||
return history[key].map((point, index) => {
|
||||
return { x: index, y: point }
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Network'>
|
||||
{{#if config.fancy}}
|
||||
<ui-linegraph points='{{graphData}}' height='500'
|
||||
legend='["Available", "Load"]' colors='["rgb(0, 102, 0)", "rgb(153, 0, 0)"]'
|
||||
xunit='seconds ago' xfactor='{{data.interval}}' yunit='W' yfactor='1'
|
||||
xinc='{{data.stored / 10}}' yinc='9'/>
|
||||
{{else}}
|
||||
<ui-section label='Available'>
|
||||
<span>{{data.supply}} W</span>
|
||||
</ui-section>
|
||||
<ui-section label='Load'>
|
||||
<span>{{data.demand}} W</span>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Areas'>
|
||||
<ui-section nowrap>
|
||||
<div class='content'>Area</div>
|
||||
<div class='content'>Charge</div>
|
||||
<div class='content'>Load</div>
|
||||
<div class='content'>Status</div>
|
||||
<div class='content'>Equipment</div>
|
||||
<div class='content'>Lighting</div>
|
||||
<div class='content'>Environment</div>
|
||||
</ui-section>
|
||||
{{#each data.areas}}
|
||||
<ui-section label='{{name}}' nowrap>
|
||||
<div class='content'>{{Math.round(adata.areas[@index].charge)}} %</div>
|
||||
<div class='content'>{{Math.round(adata.areas[@index].load)}} W</div>
|
||||
<div class='content'><span class='{{chargingState(charging)}}'>{{chargingMode(charging)}}</span></div>
|
||||
<div class='content'><span class='{{channelState(eqp)}}'>{{channelPower(eqp)}} [<span>{{channelMode(eqp)}}</span>]</span></div>
|
||||
<div class='content'><span class='{{channelState(lgt)}}'>{{channelPower(lgt)}} [<span>{{channelMode(lgt)}}</span>]</span></div>
|
||||
<div class='content'><span class='{{channelState(env)}}'>{{channelPower(env)}} [<span>{{channelMode(env)}}</span>]</span></div>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,66 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
readableFrequency () {
|
||||
return Math.round(this.get('adata.frequency')) / 10
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Settings'>
|
||||
{{#if data.headset}}
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.listening ? "power-off" : "close"}}' style='{{data.listening ? "selected" : null}}'
|
||||
action='listen'>
|
||||
{{data.listening ? "On": "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-section label='Microphone'>
|
||||
<ui-button icon='{{data.broadcasting ? "power-off" : "close"}}' style='{{data.broadcasting ? "selected" : null}}'
|
||||
action='broadcast'>
|
||||
{{data.broadcasting ? "Engaged": "Disengaged"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Speaker'>
|
||||
<ui-button icon='{{data.listening ? "power-off" : "close"}}' style='{{data.listening ? "selected" : null}}'
|
||||
action='listen'>
|
||||
{{data.listening ? "Engaged": "Disengaged"}}</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if data.command}}
|
||||
<ui-section label='High Volume'>
|
||||
<ui-button icon='{{data.useCommand ? "power-off" : "close"}}' style='{{data.useCommand ? "selected" : null}}'
|
||||
action='command'>
|
||||
{{data.useCommand ? "On": "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Channel'>
|
||||
<ui-section label='Frequency'>
|
||||
{{#if data.freqlock}}
|
||||
<span>{{readableFrequency}}</span>
|
||||
{{else}}
|
||||
<ui-button icon='fast-backward' state='{{data.frequency == data.minFrequency ? "disabled": null}}' action='frequency' params='{"adjust": -1}'/>
|
||||
<ui-button icon='backward' state='{{data.frequency == data.minFrequency ? "disabled": null}}' action='frequency' params='{"adjust": -.2}'/>
|
||||
<ui-button icon='pencil' action='frequency' params='{"tune": "input"}'>{{readableFrequency}}</ui-button>
|
||||
<ui-button icon='forward' state='{{data.frequency == data.maxFrequency ? "disabled": null}}' action='frequency' params='{"adjust": .2}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.frequency == data.maxFrequency ? "disabled": null}}' action='frequency' params='{"adjust": 1}'/>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
{{#if data.subspaceSwitchable}}
|
||||
<ui-section label='Subspace Transmission'>
|
||||
<ui-button icon='{{data.subspace ? "power-off" : "close"}}' style='{{data.subspace ? "selected" : null}}'
|
||||
action='subspace'>{{data.subspace ? "Active" : "Inactive"}}</ui-button>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
{{#if data.subspace && data.channels}}
|
||||
<ui-section label='Channels'>
|
||||
{{#each data.channels:channel}}
|
||||
<ui-button icon='{{. ? "check-square-o" : "square-o"}}'
|
||||
style='{{. ? "selected" : null}}'
|
||||
action='channel' params='{"channel": "{{channel}}"}'>
|
||||
{{channel}}</ui-button><br/>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
@@ -0,0 +1,20 @@
|
||||
<link rel='ractive' href='./shuttle_manipulator/status.ract'>
|
||||
<link rel='ractive' href='./shuttle_manipulator/templates.ract'>
|
||||
<link rel='ractive' href='./shuttle_manipulator/modification.ract'>
|
||||
|
||||
<ui-tabs tabs='{{data.tabs}}'>
|
||||
<tab name='Status'>
|
||||
<status/>
|
||||
</tab>
|
||||
<tab name='Templates'>
|
||||
<templates/>
|
||||
</tab>
|
||||
<tab name='Modification'>
|
||||
{{#if data.selected}}
|
||||
<modification/>
|
||||
{{/if}}
|
||||
{{#if !data.selected}}
|
||||
<span class='bad'>No shuttle selected.</span>
|
||||
{{/if}}
|
||||
</tab>
|
||||
</ui-tabs>
|
||||
@@ -0,0 +1,38 @@
|
||||
<ui-display title='Selected: {{data.selected.name}}'>
|
||||
{{#if data.selected.description}}
|
||||
<ui-section label='Description'>{{data.selected.description}}</ui-section>
|
||||
{{/if}}
|
||||
{{#if data.selected.admin_notes}}
|
||||
<ui-section label='Admin Notes'>{{data.selected.admin_notes}}</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
|
||||
{{#if data.existing_shuttle}}
|
||||
<ui-display title='Existing Shuttle: {{data.existing_shuttle.name}}'>
|
||||
Status: {{data.existing_shuttle.status}}
|
||||
{{#if data.existing_shuttle.timer}}
|
||||
({{data.existing_shuttle.timeleft}})
|
||||
{{/if}}
|
||||
<ui-button action='jump_to'
|
||||
params='{"type": "mobile", "id": "{{data.existing_shuttle.id}}"}'>
|
||||
Jump To
|
||||
</ui-button>
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
|
||||
{{#if !data.existing_shuttle}}
|
||||
<ui-display title='Existing Shuttle: None'></ui-display>
|
||||
{{/if}}
|
||||
|
||||
<ui-button action='preview'
|
||||
params='{"shuttle_id": "{{data.selected.shuttle_id}}"}'>
|
||||
Preview
|
||||
</ui-button>
|
||||
<ui-button action='load'
|
||||
params='{"shuttle_id": "{{data.selected.shuttle_id}}"}'
|
||||
style='danger'>
|
||||
Load
|
||||
</ui-button>
|
||||
|
||||
<ui-display title='Status'>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,14 @@
|
||||
{{#each data.shuttles}}
|
||||
<ui-section label='{{name}} ({{id}})'>
|
||||
{{status}}
|
||||
{{#if timer}}
|
||||
({{timeleft}})
|
||||
{{/if}}
|
||||
<ui-button action='jump_to' params='{"type": "mobile", "id": "{{id}}"}'>
|
||||
Jump To
|
||||
</ui-button>
|
||||
<ui-button action='fast_travel' params='{"id": "{{id}}"}' state='{{can_fast_travel ? null : 'disabled'}}'>
|
||||
Fast Travel
|
||||
</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
@@ -0,0 +1,24 @@
|
||||
<ui-tabs tabs='{{data.templates_tabs}}'>
|
||||
{{#each data.templates}}
|
||||
<tab name='{{port_id}}'>
|
||||
{{#each templates}}
|
||||
<ui-display title='{{name}}'>
|
||||
{{#if description}}
|
||||
<ui-section label='Description'>{{description}}</ui-section>
|
||||
{{/if}}
|
||||
{{#if admin_notes}}
|
||||
<ui-section label='Admin Notes'>{{admin_notes}}</ui-section>
|
||||
{{/if}}
|
||||
|
||||
<ui-button action='select_template'
|
||||
params='{"shuttle_id": "{{shuttle_id}}"}'
|
||||
state='{{data.selected.shuttle_id == shuttle_id ?
|
||||
"selected" : null}}'>
|
||||
{{data.selected.shuttle_id == shuttle_id ? "Selected" : "Select"}}
|
||||
</ui-button>
|
||||
|
||||
</ui-display>
|
||||
{{/each}}
|
||||
</tab>
|
||||
{{/each}}
|
||||
</ui-tabs>
|
||||
@@ -0,0 +1,56 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
occupantStatState () {
|
||||
switch (this.get('data.occupant.stat')) {
|
||||
case 0: return 'good'
|
||||
case 1: return 'average'
|
||||
default: return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Occupant'>
|
||||
<ui-section label='Occupant'>
|
||||
<span>{{data.occupant.name ? data.occupant.name : "No Occupant"}}</span>
|
||||
</ui-section>
|
||||
{{#if data.occupied}}
|
||||
<ui-section label='State'>
|
||||
<span class='{{occupantStatState}}'>{{data.occupant.stat == 0 ? "Conscious" : data.occupant.stat == 1 ? "Unconcious" : "Dead"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Health'>
|
||||
<ui-bar min='{{data.occupant.minHealth}}' max='{{data.occupant.maxHealth}}' value='{{data.occupant.health}}'
|
||||
state='{{data.occupant.health >= 0 ? "good" : "average"}}'>{{Math.round(adata.occupant.health)}}</ui-bar>
|
||||
</ui-section>
|
||||
{{#each [{label: "Brute", type: "bruteLoss"}, {label: "Respiratory", type: "oxyLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Burn", type: "fireLoss"}]}}
|
||||
<ui-section label='{{label}}'>
|
||||
<ui-bar min='0' max='{{data.occupant.maxHealth}}' value='{{data.occupant[type]}}' state='bad'>{{Math.round(adata.occupant[type])}}</ui-bar>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
<ui-section label='Cells'>
|
||||
<span class='{{data.occupant.cloneLoss ? "bad" : "good"}}'>{{data.occupant.cloneLoss ? "Damaged" : "Healthy"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Brain'>
|
||||
<span class='{{data.occupant.brainLoss ? "bad" : "good"}}'>{{data.occupant.brainLoss ? "Abnormal" : "Healthy"}}</span>
|
||||
</ui-section>
|
||||
<ui-section label='Bloodstream'>
|
||||
{{#each adata.occupant.reagents}}
|
||||
<span class='highlight' intro-outro='fade'>{{Math.fixed(volume, 1)}} units of {{name}}</span><br/>
|
||||
{{else}}
|
||||
<span class='good'>Pure</span>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
<ui-display title='Controls'>
|
||||
<ui-section label='Door'>
|
||||
<ui-button icon='{{data.open ? "unlock" : "lock"}}' action='door'>{{data.open ? "Open" : "Closed"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Inject'>
|
||||
{{#each data.chems}}
|
||||
<ui-button icon='flask' state='{{data.occupied && allowed ? null : "disabled"}}' action='inject' params='{"chem": "{{id}}"}'>{{name}}</ui-button><br/>
|
||||
{{/each}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,14 @@
|
||||
{{#each data.bodies}}
|
||||
<ui-section label='{{name}}' labelcolor='{{htmlcolor}}' candystripe right>
|
||||
<ui-section label='Status'><span class='{{status == "Dead" ? "bad bold" : status == "Unconscious" ? "average bold" : "good"}}'>{{status}}</span></ui-section>
|
||||
<ui-section label='Jelly'>{{exoticblood}}</ui-section>
|
||||
<ui-section label='Location'>{{area}}</ui-section>
|
||||
|
||||
<ui-button
|
||||
state='{{swap_button_state}}'
|
||||
action='swap' params='{"ref": "{{ref}}"}'>
|
||||
{{is_current ? "You Are Here" : "Swap"}}
|
||||
</ui-button>
|
||||
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
@@ -0,0 +1,70 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
capacityPercentState () {
|
||||
const charge = this.get('data.capacityPercent')
|
||||
if (charge > 50) return 'good'
|
||||
else if (charge > 15) return 'average'
|
||||
else return 'bad'
|
||||
},
|
||||
inputState () {
|
||||
if (this.get('data.capacityPercent') >= 100) return 'good'
|
||||
else if (this.get('data.inputting')) return 'average'
|
||||
else return 'bad'
|
||||
},
|
||||
outputState () {
|
||||
if (this.get('data.outputting')) return 'good'
|
||||
else if (this.get('data.charge') > 0) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Storage'>
|
||||
<ui-section label='Stored Energy'>
|
||||
<ui-bar min='0' max='100' value='{{data.capacityPercent}}' state='{{capacityPercentState}}'>{{Math.fixed(adata.capacityPercent)}}%</ui-bar>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Input'>
|
||||
<ui-section label='Charge Mode'>
|
||||
<ui-button icon='{{data.inputAttempt ? "refresh" : "close"}}' style='{{data.inputAttempt ? "selected" : null}}'
|
||||
action='tryinput'>{{data.inputAttempt ? "Auto" : "Off"}}</ui-button>
|
||||
|
||||
[<span class='{{inputState}}'>{{data.capacityPercent >= 100 ? "Fully Charged" : data.inputting ? "Charging" : "Not Charging"}}</span>]
|
||||
</ui-section>
|
||||
<ui-section label='Target Input'>
|
||||
<ui-bar min='0' max='{{data.inputLevelMax}}' value='{{data.inputLevel}}'>{{Math.round(adata.inputLevel)}}W</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Adjust Input'>
|
||||
<ui-button icon='fast-backward' state='{{data.inputLevel == 0 ? "disabled" : null}}' action='input' params='{"target": "min"}'/>
|
||||
<ui-button icon='backward' state='{{data.inputLevel == 0 ? "disabled" : null}}' action='input' params='{"adjust": -10000}'/>
|
||||
<ui-button icon='pencil' action='input' params='{"target": "input"}'>Set</ui-button>
|
||||
<ui-button icon='forward' state='{{data.inputLevel == data.inputLevelMax ? "disabled" : null}}' action='input' params='{"adjust": 10000}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.inputLevel == data.inputLevelMax ? "disabled" : null}}' action='input' params='{"target": "max"}'/>
|
||||
</ui-section>
|
||||
<ui-section label='Available'>
|
||||
<span>{{Math.round(adata.inputAvailable)}}W</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Output'>
|
||||
<ui-section label='Output Mode'>
|
||||
<ui-button icon='{{data.outputAttempt ? "power-off" : "close"}}' style='{{data.outputAttempt ? "selected" : null}}'
|
||||
action='tryoutput'>{{data.outputAttempt ? "On" : "Off"}}</ui-button>
|
||||
|
||||
[<span class='{{outputState}}'>{{data.outputting ? "Sending" : data.charge > 0 ? "Not Sending" : "No Charge"}}</span>]
|
||||
</ui-section>
|
||||
<ui-section label='Target Output'>
|
||||
<ui-bar min='0' max='{{data.outputLevelMax}}' value='{{data.outputLevel}}'>{{Math.round(adata.outputLevel)}}W</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Adjust Output'>
|
||||
<ui-button icon='fast-backward' state='{{data.outputLevel == 0 ? "disabled" : null}}' action='output' params='{"target": "min"}'/>
|
||||
<ui-button icon='backward' state='{{data.outputLevel == 0 ? "disabled" : null}}' action='output' params='{"adjust": -10000}'/>
|
||||
<ui-button icon='pencil' action='output' params='{"target": "input"}'>Set</ui-button>
|
||||
<ui-button icon='forward' state='{{data.outputLevel == data.outputLevelMax ? "disabled" : null}}' action='output' params='{"adjust": 10000}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.outputLevel == data.outputLevelMax ? "disabled" : null}}' action='output' params='{"target": "max"}'/>
|
||||
</ui-section>
|
||||
<ui-section label='Outputting'>
|
||||
<span>{{Math.round(adata.outputUsed)}}W</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,46 @@
|
||||
<ui-display title='Status'>
|
||||
<ui-section label='Generated Power'>
|
||||
{{Math.round(adata.generated)}}W
|
||||
</ui-section>
|
||||
<ui-section label='Orientation'>
|
||||
<span>{{Math.round(adata.angle)}}° ({{data.direction}})</span>
|
||||
</ui-section>
|
||||
<ui-section label='Adjust Angle'>
|
||||
<ui-button icon='step-backward' action='angle' params='{"adjust": -15}'>15°</ui-button>
|
||||
<ui-button icon='backward' action='angle' params='{"adjust": -5}'>5°</ui-button>
|
||||
<ui-button icon='forward' action='angle' params='{"adjust": 5}'>5°</ui-button>
|
||||
<ui-button icon='step-forward' action='angle' params='{"adjust": 15}'>15°</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Tracking'>
|
||||
<ui-section label='Tracker Mode'>
|
||||
<ui-button icon='close' state='{{data.tracking_state == 0 ? "selected" : null}}'
|
||||
action='tracking' params='{"mode": 0}'>Off</ui-button>
|
||||
<ui-button icon='clock-o' state='{{data.tracking_state == 1 ? "selected" : null}}'
|
||||
action='tracking' params='{"mode": 1}'>Timed</ui-button>
|
||||
<ui-button icon='refresh' state='{{data.connected_tracker ? data.tracking_state == 2 ? "selected" : null : "disabled"}}'
|
||||
action='tracking' params='{"mode": 2}'>Auto</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Tracking Rate'>
|
||||
<span>{{Math.round(adata.tracking_rate)}}°/h ({{data.rotating_way}})</span>
|
||||
</ui-section>
|
||||
<ui-section label='Adjust Rate'>
|
||||
<ui-button icon='fast-backward' action='rate' params='{"adjust": -180}'>180°</ui-button>
|
||||
<ui-button icon='step-backward' action='rate' params='{"adjust": -30}'>30°</ui-button>
|
||||
<ui-button icon='backward' action='rate' params='{"adjust": -5}'>5°</ui-button>
|
||||
<ui-button icon='forward' action='rate' params='{"adjust": 5}'>5°</ui-button>
|
||||
<ui-button icon='step-forward' action='rate' params='{"adjust": 30}'>30°</ui-button>
|
||||
<ui-button icon='fast-forward' action='rate' params='{"adjust": 180}'>180°</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title="Devices" button>
|
||||
{{#partial button}}
|
||||
<ui-button icon='refresh' action='refresh'>Refresh</ui-button>
|
||||
{{/partial}}
|
||||
<ui-section label='Solar Tracker'>
|
||||
<span class='{{data.connected_tracker ? "good" : "bad"}}'>{{data.connected_tracker ? "" : "Not "}}Found</span>
|
||||
</ui-section>
|
||||
<ui-section label='Solar Panels'>
|
||||
<span class='{{data.connected_panels ? "good" : "bad"}}'>{{Math.round(adata.connected_panels)}} Panels Connected</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,45 @@
|
||||
<ui-display title='Power' button>
|
||||
{{#partial button}}
|
||||
{{#if data.open}}
|
||||
<ui-button icon='eject' state='{{data.hasPowercell ? null : "disabled"}}' action='eject'>Eject</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}'
|
||||
style='{{data.on ? "selected" : null}}' state='{{data.hasPowercell ? null : "disabled"}}'
|
||||
action='power'>{{data.on ? "On" : "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Cell'>
|
||||
{{#if data.hasPowercell}}
|
||||
<ui-bar min='0' max='100' value='{{data.powerLevel}}'>{{Math.fixed(adata.powerLevel)}}%</ui-bar>
|
||||
{{else}}
|
||||
<span class='bad'>No Cell</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Thermostat'>
|
||||
<ui-section label='Current Temperature'>
|
||||
<span>{{Math.round(adata.currentTemp)}}°C</span>
|
||||
</ui-section>
|
||||
<ui-section label='Target Temperature'>
|
||||
<span>{{Math.round(adata.targetTemp)}}°C</span>
|
||||
</ui-section>
|
||||
{{#if data.open}}
|
||||
<ui-section label='Adjust Target'>
|
||||
<ui-button icon='fast-backward' state='{{data.targetTemp > data.minTemp ? null : "disabled"}}' action='target' params='{"adjust": -20}'/>
|
||||
<ui-button icon='backward' state='{{data.targetTemp > data.minTemp ? null : "disabled"}}' action='target' params='{"adjust": -5}'/>
|
||||
<ui-button icon='pencil' action='target' params='{"target": "input"}'>Set</ui-button>
|
||||
<ui-button icon='forward' state='{{data.targetTemp < data.maxTemp ? null : "disabled"}}' action='target' params='{"adjust": 5}'/>
|
||||
<ui-button icon='fast-forward' state='{{data.targetTemp < data.maxTemp ? null : "disabled"}}' action='target' params='{"adjust": 20}'/>
|
||||
</ui-section>
|
||||
{{/if}}
|
||||
<ui-section label='Mode'>
|
||||
{{#if data.open}}
|
||||
<ui-button icon='long-arrow-up' state='{{data.mode == "heat" ? "selected" : null}}' action='mode' params='{"mode": "heat"}'>Heat</ui-button>
|
||||
<ui-button icon='long-arrow-down' state='{{data.mode == "cool" ? "selected" : null}}' action='mode' params='{"mode": "cool"}'>Cool</ui-button>
|
||||
<ui-button icon='arrows-v' state='{{data.mode == "auto" ? "selected" : null}}' action='mode' params='{"mode": "auto"}'>Auto</ui-button>
|
||||
{{else}}
|
||||
<span>{{text.titleCase(data.mode)}}</span>
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,11 @@
|
||||
{{#each data.alarms:class}}
|
||||
<ui-display title='{{class}} Alarms'>
|
||||
<ul>
|
||||
{{#each .}}
|
||||
<li>{{.}}</li>
|
||||
{{else}}
|
||||
<li>System Nominal</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</ui-display>
|
||||
{{/each}}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{#if data.occupied && data.safeties}}
|
||||
<ui-notice>
|
||||
<span>Biological entity detected in contents. Please remove.</span>
|
||||
</ui-notice>
|
||||
{{/if}}
|
||||
{{#if data.uv_active}}
|
||||
<ui-notice>
|
||||
<span>Contents are being disinfected. Please wait.</span>
|
||||
</ui-notice>
|
||||
{{else}}
|
||||
<ui-display title='Storage' button>
|
||||
{{#partial button}}
|
||||
{{#if !data.open}}<ui-button icon='{{data.locked ? "unlock" : "lock"}}' action='lock'>{{data.locked ? 'Unlock' : 'Lock'}}</ui-button>{{/if}}
|
||||
{{#if !data.locked}}<ui-button icon='{{data.open ? "sign-out" : "sign-in"}}' action='door'>{{data.open ? 'Close' : 'Open'}}</ui-button>{{/if}}
|
||||
{{/partial}}
|
||||
{{#if data.locked}}
|
||||
<ui-notice>
|
||||
<span>Unit Locked</span>
|
||||
</ui-notice>
|
||||
{{elseif data.open}}
|
||||
<ui-section label='Helmet'>
|
||||
<ui-button icon='{{data.helmet ? "square" : "square-o"}}'state='{{data.helmet ? null : "disabled"}}'
|
||||
action='dispense' params='{"item": "helmet"}'>{{data.helmet || "Empty"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Suit'>
|
||||
<ui-button icon='{{data.suit ? "square" : "square-o"}}' state='{{data.suit ? null : "disabled"}}'
|
||||
action='dispense' params='{"item": "suit"}'>{{data.suit || "Empty"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Mask'>
|
||||
<ui-button icon='{{data.mask ? "square" : "square-o"}}' state='{{data.mask ? null : "disabled"}}'
|
||||
action='dispense' params='{"item": "mask"}'>{{data.mask || "Empty"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Storage'>
|
||||
<ui-button icon='{{data.storage ? "square" : "square-o"}}' state='{{data.storage ? null : "disabled"}}'
|
||||
action='dispense' params='{"item": "storage"}'>{{data.storage || "Empty"}}</ui-button>
|
||||
</ui-section>
|
||||
{{else}}
|
||||
<ui-button icon='recycle' state='{{data.occupied && data.safeties ? "disabled" : null}}' action='uv'>Disinfect</ui-button>
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,8 @@
|
||||
<ui-display>
|
||||
<ui-section label='Dispense'>
|
||||
<ui-button icon='{{data.plasma ? "square" : "square-o"}}' state='{{data.plasma ? null : "disabled"}}'
|
||||
action='plasma'>Plasma ({{Math.round(adata.plasma)}})</ui-button>
|
||||
<ui-button icon='{{data.oxygen ? "square" : "square-o"}}' state='{{data.oxygen ? null : "disabled"}}'
|
||||
action='oxygen'>Oxygen ({{Math.round(adata.oxygen)}})</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,35 @@
|
||||
<script>
|
||||
component.exports = {
|
||||
computed: {
|
||||
tankPressureState () {
|
||||
const pressure = this.get('data.tankPressure')
|
||||
if (pressure >= 200) return 'good'
|
||||
else if (pressure >= 100) return 'average'
|
||||
else return 'bad'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-notice>
|
||||
<span>The regulator {{data.connected? "is" : "is not"}} connected to a mask.</span>
|
||||
</ui-notice>
|
||||
<ui-display>
|
||||
<ui-section label='Tank Pressure'>
|
||||
<ui-bar min='0' max='1013' value='{{data.tankPressure}}'
|
||||
state='{{tankPressureState}}'>{{Math.round(adata.tankPressure)}} kPa</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Release Pressure'>
|
||||
<ui-bar min='{{data.minReleasePressure}}' max='{{data.maxReleasePressure}}'
|
||||
value='{{data.releasePressure}}'>{{Math.round(adata.releasePressure)}} kPa</ui-bar>
|
||||
</ui-section>
|
||||
<ui-section label='Pressure Regulator'>
|
||||
<ui-button icon='refresh' state='{{data.releasePressure != data.defaultReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "reset"}'>Reset</ui-button>
|
||||
<ui-button icon='minus' state='{{data.releasePressure > data.minReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "min"}'>Min</ui-button>
|
||||
<ui-button icon='pencil' action='pressure' params='{"pressure": "input"}'>Set</ui-button>
|
||||
<ui-button icon='plus' state='{{data.releasePressure < data.maxReleasePressure ? null : "disabled"}}'
|
||||
action='pressure' params='{"pressure": "max"}'>Max</ui-button>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,25 @@
|
||||
<ui-display title='Status'>
|
||||
<ui-section label='Temperature'>
|
||||
<span>{{Math.fixed(adata.temperature, 2)}} K</span>
|
||||
</ui-section>
|
||||
<ui-section label='Pressure'>
|
||||
<span>{{Math.fixed(adata.pressure, 2)}} kPa</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
<ui-display title='Controls'>
|
||||
<ui-section label='Power'>
|
||||
<ui-button icon='{{data.on ? "power-off" : "close"}}' style="{{data.on ? "selected" : null}}"
|
||||
action='power'>{{data.on ? "On": "Off"}}</ui-button>
|
||||
</ui-section>
|
||||
<ui-section label='Target Temperature'>
|
||||
<ui-button icon='fast-backward' style='{{data.target == data.min ? "disabled" : null}}'
|
||||
action='target' params='{"adjust": -20}'/>
|
||||
<ui-button icon='backward' style='{{data.target == data.min ? "disabled" : null}}'
|
||||
action='target' params='{"adjust": -5}'/>
|
||||
<ui-button icon='pencil' action='target' params='{"target": "input"}'>{{Math.fixed(adata.target, 2)}}</ui-button>
|
||||
<ui-button icon='forward' style='{{data.target == data.max ? "disabled" : null}}'
|
||||
action='target' params='{"adjust": 5}'/>
|
||||
<ui-button icon='fast-forward' style='{{data.target == data.max ? "disabled" : null}}'
|
||||
action='target' params='{"adjust": 20}'/>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
@@ -0,0 +1,50 @@
|
||||
<script>
|
||||
import { filterMulti } from 'util/filter'
|
||||
component.exports = {
|
||||
data: {
|
||||
filter: ''
|
||||
},
|
||||
oninit () {
|
||||
this.on({
|
||||
hover (event) {
|
||||
const uses = this.get('data.telecrystals')
|
||||
if (uses >= event.context.params.cost)
|
||||
this.set('hovered', event.context.params)
|
||||
},
|
||||
unhover (event) {
|
||||
this.set('hovered')
|
||||
}
|
||||
})
|
||||
this.observe('filter', (newkey, oldkey, keypath) => {
|
||||
const categories = this.findAll('.display:not(:first-child)')
|
||||
filterMulti(categories, this.get('filter').toLowerCase())
|
||||
}, { init: false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ui-display title='Uplink' button>
|
||||
{{#partial button}}
|
||||
{{#if config.fancy}}
|
||||
<ui-input value='{{filter}}' placeholder='Filter...'/>
|
||||
{{/if}}
|
||||
{{#if data.lockable}}
|
||||
<ui-button icon='lock' action='lock'>Lock</ui-button>
|
||||
{{/if}}
|
||||
{{/partial}}
|
||||
<ui-section label='Telecrystals' right>
|
||||
<span class='{{data.telecrystals > 0 ? "good" : "bad"}}'>{{data.telecrystals}} TC</span>
|
||||
</ui-section>
|
||||
</ui-display>
|
||||
{{#each data.categories}}
|
||||
<ui-display title='{{name}}'>
|
||||
{{#each items}}
|
||||
<ui-section label='{{name}}' candystripe right>
|
||||
<ui-button tooltip='{{name}}: {{desc}}' tooltip-side='left'
|
||||
state='{{data.telecrystals < cost || (data.telecrystals - hovered.cost < cost && hovered.item != name) ? "disabled" : null}}'
|
||||
action='buy' params='{"category": "{{category}}", "item": {{name}}, "cost": {{cost}}}'
|
||||
on-hover='hover' on-unhover='unhover'>{{cost}} TC</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
{{/each}}
|
||||
@@ -0,0 +1,16 @@
|
||||
<ui-display>
|
||||
{{#each data.wires}}
|
||||
<ui-section label='{{color}}{{wire ? " (" + wire + ")" : ""}}' labelcolor='{{color}}' candystripe right>
|
||||
<ui-button action='cut' params='{"wire":"{{color}}"}'>{{cut ? "Mend" : "Cut"}}</ui-button>
|
||||
<ui-button action='pulse' params='{"wire":"{{color}}"}'>Pulse</ui-button>
|
||||
<ui-button action='attach' params='{"wire":"{{color}}"}'>{{attached ? "Detach" : "Attach"}}</ui-button>
|
||||
</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
{{#if data.status}}
|
||||
<ui-display>
|
||||
{{#each data.status}}
|
||||
<ui-section>{{.}}</ui-section>
|
||||
{{/each}}
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
@@ -0,0 +1,7 @@
|
||||
body.nanotrasen
|
||||
background: data-url('images/nanotrasen.svg') no-repeat fixed center/70% 70%,
|
||||
linear-gradient(to bottom,
|
||||
background-color-start 0%,
|
||||
background-color-end 100%)
|
||||
@import "util/*"
|
||||
@import "components/*"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user