Skip to content

Commit

Permalink
Merge branch 'master' into intl
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Gilles authored Apr 19, 2021
2 parents 66f2e10 + 1d58b39 commit 1eb3079
Show file tree
Hide file tree
Showing 18 changed files with 343 additions and 103 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [v4.2.4](https://github.com/GladysAssistant/Gladys/compare/v4.2.3...v4.2.4)

> 16 April 2021
- Upgrade gladys-gateway-js to new version with more logs [`#1146`](https://github.com/GladysAssistant/Gladys/pull/1146)
- Fix zigbee2mqtt discover screen for Gladys Plus [`#1145`](https://github.com/GladysAssistant/Gladys/pull/1145)

#### [v4.2.3](https://github.com/GladysAssistant/Gladys/compare/v4.2.2...v4.2.3)

> 8 April 2021
- Revert "Localize all selects by passing a translation key as label (#1128)" [`#1131`](https://github.com/GladysAssistant/Gladys/pull/1131)
- Update CHANGELOG [`13c875c`](https://github.com/GladysAssistant/Gladys/commit/13c875ca9d2015622d9fda985872f313ac7968b7)

#### [v4.2.2](https://github.com/GladysAssistant/Gladys/compare/v4.2.1...v4.2.2)

> 7 April 2021
Expand Down
5 changes: 4 additions & 1 deletion front/src/config/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,10 @@
"bodyPlaceholder": "Body",
"headersLabel": "Headers",
"headersKeyPlaceholder": "Name",
"headersValuePlaceholder": "Value"
"headersValuePlaceholder": "Value",
"responseData": "Response",
"tryButton": "Try request",
"requestError": "An error happened while making the request. Are you sure parameters are right?"
}
},
"actions": {
Expand Down
5 changes: 4 additions & 1 deletion front/src/config/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,10 @@
"bodyPlaceholder": "Body",
"headersLabel": "Headers",
"headersKeyPlaceholder": "Nom",
"headersValuePlaceholder": "Valeur"
"headersValuePlaceholder": "Valeur",
"responseData": "Réponse",
"tryButton": "Essayer",
"requestError": "Une erreur est survenue lors de la requête. Êtes vous sûr d'avoir bien rempli le formulaire ?"
}
},
"actions": {
Expand Down
1 change: 1 addition & 0 deletions front/src/routes/scene/edit-scene/ActionCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ const ActionCard = ({ children, ...props }) => (
columnIndex={props.columnIndex}
index={props.index}
updateActionProperty={props.updateActionProperty}
setVariables={props.setVariables}
/>
)}
</div>
Expand Down
261 changes: 174 additions & 87 deletions front/src/routes/scene/edit-scene/actions/HttpRequest.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import { Component } from 'preact';
import { connect } from 'unistore/preact';
import { Text, Localizer } from 'preact-i18n';
import cx from 'classnames';
import update from 'immutability-helper';

const METHOD_WITH_BODY = ['post', 'patch', 'put'];

const getAllPropertiesObject = (obj, path = '', results = []) => {
Object.keys(obj).forEach(key => {
const value = obj[key];
const keyFormatted = Number.isInteger(parseInt(key, 10)) ? `[${key}]` : key;
if (typeof value === 'object') {
getAllPropertiesObject(value, `${path}${keyFormatted}.`, results);
} else {
results.push(path + keyFormatted);
}
});
return results;
};

class Header extends Component {
updateHeaderKey = e => {
this.props.updateHeader(this.props.index, {
Expand Down Expand Up @@ -57,7 +71,7 @@ class Header extends Component {
}
}

@connect('', {})
@connect('httpClient', {})
class HttpRequestAction extends Component {
handleChangeMethod = e => {
this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'method', e.target.value);
Expand Down Expand Up @@ -97,105 +111,178 @@ class HttpRequestAction extends Component {
});
this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'headers', newHeaderArray);
};
loadVariables = keys => {
const { columnIndex, index } = this.props;
const keysVariables = keys.map(key => {
const keyWithData = `data.${key}`;
return {
name: keyWithData,
type: 'http_request',
ready: true,
label: keyWithData
};
});
keysVariables.push({
name: 'status',
type: 'http_request',
ready: true,
label: 'status'
});
this.props.setVariables(columnIndex, index, keysVariables);
};
tryRequest = async e => {
e.preventDefault();
try {
await this.setState({ error: false, pending: true });
const { data, headers } = await this.props.httpClient.post('/api/v1/http/request', this.props.action);
let responseData = data;
const isJsonResponse = headers['content-type'].indexOf('application/json') !== -1;
if (isJsonResponse) {
responseData = JSON.stringify(data, null, 2);
}
this.setState({
apiTestResponse: responseData
});
if (isJsonResponse) {
const keys = getAllPropertiesObject(data);
this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'request_response_keys', keys);
this.loadVariables(keys);
}
await this.setState({ error: false, pending: false });
} catch (e) {
console.error(e);
await this.setState({ error: true, pending: false });
}
};
componentDidMount() {
if (!this.props.action.method) {
this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'method', 'post');
}
if (!this.props.action.headers) {
this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'headers', []);
}
if (this.props.action.request_response_keys) {
this.loadVariables(this.props.action.request_response_keys);
}
}
render(props) {
const displayBody = METHOD_WITH_BODY.includes(props.action.method);
return (
<div>
<p>
<Text id="editScene.actionsCard.httpRequest.description" />
</p>
<form>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.methodLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<select class="custom-select" value={props.action.method} onChange={this.handleChangeMethod}>
<option value="post">
<Text id="editScene.actionsCard.httpRequest.post" />
</option>
<option value="get">
<Text id="editScene.actionsCard.httpRequest.get" />
</option>
<option value="put">
<Text id="editScene.actionsCard.httpRequest.put" />
</option>
<option value="patch">
<Text id="editScene.actionsCard.httpRequest.patch" />
</option>
<option value="delete">
<Text id="editScene.actionsCard.httpRequest.delete" />
</option>
</select>
<div
class={cx('dimmer', {
active: this.state.pending
})}
>
<div class="loader" />
<div class="dimmer-content">
<p>
<Text id="editScene.actionsCard.httpRequest.description" />
</p>
<form>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.methodLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<select class="custom-select" value={props.action.method} onChange={this.handleChangeMethod}>
<option value="post">
<Text id="editScene.actionsCard.httpRequest.post" />
</option>
<option value="get">
<Text id="editScene.actionsCard.httpRequest.get" />
</option>
<option value="put">
<Text id="editScene.actionsCard.httpRequest.put" />
</option>
<option value="patch">
<Text id="editScene.actionsCard.httpRequest.patch" />
</option>
<option value="delete">
<Text id="editScene.actionsCard.httpRequest.delete" />
</option>
</select>
</div>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.urlLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<Localizer>
<input
type="text"
class="form-control"
value={props.action.url}
onChange={this.handleChangeUrl}
placeholder={<Text id="editScene.actionsCard.httpRequest.urlPlaceholder" />}
/>
</Localizer>
</div>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.headersLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
{props.action.headers &&
props.action.headers.map((header, index) => (
<Header
header={header}
index={index}
updateHeader={this.updateHeader}
deleteHeader={this.deleteHeader}
lastItem={index === props.action.headers.length - 1}
/>
))}
<button class="btn btn-secondary" onClick={this.addNewHeader}>
<i class="fe fe-plus" />
</button>
</div>
{displayBody && (
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.bodyLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<Localizer>
<textarea
type="text"
class="form-control"
value={props.action.body}
onChange={this.handleChangeBody}
placeholder={<Text id="editScene.actionsCard.httpRequest.bodyPlaceholder" />}
/>
</Localizer>
</div>
)}
{this.state.apiTestResponse && (
<div>
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.responseData" />
</label>
<pre>
<code>{this.state.apiTestResponse}</code>
</pre>
</div>
)}
{this.state.error && (
<div class="alert alert-danger">
<Text id="editScene.actionsCard.httpRequest.requestError" />
</div>
)}
<button class="btn btn-primary" onClick={this.tryRequest}>
<Text id="editScene.actionsCard.httpRequest.tryButton" />
</button>
</form>
</div>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.urlLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<Localizer>
<input
type="text"
class="form-control"
value={props.action.url}
onChange={this.handleChangeUrl}
placeholder={<Text id="editScene.actionsCard.httpRequest.urlPlaceholder" />}
/>
</Localizer>
</div>
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.headersLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
{props.action.headers &&
props.action.headers.map((header, index) => (
<Header
header={header}
index={index}
updateHeader={this.updateHeader}
deleteHeader={this.deleteHeader}
lastItem={index === props.action.headers.length - 1}
/>
))}
<button class="btn btn-secondary" onClick={this.addNewHeader}>
<i class="fe fe-plus" />
</button>
</div>
{displayBody && (
<div class="form-group">
<label class="form-label">
<Text id="editScene.actionsCard.httpRequest.bodyLabel" />
<span class="form-required">
<Text id="global.requiredField" />
</span>
</label>
<Localizer>
<textarea
type="text"
class="form-control"
value={props.action.body}
onChange={this.handleChangeBody}
placeholder={<Text id="editScene.actionsCard.httpRequest.bodyPlaceholder" />}
/>
</Localizer>
</div>
)}
</form>
</div>
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions front/src/utils/GatewaySession.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class GatewaySession {
}
});
this.ready = true;
this.websocketConnected = true;
this.dispatcher.dispatch('GLADYS_GATEWAY_CONNECTED');
}
}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gladys",
"version": "4.2.3",
"version": "4.2.4",
"description": "A privacy-first, open-source home assistant",
"main": "index.js",
"engines": {
Expand Down
Loading

0 comments on commit 1eb3079

Please sign in to comment.