fixed global messages for services

pull/773/merge
hunterlong 2020-08-12 21:45:17 -07:00
parent df6ffe8884
commit fa09889e23
6 changed files with 223 additions and 201 deletions

View File

@ -35,13 +35,6 @@ jobs:
echo ::set-env name=VERSION::$(cat version.txt) echo ::set-env name=VERSION::$(cat version.txt)
shell: bash shell: bash
- name: Font Awesome authentication
env:
FONTAWESOME_TOKEN: ${{ secrets.FONTAWESOME_TOKEN }}
run: |
npm config set "@fortawesome:registry" https://npm.fontawesome.com/
npm config set "//npm.fontawesome.com/:_authToken" $FONTAWESOME_TOKEN
- name: Install Global Dependencies - name: Install Global Dependencies
run: npm install -g yarn sass cross-env run: npm install -g yarn sass cross-env
@ -69,7 +62,7 @@ jobs:
- name: Upload Assets to S3 - name: Upload Assets to S3
run: | run: |
tar -czvf source.tar.gz source/ tar -czvf source.tar.gz source/
aws s3 cp source.tar.gz s3://assets.statping.com/ aws s3 cp source.tar.gz s3://assets.statping.com/${{ env.GITHUB_SHA }}
rm -rf source.tar.gz rm -rf source.tar.gz
test: test:
@ -124,6 +117,7 @@ jobs:
- name: Install Statping - name: Install Statping
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ env.GITHUB_SHA }}
run: | run: |
make build certs make build certs
chmod +x statping chmod +x statping
@ -135,7 +129,7 @@ jobs:
gotestsum --no-summary=skipped --format dots -- -covermode=count -coverprofile=coverage.out -p=1 ./... gotestsum --no-summary=skipped --format dots -- -covermode=count -coverprofile=coverage.out -p=1 ./...
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ github.sha }} COMMIT: ${{ env.GITHUB_SHA }}
DB_CONN: sqlite3 DB_CONN: sqlite3
STATPING_DIR: ${{ github.workspace }} STATPING_DIR: ${{ github.workspace }}
API_SECRET: demopassword123 API_SECRET: demopassword123
@ -196,6 +190,7 @@ jobs:
- name: Install Statping - name: Install Statping
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ env.GITHUB_SHA }}
run: | run: |
make build make build
chmod +x statping chmod +x statping
@ -251,6 +246,7 @@ jobs:
- name: Install Statping - name: Install Statping
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ env.GITHUB_SHA }}
MJML_APP: ${{ secrets.MJML_APP }} MJML_APP: ${{ secrets.MJML_APP }}
MJML_PRIVATE: ${{ secrets.MJML_PRIVATE }} MJML_PRIVATE: ${{ secrets.MJML_PRIVATE }}
run: | run: |
@ -309,7 +305,7 @@ jobs:
- name: Install Statping - name: Install Statping
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ github.sha }} COMMIT: ${{ env.GITHUB_SHA }}
run: | run: |
make build make build
chmod +x statping chmod +x statping
@ -382,7 +378,7 @@ jobs:
- name: Build Binaries - name: Build Binaries
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ github.sha }} COMMIT: ${{ env.GITHUB_SHA }}
MJML_APP: ${{ secrets.MJML_APP }} MJML_APP: ${{ secrets.MJML_APP }}
MJML_PRIVATE: ${{ secrets.MJML_PRIVATE }} MJML_PRIVATE: ${{ secrets.MJML_PRIVATE }}
run: make build-folders build-linux build-linux-arm build-darwin build-win compress-folders run: make build-folders build-linux build-linux-arm build-darwin build-win compress-folders
@ -460,11 +456,11 @@ jobs:
- name: Docker Build :base - name: Docker Build :base
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ github.sha }} COMMIT: ${{ env.GITHUB_SHA }}
run: make buildx-base run: make buildx-base
- name: Docker Build :dev - name: Docker Build :dev
env: env:
VERSION: ${{ env.VERSION }} VERSION: ${{ env.VERSION }}
COMMIT: ${{ github.sha }} COMMIT: ${{ env.GITHUB_SHA }}
run: make buildx-dev run: make buildx-dev

View File

@ -25,6 +25,15 @@
</div> </div>
</div> </div>
<div v-for="message in messagesInRange" class="bg-light shadow-sm p-3 pr-4 pl-4 col-12 mb-4">
<font-awesome-icon icon="calendar" class="mr-3" size="1x"/> {{message.description}}
<span class="d-block small text-muted mt-3">
Starts at <strong>{{niceDate(message.start_on)}}</strong> till <strong>{{niceDate(message.end_on)}}</strong>
({{dur(parseISO(message.start_on), parseISO(message.end_on))}})
</span>
</div>
<div v-for="(service, index) in services" class="service_block" v-bind:key="index"> <div v-for="(service, index) in services" class="service_block" v-bind:key="index">
<ServiceInfo :service=service /> <ServiceInfo :service=service />
</div> </div>
@ -32,6 +41,10 @@
</template> </template>
<script> <script>
import isAfter from "date-fns/isAfter";
import parseISO from "date-fns/parseISO";
import isBefore from "date-fns/isBefore";
const ServiceInfo = () => import(/* webpackChunkName: "dashboard" */ '@/components/Dashboard/ServiceInfo') const ServiceInfo = () => import(/* webpackChunkName: "dashboard" */ '@/components/Dashboard/ServiceInfo')
export default { export default {
@ -45,6 +58,9 @@
} }
}, },
computed: { computed: {
messagesInRange() {
return this.$store.getters.globalMessages.filter(m => this.isAfter(this.now(), m.start_on) && this.isBefore(this.now(), m.end_on))
},
services() { services() {
return this.$store.getters.services return this.$store.getters.services
} }

View File

@ -9,7 +9,7 @@
<span class="d-block text-dim float-right small mt-3 mb-1">Failure #{{failure.id}}</span> <span class="d-block text-dim float-right small mt-3 mb-1">Failure #{{failure.id}}</span>
</code> </code>
</div> </div>
<div v-if="loaded" v-for="message in messages" class="bg-light shadow-sm p-3 pr-4 pl-4 col-12 mt-3"> <div v-if="loaded" v-for="message in $store.getters.serviceMessages(service.id)" class="bg-light shadow-sm p-3 pr-4 pl-4 col-12 mt-3">
<font-awesome-icon icon="calendar" class="mr-3" size="1x"/> {{message.description}} <font-awesome-icon icon="calendar" class="mr-3" size="1x"/> {{message.description}}
<span class="d-block small text-muted mt-3"> <span class="d-block small text-muted mt-3">
Starts at <strong>{{niceDate(message.start_on)}}</strong> till <strong>{{niceDate(message.end_on)}}</strong> Starts at <strong>{{niceDate(message.start_on)}}</strong> till <strong>{{niceDate(message.end_on)}}</strong>
@ -44,7 +44,6 @@ name: "ServiceEvents",
}, },
data() { data() {
return { return {
messages: null,
incidents: null, incidents: null,
failure: null, failure: null,
loaded: false, loaded: false,
@ -53,6 +52,11 @@ name: "ServiceEvents",
mounted() { mounted() {
this.load() this.load()
}, },
computed: {
messages() {
return this.$store.getters.serviceMessages(this.service.id)
}
},
methods: { methods: {
async load() { async load() {
this.loaded = false this.loaded = false
@ -64,7 +68,7 @@ name: "ServiceEvents",
this.loaded = true this.loaded = true
}, },
async getMessages() { async getMessages() {
this.messages = await Api.messages() // this.messages = this.$store.getters.serviceMessages(this.service.id)
}, },
async getFailure() { async getFailure() {
const f = await Api.service_failures(this.service.id, null, null, 1) const f = await Api.service_failures(this.service.id, null, null, 1)
@ -76,7 +80,3 @@ name: "ServiceEvents",
} }
} }
</script> </script>
<style scoped>
</style>

View File

@ -1,9 +1,10 @@
import Vue from "vue"; import Vue from "vue";
const { startOfToday, startOfMonth, lastDayOfMonth, subSeconds, getUnixTime, fromUnixTime, differenceInSeconds, formatDistance, addMonths, isWithinInterval } = require('date-fns') const { startOfToday, startOfMonth, lastDayOfMonth, subSeconds, getUnixTime, fromUnixTime, differenceInSeconds, formatDistance, addMonths, addSeconds, isWithinInterval } = require('date-fns')
import formatDistanceToNow from 'date-fns/formatDistanceToNow' import formatDistanceToNow from 'date-fns/formatDistanceToNow'
import format from 'date-fns/format' import format from 'date-fns/format'
import parseISO from 'date-fns/parseISO' import parseISO from 'date-fns/parseISO'
import addSeconds from 'date-fns/addSeconds' import isBefore from 'date-fns/isBefore'
import isAfter from 'date-fns/isAfter'
export default Vue.mixin({ export default Vue.mixin({
methods: { methods: {
@ -19,9 +20,9 @@ export default Vue.mixin({
startToday() { startToday() {
return startOfToday() return startOfToday()
}, },
secondsHumanize (val) { secondsHumanize(val) {
return `${val} ${this.$t('second', val)}` return `${val} ${this.$t('second', val)}`
}, },
utc(val) { utc(val) {
return new Date.UTC(val) return new Date.UTC(val)
}, },
@ -29,23 +30,29 @@ export default Vue.mixin({
return formatDistanceToNow(parseISO(t1)) return formatDistanceToNow(parseISO(t1))
}, },
daysInMonth(t1) { daysInMonth(t1) {
return lastDayOfMonth(t1) return lastDayOfMonth(t1)
}, },
nowSubtract(seconds) { nowSubtract(seconds) {
return subSeconds(new Date(), seconds) return subSeconds(new Date(), seconds)
}, },
isAfter(date, compare) {
return isAfter(date, parseISO(compare))
},
isBefore(date, compare) {
return isBefore(date, parseISO(compare))
},
dur(t1, t2) { dur(t1, t2) {
return formatDistance(t1, t2) return formatDistance(t1, t2)
}, },
format(val, type="EEEE, MMM do h:mma") { format(val, type = "EEEE, MMM do h:mma") {
return format(val, type) return format(val, type)
}, },
niceDate(val) { niceDate(val) {
return format(parseISO(val), "EEEE, MMM do h:mma") return format(parseISO(val), "EEEE, MMM do h:mma")
}, },
parseISO(v) { parseISO(v) {
return parseISO(v) return parseISO(v)
}, },
isZero(val) { isZero(val) {
return getUnixTime(parseISO(val)) <= 0 return getUnixTime(parseISO(val)) <= 0
}, },
@ -84,14 +91,14 @@ export default Vue.mixin({
}, },
copy(txt) { copy(txt) {
this.$copyText(txt).then(function (e) { this.$copyText(txt).then(function (e) {
alert('Copied: \n'+txt) alert('Copied: \n' + txt)
}); });
}, },
serviceLink(service) { serviceLink(service) {
if (service.permalink) { if (service.permalink) {
service = this.$store.getters.serviceByPermalink(service.permalink) service = this.$store.getters.serviceByPermalink(service.permalink)
} }
if (service===undefined || this.isEmptyObject(service)) { if (service === undefined || this.isEmptyObject(service)) {
return `/service/0` return `/service/0`
} }
let link = service.permalink ? service.permalink : service.id let link = service.permalink ? service.permalink : service.id
@ -147,7 +154,7 @@ export default Vue.mixin({
}) })
return newSet return newSet
}, },
convertToChartData(data = [], multiplier=1, asInt=false) { convertToChartData(data = [], multiplier = 1, asInt = false) {
if (!data) { if (!data) {
return {data: []} return {data: []}
} }
@ -166,9 +173,9 @@ export default Vue.mixin({
}, },
humanTime(val) { humanTime(val) {
if (val >= 1000) { if (val >= 1000) {
return Math.round(val / 1000) + " ms" return Math.round(val / 1000) + " ms"
} }
return val + " μs" return val + " μs"
}, },
firstDayOfMonth(date) { firstDayOfMonth(date) {
return startOfMonth(date) return startOfMonth(date)
@ -178,6 +185,9 @@ export default Vue.mixin({
}, },
addMonths(date, amount) { addMonths(date, amount) {
return addMonths(date, amount) return addMonths(date, amount)
},
addSeconds(date, amount) {
return addSeconds(date, amount)
} }
} }
}); });

View File

@ -203,9 +203,9 @@ router.beforeEach((to, from, next) => {
const nearestWithTitle = to.matched.slice().reverse().find(r => r.meta && r.meta.title); const nearestWithTitle = to.matched.slice().reverse().find(r => r.meta && r.meta.title);
const nearestWithMeta = to.matched.slice().reverse().find(r => r.meta && r.meta.metaTags); const nearestWithMeta = to.matched.slice().reverse().find(r => r.meta && r.meta.metaTags);
const previousNearestWithMeta = from.matched.slice().reverse().find(r => r.meta && r.meta.metaTags); const previousNearestWithMeta = from.matched.slice().reverse().find(r => r.meta && r.meta.metaTags);
if(nearestWithTitle) document.title = nearestWithTitle.meta.title; if (nearestWithTitle) document.title = nearestWithTitle.meta.title;
Array.from(document.querySelectorAll('[data-vue-router-controlled]')).map(el => el.parentNode.removeChild(el)); Array.from(document.querySelectorAll('[data-vue-router-controlled]')).map(el => el.parentNode.removeChild(el));
if(!nearestWithMeta) return next(); if (!nearestWithMeta) return next();
nearestWithMeta.meta.metaTags.map(tagDef => { nearestWithMeta.meta.metaTags.map(tagDef => {
const tag = document.createElement('meta'); const tag = document.createElement('meta');
Object.keys(tagDef).forEach(key => { Object.keys(tagDef).forEach(key => {

View File

@ -16,173 +16,173 @@ export const GET_NOTIFIERS = 'GET_NOTIFIERS'
export const GET_USERS = 'GET_USERS' export const GET_USERS = 'GET_USERS'
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {
hasAllData: false, hasAllData: false,
hasPublicData: false, hasPublicData: false,
core: {}, core: {},
oauth: {}, oauth: {},
token: null, token: null,
services: [], services: [],
service: null, service: null,
groups: [], groups: [],
messages: [], messages: [],
users: [], users: [],
notifiers: [], notifiers: [],
checkins: [], checkins: [],
admin: false, admin: false,
user: false, user: false,
loggedIn: false loggedIn: false
}, },
getters: { getters: {
hasAllData: state => state.hasAllData, hasAllData: state => state.hasAllData,
hasPublicData: state => state.hasPublicData, hasPublicData: state => state.hasPublicData,
core: state => state.core, core: state => state.core,
oauth: state => state.oauth, oauth: state => state.oauth,
token: state => state.token, token: state => state.token,
services: state => state.services, services: state => state.services,
service: state => state.service, service: state => state.service,
groups: state => state.groups, groups: state => state.groups,
messages: state => state.messages, messages: state => state.messages,
incidents: state => state.incidents, incidents: state => state.incidents,
users: state => state.users, users: state => state.users,
notifiers: state => state.notifiers, notifiers: state => state.notifiers,
checkins: state => state.checkins, checkins: state => state.checkins,
loggedIn: state => state.loggedIn, loggedIn: state => state.loggedIn,
isAdmin: state => state.admin, isAdmin: state => state.admin,
isUser: state => state.user, isUser: state => state.user,
servicesInOrder: state => state.services.sort((a, b) => a.order_id - b.order_id), globalMessages: state => state.messages.filter(s => !s.service || s.service === 0),
servicesNoGroup: state => state.services.filter(g => g.group_id === 0).sort((a, b) => a.order_id - b.order_id), servicesInOrder: state => state.services.sort((a, b) => a.order_id - b.order_id),
groupsInOrder: state => state.groups.sort((a, b) => a.order_id - b.order_id), servicesNoGroup: state => state.services.filter(g => g.group_id === 0).sort((a, b) => a.order_id - b.order_id),
groupsClean: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id), groupsInOrder: state => state.groups.sort((a, b) => a.order_id - b.order_id),
groupsCleanInOrder: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id).sort((a, b) => a.order_id - b.order_id), groupsClean: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id),
groupsCleanInOrder: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id).sort((a, b) => a.order_id - b.order_id),
serviceCheckins: (state) => (id) => { serviceCheckins: (state) => (id) => {
return state.checkins.filter(c => c.service_id === id) return state.checkins.filter(c => c.service_id === id)
},
serviceByAll: (state) => (element) => {
if (element % 1 === 0) {
return state.services.find(s => s.id === element)
} else {
return state.services.find(s => s.permalink === element)
}
},
serviceById: (state) => (id) => {
return state.services.find(s => s.id === id)
},
serviceByPermalink: (state) => (permalink) => {
return state.services.find(s => s.permalink === permalink)
},
servicesInGroup: (state) => (id) => {
return state.services.filter(s => s.group_id === id).sort((a, b) => a.order_id - b.order_id)
},
serviceMessages: (state) => (id) => {
return state.messages.filter(s => s.service === id)
},
onlineServices: (state) => (online) => {
return state.services.filter(s => s.online === online)
},
groupById: (state) => (id) => {
return state.groups.find(g => g.id === id)
},
cleanGroups: (state) => () => {
return state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id)
},
userById: (state) => (id) => {
return state.users.find(u => u.id === id)
},
messageById: (state) => (id) => {
return state.messages.find(m => m.id === id)
},
}, },
mutations: { serviceByAll: (state) => (element) => {
setHasAllData (state, bool) { if (element % 1 === 0) {
state.hasAllData = bool return state.services.find(s => s.id === element)
}, } else {
setHasPublicData (state, bool) { return state.services.find(s => s.permalink === element)
state.hasPublicData = bool }
},
setCore (state, core) {
state.core = core
},
setToken (state, token) {
state.token = token
},
setService (state, service) {
state.service = service
},
setServices (state, services) {
state.services = services
},
setCheckins (state, checkins) {
state.checkins = checkins
},
setGroups (state, groups) {
state.groups = groups
},
setMessages (state, messages) {
state.messages = messages
},
setUsers (state, users) {
state.users = users
},
setNotifiers (state, notifiers) {
state.notifiers = notifiers
},
setAdmin (state, admin) {
state.admin = admin
},
setLoggedIn (state, loggedIn) {
state.loggedIn = loggedIn
},
setUser (state, user) {
state.user = user
},
setOAuth (state, oauth) {
state.oauth = oauth
},
}, },
actions: { serviceById: (state) => (id) => {
async getAllServices(context) { return state.services.find(s => s.id === id)
const services = await Api.services() },
context.commit("setServices", services); serviceByPermalink: (state) => (permalink) => {
}, return state.services.find(s => s.permalink === permalink)
async loadCore(context) { },
const core = await Api.core() servicesInGroup: (state) => (id) => {
const token = await Api.token() return state.services.filter(s => s.group_id === id).sort((a, b) => a.order_id - b.order_id)
context.commit("setCore", core); },
context.commit('setAdmin', token) serviceMessages: (state) => (id) => {
context.commit('setCore', core) return state.messages.filter(s => s.service === id)
context.commit('setUser', token!==undefined) },
}, onlineServices: (state) => (online) => {
async loadRequired(context) { return state.services.filter(s => s.online === online)
const groups = await Api.groups() },
context.commit("setGroups", groups); groupById: (state) => (id) => {
const services = await Api.services() return state.groups.find(g => g.id === id)
context.commit("setServices", services); },
const messages = await Api.messages() cleanGroups: (state) => () => {
context.commit("setMessages", messages) return state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id)
const oauth = await Api.oauth() },
context.commit("setOAuth", oauth); userById: (state) => (id) => {
context.commit("setHasPublicData", true) return state.users.find(u => u.id === id)
}, },
async loadAdmin(context) { messageById: (state) => (id) => {
const groups = await Api.groups() return state.messages.find(m => m.id === id)
context.commit("setGroups", groups); },
const services = await Api.services() },
context.commit("setServices", services); mutations: {
const messages = await Api.messages() setHasAllData(state, bool) {
context.commit("setMessages", messages) state.hasAllData = bool
context.commit("setHasPublicData", true) },
const checkins = await Api.checkins() setHasPublicData(state, bool) {
context.commit("setCheckins", checkins); state.hasPublicData = bool
const notifiers = await Api.notifiers() },
context.commit("setNotifiers", notifiers); setCore(state, core) {
const users = await Api.users() state.core = core
context.commit("setUsers", users); },
const oauth = await Api.oauth() setToken(state, token) {
context.commit("setOAuth", oauth); state.token = token
} },
setService(state, service) {
state.service = service
},
setServices(state, services) {
state.services = services
},
setCheckins(state, checkins) {
state.checkins = checkins
},
setGroups(state, groups) {
state.groups = groups
},
setMessages(state, messages) {
state.messages = messages
},
setUsers(state, users) {
state.users = users
},
setNotifiers(state, notifiers) {
state.notifiers = notifiers
},
setAdmin(state, admin) {
state.admin = admin
},
setLoggedIn(state, loggedIn) {
state.loggedIn = loggedIn
},
setUser(state, user) {
state.user = user
},
setOAuth(state, oauth) {
state.oauth = oauth
},
},
actions: {
async getAllServices(context) {
const services = await Api.services()
context.commit("setServices", services);
},
async loadCore(context) {
const core = await Api.core()
const token = await Api.token()
context.commit("setCore", core);
context.commit('setAdmin', token)
context.commit('setCore', core)
context.commit('setUser', token !== undefined)
},
async loadRequired(context) {
const groups = await Api.groups()
context.commit("setGroups", groups);
const services = await Api.services()
context.commit("setServices", services);
const messages = await Api.messages()
context.commit("setMessages", messages)
const oauth = await Api.oauth()
context.commit("setOAuth", oauth);
context.commit("setHasPublicData", true)
},
async loadAdmin(context) {
const groups = await Api.groups()
context.commit("setGroups", groups);
const services = await Api.services()
context.commit("setServices", services);
const messages = await Api.messages()
context.commit("setMessages", messages)
context.commit("setHasPublicData", true)
const checkins = await Api.checkins()
context.commit("setCheckins", checkins);
const notifiers = await Api.notifiers()
context.commit("setNotifiers", notifiers);
const users = await Api.users()
context.commit("setUsers", users);
const oauth = await Api.oauth()
context.commit("setOAuth", oauth);
} }
}
}); });