update cryptoBalance notification
This commit is contained in:
parent
6759bec826
commit
e8356c1041
8 changed files with 599 additions and 378 deletions
|
|
@ -48,6 +48,18 @@
|
||||||
"minimumTx"
|
"minimumTx"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"code": "balanceAlerts",
|
||||||
|
"display": "Balance Alerts",
|
||||||
|
"cryptoScope": "both",
|
||||||
|
"machineScope": "both",
|
||||||
|
"fields": [
|
||||||
|
"cryptoAlertThreshold",
|
||||||
|
"cashInAlertThreshold",
|
||||||
|
"cashOutCassette1AlertThreshold",
|
||||||
|
"cashOutCassette2AlertThreshold"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"code": "compliance",
|
"code": "compliance",
|
||||||
"display": "Compliance",
|
"display": "Compliance",
|
||||||
|
|
@ -84,8 +96,7 @@
|
||||||
"notificationsEmailEnabled",
|
"notificationsEmailEnabled",
|
||||||
"notificationsSMSEnabled",
|
"notificationsSMSEnabled",
|
||||||
"sms",
|
"sms",
|
||||||
"email",
|
"email"
|
||||||
"balancesThreshold"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -171,6 +182,93 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"code": "cryptoAlertThreshold",
|
||||||
|
"displayTop": "Crypto",
|
||||||
|
"displayBottom": "Threshold",
|
||||||
|
"fieldType": "integer",
|
||||||
|
"fieldClass": "fiat",
|
||||||
|
"cryptoScope": "both",
|
||||||
|
"machineScope": "global",
|
||||||
|
"enabledIf": [
|
||||||
|
"notificationsEnabled"
|
||||||
|
],
|
||||||
|
"fieldValidation": [
|
||||||
|
{
|
||||||
|
"code": "required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "min",
|
||||||
|
"min": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "cashInAlertThreshold",
|
||||||
|
"displayTop": "Cash-in",
|
||||||
|
"displayBottom": "Threshold",
|
||||||
|
"fieldType": "integer",
|
||||||
|
"fieldClass": "banknotes",
|
||||||
|
"cryptoScope": "global",
|
||||||
|
"machineScope": "both",
|
||||||
|
"enabledIf": [
|
||||||
|
"notificationsEnabled"
|
||||||
|
],
|
||||||
|
"fieldValidation": [
|
||||||
|
{
|
||||||
|
"code": "required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "min",
|
||||||
|
"min": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "cashOutCassette1AlertThreshold",
|
||||||
|
"displayTop": "Cash-out Thresholds",
|
||||||
|
"displayTopCount": 2,
|
||||||
|
"displayBottom": "Top",
|
||||||
|
"fieldType": "integer",
|
||||||
|
"fieldClass": "banknotes",
|
||||||
|
"cryptoScope": "global",
|
||||||
|
"machineScope": "both",
|
||||||
|
"default": 10,
|
||||||
|
"enabledIf": [
|
||||||
|
"notificationsEnabled"
|
||||||
|
],
|
||||||
|
"fieldValidation": [
|
||||||
|
{
|
||||||
|
"code": "required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "min",
|
||||||
|
"min": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "cashOutCassette2AlertThreshold",
|
||||||
|
"displayTopCount": 0,
|
||||||
|
"displayBottom": "Bottom",
|
||||||
|
"fieldType": "integer",
|
||||||
|
"fieldClass": "banknotes",
|
||||||
|
"cryptoScope": "global",
|
||||||
|
"machineScope": "both",
|
||||||
|
"default": 10,
|
||||||
|
"enabledIf": [
|
||||||
|
"notificationsEnabled"
|
||||||
|
],
|
||||||
|
"fieldValidation": [
|
||||||
|
{
|
||||||
|
"code": "required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "min",
|
||||||
|
"min": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"code": "zeroConfLimit",
|
"code": "zeroConfLimit",
|
||||||
"displayTop": "0-conf",
|
"displayTop": "0-conf",
|
||||||
|
|
@ -497,17 +595,6 @@
|
||||||
"notificationsEmailEnabled"
|
"notificationsEmailEnabled"
|
||||||
],
|
],
|
||||||
"fieldValidation": [{"code": "required"}]
|
"fieldValidation": [{"code": "required"}]
|
||||||
},
|
|
||||||
{
|
|
||||||
"code": "balancesThreshold",
|
|
||||||
"displayTop": "Balances",
|
|
||||||
"displayBottom": "Threshold",
|
|
||||||
"fieldType": "percentage",
|
|
||||||
"fieldClass": null,
|
|
||||||
"enabledIf": [
|
|
||||||
"notificationsEnabled"
|
|
||||||
],
|
|
||||||
"fieldValidation": [{"code": "required"}]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ function validateRequires (config) {
|
||||||
return schema.groups.filter(group => {
|
return schema.groups.filter(group => {
|
||||||
return group.fields.some(fieldCode => {
|
return group.fields.some(fieldCode => {
|
||||||
const field = getGroupField(group, fieldCode)
|
const field = getGroupField(group, fieldCode)
|
||||||
|
|
||||||
if (!field.fieldValidation.find(r => r.code === 'required')) return false
|
if (!field.fieldValidation.find(r => r.code === 'required')) return false
|
||||||
|
|
||||||
const refFields = _.map(_.partial(getField, group), field.enabledIf)
|
const refFields = _.map(_.partial(getField, group), field.enabledIf)
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,18 @@ const STALE_STATE = 2 * T.minute
|
||||||
const NETWORK_DOWN_TIME = 1 * T.minute
|
const NETWORK_DOWN_TIME = 1 * T.minute
|
||||||
const ALERT_SEND_INTERVAL = T.hour
|
const ALERT_SEND_INTERVAL = T.hour
|
||||||
|
|
||||||
const PING = Symbol('PING')
|
const PING = 'PING'
|
||||||
const STALE = Symbol('STALE')
|
const STALE = 'STALE'
|
||||||
const LOW_BALANCE = Symbol('LOW_BALANCE')
|
const LOW_CRYPTO_BALANCE = 'LOW_CRYPTO_BALANCE'
|
||||||
|
const CASH_BOX_FULL = 'CASH_BOX_FULL'
|
||||||
|
const LOW_CASH_OUT = 'LOW_CASH_OUT'
|
||||||
|
|
||||||
const CODES_DISPLAY = {
|
const CODES_DISPLAY = {
|
||||||
[PING]: 'Machine Down',
|
PING: 'Machine Down',
|
||||||
[STALE]: 'Machine Stuck',
|
STALE: 'Machine Stuck',
|
||||||
[LOW_BALANCE]: 'Low Balance'
|
LOW_CRYPTO_BALANCE: 'Low Crypto Balance',
|
||||||
|
CASH_BOX_FULL: 'Cash box full',
|
||||||
|
LOW_CASH_OUT: 'Low Cash-out'
|
||||||
}
|
}
|
||||||
|
|
||||||
let alertFingerprint
|
let alertFingerprint
|
||||||
|
|
@ -151,7 +155,7 @@ function checkStatus (plugins) {
|
||||||
.then(([balances, events, devices]) => {
|
.then(([balances, events, devices]) => {
|
||||||
return checkPings(devices)
|
return checkPings(devices)
|
||||||
.then(pings => {
|
.then(pings => {
|
||||||
alerts.general = balances
|
alerts.general = _.filter(r => !r.deviceId, balances)
|
||||||
devices.forEach(function (device) {
|
devices.forEach(function (device) {
|
||||||
const deviceId = device.deviceId
|
const deviceId = device.deviceId
|
||||||
const deviceName = device.name
|
const deviceName = device.name
|
||||||
|
|
@ -159,12 +163,13 @@ function checkStatus (plugins) {
|
||||||
return eventRow.device_id === deviceId
|
return eventRow.device_id === deviceId
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const balanceAlerts = _.filter(['deviceId', deviceId], balances)
|
||||||
const ping = pings[deviceId] || []
|
const ping = pings[deviceId] || []
|
||||||
const stuckScreen = checkStuckScreen(deviceEvents)
|
const stuckScreen = checkStuckScreen(deviceEvents)
|
||||||
|
|
||||||
const deviceAlerts = _.isEmpty(ping) ? stuckScreen : ping
|
const deviceAlerts = _.isEmpty(ping) ? stuckScreen : ping
|
||||||
|
|
||||||
alerts.devices[deviceId] = deviceAlerts
|
alerts.devices[deviceId] = _.concat(deviceAlerts, balanceAlerts)
|
||||||
alerts.deviceNames[deviceId] = deviceName
|
alerts.deviceNames[deviceId] = deviceName
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -188,9 +193,13 @@ function emailAlert (alert) {
|
||||||
case STALE:
|
case STALE:
|
||||||
const stuckAge = prettyMs(alert.age, {compact: true, verbose: true})
|
const stuckAge = prettyMs(alert.age, {compact: true, verbose: true})
|
||||||
return `Machine is stuck on ${alert.state} screen for ${stuckAge}`
|
return `Machine is stuck on ${alert.state} screen for ${stuckAge}`
|
||||||
case LOW_BALANCE:
|
case LOW_CRYPTO_BALANCE:
|
||||||
const balance = formatCurrency(alert.fiatBalance.balance, alert.fiatCode)
|
const balance = formatCurrency(alert.fiatBalance.balance, alert.fiatCode)
|
||||||
return `Low balance of ${balance} in ${alert.cryptoCode} wallet`
|
return `Low balance in ${alert.cryptoCode} [${balance}]`
|
||||||
|
case CASH_BOX_FULL:
|
||||||
|
return `Cash box full on ${alert.machineName} [${alert.notes} banknotes]`
|
||||||
|
case LOW_CASH_OUT:
|
||||||
|
return `Cassette for ${alert.denomination} ${alert.fiatCode} low [${alert.notes} banknotes]`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -470,48 +470,70 @@ function plugins (settings, deviceId) {
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDeviceBalances (_deviceId) {
|
function checkDevicesCashBalances (fiatCode, devices) {
|
||||||
const config = configManager.machineScoped(_deviceId, settings.config)
|
return _.map(device => checkDeviceCashBalances(fiatCode, device), devices)
|
||||||
const cryptoCodes = config.cryptoCurrencies
|
|
||||||
const fiatCode = config.fiatCurrency
|
|
||||||
|
|
||||||
const fiatBalancePromises = cryptoCodes.map(c => fiatBalance(fiatCode, c))
|
|
||||||
|
|
||||||
return Promise.all(fiatBalancePromises)
|
|
||||||
.then(arr => {
|
|
||||||
return arr.map((balance, i) => ({
|
|
||||||
fiatBalance: balance,
|
|
||||||
cryptoCode: cryptoCodes[i],
|
|
||||||
fiatCode,
|
|
||||||
_deviceId
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBalance (rec) {
|
function checkDeviceCashBalances (fiatCode, device) {
|
||||||
const config = configManager.unscoped(settings.config)
|
const config = configManager.machineScoped(device.deviceId, settings.config)
|
||||||
const lowBalanceThreshold = config.lowBalanceThreshold
|
const denomination1 = config.topCashOutDenomination
|
||||||
|
const denomination2 = config.bottomCashOutDenomination
|
||||||
|
const machineName = config.machineName
|
||||||
|
|
||||||
return rec.fiatBalance.balance <= lowBalanceThreshold
|
const cashInAlert = device.cashbox > config.cashInAlertThreshold
|
||||||
? {code: Symbol('LOW_BALANCE'), cryptoCode: rec.cryptoCode, fiatBalance: rec.fiatBalance, fiatCode: rec.fiatCode}
|
? {code: 'CASH_BOX_FULL', machineName, deviceId: device.deviceId, notes: device.cashbox}
|
||||||
|
: null
|
||||||
|
|
||||||
|
const cassette1Alert = device.cassette1 < config.cashOutCassette1AlertThreshold
|
||||||
|
? {code: 'LOW_CASH_OUT', cassette: 1, machineName, deviceId: device.deviceId,
|
||||||
|
notes: device.cassette1, denomination: denomination1, fiatCode}
|
||||||
|
: null
|
||||||
|
|
||||||
|
const cassette2Alert = device.cassette2 < config.cashOutCassette2AlertThreshold
|
||||||
|
? {code: 'LOW_CASH_OUT', cassette: 2, machineName, deviceId: device.deviceId,
|
||||||
|
notes: device.cassette2, denomination: denomination2, fiatCode}
|
||||||
|
: null
|
||||||
|
|
||||||
|
return _.compact([cashInAlert, cassette1Alert, cassette2Alert])
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCryptoBalances (fiatCode, devices) {
|
||||||
|
const fiatBalancePromises = cryptoCodes => _.map(c => fiatBalance(fiatCode, c), cryptoCodes)
|
||||||
|
|
||||||
|
const fetchCryptoCodes = _deviceId => {
|
||||||
|
const config = configManager.machineScoped(_deviceId, settings.config)
|
||||||
|
return config.cryptoCurrencies
|
||||||
|
}
|
||||||
|
|
||||||
|
const union = _.flow(_.map(fetchCryptoCodes), _.flatten, _.uniq)
|
||||||
|
const cryptoCodes = union(devices)
|
||||||
|
const checkCryptoBalanceWithFiat = _.partial(checkCryptoBalance, [fiatCode])
|
||||||
|
|
||||||
|
return Promise.all(fiatBalancePromises(cryptoCodes))
|
||||||
|
.then(balances => _.map(checkCryptoBalanceWithFiat, _.zip(cryptoCodes, balances)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCryptoBalance (fiatCode, rec) {
|
||||||
|
const [cryptoCode, fiatBalance] = rec
|
||||||
|
const config = configManager.cryptoScoped(cryptoCode, settings.config)
|
||||||
|
const cryptoAlertThreshold = config.cryptoAlertThreshold
|
||||||
|
|
||||||
|
return BN(fiatBalance.balance).lt(cryptoAlertThreshold)
|
||||||
|
? {code: 'LOW_CRYPTO_BALANCE', cryptoCode, fiatBalance, fiatCode}
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBalances () {
|
function checkBalances () {
|
||||||
|
const globalConfig = configManager.unscoped(settings.config)
|
||||||
|
const fiatCode = globalConfig.fiatCurrency
|
||||||
|
|
||||||
return machineLoader.getMachines()
|
return machineLoader.getMachines()
|
||||||
.then(devices => {
|
.then(devices => {
|
||||||
const deviceIds = devices.map(r => r.deviceId)
|
return Promise.all([
|
||||||
const deviceBalancePromises = deviceIds.map(deviceId => checkDeviceBalances(deviceId))
|
checkCryptoBalances(fiatCode, devices),
|
||||||
|
checkDevicesCashBalances(fiatCode, devices)
|
||||||
return Promise.all(deviceBalancePromises)
|
])
|
||||||
.then(arr => {
|
.then(_.flow(_.flattenDeep, _.compact))
|
||||||
const toMarket = r => [r.fiatCode, r.cryptoCode].join('')
|
|
||||||
const min = _.minBy(r => r.fiatBalance)
|
|
||||||
const byMarket = _.groupBy(toMarket, _.flatten(arr))
|
|
||||||
const minByMarket = _.flatMap(min, byMarket)
|
|
||||||
|
|
||||||
return _.reject(_.isNil, _.map(checkBalance, minByMarket))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ const SWEEP_HD_INTERVAL = T.minute
|
||||||
const TRADE_INTERVAL = 10 * T.seconds
|
const TRADE_INTERVAL = 10 * T.seconds
|
||||||
const PONG_INTERVAL = 10 * T.seconds
|
const PONG_INTERVAL = 10 * T.seconds
|
||||||
const PONG_CLEAR_INTERVAL = 1 * T.day
|
const PONG_CLEAR_INTERVAL = 1 * T.day
|
||||||
|
|
||||||
const CHECK_NOTIFICATION_INTERVAL = 20 * T.seconds
|
const CHECK_NOTIFICATION_INTERVAL = 20 * T.seconds
|
||||||
|
|
||||||
const PENDING_INTERVAL = 10 * T.seconds
|
const PENDING_INTERVAL = 10 * T.seconds
|
||||||
|
|
||||||
let _pi, _settings
|
let _pi, _settings
|
||||||
|
|
|
||||||
26
migrations/035-log_bank_notes.js
Normal file
26
migrations/035-log_bank_notes.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
var db = require('./db')
|
||||||
|
|
||||||
|
exports.up = function (next) {
|
||||||
|
var sql = [
|
||||||
|
`create table cash_out_refills (
|
||||||
|
id uuid PRIMARY KEY,
|
||||||
|
device_id text not null,
|
||||||
|
user_id integer not null,
|
||||||
|
cassette1 integer not null,
|
||||||
|
cassette2 integer not null,
|
||||||
|
denomination1 integer not null,
|
||||||
|
denomination2 integer not null,
|
||||||
|
created timestamptz not null default now())`,
|
||||||
|
`create table cash_in_refills (
|
||||||
|
id uuid PRIMARY KEY,
|
||||||
|
device_id text not null,
|
||||||
|
user_id integer not null,
|
||||||
|
cash_box_count integer not null,
|
||||||
|
created timestamptz not null default now())`
|
||||||
|
]
|
||||||
|
db.multi(sql, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.down = function (next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
593
public/elm.js
593
public/elm.js
File diff suppressed because one or more lines are too long
|
|
@ -248,6 +248,8 @@ p {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
border: 2px solid #E6E6E3;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminNoOptions {
|
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminNoOptions {
|
||||||
|
|
@ -279,7 +281,7 @@ p {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border: 3px solid #f6f6f4;
|
border: 2px solid #E6E6E3;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
color: #5f5f56;
|
color: #5f5f56;
|
||||||
width: 15em;
|
width: 15em;
|
||||||
|
|
@ -306,7 +308,7 @@ p {
|
||||||
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminMultiItemContainer .lamassuAdminSelectedItem {
|
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminMultiItemContainer .lamassuAdminSelectedItem {
|
||||||
background-color: #004062;
|
background-color: #004062;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
padding: 4px 4px 3px;
|
padding: 2px;
|
||||||
margin: 0 1px;
|
margin: 0 1px;
|
||||||
font-family: Inconsolata, monospace;
|
font-family: Inconsolata, monospace;
|
||||||
font-size: 70%;
|
font-size: 70%;
|
||||||
|
|
@ -315,7 +317,7 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminMultiItemContainer .lamassuAdminFallbackItem {
|
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminMultiItemContainer .lamassuAdminFallbackItem {
|
||||||
background-color: #5f5f56;
|
background-color: #37e8d7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminSingleItemContainer .lamassuAdminSelectedItem {
|
.lamassuAdminConfigTable .lamassuAdminSelectizeContainer .lamassuAdminSingleItemContainer .lamassuAdminSelectedItem {
|
||||||
|
|
@ -340,16 +342,19 @@ p {
|
||||||
.lamassuAdminConfigTable .lamassuAdminInputContainer {
|
.lamassuAdminConfigTable .lamassuAdminInputContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
border: 2px solid #E6E6E3;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminUnitDisplay {
|
.lamassuAdminConfigTable .lamassuAdminUnitDisplay {
|
||||||
border-radius: 0px 3px 3px 0px;
|
|
||||||
background-color: #E6E6E3;
|
background-color: #E6E6E3;
|
||||||
color: #5f5f56;
|
color: #5f5f56;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
|
cursor: default;
|
||||||
|
font-family: Nunito, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable input {
|
.lamassuAdminConfigTable input {
|
||||||
|
|
@ -369,29 +374,35 @@ p {
|
||||||
background: repeating-linear-gradient(45deg,#dfdfdc,#dfdfdc 2px,#e6e6e3 5px);
|
background: repeating-linear-gradient(45deg,#dfdfdc,#dfdfdc 2px,#e6e6e3 5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lamassuAdminConfigTable .lamassuAdminBasicInput::placeholder {
|
||||||
|
color: #37e8d7;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminBasicInputDisabled {
|
.lamassuAdminConfigTable .lamassuAdminBasicInputDisabled {
|
||||||
height: 25px;
|
height: 25px;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #5f5f56;
|
color: #5f5f56;
|
||||||
|
opacity: 0.7;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
cursor: default;
|
|
||||||
background: repeating-linear-gradient(45deg,#dfdfdc,#dfdfdc 2px,#e6e6e3 5px);
|
background: repeating-linear-gradient(45deg,#dfdfdc,#dfdfdc 2px,#e6e6e3 5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminBasicInputReadOnly {
|
.lamassuAdminConfigTable .lamassuAdminReadOnly {
|
||||||
height: 25px;
|
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #5f5f56;
|
|
||||||
text-align: left;
|
|
||||||
padding: 0 1em;
|
|
||||||
cursor: default;
|
|
||||||
background-color: #f6f6f4;
|
background-color: #f6f6f4;
|
||||||
border: 2px solid #E6E6E3;
|
font-family: Inconsolata, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #5f5f56;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lamassuAdminConfigTable .lamassuAdminReadOnly > .lamassuAdminBasicInputReadOnly {
|
||||||
|
padding: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable td {
|
.lamassuAdminConfigTable td {
|
||||||
|
|
@ -407,16 +418,16 @@ p {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminInvalidComponent {
|
.lamassuAdminConfigTable .lamassuAdminFocusedComponent > .lamassuAdminInputContainer {
|
||||||
border-top-color: #eb6b6e;
|
border-color: #37e8d7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminInvalidComponent input {
|
.lamassuAdminConfigTable .lamassuAdminInvalidComponent input {
|
||||||
color: #eb6b6e;
|
color: #eb6b6e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable .lamassuAdminFocusedComponent {
|
.lamassuAdminConfigTable .lamassuAdminInvalidComponent > .lamassuAdminInputContainer {
|
||||||
border-top-color: #37e8d7;
|
border-color: #eb6b6e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lamassuAdminConfigTable tbody td {
|
.lamassuAdminConfigTable tbody td {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue