diff --git a/web/app/app.module.ts b/web/app/app.module.ts index 0863efa..aa10a1b 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -32,6 +32,7 @@ import { DimensionApiService } from "./shared/services/dimension-api.service"; import { AdminApiService } from "./shared/services/admin-api.service"; import { ServiceLocator } from "./shared/services/locator.service"; import { IboxComponent } from "./elements/ibox/ibox.component"; +import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component"; @NgModule({ imports: [ @@ -64,6 +65,7 @@ import { IboxComponent } from "./elements/ibox/ibox.component"; GCalWidgetWrapperComponent, RiotHomeComponent, IboxComponent, + CustomWidgetConfigComponent, // Vendor ], diff --git a/web/app/app.routing.ts b/web/app/app.routing.ts index 404f797..df889b8 100644 --- a/web/app/app.routing.ts +++ b/web/app/app.routing.ts @@ -6,6 +6,7 @@ import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.compo import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.component"; import { GCalWidgetWrapperComponent } from "./widget_wrappers/gcal/gcal.component"; import { RiotHomeComponent } from "./riot/riot-home/home.component"; +import { CustomWidgetConfigComponent } from "./configs/widget/custom/custom.widget.component"; const routes: Routes = [ {path: "", component: HomeComponent}, @@ -21,14 +22,13 @@ const routes: Routes = [ }, { path: "widget", - children: [], - // children: [ - // { - // path: "custom", - // component: NewTestWidgetComponent, - // data: {breadcrumb: "Custom Widgets", name: "Custom Widgets"} - // }, - // ], + children: [ + { + path: "custom", + component: CustomWidgetConfigComponent, + data: {breadcrumb: "Custom Widgets", name: "Custom Widgets"} + }, + ], }, ], }, diff --git a/web/app/configs/widget/custom/custom.widget.component.html b/web/app/configs/widget/custom/custom.widget.component.html new file mode 100644 index 0000000..d7bf43c --- /dev/null +++ b/web/app/configs/widget/custom/custom.widget.component.html @@ -0,0 +1,58 @@ + +
+
+ + + + +
+
+
+ + +
+
+ + + + + + +
+
+
\ No newline at end of file diff --git a/web/app/configs/widget/custom/custom.widget.component.scss b/web/app/configs/widget/custom/custom.widget.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/web/app/configs/widget/custom/custom.widget.component.ts b/web/app/configs/widget/custom/custom.widget.component.ts new file mode 100644 index 0000000..50d4687 --- /dev/null +++ b/web/app/configs/widget/custom/custom.widget.component.ts @@ -0,0 +1,13 @@ +import { NewWidgetComponent } from "../widget.component"; +import { WIDGET_CUSTOM } from "../../../shared/models/widget"; +import { Component } from "@angular/core"; + +@Component({ + templateUrl: "custom.widget.component.html", + styleUrls: ["custom.widget.component.scss"], +}) +export class CustomWidgetConfigComponent extends NewWidgetComponent { + constructor() { + super(WIDGET_CUSTOM, "Custom Widget", "generic"); + } +} \ No newline at end of file diff --git a/web/app/configs/widget/widget.component.ts b/web/app/configs/widget/widget.component.ts index 3389f25..0edc5e1 100644 --- a/web/app/configs/widget/widget.component.ts +++ b/web/app/configs/widget/widget.component.ts @@ -18,8 +18,8 @@ export class NewWidgetComponent { public isUpdating = false; public widgets: EditableWidget[]; public newWidget: EditableWidget; + public defaultExpandedWidgetId: string; - private toggledWidgetIds: string[] = []; private scalarWrapperUrls: string[] = []; private wrapperUrl = ""; @@ -38,7 +38,7 @@ export class NewWidgetComponent { protected OnWidgetAfterDelete = new EventEmitter(); constructor(private widgetTypes: string[], - private defaultName: string, + public defaultName: string, private wrapperId = "generic", private scalarWrapperId = null) { this.isLoading = true; @@ -64,6 +64,12 @@ export class NewWidgetComponent { this.isLoading = false; this.isUpdating = false; + // We reset after discovering to ensure that the widget component can correctly + // set the state of the widget prior to us unpacking it (again) + for (let widget of this.widgets) { + this.resetWidget(widget); + } + // See if we should request editing a particular widget if (SessionStorage.editWidgetId && SessionStorage.editsRequested === 1) { let editWidget: EditableWidget = null; @@ -78,7 +84,7 @@ export class NewWidgetComponent { console.log("Requesting edit for " + editWidget.id); this.widgets = [editWidget]; otherWidgets.forEach(w => this.widgets.push(w)); - this.editWidget(editWidget); + this.defaultExpandedWidgetId = editWidget.id; } } }); @@ -171,7 +177,6 @@ export class NewWidgetComponent { * @return {string} The unwrapped URL */ private unwrapUrl(url: string): string { - console.log(this.scalarWrapperUrls); if (!this.wrapperUrl) return url; const urls = [this.wrapperUrl].concat(this.scalarWrapperUrls); @@ -225,6 +230,11 @@ export class NewWidgetComponent { * with a new widget. */ public addWidget(): Promise { + if (!this.newWidget.dimension.newUrl || this.newWidget.dimension.newUrl.trim().length === 0) { + this.toaster.pop("warning", "Please enter a URL for the widget"); + return; + } + this.packWidget(this.newWidget); this.isUpdating = true; @@ -260,7 +270,6 @@ export class NewWidgetComponent { this.isUpdating = true; this.OnWidgetBeforeEdit.emit(widget); return this.scalarApi.setWidget(SessionStorage.roomId, widget) - .then(() => this.toggleWidget(widget)) .then(() => { this.isUpdating = false; this.OnWidgetAfterEdit.emit(widget); @@ -296,38 +305,28 @@ export class NewWidgetComponent { } /** - * Puts a widget in the edit state. - * @param {EditableWidget} widget + * Resets a widget to before it had changes made to it + * @param {EditableWidget} widget The widget to reset */ - public editWidget(widget: EditableWidget) { - this.toggleWidget(widget, "edit"); + public resetWidget(widget: EditableWidget) { + this.unpackWidget(widget); + this.OnWidgetPreparedForEdit.emit(widget); } /** - * Toggles a widget between the "edit" and "canceled" state. If a targetState is - * defined, the widget is forced into that state. - * @param {EditableWidget} widget The widget to set the state of. - * @param {"edit"|"cancel"|null} targetState The target state, optional - */ - public toggleWidget(widget: EditableWidget, targetState: "edit" | "cancel" | null = null) { - let idx = this.toggledWidgetIds.indexOf(widget.id); - if (targetState === null) targetState = idx === -1 ? "edit" : "cancel"; - - if (targetState === "edit") { - this.unpackWidget(widget); - this.OnWidgetPreparedForEdit.emit(widget); - - if (idx === -1) this.toggledWidgetIds.push(widget.id); - } - else this.toggledWidgetIds.splice(idx, 1); - } - - /** - * Determines if a widget is in the edit state + * Determines if a widget has had any changes made to it * @param {EditableWidget} widget The widget to check - * @returns {boolean} true if the widget is in the edit state + * @returns {boolean} True if the widget has been edited */ - public isWidgetToggled(widget: EditableWidget) { - return this.toggledWidgetIds.indexOf(widget.id) !== -1; + public hasChanges(widget: EditableWidget):boolean { + if (widget.dimension.newUrl !== this.unwrapUrl(widget.url)) return true; + if (widget.dimension.newName !== widget.name) return true; + if (widget.dimension.newTitle !== widget.data.title) return true; + + const currentData = JSON.parse(JSON.stringify(widget.data || "{}")); + const newData = JSON.parse(JSON.stringify(widget.dimension.newData || "{}")); + if (currentData !== newData) return true; + + return false; } } \ No newline at end of file diff --git a/web/style/app.scss b/web/style/app.scss index 7a3ccb0..50db95e 100644 --- a/web/style/app.scss +++ b/web/style/app.scss @@ -29,4 +29,8 @@ body { button { cursor: pointer; +} + +.label-block { + display: block; } \ No newline at end of file