Skip to content

Commit

Permalink
wip: Upgrade to Quasar 2 / Vue 3 - mixins to xomponents - catalog act…
Browse files Browse the repository at this point in the history
…ivity(#393)
  • Loading branch information
claustres committed Jul 6, 2023
1 parent 6f39f0c commit 7cba5ea
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
108 changes: 108 additions & 0 deletions src/composables/composable.alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import _ from 'lodash'
import moment from 'moment'
import i18next from 'i18next'
import { ref, computed, watch, onBeforeMount, onBeforeUnmount } from 'vue'
import { utils as kCoreUtils } from '@kalisio/kdk/core.client'

export function useAlerts(options) {
// Functions
function formatAlertDateTime (date) {
return date.toLocaleString(kCoreUtils.getLocale(),
{ year: 'numeric', month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit' })
}
function getAlertDetailsAsHtml (alert) {
const isActive = _.get(alert, 'status.active')
const hasError = _.get(alert, 'status.error')
const checkedAt = new Date(_.get(alert, 'status.checkedAt'))
const triggeredAt = new Date(_.get(alert, 'status.triggeredAt'))
let html = getAlertLocationName(alert)
if (html) html += '</br>'
_.forOwn(alert.conditions, (value, key) => {
// Get corresponding variable
const variable = _.find(_.get(alert, 'layer.variables'), { name: key })
const label = i18n.t(variable.label) || variable.label
const unit = variable.units[0]
if (_.has(value, '$gte')) {
html += isActive
? `${label} ` + i18n.t('CatalogActivity.ALERT_GTE') + ` ${value.$gte} ${unit}</br>`
: `${label} ` + i18n.t('CatalogActivity.ALERT_LTE') + ` ${value.$gte} ${unit}</br>`
}
if (_.has(value, '$lte')) {
html += isActive
? `${label} ` + i18n.t('CatalogActivity.ALERT_LTE') + ` ${value.$lte} ${unit}</br>`
: `${label} ` + i18n.t('CatalogActivity.ALERT_GTE') + ` ${value.$lte} ${unit}</br>`
}
})
html += i18n.t('CatalogActivity.ALERT_CHECKED_AT') + ` ${formatAlertDateTime(checkedAt)}</br>`
if (isActive) {
// Order triggers by time to get nearest one easily, take care to unify weather/measure triggers
const triggers = _.sortBy(_.get(alert, 'status.triggers',
[trigger => moment.utc(trigger.time || trigger.forecastTime).valueOf()]))
const lastTrigger = _.last(triggers)
const firstTrigger = _.head(triggers)
// Check for forecast (future) or measure (past)
const lastTriggerAt = moment.utc(lastTrigger.time || lastTrigger.forecastTime)
const firstTriggerAt = moment.utc(firstTrigger.time || firstTrigger.forecastTime)
const now = moment.utc()
const nearestTrigger = (Math.abs(now.diff(firstTriggerAt)) < Math.abs(now.diff(lastTriggerAt)) ? firstTrigger : lastTrigger)
const nearestTriggerAt = new Date(nearestTrigger.time || nearestTrigger.forecastTime)
html += (nearestTrigger === lastTrigger ? i18n.t('CatalogActivity.ALERT_LAST') : i18n.t('CatalogActivity.ALERT_FIRST'))
html += i18n.t('CatalogActivity.ALERT_THRESHOLD_AT') + ` ${formatAlertDateTime(nearestTriggerAt)}</br>`
html += i18n.t('CatalogActivity.ALERT_TRIGGERED_AT') + ` ${formatAlertDateTime(triggeredAt)}</br>`
}
if (hasError) {
html += '</br><i class="la la-exclamation la-lg"></i><b>' +
i18n.t('errors.' + _.get(alert, 'status.error.data.translation.key')) + '</b></br>'
}
return html
}
function getAlertStatusAsHtml (alert) {
const isActive = _.get(alert, 'status.active')
const hasError = _.get(alert, 'status.error')
let html = ''
if (isActive) html += '<b>' + i18n.t('CatalogActivity.ALERT_ACTIVE') + '</b></br>'
else html += '<b>' + i18n.t('CatalogActivity.ALERT_INACTIVE') + '</b></br>'
// Layer name can be a translation key
html += (i18n.t(`${alert.layer.name}`) ? i18n.t(`${alert.layer.name}`) : `${alert.layer.name}`)
if (_.has(alert, 'feature')) {
// Try with default feature labels
let featureLabel = _.get(alert, 'properties.name', _.get(alert, 'properties.NAME'))
// Override if provided by layer
if (_.has(alert, 'layer.featureLabel')) featureLabel = _.get(alert, 'properties.' + _.get(alert, 'layer.featureLabel'))
if (featureLabel) html += ` - ${featureLabel}`
}
if (hasError) {
html += '</br><i class="la la-exclamation la-lg"></i><b>' +
i18n.t('errors.' + _.get(alert, 'status.error.data.translation.key')) + '</b></br>'
}
return html
}
function getAlertLocationName (alert) {
let name = _.get(alert, 'layer.name', '')
if (_.has(alert, 'feature')) {
// Try with default feature labels
name = _.get(alert, 'properties.name', _.get(alert, 'properties.NAME'))
// Override if provided by layer
if (_.has(alert, 'layer.featureLabel')) name = _.get(alert, 'properties.' + _.get(alert, 'layer.featureLabel'))
}
// Can be a translation key
return (i18n.t(name) ? i18n.t(name) : name)
}
function loadAlertLayer (alert) {
if (!_.has(alert, 'layer._id')) return null
let i18n = _.get(alert, 'layer.i18n')
// Process i18n
if (i18n) {
const locale = kCoreUtils.getAppLocale()
i18n = _.get(i18n, locale)
if (i18n) i18next.addResourceBundle(locale, 'kdk', i18n, true, true)
}
}

return {
getAlertDetailsAsHtml,
getAlertStatusAsHtml,
loadAlertLayer
}
}

106 changes: 106 additions & 0 deletions src/composables/composable.plan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import _ from 'lodash'
import { ref, computed, watch, onBeforeMount, onBeforeUnmount } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { api } from '@kalisio/kdk/core.client'

export function usePlan(options) {

// Data
const route = useRoute()
const planId = ref(null)
const plan = ref(null)
const objectiveFilters = ref([])
let planService = ''

// Functions
function hasPlan () {
return planId.value
}
function hasPlanLocation () {
return _.has(plan.value, 'location.latitude') && _.has(plan.value, 'location.longitude')
}
function hasPlanObjectives () {
return (_.get(plan.value, 'objectives', []).length > 0)
}
async function loadPlan (query = {}) {
if (!planId.value) {
plan.value = null
} else {
plan.value = await api.getService(planService, options.contextId).get(planId.value, { query })
}
}
function onPlanUpdated (updatedPlan) {
if (plan.value && (updatedPlan._id === plan.value._id)) {
plan.value = updatedPlan
}
}
function onPlanRemoved (removedPlan) {
if (plan.value && (removedPlan._id === plan.value._id)) {
plan.value = null
planId.value = null
}
}
function getPlanQuery () {
const query = {}
if (!_.isEmpty(planId.value)) {
Object.assign(query, {
plan: planId.value
})
}
return query
}
function refreshPlanId () {
const id = _.get(route, 'query.plan', null)
if (planId.value !== id) planId.value = id
}
function getPlanObjectiveQuery () {
if (_.isEmpty(objectiveFilters.value)) return {}
else return { objective: { $in: objectiveFilters.value } }
}
async function countEvents (query = {}) {
const eventsService = api.getService('archived-events', options.contextId)
const response = await eventsService.find({ query: Object.assign(query, getPlanQuery()), $limit: 0 })
return response.total
}
async function countClosedEvents (query = {}) {
const eventsService = api.getService('archived-events', options.contextId)
const response = await eventsService.find({ query: Object.assign(query, { deletedAt: { $exists: true } }, getPlanQuery()), $limit: 0 })
return response.total
}

// Lifecycle hooks
watch(() => route.to, refreshPlanId)

onBeforeMount(() => {
// Jump to archive whenever required
planService = (_.get(route, 'name').includes('archived') ? 'archived-plans' : 'plans')
refreshPlanId()
const plansService = api.getService(planService, options.contextId)
// Keep track of changes once plan is loaded
plansService.on('patched', onPlanUpdated)
plansService.on('updated', onPlanUpdated)
plansService.on('removed', onPlanRemoved)
})

// Cleanup for appendItems
onBeforeUnmount(() => {
const plansService = api.getService(planService, options.contextId)
plansService.off('patched', onPlanUpdated)
plansService.off('updated', onPlanUpdated)
plansService.off('removed', onPlanRemoved)
})

return {
plan,
planId,
objectiveFilters,
hasPlan,
hasPlanLocation,
hasPlanObjectives,
loadPlan,
getPlanQuery,
getPlanObjectiveQuery,
countEvents,
countClosedEvents
}
}
2 changes: 2 additions & 0 deletions src/composables/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './composable.plan.js'
export * from './composable.alerts.js'

0 comments on commit 7cba5ea

Please sign in to comment.