Skip to content

Commit 9065237

Browse files
committed
#107 first merge commit.
1 parent 80abb0a commit 9065237

47 files changed

Lines changed: 6613 additions & 1586 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/webapp/app/entities/dashboard/dashboard-detail.component.html

Lines changed: 246 additions & 134 deletions
Large diffs are not rendered by default.

src/main/webapp/app/entities/dashboard/dashboard-detail.component.ts

Lines changed: 89 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* limitations under the License.
1818
* #L%
1919
*/
20-
import { Component, OnInit, OnDestroy, AfterViewInit, AfterViewChecked, Input } from '@angular/core';
20+
import { Component, OnInit, OnDestroy, AfterViewInit, AfterViewChecked, Input, ViewChildren, QueryList } from '@angular/core';
2121
import { ActivatedRoute } from '@angular/router';
2222
import { Subscription, Observable } from 'rxjs/Rx';
2323
import { JhiEventManager } from 'ng-jhipster';
@@ -32,9 +32,10 @@ import { DragulaService } from 'ng2-dragula';
3232
import * as $ from 'jquery';
3333
import { NotificationService } from '../../shared/services/notification.service';
3434
import { Principal } from '../../shared/auth/principal.service';
35-
import { Widget, MessageType, EmbedResourceModalComponent, ShareableResourceType } from '../widget';
35+
import { Widget, MessageType, EmbedResourceModalComponent, ShareableResourceType, WidgetType, QueryWidgetComponent } from '../widget';
3636
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
3737
import { BsModalRef, BsModalService } from 'ngx-bootstrap';
38+
import { forwardRef } from '@angular/core';
3839

3940
declare var CKEDITOR: any;
4041

@@ -70,6 +71,12 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
7071

7172
alreadySavingDashboardMessage: boolean = false;
7273

74+
// query widgets options
75+
queryWidgetId2executionOptions: Object;
76+
@ViewChildren(forwardRef(() => QueryWidgetComponent))
77+
queryWidgets: QueryList<QueryWidgetComponent>;
78+
minimumTimeoutWindow: number;
79+
7380
// styles and widgets sizing
7481
panelHeadingHeight: string = '40px';
7582
widgetContainerPadding: string = '5px';
@@ -133,6 +140,8 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
133140
direction: 'vertical'
134141
});
135142

143+
this.minimumTimeoutWindow = this.principal['userIdentity']['contract']['pollingInterval'];
144+
136145
this.dragendSubscription = this.dragulaService.dragend('bag-items').subscribe((element) => {
137146
this.saveDashboardWithCurrentLayout();
138147

@@ -237,10 +246,19 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
237246
this.gridStepValue = Math.round((1 / 12) * this.widgetsContainerWidth);
238247

239248
this.gridStep2size = {
249+
'1': (this.gridStepValue) - this.doublePadding,
240250
'2': (2 * this.gridStepValue) - this.doublePadding,
241251
'3': (3 * this.gridStepValue) - this.doublePadding,
242252
'4': (4 * this.gridStepValue) - this.doublePadding,
243-
'5': (5 * this.gridStepValue) - this.doublePadding
253+
'5': (5 * this.gridStepValue) - this.doublePadding,
254+
'6': (6 * this.gridStepValue) - this.doublePadding,
255+
'7': (7 * this.gridStepValue) - this.doublePadding,
256+
'8': (8 * this.gridStepValue) - this.doublePadding,
257+
'9': (9 * this.gridStepValue) - this.doublePadding,
258+
'10': (10 * this.gridStepValue) - this.doublePadding,
259+
'11': (11 * this.gridStepValue) - this.doublePadding,
260+
'12': (12 * this.gridStepValue) - this.doublePadding
261+
244262
};
245263
this.heightsForCloseness = [];
246264
for (const key of Object.keys(this.gridStep2size)) {
@@ -261,7 +279,7 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
261279
enableResizingForAllWidgets() {
262280
for (const widget of this.dashboard['widgets']) {
263281
const currentLayoutWidgetInfo = this.dashboard['layout']['widgetsLayoutInfo'].get(widget['id']);
264-
this.widgetActivateResizing(currentLayoutWidgetInfo['widgetId'], currentLayoutWidgetInfo['width']);
282+
this.widgetActivateResizing(currentLayoutWidgetInfo['widgetId'], (<Widget>widget).type, currentLayoutWidgetInfo['width']);
265283
}
266284
}
267285

@@ -359,6 +377,11 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
359377
// through the dashboard select in the top navbar
360378
this.initWidgetsWithDeafultLayout();
361379
}
380+
if (this.widgetsLayoutsLoaded) {
381+
// case: we init the default layouts for all the widgets in a dashboard loaded
382+
// through the dashboard select in the top navbar
383+
this.initWidgetsWithDeafultLayout();
384+
}
362385
} else {
363386
// adding widgets following the layout order
364387
this.dashboard['layout']['widgetsLayoutInfo'].forEach((value, widgetInfoKey) => {
@@ -381,6 +404,9 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
381404
for (const widget of this.dashboard['widgets']) {
382405
const height: string = this.defaultWidgetHeight + 'px';
383406
const layout = this.buildDeaultLayoutInfo(widget.id, height);
407+
if (widget['type'] === WidgetType.QUERY) {
408+
layout['width'] = 12;
409+
}
384410
this.dashboard.addWidgetLayoutInfo(layout);
385411
}
386412
this.widgetsLayoutsLoaded = true;
@@ -405,17 +431,28 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
405431

406432
if (response.eventOccurred === 'new-widget') {
407433
const height: string = this.defaultWidgetHeight + 'px';
408-
const defaultLayoutOptions = this.buildDeaultLayoutInfo(response.content.id, height);
409434
const widget = response.content;
435+
const defaultLayoutOptions = this.buildDeaultLayoutInfo(response.content.id, height);
436+
if (widget['type'] === WidgetType.QUERY) {
437+
defaultLayoutOptions['width'] = 12;
438+
}
410439
this.dashboard.addWidget(widget);
411440
if (!this.dashboard['layout']['widgetsLayoutInfo']) {
412441
this.dashboard['layout']['widgetsLayoutInfo'] = new Map();
413442
}
414443
this.dashboard['layout']['widgetsLayoutInfo'].set(defaultLayoutOptions['widgetId'], defaultLayoutOptions);
415444
setTimeout(() => { // waiting for the panel is rendered
416-
this.widgetActivateResizing(defaultLayoutOptions['widgetId'], defaultLayoutOptions['width']);
445+
this.widgetActivateResizing(defaultLayoutOptions['widgetId'], widget.type, defaultLayoutOptions['width']);
417446
}, 50);
418447

448+
// if the new widget is a query-widget we have to update the handle the external options (auto-update flag and auto-update interval)
449+
if (widget.type === WidgetType.QUERY) {
450+
this.queryWidgetId2executionOptions[widget['id']] = {
451+
autoUpdate: false,
452+
autoUpdateIntervalWindow: this.principal['userIdentity']['contract']['pollingInterval']
453+
};
454+
}
455+
419456
// if the dashboard is shared, the new widget will be shared too
420457
if (this.dashboard['shared']) {
421458
widget['shared'] = true;
@@ -431,7 +468,7 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
431468
this.dashboard.updateWidget(editedWidget);
432469
setTimeout(() => { // waiting for the panel is rendered
433470
const widgetLayout = this.dashboard['layout']['widgetsLayoutInfo'].get(editedWidgetId);
434-
this.widgetActivateResizing(editedWidgetId, widgetLayout['width']);
471+
this.widgetActivateResizing(editedWidgetId, editedWidget.type, widgetLayout['width']);
435472
}, 50);
436473
} else if (response.eventOccurred === 'widget-removed') {
437474
const currentRemovingWidgetId: number = response.content;
@@ -523,7 +560,6 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
523560

524561
if (saveAllowed) {
525562

526-
const infoNotification = this.notificationService.push('info', 'Save', 'Saving the Dashboard layout...', 3000, 'fa fa-spinner fa-spin');
527563
const delay: number = 10;
528564

529565
setTimeout(() => {
@@ -545,11 +581,12 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
545581
delete dashboardCopy['widgets'];
546582

547583
this.dashboardService.update(dashboardCopy).subscribe((res) => {
548-
const message: string = 'Dashboard correctly saved.';
549-
this.notificationService.updateNotification(infoNotification, 'success', 'Save', message, undefined, true);
584+
console.log('Dashboard correctly saved.');
550585
this.alreadySavingDashboardMessage = false;
551586
}, (err: HttpErrorResponse) => {
552-
this.notificationService.updateNotification(infoNotification, 'error', 'Save', 'Saving attempt failed.', undefined, true);
587+
const message = `Implicit dashboard saving failed. Current dashboard status will not be available at the next application loading.\n
588+
Try to check the server connection.`;
589+
this.notificationService.push('error', 'Dashboard Save', message, undefined, true);
553590
console.log(err.message);
554591
this.alreadySavingDashboardMessage = false;
555592
});
@@ -585,15 +622,52 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
585622
});
586623
}
587624

588-
widgetActivateResizing(widgetId, originalColumnWidth) {
625+
updateQueryWidget(queryWidgetId: number) {
626+
(<QueryWidgetComponent>this.getQueryWidgetById(queryWidgetId)).performLastDataFetching();
627+
}
628+
629+
updateQueryWidgetAutoUpdateFlag(queryWidgetId: number) {
630+
const queryWidget = (<QueryWidgetComponent>this.getQueryWidgetById(queryWidgetId));
631+
queryWidget.handleAutoUpdateFlagChange();
632+
queryWidget.saveAll(true);
633+
}
634+
635+
updateQueryWidgetAutoUpdateInterval(queryWidgetId: number, autoUpdateInterval: number) {
636+
const queryWidget = (<QueryWidgetComponent>this.getQueryWidgetById(queryWidgetId));
637+
queryWidget.handleAutoUpdateIntervalChange();
638+
queryWidget.saveAll(true);
639+
}
640+
641+
getQueryWidgetById(queryWidgetId: number) {
642+
return this.queryWidgets.find((queryWidget) => queryWidget['widget']['id'] === queryWidgetId);
643+
}
644+
645+
/**
646+
* Activates the resizable function on all the widgets' panels.
647+
* @param widgetId
648+
* @param originalColumnWidth number of bootstrap columns, e.g. 1,2,3...6
649+
*/
650+
widgetActivateResizing(widgetId: number, widgetType: WidgetType,originalColumnWidth: number) {
589651

590652
const originalPxWidth = (<any>$('#panel_' + widgetId)).width();
591653

654+
let minimumWidth;
655+
let minimumHeight;
656+
if (widgetType === WidgetType.QUERY) {
657+
// overriding minimum width grid step to 12 and minimun height to 1 for Query Widgets
658+
minimumWidth = this.gridStep2size['12'] - 10; // 10 is just a little threshold, as the minimum width is not included in the available range
659+
minimumHeight = this.gridStep2size['1'];
660+
} else {
661+
minimumWidth = this.minimumWidth;
662+
minimumHeight = this.minimumHeight;
663+
}
664+
592665
(<any>$('#panel_' + widgetId)).resizable({
666+
593667
grid: this.gridStepValue,
594-
minWidth: this.minimumWidth,
668+
minWidth: minimumWidth,
595669
maxWidth: this.maximumWidth,
596-
minHeight: this.minimumHeight, // minimum height chosen according to the minimum width
670+
minHeight: minimumHeight,
597671
maxHeight: this.maximumHeight,
598672
handleSelector: '.panel',
599673
resizeWidth: true,
@@ -611,6 +685,7 @@ export class DashboardDetailComponent implements OnInit, AfterViewInit, AfterVie
611685
const newPxWidth = newUiWidth;
612686
let newColumnWidth = (newPxWidth * originalColumnWidth) / originalPxWidth; // originalPxWidth/originalColumnWidth = newPxWidth/newColumnWidth
613687
newColumnWidth = Math.round(newColumnWidth);
688+
614689
this.dashboard['layout']['widgetsLayoutInfo'].get(widgetId)['width'] = newColumnWidth;
615690

616691
// height resizing

src/main/webapp/app/entities/data-source/data-source-dialog.component.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export class DataSourceDialogComponent implements OnInit, AfterViewChecked {
106106
{
107107
type: 'HSQL',
108108
name: 'Hyper SQL'
109-
},
109+
} ,
110110
{
111111
type: 'DATA_WORLD',
112112
name: 'Data World (Beta)'
@@ -428,13 +428,13 @@ export class DataSourceDialogComponent implements OnInit, AfterViewChecked {
428428

429429
this.populateConnectionPropertiesFieldFromTable();
430430
this.dataSourceService.testConnection(this.dataSource).subscribe((res: Object) => {
431-
const message = 'Connection alive';
432-
this.notificationService.updateNotification(infoNotification, 'success', 'Data Source Connection', message, undefined, true);
433-
}, (error: HttpErrorResponse) => {
434-
const message = 'Connection NOT alive';
435-
this.notificationService.updateNotification(infoNotification, 'error', 'Data Source Connection', message, undefined, true);
436-
console.log(error.message);
437-
});
431+
const message = 'Connection alive';
432+
this.notificationService.updateNotification(infoNotification, 'success', 'Data Source Connection', message, undefined, true);
433+
}, (error: HttpErrorResponse) => {
434+
const message = 'Connection NOT alive';
435+
this.notificationService.updateNotification(infoNotification, 'error', 'Data Source Connection', message, undefined, true);
436+
console.log(error.message);
437+
});
438438
}
439439

440440
save() {
@@ -443,12 +443,12 @@ export class DataSourceDialogComponent implements OnInit, AfterViewChecked {
443443
// saving datasource type
444444
this.updateDatasourceType();
445445

446-
this.populateConnectionPropertiesFieldFromTable();
446+
this.populateConnectionPropertiesFieldFromTable();
447447

448-
// if description is empty it will be filled with the datasource name
449-
if (!this.dataSource['description']) {
450-
this.dataSource['description'] = this.dataSource['name'];
451-
}
448+
// if description is empty it will be filled with the datasource name
449+
if (!this.dataSource['description']) {
450+
this.dataSource['description'] = this.dataSource['name'];
451+
}
452452

453453
if (this.dataSource.id !== undefined) {
454454
this.subscribeToSaveResponse(

src/main/webapp/app/entities/widget/implementation/common-menu/snapshot-menu.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
<tbody>
44
<tr *ngFor="let snapshotName of snapshotNames">
55
<td class="snapshotItem"><a (click)="loadSnapshotByName(snapshotName)">{{snapshotName}}</a></td>
6+
<td class="snapshotDeleteCommand">
7+
<button class="btn btn-danger btn-xs" type="button" (click)="deleteSnapshotByName(snapshotName)" title="Delete">
8+
<span class="fa fa-trash"></span>
9+
</button>
610
</tr>
711
</tbody>
812
</table>

src/main/webapp/app/entities/widget/implementation/common-menu/snapshot-menu.component.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class SnapshotMenuComponent implements OnInit, OnDestroy, OnChanges, Afte
3030

3131
@Input() widgetId: number;
3232
@Output() snapshotLoaded: EventEmitter<Object> = new EventEmitter();
33+
@Output() noSnapshotAvailable: EventEmitter<Object> = new EventEmitter();
3334
snapshotNames: string[];
3435
loadedSnapshot: Object;
3536

@@ -38,11 +39,11 @@ export class SnapshotMenuComponent implements OnInit, OnDestroy, OnChanges, Afte
3839
this.snapshotNames = [];
3940
}
4041

41-
ngOnInit() {}
42+
ngOnInit() { }
4243

43-
ngOnDestroy() {}
44+
ngOnDestroy() { }
4445

45-
ngAfterViewInit() {}
46+
ngAfterViewInit() { }
4647

4748
ngOnChanges(changes: SimpleChanges): void {
4849
if (changes.widgetId) {
@@ -53,18 +54,35 @@ export class SnapshotMenuComponent implements OnInit, OnDestroy, OnChanges, Afte
5354
loadSnapshotsNames() {
5455
this.widgetService.loadSnapshotsNames(this.widgetId).subscribe((res: string[]) => {
5556
this.snapshotNames = res;
57+
if (this.snapshotNames.length === 0) {
58+
this.noSnapshotAvailable.emit();
59+
}
5660
});
5761
}
5862

59-
loadSnapshotByName(snaphotName: string) {
63+
loadSnapshotByName(snapshotName: string) {
6064
const request = {
61-
fileName: snaphotName
65+
fileName: snapshotName
6266
};
6367
this.widgetService.loadSnapshot(this.widgetId, request).subscribe((snapshot: Object) => {
6468
this.loadedSnapshot = snapshot;
6569
this.snapshotLoaded.emit(this.loadedSnapshot);
66-
this.loadedSnapshot = undefined;
70+
this.loadedSnapshot = undefined;
6771
});
6872
}
6973

74+
deleteSnapshotByName(snapshotName: string) {
75+
const request = {
76+
fileName: snapshotName
77+
};
78+
this.widgetService.deleteSnapshot(this.widgetId, request).subscribe((snapshotCorrectlyDeleted: boolean) => {
79+
if (snapshotCorrectlyDeleted) {
80+
this.notificationService.push('success', 'Snapshot delete', 'Snapshot correctly deleted.');
81+
}
82+
});
83+
84+
// reload menu items
85+
this.loadSnapshotsNames();
86+
}
87+
7088
}

0 commit comments

Comments
 (0)