diff --git a/config/integrations/etherpad_widget.yaml b/config/integrations/etherpad_widget.yaml
new file mode 100644
index 0000000..53aeb5a
--- /dev/null
+++ b/config/integrations/etherpad_widget.yaml
@@ -0,0 +1,7 @@
+# All this configuration does is make "Etherpad Widget" available in the UI
+type: "widget"
+integrationType: "etherpad"
+enabled: true
+name: "Etherpad"
+about: "Etherpad is a collaborative text editor. With this widget you can embed Etherpad directly in to your Matrix chat rooms so that you can securely collaborate on documents."
+avatar: "img/avatars/etherpad.png"
diff --git a/web/app/app.module.ts b/web/app/app.module.ts
index b62fe1e..04eeb30 100644
--- a/web/app/app.module.ts
+++ b/web/app/app.module.ts
@@ -29,6 +29,7 @@ import { ToggleFullscreenDirective } from "./shared/toggle-fullscreen.directive"
import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.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 { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.component";
@NgModule({
@@ -60,6 +61,7 @@ import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.compo
FullscreenButtonComponent,
YoutubeWidgetConfigComponent,
TwitchWidgetConfigComponent,
+ EtherpadWidgetConfigComponent,
VideoWidgetWrapperComponent,
// Vendor
@@ -80,7 +82,8 @@ import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.compo
IrcConfigComponent,
CustomWidgetConfigComponent,
YoutubeWidgetConfigComponent,
- TwitchWidgetConfigComponent
+ TwitchWidgetConfigComponent,
+ EtherpadWidgetConfigComponent,
]
})
export class AppModule {
diff --git a/web/app/configs/widget/etherpad/etherpad-config.component.html b/web/app/configs/widget/etherpad/etherpad-config.component.html
new file mode 100644
index 0000000..09d4f19
--- /dev/null
+++ b/web/app/configs/widget/etherpad/etherpad-config.component.html
@@ -0,0 +1,118 @@
+
+
+
+
+
+
diff --git a/web/app/configs/widget/etherpad/etherpad-config.component.scss b/web/app/configs/widget/etherpad/etherpad-config.component.scss
new file mode 100644
index 0000000..92dce18
--- /dev/null
+++ b/web/app/configs/widget/etherpad/etherpad-config.component.scss
@@ -0,0 +1,4 @@
+// component styles are encapsulated and only applied to their components
+.widget-item {
+ margin-top: 3px;
+}
diff --git a/web/app/configs/widget/etherpad/etherpad-config.component.ts b/web/app/configs/widget/etherpad/etherpad-config.component.ts
new file mode 100644
index 0000000..0400fb7
--- /dev/null
+++ b/web/app/configs/widget/etherpad/etherpad-config.component.ts
@@ -0,0 +1,124 @@
+import { Component } from "@angular/core";
+import { ModalComponent, DialogRef } from "ngx-modialog";
+import { WidgetComponent } from "../widget.component";
+import { ScalarService } from "../../../shared/scalar.service";
+import { ConfigModalContext } from "../../../integration/integration.component";
+import { ToasterService } from "angular2-toaster";
+import { Widget, WIDGET_DIM_ETHERPAD, WIDGET_SCALAR_ETHERPAD } from "../../../shared/models/widget";
+
+@Component({
+ selector: "my-etherpadwidget-config",
+ templateUrl: "etherpad-config.component.html",
+ styleUrls: ["etherpad-config.component.scss", "./../../config.component.scss"],
+})
+export class EtherpadWidgetConfigComponent extends WidgetComponent implements ModalComponent {
+
+ public newEtherpadServerUrl: string = "";
+ public useCustomServer = false;
+ public editUseCustomServer = false;
+
+ constructor(public dialog: DialogRef,
+ toaster: ToasterService,
+ scalarService: ScalarService,
+ window: Window) {
+ super(
+ toaster,
+ scalarService,
+ dialog.context.roomId,
+ window,
+ WIDGET_DIM_ETHERPAD,
+ WIDGET_SCALAR_ETHERPAD,
+ dialog.context.integrationId,
+ "Etherpad Widget",
+ "generic", // wrapper
+ "etherpad" // scalar wrapper
+ );
+ }
+
+ getPadURL(widget?: Widget): string {
+ let url: string;
+ if (widget) {
+ if (this.editUseCustomServer) {
+ url = widget.data.newPadServer + this.roomId + "_" + widget.data.newPadName;
+ } else {
+ url = "https://demo.riot.im/etherpad/p/" + this.roomId + "_" + widget.data.newPadName;
+ }
+ } else {
+ if (this.useCustomServer) {
+ url = this.newEtherpadServerUrl + this.roomId + "_" + this.newWidgetUrl;
+ } else {
+ url = "https://demo.riot.im/etherpad/p/" + this.roomId + "_" + this.newWidgetUrl;
+ }
+ }
+ return url;
+ }
+
+ private checkPadURL(url: string, widget?: Widget): boolean {
+ if (widget) {
+ if (this.editUseCustomServer) {
+ return Boolean(url === widget.data.newPadServer);
+ } else {
+ return Boolean(url === "https://demo.riot.im/etherpad/p/");
+ }
+ } else {
+ if (this.useCustomServer) {
+ return Boolean(url === this.newEtherpadServerUrl);
+ } else {
+ return Boolean(url === "https://demo.riot.im/etherpad/p/");
+ }
+ }
+ }
+
+ public validateAndAddWidget() {
+ const url = this.getPadURL() + "?userName=$matrix_user_id";
+
+ if (this.checkPadURL(url)) {
+ this.toaster.pop("warning", "Please enter a Pad Name");
+ return;
+ }
+
+ const originalUrl = this.roomId + "_" + this.newWidgetUrl;
+ this.newWidgetUrl = url;
+
+ if (this.useCustomServer) {
+ this.addWidget({padName: originalUrl, padSuffix: originalUrl, padServer: this.newEtherpadServerUrl});
+ } else {
+ this.addWidget({padName: originalUrl, padSuffix: originalUrl, padServer: "https://demo.riot.im/etherpad/p/"});
+ }
+ }
+
+ public validateAndSaveWidget(widget: Widget) {
+ const url = this.getPadURL(widget) + "?userName=$matrix_user_id";
+
+ if (this.checkPadURL(url, widget)) {
+ this.toaster.pop("warning", "Please enter a Pad Name");
+ return;
+ }
+
+ if (!widget.data) widget.data = {};
+
+ widget.newUrl = url;
+ widget.data.padName = widget.data.newPadName;
+ widget.data.padSuffix = this.roomId + "_" + widget.data.newPadName;
+ if (this.editUseCustomServer) {
+ widget.data.padServer = widget.data.newPadServer;
+ } else {
+ widget.data.padServer = "https://demo.riot.im/etherpad/p/"
+ }
+
+ delete widget.data.newPadServer;
+ delete widget.data.newPadName;
+
+ this.saveWidget(widget);
+ }
+
+ editWidget(widget: Widget) {
+ widget.data.newPadName = widget.data.padName;
+ widget.data.newPadServer = widget.data.padServer;
+ if (widget.data.newPadServer !== "https://demo.riot.im/etherpad/p/") {
+ this.editUseCustomServer = true
+ }
+ super.editWidget(widget);
+ }
+
+}
diff --git a/web/app/configs/widget/widget.component.ts b/web/app/configs/widget/widget.component.ts
index 4692e45..f3a966e 100644
--- a/web/app/configs/widget/widget.component.ts
+++ b/web/app/configs/widget/widget.component.ts
@@ -88,7 +88,16 @@ export class WidgetComponent {
}
private wrapUrl(url: string): string {
- return this.wrapperUrl + encodeURIComponent(url);
+ let encodedURL = this.wrapperUrl + encodeURIComponent(url);
+
+ //don't URL encode $vars of the widget Spec
+ //TODO do the same with vars from the data object
+ encodedURL = encodedURL.replace(encodeURIComponent("$matrix_user_id"), "$matrix_user_id");
+ encodedURL = encodedURL.replace(encodeURIComponent("$matrix_room_id"), "$matrix_room_id");
+ encodedURL = encodedURL.replace(encodeURIComponent("$matrix_display_name"), "$matrix_display_name");
+ encodedURL = encodedURL.replace(encodeURIComponent("$matrix_avatar_url"), "$matrix_avatar_url");
+
+ return encodedURL;
}
private setWidgetUrl(widget: Widget) {
diff --git a/web/app/riot/riot.component.ts b/web/app/riot/riot.component.ts
index 83fd31f..2094a7c 100644
--- a/web/app/riot/riot.component.ts
+++ b/web/app/riot/riot.component.ts
@@ -6,7 +6,7 @@ import { ToasterService } from "angular2-toaster";
import { Integration } from "../shared/models/integration";
import { IntegrationService } from "../shared/integration.service";
import * as _ from "lodash";
-import { WIDGET_DIM_CUSTOM, WIDGET_DIM_YOUTUBE, WIDGET_DIM_TWITCH } from "../shared/models/widget";
+import { WIDGET_DIM_CUSTOM, WIDGET_DIM_YOUTUBE, WIDGET_DIM_TWITCH, WIDGET_DIM_ETHERPAD } from "../shared/models/widget";
import { IntegrationComponent } from "../integration/integration.component";
@Component({
@@ -79,6 +79,9 @@ export class RiotComponent {
} else if (this.requestedScreen === "type_" + WIDGET_DIM_TWITCH) {
type = "widget";
integrationType = "twitch";
+ } else if (this.requestedScreen === "type_" + WIDGET_DIM_ETHERPAD) {
+ type = "widget";
+ integrationType = "etherpad";
} else {
console.log("Unknown screen requested: " + this.requestedScreen);
}
diff --git a/web/app/shared/integration.service.ts b/web/app/shared/integration.service.ts
index 46f2229..2a429e0 100644
--- a/web/app/shared/integration.service.ts
+++ b/web/app/shared/integration.service.ts
@@ -7,6 +7,7 @@ import { TravisCiConfigComponent } from "../configs/travisci/travisci-config.com
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";
@Injectable()
export class IntegrationService {
@@ -24,6 +25,7 @@ export class IntegrationService {
"customwidget": true,
"youtube": true,
"twitch": true,
+ "etherpad": true,
},
};
@@ -39,6 +41,7 @@ export class IntegrationService {
"customwidget": CustomWidgetConfigComponent,
"youtube": YoutubeWidgetConfigComponent,
"twitch": TwitchWidgetConfigComponent,
+ "etherpad": EtherpadWidgetConfigComponent,
},
};
diff --git a/web/app/shared/models/widget.ts b/web/app/shared/models/widget.ts
index 2186add..e921e0e 100644
--- a/web/app/shared/models/widget.ts
+++ b/web/app/shared/models/widget.ts
@@ -14,6 +14,7 @@ export const WIDGET_SCALAR_TWITCH = "";
export const WIDGET_DIM_CUSTOM = "dimension-customwidget";
export const WIDGET_DIM_YOUTUBE = "dimension-youtube";
export const WIDGET_DIM_TWITCH = "dimension-twitch";
+export const WIDGET_DIM_ETHERPAD = "dimension-etherpad";
export interface Widget {
id: string;
diff --git a/web/public/img/avatars/etherpad.png b/web/public/img/avatars/etherpad.png
new file mode 100644
index 0000000..c420f30
Binary files /dev/null and b/web/public/img/avatars/etherpad.png differ