Skip to content

Commit

Permalink
Add system warning for battery level (GladysAssistant#1953)
Browse files Browse the repository at this point in the history
  • Loading branch information
callemand authored Dec 1, 2023
1 parent 6d740f0 commit aeddefc
Show file tree
Hide file tree
Showing 25 changed files with 892 additions and 427 deletions.
4 changes: 3 additions & 1 deletion front/src/config/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2063,7 +2063,9 @@
"paused": "Paused",
"exited": "Exited",
"dead": "Dead"
}
},
"batteryLevel": "Battery level alert",
"batteryLevelDescription": "Every Saturday at 9:00 am, a message will be sent to all administrators if a device's battery level falls below the chosen threshold."
},
"newArea": {
"createNewZoneButton": "Create new zone",
Expand Down
4 changes: 3 additions & 1 deletion front/src/config/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -2064,7 +2064,9 @@
"paused": "En Pause",
"exited": "Arrêté",
"dead": "Mort"
}
},
"batteryLevel": "Alerte sur le niveau de batterie",
"batteryLevelDescription": "Tous les samedis à 9h00, un message sera envoyé à tous les administrateurs si le niveau de batterie d'un appareil passe en dessous du seuil choisi."
},
"newArea": {
"createNewZoneButton": "Créer une zone",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import cx from 'classnames';
import { Text } from 'preact-i18n';
import { Component } from 'preact';
import { SYSTEM_VARIABLE_NAMES } from '../../../../../server/utils/constants';
import debounce from 'debounce';
import { connect } from 'unistore/preact';

class SettingsSystemBatteryLevelWarning extends Component {
getBatteryLevelUnderWarning = async () => {
try {
const { value: batteryLevelUnderWarningThreshold } = await this.props.httpClient.get(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_BATTERY_LEVEL_WARNING_THRESHOLD}`
);

const { value: batteryLevelUnderWarningEnabled } = await this.props.httpClient.get(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_BATTERY_LEVEL_WARNING_ENABLED}`
);

this.setState({
batteryLevelUnderWarningThreshold,
batteryLevelUnderWarningEnabled: batteryLevelUnderWarningEnabled === '1'
});
} catch (e) {
console.error(e);
}
};

updateBatteryLevelUnderWarningThreshold = async e => {
let { value, min, max } = e.target;
if (value !== undefined && value !== null && value !== '') {
value = Math.max(Number(min), Math.min(Number(max), Number(value)));
}

await this.setState({
batteryLevelUnderWarningThreshold: value,
savingBatteryLevelUnderWarning: true
});
try {
await this.props.httpClient.post(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_BATTERY_LEVEL_WARNING_THRESHOLD}`,
{
value
}
);
} catch (e) {
console.error(e);
}
await this.setState({
savingBatteryLevelUnderWarning: false
});
};

debouncedUpdateBatteryLevelUnderWarningThreshold = debounce(this.updateBatteryLevelUnderWarningThreshold, 200);

updateBatteryLevelUnderWarningEnabled = async () => {
const value = !this.state.batteryLevelUnderWarningEnabled;
await this.setState({
batteryLevelUnderWarningEnabled: value,
savingBatteryLevelUnderWarning: true
});
try {
await this.props.httpClient.post(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_BATTERY_LEVEL_WARNING_ENABLED}`,
{
value
}
);
} catch (e) {
console.error(e);
}
await this.setState({
savingBatteryLevelUnderWarning: false
});
};

componentDidMount() {
this.getBatteryLevelUnderWarning();
}

render({}, { batteryLevelUnderWarningThreshold, batteryLevelUnderWarningEnabled }) {
return (
<div class="card">
<h4 class="card-header d-flex flex-row justify-content-between">
<label
className={cx('mb-0', {
'text-muted': !batteryLevelUnderWarningEnabled
})}
>
<Text id="systemSettings.batteryLevel" />
</label>
<label className="custom-switch">
<input
type="checkbox"
name="active"
value="1"
className="custom-switch-input"
checked={batteryLevelUnderWarningEnabled}
onClick={this.updateBatteryLevelUnderWarningEnabled}
/>
<span class="custom-switch-indicator" />
</label>
</h4>
<div class="card-body">
<form className="">
<p
class={cx({
'text-muted': !batteryLevelUnderWarningEnabled
})}
>
<Text id="systemSettings.batteryLevelDescription" />
</p>
<div class="input-group">
<input
className="form-control"
type="number"
min="0"
max="100"
disabled={!batteryLevelUnderWarningEnabled}
value={batteryLevelUnderWarningThreshold}
onChange={this.debouncedUpdateBatteryLevelUnderWarningThreshold}
/>
<div class="input-group-append">
<span class="input-group-text">
<Text id="global.percent" />
</span>
</div>
</div>
</form>
</div>
</div>
);
}
}

export default connect('httpClient', null)(SettingsSystemBatteryLevelWarning);
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { connect } from 'unistore/preact';
import { Component } from 'preact';
import { Text } from 'preact-i18n';
import cx from 'classnames';

class SettingsSystemContainers extends Component {
render({ systemContainers }, {}) {
return (
<div class="card">
<h4 class="card-header">
<Text id="systemSettings.containers" />
</h4>
<div class="table-responsive" style={{ maxHeight: '200px' }}>
<table className="table table-hover table-outline table-vcenter text-nowrap card-table">
<thead>
<tr>
<th>
<Text id="systemSettings.containerName" />
</th>
<th>
<Text id="systemSettings.containerCreated" />
</th>
<th>
<Text id="systemSettings.containerStatus" />
</th>
</tr>
</thead>
<tbody>
{systemContainers &&
systemContainers.map(container => (
<tr>
<td>{container.name}</td>
<td>{container.created_at_formatted}</td>
<td>
<span
class={cx('badge', {
'badge-success': container.state === 'running',
'badge-warning': container.state !== 'running'
})}
>
<Text id={`systemSettings.containerState.${container.state}`} />
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
}

export default connect('systemContainers', null)(SettingsSystemContainers);
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { connect } from 'unistore/preact';
import { Component } from 'preact';
import { Text } from 'preact-i18n';

class SettingsSystemDatabaseCleaning extends Component {
constructor(props) {
super(props);
this.state = {
vacuumStarted: false
};
}

vacuumDatabase = async e => {
e.preventDefault();
this.setState({
vacuumStarted: true
});
try {
await this.props.httpClient.post('/api/v1/system/vacuum');
} catch (e) {
console.error(e);
}
};

render({}, { vacuumStarted }) {
return (
<div class="card">
<h4 class="card-header">
<Text id="systemSettings.vacuumDatabaseTitle" />
</h4>

<div class="card-body">
<form className="">
<p>
<Text id="systemSettings.vacuumDatabaseDescription" />
</p>
<p>
{vacuumStarted && (
<div class="alert alert-info">
<Text id="systemSettings.vacuumDatabaseStarted" />
</div>
)}
<button onClick={this.vacuumDatabase} className="btn btn-primary">
<Text id="systemSettings.vacuumDatabaseButton" />
</button>
</p>
</form>
</div>
</div>
);
}
}

export default connect('httpClient', null)(SettingsSystemDatabaseCleaning);
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { connect } from 'unistore/preact';
import { Component } from 'preact';
import { Text } from 'preact-i18n';
import { SYSTEM_VARIABLE_NAMES } from '../../../../../server/utils/constants';
import get from 'get-value';

class SettingsSystemKeepAggregatedStates extends Component {
getDeviceAggregateStateHistoryPreference = async () => {
try {
const { value } = await this.props.httpClient.get(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_AGGREGATE_STATE_HISTORY_IN_DAYS}`
);
this.setState({
deviceAggregateStateHistoryInDays: value
});
} catch (e) {
console.error(e);
const status = get(e, 'response.status');
if (status === 404) {
// Default value is -1
this.setState({
deviceAggregateStateHistoryInDays: '-1'
});
}
}
};

updateDeviceAggregateStateHistory = async e => {
await this.setState({
deviceAggregateStateHistoryInDays: e.target.value,
savingDeviceStateHistory: true
});
try {
await this.props.httpClient.post(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_AGGREGATE_STATE_HISTORY_IN_DAYS}`,
{
value: e.target.value
}
);
} catch (e) {
console.error(e);
}
await this.setState({
savingDeviceStateHistory: false
});
};

componentDidMount() {
this.getDeviceAggregateStateHistoryPreference();
}

render({}, { deviceAggregateStateHistoryInDays }) {
return (
<div class="card">
<h4 class="card-header">
<Text id="systemSettings.deviceAggregatesStateRetentionTime" />
</h4>

<div class="card-body">
<form className="">
<p>
<Text id="systemSettings.deviceAggregatesStateRetentionTimeDescription" />
</p>
<select
className="form-control"
value={deviceAggregateStateHistoryInDays}
onChange={this.updateDeviceAggregateStateHistory}
>
<option value="7">
<Text id="signup.preferences.deviceStateHistoryDuration.durationOneWeek" />
</option>
<option value="30">
<Text id="signup.preferences.deviceStateHistoryDuration.durationOneMonth" />
</option>
<option value="90">
<Text id="signup.preferences.deviceStateHistoryDuration.durationThreeMonth" />
</option>
<option value="180">
<Text id="signup.preferences.deviceStateHistoryDuration.durationSixMonths" />
</option>
<option value="365">
<Text id="signup.preferences.deviceStateHistoryDuration.durationOneYear" />
</option>
<option value="730">
<Text id="signup.preferences.deviceStateHistoryDuration.durationTwoYears" />
</option>
<option value="-1">
<Text id="signup.preferences.deviceStateHistoryDuration.unlimited" />
</option>
</select>
</form>
</div>
</div>
);
}
}

export default connect('httpClient', null)(SettingsSystemKeepAggregatedStates);
Loading

0 comments on commit aeddefc

Please sign in to comment.