mirror of https://github.com/vector-im/riot-web
Implement new widget API (#1201)
* Implement new widget API This allows clients to see who provisioned which widgets. * Update to make state_key the wid * Update to latest API * Only show widgets which have required fields * Don't constantly show apps dialog * Fix example to include data keypull/21833/head
parent
5c89d3303b
commit
cf158530f5
|
@ -143,41 +143,44 @@ Example:
|
||||||
|
|
||||||
get_widgets
|
get_widgets
|
||||||
-----------
|
-----------
|
||||||
Get a list of all widgets in the room. The response is the `content` field
|
Get a list of all widgets in the room. The response is an array
|
||||||
of the state event.
|
of state events.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
- `room_id` (String) is the room to get the widgets in.
|
- `room_id` (String) is the room to get the widgets in.
|
||||||
Response:
|
Response:
|
||||||
{
|
[
|
||||||
$widget_id: {
|
{
|
||||||
type: "example",
|
type: "im.vector.modular.widgets",
|
||||||
url: "http://widget.url",
|
state_key: "wid1",
|
||||||
name: "Example Widget",
|
content: {
|
||||||
data: {
|
type: "grafana",
|
||||||
key: "val"
|
url: "https://grafanaurl",
|
||||||
|
name: "dashboard",
|
||||||
|
data: {key: "val"}
|
||||||
}
|
}
|
||||||
},
|
room_id: “!foo:bar”,
|
||||||
$widget_id: { ... }
|
sender: "@alice:localhost"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
Example:
|
Example:
|
||||||
{
|
{
|
||||||
action: "get_widgets",
|
action: "get_widgets",
|
||||||
room_id: "!foo:bar",
|
room_id: "!foo:bar",
|
||||||
widget_id: "abc123",
|
response: [
|
||||||
url: "http://widget.url",
|
{
|
||||||
type: "example",
|
type: "im.vector.modular.widgets",
|
||||||
response: {
|
state_key: "wid1",
|
||||||
$widget_id: {
|
content: {
|
||||||
type: "example",
|
type: "grafana",
|
||||||
url: "http://widget.url",
|
url: "https://grafanaurl",
|
||||||
name: "Example Widget",
|
name: "dashboard",
|
||||||
data: {
|
data: {key: "val"}
|
||||||
key: "val"
|
|
||||||
}
|
}
|
||||||
},
|
room_id: “!foo:bar”,
|
||||||
$widget_id: { ... }
|
sender: "@alice:localhost"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -301,33 +304,17 @@ function setWidget(event, roomId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: same dance we do for power levels. It'd be nice if the JS SDK had helper methods to do this.
|
let content = {
|
||||||
client.getStateEvent(roomId, "im.vector.modular.widgets", "").then((widgets) => {
|
type: widgetType,
|
||||||
if (widgetUrl === null) {
|
url: widgetUrl,
|
||||||
delete widgets[widgetId];
|
name: widgetName,
|
||||||
}
|
data: widgetData,
|
||||||
else {
|
};
|
||||||
widgets[widgetId] = {
|
if (widgetUrl === null) { // widget is being deleted
|
||||||
type: widgetType,
|
content = {};
|
||||||
url: widgetUrl,
|
}
|
||||||
name: widgetName,
|
|
||||||
data: widgetData,
|
client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => {
|
||||||
};
|
|
||||||
}
|
|
||||||
return client.sendStateEvent(roomId, "im.vector.modular.widgets", widgets);
|
|
||||||
}, (err) => {
|
|
||||||
if (err.errcode === "M_NOT_FOUND") {
|
|
||||||
return client.sendStateEvent(roomId, "im.vector.modular.widgets", {
|
|
||||||
[widgetId]: {
|
|
||||||
type: widgetType,
|
|
||||||
url: widgetUrl,
|
|
||||||
name: widgetName,
|
|
||||||
data: widgetData,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}).done(() => {
|
|
||||||
sendResponse(event, {
|
sendResponse(event, {
|
||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
|
@ -337,7 +324,26 @@ function setWidget(event, roomId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWidgets(event, roomId) {
|
function getWidgets(event, roomId) {
|
||||||
returnStateEvent(event, roomId, "im.vector.modular.widgets", "");
|
const client = MatrixClientPeg.get();
|
||||||
|
if (!client) {
|
||||||
|
sendError(event, _t('You need to be logged in.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const room = client.getRoom(roomId);
|
||||||
|
if (!room) {
|
||||||
|
sendError(event, _t('This room is not recognised.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const stateEvents = room.currentState.getStateEvents("im.vector.modular.widgets");
|
||||||
|
// Only return widgets which have required fields
|
||||||
|
let widgetStateEvents = [];
|
||||||
|
stateEvents.forEach((ev) => {
|
||||||
|
if (ev.getContent().type && ev.getContent().url) {
|
||||||
|
widgetStateEvents.push(ev.event); // return the raw event
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sendResponse(event, widgetStateEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPlumbingState(event, roomId, status) {
|
function setPlumbingState(event, roomId, status) {
|
||||||
|
|
|
@ -275,8 +275,14 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldShowApps: function(room) {
|
_shouldShowApps: function(room) {
|
||||||
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets', '');
|
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
|
||||||
return appsStateEvents && Object.keys(appsStateEvents.getContent()).length > 0;
|
// any valid widget = show apps
|
||||||
|
for (let i = 0; i < appsStateEvents.length; i++) {
|
||||||
|
if (appsStateEvents[i].getContent().type && appsStateEvents[i].getContent().url) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
|
|
@ -91,24 +91,16 @@ export default React.createClass({
|
||||||
|
|
||||||
_onDeleteClick: function() {
|
_onDeleteClick: function() {
|
||||||
console.log("Delete widget %s", this.props.id);
|
console.log("Delete widget %s", this.props.id);
|
||||||
const appsStateEvents = this.props.room.currentState.getStateEvents('im.vector.modular.widgets', '');
|
MatrixClientPeg.get().sendStateEvent(
|
||||||
if (!appsStateEvents) {
|
this.props.room.roomId,
|
||||||
return;
|
'im.vector.modular.widgets',
|
||||||
}
|
{}, // empty content
|
||||||
const appsStateEvent = appsStateEvents.getContent();
|
this.props.id,
|
||||||
if (appsStateEvent[this.props.id]) {
|
).then(() => {
|
||||||
delete appsStateEvent[this.props.id];
|
console.log('Deleted widget');
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
}, (e) => {
|
||||||
this.props.room.roomId,
|
console.error('Failed to delete widget', e);
|
||||||
'im.vector.modular.widgets',
|
});
|
||||||
appsStateEvent,
|
|
||||||
'',
|
|
||||||
).then(() => {
|
|
||||||
console.log('Deleted widget');
|
|
||||||
}, (e) => {
|
|
||||||
console.error('Failed to delete widget', e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
formatAppTileName: function() {
|
formatAppTileName: function() {
|
||||||
|
|
|
@ -111,26 +111,6 @@ module.exports = React.createClass({
|
||||||
app.name = app.name || app.type;
|
app.name = app.name || app.type;
|
||||||
app.url = this.encodeUri(app.url, params);
|
app.url = this.encodeUri(app.url, params);
|
||||||
|
|
||||||
// switch(app.type) {
|
|
||||||
// case 'etherpad':
|
|
||||||
// app.queryParams = '?userName=' + this.props.userId +
|
|
||||||
// '&padId=' + this.props.room.roomId;
|
|
||||||
// break;
|
|
||||||
// case 'jitsi': {
|
|
||||||
//
|
|
||||||
// app.queryParams = '?confId=' + app.data.confId +
|
|
||||||
// '&displayName=' + encodeURIComponent(user.displayName) +
|
|
||||||
// '&avatarUrl=' + encodeURIComponent(MatrixClientPeg.get().mxcUrlToHttp(user.avatarUrl)) +
|
|
||||||
// '&email=' + encodeURIComponent(this.props.userId) +
|
|
||||||
// '&isAudioConf=' + app.data.isAudioConf;
|
|
||||||
//
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 'vrdemo':
|
|
||||||
// app.queryParams = '?roomAlias=' + encodeURIComponent(app.data.roomAlias);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -142,17 +122,15 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_getApps: function() {
|
_getApps: function() {
|
||||||
const appsStateEvents = this.props.room.currentState.getStateEvents('im.vector.modular.widgets', '');
|
const appsStateEvents = this.props.room.currentState.getStateEvents('im.vector.modular.widgets');
|
||||||
if (!appsStateEvents) {
|
if (!appsStateEvents) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const appsStateEvent = appsStateEvents.getContent();
|
|
||||||
if (Object.keys(appsStateEvent).length < 1) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(appsStateEvent).map((appId) => {
|
return appsStateEvents.filter((ev) => {
|
||||||
return this._initAppConfig(appId, appsStateEvent[appId]);
|
return ev.getContent().type && ev.getContent().url;
|
||||||
|
}).map((ev) => {
|
||||||
|
return this._initAppConfig(ev.getStateKey(), ev.getContent());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue