mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Styling for widgets (mostly)
This commit is contained in:
parent
ebe0048710
commit
a09a4d6b51
@ -13,7 +13,6 @@ import { UiSwitchModule } from "angular2-ui-switch";
|
|||||||
import { ScalarService } from "./shared/services/scalar.service";
|
import { ScalarService } from "./shared/services/scalar.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 { IntegrationComponent } from "./integration/integration.component";
|
|
||||||
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 { IntegrationService } from "./shared/services/integration.service";
|
||||||
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
||||||
@ -29,6 +28,8 @@ import { PageHeaderComponent } from "./page-header/page-header.component";
|
|||||||
import { SpinnerComponent } from "./spinner/spinner.component";
|
import { SpinnerComponent } from "./spinner/spinner.component";
|
||||||
import { BreadcrumbsModule } from "ng2-breadcrumbs";
|
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 { IntegrationComponent } from "./integration/integration.component";
|
||||||
|
|
||||||
const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigComponents();
|
const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigComponents();
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigCo
|
|||||||
HomeComponent,
|
HomeComponent,
|
||||||
RiotComponent,
|
RiotComponent,
|
||||||
IntegrationComponent,
|
IntegrationComponent,
|
||||||
|
IntegrationBagComponent,
|
||||||
PageHeaderComponent,
|
PageHeaderComponent,
|
||||||
SpinnerComponent,
|
SpinnerComponent,
|
||||||
ScalarCloseComponent,
|
ScalarCloseComponent,
|
||||||
|
9
web/app/integration-bag/integration-bag.component.html
Normal file
9
web/app/integration-bag/integration-bag.component.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<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">
|
||||||
|
<img class="integration-avatar" [src]="getSafeUrl(integration.avatar)"/>
|
||||||
|
<div class="integration-name">{{ integration.name }}</div>
|
||||||
|
<div class="integration-description">{{ integration.about }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
37
web/app/integration-bag/integration-bag.component.scss
Normal file
37
web/app/integration-bag/integration-bag.component.scss
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// component styles are encapsulated and only applied to their components
|
||||||
|
.integration-bag {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration {
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 7px;
|
||||||
|
padding: 5px;
|
||||||
|
width: calc(325px - 14px);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration .integration-avatar {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration .integration-name {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 100;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration .integration-description {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-left: 55px;
|
||||||
|
color: #999;
|
||||||
|
}
|
25
web/app/integration-bag/integration-bag.component.ts
Normal file
25
web/app/integration-bag/integration-bag.component.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||||
|
import { Integration } from "../shared/models/integration";
|
||||||
|
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "my-integration-bag",
|
||||||
|
templateUrl: "./integration-bag.component.html",
|
||||||
|
styleUrls: ["./integration-bag.component.scss"],
|
||||||
|
})
|
||||||
|
export class IntegrationBagComponent {
|
||||||
|
|
||||||
|
@Input() integrations: Integration[];
|
||||||
|
@Output() integrationClicked: EventEmitter<Integration> = new EventEmitter<Integration>();
|
||||||
|
|
||||||
|
constructor(private sanitizer: DomSanitizer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSafeUrl(url: string): SafeResourceUrl {
|
||||||
|
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onClick(integration: Integration) {
|
||||||
|
this.integrationClicked.emit(integration);
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,5 @@
|
|||||||
<div class="integration">
|
<div class="integration">
|
||||||
<img [src]="integration.avatar" class="avatar">
|
<img class="integration-avatar" [src]="getSafeUrl(integration.avatar)"/>
|
||||||
<div class="title">
|
<div class="integration-name">{{ integration.name }}</div>
|
||||||
<b>{{ integration.name }}</b>
|
<div class="integration-description">{{ integration.about }}</div>
|
||||||
<div style="display: flex;">
|
|
||||||
<div class="switch" *ngIf="integration.type !== 'bridge' && integration.type !== 'widget'">
|
|
||||||
<ui-switch [checked]="integration.isEnabled" size="small" [disabled]="integration.isBroken"
|
|
||||||
(change)="update()"></ui-switch>
|
|
||||||
</div>
|
|
||||||
<div class="switch" *ngIf="canHaveErrors(integration) && !integration.isEnabled">
|
|
||||||
<i class="fa fa-warning text-warning" ngbTooltip="{{ integration.bridgeError }}"></i>
|
|
||||||
</div>
|
|
||||||
<div class="toolbar">
|
|
||||||
<i class="fa fa-question-circle text-info" ngbTooltip="{{integration.about}}"
|
|
||||||
*ngIf="integration.about"></i>
|
|
||||||
<i class="fa fa-cog text-info config-icon" (click)="configureIntegration()"
|
|
||||||
*ngIf="integration.isEnabled && integration.hasConfig"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="clear: both;"></div>
|
|
||||||
</div>
|
</div>
|
@ -1,38 +1,31 @@
|
|||||||
// component styles are encapsulated and only applied to their components
|
// component styles are encapsulated and only applied to their components
|
||||||
.integration {
|
.integration {
|
||||||
flex: auto;
|
border: 1px solid #eee;
|
||||||
margin: 5px;
|
border-radius: 3px;
|
||||||
padding: 10px;
|
margin-left: 7px;
|
||||||
border: 1px solid #ccc;
|
margin-right: 7px;
|
||||||
border-radius: 4px;
|
padding: 5px;
|
||||||
min-width: 150px;
|
width: calc(325px - 14px);
|
||||||
background-color: white;
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.integration .integration-avatar {
|
||||||
float: left;
|
|
||||||
margin-right: 7px;
|
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
border-radius: 50px;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.integration .integration-name {
|
||||||
float: right;
|
|
||||||
width: calc(100% - 57px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
font-size: 1.1em;
|
||||||
|
font-weight: 100;
|
||||||
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
.integration .integration-description {
|
||||||
display: inline-block;
|
display: block;
|
||||||
vertical-align: top;
|
font-size: 0.8em;
|
||||||
margin-left: 5px;
|
margin-left: 55px;
|
||||||
}
|
color: #999;
|
||||||
|
|
||||||
.config-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
@ -1,8 +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 { Integration } from "../shared/models/integration";
|
||||||
import { overlayConfigFactory } from "ngx-modialog";
|
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||||
import { BSModalContext, Modal } from "ngx-modialog/plugins/bootstrap";
|
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
||||||
import { IntegrationService } from "../shared/services/integration.service";
|
|
||||||
|
|
||||||
export class ConfigModalContext extends BSModalContext {
|
export class ConfigModalContext extends BSModalContext {
|
||||||
public integration: Integration;
|
public integration: Integration;
|
||||||
@ -20,30 +19,12 @@ export class ConfigModalContext extends BSModalContext {
|
|||||||
export class IntegrationComponent {
|
export class IntegrationComponent {
|
||||||
|
|
||||||
@Input() integration: Integration;
|
@Input() integration: Integration;
|
||||||
@Input() roomId: string;
|
@Output() selected: EventEmitter<any> = new EventEmitter<any>();
|
||||||
@Input() scalarToken: string;
|
|
||||||
@Output() updated: EventEmitter<any> = new EventEmitter();
|
|
||||||
|
|
||||||
constructor(public modal: Modal) {
|
constructor(private sanitizer: DomSanitizer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(): void {
|
public getSafeUrl(url: string): SafeResourceUrl {
|
||||||
this.integration.isEnabled = !this.integration.isEnabled;
|
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
||||||
this.updated.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public configureIntegration(integrationId: string = null): void {
|
|
||||||
this.modal.open(IntegrationService.getConfigComponent(this.integration), overlayConfigFactory({
|
|
||||||
integration: this.integration,
|
|
||||||
roomId: this.roomId,
|
|
||||||
scalarToken: this.scalarToken,
|
|
||||||
isBlocking: false,
|
|
||||||
integrationId: integrationId,
|
|
||||||
size: "lg"
|
|
||||||
}, BSModalContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
public canHaveErrors(integration: Integration): boolean {
|
|
||||||
return integration.type === "bridge" || integration.type === "widget";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,14 +35,10 @@
|
|||||||
<div *ngFor="let category of getCategories()">
|
<div *ngFor="let category of getCategories()">
|
||||||
<div class="ibox" *ngIf="getIntegrationsIn(category).length > 0">
|
<div class="ibox" *ngIf="getIntegrationsIn(category).length > 0">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<h4>{{ category }}</h4>
|
<h5>{{ category }}</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<div class="integration" *ngFor="let integration of getIntegrationsIn(category)">
|
<my-integration-bag [integrations]="getIntegrationsIn(category)"></my-integration-bag>
|
||||||
<img class="integration-avatar" [src]="getSafeUrl(integration.avatar)"/>
|
|
||||||
<div class="integration-name">{{ integration.name }}</div>
|
|
||||||
<div class="integration-description">{{ integration.about }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,6 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { ApiService } from "../../shared/services/api.service";
|
import { ApiService } from "../../shared/services/api.service";
|
||||||
import { ScalarService } from "../../shared/services/scalar.service";
|
import { ScalarService } from "../../shared/services/scalar.service";
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
|
||||||
|
|
||||||
const CATEGORY_MAP = {
|
const CATEGORY_MAP = {
|
||||||
"Widgets": ["widget"],
|
"Widgets": ["widget"],
|
||||||
@ -33,14 +32,13 @@ export class RiotHomeComponent {
|
|||||||
private userId: string;
|
private userId: string;
|
||||||
private requestedScreen: string = null;
|
private requestedScreen: string = null;
|
||||||
private requestedIntegration: string = null;
|
private requestedIntegration: string = null;
|
||||||
private integrationsForCategory: { [category: string]: Integration[] } = {};
|
public integrationsForCategory: { [category: string]: Integration[] } = {};
|
||||||
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 api: ApiService,
|
||||||
private scalar: ScalarService,
|
private scalar: ScalarService,
|
||||||
private toaster: ToasterService,
|
private toaster: ToasterService) {
|
||||||
private sanitizer: DomSanitizer) {
|
|
||||||
let params: any = this.activatedRoute.snapshot.queryParams;
|
let params: any = this.activatedRoute.snapshot.queryParams;
|
||||||
|
|
||||||
this.requestedScreen = params.screen;
|
this.requestedScreen = params.screen;
|
||||||
@ -75,10 +73,6 @@ export class RiotHomeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSafeUrl(url: string): SafeResourceUrl {
|
|
||||||
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public hasIntegrations(): boolean {
|
public hasIntegrations(): boolean {
|
||||||
for (const category of this.getCategories()) {
|
for (const category of this.getCategories()) {
|
||||||
if (this.getIntegrationsIn(category).length > 0) return true;
|
if (this.getIntegrationsIn(category).length > 0) return true;
|
||||||
@ -196,7 +190,8 @@ export class RiotHomeComponent {
|
|||||||
if (opened) return;
|
if (opened) return;
|
||||||
if (component.integration.type !== type || component.integration.integrationType !== integrationType) return;
|
if (component.integration.type !== type || component.integration.integrationType !== integrationType) return;
|
||||||
console.log("Configuring integration " + this.requestedIntegration + " type=" + type + " integrationType=" + integrationType);
|
console.log("Configuring integration " + this.requestedIntegration + " type=" + type + " integrationType=" + integrationType);
|
||||||
component.configureIntegration(this.requestedIntegration);
|
//component.configureIntegration(this.requestedIntegration);
|
||||||
|
// TODO: Support editing integrations
|
||||||
opened = true;
|
opened = true;
|
||||||
});
|
});
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
|
@ -6,5 +6,4 @@ import { Component } from "@angular/core";
|
|||||||
styleUrls: ["./riot.component.scss"],
|
styleUrls: ["./riot.component.scss"],
|
||||||
})
|
})
|
||||||
export class RiotComponent {
|
export class RiotComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// styles in src/style directory are applied to the whole page
|
// styles in src/style directory are applied to the whole page
|
||||||
@import url('https://fonts.googleapis.com/css?family=Open+Sans:100|Roboto:300');
|
@import url('https://fonts.googleapis.com/css?family=Open+Sans:100|Roboto:300');
|
||||||
@import '../../node_modules/angular2-toaster/toaster';
|
@import '../../node_modules/angular2-toaster/toaster';
|
||||||
|
@import "components/ibox.scss";
|
||||||
@import "riot";
|
@import "riot";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
22
web/style/components/ibox.scss
Normal file
22
web/style/components/ibox.scss
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
.ibox {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ibox .ibox-title {
|
||||||
|
padding: 5px;
|
||||||
|
border-bottom: 1px solid #e7eaec;
|
||||||
|
border-top: 2px solid #e7eaec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ibox .ibox-title h5 {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.1em;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ibox .ibox-content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user