/*
Copyright (C) 2017 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
// @flow
import moment from 'moment'
import { servicesUrl } from '../constants'
import Api from '../utils/ApiCaller'
import type { NotificationItemData, NotificationItem } from '../types/NotificationItem'
class NotificationStorage {
static storeName: string = 'seenNotifications'
static loadSeen(): ?NotificationItemData[] {
let storage: ?string = localStorage.getItem(this.storeName)
if (!storage) {
return null
}
let notificationItems: NotificationItem[] = JSON.parse(storage)
let notificationItem: ?NotificationItem = notificationItems.find(n => n.projectId === Api.projectId)
if (!notificationItem) {
return null
}
return notificationItem.items
}
static saveSeen(items: NotificationItemData[]) {
let currentStorage: ?string = localStorage.getItem(this.storeName)
let currentItems: NotificationItem[] = []
if (currentStorage) {
currentItems = (JSON.parse(currentStorage): NotificationItem[])
currentItems = currentItems.filter(i => i.projectId !== Api.projectId)
}
let newItem: NotificationItem = {
projectId: Api.projectId,
items,
}
localStorage.setItem(this.storeName, JSON.stringify([
...currentItems,
newItem,
]))
}
static clean(notificationItems: NotificationItemData[]) {
let storageData = this.loadSeen()
if (!storageData) {
return
}
storageData = storageData.filter(i => notificationItems.find(j => i.id === j.id))
this.saveSeen(storageData)
}
}
class DataUtils {
static getMainInfo(item: any) {
if (item.type === 'migration') {
return item
}
if (item.executions && item.executions.length) {
let availableExecutions = item.executions.filter(i => !i.deleted_at)
if (availableExecutions.length) {
availableExecutions.sort((a, b) => b.number - a.number)
return availableExecutions[0]
}
}
return item
}
static getUpdatedAt(item: any) {
let info = this.getMainInfo(item)
return info.updated_at || info.created_at
}
static getItemDescription(item: any) {
let type = item.type === 'replica' ? 'Replica' : 'Migration'
let mainInfo = this.getMainInfo(item)
let description = ''
let id = `${mainInfo.id.substr(0, 7)}...`
switch (mainInfo.status) {
case 'COMPLETED':
description = `${type} execution ${id} completed successfully`
break
case 'ERROR':
description = `${type} execution ${id} failed`
break
case 'RUNNING':
description = `${type} execution ${id} running`
break
default:
break
}
return description
}
}
class NotificationSource {
async loadData(): Promise {
let [migrationsResponse, replicasResponse] = await Promise.all([
Api.send({ url: `${servicesUrl.coriolis}/${Api.projectId}/migrations`, skipLog: true, quietError: true }),
Api.send({ url: `${servicesUrl.coriolis}/${Api.projectId}/replicas/detail`, skipLog: true, quietError: true }),
])
let migrations = migrationsResponse.data.migrations
let replicas = replicasResponse.data.replicas
let apiData = [...migrations, ...replicas]
apiData.sort((a, b) => moment(DataUtils.getUpdatedAt(b)).diff(DataUtils.getUpdatedAt(a)))
let notificationItems: NotificationItemData[] = apiData.map(item => {
let mainInfo = DataUtils.getMainInfo(item)
let newItem: NotificationItemData = {
id: item.id,
status: mainInfo.status,
type: item.type,
name: item.instances[0],
updatedAt: mainInfo.updated_at,
description: DataUtils.getItemDescription(item),
}
return newItem
}).filter(item => item.status).filter((item, i) => i < 10)
let storageData = NotificationStorage.loadSeen()
if (!storageData) {
NotificationStorage.saveSeen(notificationItems)
storageData = NotificationStorage.loadSeen() || []
}
notificationItems.forEach(item => {
item.unseen = true
// $FlowIgnore
storageData.forEach(storageItem => {
if (storageItem.id === item.id && storageItem.status === item.status && storageItem.updatedAt === item.updatedAt) {
item.unseen = false
}
})
})
NotificationStorage.clean(notificationItems)
return notificationItems
}
saveSeen(notificationItems: NotificationItemData[]) {
NotificationStorage.saveSeen(notificationItems)
}
}
export default new NotificationSource()