mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-08-31 14:12:08 +00:00
Add etherpad widget configuration
This commit is contained in:
parent
7fd674a8ff
commit
fce6f2174a
@ -33,6 +33,8 @@ import { ServiceLocator } from "./shared/services/locator.service";
|
|||||||
import { IboxComponent } from "./elements/ibox/ibox.component";
|
import { IboxComponent } from "./elements/ibox/ibox.component";
|
||||||
import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component";
|
import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component";
|
||||||
import { ConfigScreenWidgetComponent } from "./configs/widget/config_screen/config_screen.widget.component";
|
import { ConfigScreenWidgetComponent } from "./configs/widget/config_screen/config_screen.widget.component";
|
||||||
|
import { EtherpadWidgetConfigComponent } from "./configs/widget/etherpad/etherpad.widget.component";
|
||||||
|
import { NameService } from "./shared/services/name.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -66,6 +68,7 @@ import { ConfigScreenWidgetComponent } from "./configs/widget/config_screen/conf
|
|||||||
IboxComponent,
|
IboxComponent,
|
||||||
ConfigScreenWidgetComponent,
|
ConfigScreenWidgetComponent,
|
||||||
CustomWidgetConfigComponent,
|
CustomWidgetConfigComponent,
|
||||||
|
EtherpadWidgetConfigComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
@ -74,6 +77,7 @@ import { ConfigScreenWidgetComponent } from "./configs/widget/config_screen/conf
|
|||||||
ScalarServerApiService,
|
ScalarServerApiService,
|
||||||
DimensionApiService,
|
DimensionApiService,
|
||||||
AdminApiService,
|
AdminApiService,
|
||||||
|
NameService,
|
||||||
{provide: Window, useValue: window},
|
{provide: Window, useValue: window},
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
|
@ -7,6 +7,7 @@ import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.compo
|
|||||||
import { GCalWidgetWrapperComponent } from "./widget_wrappers/gcal/gcal.component";
|
import { GCalWidgetWrapperComponent } from "./widget_wrappers/gcal/gcal.component";
|
||||||
import { RiotHomeComponent } from "./riot/riot-home/home.component";
|
import { RiotHomeComponent } from "./riot/riot-home/home.component";
|
||||||
import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component";
|
import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component";
|
||||||
|
import { EtherpadWidgetConfigComponent } from "./configs/widget/etherpad/etherpad.widget.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -28,6 +29,11 @@ const routes: Routes = [
|
|||||||
component: CustomWidgetConfigComponent,
|
component: CustomWidgetConfigComponent,
|
||||||
data: {breadcrumb: "Custom Widgets", name: "Custom Widgets"}
|
data: {breadcrumb: "Custom Widgets", name: "Custom Widgets"}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "etherpad",
|
||||||
|
component: EtherpadWidgetConfigComponent,
|
||||||
|
data: {breadcrumb: "Etherpad Widgets", name: "Etherpad Widgets"}
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
<my-widget-config [widgetComponent]="this">
|
||||||
|
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||||
|
<label class="label-block">
|
||||||
|
Pad Name
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
placeholder="{{ defaultName }}"
|
||||||
|
[(ngModel)]="widget.dimension.newName" name="widget-name-{{widget.id}}"
|
||||||
|
[disabled]="isUpdating"/>
|
||||||
|
</label>
|
||||||
|
<label class="label-block">
|
||||||
|
Pad URL
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
placeholder="https://demo.riot.im/etherpad/p/MyCoolPadName"
|
||||||
|
[(ngModel)]="widget.dimension.newUrl" name="widget-url-{{widget.id}}"
|
||||||
|
[disabled]="isUpdating"/>
|
||||||
|
</label>
|
||||||
|
</ng-template>
|
||||||
|
</my-widget-config>
|
34
web/app/configs/widget/etherpad/etherpad.widget.component.ts
Normal file
34
web/app/configs/widget/etherpad/etherpad.widget.component.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { NewWidgetComponent } from "../widget.component";
|
||||||
|
import { EditableWidget, WIDGET_ETHERPAD } from "../../../shared/models/widget";
|
||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { EtherpadWidget } from "../../../shared/models/integration";
|
||||||
|
import { SessionStorage } from "../../../shared/SessionStorage";
|
||||||
|
import { NameService } from "../../../shared/services/name.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "etherpad.widget.component.html",
|
||||||
|
styleUrls: ["etherpad.widget.component.scss"],
|
||||||
|
})
|
||||||
|
export class EtherpadWidgetConfigComponent extends NewWidgetComponent {
|
||||||
|
|
||||||
|
private etherpadWidget: EtherpadWidget = <EtherpadWidget>SessionStorage.editIntegration;
|
||||||
|
|
||||||
|
constructor(private nameService: NameService) {
|
||||||
|
super(WIDGET_ETHERPAD, "Etherpad Widget", "generic", "etherpad");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OnNewWidgetPrepared(widget: EditableWidget): void {
|
||||||
|
const name = this.nameService.getHumanReadableName();
|
||||||
|
|
||||||
|
let template = "https://demo.riot.im/etherpad/p/$roomId_$padName";
|
||||||
|
if (this.etherpadWidget.options && this.etherpadWidget.options.defaultUrl) {
|
||||||
|
template = this.etherpadWidget.options.defaultUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template = template.replace("$roomId", encodeURIComponent(SessionStorage.roomId));
|
||||||
|
template = template.replace("$padName", encodeURIComponent(name));
|
||||||
|
|
||||||
|
widget.dimension.newUrl = template;
|
||||||
|
widget.dimension.newName = name;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import { EventEmitter } from "@angular/core";
|
|
||||||
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 { ScalarClientApiService } from "../../shared/services/scalar-client-api.service";
|
import { ScalarClientApiService } from "../../shared/services/scalar-client-api.service";
|
||||||
import { ServiceLocator } from "../../shared/services/locator.service";
|
import { ServiceLocator } from "../../shared/services/locator.service";
|
||||||
import { SessionStorage } from "../../shared/SessionStorage";
|
import { SessionStorage } from "../../shared/SessionStorage";
|
||||||
|
import { OnInit } from "@angular/core";
|
||||||
|
|
||||||
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=",
|
||||||
@ -12,7 +12,7 @@ const SCALAR_WIDGET_LINKS = [
|
|||||||
"https://demo.riot.im/scalar/api/widgets/__TYPE__.html?url=",
|
"https://demo.riot.im/scalar/api/widgets/__TYPE__.html?url=",
|
||||||
];
|
];
|
||||||
|
|
||||||
export class NewWidgetComponent {
|
export class NewWidgetComponent implements OnInit {
|
||||||
|
|
||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
public isUpdating = false;
|
public isUpdating = false;
|
||||||
@ -27,40 +27,32 @@ export class NewWidgetComponent {
|
|||||||
private window = ServiceLocator.injector.get(Window);
|
private window = ServiceLocator.injector.get(Window);
|
||||||
private scalarApi = ServiceLocator.injector.get(ScalarClientApiService);
|
private scalarApi = ServiceLocator.injector.get(ScalarClientApiService);
|
||||||
|
|
||||||
protected OnNewWidgetPrepared = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetsDiscovered = new EventEmitter<EditableWidget[]>();
|
|
||||||
protected OnWidgetBeforeAdd = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetAfterAdd = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetPreparedForEdit = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetBeforeEdit = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetAfterEdit = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetBeforeDelete = new EventEmitter<EditableWidget>();
|
|
||||||
protected OnWidgetAfterDelete = new EventEmitter<EditableWidget>();
|
|
||||||
|
|
||||||
constructor(private widgetTypes: string[],
|
constructor(private widgetTypes: string[],
|
||||||
public defaultName: string,
|
public defaultName: string,
|
||||||
private wrapperId = "generic",
|
private wrapperId = "generic",
|
||||||
private scalarWrapperId = null) {
|
private scalarWrapperId = null) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (wrapperId) {
|
public ngOnInit(): void {
|
||||||
this.wrapperUrl = this.window.location.origin + "/widgets/" + wrapperId + "?url=";
|
if (this.wrapperId) {
|
||||||
|
this.wrapperUrl = this.window.location.origin + "/widgets/" + this.wrapperId + "?url=";
|
||||||
|
|
||||||
if (!scalarWrapperId) scalarWrapperId = wrapperId;
|
if (!this.scalarWrapperId) this.scalarWrapperId = this.wrapperId;
|
||||||
for (let widgetLink of SCALAR_WIDGET_LINKS) {
|
for (let widgetLink of SCALAR_WIDGET_LINKS) {
|
||||||
this.scalarWrapperUrls.push(widgetLink.replace("__TYPE__", scalarWrapperId));
|
this.scalarWrapperUrls.push(widgetLink.replace("__TYPE__", this.scalarWrapperId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prepareNewWidget();
|
this.prepareNewWidget();
|
||||||
this.getWidgetsOfType(widgetTypes).then(widgets => {
|
this.getWidgetsOfType(this.widgetTypes).then(widgets => {
|
||||||
this.widgets = widgets;
|
this.widgets = widgets;
|
||||||
for (let widget of this.widgets) {
|
for (let widget of this.widgets) {
|
||||||
this.unpackWidget(widget);
|
this.unpackWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.OnWidgetsDiscovered.emit(this.widgets);
|
this.OnWidgetsDiscovered(this.widgets);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
|
|
||||||
@ -155,7 +147,8 @@ export class NewWidgetComponent {
|
|||||||
newData: {},
|
newData: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.OnNewWidgetPrepared.emit(this.newWidget);
|
console.log("Emitting new widget prepared event");
|
||||||
|
this.OnNewWidgetPrepared(this.newWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,12 +231,12 @@ export class NewWidgetComponent {
|
|||||||
this.packWidget(this.newWidget);
|
this.packWidget(this.newWidget);
|
||||||
|
|
||||||
this.isUpdating = true;
|
this.isUpdating = true;
|
||||||
this.OnWidgetBeforeAdd.emit(this.newWidget);
|
this.OnWidgetBeforeAdd(this.newWidget);
|
||||||
return this.scalarApi.setWidget(SessionStorage.roomId, this.newWidget)
|
return this.scalarApi.setWidget(SessionStorage.roomId, this.newWidget)
|
||||||
.then(() => this.widgets.push(this.newWidget))
|
.then(() => this.widgets.push(this.newWidget))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
this.OnWidgetAfterAdd.emit(this.newWidget);
|
this.OnWidgetAfterAdd(this.newWidget);
|
||||||
this.prepareNewWidget();
|
this.prepareNewWidget();
|
||||||
this.toaster.pop("success", "Widget added!");
|
this.toaster.pop("success", "Widget added!");
|
||||||
})
|
})
|
||||||
@ -268,11 +261,11 @@ export class NewWidgetComponent {
|
|||||||
this.packWidget(widget);
|
this.packWidget(widget);
|
||||||
|
|
||||||
this.isUpdating = true;
|
this.isUpdating = true;
|
||||||
this.OnWidgetBeforeEdit.emit(widget);
|
this.OnWidgetBeforeEdit(widget);
|
||||||
return this.scalarApi.setWidget(SessionStorage.roomId, widget)
|
return this.scalarApi.setWidget(SessionStorage.roomId, widget)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
this.OnWidgetAfterEdit.emit(widget);
|
this.OnWidgetAfterEdit(widget);
|
||||||
this.toaster.pop("success", "Widget updated!");
|
this.toaster.pop("success", "Widget updated!");
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@ -289,12 +282,12 @@ export class NewWidgetComponent {
|
|||||||
*/
|
*/
|
||||||
public removeWidget(widget: EditableWidget): Promise<any> {
|
public removeWidget(widget: EditableWidget): Promise<any> {
|
||||||
this.isUpdating = true;
|
this.isUpdating = true;
|
||||||
this.OnWidgetBeforeDelete.emit(widget);
|
this.OnWidgetBeforeDelete(widget);
|
||||||
return this.scalarApi.deleteWidget(SessionStorage.roomId, widget)
|
return this.scalarApi.deleteWidget(SessionStorage.roomId, widget)
|
||||||
.then(() => this.widgets.splice(this.widgets.indexOf(widget), 1))
|
.then(() => this.widgets.splice(this.widgets.indexOf(widget), 1))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
this.OnWidgetAfterDelete.emit(widget);
|
this.OnWidgetAfterDelete(widget);
|
||||||
this.toaster.pop("success", "Widget deleted!");
|
this.toaster.pop("success", "Widget deleted!");
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@ -310,6 +303,90 @@ export class NewWidgetComponent {
|
|||||||
*/
|
*/
|
||||||
public resetWidget(widget: EditableWidget) {
|
public resetWidget(widget: EditableWidget) {
|
||||||
this.unpackWidget(widget);
|
this.unpackWidget(widget);
|
||||||
this.OnWidgetPreparedForEdit.emit(widget);
|
this.OnWidgetPreparedForEdit(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component hooks below here
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a new widget has been created in the newWidget field
|
||||||
|
* @param {EditableWidget} _widget The widget that has been prepared
|
||||||
|
*/
|
||||||
|
protected OnNewWidgetPrepared(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after all the widgets have been discovered and unpacked for the room.
|
||||||
|
* @param {EditableWidget[]} _widgets The widgets that were discovered
|
||||||
|
*/
|
||||||
|
protected OnWidgetsDiscovered(_widgets: EditableWidget[]): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the widget is added to the room, but after the Dimension-specific
|
||||||
|
* settings have been copied over to the primary fields.
|
||||||
|
* @param {EditableWidget} _widget The widget that is about to be added
|
||||||
|
*/
|
||||||
|
protected OnWidgetBeforeAdd(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after the widget has been added to the room, but before the newWidget field
|
||||||
|
* has been set to a new widget.
|
||||||
|
* @param {EditableWidget} _widget The widget that has been added.
|
||||||
|
*/
|
||||||
|
protected OnWidgetAfterAdd(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the given widget has been asked to be prepared for editing. At this point
|
||||||
|
* the widget is not being persisted to the room, it is just updating the EditingWidget's
|
||||||
|
* properties for the user's ability to edit it.
|
||||||
|
* @param {EditableWidget} _widget The widget that has been prepared for editing
|
||||||
|
*/
|
||||||
|
protected OnWidgetPreparedForEdit(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the given widget has been updated in the room, but after the
|
||||||
|
* Dimension-specific settings have been copied over to the primary fields.
|
||||||
|
* This is not called for widgets being deleted.
|
||||||
|
* @param {EditableWidget} _widget The widget about to be edited
|
||||||
|
*/
|
||||||
|
protected OnWidgetBeforeEdit(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after a given widget has been updated in the room. This is not called for
|
||||||
|
* widgets being deleted.
|
||||||
|
* @param {EditableWidget} _widget The widget that has been updated.
|
||||||
|
*/
|
||||||
|
protected OnWidgetAfterEdit(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the given widget has been removed from the room. No changes to the
|
||||||
|
* widget have been made at this point.
|
||||||
|
* @param {EditableWidget} _widget The widget about to be deleted.
|
||||||
|
*/
|
||||||
|
protected OnWidgetBeforeDelete(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after a given widget has been deleted from the room. The widget will be in
|
||||||
|
* the deleted state and will no longer be tracked anywhere on the component.
|
||||||
|
* @param {EditableWidget} _widget The widget that has been deleted.
|
||||||
|
*/
|
||||||
|
protected OnWidgetAfterDelete(_widget: EditableWidget): void {
|
||||||
|
// Component hook
|
||||||
}
|
}
|
||||||
}
|
}
|
18
web/app/shared/services/name.service.ts
Normal file
18
web/app/shared/services/name.service.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import * as gobyInit from "goby";
|
||||||
|
|
||||||
|
const goby = gobyInit.init({
|
||||||
|
// Converts words to a url-safe name
|
||||||
|
// Ie: "hello world how-are you" becomes "HelloWorldHowAreYou"
|
||||||
|
decorator: parts => parts.map(p => p ? p.split('-').map(p2 => p2 ? p2[0].toUpperCase() + p2.substring(1).toLowerCase() : '').join('') : '').join(''),
|
||||||
|
});
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NameService {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHumanReadableName(): string {
|
||||||
|
return goby.generate(["adj", "pre", "suf"]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user