Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warning system for battery level #1936

Merged
merged 5 commits into from Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion front/src/config/i18n/en.json
Expand Up @@ -2052,7 +2052,9 @@
"paused": "Paused",
"exited": "Exited",
"dead": "Dead"
}
},
"batteryLevel": "Battery level alert",
"batteryLevelDescription": "At 09:00 AM, only on Saturday, a message will be sent to all admins as soon as the battery level drops below the chosen percentage"
},
"newArea": {
"createNewZoneButton": "Create new zone",
Expand Down
4 changes: 3 additions & 1 deletion front/src/config/i18n/fr.json
Expand Up @@ -2053,7 +2053,9 @@
"paused": "En Pause",
"exited": "Arrêté",
"dead": "Mort"
}
},
"batteryLevel": "Alerte sur le niveau de batterie",
"batteryLevelDescription": "A 09h00, uniquement le samedi, un message sera envoyer à tous les admins dès que le niveau du batterie parsera en dessous du pourcentage choisi"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

"À 09h00, uniquement le samedi, un message sera envoyé à tous les admins dès que le niveau de la batterie parsera en dessous du pourcentage choisi"

},
"newArea": {
"createNewZoneButton": "Créer une zone",
Expand Down
@@ -0,0 +1,130 @@
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 => {
await this.setState({
batteryLevelUnderWarningThreshold: e.target.value,
savingBatteryLevelUnderWarning: true
});
try {
await this.props.httpClient.post(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_BATTERY_LEVEL_WARNING_THRESHOLD}`,
{
value: e.target.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, savingBatteryLevelUnderWarning }) {
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="1"
max="100"
disabled={savingBatteryLevelUnderWarning || !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);
@@ -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);
@@ -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);
@@ -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);