diff --git a/src/action/index.ts b/src/action/index.ts
index 3c9b18a..3a0e707 100644
--- a/src/action/index.ts
+++ b/src/action/index.ts
@@ -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
@@ -51,6 +51,7 @@ export { SetUserTimezoneAction } from './setusertimezone'
export { SignOutAtDeviceAction } from './signoutatdevice'
export { TriedDisablingDeviceAdminAction } from './trieddisablingdeviceadmin'
export { UpdateAppActivitiesAction } from './updateappactivities'
+export { UpdateCategoryBatteryLimitAction } from './updatecategorybatterylimit'
export { UpdateCategoryBlockAllNotificationsAction } from './updatecategoryblockallnotifications'
export { UpdateCategoryBlockedTimesAction } from './updatecategoryblockedtimes'
export { UpdateCategoryTemporarilyBlockedAction } from './updatecategorytemporarilyblocked'
diff --git a/src/action/serialization/parentaction.ts b/src/action/serialization/parentaction.ts
index 7556b80..dbd9f53 100644
--- a/src/action/serialization/parentaction.ts
+++ b/src/action/serialization/parentaction.ts
@@ -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
@@ -42,6 +42,7 @@ import { SerializedSetRelaxPrimaryDeviceAction, SetRelaxPrimaryDeviceAction } fr
import { SerializedSetSendDeviceConnected, SetSendDeviceConnected } from '../setsenddeviceconnected'
import { SerializedSetUserDisableLimitsUntilAction, SetUserDisableLimitsUntilAction } from '../setuserdisablelimitsuntil'
import { SerializedSetUserTimezoneAction, SetUserTimezoneAction } from '../setusertimezone'
+import { SerializedUpdateCategoryBatteryLimitAction, UpdateCategoryBatteryLimitAction } from '../updatecategorybatterylimit'
import { SerializedUpdateCategoryBlockAllNotificationsAction, UpdateCategoryBlockAllNotificationsAction } from '../updatecategoryblockallnotifications'
import { SerializedUpdateCategoryBlockedTimesAction, UpdateCategoryBlockedTimesAction } from '../updatecategoryblockedtimes'
import { SerializedUpdateCategoryTemporarilyBlockedAction, UpdateCategoryTemporarilyBlockedAction } from '../updatecategorytemporarilyblocked'
@@ -81,6 +82,7 @@ export type SerializedParentAction =
SerializedSetSendDeviceConnected |
SerializedSetUserDisableLimitsUntilAction |
SerializedSetUserTimezoneAction |
+ SerializedUpdateCategoryBatteryLimitAction |
SerializedUpdateCategoryBlockAllNotificationsAction |
SerializedUpdateCategoryBlockedTimesAction |
SerializedUpdateCategoryTemporarilyBlockedAction |
@@ -146,6 +148,8 @@ export const parseParentAction = (action: SerializedParentAction): ParentAction
return SetUserDisableLimitsUntilAction.parse(action)
} else if (action.type === 'SET_USER_TIMEZONE') {
return SetUserTimezoneAction.parse(action)
+ } else if (action.type === 'UPDATE_CATEGORY_BATTERY_LIMIT') {
+ return UpdateCategoryBatteryLimitAction.parse(action)
} else if (action.type === 'UPDATE_CATEGORY_BLOCK_ALL_NOTIFICATIONS') {
return UpdateCategoryBlockAllNotificationsAction.parse(action)
} else if (action.type === 'UPDATE_CATEGORY_BLOCKED_TIMES') {
diff --git a/src/action/updatecategorybatterylimit.ts b/src/action/updatecategorybatterylimit.ts
new file mode 100644
index 0000000..71cf9f2
--- /dev/null
+++ b/src/action/updatecategorybatterylimit.ts
@@ -0,0 +1,69 @@
+/*
+ * 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 .
+ */
+
+import { assertIdWithinFamily } from '../util/token'
+import { ParentAction } from './basetypes'
+
+export class UpdateCategoryBatteryLimitAction extends ParentAction {
+ readonly categoryId: string
+ readonly chargeLimit?: number
+ readonly mobileLimit?: number
+
+ constructor ({ categoryId, chargeLimit, mobileLimit }: {
+ categoryId: string
+ chargeLimit?: number
+ mobileLimit?: number
+ }) {
+ super()
+
+ assertIdWithinFamily(categoryId)
+
+ if (chargeLimit !== undefined) {
+ if ((!Number.isSafeInteger(chargeLimit)) || chargeLimit < 0 || chargeLimit > 100) {
+ throw new Error('charge limit out of range')
+ }
+ }
+
+ if (mobileLimit !== undefined) {
+ if ((!Number.isSafeInteger(mobileLimit)) || mobileLimit < 0 || mobileLimit > 100) {
+ throw new Error('mobile limit out of range')
+ }
+ }
+
+ this.categoryId = categoryId
+ this.chargeLimit = chargeLimit
+ this.mobileLimit = mobileLimit
+ }
+
+ serialize = (): SerializedUpdateCategoryBatteryLimitAction => ({
+ type: 'UPDATE_CATEGORY_BATTERY_LIMIT',
+ categoryId: this.categoryId,
+ mobileLimit: this.mobileLimit,
+ chargeLimit: this.chargeLimit
+ })
+
+ static parse = ({ categoryId, chargeLimit, mobileLimit }: SerializedUpdateCategoryBatteryLimitAction) => (
+ new UpdateCategoryBatteryLimitAction({ categoryId, chargeLimit, mobileLimit })
+ )
+}
+
+export interface SerializedUpdateCategoryBatteryLimitAction {
+ type: 'UPDATE_CATEGORY_BATTERY_LIMIT'
+ categoryId: string
+ chargeLimit?: number
+ mobileLimit?: number
+}
diff --git a/src/api/validator.ts b/src/api/validator.ts
index ce1ad26..7959c61 100644
--- a/src/api/validator.ts
+++ b/src/api/validator.ts
@@ -768,6 +768,31 @@ const definitions = {
"userId"
]
},
+ "SerializedUpdateCategoryBatteryLimitAction": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "UPDATE_CATEGORY_BATTERY_LIMIT"
+ ]
+ },
+ "categoryId": {
+ "type": "string"
+ },
+ "chargeLimit": {
+ "type": "number"
+ },
+ "mobileLimit": {
+ "type": "number"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "categoryId",
+ "type"
+ ]
+ },
"SerializedUpdateCategoryBlockAllNotificationsAction": {
"type": "object",
"properties": {
@@ -1619,6 +1644,9 @@ export const isSerializedParentAction: (value: object) => value is SerializedPar
{
"$ref": "#/definitions/SerializedSetUserTimezoneAction"
},
+ {
+ "$ref": "#/definitions/SerializedUpdateCategoryBatteryLimitAction"
+ },
{
"$ref": "#/definitions/SerializedUpdateCategoryBlockAllNotificationsAction"
},
diff --git a/src/database/category.ts b/src/database/category.ts
index d1dba5f..d88e43a 100644
--- a/src/database/category.ts
+++ b/src/database/category.ts
@@ -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
@@ -48,8 +48,13 @@ export interface CategoryAttributesVersion4 {
timeWarningFlags: number
}
+export interface CategoryAttributesVersion5 {
+ minBatteryCharging: number
+ minBatteryMobile: number
+}
+
export type CategoryAttributes = CategoryAttributesVersion1 & CategoryAttributesVersion2 &
- CategoryAttributesVersion3 & CategoryAttributesVersion4
+ CategoryAttributesVersion3 & CategoryAttributesVersion4 & CategoryAttributesVersion5
export type CategoryModel = Sequelize.Model & CategoryAttributes
export type CategoryModelStatic = typeof Sequelize.Model & {
@@ -119,11 +124,33 @@ export const attributesVersion4: SequelizeAttributes
}
}
+export const attributesVersion5: SequelizeAttributes = {
+ minBatteryMobile: {
+ type: Sequelize.INTEGER,
+ defaultValue: 0,
+ allowNull: false,
+ validate: {
+ min: 0,
+ max: 100
+ }
+ },
+ minBatteryCharging: {
+ type: Sequelize.INTEGER,
+ defaultValue: 0,
+ allowNull: false,
+ validate: {
+ min: 0,
+ max: 100
+ }
+ }
+}
+
export const attributes: SequelizeAttributes = {
...attributesVersion1,
...attributesVersion2,
...attributesVersion3,
- ...attributesVersion4
+ ...attributesVersion4,
+ ...attributesVersion5
}
export const createCategoryModel = (sequelize: Sequelize.Sequelize): CategoryModelStatic => sequelize.define('Category', attributes) as CategoryModelStatic
diff --git a/src/database/migration/migrations/20200113-add-min-battery-level.ts b/src/database/migration/migrations/20200113-add-min-battery-level.ts
new file mode 100644
index 0000000..bc0c429
--- /dev/null
+++ b/src/database/migration/migrations/20200113-add-min-battery-level.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 .
+ */
+
+import { QueryInterface, Sequelize, Transaction } from 'sequelize'
+import { attributesVersion5 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', 'minBatteryMobile', {
+ ...categoryAttributes.minBatteryMobile
+ }, {
+ transaction
+ })
+
+ await queryInterface.addColumn('Categories', 'minBatteryCharging', {
+ ...categoryAttributes.minBatteryCharging
+ }, {
+ transaction
+ })
+ })
+}
+
+export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
+ await sequelize.transaction({
+ type: Transaction.TYPES.EXCLUSIVE
+ }, async (transaction) => {
+ await queryInterface.removeColumn('Categories', 'minBatteryMobile', { transaction })
+ await queryInterface.removeColumn('Categories', 'minBatteryCharging', { transaction })
+ })
+}
diff --git a/src/function/sync/apply-actions/dispatch-parent-action/index.ts b/src/function/sync/apply-actions/dispatch-parent-action/index.ts
index 78f445a..4ce2b0c 100644
--- a/src/function/sync/apply-actions/dispatch-parent-action/index.ts
+++ b/src/function/sync/apply-actions/dispatch-parent-action/index.ts
@@ -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
@@ -43,6 +43,7 @@ import {
SetSendDeviceConnected,
SetUserDisableLimitsUntilAction,
SetUserTimezoneAction,
+ UpdateCategoryBatteryLimitAction,
UpdateCategoryBlockAllNotificationsAction,
UpdateCategoryBlockedTimesAction,
UpdateCategoryTemporarilyBlockedAction,
@@ -82,6 +83,7 @@ import { dispatchSetRelaxPrimaryDevice } from './setrelaxprimarydevice'
import { dispatchSetSendDeviceConnected } from './setsenddeviceconnected'
import { dispatchUserSetDisableLimitsUntil } from './setuserdisablelmitsuntil'
import { dispatchSetUserTimezone } from './setusertimezone'
+import { dispatchUpdateCategoryBatteryLimit } from './updatecategorybatterylimit'
import { dispatchUpdateCategoryBlockAllNotifications } from './updatecategoryblockallnotifications'
import { dispatchUpdateCategoryBlockedTimes } from './updatecategoryblockedtimes'
import { dispatchUpdateCategoryTemporarilyBlocked } from './updatecategorytemporarilyblocked'
@@ -140,6 +142,8 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source
await dispatchUserSetDisableLimitsUntil({ action, cache })
} else if (action instanceof SetUserTimezoneAction) {
await dispatchSetUserTimezone({ action, cache })
+ } else if (action instanceof UpdateCategoryBatteryLimitAction) {
+ await dispatchUpdateCategoryBatteryLimit({ action, cache })
} else if (action instanceof UpdateCategoryBlockAllNotificationsAction) {
await dispatchUpdateCategoryBlockAllNotifications({ action, cache })
} else if (action instanceof UpdateCategoryBlockedTimesAction) {
diff --git a/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts b/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts
new file mode 100644
index 0000000..3f94679
--- /dev/null
+++ b/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+
+import { UpdateCategoryBatteryLimitAction } from '../../../../action'
+import { Cache } from '../cache'
+
+export async function dispatchUpdateCategoryBatteryLimit ({ action, cache }: {
+ action: UpdateCategoryBatteryLimitAction
+ cache: Cache
+}) {
+ const categoryEntry = await cache.database.category.findOne({
+ where: {
+ familyId: cache.familyId,
+ categoryId: action.categoryId
+ },
+ transaction: cache.transaction
+ })
+
+ if (!categoryEntry) {
+ throw new Error('invalid category id')
+ }
+
+ if (action.chargeLimit !== undefined) {
+ categoryEntry.minBatteryCharging = action.chargeLimit
+ }
+
+ if (action.mobileLimit !== undefined) {
+ categoryEntry.minBatteryMobile = action.mobileLimit
+ }
+
+ await categoryEntry.save({ transaction: cache.transaction })
+
+ cache.categoriesWithModifiedBaseData.push(action.categoryId)
+ cache.areChangesImportant = true
+}
diff --git a/src/function/sync/get-server-data-status.ts b/src/function/sync/get-server-data-status.ts
index bba8e39..e93c379 100644
--- a/src/function/sync/get-server-data-status.ts
+++ b/src/function/sync/get-server-data-status.ts
@@ -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
@@ -339,7 +339,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
'baseVersion',
'parentCategoryId',
'blockAllNotifications',
- 'timeWarningFlags'
+ 'timeWarningFlags',
+ 'minBatteryCharging',
+ 'minBatteryMobile'
],
transaction
})).map((item) => ({
@@ -352,7 +354,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
baseVersion: item.baseVersion,
parentCategoryId: item.parentCategoryId,
blockAllNotifications: item.blockAllNotifications,
- timeWarningFlags: item.timeWarningFlags
+ timeWarningFlags: item.timeWarningFlags,
+ minBatteryCharging: item.minBatteryCharging,
+ minBatteryMobile: item.minBatteryMobile
}))
result.categoryBase = dataForSyncing.map((item): ServerUpdatedCategoryBaseData => ({
@@ -365,7 +369,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
version: item.baseVersion,
parentCategoryId: item.parentCategoryId,
blockAllNotifications: item.blockAllNotifications,
- timeWarnings: item.timeWarningFlags
+ timeWarnings: item.timeWarningFlags,
+ mblMobile: item.minBatteryMobile,
+ mblCharging: item.minBatteryCharging
}))
}
diff --git a/src/object/serverdatastatus.ts b/src/object/serverdatastatus.ts
index ca1e553..e514ff1 100644
--- a/src/object/serverdatastatus.ts
+++ b/src/object/serverdatastatus.ts
@@ -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
@@ -104,6 +104,9 @@ export interface ServerUpdatedCategoryBaseData {
parentCategoryId: string
blockAllNotifications: boolean
timeWarnings: number
+ // mbl = minimum battery level
+ mblCharging: number
+ mblMobile: number
}
export interface ServerUpdatedCategoryAssignedApps {