import '../viewparts/monitoring-summary.js'
import '../viewparts/pending-q-monitor.js'
import '../viewparts/scenarios-monitor.js'
import '../viewparts/connections-monitor.js'
import gql from 'graphql-tag'
import { css, html } from 'lit'
import { customElement, property, state } from 'lit/decorators.js'
import { client, subscribe } from '@operato/graphql'
import { i18next, localize } from '@operato/i18n'
import { PageView, InheritedValueType } from '@operato/shell'
import { ScrollbarStyles } from '@operato/styles'
function IS_SCENARIO_RUNNING(state) {
return state && state !== 'UNLOADED'
}
function toColor(string) {
var hash = 0
if (string.length === 0) return hash
for (var i = 0; i < string.length; i++) {
hash = string.charCodeAt(i) + ((hash << 5) - hash)
hash = hash & hash
}
var color = '#'
for (var i = 0; i < 3; i++) {
var value = (hash >> (i * 8)) & 255
color += ('00' + value.toString(16)).substr(-2)
}
return color
}
@customElement('integration-monitor')
export class IntegrationMonitor extends localize(i18next)(PageView) {
static ScenarioInstanceStatus = ['READY', 'STARTED', 'STOPPED', 'HALTED']
static styles = [
ScrollbarStyles,
css`
:host {
display: flex;
flex-direction: column;
overflow: hidden;
background-color: var(--md-sys-color-background);
padding: var(--spacing-large);
}
integration-summary {
margin-bottom: var(--spacing-large);
}
content {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
}
connections-monitor {
width: 180px;
}
scenarios-monitor {
flex: 1;
margin: 0 var(--spacing-large) 0 0;
}
@media screen and (max-width: 480px) {
:host {
padding: var(--spacing-medium);
}
integration-summary {
margin-bottom: var(--spacing-medium);
}
content {
display: block;
overflow: auto;
}
scenarios-monitor {
min-height: 350px;
margin: 0 0 var(--spacing-medium) 0;
}
connections-monitor {
width: initial;
}
}
`
]
@property({ type: Array }) scenarios: any
@property({ type: Array }) pendings: any
@property({ type: Array }) connections: any
@property({ type: Object }) colorIndex: any
scenarioInstanceStateSubscription: any
scenarioQueueStateSubscription: any
connectionStateSubscription: any
get context() {
return {
title: i18next.t('text.integration monitor'),
help: 'integration/ui/integration-monitor'
}
}
render() {
return html`
`
}
async pageUpdated(changes) {
if ('active' in changes) {
if (this.active) {
await this.fetchScenarios()
await this.fetchConnections()
await this.startSubscribe()
} else {
await this.stopSubscribe()
}
}
}
async fetchScenarios() {
const response = await client.query({
query: gql`
query ($inherited: InheritedValueType) {
responses: scenarios(inherited: $inherited) {
items {
id
name
description
active
state
schedule
timezone
instances {
instanceName
scenarioName
state
progress {
rate
steps
step
rounds
}
variables
data
message
}
updater {
id
name
}
updatedAt
domain {
id
name
}
}
total
}
}
`,
variables: {
inherited: InheritedValueType.Include
}
})
var colorIndex = {}
this.scenarios = (response.data.responses.items || []).map(scenario => {
var color = toColor(scenario.id)
colorIndex[scenario.id] = color
return {
...scenario,
color
}
})
this.colorIndex = colorIndex
}
async fetchConnections() {
const response = await client.query({
query: gql`
query ($inherited: InheritedValueType) {
responses: connections(inherited: $inherited) {
items {
id
name
description
type
state
domain {
id
name
}
}
total
}
}
`,
variables: {
inherited: InheritedValueType.Include
}
})
this.connections = response.data.responses.items || []
// .map(connection => {
// var color = toColor(scenario.id)
// colorIndex[scenario.id] = color
// return {
// ...scenario,
// color
// }
// })
// this.colorIndex = colorIndex
}
async startSubscribe() {
if (this.scenarioInstanceStateSubscription) {
return
}
this.scenarioInstanceStateSubscription = await subscribe(
{
query: gql`
subscription {
scenarioInstanceState {
instanceName
scenarioName
state
progress {
rate
steps
step
rounds
}
}
}
`
},
{
next: async ({ data }) => {
if (data) {
var { scenarioName, instanceName, state } = data.scenarioInstanceState
this.scenarios = this.scenarios || []
var scenario = this.scenarios.find(scenario => scenario.name === scenarioName)
if (scenario) {
var idx = scenario.instances.findIndex(instance => instance.instanceName === instanceName)
if (idx == -1) {
if (IS_SCENARIO_RUNNING(state)) {
scenario.instances.push(data.scenarioInstanceState)
}
} else {
if (!IS_SCENARIO_RUNNING(state)) {
scenario.instances.splice(idx, 1)
} else {
scenario.instances.splice(idx, 1, data.scenarioInstanceState)
}
}
} else {
this.scenarios = []
await this.stopSubscribe()
await this.fetchScenarios()
await this.startSubscribe()
return
}
/* change object intentionally to force to refresh scenario */
this.scenarios.splice(this.scenarios.indexOf(scenario), 1, { ...scenario })
this.scenarios = [...this.scenarios]
}
},
start: subscription => {
console.log(subscription)
},
error: error => {
console.log(error)
},
complete: () => {
console.log('complete')
}
}
)
this.scenarioQueueStateSubscription = await subscribe(
{
query: gql`
subscription {
scenarioQueueState {
queue {
stuff
due
priority
tag
}
}
}
`
},
{
next: ({ data }) => {
if (data) {
this.pendings = data.scenarioQueueState.queue
}
}
}
)
this.connectionStateSubscription = await subscribe(
{
query: gql`
subscription {
connectionState {
id
name
description
type
state
domain {
id
name
}
}
}
`
},
{
next: async ({ data }) => {
if (data) {
var state = data.connectionState
this.connections = this.connections || []
var idx = this.connections.findIndex(
connection => connection.id === state.id && connection.domain.id === state.domain.id
)
if (idx !== -1) {
this.connections[idx] = data.connectionState
this.connections = [...this.connections]
} else {
this.connections = [...this.connections, data.connectionState]
}
}
}
}
)
}
async stopSubscribe() {
await this.scenarioInstanceStateSubscription?.unsubscribe()
await this.scenarioQueueStateSubscription?.unsubscribe()
await this.connectionStateSubscription?.unsubscribe()
delete this.scenarioInstanceStateSubscription
delete this.scenarioQueueStateSubscription
delete this.connectionStateSubscription
}
}