mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-08-31 06:02:09 +00:00
Re-wire the UI to support the new backend
This still doesn't allow editing, but it supports showing the widgets at least.
This commit is contained in:
parent
599fb80112
commit
4965b61f2d
@ -1,4 +1,4 @@
|
|||||||
import { GET, Path, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
import * as Promise from "bluebird";
|
||||||
import { ScalarService } from "../scalar/ScalarService";
|
import { ScalarService } from "../scalar/ScalarService";
|
||||||
import { DimensionStore } from "../../db/DimensionStore";
|
import { DimensionStore } from "../../db/DimensionStore";
|
||||||
@ -35,6 +35,13 @@ export class DimensionIntegrationsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("room/:roomId")
|
||||||
|
public getIntegrationsInRoom(@QueryParam("scalar_token") scalarToken: string, @PathParam("roomId") roomId: string) :Promise<IntegrationsResponse>{
|
||||||
|
console.log(roomId);
|
||||||
|
return this.getEnabledIntegrations(scalarToken);
|
||||||
|
}
|
||||||
|
|
||||||
private getIntegrations(isEnabledCheck?: boolean): Promise<IntegrationsResponse> {
|
private getIntegrations(isEnabledCheck?: boolean): Promise<IntegrationsResponse> {
|
||||||
const cachedResponse = DimensionIntegrationsService.integrationCache.get("integrations_" + isEnabledCheck);
|
const cachedResponse = DimensionIntegrationsService.integrationCache.get("integrations_" + isEnabledCheck);
|
||||||
if (cachedResponse) {
|
if (cachedResponse) {
|
||||||
|
@ -12,6 +12,7 @@ export default {
|
|||||||
"avatarUrl": {type: DataType.STRING, allowNull: false},
|
"avatarUrl": {type: DataType.STRING, allowNull: false},
|
||||||
"description": {type: DataType.STRING, allowNull: false},
|
"description": {type: DataType.STRING, allowNull: false},
|
||||||
"isEnabled": {type: DataType.BOOLEAN, allowNull: false},
|
"isEnabled": {type: DataType.BOOLEAN, allowNull: false},
|
||||||
|
"isPublic": {type: DataType.BOOLEAN, allowNull: false},
|
||||||
"optionsJson": {type: DataType.STRING, allowNull: true},
|
"optionsJson": {type: DataType.STRING, allowNull: true},
|
||||||
}))
|
}))
|
||||||
.then(() => queryInterface.bulkInsert("dimension_widgets", [
|
.then(() => queryInterface.bulkInsert("dimension_widgets", [
|
||||||
@ -64,6 +65,15 @@ export default {
|
|||||||
avatarUrl: "/img/avatars/twitch.png",
|
avatarUrl: "/img/avatars/twitch.png",
|
||||||
description: "Embed a Twitch livestream into your room.",
|
description: "Embed a Twitch livestream into your room.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "jitsi",
|
||||||
|
name: "Jitsi Conference",
|
||||||
|
isEnabled: true,
|
||||||
|
isPublic: true,
|
||||||
|
avatarUrl: "/img/avatars/jitsi.png",
|
||||||
|
description: "Hold a video conference with Jitsi Meet",
|
||||||
|
optionsJson: '{"jitsiDomain":"jitsi.riot.im", "scriptUrl":"https://jitsi.riot.im/libs/external_api.min.js"}',
|
||||||
|
},
|
||||||
]));
|
]));
|
||||||
},
|
},
|
||||||
down: (queryInterface: QueryInterface) => {
|
down: (queryInterface: QueryInterface) => {
|
||||||
|
@ -5,6 +5,7 @@ export class Integration {
|
|||||||
public category: "bot" | "complex-bot" | "bridge" | "widget";
|
public category: "bot" | "complex-bot" | "bridge" | "widget";
|
||||||
public type: string;
|
public type: string;
|
||||||
public requirements: IntegrationRequirement[];
|
public requirements: IntegrationRequirement[];
|
||||||
|
public isEncryptionSupported = false;
|
||||||
|
|
||||||
// These are meant to be set by us
|
// These are meant to be set by us
|
||||||
public displayName: string;
|
public displayName: string;
|
||||||
@ -26,5 +27,9 @@ export class Integration {
|
|||||||
export interface IntegrationRequirement {
|
export interface IntegrationRequirement {
|
||||||
condition: "publicRoom" | "canSendEventTypes";
|
condition: "publicRoom" | "canSendEventTypes";
|
||||||
argument: any;
|
argument: any;
|
||||||
|
|
||||||
|
// For publicRoom this is true or false (boolean)
|
||||||
|
// For canSendEventTypes this is an array of {isState: boolean, type: string}
|
||||||
|
// For userInRoom this is the user ID
|
||||||
expectedValue: any;
|
expectedValue: any;
|
||||||
}
|
}
|
@ -5,6 +5,11 @@ export interface EtherpadWidgetOptions {
|
|||||||
defaultUrl: string;
|
defaultUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface JitsiWidgetOptions {
|
||||||
|
jitsiDomain: string;
|
||||||
|
scriptUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class Widget extends Integration {
|
export class Widget extends Integration {
|
||||||
public options: any;
|
public options: any;
|
||||||
|
|
||||||
@ -14,8 +19,11 @@ export class Widget extends Integration {
|
|||||||
this.options = widgetRecord.optionsJson ? JSON.parse(widgetRecord.optionsJson) : {};
|
this.options = widgetRecord.optionsJson ? JSON.parse(widgetRecord.optionsJson) : {};
|
||||||
this.requirements = [{
|
this.requirements = [{
|
||||||
condition: "canSendEventTypes",
|
condition: "canSendEventTypes",
|
||||||
argument: ["im.vector.widget"],
|
argument: [{isState: true, type: "im.vector.widget"}],
|
||||||
expectedValue: true,
|
expectedValue: true,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
// Technically widgets are supported in encrypted rooms, although at risk.
|
||||||
|
this.isEncryptionSupported = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,6 +14,8 @@ export class MatrixOpenIdClient {
|
|||||||
"/_matrix/federation/v1/openid/userinfo",
|
"/_matrix/federation/v1/openid/userinfo",
|
||||||
{access_token: this.openId.access_token}
|
{access_token: this.openId.access_token}
|
||||||
).then(response => {
|
).then(response => {
|
||||||
|
// Annoyingly, the response isn't JSON for this
|
||||||
|
response = JSON.parse(response);
|
||||||
return response['sub'];
|
return response['sub'];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,14 @@ import { routing } from "./app.routing";
|
|||||||
import { createNewHosts, removeNgStyles } from "@angularclass/hmr";
|
import { createNewHosts, removeNgStyles } from "@angularclass/hmr";
|
||||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||||
import { RiotComponent } from "./riot/riot.component";
|
import { RiotComponent } from "./riot/riot.component";
|
||||||
import { ApiService } from "./shared/services/api.service";
|
|
||||||
import { UiSwitchModule } from "angular2-ui-switch";
|
import { UiSwitchModule } from "angular2-ui-switch";
|
||||||
import { ScalarService } from "./shared/services/scalar.service";
|
import { ScalarClientApiService } from "./shared/services/scalar-client-api.service";
|
||||||
import { ToasterModule } from "angular2-toaster";
|
import { ToasterModule } from "angular2-toaster";
|
||||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
import { ScalarCloseComponent } from "./riot/scalar-close/scalar-close.component";
|
import { ScalarCloseComponent } from "./riot/scalar-close/scalar-close.component";
|
||||||
import { IntegrationService } from "./shared/services/integration.service";
|
import { LegacyIntegrationService } from "./shared/services/legacy/integration.service";
|
||||||
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
||||||
import { ModalModule } from "ngx-modialog";
|
import { ModalModule } from "ngx-modialog";
|
||||||
import { IrcApiService } from "./shared/services/irc-api.service";
|
|
||||||
import { GenericWidgetWrapperComponent } from "./widget_wrappers/generic/generic.component";
|
import { GenericWidgetWrapperComponent } from "./widget_wrappers/generic/generic.component";
|
||||||
import { ToggleFullscreenDirective } from "./shared/directives/toggle-fullscreen.directive";
|
import { ToggleFullscreenDirective } from "./shared/directives/toggle-fullscreen.directive";
|
||||||
import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.component";
|
import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.component";
|
||||||
@ -30,8 +28,11 @@ import { BreadcrumbsModule } from "ng2-breadcrumbs";
|
|||||||
import { RiotHomeComponent } from "./riot/riot-home/home.component";
|
import { RiotHomeComponent } from "./riot/riot-home/home.component";
|
||||||
import { IntegrationBagComponent } from "./integration-bag/integration-bag.component";
|
import { IntegrationBagComponent } from "./integration-bag/integration-bag.component";
|
||||||
import { IntegrationComponent } from "./integration/integration.component";
|
import { IntegrationComponent } from "./integration/integration.component";
|
||||||
|
import { ScalarServerApiService } from "./shared/services/scalar-server-api.service";
|
||||||
|
import { DimensionApiService } from "./shared/services/dimension-api.service";
|
||||||
|
import { AdminApiService } from "./shared/services/admin-api.service";
|
||||||
|
|
||||||
const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigComponents();
|
const WIDGET_CONFIGURATION_COMPONENTS: any[] = LegacyIntegrationService.getAllConfigComponents();
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -68,10 +69,10 @@ const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigCo
|
|||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
ApiService,
|
ScalarClientApiService,
|
||||||
ScalarService,
|
ScalarServerApiService,
|
||||||
IntegrationService,
|
DimensionApiService,
|
||||||
IrcApiService,
|
AdminApiService,
|
||||||
{provide: Window, useValue: window},
|
{provide: Window, useValue: window},
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { CircleCiIntegration } from "../../shared/models/integration";
|
import { CircleCiIntegration } from "../../shared/models/legacyintegration";
|
||||||
import { ModalComponent, DialogRef } from "ngx-modialog";
|
import { ModalComponent, DialogRef } from "ngx-modialog";
|
||||||
import { ConfigModalContext } from "../../integration/integration.component";
|
import { ConfigModalContext } from "../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-circleci-config",
|
selector: "my-circleci-config",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Component, OnDestroy } from "@angular/core";
|
import { Component, OnDestroy } from "@angular/core";
|
||||||
import { IRCIntegration } from "../../shared/models/integration";
|
import { IRCIntegration } from "../../shared/models/legacyintegration";
|
||||||
import { ModalComponent, DialogRef } from "ngx-modialog";
|
import { ModalComponent, DialogRef } from "ngx-modialog";
|
||||||
import { ConfigModalContext } from "../../integration/integration.component";
|
import { ConfigModalContext } from "../../integration/integration.component";
|
||||||
import { IrcApiService } from "../../shared/services/irc-api.service";
|
import { IrcApiService } from "../../shared/services/legacy/irc-api.service";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { IntervalObservable } from "rxjs/observable/IntervalObservable";
|
import { IntervalObservable } from "rxjs/observable/IntervalObservable";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
import { Subscription } from "rxjs";
|
import { Subscription } from "rxjs";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { RSSIntegration } from "../../shared/models/integration";
|
import { RSSIntegration } from "../../shared/models/legacyintegration";
|
||||||
import { ModalComponent, DialogRef } from "ngx-modialog";
|
import { ModalComponent, DialogRef } from "ngx-modialog";
|
||||||
import { ConfigModalContext } from "../../integration/integration.component";
|
import { ConfigModalContext } from "../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-rss-config",
|
selector: "my-rss-config",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { TravisCiIntegration } from "../../shared/models/integration";
|
import { TravisCiIntegration } from "../../shared/models/legacyintegration";
|
||||||
import { ModalComponent, DialogRef } from "ngx-modialog";
|
import { ModalComponent, DialogRef } from "ngx-modialog";
|
||||||
import { ConfigModalContext } from "../../integration/integration.component";
|
import { ConfigModalContext } from "../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-travisci-config",
|
selector: "my-travisci-config",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { WIDGET_CUSTOM } from "../../../shared/models/widget";
|
import { WIDGET_CUSTOM } from "../../../shared/models/widget";
|
||||||
@ -15,7 +15,7 @@ export class CustomWidgetConfigComponent extends WidgetComponent implements Moda
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { WIDGET_ETHERPAD } from "../../../shared/models/widget";
|
import { WIDGET_ETHERPAD } from "../../../shared/models/widget";
|
||||||
import { EtherpadWidgetIntegration } from "../../../shared/models/integration";
|
import { EtherpadWidgetIntegration } from "../../../shared/models/legacyintegration";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-etherpadwidget-config",
|
selector: "my-etherpadwidget-config",
|
||||||
@ -18,7 +18,7 @@ export class EtherpadWidgetConfigComponent extends WidgetComponent implements Mo
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { EditableWidget, WIDGET_GOOGLE_CALENDAR } from "../../../shared/models/widget";
|
import { EditableWidget, WIDGET_GOOGLE_CALENDAR } from "../../../shared/models/widget";
|
||||||
@ -15,7 +15,7 @@ export class GoogleCalendarWidgetConfigComponent extends WidgetComponent impleme
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { WIDGET_GOOGLE_DOCS } from "../../../shared/models/widget";
|
import { WIDGET_GOOGLE_DOCS } from "../../../shared/models/widget";
|
||||||
@ -15,7 +15,7 @@ export class GoogleDocsWidgetConfigComponent extends WidgetComponent implements
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { EditableWidget, WIDGET_JITSI } from "../../../shared/models/widget";
|
import { EditableWidget, WIDGET_JITSI } from "../../../shared/models/widget";
|
||||||
import { JitsiWidgetIntegration } from "../../../shared/models/integration";
|
import { JitsiWidgetIntegration } from "../../../shared/models/legacyintegration";
|
||||||
import * as gobyInit from "goby";
|
import * as gobyInit from "goby";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export class JitsiWidgetConfigComponent extends WidgetComponent implements Modal
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { EditableWidget, WIDGET_TWITCH } from "../../../shared/models/widget";
|
import { EditableWidget, WIDGET_TWITCH } from "../../../shared/models/widget";
|
||||||
@ -15,7 +15,7 @@ export class TwitchWidgetConfigComponent extends WidgetComponent implements Moda
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ScalarService } from "../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../shared/services/scalar-client-api.service";
|
||||||
import { convertScalarWidgetsToDtos, EditableWidget } from "../../shared/models/widget";
|
import { convertScalarWidgetsToDtos, EditableWidget } from "../../shared/models/widget";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { Integration } from "../../shared/models/integration";
|
import { LegacyIntegration } from "../../shared/models/legacyintegration";
|
||||||
|
|
||||||
const SCALAR_WIDGET_LINKS = [
|
const SCALAR_WIDGET_LINKS = [
|
||||||
"https://scalar-staging.riot.im/scalar/api/widgets/__TYPE__.html?url=",
|
"https://scalar-staging.riot.im/scalar/api/widgets/__TYPE__.html?url=",
|
||||||
@ -23,9 +23,9 @@ export class WidgetComponent {
|
|||||||
|
|
||||||
constructor(window: Window,
|
constructor(window: Window,
|
||||||
protected toaster: ToasterService,
|
protected toaster: ToasterService,
|
||||||
protected scalarApi: ScalarService,
|
protected scalarApi: ScalarClientApiService,
|
||||||
public roomId: string,
|
public roomId: string,
|
||||||
public integration: Integration,
|
public integration: LegacyIntegration,
|
||||||
editWidgetId: string,
|
editWidgetId: string,
|
||||||
private widgetIds: string[],
|
private widgetIds: string[],
|
||||||
private defaultName: string,
|
private defaultName: string,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
import { WidgetComponent } from "../widget.component";
|
import { WidgetComponent } from "../widget.component";
|
||||||
import { ScalarService } from "../../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../../shared/services/scalar-client-api.service";
|
||||||
import { ConfigModalContext } from "../../../integration/integration.component";
|
import { ConfigModalContext } from "../../../integration/integration.component";
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { EditableWidget, WIDGET_YOUTUBE } from "../../../shared/models/widget";
|
import { EditableWidget, WIDGET_YOUTUBE } from "../../../shared/models/widget";
|
||||||
@ -17,7 +17,7 @@ export class YoutubeWidgetConfigComponent extends WidgetComponent implements Mod
|
|||||||
|
|
||||||
constructor(public dialog: DialogRef<ConfigModalContext>,
|
constructor(public dialog: DialogRef<ConfigModalContext>,
|
||||||
toaster: ToasterService,
|
toaster: ToasterService,
|
||||||
scalarService: ScalarService,
|
scalarService: ScalarClientApiService,
|
||||||
window: Window) {
|
window: Window) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
<div class="integration-bag">
|
<div class="integration-bag">
|
||||||
<!--<my-integration *ngFor="let integration of integrations"-->
|
|
||||||
<!--[integration]="integration" (selected)="onClick(integration)"></my-integration>-->
|
|
||||||
<div class="integration" *ngFor="let integration of integrations">
|
<div class="integration" *ngFor="let integration of integrations">
|
||||||
<img class="integration-avatar" [src]="getSafeUrl(integration.avatar)"/>
|
<img class="integration-avatar" [src]="getSafeUrl(integration.avatarUrl)"/>
|
||||||
<div class="integration-name">{{ integration.name }}</div>
|
<div class="integration-name">{{ integration.displayName }}</div>
|
||||||
<div class="integration-description">{{ integration.about }}</div>
|
<div class="integration-description">{{ integration.description }}</div>
|
||||||
<div class="integration-arrow"><i class="fa fa-chevron-right"></i></div>
|
<div class="integration-arrow"><i class="fa fa-chevron-right"></i></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -1,6 +1,7 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||||
import { Integration } from "../shared/models/integration";
|
import { LegacyIntegration } from "../shared/models/legacyintegration";
|
||||||
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
||||||
|
import { Integration } from "../shared/models/integration";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-integration-bag",
|
selector: "my-integration-bag",
|
||||||
@ -9,7 +10,7 @@ import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
|||||||
})
|
})
|
||||||
export class IntegrationBagComponent {
|
export class IntegrationBagComponent {
|
||||||
|
|
||||||
@Input() integrations: Integration[];
|
@Input() integrations: LegacyIntegration[];
|
||||||
@Output() integrationClicked: EventEmitter<Integration> = new EventEmitter<Integration>();
|
@Output() integrationClicked: EventEmitter<Integration> = new EventEmitter<Integration>();
|
||||||
|
|
||||||
constructor(private sanitizer: DomSanitizer) {
|
constructor(private sanitizer: DomSanitizer) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||||
import { Integration } from "../shared/models/integration";
|
import { LegacyIntegration } from "../shared/models/legacyintegration";
|
||||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||||
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
||||||
|
|
||||||
export class ConfigModalContext extends BSModalContext {
|
export class ConfigModalContext extends BSModalContext {
|
||||||
public integration: Integration;
|
public integration: LegacyIntegration;
|
||||||
public roomId: string;
|
public roomId: string;
|
||||||
public userId: string;
|
public userId: string;
|
||||||
public scalarToken: string;
|
public scalarToken: string;
|
||||||
@ -18,7 +18,7 @@ export class ConfigModalContext extends BSModalContext {
|
|||||||
})
|
})
|
||||||
export class IntegrationComponent {
|
export class IntegrationComponent {
|
||||||
|
|
||||||
@Input() integration: Integration;
|
@Input() integration: LegacyIntegration;
|
||||||
@Output() selected: EventEmitter<any> = new EventEmitter<any>();
|
@Output() selected: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
constructor(private sanitizer: DomSanitizer) {
|
constructor(private sanitizer: DomSanitizer) {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Component, ViewChildren } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { IntegrationService } from "../../shared/services/integration.service";
|
|
||||||
import { IntegrationComponent } from "../../integration/integration.component";
|
|
||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { Integration } from "../../shared/models/integration";
|
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ScalarClientApiService } from "../../shared/services/scalar-client-api.service";
|
||||||
import { ScalarService } from "../../shared/services/scalar.service";
|
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
|
import { ScalarServerApiService } from "../../shared/services/scalar-server-api.service";
|
||||||
|
import { AuthedApi } from "../../shared/services/AuthedApi";
|
||||||
|
import { DimensionApiService } from "../../shared/services/dimension-api.service";
|
||||||
|
import { Integration, IntegrationRequirement } from "../../shared/models/integration";
|
||||||
|
import { IntegrationService } from "../../shared/services/integration.service";
|
||||||
|
|
||||||
const CATEGORY_MAP = {
|
const CATEGORY_MAP = {
|
||||||
"Widgets": ["widget"],
|
"Widgets": ["widget"],
|
||||||
@ -20,14 +21,11 @@ const CATEGORY_MAP = {
|
|||||||
styleUrls: ["./home.component.scss"],
|
styleUrls: ["./home.component.scss"],
|
||||||
})
|
})
|
||||||
export class RiotHomeComponent {
|
export class RiotHomeComponent {
|
||||||
@ViewChildren(IntegrationComponent) integrationComponents: Array<IntegrationComponent>;
|
|
||||||
|
|
||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
public isError = false;
|
public isError = false;
|
||||||
public errorMessage: string;
|
public errorMessage: string;
|
||||||
public isRoomEncrypted: boolean;
|
public isRoomEncrypted: boolean;
|
||||||
|
|
||||||
private scalarToken: string;
|
|
||||||
private roomId: string;
|
private roomId: string;
|
||||||
private userId: string;
|
private userId: string;
|
||||||
private requestedScreen: string = null;
|
private requestedScreen: string = null;
|
||||||
@ -36,8 +34,9 @@ export class RiotHomeComponent {
|
|||||||
private categoryMap: { [categoryName: string]: string[] } = CATEGORY_MAP;
|
private categoryMap: { [categoryName: string]: string[] } = CATEGORY_MAP;
|
||||||
|
|
||||||
constructor(private activatedRoute: ActivatedRoute,
|
constructor(private activatedRoute: ActivatedRoute,
|
||||||
private api: ApiService,
|
private scalarApi: ScalarServerApiService,
|
||||||
private scalar: ScalarService,
|
private scalar: ScalarClientApiService,
|
||||||
|
private dimensionApi: DimensionApiService,
|
||||||
private toaster: ToasterService) {
|
private toaster: ToasterService) {
|
||||||
let params: any = this.activatedRoute.snapshot.queryParams;
|
let params: any = this.activatedRoute.snapshot.queryParams;
|
||||||
|
|
||||||
@ -51,9 +50,10 @@ export class RiotHomeComponent {
|
|||||||
this.errorMessage = "Unable to load Dimension - missing room ID or token.";
|
this.errorMessage = "Unable to load Dimension - missing room ID or token.";
|
||||||
} else {
|
} else {
|
||||||
this.roomId = params.room_id;
|
this.roomId = params.room_id;
|
||||||
this.scalarToken = params.scalar_token;
|
AuthedApi.SCALAR_TOKEN = params.scalar_token;
|
||||||
|
|
||||||
this.api.getTokenOwner(params.scalar_token).then(userId => {
|
this.scalarApi.getAccount().then(response => {
|
||||||
|
const userId = response.user_id;
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
console.error("No user returned for token. Is the token registered in Dimension?");
|
console.error("No user returned for token. Is the token registered in Dimension?");
|
||||||
this.isError = true;
|
this.isError = true;
|
||||||
@ -89,31 +89,42 @@ export class RiotHomeComponent {
|
|||||||
return this.integrationsForCategory[category];
|
return this.integrationsForCategory[category];
|
||||||
}
|
}
|
||||||
|
|
||||||
public modifyIntegration(integration: Integration) {
|
private getIntegrations(): Integration[] {
|
||||||
console.log(this.userId + " is trying to modify " + integration.name);
|
const result: Integration[] = [];
|
||||||
|
|
||||||
if (integration.hasAdditionalConfig) {
|
for (const category of this.getCategories()) {
|
||||||
// TODO: Navigate to edit screen
|
for (const integration of this.getIntegrationsIn(category)) {
|
||||||
console.log("EDIT SCREEN FOR " + integration.name);
|
result.push(integration);
|
||||||
} else {
|
}
|
||||||
// It's a flip-a-bit (simple bot)
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public modifyIntegration(integration: Integration) {
|
||||||
|
console.log(this.userId + " is trying to modify " + integration.displayName);
|
||||||
|
|
||||||
|
if (integration.category === "bot") {
|
||||||
|
// It's a bot
|
||||||
// TODO: "Are you sure?" dialog
|
// TODO: "Are you sure?" dialog
|
||||||
|
|
||||||
let promise = null;
|
// let promise = null;
|
||||||
if (!integration.isEnabled) {
|
const promise = Promise.resolve();
|
||||||
promise = this.scalar.inviteUser(this.roomId, integration.userId);
|
// if (!integration._inRoom) {
|
||||||
} else promise = this.api.removeIntegration(this.roomId, integration.type, integration.integrationType, this.scalarToken);
|
// promise = this.scalar.inviteUser(this.roomId, integration.userId);
|
||||||
|
// } else promise = this.api.removeIntegration(this.roomId, integration.type, integration.integrationType, this.scalarToken);
|
||||||
// We set this ahead of the promise for debouncing
|
// We set this ahead of the promise for debouncing
|
||||||
integration.isEnabled = !integration.isEnabled;
|
|
||||||
integration.isUpdating = true;
|
integration._inRoom = !integration._inRoom;
|
||||||
|
integration._isUpdating = true;
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
integration.isUpdating = false;
|
integration._isUpdating = false;
|
||||||
if (integration.isEnabled) this.toaster.pop("success", integration.name + " was invited to the room");
|
if (integration._inRoom) this.toaster.pop("success", integration.displayName + " was invited to the room");
|
||||||
else this.toaster.pop("success", integration.name + " was removed from the room");
|
else this.toaster.pop("success", integration.displayName + " was removed from the room");
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
integration.isEnabled = !integration.isEnabled; // revert the status change
|
integration._inRoom = !integration._inRoom; // revert the status change
|
||||||
integration.isUpdating = false;
|
integration._isUpdating = false;
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
let errorMessage = null;
|
let errorMessage = null;
|
||||||
@ -122,31 +133,27 @@ export class RiotHomeComponent {
|
|||||||
if (!errorMessage) errorMessage = "Could not update integration status";
|
if (!errorMessage) errorMessage = "Could not update integration status";
|
||||||
|
|
||||||
this.toaster.pop("error", errorMessage);
|
this.toaster.pop("error", errorMessage);
|
||||||
})
|
});
|
||||||
|
} else {
|
||||||
|
// TODO: Navigate to edit screen
|
||||||
|
console.log("EDIT SCREEN FOR " + integration.displayName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private prepareIntegrations() {
|
private prepareIntegrations() {
|
||||||
this.scalar.isRoomEncrypted(this.roomId).then(payload => {
|
this.scalar.isRoomEncrypted(this.roomId).then(payload => {
|
||||||
this.isRoomEncrypted = payload.response;
|
this.isRoomEncrypted = payload.response;
|
||||||
return this.api.getIntegrations(this.roomId, this.scalarToken);
|
return this.dimensionApi.getIntegrations(this.roomId);
|
||||||
}).then(integrations => {
|
}).then(response => {
|
||||||
|
const integrations: Integration[] = _.flatten(Object.keys(response).map(k => response[k]));
|
||||||
const supportedIntegrations: Integration[] = _.filter(integrations, i => IntegrationService.isSupported(i));
|
const supportedIntegrations: Integration[] = _.filter(integrations, i => IntegrationService.isSupported(i));
|
||||||
|
|
||||||
for (const integration of supportedIntegrations) {
|
|
||||||
// Widgets technically support encrypted rooms, so unless they explicitly declare that
|
|
||||||
// they don't, we'll assume they do. A warning about adding widgets in encrypted rooms
|
|
||||||
// is displayed to users elsewhere.
|
|
||||||
if (integration.type === "widget" && integration.supportsEncryptedRooms !== false)
|
|
||||||
integration.supportsEncryptedRooms = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flag integrations that aren't supported in encrypted rooms
|
// Flag integrations that aren't supported in encrypted rooms
|
||||||
if (this.isRoomEncrypted) {
|
if (this.isRoomEncrypted) {
|
||||||
for (const integration of supportedIntegrations) {
|
for (const integration of supportedIntegrations) {
|
||||||
if (!integration.supportsEncryptedRooms) {
|
if (!integration.isEncryptionSupported) {
|
||||||
integration.isSupported = false;
|
integration._isSupported = false;
|
||||||
integration.notSupportedReason = "This integration is not supported in encrypted rooms";
|
integration._notSupportedReason = "This integration is not supported in encrypted rooms";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +161,7 @@ export class RiotHomeComponent {
|
|||||||
// Set up the categories
|
// Set up the categories
|
||||||
for (const category of Object.keys(this.categoryMap)) {
|
for (const category of Object.keys(this.categoryMap)) {
|
||||||
const supportedTypes = this.categoryMap[category];
|
const supportedTypes = this.categoryMap[category];
|
||||||
this.integrationsForCategory[category] = _.filter(supportedIntegrations, i => supportedTypes.indexOf(i.type) !== -1);
|
this.integrationsForCategory[category] = _.filter(supportedIntegrations, i => supportedTypes.indexOf(i.category) !== -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = supportedIntegrations.map(i => this.updateIntegrationState(i));
|
let promises = supportedIntegrations.map(i => this.updateIntegrationState(i));
|
||||||
@ -173,92 +180,57 @@ export class RiotHomeComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private tryOpenConfigScreen() {
|
private tryOpenConfigScreen() {
|
||||||
|
let category = null;
|
||||||
let type = null;
|
let type = null;
|
||||||
let integrationType = null;
|
|
||||||
if (!this.requestedScreen) return;
|
if (!this.requestedScreen) return;
|
||||||
|
|
||||||
const targetIntegration = IntegrationService.getIntegrationForScreen(this.requestedScreen);
|
const targetIntegration = IntegrationService.getIntegrationForScreen(this.requestedScreen);
|
||||||
if (targetIntegration) {
|
if (targetIntegration) {
|
||||||
|
category = targetIntegration.category;
|
||||||
type = targetIntegration.type;
|
type = targetIntegration.type;
|
||||||
integrationType = targetIntegration.integrationType;
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Unknown screen requested: " + this.requestedScreen);
|
console.log("Unknown screen requested: " + this.requestedScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
let opened = false;
|
for (const integration of this.getIntegrations()) {
|
||||||
this.integrationComponents.forEach(component => {
|
if (integration.category === category && integration.type === type) {
|
||||||
if (opened) return;
|
console.log("Configuring integration " + this.requestedIntegration + " category=" + category + " type=" + type);
|
||||||
if (component.integration.type !== type || component.integration.integrationType !== integrationType) return;
|
// TODO: Actually edit integration
|
||||||
console.log("Configuring integration " + this.requestedIntegration + " type=" + type + " integrationType=" + integrationType);
|
return;
|
||||||
//component.configureIntegration(this.requestedIntegration);
|
}
|
||||||
// TODO: Support editing integrations
|
|
||||||
opened = true;
|
|
||||||
});
|
|
||||||
if (!opened) {
|
|
||||||
console.log("Failed to find integration component for type=" + type + " integrationType=" + integrationType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Failed to find integration component for category=" + category + " type=" + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateIntegrationState(integration: Integration) {
|
private updateIntegrationState(integration: Integration) {
|
||||||
integration.hasAdditionalConfig = IntegrationService.hasConfig(integration);
|
if (!integration.requirements) return;
|
||||||
|
|
||||||
if (integration.type === "widget") {
|
let promises = integration.requirements.map(r => this.checkRequirement(r));
|
||||||
if (!integration.requirements) integration.requirements = {};
|
|
||||||
integration.requirements["canSetWidget"] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the integration has requirements, then we'll check those instead of anything else
|
return Promise.all(promises).then(() => {
|
||||||
if (integration.requirements) {
|
integration._isSupported = true;
|
||||||
let keys = _.keys(integration.requirements);
|
integration._notSupportedReason = null;
|
||||||
let promises = [];
|
}, error => {
|
||||||
|
|
||||||
for (let key of keys) {
|
|
||||||
let requirement = this.checkRequirement(integration, key);
|
|
||||||
promises.push(requirement);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
|
||||||
integration.isSupported = true;
|
|
||||||
integration.notSupportedReason = null;
|
|
||||||
}, error => {
|
|
||||||
console.error(error);
|
|
||||||
integration.isSupported = false;
|
|
||||||
integration.notSupportedReason = error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// The integration doesn't have requirements, so we'll just make sure the bot user can be retrieved.
|
|
||||||
return this.scalar.getMembershipState(this.roomId, integration.userId).then(payload => {
|
|
||||||
if (payload.response) {
|
|
||||||
integration.isSupported = true;
|
|
||||||
integration.notSupportedReason = null;
|
|
||||||
integration.isEnabled = (payload.response.membership === "join" || payload.response.membership === "invite");
|
|
||||||
} else {
|
|
||||||
console.error("No response received to membership query of " + integration.userId);
|
|
||||||
integration.isSupported = false;
|
|
||||||
integration.notSupportedReason = "Unable to query membership state for this bot";
|
|
||||||
}
|
|
||||||
}, (error) => {
|
|
||||||
console.error(error);
|
console.error(error);
|
||||||
integration.isSupported = false;
|
integration._isSupported = false;
|
||||||
integration.notSupportedReason = "Unable to query membership state for this bot";
|
integration._notSupportedReason = error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkRequirement(integration: Integration, key: string) {
|
private checkRequirement(requirement: IntegrationRequirement) {
|
||||||
let requirement = integration.requirements[key];
|
switch (requirement.condition) {
|
||||||
|
case "publicRoom":
|
||||||
switch (key) {
|
|
||||||
case "joinRule":
|
|
||||||
return this.scalar.getJoinRule(this.roomId).then(payload => {
|
return this.scalar.getJoinRule(this.roomId).then(payload => {
|
||||||
if (!payload.response) {
|
if (!payload.response) {
|
||||||
return Promise.reject("Could not communicate with Riot");
|
return Promise.reject("Could not communicate with Riot");
|
||||||
}
|
}
|
||||||
return payload.response.join_rule === requirement
|
const isPublic = payload.response.join_rule === "public";
|
||||||
? Promise.resolve()
|
if (isPublic !== requirement.expectedValue) {
|
||||||
: Promise.reject("The room must be " + requirement + " to use this integration.");
|
return Promise.reject("The room must be " + (isPublic ? "non-public" : "public") + " to use this integration");
|
||||||
|
} else return Promise.resolve();
|
||||||
});
|
});
|
||||||
case "canSetWidget":
|
case "canSendEventTypes":
|
||||||
const processPayload = payload => {
|
const processPayload = payload => {
|
||||||
const response = <any>payload.response;
|
const response = <any>payload.response;
|
||||||
if (response === true) return Promise.resolve();
|
if (response === true) return Promise.resolve();
|
||||||
@ -266,9 +238,17 @@ export class RiotHomeComponent {
|
|||||||
return Promise.reject("You cannot modify widgets in this room");
|
return Promise.reject("You cannot modify widgets in this room");
|
||||||
return Promise.reject("Error communicating with Riot");
|
return Promise.reject("Error communicating with Riot");
|
||||||
};
|
};
|
||||||
return this.scalar.canSendEvent(this.roomId, "im.vector.modular.widgets", true).then(processPayload).catch(processPayload);
|
|
||||||
|
let promiseChain = Promise.resolve();
|
||||||
|
requirement.argument.forEach(e => promiseChain = promiseChain.then(() => this.scalar.canSendEvent(this.roomId, e.type, e.isState).then(processPayload).catch(processPayload)));
|
||||||
|
return promiseChain.then(() => {
|
||||||
|
if (!requirement.expectedValue) return Promise.reject("Expected to not be able to send specific event types");
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
if (requirement.expectedValue) return Promise.reject("Expected to be able to send specific event types");
|
||||||
|
});
|
||||||
default:
|
default:
|
||||||
return Promise.reject("Requirement '" + key + "' not found");
|
return Promise.reject("Requirement '" + requirement.condition + "' not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { ScalarService } from "../../shared/services/scalar.service";
|
import { ScalarClientApiService } from "../../shared/services/scalar-client-api.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "my-scalar-close",
|
selector: "my-scalar-close",
|
||||||
@ -8,7 +8,7 @@ import { ScalarService } from "../../shared/services/scalar.service";
|
|||||||
})
|
})
|
||||||
export class ScalarCloseComponent {
|
export class ScalarCloseComponent {
|
||||||
|
|
||||||
constructor(private scalar: ScalarService) {
|
constructor(private scalar: ScalarClientApiService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeScalar() {
|
public closeScalar() {
|
||||||
|
5
web/app/shared/models/dimension_responses.ts
Normal file
5
web/app/shared/models/dimension_responses.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Widget } from "./integration";
|
||||||
|
|
||||||
|
export interface DimensionIntegrationsResponse {
|
||||||
|
widgets: Widget[];
|
||||||
|
}
|
@ -1,49 +1,40 @@
|
|||||||
export interface Integration {
|
export interface Integration {
|
||||||
// These are from the server
|
category: "bot" | "complex-bot" | "bridge" | "widget";
|
||||||
type: string;
|
type: string;
|
||||||
integrationType: string;
|
requirements: IntegrationRequirement[];
|
||||||
userId: string;
|
isEncryptionSupported: boolean;
|
||||||
name: string;
|
displayName: string;
|
||||||
avatar: string;
|
avatarUrl: string;
|
||||||
about: string; // nullable
|
description: string;
|
||||||
supportsEncryptedRooms: boolean;
|
isEnabled: boolean;
|
||||||
requirements: any; // nullable
|
isPublic: boolean;
|
||||||
|
|
||||||
// These are set in the UI
|
// Used by us
|
||||||
isSupported: boolean;
|
_inRoom: boolean;
|
||||||
notSupportedReason: string;
|
_isUpdating: boolean;
|
||||||
hasAdditionalConfig: boolean;
|
_isSupported: boolean;
|
||||||
isEnabled: boolean; // for the flip-a-bit integrations
|
_notSupportedReason: string;
|
||||||
isUpdating: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RSSIntegration extends Integration {
|
export interface Widget extends Integration {
|
||||||
feeds: string[];
|
options: any;
|
||||||
immutableFeeds: { url: string, ownerId: string }[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TravisCiIntegration extends Integration {
|
export interface EtherpadWidget extends Widget {
|
||||||
repoTemplates: { repoKey: string, template: string, newTemplate: string }[]; // newTemplate is local
|
options: {
|
||||||
immutableRepoTemplates: { repoKey: string, template: string, ownerId: string }[];
|
defaultUrl: string;
|
||||||
webhookUrl: string; // immutable
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CircleCiIntegration extends Integration {
|
export interface JitsiWidget extends Widget {
|
||||||
repoTemplates: { repoKey: string, template: string, newTemplate: string }[]; // newTemplate is local
|
options: {
|
||||||
immutableRepoTemplates: { repoKey: string, template: string, ownerId: string }[];
|
jitsiDomain: string;
|
||||||
webhookUrl: string; // immutable
|
scriptUrl: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRCIntegration extends Integration {
|
export interface IntegrationRequirement {
|
||||||
availableNetworks: { name: string, id: string }[];
|
condition: "publicRoom" | "canSendEventTypes";
|
||||||
channels: { [networkId: string]: string[] };
|
argument: any;
|
||||||
}
|
expectedValue: any;
|
||||||
|
|
||||||
export interface EtherpadWidgetIntegration extends Integration {
|
|
||||||
defaultUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface JitsiWidgetIntegration extends Integration {
|
|
||||||
jitsiDomain: string;
|
|
||||||
scriptUrl: string
|
|
||||||
}
|
}
|
49
web/app/shared/models/legacyintegration.ts
Normal file
49
web/app/shared/models/legacyintegration.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
export interface LegacyIntegration {
|
||||||
|
// These are from the server
|
||||||
|
type: string;
|
||||||
|
integrationType: string;
|
||||||
|
userId: string;
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
about: string; // nullable
|
||||||
|
supportsEncryptedRooms: boolean;
|
||||||
|
requirements: any; // nullable
|
||||||
|
|
||||||
|
// These are set in the UI
|
||||||
|
isSupported: boolean;
|
||||||
|
notSupportedReason: string;
|
||||||
|
hasAdditionalConfig: boolean;
|
||||||
|
isEnabled: boolean; // for the flip-a-bit integrations
|
||||||
|
isUpdating: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RSSIntegration extends LegacyIntegration {
|
||||||
|
feeds: string[];
|
||||||
|
immutableFeeds: { url: string, ownerId: string }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TravisCiIntegration extends LegacyIntegration {
|
||||||
|
repoTemplates: { repoKey: string, template: string, newTemplate: string }[]; // newTemplate is local
|
||||||
|
immutableRepoTemplates: { repoKey: string, template: string, ownerId: string }[];
|
||||||
|
webhookUrl: string; // immutable
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CircleCiIntegration extends LegacyIntegration {
|
||||||
|
repoTemplates: { repoKey: string, template: string, newTemplate: string }[]; // newTemplate is local
|
||||||
|
immutableRepoTemplates: { repoKey: string, template: string, ownerId: string }[];
|
||||||
|
webhookUrl: string; // immutable
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRCIntegration extends LegacyIntegration {
|
||||||
|
availableNetworks: { name: string, id: string }[];
|
||||||
|
channels: { [networkId: string]: string[] };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EtherpadWidgetIntegration extends LegacyIntegration {
|
||||||
|
defaultUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JitsiWidgetIntegration extends LegacyIntegration {
|
||||||
|
jitsiDomain: string;
|
||||||
|
scriptUrl: string
|
||||||
|
}
|
3
web/app/shared/models/scalar_server_responses.ts
Normal file
3
web/app/shared/models/scalar_server_responses.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export interface ScalarAccountResponse {
|
||||||
|
user_id: string;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { WidgetsResponse } from "./scalar_responses";
|
import { WidgetsResponse } from "./scalar_client_responses";
|
||||||
|
|
||||||
export const WIDGET_CUSTOM = ["customwidget", "dimension-customwidget"];
|
export const WIDGET_CUSTOM = ["customwidget", "dimension-customwidget"];
|
||||||
export const WIDGET_ETHERPAD = ["etherpad", "dimension-etherpad"];
|
export const WIDGET_ETHERPAD = ["etherpad", "dimension-etherpad"];
|
||||||
|
15
web/app/shared/services/AuthedApi.ts
Normal file
15
web/app/shared/services/AuthedApi.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Http, Response } from "@angular/http";
|
||||||
|
import { Observable } from "rxjs/Observable";
|
||||||
|
|
||||||
|
export class AuthedApi {
|
||||||
|
public static SCALAR_TOKEN: string = null;
|
||||||
|
|
||||||
|
constructor(protected http: Http) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected authedGet(url: string, qs?: any): Observable<Response> {
|
||||||
|
if (!qs) qs = {};
|
||||||
|
qs["scalar_token"] = AuthedApi.SCALAR_TOKEN;
|
||||||
|
return this.http.get(url, {params: qs});
|
||||||
|
}
|
||||||
|
}
|
10
web/app/shared/services/admin-api.service.ts
Normal file
10
web/app/shared/services/admin-api.service.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Http } from "@angular/http";
|
||||||
|
import { AuthedApi } from "./AuthedApi";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdminApiService extends AuthedApi {
|
||||||
|
constructor(http: Http) {
|
||||||
|
super(http);
|
||||||
|
}
|
||||||
|
}
|
15
web/app/shared/services/dimension-api.service.ts
Normal file
15
web/app/shared/services/dimension-api.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Http } from "@angular/http";
|
||||||
|
import { AuthedApi } from "./AuthedApi";
|
||||||
|
import { DimensionIntegrationsResponse } from "../models/dimension_responses";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DimensionApiService extends AuthedApi {
|
||||||
|
constructor(http: Http) {
|
||||||
|
super(http);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIntegrations(roomId: string): Promise<DimensionIntegrationsResponse> {
|
||||||
|
return this.authedGet("/api/v1/dimension/integrations/room/" + roomId).map(r => r.json()).toPromise();
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,9 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Component, Injectable } from "@angular/core";
|
||||||
import { Integration } from "../models/integration";
|
|
||||||
import { RssConfigComponent } from "../../configs/rss/rss-config.component";
|
|
||||||
import { ContainerContent } from "ngx-modialog";
|
|
||||||
import { IrcConfigComponent } from "../../configs/irc/irc-config.component";
|
|
||||||
import { TravisCiConfigComponent } from "../../configs/travisci/travisci-config.component";
|
|
||||||
import { CustomWidgetConfigComponent } from "../../configs/widget/custom_widget/custom_widget-config.component";
|
|
||||||
import { YoutubeWidgetConfigComponent } from "../../configs/widget/youtube/youtube-config.component";
|
|
||||||
import { TwitchWidgetConfigComponent } from "../../configs/widget/twitch/twitch-config.component";
|
|
||||||
import { EtherpadWidgetConfigComponent } from "../../configs/widget/etherpad/etherpad-config.component";
|
|
||||||
import { JitsiWidgetConfigComponent } from "../../configs/widget/jitsi/jitsi-config.component";
|
|
||||||
import {
|
import {
|
||||||
WIDGET_CUSTOM, WIDGET_ETHERPAD, WIDGET_GOOGLE_CALENDAR, WIDGET_GOOGLE_DOCS, WIDGET_JITSI, WIDGET_TWITCH,
|
WIDGET_CUSTOM, WIDGET_ETHERPAD, WIDGET_GOOGLE_CALENDAR, WIDGET_GOOGLE_DOCS, WIDGET_JITSI, WIDGET_TWITCH,
|
||||||
WIDGET_YOUTUBE
|
WIDGET_YOUTUBE
|
||||||
} from "../models/widget";
|
} from "../models/widget";
|
||||||
import { GoogleDocsWidgetConfigComponent } from "../../configs/widget/googledocs/googledocs-config.component";
|
import { Integration } from "../models/integration";
|
||||||
import { GoogleCalendarWidgetConfigComponent } from "../../configs/widget/googlecalendar/googlecalendar-config.component";
|
|
||||||
import { CircleCiConfigComponent } from "../../configs/circleci/circleci-config.component";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IntegrationService {
|
export class IntegrationService {
|
||||||
@ -24,53 +12,53 @@ export class IntegrationService {
|
|||||||
"bot": {}, // empty == supported
|
"bot": {}, // empty == supported
|
||||||
"complex-bot": {
|
"complex-bot": {
|
||||||
"rss": {
|
"rss": {
|
||||||
component: RssConfigComponent,
|
//component: RssConfigComponent,
|
||||||
},
|
},
|
||||||
"travisci": {
|
"travisci": {
|
||||||
component: TravisCiConfigComponent,
|
//component: TravisCiConfigComponent,
|
||||||
},
|
},
|
||||||
"circleci": {
|
"circleci": {
|
||||||
component: CircleCiConfigComponent,
|
//component: CircleCiConfigComponent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"bridge": {
|
"bridge": {
|
||||||
"irc": {
|
"irc": {
|
||||||
component: IrcConfigComponent,
|
//component: IrcConfigComponent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"widget": {
|
"widget": {
|
||||||
"customwidget": {
|
"customwidget": {
|
||||||
component: CustomWidgetConfigComponent,
|
//component: CustomWidgetConfigComponent,
|
||||||
types: WIDGET_CUSTOM,
|
types: WIDGET_CUSTOM,
|
||||||
},
|
},
|
||||||
"youtube": {
|
"youtube": {
|
||||||
component: YoutubeWidgetConfigComponent,
|
//component: YoutubeWidgetConfigComponent,
|
||||||
types: WIDGET_YOUTUBE
|
types: WIDGET_YOUTUBE
|
||||||
},
|
},
|
||||||
"etherpad": {
|
"etherpad": {
|
||||||
component: EtherpadWidgetConfigComponent,
|
//component: EtherpadWidgetConfigComponent,
|
||||||
types: WIDGET_ETHERPAD,
|
types: WIDGET_ETHERPAD,
|
||||||
},
|
},
|
||||||
"twitch": {
|
"twitch": {
|
||||||
component: TwitchWidgetConfigComponent,
|
//component: TwitchWidgetConfigComponent,
|
||||||
types: WIDGET_TWITCH,
|
types: WIDGET_TWITCH,
|
||||||
},
|
},
|
||||||
"jitsi": {
|
"jitsi": {
|
||||||
component: JitsiWidgetConfigComponent,
|
//component: JitsiWidgetConfigComponent,
|
||||||
types: WIDGET_JITSI,
|
types: WIDGET_JITSI,
|
||||||
},
|
},
|
||||||
"googledocs": {
|
"googledocs": {
|
||||||
component: GoogleDocsWidgetConfigComponent,
|
//component: GoogleDocsWidgetConfigComponent,
|
||||||
types: WIDGET_GOOGLE_DOCS,
|
types: WIDGET_GOOGLE_DOCS,
|
||||||
},
|
},
|
||||||
"googlecalendar": {
|
"googlecalendar": {
|
||||||
component: GoogleCalendarWidgetConfigComponent,
|
//component: GoogleCalendarWidgetConfigComponent,
|
||||||
types: WIDGET_GOOGLE_CALENDAR,
|
types: WIDGET_GOOGLE_CALENDAR,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static getAllConfigComponents(): ContainerContent[] {
|
static getAllConfigComponents(): Component[] {
|
||||||
const components = [];
|
const components = [];
|
||||||
|
|
||||||
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
||||||
@ -84,34 +72,30 @@ export class IntegrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isSupported(integration: Integration): boolean {
|
static isSupported(integration: Integration): boolean {
|
||||||
const forType = IntegrationService.supportedIntegrationsMap[integration.type];
|
const forType = IntegrationService.supportedIntegrationsMap[integration.category];
|
||||||
if (!forType) return false;
|
if (!forType) return false;
|
||||||
|
|
||||||
if (Object.keys(forType).length === 0) return true;
|
if (Object.keys(forType).length === 0) return true;
|
||||||
|
|
||||||
return forType[integration.integrationType]; // has sub type
|
return forType[integration.type]; // has sub type
|
||||||
}
|
}
|
||||||
|
|
||||||
static hasConfig(integration: Integration): boolean {
|
static getConfigComponent(integration: Integration): Component {
|
||||||
return integration.type !== "bot";
|
return IntegrationService.supportedIntegrationsMap[integration.category][integration.type].component;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getConfigComponent(integration: Integration): ContainerContent {
|
static getIntegrationForScreen(screen: string): { category: string, type: string } {
|
||||||
return IntegrationService.supportedIntegrationsMap[integration.type][integration.integrationType].component;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getIntegrationForScreen(screen: string): { type: string, integrationType: string } {
|
|
||||||
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
||||||
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
||||||
const integrationTypes = IntegrationService.supportedIntegrationsMap[iType][iiType].types;
|
const integrationTypes = IntegrationService.supportedIntegrationsMap[iType][iiType].types;
|
||||||
const integrationScreens = integrationTypes.map(t => "type_" + t);
|
const integrationScreens = integrationTypes.map(t => "type_" + t);
|
||||||
if (integrationScreens.includes(screen)) return {type: iType, integrationType: iiType};
|
if (integrationScreens.includes(screen)) return {category: iType, type: iiType};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import { Http } from "@angular/http";
|
import { Http } from "@angular/http";
|
||||||
import { Integration } from "../models/integration";
|
import { LegacyIntegration } from "../../models/legacyintegration";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApiService {
|
export class ApiService {
|
||||||
@ -17,7 +17,7 @@ export class ApiService {
|
|||||||
.map(res => res.status === 200 ? res.json()["userId"] : null).toPromise();
|
.map(res => res.status === 200 ? res.json()["userId"] : null).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
getIntegrations(roomId: string, scalarToken: string): Promise<Integration[]> {
|
getIntegrations(roomId: string, scalarToken: string): Promise<LegacyIntegration[]> {
|
||||||
return this.http.get("/api/v1/dimension/integrations/" + roomId, {params: {scalar_token: scalarToken}})
|
return this.http.get("/api/v1/dimension/integrations/" + roomId, {params: {scalar_token: scalarToken}})
|
||||||
.map(res => res.json()).toPromise();
|
.map(res => res.json()).toPromise();
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ export class ApiService {
|
|||||||
.map(res => res.json()).toPromise();
|
.map(res => res.json()).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
getIntegration(type: string, integrationType: string): Promise<Integration> {
|
getIntegration(type: string, integrationType: string): Promise<LegacyIntegration> {
|
||||||
const url = "/api/v1/dimension/integration/" + type + "/" + integrationType;
|
const url = "/api/v1/dimension/integration/" + type + "/" + integrationType;
|
||||||
return this.http.get(url).map(res => res.json()).toPromise();
|
return this.http.get(url).map(res => res.json()).toPromise();
|
||||||
}
|
}
|
@ -1,24 +1,24 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import { Integration } from "./models/integration";
|
import { LegacyIntegration } from "../../models/legacyintegration";
|
||||||
import { RssConfigComponent } from "../configs/rss/rss-config.component";
|
import { RssConfigComponent } from "../../../configs/rss/rss-config.component";
|
||||||
import { ContainerContent } from "ngx-modialog";
|
import { ContainerContent } from "ngx-modialog";
|
||||||
import { IrcConfigComponent } from "../configs/irc/irc-config.component";
|
import { IrcConfigComponent } from "../../../configs/irc/irc-config.component";
|
||||||
import { TravisCiConfigComponent } from "../configs/travisci/travisci-config.component";
|
import { TravisCiConfigComponent } from "../../../configs/travisci/travisci-config.component";
|
||||||
import { CircleCiConfigComponent } from "../configs/circleci/circleci-config.component";
|
import { CustomWidgetConfigComponent } from "../../../configs/widget/custom_widget/custom_widget-config.component";
|
||||||
import { CustomWidgetConfigComponent } from "../configs/widget/custom_widget/custom_widget-config.component";
|
import { YoutubeWidgetConfigComponent } from "../../../configs/widget/youtube/youtube-config.component";
|
||||||
import { YoutubeWidgetConfigComponent } from "../configs/widget/youtube/youtube-config.component";
|
import { TwitchWidgetConfigComponent } from "../../../configs/widget/twitch/twitch-config.component";
|
||||||
import { TwitchWidgetConfigComponent } from "../configs/widget/twitch/twitch-config.component";
|
import { EtherpadWidgetConfigComponent } from "../../../configs/widget/etherpad/etherpad-config.component";
|
||||||
import { EtherpadWidgetConfigComponent } from "../configs/widget/etherpad/etherpad-config.component";
|
import { JitsiWidgetConfigComponent } from "../../../configs/widget/jitsi/jitsi-config.component";
|
||||||
import { JitsiWidgetConfigComponent } from "../configs/widget/jitsi/jitsi-config.component";
|
|
||||||
import {
|
import {
|
||||||
WIDGET_CUSTOM, WIDGET_ETHERPAD, WIDGET_GOOGLE_CALENDAR, WIDGET_GOOGLE_DOCS, WIDGET_JITSI, WIDGET_TWITCH,
|
WIDGET_CUSTOM, WIDGET_ETHERPAD, WIDGET_GOOGLE_CALENDAR, WIDGET_GOOGLE_DOCS, WIDGET_JITSI, WIDGET_TWITCH,
|
||||||
WIDGET_YOUTUBE
|
WIDGET_YOUTUBE
|
||||||
} from "./models/widget";
|
} from "../../models/widget";
|
||||||
import { GoogleDocsWidgetConfigComponent } from "../configs/widget/googledocs/googledocs-config.component";
|
import { GoogleDocsWidgetConfigComponent } from "../../../configs/widget/googledocs/googledocs-config.component";
|
||||||
import { GoogleCalendarWidgetConfigComponent } from "../configs/widget/googlecalendar/googlecalendar-config.component";
|
import { GoogleCalendarWidgetConfigComponent } from "../../../configs/widget/googlecalendar/googlecalendar-config.component";
|
||||||
|
import { CircleCiConfigComponent } from "../../../configs/circleci/circleci-config.component";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IntegrationService {
|
export class LegacyIntegrationService {
|
||||||
|
|
||||||
private static supportedIntegrationsMap = {
|
private static supportedIntegrationsMap = {
|
||||||
"bot": {}, // empty == supported
|
"bot": {}, // empty == supported
|
||||||
@ -73,9 +73,9 @@ export class IntegrationService {
|
|||||||
static getAllConfigComponents(): ContainerContent[] {
|
static getAllConfigComponents(): ContainerContent[] {
|
||||||
const components = [];
|
const components = [];
|
||||||
|
|
||||||
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
for (const iType of Object.keys(LegacyIntegrationService.supportedIntegrationsMap)) {
|
||||||
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
for (const iiType of Object.keys(LegacyIntegrationService.supportedIntegrationsMap[iType])) {
|
||||||
const component = IntegrationService.supportedIntegrationsMap[iType][iiType].component;
|
const component = LegacyIntegrationService.supportedIntegrationsMap[iType][iiType].component;
|
||||||
if (component) components.push(component);
|
if (component) components.push(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,8 +83,8 @@ export class IntegrationService {
|
|||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isSupported(integration: Integration): boolean {
|
static isSupported(integration: LegacyIntegration): boolean {
|
||||||
const forType = IntegrationService.supportedIntegrationsMap[integration.type];
|
const forType = LegacyIntegrationService.supportedIntegrationsMap[integration.type];
|
||||||
if (!forType) return false;
|
if (!forType) return false;
|
||||||
|
|
||||||
if (Object.keys(forType).length === 0) return true;
|
if (Object.keys(forType).length === 0) return true;
|
||||||
@ -92,18 +92,18 @@ export class IntegrationService {
|
|||||||
return forType[integration.integrationType]; // has sub type
|
return forType[integration.integrationType]; // has sub type
|
||||||
}
|
}
|
||||||
|
|
||||||
static hasConfig(integration: Integration): boolean {
|
static hasConfig(integration: LegacyIntegration): boolean {
|
||||||
return integration.type !== "bot";
|
return integration.type !== "bot";
|
||||||
}
|
}
|
||||||
|
|
||||||
static getConfigComponent(integration: Integration): ContainerContent {
|
static getConfigComponent(integration: LegacyIntegration): ContainerContent {
|
||||||
return IntegrationService.supportedIntegrationsMap[integration.type][integration.integrationType].component;
|
return LegacyIntegrationService.supportedIntegrationsMap[integration.type][integration.integrationType].component;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getIntegrationForScreen(screen: string): { type: string, integrationType: string } {
|
static getIntegrationForScreen(screen: string): { type: string, integrationType: string } {
|
||||||
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
for (const iType of Object.keys(LegacyIntegrationService.supportedIntegrationsMap)) {
|
||||||
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
for (const iiType of Object.keys(LegacyIntegrationService.supportedIntegrationsMap[iType])) {
|
||||||
const integrationTypes = IntegrationService.supportedIntegrationsMap[iType][iiType].types;
|
const integrationTypes = LegacyIntegrationService.supportedIntegrationsMap[iType][iiType].types;
|
||||||
const integrationScreens = integrationTypes.map(t => "type_" + t);
|
const integrationScreens = integrationTypes.map(t => "type_" + t);
|
||||||
if (integrationScreens.includes(screen)) return {type: iType, integrationType: iiType};
|
if (integrationScreens.includes(screen)) return {type: iType, integrationType: iiType};
|
||||||
}
|
}
|
@ -6,17 +6,17 @@ import {
|
|||||||
MembershipStateResponse, RoomEncryptionStatusResponse,
|
MembershipStateResponse, RoomEncryptionStatusResponse,
|
||||||
ScalarSuccessResponse,
|
ScalarSuccessResponse,
|
||||||
WidgetsResponse
|
WidgetsResponse
|
||||||
} from "../models/scalar_responses";
|
} from "../models/scalar_client_responses";
|
||||||
import { EditableWidget } from "../models/widget";
|
import { EditableWidget } from "../models/widget";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScalarService {
|
export class ScalarClientApiService {
|
||||||
|
|
||||||
private static actionMap: { [key: string]: { resolve: (obj: any) => void, reject: (obj: any) => void } } = {};
|
private static actionMap: { [key: string]: { resolve: (obj: any) => void, reject: (obj: any) => void } } = {};
|
||||||
|
|
||||||
public static getAndRemoveActionHandler(requestKey: string): { resolve: (obj: any) => void, reject: (obj: any) => void } {
|
public static getAndRemoveActionHandler(requestKey: string): { resolve: (obj: any) => void, reject: (obj: any) => void } {
|
||||||
let handler = ScalarService.actionMap[requestKey];
|
let handler = ScalarClientApiService.actionMap[requestKey];
|
||||||
ScalarService.actionMap[requestKey] = null;
|
ScalarClientApiService.actionMap[requestKey] = null;
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ export class ScalarService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScalarService.actionMap[requestKey] = {
|
ScalarClientApiService.actionMap[requestKey] = {
|
||||||
resolve: resolve,
|
resolve: resolve,
|
||||||
reject: reject
|
reject: reject
|
||||||
};
|
};
|
||||||
@ -117,7 +117,7 @@ window.addEventListener("message", event => {
|
|||||||
let requestKey = event.data["request_id"];
|
let requestKey = event.data["request_id"];
|
||||||
if (!requestKey) return;
|
if (!requestKey) return;
|
||||||
|
|
||||||
let action = ScalarService.getAndRemoveActionHandler(requestKey);
|
let action = ScalarClientApiService.getAndRemoveActionHandler(requestKey);
|
||||||
if (!action) return;
|
if (!action) return;
|
||||||
|
|
||||||
if (event.data.response && event.data.response.error) action.reject(event.data);
|
if (event.data.response && event.data.response.error) action.reject(event.data);
|
15
web/app/shared/services/scalar-server-api.service.ts
Normal file
15
web/app/shared/services/scalar-server-api.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Http } from "@angular/http";
|
||||||
|
import { ScalarAccountResponse } from "../models/scalar_server_responses";
|
||||||
|
import { AuthedApi } from "./AuthedApi";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ScalarServerApiService extends AuthedApi {
|
||||||
|
constructor(http: Http) {
|
||||||
|
super(http)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAccount(): Promise<ScalarAccountResponse> {
|
||||||
|
return this.authedGet("/api/v1/scalar/account").map(res => res.json()).toPromise();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
|
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import * as $ from "jquery";
|
import * as $ from "jquery";
|
||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/legacy/api.service";
|
||||||
import { JitsiWidgetIntegration } from "../../shared/models/integration";
|
import { JitsiWidgetIntegration } from "../../shared/models/legacyintegration";
|
||||||
|
|
||||||
declare var JitsiMeetExternalAPI: any;
|
declare var JitsiMeetExternalAPI: any;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user