Add support for temporarily blocking with end time

This commit is contained in:
Jonas Lochmann
2020-01-27 01:00:00 +01:00
parent b55c375506
commit 719af663f5
8 changed files with 92 additions and 13 deletions
+23 -5
View File
@@ -1,6 +1,6 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 Jonas Lochmann
* Copyright (C) 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -21,24 +21,41 @@ import { ParentAction } from './basetypes'
export class UpdateCategoryTemporarilyBlockedAction extends ParentAction {
readonly categoryId: string
readonly blocked: boolean
readonly endTime?: number
constructor ({ categoryId, blocked }: {categoryId: string, blocked: boolean}) {
constructor ({ categoryId, blocked, endTime }: {
categoryId: string
blocked: boolean
endTime?: number
}) {
super()
assertIdWithinFamily(categoryId)
if (endTime !== undefined) {
if (!Number.isSafeInteger(endTime)) {
throw new Error()
}
if (!blocked) {
throw new Error()
}
}
this.categoryId = categoryId
this.blocked = blocked
this.endTime = endTime
}
serialize = (): SerializedUpdateCategoryTemporarilyBlockedAction => ({
type: 'UPDATE_CATEGORY_TEMPORARILY_BLOCKED',
categoryId: this.categoryId,
blocked: this.blocked
blocked: this.blocked,
endTime: this.endTime
})
static parse = ({ categoryId, blocked }: SerializedUpdateCategoryTemporarilyBlockedAction) => (
new UpdateCategoryTemporarilyBlockedAction({ categoryId, blocked })
static parse = ({ categoryId, blocked, endTime }: SerializedUpdateCategoryTemporarilyBlockedAction) => (
new UpdateCategoryTemporarilyBlockedAction({ categoryId, blocked, endTime })
)
}
@@ -46,4 +63,5 @@ export interface SerializedUpdateCategoryTemporarilyBlockedAction {
type: 'UPDATE_CATEGORY_TEMPORARILY_BLOCKED'
categoryId: string
blocked: boolean
endTime?: number
}
+3
View File
@@ -853,6 +853,9 @@ const definitions = {
},
"blocked": {
"type": "boolean"
},
"endTime": {
"type": "number"
}
},
"additionalProperties": false,
+16 -3
View File
@@ -17,7 +17,7 @@
import * as Sequelize from 'sequelize'
import { serializedBitmaskRegex } from '../util/bitmask'
import { booleanColumn, familyIdColumn, idWithinFamilyColumn, labelColumn, optionalIdWithinFamilyColumn, versionColumn } from './columns'
import { booleanColumn, familyIdColumn, idWithinFamilyColumn, labelColumn, optionalIdWithinFamilyColumn, timestampColumn, versionColumn } from './columns'
import { SequelizeAttributes } from './types'
export const allowedTimeWarningFlags = 1 | 2 | 4 | 8 | 16
@@ -53,8 +53,13 @@ export interface CategoryAttributesVersion5 {
minBatteryMobile: number
}
export interface CategoryAttributesVersion6 {
temporarilyBlockedEndTime: number
}
export type CategoryAttributes = CategoryAttributesVersion1 & CategoryAttributesVersion2 &
CategoryAttributesVersion3 & CategoryAttributesVersion4 & CategoryAttributesVersion5
CategoryAttributesVersion3 & CategoryAttributesVersion4 & CategoryAttributesVersion5 &
CategoryAttributesVersion6
export type CategoryModel = Sequelize.Model & CategoryAttributes
export type CategoryModelStatic = typeof Sequelize.Model & {
@@ -145,12 +150,20 @@ export const attributesVersion5: SequelizeAttributes<CategoryAttributesVersion5>
}
}
export const attributesVersion6: SequelizeAttributes<CategoryAttributesVersion6> = {
temporarilyBlockedEndTime: {
...timestampColumn,
defaultValue: 0
}
}
export const attributes: SequelizeAttributes<CategoryAttributes> = {
...attributesVersion1,
...attributesVersion2,
...attributesVersion3,
...attributesVersion4,
...attributesVersion5
...attributesVersion5,
...attributesVersion6
}
export const createCategoryModel = (sequelize: Sequelize.Sequelize): CategoryModelStatic => sequelize.define('Category', attributes) as CategoryModelStatic
@@ -0,0 +1,39 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 - 2020 Jonas Lochmann
*
* 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, version 3 of the License.
*
* 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 <https://www.gnu.org/licenses/>.
*/
import { QueryInterface, Sequelize, Transaction } from 'sequelize'
import { attributesVersion6 as categoryAttributes } from '../../category'
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: Transaction.TYPES.EXCLUSIVE
}, async (transaction) => {
await queryInterface.addColumn('Categories', 'temporarilyBlockedEndTime', {
...categoryAttributes.temporarilyBlockedEndTime
}, {
transaction
})
})
}
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: Transaction.TYPES.EXCLUSIVE
}, async (transaction) => {
await queryInterface.removeColumn('Categories', 'temporarilyBlockedEndTime', { transaction })
})
}
@@ -45,6 +45,7 @@ export async function dispatchCreateCategory ({ action, cache }: {
title: action.title,
blockedMinutesInWeek: '',
temporarilyBlocked: false,
temporarilyBlockedEndTime: 0,
extraTimeInMillis: 0,
timeLimitRulesVersion: generateVersionId(),
baseVersion: generateVersionId(),
@@ -1,6 +1,6 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 Jonas Lochmann
* Copyright (C) 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -29,7 +29,8 @@ export async function dispatchUpdateCategoryTemporarilyBlocked ({ action, cache
}
const [affectedRows] = await cache.database.category.update({
temporarilyBlocked: action.blocked
temporarilyBlocked: action.blocked,
temporarilyBlockedEndTime: action.blocked ? (action.endTime ?? 0) : 0
}, {
where: {
familyId: cache.familyId,
+6 -3
View File
@@ -341,7 +341,8 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
'blockAllNotifications',
'timeWarningFlags',
'minBatteryCharging',
'minBatteryMobile'
'minBatteryMobile',
'temporarilyBlockedEndTime'
],
transaction
})).map((item) => ({
@@ -356,7 +357,8 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
blockAllNotifications: item.blockAllNotifications,
timeWarningFlags: item.timeWarningFlags,
minBatteryCharging: item.minBatteryCharging,
minBatteryMobile: item.minBatteryMobile
minBatteryMobile: item.minBatteryMobile,
temporarilyBlockedEndTime: item.temporarilyBlockedEndTime
}))
result.categoryBase = dataForSyncing.map((item): ServerUpdatedCategoryBaseData => ({
@@ -371,7 +373,8 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
blockAllNotifications: item.blockAllNotifications,
timeWarnings: item.timeWarningFlags,
mblMobile: item.minBatteryMobile,
mblCharging: item.minBatteryCharging
mblCharging: item.minBatteryCharging,
tempBlockTime: item.temporarilyBlockedEndTime
}))
}
+1
View File
@@ -100,6 +100,7 @@ export interface ServerUpdatedCategoryBaseData {
blockedTimes: string // blockedMinutesInWeek
extraTime: number
tempBlocked: boolean
tempBlockTime: number
version: string
parentCategoryId: string
blockAllNotifications: boolean