826 lines
23 KiB
Vue
826 lines
23 KiB
Vue
<template>
|
|
<div>
|
|
<v-data-table
|
|
v-model="selected"
|
|
:headers="customHeaders"
|
|
:items="alerts"
|
|
item-key="id"
|
|
:pagination.sync="pagination"
|
|
:total-items="pagination.totalItems"
|
|
:rows-per-page-items="pagination.rowsPerPageItems"
|
|
:loading="isSearching"
|
|
class="alert-table"
|
|
:class="[ displayDensity ]"
|
|
:style="columnWidths"
|
|
sort-icon="arrow_drop_down"
|
|
select-all
|
|
>
|
|
<template
|
|
slot="items"
|
|
slot-scope="props"
|
|
>
|
|
<tr
|
|
:style="{ 'background-color': severityColor(props.item.severity) }"
|
|
class="hover-lighten"
|
|
@click="selectItem(props.item)"
|
|
>
|
|
<td
|
|
class="text-no-wrap"
|
|
:style="fontStyle"
|
|
>
|
|
<v-checkbox
|
|
v-if="selectableRows"
|
|
v-model="props.selected"
|
|
primary
|
|
hide-details
|
|
color="gray"
|
|
class="select-box"
|
|
:ripple="false"
|
|
:size="fontSize"
|
|
@click.stop
|
|
/>
|
|
<v-icon
|
|
v-else-if="props.item.trendIndication == 'moreSevere'"
|
|
:class="['trend-arrow', textColor(props.item.severity)]"
|
|
:size="fontSize"
|
|
@click.stop="multiselect = true; props.selected = true"
|
|
>
|
|
arrow_upward
|
|
</v-icon>
|
|
<v-icon
|
|
v-else-if="props.item.trendIndication == 'lessSevere'"
|
|
:class="['trend-arrow', textColor(props.item.severity)]"
|
|
:size="fontSize"
|
|
@click.stop="multiselect = true; props.selected = true"
|
|
>
|
|
arrow_downward
|
|
</v-icon>
|
|
<v-icon
|
|
v-else
|
|
:class="['trend-arrow', textColor(props.item.severity)]"
|
|
:size="fontSize"
|
|
@click.stop="multiselect = true; props.selected = true"
|
|
>
|
|
remove
|
|
</v-icon>
|
|
</td>
|
|
<td
|
|
v-for="col in $config.columns"
|
|
:key="col"
|
|
:class="['text-no-wrap', textColor(props.item.severity)]"
|
|
:style="fontStyle"
|
|
>
|
|
<span
|
|
v-if="col == 'id'"
|
|
>
|
|
{{ props.item.id | shortId }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'resource'"
|
|
>
|
|
{{ props.item.resource }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'event'"
|
|
>
|
|
{{ props.item.event }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'environment'"
|
|
>
|
|
{{ props.item.environment }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'severity'"
|
|
>
|
|
<span
|
|
:class="['label', 'label-' + props.item.severity.toLowerCase()]"
|
|
:style="fontStyle"
|
|
>
|
|
{{ props.item.severity | capitalize }}
|
|
</span>
|
|
</span>
|
|
<span
|
|
v-if="col == 'correlate'"
|
|
>
|
|
{{ props.item.correlate.join(', ') }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'status'"
|
|
>
|
|
<span
|
|
class="label"
|
|
:style="fontStyle"
|
|
>
|
|
{{ props.item.status | capitalize }}
|
|
|
|
</span>
|
|
<span
|
|
v-if="showNotesIcon"
|
|
>
|
|
<span
|
|
v-if="lastNote(props.item)"
|
|
class="pl-2"
|
|
>
|
|
<v-tooltip bottom>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<v-icon
|
|
v-bind="attrs"
|
|
small
|
|
v-on="on"
|
|
>text_snippet</v-icon>
|
|
</template>
|
|
<span>{{ lastNote(props.item) }}</span>
|
|
</v-tooltip>
|
|
</span>
|
|
</span>
|
|
</span>
|
|
<span
|
|
v-if="col == 'service'"
|
|
>
|
|
{{ props.item.service.join(', ') }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'group'"
|
|
>
|
|
{{ props.item.group }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'value'"
|
|
>
|
|
<div class="fixed-table">
|
|
<div class="text-truncate">
|
|
<span v-html="props.item.value" />
|
|
</div>
|
|
</div>
|
|
</span>
|
|
<span
|
|
v-if="col == 'text'"
|
|
>
|
|
<div class="fixed-table">
|
|
<div class="text-truncate">
|
|
<span v-html="props.item.text" />
|
|
</div>
|
|
</div>
|
|
</span>
|
|
<span
|
|
v-if="col == 'tags'"
|
|
>
|
|
<span
|
|
v-for="tag in props.item.tags"
|
|
:key="tag"
|
|
><span
|
|
class="label"
|
|
:style="fontStyle"
|
|
>{{ tag }}</span> </span>
|
|
</span>
|
|
<span
|
|
v-if="props.item.attributes.hasOwnProperty(col)"
|
|
>
|
|
<span v-html="props.item.attributes[col]" />
|
|
</span>
|
|
<span
|
|
v-if="col == 'origin'"
|
|
>
|
|
{{ props.item.origin }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'type'"
|
|
>
|
|
<span
|
|
class="label"
|
|
:style="fontStyle"
|
|
>
|
|
{{ props.item.type | splitCaps }}
|
|
</span>
|
|
</span>
|
|
<span
|
|
v-if="col == 'createTime'"
|
|
>
|
|
<date-time
|
|
:value="props.item.createTime"
|
|
format="mediumDate"
|
|
/>
|
|
</span>
|
|
<span
|
|
v-if="col == 'timeout'"
|
|
>
|
|
{{ props.item.timeout | hhmmss }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'timeoutLeft'"
|
|
class="text-xs-right"
|
|
>
|
|
{{ timeoutLeft(props.item) | hhmmss }}
|
|
</span>
|
|
<!-- rawData not supported -->
|
|
<span
|
|
v-if="col == 'customer' && $config.customer_views"
|
|
>
|
|
{{ props.item.customer }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'duplicateCount'"
|
|
>
|
|
{{ props.item.duplicateCount }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'repeat'"
|
|
>
|
|
<span
|
|
class="label"
|
|
:style="fontStyle"
|
|
>
|
|
{{ props.item.repeat | capitalize }}
|
|
</span>
|
|
</span>
|
|
<span
|
|
v-if="col == 'previousSeverity'"
|
|
>
|
|
<span
|
|
:class="['label', 'label-' + props.item.previousSeverity.toLowerCase()]"
|
|
:style="fontStyle"
|
|
>
|
|
{{ props.item.previousSeverity | capitalize }}
|
|
</span>
|
|
</span>
|
|
<!-- trendIndication not supported -->
|
|
<span
|
|
v-if="col == 'receiveTime'"
|
|
>
|
|
<date-time
|
|
:value="props.item.receiveTime"
|
|
format="mediumDate"
|
|
/>
|
|
</span>
|
|
<span
|
|
v-if="col == 'duration'"
|
|
class="text-xs-right"
|
|
>
|
|
{{ duration(props.item) | hhmmss }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'lastReceiveId'"
|
|
>
|
|
{{ props.item.lastReceiveId | shortId }}
|
|
</span>
|
|
<span
|
|
v-if="col == 'lastReceiveTime'"
|
|
>
|
|
<date-time
|
|
:value="props.item.lastReceiveTime"
|
|
format="mediumDate"
|
|
/>
|
|
</span>
|
|
<!-- only history supported is most recent note -->
|
|
<span
|
|
v-if="col == 'note'"
|
|
>
|
|
{{ lastNote(props.item) }}
|
|
</span>
|
|
</td>
|
|
<td
|
|
:class="['text-no-wrap', textColor(props.item.severity)]"
|
|
>
|
|
<div
|
|
class="action-buttons"
|
|
:style="{ 'background-color': severityColor(props.item.severity) }"
|
|
>
|
|
...
|
|
<v-btn
|
|
v-if="isAcked(props.item.status) || isClosed(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="takeAction(props.item.id, 'open')"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
refresh
|
|
</v-icon>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
v-if="!isWatched(props.item.tags)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="watchAlert(props.item.id)"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
visibility
|
|
</v-icon>
|
|
</v-btn>
|
|
<v-btn
|
|
v-if="isWatched(props.item.tags)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="unwatchAlert(props.item.id)"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
visibility_off
|
|
</v-icon>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
v-if="isOpen(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="ackAlert(props.item.id)"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
check
|
|
</v-icon>
|
|
</v-btn>
|
|
<v-btn
|
|
v-if="isAcked(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="takeAction(props.item.id, 'unack')"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
undo
|
|
</v-icon>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
v-if="isOpen(props.item.status) || isAcked(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="shelveAlert(props.item.id)"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
schedule
|
|
</v-icon>
|
|
</v-btn>
|
|
<v-btn
|
|
v-if="isShelved(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="takeAction(props.item.id, 'unshelve')"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
restore
|
|
</v-icon>
|
|
</v-btn>
|
|
|
|
<v-btn
|
|
v-if="!isClosed(props.item.status)"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="takeAction(props.item.id, 'close')"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
highlight_off
|
|
</v-icon>
|
|
</v-btn>
|
|
<v-btn
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="deleteAlert(props.item.id)"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
delete
|
|
</v-icon>
|
|
</v-btn>
|
|
<!-- <v-btn
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
@click.stop="clipboardCopy(JSON.stringify(props.item, null, 4))"
|
|
>
|
|
<v-icon
|
|
:size="fontSize"
|
|
>
|
|
content_copy
|
|
</v-icon>
|
|
</v-btn> -->
|
|
|
|
<v-menu
|
|
bottom
|
|
left
|
|
>
|
|
<v-btn
|
|
slot="activator"
|
|
flat
|
|
icon
|
|
small
|
|
class="btn--plain pa-0 ma-0"
|
|
>
|
|
<v-icon small>
|
|
more_vert
|
|
</v-icon>
|
|
</v-btn>
|
|
|
|
<v-list
|
|
subheader
|
|
>
|
|
<v-subheader>Actions</v-subheader>
|
|
<v-divider />
|
|
<v-list-tile
|
|
v-for="(action, i) in actions"
|
|
:key="i"
|
|
@click.stop="takeAction(props.item.id, action)"
|
|
>
|
|
<v-list-tile-title>{{ action | splitCaps }}</v-list-tile-title>
|
|
</v-list-tile>
|
|
</v-list>
|
|
</v-menu>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
<template slot="no-data">
|
|
<div class="text-xs-center">
|
|
<span v-if="isLoading">{{ $t('Loading') }}...</span>
|
|
<span v-if="!isLoading">{{ $t('NoDataAvailable') }}</span>
|
|
</div>
|
|
</template>
|
|
</v-data-table>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import debounce from 'lodash/debounce'
|
|
import get from 'lodash/get'
|
|
import DateTime from './lib/DateTime'
|
|
import moment from 'moment'
|
|
import i18n from '@/plugins/i18n'
|
|
|
|
export default {
|
|
components: {
|
|
DateTime
|
|
},
|
|
props: {
|
|
alerts: {
|
|
type: Array,
|
|
default: () => []
|
|
}
|
|
},
|
|
data: vm => ({
|
|
search: '',
|
|
headersMap: {
|
|
id: { text: i18n.t('AlertId'), value: 'id' },
|
|
resource: { text: i18n.t('Resource'), value: 'resource' },
|
|
event: { text: i18n.t('Event'), value: 'event' },
|
|
environment: { text: i18n.t('Environment'), value: 'environment' },
|
|
severity: { text: i18n.t('Severity'), value: 'severity' },
|
|
correlate: { text: i18n.t('Correlate'), value: 'correlate' },
|
|
status: { text: i18n.t('Status'), value: 'status' },
|
|
service: { text: i18n.t('Service'), value: 'service' },
|
|
group: { text: i18n.t('Group'), value: 'group' },
|
|
value: { text: i18n.t('Value'), value: 'value', class: 'value-header' },
|
|
text: { text: i18n.t('Description'), value: 'text', class: 'text-header' },
|
|
tags: { text: i18n.t('Tags'), value: 'tags' },
|
|
attributes: { text: i18n.t('Attribute'), value: 'attributes' },
|
|
origin: { text: i18n.t('Origin'), value: 'origin' },
|
|
type: { text: i18n.t('Type'), value: 'type' },
|
|
createTime: { text: i18n.t('CreateTime'), value: 'createTime' },
|
|
timeout: { text: i18n.t('Timeout'), value: 'timeout' },
|
|
timeoutLeft: { text: i18n.t('TimeoutLeft'), value: 'timeoutLeft' },
|
|
customer: { text: i18n.t('Customer'), value: 'customer' },
|
|
duplicateCount: { text: i18n.t('Dupl'), value: 'duplicateCount' },
|
|
repeat: { text: i18n.t('Repeat'), value: 'repeat' },
|
|
previousSeverity: { text: i18n.t('PrevSeverity'), value: 'previousSeverity' },
|
|
trendIndication: { text: i18n.t('TrendIndication'), value: 'trendIndication' },
|
|
receiveTime: { text: i18n.t('ReceiveTime'), value: 'receiveTime' },
|
|
duration: { text: i18n.t('Duration'), value: 'duration' },
|
|
lastReceiveId: { text: i18n.t('LastReceiveId'), value: 'lastReceiveId' },
|
|
lastReceiveTime: { text: i18n.t('LastReceiveTime'), value: 'lastReceiveTime' },
|
|
note: { text: i18n.t('LastNote'), value: 'note', sortable: false }
|
|
},
|
|
details: false,
|
|
selectedId: null,
|
|
multiselect: false,
|
|
timer: null
|
|
}),
|
|
computed: {
|
|
displayDensity() {
|
|
return (
|
|
this.$store.getters.getPreference('displayDensity') ||
|
|
this.$store.state.alerts.displayDensity
|
|
)
|
|
},
|
|
fontStyle() {
|
|
const font = this.$store.getters.getPreference('font')
|
|
return {
|
|
'font-family': font['font-family'],
|
|
'font-size': font['font-size'],
|
|
'font-weight': font['font-weight']
|
|
}
|
|
},
|
|
fontSize() {
|
|
return this.$store.getters.getPreference('font')['font-size']
|
|
},
|
|
columnWidths() {
|
|
return {
|
|
'--value-width': this.valueWidth() + 'px',
|
|
'--text-width': this.textWidth() + 'px'
|
|
}
|
|
},
|
|
isLoading() {
|
|
return this.$store.state.alerts.isLoading
|
|
},
|
|
isSearching() {
|
|
return this.$store.state.alerts.isSearching ? 'primary' : false
|
|
},
|
|
showNotesIcon() {
|
|
return this.$store.getters.getPreference('showNotesIcon')
|
|
},
|
|
rowsPerPage() {
|
|
return this.$store.getters.getPreference('rowsPerPage')
|
|
},
|
|
pagination: {
|
|
get() {
|
|
return this.$store.state.alerts.pagination
|
|
},
|
|
set(value) {
|
|
this.$store.dispatch('alerts/setPagination', value)
|
|
}
|
|
},
|
|
actions() {
|
|
return this.$config.actions
|
|
},
|
|
customHeaders() {
|
|
return this.$config.columns.map(c =>
|
|
this.headersMap[c] || { text: this.$options.filters.capitalize(c), value: 'attributes.' + c }
|
|
)
|
|
},
|
|
selectedItem() {
|
|
return this.alerts.filter(a => a.id == this.selectedId)[0]
|
|
},
|
|
selectableRows() {
|
|
return this.selected.length > 0
|
|
},
|
|
selected: {
|
|
get() {
|
|
return this.$store.state.alerts.selected
|
|
},
|
|
set(value) {
|
|
this.$store.dispatch('alerts/updateSelected', value)
|
|
}
|
|
},
|
|
ackTimeout() {
|
|
return this.$store.getters.getPreference('ackTimeout')
|
|
},
|
|
shelveTimeout() {
|
|
return this.$store.getters.getPreference('shelveTimeout')
|
|
},
|
|
username() {
|
|
return this.$store.getters['auth/getUsername']
|
|
}
|
|
},
|
|
watch: {
|
|
rowsPerPage(val) {
|
|
this.pagination = Object.assign({}, this.pagination, {rowsPerPage: val})
|
|
}
|
|
},
|
|
methods: {
|
|
duration(item) {
|
|
return moment.duration(moment().diff(moment(item.receiveTime)))
|
|
},
|
|
timeoutLeft(item) {
|
|
let ackedOrShelved = this.isShelved(item.status) || this.isAcked(item.status)
|
|
let lastModified = ackedOrShelved && item.updateTime ? item.updateTime : item.lastReceiveTime
|
|
let expireTime = moment(lastModified).add(item.timeout, 'seconds')
|
|
return expireTime.isAfter() ? expireTime.diff(moment(), 'seconds') : moment.duration()
|
|
},
|
|
lastNote(item) {
|
|
const note = item.history.filter(h => h.type == 'note' || h.type == 'dismiss').pop()
|
|
return note && note.type == 'note' ? note.text : ''
|
|
},
|
|
valueWidth() {
|
|
return this.$store.getters.getPreference('valueWidth')
|
|
},
|
|
textWidth() {
|
|
return this.$store.getters.getPreference('textWidth')
|
|
},
|
|
textColor(severity) {
|
|
if (this.severityColor(severity) === 'black' || this.severityColor(severity) === '#000000') {
|
|
return 'white--text'
|
|
}
|
|
return this.$store.getters.getConfig('colors').text
|
|
? `${this.$store.getters.getConfig('colors').text}--text`
|
|
: ''
|
|
},
|
|
severityColor(severity) {
|
|
return this.$store.getters.getConfig('colors').severity[severity] || 'white'
|
|
},
|
|
selectItem(item) {
|
|
if (!this.selected.length) {
|
|
this.$emit('set-alert', item)
|
|
}
|
|
},
|
|
isOpen(status) {
|
|
return status == 'open' || status == 'NORM' || status == 'UNACK' || status == 'RTNUN'
|
|
},
|
|
isWatched(tags) {
|
|
return tags ? tags.indexOf(`watch:${this.username}`) > -1 : false
|
|
},
|
|
isAcked(status) {
|
|
return status == 'ack' || status == 'ACKED'
|
|
},
|
|
isShelved(status) {
|
|
return status == 'shelved' || status == 'SHLVD'
|
|
},
|
|
isClosed(status) {
|
|
return status == 'closed'
|
|
},
|
|
takeAction: debounce(function(id, action) {
|
|
this.$store
|
|
.dispatch('alerts/takeAction', [id, action, ''])
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
ackAlert: debounce(function(id) {
|
|
this.$store
|
|
.dispatch('alerts/takeAction', [id, 'ack', '', this.ackTimeout])
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
shelveAlert: debounce(function(id) {
|
|
this.$store
|
|
.dispatch('alerts/takeAction', [id, 'shelve', '', this.shelveTimeout])
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
watchAlert: debounce(function(id) {
|
|
this.$store
|
|
.dispatch('alerts/watchAlert', id)
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
unwatchAlert: debounce(function(id) {
|
|
this.$store
|
|
.dispatch('alerts/unwatchAlert', id)
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
deleteAlert: debounce(function(id) {
|
|
confirm(i18n.t('ConfirmDelete')) &&
|
|
this.$store.dispatch('alerts/deleteAlert', id)
|
|
.then(() => this.$store.dispatch('alerts/getAlerts'))
|
|
}, 200, {leading: true, trailing: false}),
|
|
clipboardCopy(text) {
|
|
let textarea = document.createElement('textarea')
|
|
textarea.textContent = text
|
|
document.body.appendChild(textarea)
|
|
textarea.select()
|
|
document.execCommand('copy')
|
|
document.body.removeChild(textarea)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.alert-table .v-table th, td {
|
|
padding: 0px 5px !important;
|
|
}
|
|
|
|
.value-header {
|
|
width: var(--value-width);
|
|
min-width: var(--value-width);
|
|
}
|
|
|
|
.text-header {
|
|
width: var(--text-width);
|
|
min-width: var(--text-width);
|
|
}
|
|
|
|
.comfortable table.v-table tbody td, table.v-table tbody th {
|
|
height: 42px !important;
|
|
}
|
|
|
|
.compact table.v-table tbody td, table.v-table tbody th {
|
|
height: 34px !important;
|
|
}
|
|
|
|
.alert-table .v-table tbody td {
|
|
border-top: 1px solid rgb(221, 221, 221);
|
|
}
|
|
|
|
.fixed-table {
|
|
display: table;
|
|
table-layout: fixed;
|
|
width: 100%;
|
|
}
|
|
|
|
i.trend-arrow {
|
|
width: 24px !important;
|
|
}
|
|
|
|
div.select-box {
|
|
width: 24px !important;
|
|
}
|
|
|
|
.label {
|
|
font-weight: bold;
|
|
line-height: 14px;
|
|
color: #ffffff;
|
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
|
white-space: nowrap;
|
|
vertical-align: baseline;
|
|
background-color: #999999;
|
|
}
|
|
|
|
.label {
|
|
padding: 1px 4px 2px;
|
|
-webkit-border-radius: 3px;
|
|
-moz-border-radius: 3px;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.label-critical {
|
|
background-color: #b94a48;
|
|
}
|
|
|
|
.label-major {
|
|
background-color: #f89406;
|
|
}
|
|
|
|
.label-minor {
|
|
background-color: #ffd700;
|
|
}
|
|
|
|
.label-warning {
|
|
background-color: #3a87ad;
|
|
}
|
|
|
|
.label-normal,
|
|
.label-cleared,
|
|
.label-ok,
|
|
.label-informational {
|
|
background-color: #468847;
|
|
}
|
|
|
|
.label-inverse {
|
|
background-color: #333333;
|
|
}
|
|
|
|
.hover-lighten:hover {
|
|
filter: brightness(0.87);
|
|
}
|
|
|
|
.btn--plain {
|
|
height: auto;
|
|
width: auto;
|
|
margin: 0;
|
|
padding: 8px;
|
|
min-width: 0;
|
|
font-size: 24px;
|
|
}
|
|
.btn--plain {
|
|
padding: 0;
|
|
opacity: 0.6;
|
|
}
|
|
.btn--plain:before {
|
|
background-color: transparent !important;
|
|
transition: none !important;
|
|
}
|
|
.btn--plain:hover {
|
|
opacity: 1;
|
|
}
|
|
|
|
div.action-buttons {
|
|
position: absolute;
|
|
opacity: 0;
|
|
right: 0;
|
|
top: 0.5em;
|
|
height: 2em;
|
|
}
|
|
|
|
tr:hover div.action-buttons {
|
|
opacity: 1;
|
|
}
|
|
</style>
|