TT#95600 Improve api methods

Change-Id: If3223cadc11c034591fa539401aeff84f9a1ea0d
mr9.1.1
Hans-Peter Herzog 5 years ago
parent 6f52bb20b0
commit e24a029a7e

@ -4,7 +4,7 @@ import Vue from 'vue'
import { i18n } from 'src/boot/i18n'
import { getJsonBody } from './utils'
import { normalizeDestination } from '../filters/number-format'
import { LIST_ALL_ROWS, patchReplaceFull, get, getList } from './common'
import { LIST_ALL_ROWS, patchReplaceFull, get, getList, del } from './common'
export function getMappings (id) {
return new Promise((resolve, reject) => {
@ -613,36 +613,157 @@ export function convertTimesetToWeekdays (options) {
}
}
export function loadTimesetTimes (options) {
return new Promise((resolve, reject) => {
Promise.resolve().then(() => {
return getTimesets(options.subscriberId)
}).then((timesets) => {
const times = convertTimesetToWeekdays({ timesets: timesets, timesetName: options.timeset })
return times
}).then((times) => {
resolve(times)
}).catch((err) => {
reject(err)
})
})
function convertToTimes (times) {
return times.reduce((timesConverted, time) => {
const hourParts = time.hour.split('-')
let minuteParts = null
if (time.minute !== null && time.minute !== '') {
minuteParts = time.minute.split('-')
}
if (hourParts.length === 1 && minuteParts === null) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':00',
to: normalizeTimePart(hourParts[0]) + ':00',
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 1 && minuteParts !== null && minuteParts.length === 1) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
to: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 1 && minuteParts !== null && minuteParts.length === 2) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
to: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[1]),
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 2 && minuteParts === null) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':00',
to: normalizeTimePart(hourParts[1]) + ':00',
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 2 && minuteParts !== null && minuteParts.length === 1) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
to: normalizeTimePart(hourParts[1]) + ':' + normalizeTimePart(minuteParts[0]),
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 2 && minuteParts !== null && minuteParts.length === 2) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
to: normalizeTimePart(hourParts[1]) + ':' + normalizeTimePart(minuteParts[1]),
weekday: parseInt(time.wday)
})
} else if (hourParts.length === 2 && minuteParts !== null && minuteParts.length === 2) {
timesConverted.push({
from: normalizeTimePart(hourParts[0]) + ':' + normalizeTimePart(minuteParts[0]),
to: normalizeTimePart(hourParts[1]) + ':' + normalizeTimePart(minuteParts[1]),
weekday: parseInt(time.wday)
})
}
return timesConverted
}, [])
}
export function deleteTimeFromTimeset (options) {
const headers = {
'Content-Type': 'application/json-patch+json'
function normalizeTimePart (part) {
if (part.length === 1) {
return '0' + part
} else {
return part
}
return new Promise((resolve, reject) => {
Vue.http.patch('api/cftimesets/' + options.timesetId, [{
op: 'replace',
path: '/times',
value: options.times
}], { headers: headers }).then((result) => {
resolve(result)
}).catch((err) => {
reject(err)
})
}
export async function loadTimesetTimes (options) {
const timesets = await getTimesets(options.subscriberId)
const filteredTimesets = timesets.filter(timeset => timeset.name === options.timeset)
if (filteredTimesets.length === 1) {
return {
times: convertToTimes(filteredTimesets[0].times),
timesetIsCompatible: true,
timesetExists: filteredTimesets.length === 1,
timesetHasReverse: false,
timesetHasDuplicate: filteredTimesets.length > 1,
timesetId: filteredTimesets[0].id
}
} else {
return {
times: [],
timesetIsCompatible: true,
timesetExists: false,
timesetHasReverse: false,
timesetHasDuplicate: false,
timesetId: null
}
}
}
export async function appendTimeToTimeset (options) {
const timeset = await get({
resource: 'cftimesets',
resourceId: options.timesetId
})
const times = _.cloneDeep(timeset.times)
times.push(options.time)
const updatedTimeset = await patchReplaceFull({
resource: 'cftimesets',
resourceId: options.timesetId,
fieldPath: 'times',
value: times
})
return {
times: convertToTimes(updatedTimeset.times),
timesetIsCompatible: true,
timesetExists: true,
timesetHasReverse: false,
timesetHasDuplicate: false,
timesetId: updatedTimeset.id
}
}
/**
* Removes a specific time from a given timeset
* @param options
* @param options.timesetId
* @param options.timeId
* @returns {Promise<void>}
*/
export async function deleteTimeFromTimeset (options) {
const timeset = await get({
resource: 'cftimesets',
resourceId: options.timesetId
})
const updatedTimes = timeset.times.filter((time, index) => index !== options.timeId)
if (updatedTimes.length === 0) {
await del({
resource: 'cftimesets',
resourceId: options.timesetId
})
return {
times: null,
timesetIsCompatible: true,
timesetExists: false,
timesetHasReverse: false,
timesetHasDuplicate: false,
timesetId: null
}
} else {
const updatedTimeset = await patchReplaceFull({
resource: 'cftimesets',
resourceId: options.timesetId,
fieldPath: 'times',
value: updatedTimes
})
return {
times: convertToTimes(updatedTimeset.times),
timesetIsCompatible: true,
timesetExists: true,
timesetHasReverse: false,
timesetHasDuplicate: false,
timesetId: updatedTimeset.id
}
}
}
export function deleteTimesetById (id) {
@ -767,22 +888,6 @@ export function getTimesByTimesetId (id) {
})
}
export function appendTimeToTimeset (options) {
return new Promise((resolve, reject) => {
const convertedTime = convertAddTime({ time: options.time[0], weekday: options.weekday })
Promise.resolve().then(() => {
return getTimesByTimesetId(options.id)
}).then((times) => {
const concatTimes = times.concat(convertedTime)
return addTimeToTimeset({ id: options.id, times: concatTimes })
}).then(() => {
resolve()
}).catch((err) => {
reject(err)
})
})
}
export function getSourcesetById (id) {
return new Promise((resolve, reject) => {
Vue.http.get('api/cfsourcesets/' + id).then((res) => {

@ -27,121 +27,126 @@ export class ApiResponseError extends Error {
}
}
export function getList (options) {
return new Promise((resolve, reject) => {
options = options || {}
options = _.merge({
all: false,
params: {
page: LIST_DEFAULT_PAGE,
rows: LIST_DEFAULT_ROWS
},
headers: GET_HEADERS
}, options)
Promise.resolve().then(() => {
if (options.all === true) {
options.params.rows = LIST_ALL_ROWS
}
return Vue.http.get(options.path, {
params: options.params,
headers: options.headers
})
}).then((res) => {
const body = getJsonBody(res.body)
if (options.all === true && body.total_count > LIST_ALL_ROWS) {
return Vue.http.get(options.path, {
params: _.merge(options.params, {
rows: body.total_count
}),
headers: options.headers
})
} else {
return Promise.resolve(res)
}
}).then((res) => {
const body = getJsonBody(res.body)
const totalCount = _.get(body, 'total_count', 0)
let lastPage = Math.ceil(totalCount / options.params.rows)
if (options.all === true) {
lastPage = 1
}
if (lastPage === 0) {
lastPage = null
}
const items = _.get(body, options.root, [])
for (let i = 0; i < items.length; i++) {
items[i] = normalizeEntity(items[i])
}
resolve({
items: items,
lastPage: lastPage
})
}).catch((err) => {
reject(err)
})
export async function getList (options) {
options = options || {}
options = _.merge({
all: false,
params: {
page: LIST_DEFAULT_PAGE,
rows: LIST_DEFAULT_ROWS
},
headers: GET_HEADERS
}, options)
if (options.all === true) {
options.params.rows = LIST_ALL_ROWS
}
if (options.resource !== undefined) {
options.path = 'api/' + options.resource
options.root = '_embedded.ngcp:' + options.resource
}
const firstRes = await Vue.http.get(options.path, {
params: options.params,
headers: options.headers
})
let secondRes = null
const firstResBody = getJsonBody(firstRes.body)
if (options.all === true && firstResBody.total_count > LIST_ALL_ROWS) {
secondRes = await Vue.http.get(options.path, {
params: _.merge(options.params, {
rows: firstResBody.total_count
}),
headers: options.headers
})
}
let res = firstRes
let body = firstResBody
if (secondRes !== null) {
res = secondRes
body = getJsonBody(res.body)
}
const totalCount = _.get(body, 'total_count', 0)
let lastPage = Math.ceil(totalCount / options.params.rows)
if (options.all === true) {
lastPage = 1
}
if (lastPage === 0) {
lastPage = null
}
const items = _.get(body, options.root, [])
for (let i = 0; i < items.length; i++) {
items[i] = normalizeEntity(items[i])
}
return {
items: items,
lastPage: lastPage
}
}
export function get (options) {
return new Promise((resolve, reject) => {
options = options || {}
options = _.merge({
headers: GET_HEADERS
}, options)
const requestOptions = {
headers: options.headers,
params: options.params
}
export async function get (options) {
options = options || {}
options = _.merge({
headers: GET_HEADERS
}, options)
const requestOptions = {
headers: options.headers,
params: options.params
}
if (options.blob === true) {
requestOptions.responseType = 'blob'
}
let path = options.path
if (options.resource !== undefined && options.resourceId !== undefined) {
path = 'api/' + options.resource + '/' + options.resourceId
}
try {
const res = await Vue.http.get(path, requestOptions)
let body = null
if (options.blob === true) {
requestOptions.responseType = 'blob'
body = URL.createObjectURL(res.body)
} else {
body = normalizeEntity(getJsonBody(res.body))
}
return Vue.http.get(options.path, requestOptions).then((result) => {
let body = null
if (options.blob === true) {
body = URL.createObjectURL(result.body)
} else {
body = normalizeEntity(getJsonBody(result.body))
}
resolve(body)
}).catch((err) => {
const code = _.get(err, 'body.code', null)
const message = _.get(err, 'body.message', null)
if (code !== null && message !== null) {
reject(new ApiResponseError(err.body.code, err.body.message))
} else {
reject(err)
}
})
})
return body
} catch (err) {
const code = _.get(err, 'body.code', null)
const message = _.get(err, 'body.message', null)
if (code !== null && message !== null) {
throw new ApiResponseError(err.body.code, err.body.message)
} else {
throw err
}
}
}
export function patch (operation, options) {
return new Promise((resolve, reject) => {
options = options || {}
options = _.merge({
headers: PATCH_HEADERS
}, options)
const body = {
op: operation,
path: '/' + options.fieldPath
}
if (options.value !== undefined) {
body.value = options.value
}
Vue.http.patch(options.path, [body], {
export async function patch (operation, options) {
options = options || {}
options = _.merge({
headers: PATCH_HEADERS
}, options)
const body = {
op: operation,
path: '/' + options.fieldPath
}
if (options.value !== undefined) {
body.value = options.value
}
let path = options.path
if (options.resource !== undefined && options.resourceId !== undefined) {
path = 'api/' + options.resource + '/' + options.resourceId
}
try {
return await Vue.http.patch(path, [body], {
headers: options.headers
}).then((result) => {
resolve(result)
}).catch((err) => {
const code = _.get(err, 'body.code', null)
const message = _.get(err, 'body.message', null)
if (code !== null && message !== null) {
reject(new ApiResponseError(err.body.code, err.body.message))
} else {
reject(err)
}
})
})
} catch (err) {
const code = _.get(err, 'body.code', null)
const message = _.get(err, 'body.message', null)
if (code !== null && message !== null) {
throw new ApiResponseError(err.body.code, err.body.message)
} else {
throw err
}
}
}
export function patchReplace (options) {
@ -156,20 +161,15 @@ export function patchRemove (options) {
return patch('remove', options)
}
export function patchFull (operation, options) {
return new Promise((resolve, reject) => {
options = options || {}
options = _.merge(options, {
headers: {
Prefer: 'return=representation'
}
})
patch(operation, options).then((result) => {
resolve(getJsonBody(result.body))
}).catch((err) => {
reject(err)
})
export async function patchFull (operation, options) {
options = options || {}
options = _.merge(options, {
headers: {
Prefer: 'return=representation'
}
})
const res = await patch(operation, options)
return normalizeEntity(getJsonBody(res.body))
}
export function patchReplaceFull (options) {
@ -184,6 +184,32 @@ export function patchRemoveFull (options) {
return patchFull('remove', options)
}
export async function del (options) {
options = options || {}
options = _.merge({
headers: GET_HEADERS
}, options)
const requestOptions = {
headers: options.headers,
params: options.params
}
let path = options.path
if (options.resource !== undefined && options.resourceId !== undefined) {
path = 'api/' + options.resource + '/' + options.resourceId
}
try {
await Vue.http.delete(path, requestOptions)
} catch (err) {
const code = _.get(err, 'body.code', null)
const message = _.get(err, 'body.message', null)
if (code !== null && message !== null) {
throw new ApiResponseError(err.body.code, err.body.message)
} else {
throw err
}
}
}
export function getFieldList (options) {
return new Promise((resolve, reject) => {
options = options || {}

@ -6,7 +6,8 @@ import NumberFormatFilter, {
} from 'src/filters/number-format'
import DateFilter, {
smartTime,
time
time,
weekday
} from 'src/filters/date'
import {
startCase
@ -28,4 +29,5 @@ export default () => {
Vue.filter('groupName', displayName)
Vue.filter('displayName', displayName)
Vue.filter('time', time)
Vue.filter('weekday', weekday)
}

@ -11,6 +11,7 @@
options-dense
emit-value
map-options
dense
:options="selectOptions"
/>
</div>
@ -19,6 +20,7 @@
>
<csc-input-time
v-model="timeFrom"
dense
/>
</div>
<div
@ -26,6 +28,7 @@
>
<csc-input-time
v-model="timeTo"
dense
class="col-2"
/>
</div>

@ -1,7 +1,7 @@
<template>
<q-item>
<q-item-section>
{{ weekday }}, {{ from | time }} - {{ to | time }}
{{ time.weekday | weekday }}, {{ time.from }} - {{ time.to }}
</q-item-section>
<q-item-section
side
@ -12,7 +12,7 @@
color="negative"
icon="delete"
:label="$t('buttons.remove')"
@click="deleteTime(index)"
@click="deleteTime"
/>
</csc-more-menu>
</q-item-section>
@ -23,9 +23,6 @@
import {
mapGetters
} from 'vuex'
import {
date
} from 'quasar'
import CscMoreMenu from 'components/CscMoreMenu'
import CscPopupMenuItem from 'components/CscPopupMenuItem'
@ -36,10 +33,6 @@ export default {
time: {
type: Object,
default: null
},
index: {
type: Number,
default: null
}
},
data () {
@ -49,48 +42,12 @@ export default {
computed: {
...mapGetters('callForward', {
timesLength: 'getTimesetTimesLength'
}),
weekday () {
return this.time.weekday
},
from () {
return date.buildDate({
hours: this.time.from.split(':')[0],
minutes: this.time.from.split(':')[1]
})
},
to () {
return date.buildDate({
hours: this.time.to.split(':')[0],
minutes: this.time.to.split(':')[1]
})
}
})
},
methods: {
deleteTime (index) {
if (this.timesLength <= 1) {
this.$emit('delete-last-time', index)
} else {
this.$emit('delete-time', {
index: index,
removedDay: this.weekday
})
}
deleteTime () {
this.$emit('delete-time')
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.q-item-side.csc-call-forward-time-btn-container
margin-left 0
.q-btn.csc-call-forward-time-btn
.q-icon
margin-right 0
.csc-time
.q-if-disabled::before
background-image none
background-color currentColor
</style>

@ -11,8 +11,7 @@
:class="'csc-item-' + ((index % 2 === 0)?'odd':'even')"
:time="time"
:index="index"
@delete-time="deleteTime"
@delete-last-time="deleteLastTime"
@delete-time="deleteTime(index)"
/>
</q-list>
<div
@ -79,11 +78,8 @@ export default {
enableAddForm () {
this.$emit('enable-add-form')
},
deleteTime (data) {
this.$emit('delete-time', data)
},
deleteLastTime (data) {
this.$emit('delete-last-time', data)
deleteTime (index) {
this.$emit('delete-time', index)
}
}
}

@ -5,17 +5,7 @@
:sourcesets="sourcesets"
:destinations="destinations"
:timeset-name="timesetName"
:loading="loadDestinationState === 'requesting' ||
addSourcesetState === 'requesting' ||
updateOwnPhoneToggleState === 'requesting' ||
addDestinationState === 'requesting' ||
removeDestinationState === 'requesting' ||
changeDestinationState === 'requesting' ||
addTimeState === 'requesting' ||
resetTimeState === 'requesting' ||
removeTimeState === 'requesting' ||
addSourceState === 'requesting' ||
removeSourceState === 'requesting'"
:loading="timesetLoading"
>
<div
v-if="showSections"
@ -30,7 +20,6 @@
:timeset-times-loaded="timesetTimesLoaded"
@enable-add-form="enableTimesAddForm"
@delete-time="deleteTimeDialog"
@delete-last-time="deleteLastTimeDialog"
/>
</div>
<div
@ -45,10 +34,10 @@
/>
</div>
<div
v-if="timesetHasDuplicate ||
v-if="!timesetLoading && (timesetHasDuplicate ||
!timesetIsCompatible ||
timesetHasReverse ||
showDefinedAlert"
showDefinedAlert)"
class="row justify-center q-pa-md q-pt-xl"
>
<div
@ -204,6 +193,19 @@ export default {
'addSourcesetError',
'timesetTimesLoaded'
]),
timesetLoading () {
return this.loadDestinationState === 'requesting' ||
this.addSourcesetState === 'requesting' ||
this.updateOwnPhoneToggleState === 'requesting' ||
this.addDestinationState === 'requesting' ||
this.removeDestinationState === 'requesting' ||
this.changeDestinationState === 'requesting' ||
this.addTimeState === 'requesting' ||
this.resetTimeState === 'requesting' ||
this.removeTimeState === 'requesting' ||
this.addSourceState === 'requesting' ||
this.removeSourceState === 'requesting'
},
labelReset () {
return this.$t('pages.callForward.times.resetTimeset', {
timeset: this.timesetName
@ -325,8 +327,7 @@ export default {
enableTimesAddForm () {
this.$store.commit('callForward/setActiveTimeForm', true)
},
deleteTimeDialog (data) {
this.deleteTimeData = data
deleteTimeDialog (index) {
this.$q.dialog({
title: this.$t('pages.callForward.times.removeDialogTitle'),
message: this.deleteTimeMessage,
@ -334,26 +335,13 @@ export default {
cancel: true,
persistent: true
}).onOk(data => {
this.deleteTime()
this.deleteTime(index)
})
},
deleteTime () {
this.$store.dispatch('callForward/deleteTimeFromTimeset', this.deleteTimeData)
this.deleteTimeData = null
},
deleteLastTimeDialog () {
this.$q.dialog({
title: this.$t('pages.callForward.times.removeDialogTitle'),
message: this.$t('pages.callForward.times.removeLastDialogText'),
color: 'negative',
cancel: true,
persistent: true
}).onOk(data => {
this.deleteLastTime()
deleteTime (index) {
this.$store.dispatch('callForward/deleteTimeFromTimeset', {
index: index
})
},
deleteLastTime () {
this.$store.dispatch('callForward/deleteTimesetById')
}
}
}

@ -6,7 +6,7 @@ import { i18n } from 'src/boot/i18n'
const { formatDate } = date
export default function (value) {
var timeStamp = new Date(value)
const timeStamp = new Date(value)
return `${formatDate(timeStamp, 'MMMM D, YYYY')} at ${formatDate(timeStamp, 'h:mm a')}`
}
@ -49,3 +49,23 @@ export function smartTime ($date) {
return momentDate.format('LLL')
}
}
export const WeekdayMap = {
sunday: 1,
monday: 2,
tuesday: 3,
wednesday: 4,
thursday: 5,
friday: 6,
saturday: 7
}
export function weekday (weekdayNumber) {
let weekdayString = ''
Object.keys(WeekdayMap).forEach((weekday) => {
if (WeekdayMap[weekday] === weekdayNumber) {
weekdayString = i18n.t('pages.callForward.times.' + weekday)
}
})
return weekdayString
}

@ -135,7 +135,7 @@ export default {
i18n.t('pages.callForward.times.resetErrorMessage')
},
showDefinedAlert (state) {
return !state.timesetExists && !state.activeTimeForm && state.addTimeState !== 'succeeded'
return !state.timesetExists && !state.activeTimeForm
},
destinationsLoaded (state) {
return state.destinations.length > 0
@ -347,7 +347,7 @@ export default {
state.removeTimeState = RequestState.requesting
state.removeTimeError = null
},
removeTimeSucceeded (state) {
removeTimeSucceeded (state, updatedTimeset) {
state.removeTimeState = RequestState.succeeded
state.removeTimeError = null
},
@ -687,26 +687,38 @@ export default {
context.commit('loadTimesSucceeded', result)
})
},
deleteTimeFromTimeset (context, options) {
async appendTimeToTimeset (context, options) {
try {
context.commit('addTimeRequesting')
const fromParts = options.time[0].from.split(':')
const toParts = options.time[0].to.split(':')
const updatedTimes = await appendTimeToTimeset({
timesetId: context.getters.getTimesetId,
time: {
minute: fromParts[1] + '-' + toParts[1],
hour: fromParts[0] + '-' + toParts[0],
wday: options.weekday
}
})
context.commit('addTimeSucceeded')
context.commit('loadTimesSucceeded', updatedTimes)
} catch (err) {
console.log(err)
context.commit('addTimeFailed', err.message)
}
},
async deleteTimeFromTimeset (context, options) {
context.commit('removeTimeRequesting')
const clonedTimes = _.cloneDeep(context.getters.getTimesetTimes)
const indexInt = parseInt(options.index)
clonedTimes.splice(indexInt, 1)
clonedTimes.forEach((time) => {
delete time.weekday
delete time.from
delete time.to
})
deleteTimeFromTimeset({
subscriberId: context.getters.subscriberId,
timesetId: context.getters.getTimesetId,
times: clonedTimes
}).then(() => {
context.commit('setLastRemovedDay', options.removedDay)
try {
const updatedTimes = await deleteTimeFromTimeset({
timesetId: context.getters.getTimesetId,
timeId: options.index
})
context.commit('removeTimeSucceeded')
}).catch((err) => {
context.commit('loadTimesSucceeded', updatedTimes)
} catch (err) {
context.commit('removeTimeFailed', err.message)
})
}
},
deleteTimesetById (context) {
context.commit('removeTimeRequesting')
@ -743,18 +755,6 @@ export default {
context.commit('addTimeFailed', err.message)
})
},
appendTimeToTimeset (context, options) {
context.commit('addTimeRequesting')
appendTimeToTimeset({
time: options.time,
weekday: options.weekday,
id: context.getters.getTimesetId
}).then(() => {
context.commit('addTimeSucceeded')
}).catch((err) => {
context.commit('addTimeFailed', err.message)
})
},
loadDestinations (context, options) {
context.commit('loadDestinationRequesting')
loadDestinations({

Loading…
Cancel
Save