mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
translation
- the traslation feature without the changes from other branches
This commit is contained in:
parent
db2298172f
commit
9dc4e99aca
670
package-lock.json
generated
670
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,8 @@
|
||||
},
|
||||
"author": "Travis Ralston",
|
||||
"dependencies": {
|
||||
"@ngx-translate/core": "^12.1.2",
|
||||
"@ngx-translate/http-loader": "^6.0.0",
|
||||
"@types/bluebird": "^3.5.27",
|
||||
"@types/body-parser": "^1.17.0",
|
||||
"@types/node": "^12.0.10",
|
||||
@ -46,10 +48,10 @@
|
||||
"semver": "^6.0.0",
|
||||
"sequelize": "^5.18.4",
|
||||
"sequelize-typescript": "^1.0.0",
|
||||
"sharp": "^0.21.1",
|
||||
"sharp": "^0.26.0",
|
||||
"split-host": "^0.1.1",
|
||||
"spotify-uri": "^1.0.0",
|
||||
"sqlite3": "^4.0.9",
|
||||
"sqlite3": "^4.2.0",
|
||||
"telegraf": "^3.30.1",
|
||||
"typescript": "^3.5.2",
|
||||
"typescript-ioc": "^1.2.5",
|
||||
@ -100,7 +102,7 @@
|
||||
"mini-css-extract-plugin": "^0.7.0",
|
||||
"ng2-breadcrumbs": "^0.1.281",
|
||||
"ngx-modialog": "^5.0.1",
|
||||
"node-sass": "^4.12.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"postcss-cssnext": "^3.1.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
|
@ -1,11 +1,11 @@
|
||||
<ul class="adminNav">
|
||||
<li (click)="goto('')" [ngClass]="[isActive('', true) ? 'active' : '']">Dashboard</li>
|
||||
<li (click)="goto('widgets')" [ngClass]="[isActive('widgets') ? 'active' : '']">Widgets</li>
|
||||
<li (click)="goto('neb')" [ngClass]="[isActive('neb') ? 'active' : '']">go-neb</li>
|
||||
<li (click)="goto('custom-bots')" [ngClass]="[isActive('custom-bots') ? 'active' : '']">Custom Bots</li>
|
||||
<li (click)="goto('bridges')" [ngClass]="[isActive('bridges') ? 'active' : '']">Bridges</li>
|
||||
<li (click)="goto('stickerpacks')" [ngClass]="[isActive('stickerpacks') ? 'active' : '']">Sticker Packs</li>
|
||||
<li (click)="goto('terms')" [ngClass]="[isActive('terms') ? 'active' : '']">Terms of Service</li>
|
||||
<li (click)="goto('')" [ngClass]="[isActive('', true) ? 'active' : '']">{{'Dashboard' | translate}}</li>
|
||||
<li (click)="goto('widgets')" [ngClass]="[isActive('widgets') ? 'active' : '']">{{'Widgets' | translate}}</li>
|
||||
<li (click)="goto('neb')" [ngClass]="[isActive('neb') ? 'active' : '']">{{'go-neb' | translate}}</li>
|
||||
<li (click)="goto('custom-bots')" [ngClass]="[isActive('custom-bots') ? 'active' : '']">{{'Custom Bots' | translate}}</li>
|
||||
<li (click)="goto('bridges')" [ngClass]="[isActive('bridges') ? 'active' : '']">{{'Bridges' | translate}}</li>
|
||||
<li (click)="goto('stickerpacks')" [ngClass]="[isActive('stickerpacks') ? 'active' : '']">{{'Sticker Packs' | translate}}</li>
|
||||
<li (click)="goto('terms')" [ngClass]="[isActive('terms') ? 'active' : '']">{{'Terms of Service' | translate}}</li>
|
||||
</ul>
|
||||
<span class="version">{{ version }}</span>
|
||||
|
||||
|
@ -5,25 +5,24 @@
|
||||
<my-ibox boxTitle="Bridges">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For
|
||||
example, an IRC bridge can allow IRC and matrix users to communicate with each other.
|
||||
{{'Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th>{{'Description' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!bridges || bridges.length === 0">
|
||||
<td colspan="3"><i>No bridges.</i></td>
|
||||
<td colspan="3"><i>{{'No bridges.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of bridges trackById">
|
||||
<td>{{ bridge.displayName }}</td>
|
||||
<td>{{ bridge.description }}</td>
|
||||
<td>{{ bridge.displayName | translate }}</td>
|
||||
<td>{{ bridge.description | translate }}</td>
|
||||
<td class="text-center">
|
||||
<span class="editButton" [routerLink]="[bridge.type]" title="edit">
|
||||
<i class="fa fa-pencil-alt"></i>
|
||||
|
@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { ToasterService } from "angular2-toaster";
|
||||
import { FE_Bridge } from "../../shared/models/integration";
|
||||
import { AdminIntegrationsApiService } from "../../shared/services/admin/admin-integrations-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./bridges.component.html",
|
||||
@ -13,7 +14,8 @@ export class AdminBridgesComponent implements OnInit {
|
||||
public bridges: FE_Bridge<any>[];
|
||||
|
||||
constructor(private adminIntegrations: AdminIntegrationsApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService, public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -22,7 +24,7 @@ export class AdminBridgesComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load bridges");
|
||||
this.translate.get('Failed to load bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,20 @@
|
||||
<my-ibox boxTitle="Gitter Bridge Configurations">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
<a href="https://github.com/matrix-org/matrix-appservice-gitter" target="_blank">matrix-appservice-gitter</a>
|
||||
is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a
|
||||
single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.
|
||||
<a href="https://github.com/matrix-org/matrix-appservice-gitter" target="_blank">{{'matrix-appservice-gitter' | translate}}</a>
|
||||
{{'is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="2"><i>No bridge configurations.</i></td>
|
||||
<td colspan="2"><i>{{'No bridge configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of configurations trackById">
|
||||
<td>
|
||||
@ -37,11 +36,11 @@
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addModularHostedBridge()"
|
||||
[disabled]="(configurations && configurations.length > 0) || isUpdating">
|
||||
<i class="fa fa-plus"></i> Add matrix.org's bridge
|
||||
<i class="fa fa-plus"></i>{{'Add matrix.org\'s bridge' | translate}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedBridge()"
|
||||
[disabled]="(configurations && configurations.length > 0) || isUpdating">
|
||||
<i class="fa fa-plus"></i> Add self-hosted bridge
|
||||
<i class="fa fa-plus"></i>{{'Add self-hosted bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -9,6 +9,7 @@ import { AdminGitterApiService } from "../../../shared/services/admin/admin-gitt
|
||||
import { FE_GitterBridge } from "../../../shared/models/gitter";
|
||||
import { FE_Upstream } from "../../../shared/models/admin-responses";
|
||||
import { AdminUpstreamApiService } from "../../../shared/services/admin/admin-upstream-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./gitter.component.html",
|
||||
@ -25,7 +26,9 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
constructor(private gitterApi: AdminGitterApiService,
|
||||
private upstreamApi: AdminUpstreamApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -38,7 +41,7 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
this.configurations = await this.gitterApi.getBridges();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading bridges");
|
||||
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); } );
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,12 +51,12 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
const createBridge = (upstream: FE_Upstream) => {
|
||||
return this.gitterApi.newFromUpstream(upstream).then(bridge => {
|
||||
this.configurations.push(bridge);
|
||||
this.toaster.pop("success", "matrix.org's Gitter bridge added");
|
||||
this.translate.get('matrix.org\'s Gitter bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.isUpdating = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error adding matrix.org's Gitter Bridge");
|
||||
this.translate.get('Error adding matrix.org\'s Gitter Bridge').subscribe((res: string) => {this.toaster.pop("error", res); } );
|
||||
});
|
||||
};
|
||||
|
||||
@ -66,7 +69,7 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
createBridge(upstream);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error creating matrix.org's Gitter Bridge");
|
||||
this.translate.get('Error creating matrix.org\'s Gitter Bridge').subscribe((res: string) => {this.toaster.pop("error", res); } );
|
||||
});
|
||||
} else createBridge(vectorUpstreams[0]);
|
||||
}
|
||||
@ -80,7 +83,7 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedGitterBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Gitter bridge list");
|
||||
this.translate.get('Failed to get an update Gitter bridge list').subscribe((res: string) => {this.toaster.pop("error", res); } );
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -95,7 +98,7 @@ export class AdminGitterBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedGitterBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Gitter bridge list");
|
||||
this.translate.get('Failed to get an update Gitter bridge list').subscribe((res: string) => {this.toaster.pop("error", res); } );
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} self-hosted Gitter bridge</h4>
|
||||
<h4> {{'self-hosted Gitter bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>
|
||||
Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public
|
||||
internet.
|
||||
{{'Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.' | translate}}
|
||||
</p>
|
||||
|
||||
<label class="label-block">
|
||||
Provisioning URL
|
||||
<span class="text-muted ">The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.</span>
|
||||
{{'Provisioning URL' | translate}}
|
||||
<span class="text-muted ">
|
||||
{{'The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.' | translate}}
|
||||
</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="http://localhost:9000"
|
||||
[(ngModel)]="provisionUrl" [disabled]="isSaving"/>
|
||||
@ -18,10 +19,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminGitterApiService } from "../../../../shared/services/admin/admin-gitter-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class ManageSelfhostedGitterBridgeDialogContext extends BSModalContext {
|
||||
public provisionUrl: string;
|
||||
@ -22,7 +23,9 @@ export class AdminGitterBridgeManageSelfhostedComponent implements ModalComponen
|
||||
|
||||
constructor(public dialog: DialogRef<ManageSelfhostedGitterBridgeDialogContext>,
|
||||
private gitterApi: AdminGitterApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.provisionUrl = dialog.context.provisionUrl;
|
||||
this.bridgeId = dialog.context.bridgeId;
|
||||
this.isAdding = !this.bridgeId;
|
||||
@ -32,21 +35,21 @@ export class AdminGitterBridgeManageSelfhostedComponent implements ModalComponen
|
||||
this.isSaving = true;
|
||||
if (this.isAdding) {
|
||||
this.gitterApi.newSelfhosted(this.provisionUrl).then(() => {
|
||||
this.toaster.pop("success", "Gitter bridge added");
|
||||
this.translate.get('Gitter bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to create Gitter bridge");
|
||||
this.translate.get('Failed to create Gitter bridge').subscribe((res: string) => { this.toaster.pop("error", res); });
|
||||
});
|
||||
} else {
|
||||
this.gitterApi.updateSelfhosted(this.bridgeId, this.provisionUrl).then(() => {
|
||||
this.toaster.pop("success", "Gitter bridge updated");
|
||||
this.translate.get('Gitter bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to update Gitter bridge");
|
||||
this.translate.get('Failed to update Gitter bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Add a new self-hosted IRC Bridge</h4>
|
||||
<h4>{{'Add a new self-hosted IRC Bridge' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>Self-hosted IRC bridges must have <code>provisioning</code> enabled in the configuration.</p>
|
||||
<p>{{'Self-hosted IRC bridges must have' | translate}}<code>{{'provisioning' | translate}}</code> {{'enabled in the configuration.' | translate}}</p>
|
||||
|
||||
<label class="label-block">
|
||||
Provisioning URL
|
||||
<span class="text-muted ">The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.</span>
|
||||
{{'Provisioning URL' | translate}}
|
||||
<span class="text-muted ">{{'The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="http://localhost:9999"
|
||||
[(ngModel)]="provisionUrl" [disabled]="isSaving"/>
|
||||
@ -15,10 +15,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminIrcApiService } from "../../../../shared/services/admin/admin-irc-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class AddSelfhostedIrcBridgeDialogContext extends BSModalContext {
|
||||
}
|
||||
@ -18,18 +19,20 @@ export class AdminIrcBridgeAddSelfhostedComponent implements ModalComponent<AddS
|
||||
|
||||
constructor(public dialog: DialogRef<AddSelfhostedIrcBridgeDialogContext>,
|
||||
private ircApi: AdminIrcApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public add() {
|
||||
this.isSaving = true;
|
||||
this.ircApi.newSelfhosted(this.provisionUrl).then(() => {
|
||||
this.toaster.pop("success", "IRC Bridge added");
|
||||
this.translate.get('IRC Bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to create IRC bridge");
|
||||
this.translate.get('Failed to create IRC bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,22 +5,21 @@
|
||||
<my-ibox boxTitle="IRC Bridge Configurations">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
<a href="https://github.com/matrix-org/matrix-appservice-irc" target="_blank">matrix-appservice-irc</a>
|
||||
is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC
|
||||
bridges to better distribute the load across multiple networks in large deployments.
|
||||
<a href="https://github.com/matrix-org/matrix-appservice-irc" target="_blank">{{'matrix-appservice-irc' | translate}}</a>
|
||||
{{'is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enabled Networks</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Enabled Networks' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="3"><i>No bridge configurations.</i></td>
|
||||
<td colspan="3"><i>{{'No bridge configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of configurations trackById">
|
||||
<td>
|
||||
@ -33,7 +32,7 @@
|
||||
</td>
|
||||
<td *ngIf="!bridge.isOnline" class="error-text" colspan="2">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
This bridge is offline or unavailable.
|
||||
{{'This bridge is offline or unavailable.' | translate}}
|
||||
</td>
|
||||
<td class="text-center" *ngIf="bridge.isOnline">
|
||||
<span class="editButton" (click)="editNetworks(bridge)">
|
||||
@ -45,10 +44,10 @@
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addModularHostedBridge()"
|
||||
*ngIf="!hasModularBridge">
|
||||
<i class="fa fa-plus"></i> Add matrix.org's bridge
|
||||
<i class="fa fa-plus"></i> {{'Add matrix.org\'s bridge' | translate}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedBridge()">
|
||||
<i class="fa fa-plus"></i> Add self-hosted bridge
|
||||
<i class="fa fa-plus"></i> {{'Add self-hosted bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
AddSelfhostedIrcBridgeDialogContext,
|
||||
AdminIrcBridgeAddSelfhostedComponent
|
||||
} from "./add-selfhosted/add-selfhosted.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./irc.component.html",
|
||||
@ -27,7 +28,9 @@ export class AdminIrcBridgeComponent implements OnInit {
|
||||
constructor(private upstreamApi: AdminUpstreamApiService,
|
||||
private ircApi: AdminIrcApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -48,7 +51,7 @@ export class AdminIrcBridgeComponent implements OnInit {
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading bridges");
|
||||
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,13 +70,13 @@ export class AdminIrcBridgeComponent implements OnInit {
|
||||
const createBridge = (upstream: FE_Upstream) => {
|
||||
return this.ircApi.newFromUpstream(upstream).then(bridge => {
|
||||
this.configurations.push(bridge);
|
||||
this.toaster.pop("success", "matrix.org's IRC bridge added", "Click the pencil icon to enable networks.");
|
||||
this.translate.get(['Click the pencil icon to enable networks.', 'matrix.org\'s IRC bridge added']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); });
|
||||
this.isUpdating = false;
|
||||
this.hasModularBridge = true;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error adding matrix.org's IRC Bridge");
|
||||
this.translate.get('Error adding matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
};
|
||||
const vectorUpstreams = this.upstreams.filter(u => u.type === "vector");
|
||||
@ -85,7 +88,7 @@ export class AdminIrcBridgeComponent implements OnInit {
|
||||
createBridge(upstream);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error creating matrix.org's IRC Bridge");
|
||||
this.translate.get('Error creating matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else createBridge(vectorUpstreams[0]);
|
||||
}
|
||||
@ -97,7 +100,7 @@ export class AdminIrcBridgeComponent implements OnInit {
|
||||
}, AddSelfhostedIrcBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update IRC bridge list");
|
||||
this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Network</th>
|
||||
<th>Enabled</th>
|
||||
<th>{{'Network' | translate}}</th>
|
||||
<th>{{'Enabled' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { FE_IrcBridge } from "../../../../shared/models/irc";
|
||||
import { AdminIrcApiService } from "../../../../shared/services/admin/admin-irc-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class IrcNetworksDialogContext extends BSModalContext {
|
||||
public bridge: FE_IrcBridge;
|
||||
@ -29,7 +30,9 @@ export class AdminIrcBridgeNetworksComponent implements ModalComponent<IrcNetwor
|
||||
|
||||
constructor(public dialog: DialogRef<IrcNetworksDialogContext>,
|
||||
private ircApi: AdminIrcApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.bridge = dialog.context.bridge;
|
||||
|
||||
const networkIds = Object.keys(this.bridge.availableNetworks);
|
||||
@ -51,13 +54,13 @@ export class AdminIrcBridgeNetworksComponent implements ModalComponent<IrcNetwor
|
||||
this.isUpdating = true;
|
||||
this.ircApi.setNetworkEnabled(this.bridge.id, network.id, network.isEnabled).then(() => {
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Network " + (network.isEnabled ? "enabled" : "disabled"));
|
||||
this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Network " + (network.isEnabled ? res[0] : res[1])); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isUpdating = false;
|
||||
network.isEnabled = !network.isEnabled;
|
||||
this.bridge.availableNetworks[network.id].isEnabled = network.isEnabled;
|
||||
this.toaster.pop("error", "Failed to update network");
|
||||
this.translate.get('Failed to update network').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} self-hosted Slack bridge</h4>
|
||||
<h4> {{'self-hosted Slack bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>
|
||||
Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public
|
||||
internet.
|
||||
{{'Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.' | translate}}
|
||||
</p>
|
||||
|
||||
<label class="label-block">
|
||||
Provisioning URL
|
||||
<span class="text-muted ">The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.</span>
|
||||
{{'Provisioning URL' | translate}}
|
||||
<span class="text-muted ">{{'The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="http://localhost:9000"
|
||||
[(ngModel)]="provisionUrl" [disabled]="isSaving"/>
|
||||
@ -18,10 +17,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminSlackApiService } from "../../../../shared/services/admin/admin-slack-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class ManageSelfhostedSlackBridgeDialogContext extends BSModalContext {
|
||||
public provisionUrl: string;
|
||||
@ -22,7 +23,9 @@ export class AdminSlackBridgeManageSelfhostedComponent implements ModalComponent
|
||||
|
||||
constructor(public dialog: DialogRef<ManageSelfhostedSlackBridgeDialogContext>,
|
||||
private slackApi: AdminSlackApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.provisionUrl = dialog.context.provisionUrl;
|
||||
this.bridgeId = dialog.context.bridgeId;
|
||||
this.isAdding = !this.bridgeId;
|
||||
@ -32,21 +35,21 @@ export class AdminSlackBridgeManageSelfhostedComponent implements ModalComponent
|
||||
this.isSaving = true;
|
||||
if (this.isAdding) {
|
||||
this.slackApi.newSelfhosted(this.provisionUrl).then(() => {
|
||||
this.toaster.pop("success", "Slack bridge added");
|
||||
this.translate.get('Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to create Slack bridge");
|
||||
this.translate.get('Failed to create Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else {
|
||||
this.slackApi.updateSelfhosted(this.bridgeId, this.provisionUrl).then(() => {
|
||||
this.toaster.pop("success", "Slack bridge updated");
|
||||
this.translate.get('Slack bridge updated').subscribe((res: string) => {this.toaster.pop("success", res);});
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to update Slack bridge");
|
||||
this.translate.get('Failed to update Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -6,21 +6,20 @@
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
<a href="https://github.com/matrix-org/matrix-appservice-slack"
|
||||
target="_blank">matrix-appservice-slack</a>
|
||||
is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access
|
||||
their Slack workspaces and from there they can pick the channels they'd like to bridge.
|
||||
target="_blank">{{'matrix-appservice-slack' | translate}}</a>
|
||||
{{'is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they\'d like to bridge.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="2"><i>No bridge configurations.</i></td>
|
||||
<td colspan="2"><i>{{'No bridge configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of configurations trackById">
|
||||
<td>
|
||||
@ -38,11 +37,11 @@
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addModularHostedBridge()"
|
||||
[disabled]="(configurations && configurations.length > 0) || isUpdating">
|
||||
<i class="fa fa-plus"></i> Add matrix.org's bridge
|
||||
<i class="fa fa-plus"></i> {{'Add matrix.org\'s bridge' | translate}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedBridge()"
|
||||
[disabled]="(configurations && configurations.length > 0) || isUpdating">
|
||||
<i class="fa fa-plus"></i> Add self-hosted bridge
|
||||
<i class="fa fa-plus"></i> {{'Add self-hosted bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from "./manage-selfhosted/manage-selfhosted.component";
|
||||
import { FE_SlackBridge } from "../../../shared/models/slack";
|
||||
import { AdminSlackApiService } from "../../../shared/services/admin/admin-slack-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./slack.component.html",
|
||||
@ -25,7 +26,9 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
constructor(private slackApi: AdminSlackApiService,
|
||||
private upstreamApi: AdminUpstreamApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -38,7 +41,7 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
this.configurations = await this.slackApi.getBridges();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading bridges");
|
||||
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,12 +51,12 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
const createBridge = (upstream: FE_Upstream) => {
|
||||
return this.slackApi.newFromUpstream(upstream).then(bridge => {
|
||||
this.configurations.push(bridge);
|
||||
this.toaster.pop("success", "matrix.org's Slack bridge added");
|
||||
this.translate.get('matrix.org\'s Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.isUpdating = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error adding matrix.org's Slack Bridge");
|
||||
this.translate.get('Error adding matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
};
|
||||
|
||||
@ -66,7 +69,7 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
createBridge(upstream);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error creating matrix.org's Slack Bridge");
|
||||
this.translate.get('Error creating matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else createBridge(vectorUpstreams[0]);
|
||||
}
|
||||
@ -80,7 +83,7 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedSlackBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Slack bridge list");
|
||||
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -95,7 +98,7 @@ export class AdminSlackBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedSlackBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Slack bridge list");
|
||||
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,46 +1,46 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} self-hosted Telegram bridge</h4>
|
||||
<h4> {{'self-hosted Telegram bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>Self-hosted Telegram bridges must have <code>provisioning</code> enabled in the configuration.</p>
|
||||
<p>{{'Self-hosted Telegram bridges must have' | translate}} <code>{{'provisioning' | translate}}</code> {{'enabled in the configuration.' | translate}}</p>
|
||||
|
||||
<label class="label-block">
|
||||
Provisioning URL
|
||||
<span class="text-muted ">The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.</span>
|
||||
{{'Provisioning URL' | translate}}
|
||||
<span class="text-muted ">{{'The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="http://localhost:9999/_matrix/provision/v1"
|
||||
[(ngModel)]="provisionUrl" [disabled]="isSaving"/>
|
||||
</label>
|
||||
|
||||
<label class="label-block">
|
||||
Shared Secret
|
||||
<span class="text-muted ">The shared secret defined in the configuration for provisioning.</span>
|
||||
{{'Shared Secret' | translate}}
|
||||
<span class="text-muted ">{{'The shared secret defined in the configuration for provisioning.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="some_secret_value"
|
||||
[(ngModel)]="sharedSecret" [disabled]="isSaving"/>
|
||||
</label>
|
||||
|
||||
<label class="label-block">
|
||||
Promote Telegram Puppeting
|
||||
<span class="text-muted ">If enabled, Dimension will recommend that users log in to their Telegram accounts.</span>
|
||||
{{'Promote Telegram Puppeting' | translate}}
|
||||
<span class="text-muted ">{{'If enabled, Dimension will recommend that users log in to their Telegram accounts.' | translate}}</span>
|
||||
<ui-switch [checked]="allowTgPuppets" size="small" [disabled]="isSaving"
|
||||
(change)="allowTgPuppets = !allowTgPuppets"></ui-switch>
|
||||
</label>
|
||||
|
||||
<label class="label-block">
|
||||
Promote Matrix Puppeting
|
||||
<span class="text-muted ">If enabled, Dimension will recommend that users log in to their Matrix accounts.</span>
|
||||
{{'Promote Matrix Puppeting' | translate}}
|
||||
<span class="text-muted ">{{'If enabled, Dimension will recommend that users log in to their Matrix accounts.' | translate}}</span>
|
||||
<ui-switch [checked]="allowMxPuppets" size="small" [disabled]="isSaving"
|
||||
(change)="allowMxPuppets = !allowMxPuppets"></ui-switch>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminTelegramApiService } from "../../../../shared/services/admin/admin-telegram-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class ManageSelfhostedTelegramBridgeDialogContext extends BSModalContext {
|
||||
public provisionUrl: string;
|
||||
@ -28,7 +29,9 @@ export class AdminTelegramBridgeManageSelfhostedComponent implements ModalCompon
|
||||
|
||||
constructor(public dialog: DialogRef<ManageSelfhostedTelegramBridgeDialogContext>,
|
||||
private telegramApi: AdminTelegramApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.provisionUrl = dialog.context.provisionUrl;
|
||||
this.sharedSecret = dialog.context.sharedSecret;
|
||||
this.allowTgPuppets = dialog.context.allowTgPuppets;
|
||||
@ -45,21 +48,21 @@ export class AdminTelegramBridgeManageSelfhostedComponent implements ModalCompon
|
||||
};
|
||||
if (this.isAdding) {
|
||||
this.telegramApi.newSelfhosted(this.provisionUrl, this.sharedSecret, options).then(() => {
|
||||
this.toaster.pop("success", "Telegram bridge added");
|
||||
this.translate.get('Telegram bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to create Telegram bridge");
|
||||
this.translate.get('Failed to create Telegram bridge').subscribe((res: string) => { this.toaster.pop("error", res); });
|
||||
});
|
||||
} else {
|
||||
this.telegramApi.updateSelfhosted(this.bridgeId, this.provisionUrl, this.sharedSecret, options).then(() => {
|
||||
this.toaster.pop("success", "Telegram bridge updated");
|
||||
this.translate.get('Telegram bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to update Telegram bridge");
|
||||
this.translate.get('Failed to update Telegram bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,24 +5,19 @@
|
||||
<my-ibox boxTitle="Telegram Bridge Configurations">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
<a href="https://github.com/tulir/mautrix-telegram" target="_blank">mautrix-telegram</a>
|
||||
is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be
|
||||
done through a "relay bot" (all Matrix users are represented through a single bot in Telegram)
|
||||
or by making use of a user's real Telegram account (known as "puppeting"). Currently
|
||||
only one Telegram bridge can be configured at a time.
|
||||
</p>
|
||||
|
||||
<a href="https://github.com/tulir/mautrix-telegram" target="_blank">{{'mautrix-telegram' | translate}}</a>
|
||||
{{'is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a \'relay bot\' (all Matrix users are represented through a single bot in Telegram) or by making use of a user\'s real Telegram account (known as \'puppeting\'). Currently only one Telegram bridge can be configured at a time.' | translate}}
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enabled Features</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th>{{'Enabled Features' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="3"><i>No bridge configurations.</i></td>
|
||||
<td colspan="3"><i>{{'No bridge configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of configurations trackById">
|
||||
<td>
|
||||
@ -43,7 +38,7 @@
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedBridge()"
|
||||
[disabled]="configurations && configurations.length > 0">
|
||||
<i class="fa fa-plus"></i> Add self-hosted bridge
|
||||
<i class="fa fa-plus"></i> {{'Add self-hosted bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
} from "./manage-selfhosted/manage-selfhosted.component";
|
||||
import { FE_TelegramBridge } from "../../../shared/models/telegram";
|
||||
import { AdminTelegramApiService } from "../../../shared/services/admin/admin-telegram-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./telegram.component.html",
|
||||
@ -20,7 +21,9 @@ export class AdminTelegramBridgeComponent implements OnInit {
|
||||
|
||||
constructor(private telegramApi: AdminTelegramApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -32,7 +35,7 @@ export class AdminTelegramBridgeComponent implements OnInit {
|
||||
this.configurations = await this.telegramApi.getBridges();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading bridges");
|
||||
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +50,7 @@ export class AdminTelegramBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedTelegramBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Telegram bridge list");
|
||||
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -72,7 +75,7 @@ export class AdminTelegramBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedTelegramBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Telegram bridge list");
|
||||
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} self-hosted webhook bridge</h4>
|
||||
<h4> {{'self-hosted webhook bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>Self-hosted webhook bridges must have <code>provisioning</code> enabled in the configuration.</p>
|
||||
<p>{{'Self-hosted webhook bridges must have' | translate}} <code>{{'provisioning' | translate}}</code> {{'enabled in the configuration.' | translate}}</p>
|
||||
|
||||
<label class="label-block">
|
||||
Provisioning URL
|
||||
<span class="text-muted ">The public URL for the bridge.</span>
|
||||
{{'Provisioning URL' | translate}}
|
||||
<span class="text-muted ">{{'The public URL for the bridge.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://webhooks.example.org:9000/"
|
||||
[(ngModel)]="provisionUrl" [disabled]="isSaving"/>
|
||||
</label>
|
||||
|
||||
<label class="label-block">
|
||||
Shared Secret
|
||||
<span class="text-muted ">The provisioning secret defined in the configuration.</span>
|
||||
{{'Shared Secret' | translate}}
|
||||
<span class="text-muted ">{{'The provisioning secret defined in the configuration.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="some_secret_value"
|
||||
[(ngModel)]="sharedSecret" [disabled]="isSaving"/>
|
||||
@ -23,10 +23,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminWebhooksApiService } from "../../../../shared/services/admin/admin-webhooks-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class ManageSelfhostedWebhooksBridgeDialogContext extends BSModalContext {
|
||||
public provisionUrl: string;
|
||||
@ -26,7 +27,9 @@ export class AdminWebhooksBridgeManageSelfhostedComponent implements ModalCompon
|
||||
|
||||
constructor(public dialog: DialogRef<ManageSelfhostedWebhooksBridgeDialogContext>,
|
||||
private webhooksApi: AdminWebhooksApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.provisionUrl = dialog.context.provisionUrl;
|
||||
this.sharedSecret = dialog.context.sharedSecret;
|
||||
this.bridgeId = dialog.context.bridgeId;
|
||||
@ -37,21 +40,21 @@ export class AdminWebhooksBridgeManageSelfhostedComponent implements ModalCompon
|
||||
this.isSaving = true;
|
||||
if (this.isAdding) {
|
||||
this.webhooksApi.newSelfhosted(this.provisionUrl, this.sharedSecret).then(() => {
|
||||
this.toaster.pop("success", "Webhook bridge added");
|
||||
this.translate.get('Webhook bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to create Webhook bridge");
|
||||
this.translate.get('Failed to create Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else {
|
||||
this.webhooksApi.updateSelfhosted(this.bridgeId, this.provisionUrl, this.sharedSecret).then(() => {
|
||||
this.toaster.pop("success", "Webhook bridge updated");
|
||||
this.translate.get('Webhook bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Failed to update Webhook bridge");
|
||||
this.translate.get('Failed to update Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,20 +5,20 @@
|
||||
<my-ibox boxTitle="Webhooks Bridge Configuration">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
<a href="https://github.com/turt2live/matrix-appservice-webhooks" target="_blank">matrix-appservice-webhooks</a>
|
||||
provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.
|
||||
<a href="https://github.com/turt2live/matrix-appservice-webhooks" target="_blank">{{'matrix-appservice-webhooks' | translate}}</a>
|
||||
{{'provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="2"><i>No bridge configurations.</i></td>
|
||||
<td colspan="2"><i>{{'No bridge configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bridge of configurations trackById">
|
||||
<td>
|
||||
@ -36,7 +36,7 @@
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedBridge()"
|
||||
[disabled]="configurations && configurations.length > 0">
|
||||
<i class="fa fa-plus"></i> Add self-hosted bridge
|
||||
<i class="fa fa-plus"></i> {{'Add self-hosted bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
} from "./manage-selfhosted/manage-selfhosted.component";
|
||||
import { FE_WebhooksBridge } from "../../../shared/models/webhooks";
|
||||
import { AdminWebhooksApiService } from "../../../shared/services/admin/admin-webhooks-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./webhooks.component.html",
|
||||
@ -20,7 +21,9 @@ export class AdminWebhooksBridgeComponent implements OnInit {
|
||||
|
||||
constructor(private webhooksApi: AdminWebhooksApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -32,7 +35,7 @@ export class AdminWebhooksBridgeComponent implements OnInit {
|
||||
this.configurations = await this.webhooksApi.getBridges();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading bridges");
|
||||
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +50,7 @@ export class AdminWebhooksBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedWebhooksBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Webhooks bridge list");
|
||||
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -63,7 +66,7 @@ export class AdminWebhooksBridgeComponent implements OnInit {
|
||||
}, ManageSelfhostedWebhooksBridgeDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an update Webhooks bridge list");
|
||||
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} custom bot</h4>
|
||||
<h4>{{ isAdding ? "Add a new" : "Edit" }} {{ 'custom bot' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<label class="label-block">
|
||||
User ID
|
||||
<span class="text-muted">The user ID that Dimension will invite to rooms.</span>
|
||||
<span class="text-muted">{{'The user ID that Dimension will invite to rooms.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="@yourbot:example.org"
|
||||
[(ngModel)]="bot.userId" [disabled]="isSaving" (blur)="loadProfile()"/>
|
||||
@ -13,15 +13,15 @@
|
||||
|
||||
<label class="label-block">
|
||||
Description
|
||||
<span class="text-muted ">A few words here will help people understand what the bot does.</span>
|
||||
<span class="text-muted ">{{'A few words here will help people understand what the bot does.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="Does awesome things"
|
||||
[(ngModel)]="bot.description" [disabled]="isSaving"/>
|
||||
</label>
|
||||
|
||||
<label class="label-block">
|
||||
Display Name
|
||||
<span class="text-muted ">This is the name Dimension will use to tell users which bot this is.</span>
|
||||
{{'Display Name' | translate}}
|
||||
<span class="text-muted ">{{'This is the name Dimension will use to tell users which bot this is.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="Cool Bot"
|
||||
[(ngModel)]="bot.name" [disabled]="isSaving"/>
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
<label class="label-block">
|
||||
Avatar URL
|
||||
<span class="text-muted ">This can either be an MXC URI or a plain URL.</span>
|
||||
<span class="text-muted ">{{'This can either be an MXC URI or a plain URL.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="mxc://example.org/C00lAvat4r"
|
||||
[(ngModel)]="bot.avatarUrl" [disabled]="isSaving"/>
|
||||
@ -37,7 +37,9 @@
|
||||
|
||||
<label class="label-block">
|
||||
Access Token
|
||||
<span class="text-muted ">This is used by Dimension to force the bot to leave the room when the user removes the bot. <a href="https://t2bot.io/docs/access_tokens/" target="_blank">Learn more about access tokens</a>.</span>
|
||||
<span class="text-muted ">{{'This is used by Dimension to force the bot to leave the room when the user removes the bot.' | translate}}
|
||||
<a href="https://t2bot.io/docs/access_tokens/" target="_blank">{{'Learn more about access tokens.' | translate}}</a>.
|
||||
</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="MDaX..."
|
||||
[(ngModel)]="bot.accessToken" [disabled]="isSaving"/>
|
||||
@ -45,10 +47,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="add()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i>{{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { FE_CustomSimpleBot, FE_UserProfile } from "../../../shared/models/admin-responses";
|
||||
import { AdminCustomSimpleBotsApiService } from "../../../shared/services/admin/admin-custom-simple-bots-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class AddCustomBotDialogContext extends BSModalContext {
|
||||
bot: FE_CustomSimpleBot;
|
||||
@ -23,7 +24,9 @@ export class AdminAddCustomBotComponent implements ModalComponent<AddCustomBotDi
|
||||
|
||||
constructor(public dialog: DialogRef<AddCustomBotDialogContext>,
|
||||
private botApi: AdminCustomSimpleBotsApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.bot = this.dialog.context.bot || <FE_CustomSimpleBot>{};
|
||||
this.isAdding = !this.dialog.context.bot;
|
||||
}
|
||||
@ -45,23 +48,23 @@ export class AdminAddCustomBotComponent implements ModalComponent<AddCustomBotDi
|
||||
|
||||
public add() {
|
||||
if (!this.bot.name) {
|
||||
this.toaster.pop("warning", "Please enter a name for the bot");
|
||||
this.translate.get('Please enter a name for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
if (!this.bot.avatarUrl) {
|
||||
this.toaster.pop("warning", "Please enter an avatar URL for the bot");
|
||||
this.translate.get('Please enter an avatar URL for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
if (!this.bot.userId) {
|
||||
this.toaster.pop("warning", "Please enter a user ID for the bot");
|
||||
this.translate.get('Please enter a user ID for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
if (!this.bot.description) {
|
||||
this.toaster.pop("warning", "Please enter a description for the bot");
|
||||
this.translate.get('Please enter a description for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
if (!this.bot.accessToken) {
|
||||
this.toaster.pop("warning", "Please enter an access token for the bot");
|
||||
this.translate.get('Please enter an access token for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -85,12 +88,12 @@ export class AdminAddCustomBotComponent implements ModalComponent<AddCustomBotDi
|
||||
}
|
||||
|
||||
promise.then(() => {
|
||||
this.toaster.pop("success", "Bot updated");
|
||||
this.translate.get('Bot updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(error => {
|
||||
this.isSaving = false;
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error updating bot");
|
||||
this.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,21 @@
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="Custom bots">
|
||||
<my-ibox boxTitle="{{'Custom bots' | translate}}">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Custom bots give you the ability to add your own bots to Dimension for users to add
|
||||
to their rooms. These bots can't have any configuration to them and must be able to
|
||||
accept room invites on their own. All Dimension will do when a user wants to add the
|
||||
bot is invite it to the room.
|
||||
<p>{{'Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can\'t have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Name' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!bots || bots.length === 0">
|
||||
<td colspan="2"><i>No custom bots.</i></td>
|
||||
<td colspan="2"><i>{{'No custom bots.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let bot of bots trackById">
|
||||
<td>
|
||||
@ -38,7 +34,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addBot()">
|
||||
<i class="fa fa-plus"></i> Add custom bot
|
||||
<i class="fa fa-plus"></i>{{ 'Add custom bot' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -4,6 +4,7 @@ import { FE_CustomSimpleBot } from "../../shared/models/admin-responses";
|
||||
import { AdminCustomSimpleBotsApiService } from "../../shared/services/admin/admin-custom-simple-bots-api.service";
|
||||
import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||
import { AddCustomBotDialogContext, AdminAddCustomBotComponent } from "./add/add.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./custom-bots.component.html",
|
||||
@ -17,11 +18,13 @@ export class AdminCustomBotsComponent {
|
||||
|
||||
constructor(private botApi: AdminCustomSimpleBotsApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
|
||||
this.reload().then(() => this.isLoading = false).catch(error => {
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error loading go-neb configuration");
|
||||
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -39,7 +42,7 @@ export class AdminCustomBotsComponent {
|
||||
}, AddCustomBotDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an updated bot list");
|
||||
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -53,7 +56,7 @@ export class AdminCustomBotsComponent {
|
||||
}, AddCustomBotDialogContext)).result.then(() => {
|
||||
this.reload().catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to get an updated bot list");
|
||||
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -63,11 +66,11 @@ export class AdminCustomBotsComponent {
|
||||
bot.isEnabled = !bot.isEnabled;
|
||||
this.botApi.updateBot(bot.id, bot).then(() => {
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Bot " + (bot.isEnabled ? "enabled" : "disabled"));
|
||||
this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Bot " + (bot.isEnabled ? res[0] : res[1])); });
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
bot.isEnabled = !bot.isEnabled;
|
||||
this.toaster.pop("error", "Error updating bot");
|
||||
this.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2,42 +2,41 @@
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="Configuration">
|
||||
<my-ibox boxTitle="{{'Configuration' | translate}}">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Parts of your configuration are displayed below. To change these values, edit your configuration and
|
||||
restart Dimension.
|
||||
{{'Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.' | translate}}
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<strong>Administrators</strong>
|
||||
<strong>{{'Administrators' | translate}}</strong>
|
||||
<ul>
|
||||
<li *ngFor="let user of config.admins trackById">{{ user }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Widget Blacklist</strong>
|
||||
<strong>{{'Widget Blacklist' | translate}}</strong>
|
||||
<ul>
|
||||
<li *ngFor="let ip of config.widgetBlacklist trackById">{{ ip }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Homeserver</strong><br/>
|
||||
<strong>{{'Homeserver' | translate}}</strong><br/>
|
||||
Name: {{ config.homeserver.name }}<br/>
|
||||
Federation URL: {{ config.homeserver.federationUrl }}<br/>
|
||||
Federation Hostname: {{ config.homeserver.federationHostname }}<br/>
|
||||
Client/Server URL: {{ config.homeserver.clientServerUrl }}<br/>
|
||||
Utility User ID: {{ config.homeserver.userId }}
|
||||
{{'Federation URL' | translate}}: {{ config.homeserver.federationUrl }}<br/>
|
||||
{{'Federation Hostname' | translate}}: {{ config.homeserver.federationHostname }}<br/>
|
||||
{{'Client/Server URL'| translate}}: {{ config.homeserver.clientServerUrl }}<br/>
|
||||
{{'Utility User ID' | translate}}: {{ config.homeserver.userId }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<strong>Sessions</strong><br/>
|
||||
Tokens registered: {{ config.sessionInfo.numTokens }}<br/>
|
||||
<strong>{{'Sessions' | translate}}</strong><br/>
|
||||
{{'Tokens registered' | translate}}: {{ config.sessionInfo.numTokens }}<br/>
|
||||
<button class="btn btn-danger btn-sm" type="button" (click)="logoutAll()">
|
||||
Logout Everyone
|
||||
{{'Logout Everyone' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
AdminLogoutConfirmationDialogComponent,
|
||||
LogoutConfirmationDialogContext
|
||||
} from "./logout-confirmation/logout-confirmation.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./home.component.html",
|
||||
@ -19,7 +20,9 @@ export class AdminHomeComponent {
|
||||
|
||||
constructor(private adminApi: AdminApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
adminApi.getConfig().then(config => {
|
||||
this.config = config;
|
||||
this.isLoading = false;
|
||||
@ -31,11 +34,11 @@ export class AdminHomeComponent {
|
||||
isBlocking: true,
|
||||
}, LogoutConfirmationDialogContext)).result.then(() => {
|
||||
this.adminApi.logoutAll().then(() => {
|
||||
this.toaster.pop("success", "Everyone has been logged out");
|
||||
this.translate.get('Everyone has been logged out').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.config.sessionInfo.numTokens = 0;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error logging everyone out");
|
||||
this.translate.get('Error logging everyone out').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Logout confirmation</h4>
|
||||
<h4>{{'Logout confirmation' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<p>
|
||||
Logging everyone out will disable all known login tokens for Dimension and upstream integration managers.
|
||||
Most clients will automatically re-register for a login token behind the scenes, similar to how a login
|
||||
token was first acquired.
|
||||
{{'Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.' | translate}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="dialog.dismiss()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="logout everyone" class="btn btn-danger btn-sm">
|
||||
<i class="far fa-times-circle"></i> Logout Everyone
|
||||
<i class="far fa-times-circle"></i> {{'Logout Everyone' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -1,27 +1,26 @@
|
||||
<my-ibox boxTitle="New self-hosted go-neb">
|
||||
<my-ibox boxTitle="{{'New self-hosted go-neb' | translate}}">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Self-hosted go-neb instances are powered by application services installed on your homeserver. The
|
||||
application service is responsible for creating the bots dynamically.
|
||||
{{'Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.' | translate}}
|
||||
</p>
|
||||
|
||||
<label class="label-block">
|
||||
User Prefix
|
||||
<span class="text-muted ">This is the prefix used for all bot users.</span>
|
||||
{{'User Prefix' | translate}}
|
||||
<span class="text-muted ">{{'This is the prefix used for all bot users.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="@_neb"
|
||||
[(ngModel)]="userPrefix" [disabled]="isSaving"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
API URL
|
||||
<span class="text-muted ">The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.</span>
|
||||
{{'API URL' | translate}}
|
||||
<span class="text-muted ">{{'The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="http://localhost:4050"
|
||||
[(ngModel)]="adminUrl" [disabled]="isSaving"/>
|
||||
</label>
|
||||
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm" [disabled]="isSaving">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
@ -8,6 +8,7 @@ import {
|
||||
AdminNebAppserviceConfigComponent,
|
||||
AppserviceConfigDialogContext
|
||||
} from "../appservice-config/appservice-config.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
|
||||
@Component({
|
||||
@ -25,7 +26,9 @@ export class AdminAddSelfhostedNebComponent {
|
||||
private toaster: ToasterService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public save(): void {
|
||||
@ -33,8 +36,7 @@ export class AdminAddSelfhostedNebComponent {
|
||||
this.asApi.createAppservice(this.userPrefix).then(appservice => {
|
||||
return this.nebApi.newAppserviceConfiguration(this.adminUrl, appservice);
|
||||
}).then(neb => {
|
||||
this.toaster.pop("success", "New go-neb created");
|
||||
|
||||
this.translate.get('New go-neb created').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.modal.open(AdminNebAppserviceConfigComponent, overlayConfigFactory({
|
||||
neb: neb,
|
||||
|
||||
@ -44,7 +46,7 @@ export class AdminAddSelfhostedNebComponent {
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isSaving = false;
|
||||
this.toaster.pop("error", "Error creating appservice");
|
||||
this.translate.get('Error creating appservice').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>go-neb appservice configuration</h4>
|
||||
<h4>{{'go-neb appservice configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="isLoading">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="!isLoading">
|
||||
Copy and paste this configuration to <code>appservice-{{appservice.id}}.yaml</code> on your homeserver and
|
||||
register it as an application service.
|
||||
{{'Copy and paste this configuration to' | translate}} <code>appservice-{{appservice.id}}.yaml</code>
|
||||
{{'on your homeserver and register it as an application service.' | translate}}
|
||||
<br/>
|
||||
<pre>{{appserviceConfig}}</pre>
|
||||
</div>
|
||||
<div class="dialog-footer" *ngIf="!isLoading">
|
||||
<button type="button" (click)="dialog.close()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="test()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="fa fa-exchange-alt"></i> Test Configuration
|
||||
<i class="fa fa-exchange-alt"></i> {{'Test Configuration' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { FE_Appservice, FE_NebConfiguration } from "../../../shared/models/admin-responses";
|
||||
import { AdminAppserviceApiService } from "../../../shared/services/admin/admin-appservice-api.service";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class AppserviceConfigDialogContext extends BSModalContext {
|
||||
public neb: FE_NebConfiguration;
|
||||
@ -19,7 +20,11 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent<Appserv
|
||||
public neb: FE_NebConfiguration;
|
||||
public appservice: FE_Appservice;
|
||||
|
||||
constructor(public dialog: DialogRef<AppserviceConfigDialogContext>, private adminAppserviceApi: AdminAppserviceApiService, private toaster: ToasterService) {
|
||||
constructor(public dialog: DialogRef<AppserviceConfigDialogContext>,
|
||||
private adminAppserviceApi: AdminAppserviceApiService,
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.neb = dialog.context.neb;
|
||||
|
||||
this.adminAppserviceApi.getAppservice(this.neb.appserviceId).then(appservice => {
|
||||
@ -27,7 +32,7 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent<Appserv
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Could not load appservice configuration");
|
||||
this.translate.get('Could not load appservice configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -48,10 +53,10 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent<Appserv
|
||||
|
||||
public test() {
|
||||
this.adminAppserviceApi.test(this.neb.appserviceId).then(() => {
|
||||
this.toaster.pop("success", "The appservice appears to be correctly set up");
|
||||
this.translate.get('The appservice appears to be correctly set up').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "The appservice is not correctly set up");
|
||||
this.translate.get('The appservice is not correctly set up').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,33 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Giphy Configuration</h4>
|
||||
<h4>{{'Giphy Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="isLoading">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="!isLoading">
|
||||
<label class="label-block">
|
||||
Api Key
|
||||
<span class="text-muted ">The API key from <a href="https://developers.giphy.com/" target="_blank">developers.giphy.com</a>.</span>
|
||||
{{'Api Key' | translate}}
|
||||
<span class="text-muted ">{{'The API key from' | translate}} <a href="https://developers.giphy.com/" target="_blank">developers.giphy.com</a>.</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_api_key_here"
|
||||
[(ngModel)]="config.api_key" [disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Image Size
|
||||
<span class="text-muted ">GIFs can be large, and sometimes it is more desirable to have them downsized.</span>
|
||||
{{'Image Size' | translate}}
|
||||
<span class="text-muted ">{{'GIFs can be large, and sometimes it is more desirable to have them downsized.' | translate}}</span>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" [(ngModel)]="config.use_downsized" [disabled]="isUpdating"/>
|
||||
Use downsized images
|
||||
{{'Use downsized images' | translate}}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dialog-footer" *ngIf="!isLoading">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context";
|
||||
import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service";
|
||||
import { FE_NebConfiguration } from "../../../../shared/models/admin-responses";
|
||||
import { FE_Integration } from "../../../../shared/models/integration";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface GiphyConfig {
|
||||
api_key: string;
|
||||
@ -25,7 +26,9 @@ export class AdminNebGiphyConfigComponent implements ModalComponent<NebBotConfig
|
||||
|
||||
constructor(public dialog: DialogRef<NebBotConfigurationDialogContext>,
|
||||
private adminNebApi: AdminNebApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.neb = dialog.context.neb;
|
||||
this.integration = dialog.context.integration;
|
||||
}
|
||||
@ -36,19 +39,19 @@ export class AdminNebGiphyConfigComponent implements ModalComponent<NebBotConfig
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading configuration");
|
||||
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save() {
|
||||
this.isUpdating = true;
|
||||
this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating integration");
|
||||
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Google Configuration</h4>
|
||||
<h4>{{'Google Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="isLoading">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="!isLoading">
|
||||
<label class="label-block">
|
||||
Api Key
|
||||
<span class="text-muted ">The API key for your Google Application.</span>
|
||||
{{'Api Key' | translate}}
|
||||
<span class="text-muted ">{{'The API key for your Google Application.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_api_key_here"
|
||||
[(ngModel)]="config.api_key" [disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Search Engine ID
|
||||
<span class="text-muted ">The search engine ID</span>
|
||||
<span class="text-muted ">{{'The search engine ID' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_cx_id_here"
|
||||
[(ngModel)]="config.cx" [disabled]="isUpdating"/>
|
||||
@ -23,10 +23,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer" *ngIf="!isLoading">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context";
|
||||
import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service";
|
||||
import { FE_NebConfiguration } from "../../../../shared/models/admin-responses";
|
||||
import { FE_Integration } from "../../../../shared/models/integration";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface GoogleConfig {
|
||||
api_key: string;
|
||||
@ -25,7 +26,9 @@ export class AdminNebGoogleConfigComponent implements ModalComponent<NebBotConfi
|
||||
|
||||
constructor(public dialog: DialogRef<NebBotConfigurationDialogContext>,
|
||||
private adminNebApi: AdminNebApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.neb = dialog.context.neb;
|
||||
this.integration = dialog.context.integration;
|
||||
}
|
||||
@ -36,19 +39,19 @@ export class AdminNebGoogleConfigComponent implements ModalComponent<NebBotConfi
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading configuration");
|
||||
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save() {
|
||||
this.isUpdating = true;
|
||||
this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating integration");
|
||||
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Guggy Configuration</h4>
|
||||
<h4>{{'Guggy Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="isLoading">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="!isLoading">
|
||||
<label class="label-block">
|
||||
Api Key
|
||||
<span class="text-muted ">The API key for <a href="http://docs.guggy.com/" target="_blank">Guggy's API</a>.</span>
|
||||
{{'Api Key' | translate}}
|
||||
<span class="text-muted ">{{'The API key for' | translate}} <a href="http://docs.guggy.com/" target="_blank">Guggy's API</a>.</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_api_key_here"
|
||||
[(ngModel)]="config.api_key" [disabled]="isUpdating"/>
|
||||
@ -16,10 +16,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer" *ngIf="!isLoading">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context";
|
||||
import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service";
|
||||
import { FE_NebConfiguration } from "../../../../shared/models/admin-responses";
|
||||
import { FE_Integration } from "../../../../shared/models/integration";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface GuggyConfig {
|
||||
api_key: string;
|
||||
@ -24,7 +25,9 @@ export class AdminNebGuggyConfigComponent implements ModalComponent<NebBotConfig
|
||||
|
||||
constructor(public dialog: DialogRef<NebBotConfigurationDialogContext>,
|
||||
private adminNebApi: AdminNebApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.neb = dialog.context.neb;
|
||||
this.integration = dialog.context.integration;
|
||||
}
|
||||
@ -35,19 +38,19 @@ export class AdminNebGuggyConfigComponent implements ModalComponent<NebBotConfig
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading configuration");
|
||||
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save() {
|
||||
this.isUpdating = true;
|
||||
this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating integration");
|
||||
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Imgur Configuration</h4>
|
||||
<h4>{{'Imgur Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="isLoading">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="dialog-content" *ngIf="!isLoading">
|
||||
<label class="label-block">
|
||||
Client ID
|
||||
<span class="text-muted ">The client ID of your <a href="https://apidocs.imgur.com/" target="_blank">Imgur Application</a>.</span>
|
||||
{{'Client ID' | translate}}
|
||||
<span class="text-muted ">{{'The client ID of your' | translate}} <a href="https://apidocs.imgur.com/" target="_blank">{{'Imgur Application' | translate}}</a>.</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_client_id"
|
||||
[(ngModel)]="config.client_id" [disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Client Secret
|
||||
<span class="text-muted ">The client secret of your <a href="https://apidocs.imgur.com/" target="_blank">Imgur Application</a>.</span>
|
||||
{{'Client Secret' | translate}}
|
||||
<span class="text-muted ">{{'The client secret of your' | translate}} <a href="https://apidocs.imgur.com/" target="_blank">{{'Imgur Application' | translate}}</a>.</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="your_client_secret"
|
||||
[(ngModel)]="config.client_secret" [disabled]="isUpdating"/>
|
||||
@ -23,10 +23,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer" *ngIf="!isLoading">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context";
|
||||
import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service";
|
||||
import { FE_NebConfiguration } from "../../../../shared/models/admin-responses";
|
||||
import { FE_Integration } from "../../../../shared/models/integration";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface ImgurConfig {
|
||||
client_id: string;
|
||||
@ -25,7 +26,9 @@ export class AdminNebImgurConfigComponent implements ModalComponent<NebBotConfig
|
||||
|
||||
constructor(public dialog: DialogRef<NebBotConfigurationDialogContext>,
|
||||
private adminNebApi: AdminNebApiService,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.neb = dialog.context.neb;
|
||||
this.integration = dialog.context.integration;
|
||||
}
|
||||
@ -36,19 +39,19 @@ export class AdminNebImgurConfigComponent implements ModalComponent<NebBotConfig
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error loading configuration");
|
||||
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save() {
|
||||
this.isUpdating = true;
|
||||
this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating integration");
|
||||
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,14 @@
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="go-neb configuration">
|
||||
<div class="my-ibox-content">
|
||||
<p>go-neb supports many different types of bots, each of which is listed below. Here you can configure which
|
||||
bots this go-neb instance should use.</p>
|
||||
<p>{{'go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.' | translate}}</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center">Actions</th>
|
||||
<th>{{'Description' | translate}}</th>
|
||||
<th class="text-center">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -11,6 +11,7 @@ import { NebBotConfigurationDialogContext } from "../config/config-context";
|
||||
import { AdminNebGuggyConfigComponent } from "../config/guggy/guggy.component";
|
||||
import { AdminNebGoogleConfigComponent } from "../config/google/google.component";
|
||||
import { AdminNebImgurConfigComponent } from "../config/imgur/imgur.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
|
||||
@Component({
|
||||
@ -30,7 +31,9 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
|
||||
constructor(private nebApi: AdminNebApiService,
|
||||
private route: ActivatedRoute,
|
||||
private modal: Modal,
|
||||
private toaster: ToasterService) {
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -58,12 +61,12 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
|
||||
try {
|
||||
await this.nebApi.toggleIntegration(this.nebConfig.id, bot.type, bot.isEnabled);
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Integration updated");
|
||||
this.translate.get('Integration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
bot.isEnabled = !bot.isEnabled; // revert change
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error updating integration");
|
||||
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -76,7 +79,7 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
|
||||
await this.nebApi.setIntegrationConfiguration(this.nebConfig.id, bot.type, {});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.toaster.pop("warning", "Failed to configure the integration", "Manual troubleshooting may be requred");
|
||||
this.translate.get(['Failed to configure the integration', 'Manual troubleshooting may be requred' ]).subscribe((res: string) => {this.toaster.pop("warning", res[0], res[1]); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -120,7 +123,7 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop('error', "Could not get go-neb configuration");
|
||||
this.translate.get('Could not get go-neb configuration').subscribe((res: string) => {this.toaster.pop('error', res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,24 +2,21 @@
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="go-neb configurations">
|
||||
<my-ibox boxTitle="{{'go-neb configurations' | translate}}">
|
||||
<div class="my-ibox-content">
|
||||
<p><a href="https://github.com/matrix-org/go-neb" target="_blank">go-neb</a> is a multi-purpose bot that can
|
||||
provide various services, such as reaction GIFs and Github notifications. There are two options for
|
||||
go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have
|
||||
multiple services associated with it (ie: one go-neb here can do everything).</p>
|
||||
<p><a href="https://github.com/matrix-org/go-neb" target="_blank">go-neb</a> {{'is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org\'s or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).' | translate}}</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Enabled Bots</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Enabled Bots' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!configurations || configurations.length === 0">
|
||||
<td colspan="3"><i>No go-neb configurations.</i></td>
|
||||
<td colspan="3"><i>{{'No go-neb configurations.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let neb of configurations trackById">
|
||||
<td>
|
||||
@ -43,10 +40,10 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addModularHostedNeb()" *ngIf="!hasModularNeb">
|
||||
<i class="fa fa-plus"></i> Add matrix.org's go-neb
|
||||
<i class="fa fa-plus"></i> {{'Add matrix.org\'s go-neb' | translate}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="addSelfHostedNeb()">
|
||||
<i class="fa fa-plus"></i> Add self-hosted go-neb
|
||||
<i class="fa fa-plus"></i> {{'Add self-hosted go-neb' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
AppserviceConfigDialogContext
|
||||
} from "./appservice-config/appservice-config.component";
|
||||
import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./neb.component.html",
|
||||
@ -30,11 +31,13 @@ export class AdminNebComponent {
|
||||
private toaster: ToasterService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
|
||||
this.reload().then(() => this.isLoading = false).catch(error => {
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error loading go-neb configuration");
|
||||
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -97,13 +100,13 @@ export class AdminNebComponent {
|
||||
const createNeb = (upstream: FE_Upstream) => {
|
||||
return this.nebApi.newUpstreamConfiguration(upstream).then(neb => {
|
||||
this.configurations.push(neb);
|
||||
this.toaster.pop("success", "matrix.org's go-neb added", "Click the pencil icon to enable the bots.");
|
||||
this.translate.get(['matrix.org\'s go-neb added', 'Click the pencil icon to enable the bots.']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); });
|
||||
this.isAddingModularNeb = false;
|
||||
this.hasModularNeb = true;
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
this.isAddingModularNeb = false;
|
||||
this.toaster.pop("error", "Error adding matrix.org's go-neb");
|
||||
this.translate.get('Error adding matrix.org\'s go-neb').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
};
|
||||
|
||||
@ -116,7 +119,7 @@ export class AdminNebComponent {
|
||||
createNeb(upstream);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error creating matrix.org go-neb");
|
||||
this.translate.get('Error creating matrix.org go-neb').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else createNeb(vectorUpstreams[0]);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,9 +5,7 @@
|
||||
<my-ibox boxTitle="Sticker Packs">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able
|
||||
to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled
|
||||
then the 'sticker picker' widget will be disabled.
|
||||
{{'Sticker packs provide a way to convey memes or feelings to others in a room. From here you\'re able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the \'sticker picker\' widget will be disabled.' | translate}}
|
||||
</p>
|
||||
|
||||
<div class="input-group input-group-sm telegram-import">
|
||||
@ -17,7 +15,7 @@
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" (click)="startTelegramImport()" [disabled]="!tgUrl || isImporting">
|
||||
<i class="fa fa-download"></i>
|
||||
Import from Telegram
|
||||
{{'Import from Telegram' | translate}}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
@ -26,24 +24,24 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Author</th>
|
||||
<th>License</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Description' | translate}}</th>
|
||||
<th>{{'Author' | translate}}</th>
|
||||
<th>{{'License' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!packs || packs.length === 0">
|
||||
<td colspan="5"><i>No sticker packs installed.</i></td>
|
||||
<td colspan="5"><i>{{'No sticker packs installed.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let pack of packs trackById">
|
||||
<td>{{ pack.displayName }}</td>
|
||||
<td>{{ pack.description }}</td>
|
||||
<td>{{ pack.displayName | translate}}</td>
|
||||
<td>{{ pack.description | translate }}</td>
|
||||
|
||||
<td *ngIf="pack.author.type !== 'none'">
|
||||
<a [href]="pack.author.reference" target="_blank">{{ pack.author.name }}</a>
|
||||
</td>
|
||||
<td *ngIf="pack.author.type === 'none'">Dimension</td>
|
||||
<td *ngIf="pack.author.type === 'none'">{{'Dimension' | translate}}</td>
|
||||
|
||||
<td><a [href]="pack.license.urlPath" target="_blank">{{ pack.license.name }}</a></td>
|
||||
<td class="text-center">
|
||||
|
@ -4,6 +4,7 @@ import { FE_StickerPack } from "../../shared/models/integration";
|
||||
import { AdminStickersApiService } from "../../shared/services/admin/admin-stickers-api-service";
|
||||
import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||
import { AdminStickerPackPreviewComponent, StickerPackPreviewDialogContext } from "./preview/preview.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./sticker-packs.component.html",
|
||||
@ -19,7 +20,9 @@ export class AdminStickerPacksComponent implements OnInit {
|
||||
|
||||
constructor(private adminStickers: AdminStickersApiService,
|
||||
private toaster: ToasterService,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -28,7 +31,7 @@ export class AdminStickerPacksComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load sticker packs");
|
||||
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -37,12 +40,12 @@ export class AdminStickerPacksComponent implements OnInit {
|
||||
this.isUpdating = true;
|
||||
this.adminStickers.togglePack(pack.id, pack.isEnabled).then(() => {
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Sticker pack updated");
|
||||
this.translate.get('Sticker pack updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
pack.isEnabled = !pack.isEnabled; // revert change
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error updating sticker pack");
|
||||
this.translate.get('Error updating sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,11 +64,11 @@ export class AdminStickerPacksComponent implements OnInit {
|
||||
this.isImporting = false;
|
||||
this.tgUrl = "";
|
||||
this.packs.push(pack);
|
||||
this.toaster.pop("success", "Telegram sticker pack imported");
|
||||
this.translate.get('Telegram sticker pack imported').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isImporting = false;
|
||||
this.toaster.pop("error", "Error importing sticker pack");
|
||||
this.translate.get('Error importing sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,18 @@
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox *ngFor="let code of chosenLanguageCodes">
|
||||
<div class="my-ibox-title">
|
||||
<h5>{{languages[code].langName}} version</h5>
|
||||
<h5>{{languages[code].langName}} {{'version' | translate}}</h5>
|
||||
</div>
|
||||
<div class="my-ibox-content">
|
||||
<label class="label-block">
|
||||
Name
|
||||
<span class="text-muted ">The translated name of your policy</span>
|
||||
<span class="text-muted ">{{'The translated name of your policy' | translate}}</span>
|
||||
<input type="text" class="form-control" placeholder="My Policy" [(ngModel)]="languages[code].name"
|
||||
[disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Policy text
|
||||
<span class="text-muted">This is where you put your policy's content.</span>
|
||||
{{'Policy text' | translate}}
|
||||
<span class="text-muted">{{'This is where you put your policy\'s content.' | translate}}</span>
|
||||
</label>
|
||||
<ckeditor [editor]="Editor" [(ngModel)]="languages[code].text" [disabled]="isUpdating"></ckeditor>
|
||||
</div>
|
||||
@ -33,13 +33,13 @@
|
||||
<my-ibox [hasTitle]="false">
|
||||
<div class="my-ibox-content buttons">
|
||||
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm" *ngIf="!isEditing">
|
||||
<i class="far fa-save"></i> Create draft
|
||||
<i class="far fa-save"></i> {{'Create draft' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm" *ngIf="isEditing">
|
||||
<i class="far fa-save"></i> Save draft
|
||||
<i class="far fa-save"></i> {{'Save draft' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="publish()" title="save" class="btn btn-primary btn-sm" *ngIf="isEditing">
|
||||
<i class="fas fa-upload"></i> Publish
|
||||
<i class="fas fa-upload"></i> {{'Publish' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
AdminTermsNewEditPublishDialogComponent,
|
||||
AdminTermsNewEditPublishDialogContext
|
||||
} from "./publish/publish.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface ILanguage {
|
||||
name: string,
|
||||
@ -66,7 +67,9 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
private toaster: ToasterService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private modal: Modal) {
|
||||
private modal: Modal,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -94,7 +97,7 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load policy");
|
||||
this.translate.get('Failed to load policy').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
} else {
|
||||
this.adminTerms.getAllPolicies().then(policies => {
|
||||
@ -102,7 +105,7 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load policies");
|
||||
this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -133,11 +136,11 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
});
|
||||
|
||||
await this.adminTerms.publishDraft(this.shortcode, val);
|
||||
this.toaster.pop("success", "Policy published");
|
||||
this.translate.get('Policy published').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.router.navigate(["../.."], {relativeTo: this.activatedRoute});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.toaster.pop("error", "Error publishing policy");
|
||||
this.translate.get('Error publishing policy').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isUpdating = false;
|
||||
}
|
||||
});
|
||||
@ -146,11 +149,11 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
public async create() {
|
||||
for (const languageCode in this.languages) {
|
||||
if (this.languages[languageCode].name.trim().length <= 0) {
|
||||
this.toaster.pop("warning", "Please enter a name for all policies");
|
||||
this.translate.get('Please enter a name for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
if (this.languages[languageCode].text.trim().length <= 0) {
|
||||
this.toaster.pop("warning", "Please enter text for all policies");
|
||||
this.translate.get('Please enter text for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -164,12 +167,11 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
text: this.languages['en'].text,
|
||||
url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/draft`,
|
||||
});
|
||||
|
||||
this.toaster.pop("success", "Draft saved");
|
||||
this.translate.get('Draft saved').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.router.navigate(["../.."], {relativeTo: this.activatedRoute});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.toaster.pop("error", "Error saving policy");
|
||||
this.translate.get('Error saving policy').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isUpdating = false;
|
||||
}
|
||||
return;
|
||||
@ -188,12 +190,11 @@ export class AdminNewEditTermsComponent implements OnInit {
|
||||
text: this.languages['en'].text,
|
||||
url: `${window.location.origin}/widgets/terms/${shortcode}/en/draft`,
|
||||
});
|
||||
|
||||
this.toaster.pop("success", "Draft created");
|
||||
this.translate.get('Draft created').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.router.navigate([".."], {relativeTo: this.activatedRoute});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.toaster.pop("error", "Error creating document");
|
||||
this.translate.get('Error creating document').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isUpdating = false;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Publish policy</h4>
|
||||
<h4>{{'Publish policy' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<label class="label-block">
|
||||
Version number
|
||||
<span class="text-muted ">The version number of this policy</span>
|
||||
{{'Version number' | translate}}
|
||||
<span class="text-muted ">{{'The version number of this policy' | translate}}</span>
|
||||
<input type="text" class="form-control" placeholder="eg: 1.1.0" [(ngModel)]="version"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="publish()" title="close" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-upload"></i> Publish
|
||||
<i class="fas fa-upload"></i> {{'Publish' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="save" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { ToasterService } from "angular2-toaster";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class AdminTermsNewEditPublishDialogContext extends BSModalContext {
|
||||
}
|
||||
@ -14,12 +15,12 @@ export class AdminTermsNewEditPublishDialogComponent implements ModalComponent<A
|
||||
|
||||
public version: string;
|
||||
|
||||
constructor(public dialog: DialogRef<AdminTermsNewEditPublishDialogContext>, private toaster: ToasterService) {
|
||||
constructor(public dialog: DialogRef<AdminTermsNewEditPublishDialogContext>, private toaster: ToasterService, public translate: TranslateService) {
|
||||
}
|
||||
|
||||
public publish() {
|
||||
if (!this.version || !this.version.trim()) {
|
||||
this.toaster.pop("warning", "Please enter a version number");
|
||||
this.translate.get('Please enter a version number').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
this.dialog.close(this.version);
|
||||
|
@ -2,26 +2,23 @@
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="Terms of Service">
|
||||
<my-ibox boxTitle="{{'Terms of Service' | translate}}">
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
Before users can use Dimension they must agree to the terms of service for using your
|
||||
instance. If you're using any matrix.org bridges, users will be required to accept
|
||||
the terms of service for your upstream integration managers (scalar.vector.im usually)
|
||||
in addition to the terms you add here.
|
||||
{{'Before users can use Dimension they must agree to the terms of service for using your instance. If you\'re using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.' | translate}}
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Policy Name</th>
|
||||
<th>Version</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
<th>{{'Policy Name' | translate}}</th>
|
||||
<th>{{'Version' | translate}}</th>
|
||||
<th class="text-center" style="width: 120px;">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="!policies || policies.length === 0">
|
||||
<td colspan="3"><i>No policies written.</i></td>
|
||||
<td colspan="3"><i>{{'No policies written.' | translate}}</i></td>
|
||||
</tr>
|
||||
<tr *ngFor="let policy of policies trackById">
|
||||
<td>{{ policy.languages['en'].name }}</td>
|
||||
@ -37,7 +34,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="createPolicy()">
|
||||
<i class="fa fa-plus"></i> New draft policy
|
||||
<i class="fa fa-plus"></i> {{'New draft policy' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
|
@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { FE_TermsEditable } from "../../shared/models/terms";
|
||||
import { AdminTermsApiService } from "../../shared/services/admin/admin-terms-api.service";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./terms.component.html",
|
||||
@ -19,7 +20,9 @@ export class AdminTermsComponent implements OnInit {
|
||||
constructor(private adminTerms: AdminTermsApiService,
|
||||
private toaster: ToasterService,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute) {
|
||||
private activatedRoute: ActivatedRoute,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -31,7 +34,7 @@ export class AdminTermsComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load policies");
|
||||
this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Etherpad Widget Configuration</h4>
|
||||
<h4>{{'Etherpad Widget Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<label class="label-block">
|
||||
Default Pad URL Template
|
||||
<span class="text-muted ">$padName and $roomId will be replaced during creation to help create a unique pad URL.</span>
|
||||
{{'Default Pad URL Template' | translate}}
|
||||
<span class="text-muted ">{{'$padName and $roomId will be replaced during creation to help create a unique pad URL.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://scalar.vector.im/etherpad/p/$padName_$roomId"
|
||||
[(ngModel)]="widget.options.defaultUrl" [disabled]="isUpdating"/>
|
||||
@ -13,10 +13,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -4,6 +4,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { WidgetConfigDialogContext } from "../widgets.component";
|
||||
import { AdminIntegrationsApiService } from "../../../shared/services/admin/admin-integrations-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./etherpad.component.html",
|
||||
@ -15,7 +16,11 @@ export class AdminWidgetEtherpadConfigComponent implements ModalComponent<Widget
|
||||
public widget: FE_EtherpadWidget;
|
||||
private originalWidget: FE_EtherpadWidget;
|
||||
|
||||
constructor(public dialog: DialogRef<WidgetConfigDialogContext>, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService) {
|
||||
constructor(public dialog: DialogRef<WidgetConfigDialogContext>,
|
||||
private adminIntegrationsApi: AdminIntegrationsApiService,
|
||||
private toaster: ToasterService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.originalWidget = dialog.context.widget;
|
||||
this.widget = JSON.parse(JSON.stringify(this.originalWidget));
|
||||
}
|
||||
@ -24,12 +29,12 @@ export class AdminWidgetEtherpadConfigComponent implements ModalComponent<Widget
|
||||
this.isUpdating = true;
|
||||
this.adminIntegrationsApi.setIntegrationOptions(this.widget.category, this.widget.type, this.widget.options).then(() => {
|
||||
this.originalWidget.options = this.widget.options;
|
||||
this.toaster.pop("success", "Widget updated");
|
||||
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating widget");
|
||||
this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Jitsi Widget Configuration</h4>
|
||||
<h4>{{'Jitsi Widget Configuration' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<label class="label-block">
|
||||
Jitsi Domain
|
||||
<span class="text-muted ">This is the domain that is used to host the conference.</span>
|
||||
{{'Jitsi Domain' | translate}}
|
||||
<span class="text-muted ">{{'This is the domain that is used to host the conference.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="jitsi.riot.im"
|
||||
[(ngModel)]="widget.options.jitsiDomain" [disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Use this domain as the default conference domain
|
||||
<span class="text-muted ">Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you'll force Dimension to use your Jitsi domain at risk of having clients not respect it.</span>
|
||||
{{'Use this domain as the default conference domain' | translate}}
|
||||
<span class="text-muted ">{{'Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you\'ll force Dimension to use your Jitsi domain at risk of having clients not respect it.' | translate}}</span>
|
||||
<ui-switch [checked]="widget.options.useDomainAsDefault" size="medium" [disabled]="isUpdating"
|
||||
(change)="toggleForcedJitsi()"></ui-switch>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Jitsi Script URL
|
||||
<span class="text-muted ">This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.</span>
|
||||
{{'Jitsi Script URL' | translate}}
|
||||
<span class="text-muted ">{{'This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://jitsi.riot.im/libs/external_api.min.js"
|
||||
[(ngModel)]="widget.options.scriptUrl" [disabled]="isUpdating"/>
|
||||
@ -26,10 +26,10 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="save()" title="save" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Cancel
|
||||
<i class="far fa-times-circle"></i> {{'Cancel' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -4,6 +4,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||
import { WidgetConfigDialogContext } from "../widgets.component";
|
||||
import { AdminIntegrationsApiService } from "../../../shared/services/admin/admin-integrations-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./jitsi.component.html",
|
||||
@ -15,7 +16,8 @@ export class AdminWidgetJitsiConfigComponent implements ModalComponent<WidgetCon
|
||||
public widget: FE_JitsiWidget;
|
||||
private originalWidget: FE_JitsiWidget;
|
||||
|
||||
constructor(public dialog: DialogRef<WidgetConfigDialogContext>, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService) {
|
||||
constructor(public dialog: DialogRef<WidgetConfigDialogContext>, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.originalWidget = dialog.context.widget;
|
||||
this.widget = JSON.parse(JSON.stringify(this.originalWidget));
|
||||
|
||||
@ -27,12 +29,12 @@ export class AdminWidgetJitsiConfigComponent implements ModalComponent<WidgetCon
|
||||
this.isUpdating = true;
|
||||
this.adminIntegrationsApi.setIntegrationOptions(this.widget.category, this.widget.type, this.widget.options).then(() => {
|
||||
this.originalWidget.options = this.widget.options;
|
||||
this.toaster.pop("success", "Widget updated");
|
||||
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.dialog.close();
|
||||
}).catch(err => {
|
||||
this.isUpdating = false;
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating widget");
|
||||
this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,21 +4,20 @@
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="Widgets">
|
||||
<div class="my-ibox-content">
|
||||
<p>Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets
|
||||
Dimension will offer to users.</p>
|
||||
<p>{{'Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.' | translate}}</p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center">Actions</th>
|
||||
<th>{{'Description' | translate}}</th>
|
||||
<th class="text-center">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let widget of widgets trackById">
|
||||
<td>{{ widget.displayName }}</td>
|
||||
<td>{{ widget.description }}</td>
|
||||
<td>{{ widget.displayName | translate }}</td>
|
||||
<td>{{ widget.description | translate }}</td>
|
||||
<td class="text-right">
|
||||
<span class="editButton" (click)="editWidget(widget)"
|
||||
*ngIf="widget.isEnabled && hasConfiguration(widget)">
|
||||
|
@ -6,6 +6,7 @@ import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { AdminWidgetJitsiConfigComponent } from "./jitsi/jitsi.component";
|
||||
import { AdminIntegrationsApiService } from "../../shared/services/admin/admin-integrations-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class WidgetConfigDialogContext extends BSModalContext {
|
||||
public widget: FE_Widget;
|
||||
@ -21,13 +22,14 @@ export class AdminWidgetsComponent {
|
||||
public isUpdating = false;
|
||||
public widgets: FE_Widget[];
|
||||
|
||||
constructor(private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, private modal: Modal) {
|
||||
constructor(private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, private modal: Modal, public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.adminIntegrationsApi.getAllWidgets().then(widgets => {
|
||||
this.isLoading = false;
|
||||
this.widgets = widgets;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load widgets");
|
||||
this.translate.get('Failed to load widgets').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -36,12 +38,12 @@ export class AdminWidgetsComponent {
|
||||
this.isUpdating = true;
|
||||
this.adminIntegrationsApi.toggleIntegration(widget.category, widget.type, widget.isEnabled).then(() => {
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Widget updated");
|
||||
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
widget.isEnabled = !widget.isEnabled; // revert change
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error updating widget");
|
||||
this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -53,7 +55,7 @@ export class AdminWidgetsComponent {
|
||||
|
||||
if (!component) {
|
||||
console.error("No known dialog component for " + widget.type);
|
||||
this.toaster.pop("error", "Error opening configuration page");
|
||||
this.translate.get('Error opening configuration page').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { Component } from "@angular/core";
|
||||
import "../style/app.scss";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
|
||||
@Component({
|
||||
selector: "my-app", // <my-app></my-app>
|
||||
@ -8,7 +10,13 @@ import "../style/app.scss";
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
constructor() {
|
||||
console.log("Dimension AppComponent constructed");
|
||||
constructor(public translate: TranslateService, public http: HttpClient) {
|
||||
translate.addLangs(['en', 'de']);
|
||||
translate.setDefaultLang('de');
|
||||
if (navigator.language === 'de') {
|
||||
translate.use('de');
|
||||
} else {
|
||||
translate.use('en');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { UiSwitchModule } from "angular2-ui-switch";
|
||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { routing } from "./app.routing";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
import { HttpClient, HttpClientModule } from "@angular/common/http";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import { AppComponent } from "./app.component";
|
||||
import { HomeComponent } from "./home/home.component";
|
||||
@ -118,6 +118,13 @@ import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
|
||||
import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component";
|
||||
import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/publish/publish.component";
|
||||
import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component";
|
||||
import { TranslateLoader, TranslateModule } from "@ngx-translate/core";
|
||||
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http);
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -133,6 +140,13 @@ import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.compo
|
||||
BootstrapModalModule,
|
||||
BreadcrumbsModule,
|
||||
CKEditorModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: HttpLoaderFactory,
|
||||
deps: [HttpClient]
|
||||
}
|
||||
})
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
@ -183,7 +183,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: "etherpad",
|
||||
component: EtherpadWidgetConfigComponent,
|
||||
data: {breadcrumb: "Etherpad Widgets", name: "Etherpad Widgets"},
|
||||
data: {breadcrumb: "Notes Widgets", name: "Notes Widgets"},
|
||||
},
|
||||
{
|
||||
path: "googlecalendar",
|
||||
|
@ -6,6 +6,7 @@ import { IntegrationsApiService } from "../../shared/services/integrations/integ
|
||||
import { ToasterService } from "angular2-toaster";
|
||||
import { ServiceLocator } from "../../shared/registry/locator.service";
|
||||
import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class BridgeComponent<T> implements OnInit, OnDestroy {
|
||||
|
||||
@ -14,7 +15,6 @@ export class BridgeComponent<T> implements OnInit, OnDestroy {
|
||||
public bridge: FE_Bridge<T>;
|
||||
public newConfig: T;
|
||||
public roomId: string;
|
||||
|
||||
private routeQuerySubscription: Subscription;
|
||||
|
||||
protected toaster = ServiceLocator.injector.get(ToasterService);
|
||||
@ -22,7 +22,8 @@ export class BridgeComponent<T> implements OnInit, OnDestroy {
|
||||
protected route = ServiceLocator.injector.get(ActivatedRoute);
|
||||
protected scalarClientApi = ServiceLocator.injector.get(ScalarClientApiService);
|
||||
|
||||
constructor(private integrationType: string) {
|
||||
constructor(private integrationType: string, public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.isLoading = true;
|
||||
this.isUpdating = false;
|
||||
}
|
||||
@ -50,19 +51,19 @@ export class BridgeComponent<T> implements OnInit, OnDestroy {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load configuration");
|
||||
this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save(): void {
|
||||
this.isUpdating = true;
|
||||
this.integrationsApi.setIntegrationConfiguration("bridge", this.integrationType, this.roomId, this.newConfig).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.bridge.config = this.newConfig;
|
||||
this.isUpdating = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating configuration");
|
||||
this.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isUpdating = false;
|
||||
});
|
||||
}
|
||||
|
@ -2,18 +2,18 @@
|
||||
<ng-template #bridgeParamsTemplate>
|
||||
<my-ibox [isCollapsible]="false">
|
||||
<h5 class="my-ibox-title">
|
||||
Bridge to Gitter
|
||||
{{'Bridge to Gitter' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<div *ngIf="isBridged">
|
||||
This room is bridged to "{{ bridge.config.link.gitterRoomName }}" on Gitter.
|
||||
{{'This room is bridged to on Gitter' | translate}} "{{ bridge.config.link.gitterRoomName }}" {{'on Gitter' | translate}}.
|
||||
<button type="button" class="btn btn-sm btn-danger" [disabled]="isBusy" (click)="unbridgeRoom()">
|
||||
Unbridge
|
||||
{{'Unbridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="!isBridged">
|
||||
<label class="label-block">
|
||||
Gitter Room
|
||||
{{'Gitter Room' | translate}}
|
||||
<input title="room name" type="text" class="form-control form-control-sm col-md-3"
|
||||
[(ngModel)]="gitterRoomName" [disabled]="isBusy" placeholder="my-org/room"/>
|
||||
</label>
|
||||
|
@ -3,6 +3,7 @@ import { BridgeComponent } from "../bridge.component";
|
||||
import { FE_GitterLink } from "../../../shared/models/gitter";
|
||||
import { GitterApiService } from "../../../shared/services/integrations/gitter-api.service";
|
||||
import { ScalarClientApiService } from "../../../shared/services/scalar/scalar-client-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface GitterConfig {
|
||||
botUserId: string;
|
||||
@ -18,8 +19,9 @@ export class GitterBridgeConfigComponent extends BridgeComponent<GitterConfig> {
|
||||
public gitterRoomName: string;
|
||||
public isBusy: boolean;
|
||||
|
||||
constructor(private gitter: GitterApiService, private scalar: ScalarClientApiService) {
|
||||
super("gitter");
|
||||
constructor(private gitter: GitterApiService, private scalar: ScalarClientApiService, public translate: TranslateService) {
|
||||
super("gitter", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public get isBridged(): boolean {
|
||||
@ -35,7 +37,7 @@ export class GitterBridgeConfigComponent extends BridgeComponent<GitterConfig> {
|
||||
if (!e.response || !e.response.error || !e.response.error._error ||
|
||||
e.response.error._error.message.indexOf("already in the room") === -1) {
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("error", "Error inviting bridge");
|
||||
this.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -43,11 +45,11 @@ export class GitterBridgeConfigComponent extends BridgeComponent<GitterConfig> {
|
||||
this.gitter.bridgeRoom(this.roomId, this.gitterRoomName).then(link => {
|
||||
this.bridge.config.link = link;
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("success", "Bridge requested");
|
||||
this.translate.get('Bridge requested').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isBusy = false;
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error requesting bridge");
|
||||
this.translate.get('Error requesting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -56,11 +58,11 @@ export class GitterBridgeConfigComponent extends BridgeComponent<GitterConfig> {
|
||||
this.gitter.unbridgeRoom(this.roomId).then(() => {
|
||||
this.bridge.config.link = null;
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("success", "Bridge removed");
|
||||
this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isBusy = false;
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error removing bridge");
|
||||
this.translate.get('Error removing bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -2,18 +2,16 @@
|
||||
<ng-template #bridgeParamsTemplate>
|
||||
<my-ibox [isCollapsible]="true">
|
||||
<h5 class="my-ibox-title">
|
||||
Add an IRC channel
|
||||
{{'Add an IRC channel' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<div class="alert alert-info">
|
||||
Bridging a channel requires authorization from a channel operator. When entering a channel below, a
|
||||
bot will
|
||||
join the channel to ensure it exists and has operators available.
|
||||
{{'Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.' | translate}}
|
||||
</div>
|
||||
|
||||
<div *ngIf="channelStep === 1">
|
||||
<label class="label-block">
|
||||
Network
|
||||
{{'Network' | translate}}
|
||||
<select class="form-control form-control-sm" [(ngModel)]="networkId" [disabled]="loadingOps">
|
||||
<option *ngFor="let network of getNetworks()" [ngValue]="network.id">
|
||||
{{ network.name }}
|
||||
@ -21,7 +19,7 @@
|
||||
</select>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Channel Name
|
||||
{{'Channel Name' | translate}}
|
||||
</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<div class="input-group-addon">#</div>
|
||||
@ -31,15 +29,15 @@
|
||||
<div style="margin-top: 25px">
|
||||
<button type="button" class="btn btn-sm btn-primary" [disabled]="loadingOps"
|
||||
(click)="loadOps()">
|
||||
Next
|
||||
{{'Next' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="channelStep === 2">
|
||||
<label class="label-block">
|
||||
Operator
|
||||
<span class="text-muted ">The person selected here will be asked to approve or deny the bridge request.</span>
|
||||
{{'Operator' | translate}}
|
||||
<span class="text-muted ">{{'The person selected here will be asked to approve or deny the bridge request.' | translate}}</span>
|
||||
<select class="form-control form-control-sm" [(ngModel)]="op" [disabled]="requestingBridge">
|
||||
<option *ngFor="let op of ops" [ngValue]="op">{{ op }}</option>
|
||||
</select>
|
||||
@ -47,7 +45,7 @@
|
||||
<div style="margin-top: 25px">
|
||||
<button type="button" class="btn btn-sm btn-primary" [disabled]="requestingBridge"
|
||||
(click)="requestBridge()">
|
||||
Request Bridge
|
||||
{{'Request Bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -55,20 +53,20 @@
|
||||
</my-ibox>
|
||||
<my-ibox [isCollapsible]="true">
|
||||
<h5 class="my-ibox-title">
|
||||
IRC Networks
|
||||
{{'IRC Networks' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Channel</th>
|
||||
<th>Network</th>
|
||||
<th class="actions-col">Actions</th>
|
||||
<th>{{'Channel' | translate}}</th>
|
||||
<th>{{'Network' | translate}}</th>
|
||||
<th class="actions-col">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="getChannels().length === 0">
|
||||
<td colspan="3">No bridged channels</td>
|
||||
<td colspan="3">{{'No bridged channels' | translate}}</td>
|
||||
</tr>
|
||||
<tr *ngFor="let channel of getChannels()">
|
||||
<td>
|
||||
@ -80,7 +78,7 @@
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
[disabled]="isUpdating || channel.pending"
|
||||
(click)="removeChannel(channel)">
|
||||
<i class="far fa-trash-alt"></i> Remove
|
||||
<i class="far fa-trash-alt"></i> {{'Remove' | translate}}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
||||
import { BridgeComponent } from "../bridge.component";
|
||||
import { FE_IrcBridgeAvailableNetworks } from "../../../shared/models/irc";
|
||||
import { IrcApiService } from "../../../shared/services/integrations/irc-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface IrcConfig {
|
||||
availableNetworks: FE_IrcBridgeAvailableNetworks;
|
||||
@ -34,8 +35,9 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
public op: string;
|
||||
public pending: LocalChannel[] = [];
|
||||
|
||||
constructor(private irc: IrcApiService) {
|
||||
super("irc");
|
||||
constructor(private irc: IrcApiService, public translate: TranslateService) {
|
||||
super("irc", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
private resetForm() {
|
||||
@ -55,7 +57,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
|
||||
public loadOps() {
|
||||
if (!this.channel.trim()) {
|
||||
this.toaster.pop("warning", "Please enter a channel name");
|
||||
this.translate.get('Please enter a channel name').subscribe((res: string) => {this.toaster.pop("warning", res); });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -68,7 +70,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.loadingOps = false;
|
||||
this.toaster.pop("error", "Error loading channel operators");
|
||||
this.translate.get('Error loading channel operators').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -86,7 +88,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.requestingBridge = false;
|
||||
this.toaster.pop("error", "Failed to make the bridge an administrator", "Please ensure you are an 'Admin' for the room");
|
||||
this.translate.get(['Failed to make the bridge an administrator', 'Please ensure you are an \'Admin\' for the room']).subscribe((res: string) => {this.toaster.pop("error", res[0], res[1]); });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -99,11 +101,11 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
pending: true,
|
||||
});
|
||||
this.resetForm();
|
||||
this.toaster.pop("success", "Link requested!", "The operator selected will have to approve the bridge for it to work");
|
||||
this.translate.get(['Link requested!', 'The operator selected will have to approve the bridge for it to work']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.requestingBridge = false;
|
||||
this.toaster.pop("error", "Failed to request a link");
|
||||
this.translate.get('Failed to request a link').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -133,10 +135,10 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
|
||||
this.isUpdating = false;
|
||||
const idx = this.bridge.config.links[channel.networkId].findIndex(c => c.channelName === channel.name);
|
||||
if (idx !== -1) this.bridge.config.links[channel.networkId].splice(idx, 1);
|
||||
this.toaster.pop("success", "Link removed");
|
||||
this.translate.get('Link removed').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to remove link");
|
||||
this.translate.get('Failed to remove link').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -2,30 +2,28 @@
|
||||
<ng-template #bridgeParamsTemplate>
|
||||
<my-ibox [isCollapsible]="false">
|
||||
<h5 class="my-ibox-title">
|
||||
Bridge to Slack
|
||||
{{'Bridge to Slack' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content" *ngIf="loadingTeams">
|
||||
<my-spinner></my-spinner>
|
||||
</div>
|
||||
<div class="my-ibox-content" *ngIf="!loadingTeams">
|
||||
<div *ngIf="isBridged && bridge.config.link.isWebhook">
|
||||
This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as
|
||||
rich bridging as the new approach. It is recommended to re-create the bridge with the new process.
|
||||
{{'This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn\'t support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.' | translate}}
|
||||
<br/>
|
||||
<button type="button" class="btn btn-sm btn-danger" [disabled]="isBusy" (click)="unbridgeRoom()">
|
||||
Unbridge
|
||||
{{'Unbridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="isBridged && !bridge.config.link.isWebhook">
|
||||
This room is bridged to "{{ bridge.config.link.channelName }}" on Slack.
|
||||
<button type="button" class="btn btn-sm btn-danger" [disabled]="isBusy" (click)="unbridgeRoom()">
|
||||
Unbridge
|
||||
{{'Unbridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="!isBridged && needsAuth">
|
||||
<p>
|
||||
In order to bridge Slack channels, you'll need to authorize the bridge to access your teams
|
||||
and channels. Please click the button below to do so.
|
||||
{{'In order to bridge Slack channels, you\'ll need to authorize the bridge to access your teams and channels. Please click the button below to do so.' | translate}}
|
||||
</p>
|
||||
<a [href]="authUrl" rel="noopener" target="_blank">
|
||||
<img src="/img/slack_auth_button.png" class="slack-auth-button" alt="sign in with slack"/>
|
||||
@ -33,7 +31,7 @@
|
||||
</div>
|
||||
<div *ngIf="!isBridged && !needsAuth">
|
||||
<label class="label-block">
|
||||
Team
|
||||
{{'Team' | translate}}
|
||||
<select class="form-control form-control-sm" [(ngModel)]="teamId"
|
||||
(change)="loadChannels()" [disabled]="isBusy">
|
||||
<option *ngFor="let team of teams" [ngValue]="team.id">
|
||||
@ -42,7 +40,7 @@
|
||||
</select>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Channel
|
||||
{{'Channel' | translate}}
|
||||
<select class="form-control form-control-sm" [(ngModel)]="channelId" [disabled]="isBusy">
|
||||
<option *ngFor="let channel of channels" [ngValue]="channel.id">
|
||||
{{ channel.name }}
|
||||
|
@ -4,6 +4,7 @@ import { FE_SlackChannel, FE_SlackLink, FE_SlackTeam } from "../../../shared/mod
|
||||
import { SlackApiService } from "../../../shared/services/integrations/slack-api.service";
|
||||
import { ScalarClientApiService } from "../../../shared/services/scalar/scalar-client-api.service";
|
||||
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface SlackConfig {
|
||||
botUserId: string;
|
||||
@ -27,8 +28,9 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
|
||||
private timerId: any;
|
||||
|
||||
constructor(private slack: SlackApiService, private scalar: ScalarClientApiService, private sanitizer: DomSanitizer) {
|
||||
super("slack");
|
||||
constructor(private slack: SlackApiService, private scalar: ScalarClientApiService, private sanitizer: DomSanitizer, public translate: TranslateService) {
|
||||
super("slack", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
@ -58,7 +60,7 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
this.loadingTeams = false;
|
||||
}).catch(error2 => {
|
||||
console.error(error2);
|
||||
this.toaster.pop("error", "Error getting Slack authorization information");
|
||||
this.translate.get('Error getting Slack authorization information').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
|
||||
this.timerId = setInterval(() => {
|
||||
@ -67,7 +69,7 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
}
|
||||
} else {
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error getting teams");
|
||||
this.translate.get('Error getting teams').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -84,7 +86,7 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
this.isBusy = false;
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error getting channels for team");
|
||||
this.translate.get('Error getting channels for team').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isBusy = false;
|
||||
});
|
||||
}
|
||||
@ -98,7 +100,7 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
if (!e.response || !e.response.error || !e.response.error._error ||
|
||||
e.response.error._error.message.indexOf("already in the room") === -1) {
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("error", "Error inviting bridge");
|
||||
this.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -106,11 +108,11 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
this.slack.bridgeRoom(this.roomId, this.teamId, this.channelId).then(link => {
|
||||
this.bridge.config.link = link;
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("success", "Bridge requested");
|
||||
this.translate.get('Bridge requested').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isBusy = false;
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error requesting bridge");
|
||||
this.translate.get('Error requesting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -119,11 +121,11 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
|
||||
this.slack.unbridgeRoom(this.roomId).then(() => {
|
||||
this.bridge.config.link = null;
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("success", "Bridge removed");
|
||||
this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isBusy = false;
|
||||
console.error(error);
|
||||
this.toaster.pop("error", "Error removing bridge");
|
||||
this.translate.get('Error removing bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Telegram chat is already bridged</h4>
|
||||
<h4>{{'Telegram chat is already bridged' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge
|
||||
the other room and instead bridge it here?
|
||||
{{'You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge the other room and instead bridge it here?' | translate}}
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="unbridgeAndContinue()" title="unbridge and continue"
|
||||
class="btn btn-danger btn-sm">
|
||||
Unbridge and continue
|
||||
{{'Unbridge and continue' | translate}}
|
||||
</button>
|
||||
<button type="button" (click)="cancel()" title="cancel" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-times-circle"></i> No, don't bridge
|
||||
<i class="far fa-times-circle"></i> {{'No, don\'t bridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -1,14 +1,13 @@
|
||||
<div class="dialog">
|
||||
<div class="dialog-header">
|
||||
<h4>Telegram chat is already bridged</h4>
|
||||
<h4>{{'Telegram chat is already bridged' | translate}}</h4>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not
|
||||
have the required permissions to be able to unbridge the other room.
|
||||
{{'That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not have the required permissions to be able to unbridge the other room.' | translate}}
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="dialog.close()" title="cancel" class="btn btn-primary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -2,25 +2,25 @@
|
||||
<ng-template #bridgeParamsTemplate>
|
||||
<my-ibox [isCollapsible]="false">
|
||||
<h5 class="my-ibox-title">
|
||||
Bridge to Telegram
|
||||
{{'Bridge to Telegram' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<div *ngIf="isBridged">
|
||||
This room is bridged to "{{ chatName }}" (<code>{{ chatId }}</code>) on Telegram.
|
||||
{{'This room is bridged to on Telegram' | translate}} "{{ chatName }}" (<code>{{ chatId }}</code>) {{'on Telegram' | translate}}.
|
||||
<div *ngIf="canUnbridge">
|
||||
<button type="button" class="btn btn-sm btn-danger" [disabled]="isUpdating"
|
||||
(click)="unbridgeRoom()">
|
||||
Unbridge
|
||||
{{'Unbridge' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
<span *ngIf="!canUnbridge">
|
||||
You do not have the necessary permissions in this room to unbridge the channel.
|
||||
{{'You do not have the necessary permissions in this room to unbridge the channel.' | translate}}
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="!isBridged">
|
||||
<label class="label-block">
|
||||
Chat ID
|
||||
<span class="text-muted">After inviting <a href="https://t.me/{{ botUsername }}" target="_blank">@{{ botUsername }}</a> to your Telegram chat, run the command <code>/id</code> in the Telegram room to get the chat ID.</span>
|
||||
<span class="text-muted">{{'After inviting' | translate}} <a href="https://t.me/{{ botUsername }}" target="_blank">@{{ botUsername }}</a> {{'to your Telegram chat, run the command' | translate}} <code>/id</code> {{'in the Telegram room to get the chat ID.' | translate}}</span>
|
||||
<input title="chat ID" type="text" class="form-control form-control-sm col-md-3"
|
||||
[(ngModel)]="chatId" [disabled]="isUpdating"/>
|
||||
</label>
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
CannotUnbridgeDialogContext,
|
||||
TelegramCannotUnbridgeComponent
|
||||
} from "./cannot-unbridge/cannot-unbridge.component";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface TelegramConfig {
|
||||
puppet: {
|
||||
@ -39,8 +40,9 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
|
||||
|
||||
public isUpdating: boolean;
|
||||
|
||||
constructor(private telegram: TelegramApiService, private modal: Modal) {
|
||||
super("telegram");
|
||||
constructor(private telegram: TelegramApiService, private modal: Modal, public translate: TranslateService) {
|
||||
super("telegram", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public get isBridged(): boolean {
|
||||
@ -103,20 +105,20 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
|
||||
this.bridge.config.portalInfo = portalInfo;
|
||||
this.bridge.config.linked = [portalInfo.chatId];
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Bridge updated");
|
||||
this.translate.get('Bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isUpdating = false;
|
||||
console.error(error);
|
||||
|
||||
const body = error.json ? error.json() : null;
|
||||
let message = "Error bridging room";
|
||||
let message = 'Error bridging room';
|
||||
if (body) {
|
||||
if (body["dim_errcode"] === "CHAT_ALREADY_BRIDGED") message = "That Telegram chat is already bridged to another room";
|
||||
if (body["dim_errcode"] === "ROOM_ALREADY_BRIDGED") message = "This room is already bridged to a Telegram chat";
|
||||
if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = "The Telegram bot has not been invited to the chat";
|
||||
if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = "You do not have permission to bridge that chat";
|
||||
}
|
||||
this.toaster.pop("error", message);
|
||||
if (body["dim_errcode"] === "CHAT_ALREADY_BRIDGED") message = 'That Telegram chat is already bridged to another room';
|
||||
if (body["dim_errcode"] === "ROOM_ALREADY_BRIDGED") message = 'This room is already bridged to a Telegram chat';
|
||||
if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = 'The Telegram bot has not been invited to the chat';
|
||||
if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = 'You do not have permission to bridge that chat';
|
||||
}
|
||||
this.translate.get(message).subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -126,18 +128,17 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
|
||||
this.bridge.config.portalInfo = portalInfo;
|
||||
this.bridge.config.linked = [];
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Bridge removed");
|
||||
this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(error => {
|
||||
this.isUpdating = false;
|
||||
console.error(error);
|
||||
|
||||
const body = error.json ? error.json() : null;
|
||||
let message = "Error removing bridge";
|
||||
let message = 'Error removing bridge';
|
||||
if (body) {
|
||||
if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = "The Telegram bot has not been invited to the chat";
|
||||
if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = "You do not have permission to unbridge that chat";
|
||||
if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = 'The Telegram bot has not been invited to the chat';
|
||||
if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = 'You do not have permission to unbridge that chat';
|
||||
}
|
||||
this.toaster.pop("error", message);
|
||||
this.translate.get(message).subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -2,17 +2,17 @@
|
||||
<ng-template #bridgeParamsTemplate>
|
||||
<my-ibox [isCollapsible]="true">
|
||||
<h5 class="my-ibox-title">
|
||||
Add a new webhook
|
||||
{{'Add a new webhook' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<label class="label-block">
|
||||
Webhook Name
|
||||
{{'Webhook Name' | translate}}
|
||||
<input title="webhook name" type="text" class="form-control form-control-sm"
|
||||
[(ngModel)]="webhookName" [disabled]="isBusy">
|
||||
</label>
|
||||
<div style="margin-top: 25px">
|
||||
<button type="button" class="btn btn-sm btn-primary" [disabled]="isBusy" (click)="newHook()">
|
||||
Create
|
||||
{{'Create' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -26,25 +26,25 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>{{'Type' | translate}}</th>
|
||||
<th>URL</th>
|
||||
<th class="actions-col">Actions</th>
|
||||
<th class="actions-col">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngIf="newConfig.webhooks.length === 0">
|
||||
<td colspan="4">No webhooks</td>
|
||||
<td colspan="4">{{'No webhooks' | translate}}</td>
|
||||
</tr>
|
||||
<tr *ngFor="let hook of newConfig.webhooks">
|
||||
<td *ngIf="hook.label">{{ hook.label }}</td>
|
||||
<td *ngIf="!hook.label"><i>No name</i></td>
|
||||
<td *ngIf="!hook.label"><i>{{'No name' | translate}}</i></td>
|
||||
<td>{{ hook.type }}</td>
|
||||
<td class="webhook-url"><a [href]="hook.url" target="_blank">{{ hook.url }}</a></td>
|
||||
<td class="actions-col">
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
[disabled]="isBusy"
|
||||
(click)="removeHook(hook)">
|
||||
<i class="far fa-trash-alt"></i> Delete
|
||||
<i class="far fa-trash-alt"></i> {{'Delete' | translate}}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -3,6 +3,7 @@ import { BridgeComponent } from "../bridge.component";
|
||||
import { FE_Webhook } from "../../../shared/models/webhooks";
|
||||
import { WebhooksApiService } from "../../../shared/services/integrations/webhooks-api.service";
|
||||
import { ScalarClientApiService } from "../../../shared/services/scalar/scalar-client-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface WebhooksConfig {
|
||||
webhooks: FE_Webhook[];
|
||||
@ -18,8 +19,8 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent<WebhooksConfi
|
||||
public webhookName: string;
|
||||
public isBusy = false;
|
||||
|
||||
constructor(private webhooks: WebhooksApiService, private scalar: ScalarClientApiService) {
|
||||
super("webhooks");
|
||||
constructor(private webhooks: WebhooksApiService, private scalar: ScalarClientApiService, public translate: TranslateService) {
|
||||
super("webhooks", translate);
|
||||
}
|
||||
|
||||
public async newHook() {
|
||||
@ -31,7 +32,7 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent<WebhooksConfi
|
||||
if (!e.response || !e.response.error || !e.response.error._error ||
|
||||
e.response.error._error.message.indexOf("already in the room") === -1) {
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("error", "Error inviting bridge");
|
||||
this.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -40,11 +41,11 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent<WebhooksConfi
|
||||
this.newConfig.webhooks.push(hook);
|
||||
this.isBusy = false;
|
||||
this.webhookName = "";
|
||||
this.toaster.pop("success", "Webhook created");
|
||||
this.translate.get('Webhook created').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("error", "Error creating webhook");
|
||||
this.translate.get('Error creating webhook').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -54,11 +55,11 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent<WebhooksConfi
|
||||
const idx = this.newConfig.webhooks.indexOf(hook);
|
||||
if (idx !== -1) this.newConfig.webhooks.splice(idx, 1);
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("success", "Webhook deleted");
|
||||
this.translate.get('Webhook deleted').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isBusy = false;
|
||||
this.toaster.pop("error", "Error deleting webhook");
|
||||
this.translate.get('Error deleting webhook').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import { IntegrationsApiService } from "../../shared/services/integrations/integ
|
||||
import { ToasterService } from "angular2-toaster";
|
||||
import { ServiceLocator } from "../../shared/registry/locator.service";
|
||||
import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class ComplexBotComponent<T> implements OnInit, OnDestroy {
|
||||
|
||||
@ -22,7 +23,7 @@ export class ComplexBotComponent<T> implements OnInit, OnDestroy {
|
||||
protected route = ServiceLocator.injector.get(ActivatedRoute);
|
||||
protected scalarClientApi = ServiceLocator.injector.get(ScalarClientApiService);
|
||||
|
||||
constructor(private integrationType: string) {
|
||||
constructor(private integrationType: string, public translate: TranslateService) {
|
||||
this.isLoading = true;
|
||||
this.isUpdating = false;
|
||||
}
|
||||
@ -50,20 +51,20 @@ export class ComplexBotComponent<T> implements OnInit, OnDestroy {
|
||||
this.isLoading = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Failed to load configuration");
|
||||
this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
public save(): void {
|
||||
this.isUpdating = true;
|
||||
this.integrationsApi.setIntegrationConfiguration("complex-bot", this.integrationType, this.roomId, this.newConfig).then(() => {
|
||||
this.toaster.pop("success", "Configuration updated");
|
||||
this.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.bot.config = this.newConfig;
|
||||
this.newConfig = JSON.parse(JSON.stringify(this.bot.config));
|
||||
this.isUpdating = false;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.toaster.pop("error", "Error updating configuration");
|
||||
this.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
this.isUpdating = false;
|
||||
});
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
<ng-template #botParamsTemplate>
|
||||
<my-ibox>
|
||||
<h5 class="my-ibox-title">
|
||||
Feeds
|
||||
{{'Feeds' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<form (submit)="interceptSave()" novalidate name="saveForm">
|
||||
@ -10,8 +10,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
<th>Added by</th>
|
||||
<th class="actions-col">Actions</th>
|
||||
<th>{{'Added by' | translate}}</th>
|
||||
<th class="actions-col">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -22,7 +22,7 @@
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
[disabled]="isUpdating || !feed.isSelf"
|
||||
(click)="removeFeed(feed)">
|
||||
<i class="far fa-trash-alt"></i> Remove
|
||||
<i class="far fa-trash-alt"></i> {{'Remove' | translate}}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -38,7 +38,7 @@
|
||||
<button type="button" class="btn btn-outline-success"
|
||||
[disabled]="isUpdating"
|
||||
(click)="addFeed()">
|
||||
<i class="fa fa-plus"></i> Add
|
||||
<i class="fa fa-plus"></i> {{'Add' | translate}}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
@ -48,7 +48,7 @@
|
||||
</table>
|
||||
<div style="margin-top: 25px">
|
||||
<button type="submit" class="btn btn-sm btn-primary" [disabled]="isUpdating">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ComplexBotComponent } from "../complex-bot.component";
|
||||
import { Component } from "@angular/core";
|
||||
import { SessionStorage } from "../../../shared/SessionStorage";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface RssConfig {
|
||||
feeds: {
|
||||
@ -24,13 +25,14 @@ export class RssComplexBotConfigComponent extends ComplexBotComponent<RssConfig>
|
||||
|
||||
public newFeedUrl = "";
|
||||
|
||||
constructor() {
|
||||
super("rss");
|
||||
constructor(public translate: TranslateService) {
|
||||
super("rss", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public addFeed(): void {
|
||||
if (!this.newFeedUrl.trim()) {
|
||||
this.toaster.pop('warning', 'Please enter a feed URL');
|
||||
this.translate.get('Please enter a feed URL').subscribe((res: string) => {this.toaster.pop('warning', res); });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,50 +2,49 @@
|
||||
<ng-template #botParamsTemplate>
|
||||
<my-ibox [isCollapsible]="true">
|
||||
<h5 class="my-ibox-title">
|
||||
.travis.yml configuration and template information
|
||||
{{'.travis.yml configuration and template information' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<p>
|
||||
The following section needs to be added to your <code>.travis.yml</code> file in your repositories:
|
||||
{{'The following section needs to be added to your' | translate}} <code>.travis.yml</code> {{'file in your repositories:' | translate}}
|
||||
</p>
|
||||
<pre>{{ travisYaml }}</pre>
|
||||
|
||||
<p>
|
||||
The following variables can be used in your template. This template is used to post a message to the
|
||||
room when your webhook is activated.
|
||||
{{'The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.' | translate}}
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>{{ '%{repository_slug}' }}</code> - The repository identifier (eg: "matrix-org/synapse")</li>
|
||||
<li><code>{{ '%{repository_name}' }}</code> - The repository name (eg: "synapse")</li>
|
||||
<li><code>{{ '%{build_number}' }}</code> - The build number</li>
|
||||
<li><code>{{ '%{build_id}' }}</code> - The build ID</li>
|
||||
<li><code>{{ '%{branch}' }}</code> - The branch name</li>
|
||||
<li><code>{{ '%{commit}' }}</code> - A short version of the commit SHA</li>
|
||||
<li><code>{{ '%{commit_subject}' }}</code> - The first line of the commit message</li>
|
||||
<li><code>{{ '%{commit_message}' }}</code> - The full commit message</li>
|
||||
<li><code>{{ '%{author}' }}</code> - The author of the commit</li>
|
||||
<li><code>{{ '%{result}' }}</code> - The result of the build</li>
|
||||
<li><code>{{ '%{message}' }}</code> - The message from Travis CI about the build</li>
|
||||
<li><code>{{ '%{duration}' }}</code> - The total duration of all builds in the matrix</li>
|
||||
<li><code>{{ '%{elapsed_timed}' }}</code> - The time it took to run the build</li>
|
||||
<li><code>{{ '%{compare_url}' }}</code> - A URL to see the changes which triggered the build</li>
|
||||
<li><code>{{ '%{build_url}' }}</code> - A URL to see the build information</li>
|
||||
<li><code>{{ '%{repository_slug}' }}</code> - {{'The repository identifier' | translate}} (eg: "matrix-org/synapse")</li>
|
||||
<li><code>{{ '%{repository_name}' }}</code> - {{'The repository name' | translate}} (eg: "synapse")</li>
|
||||
<li><code>{{ '%{build_number}' }}</code> - {{'The build number' | translate}}</li>
|
||||
<li><code>{{ '%{build_id}' }}</code> - {{'The build ID' | translate}}</li>
|
||||
<li><code>{{ '%{branch}' }}</code> - {{'The branch name' | translate}}</li>
|
||||
<li><code>{{ '%{commit}' }}</code> - {{'A short version of the commit SHA' | translate}}</li>
|
||||
<li><code>{{ '%{commit_subject}' }}</code> - {{'The first line of the commit message' | translate}}</li>
|
||||
<li><code>{{ '%{commit_message}' }}</code> - {{'The full commit message' | translate}}</li>
|
||||
<li><code>{{ '%{author}' }}</code> - {{'The author of the commit' | translate}}</li>
|
||||
<li><code>{{ '%{result}' }}</code> - {{'The result of the build' | translate}}</li>
|
||||
<li><code>{{ '%{message}' }}</code> - {{'The message from Travis CI about the build' | translate}}</li>
|
||||
<li><code>{{ '%{duration}' }}</code> - {{'The total duration of all builds in the matrix' | translate}}</li>
|
||||
<li><code>{{ '%{elapsed_timed}' }}</code> - {{'The time it took to run the build' | translate}}</li>
|
||||
<li><code>{{ '%{compare_url}' }}</code> - {{'A URL to see the changes which triggered the build' | translate}}</li>
|
||||
<li><code>{{ '%{build_url}' }}</code> - {{'A URL to see the build information' | translate}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</my-ibox>
|
||||
<my-ibox>
|
||||
<h5 class="my-ibox-title">
|
||||
Repositories
|
||||
{{'Repositories' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<form (submit)="interceptSave()" novalidate name="saveForm">
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Repository</th>
|
||||
<th>Template</th>
|
||||
<th>Added by</th>
|
||||
<th class="actions-col">Actions</th>
|
||||
<th>{{'Repository' | translate}}</th>
|
||||
<th>{{'Template' | translate}}</th>
|
||||
<th>{{'Added by' | translate}}</th>
|
||||
<th class="actions-col">{{'Actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -61,7 +60,7 @@
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
[disabled]="isUpdating || !repo.isSelf"
|
||||
(click)="removeRepo(repo)">
|
||||
<i class="far fa-trash-alt"></i> Remove
|
||||
<i class="far fa-trash-alt"></i> {{'Remove' | translate}}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -77,7 +76,7 @@
|
||||
<button type="button" class="btn btn-outline-success"
|
||||
[disabled]="isUpdating"
|
||||
(click)="addRepo()">
|
||||
<i class="fa fa-plus"></i> Add
|
||||
<i class="fa fa-plus"></i> {{'Add' | translate}}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
@ -87,7 +86,7 @@
|
||||
</table>
|
||||
<div style="margin-top: 25px">
|
||||
<button type="submit" class="btn btn-sm btn-primary" [disabled]="isUpdating">
|
||||
<i class="far fa-save"></i> Save
|
||||
<i class="far fa-save"></i> {{'Save' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ComplexBotComponent } from "../complex-bot.component";
|
||||
import { Component } from "@angular/core";
|
||||
import { SessionStorage } from "../../../shared/SessionStorage";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
interface TravisCiConfig {
|
||||
webhookId: string;
|
||||
@ -27,8 +28,9 @@ export class TravisCiComplexBotConfigComponent extends ComplexBotComponent<Travi
|
||||
|
||||
public newRepoKey = "";
|
||||
|
||||
constructor() {
|
||||
super("travisci");
|
||||
constructor(public translate: TranslateService) {
|
||||
super("travisci", translate);
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public get webhookUrl(): string {
|
||||
@ -50,7 +52,7 @@ export class TravisCiComplexBotConfigComponent extends ComplexBotComponent<Travi
|
||||
|
||||
public addRepo(): void {
|
||||
if (!this.newRepoKey.trim()) {
|
||||
this.toaster.pop('warning', 'Please enter a repository');
|
||||
this.translate.get('Please enter a repository').subscribe((res: string) => {this.toaster.pop('warning', res); });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" (click)="dialog.close()" title="close" class="btn btn-secondary btn-sm">
|
||||
<i class="far fa-times-circle"></i> Close
|
||||
<i class="far fa-times-circle"></i> {{'Close' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -5,6 +5,7 @@ import { ScalarClientApiService } from "../../shared/services/scalar/scalar-clie
|
||||
import { IntegrationsApiService } from "../../shared/services/integrations/integrations-api.service";
|
||||
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||
import { DialogRef } from "ngx-modialog";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
export class SimpleBotConfigDialogContext extends BSModalContext {
|
||||
public bot: FE_SimpleBot;
|
||||
@ -24,7 +25,9 @@ export class ConfigSimpleBotComponent {
|
||||
constructor(public dialog: DialogRef<SimpleBotConfigDialogContext>,
|
||||
private toaster: ToasterService,
|
||||
private scalar: ScalarClientApiService,
|
||||
private integrationsApi: IntegrationsApiService) {
|
||||
private integrationsApi: IntegrationsApiService,
|
||||
public translate: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.bot = dialog.context.bot;
|
||||
this.roomId = dialog.context.roomId;
|
||||
|
||||
@ -41,8 +44,11 @@ export class ConfigSimpleBotComponent {
|
||||
this.bot._isUpdating = true;
|
||||
promise.then(() => {
|
||||
this.bot._isUpdating = false;
|
||||
if (this.bot._inRoom) this.toaster.pop("success", this.bot.displayName + " was invited to the room");
|
||||
else this.toaster.pop("success", this.bot.displayName + " was removed from the room");
|
||||
if (this.bot._inRoom) {
|
||||
this.translate.get('was invited to the room').subscribe((res: string) => {this.toaster.pop("success", this.bot.displayName + res); });
|
||||
} else {
|
||||
this.translate.get('was removed from the room').subscribe((res: string) => {this.toaster.pop("success", this.bot.displayName + res); });
|
||||
}
|
||||
}).catch(err => {
|
||||
this.bot._inRoom = !this.bot._inRoom; // revert the status change
|
||||
this.bot._isUpdating = false;
|
||||
@ -51,9 +57,8 @@ export class ConfigSimpleBotComponent {
|
||||
let errorMessage = null;
|
||||
if (err.json) errorMessage = err.json().error;
|
||||
if (err.response && err.response.error) errorMessage = err.response.error.message;
|
||||
if (!errorMessage) errorMessage = "Could not update integration status";
|
||||
|
||||
this.toaster.pop("error", errorMessage);
|
||||
if (!errorMessage) errorMessage = "";
|
||||
this.translate.get('Could not update integration status').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
<div *ngIf="!isLoading">
|
||||
<my-ibox boxTitle="Sticker Packs" *ngIf="packs.length <= 0 && !customEnabled">
|
||||
<div class="my-ibox-content">
|
||||
<h5 style="text-align: center;">Sticker packs are not enabled on this Dimension instance.</h5>
|
||||
<h5 style="text-align: center;">{{'Sticker packs are not enabled on this Dimension instance.' | translate}}</h5>
|
||||
</div>
|
||||
</my-ibox>
|
||||
<my-ibox boxTitle="Add Sticker Packs" *ngIf="customEnabled">
|
||||
@ -12,14 +12,14 @@
|
||||
<form (submit)="importPack()" novalidate name="importForm">
|
||||
<label class="label-block">
|
||||
Stickerpack URL
|
||||
<span class="text-muted">Start a conversation with {{stickerBot}} to create your own stickerpack.</span>
|
||||
<span class="text-muted">{{'Start a conversation with' | translate}} {{stickerBot}} {{'to create your own stickerpack.' | translate}}</span>
|
||||
<input type="text" class="form-control" name="packUrl"
|
||||
placeholder="{{managerUrl}}/pack/..."
|
||||
[(ngModel)]="packUrl" [disabled]="isImporting"/>
|
||||
</label>
|
||||
<div style="margin-top: 25px">
|
||||
<button type="submit" class="btn btn-sm btn-success" [disabled]="isImporting">
|
||||
<i class="fa fa-plus"></i> Add stickerpack
|
||||
<i class="fa fa-plus"></i> {{'Add stickerpack' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -33,11 +33,11 @@
|
||||
<ui-switch [checked]="pack.isSelected" size="medium" [disabled]="isUpdating"
|
||||
(change)="toggleSelected(pack)" class="toggle-switch"></ui-switch>
|
||||
|
||||
<span class="name">{{ pack.displayName }}</span>
|
||||
<span class="description">{{ pack.description }}</span>
|
||||
<span class="name">{{ pack.displayName | translate}}</span>
|
||||
<span class="description">{{ pack.description | translate}}</span>
|
||||
|
||||
<span class="author" *ngIf="pack.author.type !== 'none'">Created by <a
|
||||
[href]="pack.author.reference">{{ pack.author.name }}</a> under </span>
|
||||
<span class="author" *ngIf="pack.author.type !== 'none'">{{'Created by' | translate}} <a
|
||||
[href]="pack.author.reference">{{ pack.author.name }}</a> {{'under' | translate}} </span>
|
||||
<span class="license"><a [href]="pack.license.urlPath">{{ pack.license.name }}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5,6 +5,7 @@ import { ToasterService } from "angular2-toaster";
|
||||
import { MediaService } from "../../shared/services/media.service";
|
||||
import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service";
|
||||
import { WIDGET_STICKER_PICKER } from "../../shared/models/widget";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "stickerpicker.component.html",
|
||||
@ -27,7 +28,9 @@ export class StickerpickerComponent implements OnInit {
|
||||
private media: MediaService,
|
||||
private scalarClient: ScalarClientApiService,
|
||||
private toaster: ToasterService,
|
||||
private window: Window) {
|
||||
private window: Window,
|
||||
public translate?: TranslateService) {
|
||||
this.translate = translate;
|
||||
this.isLoading = true;
|
||||
this.isUpdating = false;
|
||||
}
|
||||
@ -38,7 +41,7 @@ export class StickerpickerComponent implements OnInit {
|
||||
this.isLoading = false;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.toaster.pop("error", "Failed to load sticker packs");
|
||||
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
}
|
||||
|
||||
this.stickerApi.getConfig().then(config => {
|
||||
@ -55,12 +58,12 @@ export class StickerpickerComponent implements OnInit {
|
||||
this.packs.splice(0, 0, pack);
|
||||
this.packUrl = "";
|
||||
this.isImporting = false;
|
||||
this.toaster.pop("success", "Stickerpack added");
|
||||
this.translate.get('Stickerpack added').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
this.addWidget();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.isImporting = false;
|
||||
this.toaster.pop("error", "Error adding stickerpack");
|
||||
this.translate.get('Error adding stickerpack').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -73,14 +76,13 @@ export class StickerpickerComponent implements OnInit {
|
||||
this.isUpdating = true;
|
||||
this.stickerApi.togglePackSelection(pack.id, pack.isSelected).then(() => {
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("success", "Stickers updated");
|
||||
|
||||
this.translate.get('Stickers updated').subscribe((res: string) => {this.toaster.pop("success", res); });
|
||||
if (this.packs.filter(p => p.isSelected).length > 0) this.addWidget();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
pack.isSelected = !pack.isSelected; // revert change
|
||||
this.isUpdating = false;
|
||||
this.toaster.pop("error", "Error updating stickers");
|
||||
this.translate.get('Error updating stickers').subscribe((res: string) => {this.toaster.pop("error", res); });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div *ngIf="!widgetComponent.isLoading">
|
||||
<my-ibox [isCollapsible]="true" [defaultCollapsed]="widgetComponent.defaultExpandedWidgetId">
|
||||
<h5 class="my-ibox-title">
|
||||
<i class="far fa-plus-square"></i> Add {{ widgetComponent.defaultName }}
|
||||
<i class="far fa-plus-square"></i> {{ widgetComponent.defaultName | translate }} {{'Add' | translate}}
|
||||
</h5>
|
||||
<div class="my-ibox-content">
|
||||
<form (submit)="widgetComponent.addWidget()" novalidate name="addForm">
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
<div style="margin-top: 25px">
|
||||
<button type="submit" class="btn btn-sm btn-success" [disabled]="widgetComponent.isUpdating">
|
||||
<i class="fa fa-plus"></i> Add Widget
|
||||
<i class="fa fa-plus"></i> {{'Add Widget' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -32,11 +32,11 @@
|
||||
|
||||
<div style="margin-top: 25px">
|
||||
<button type="submit" class="btn btn-sm btn-primary" [disabled]="widgetComponent.isUpdating">
|
||||
<i class="far fa-save"></i> Save Widget
|
||||
<i class="far fa-save"></i>{{'Save Widget' | translate}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" [disabled]="widgetComponent.isUpdating"
|
||||
<button type="button" class="btn btn-sm ml-1 btn-outline-danger" [disabled]="widgetComponent.isUpdating"
|
||||
(click)="widgetComponent.removeWidget(widget)">
|
||||
<i class="far fa-trash-alt"></i> Remove Widget
|
||||
<i class="far fa-trash-alt"></i>{{'Remove Widget' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,14 +1,14 @@
|
||||
<my-widget-config [widgetComponent]="this">
|
||||
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||
<label class="label-block">
|
||||
Widget Name
|
||||
{{'Widget Name' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="{{ defaultName }}"
|
||||
placeholder="{{ defaultName | translate}}"
|
||||
[(ngModel)]="widget.dimension.newName" name="widget-name-{{widget.id}}"
|
||||
[disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Widget URL
|
||||
{{'Widget URL' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://matrix.org"
|
||||
[(ngModel)]="widget.dimension.newUrl" name="widget-url-{{widget.id}}"
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { WidgetComponent } from "../widget.component";
|
||||
import { WIDGET_CUSTOM } from "../../../shared/models/widget";
|
||||
import { Component } from "@angular/core";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "custom.widget.component.html",
|
||||
styleUrls: ["custom.widget.component.scss"],
|
||||
})
|
||||
export class CustomWidgetConfigComponent extends WidgetComponent {
|
||||
constructor() {
|
||||
super(WIDGET_CUSTOM, "Custom Widget", "generic");
|
||||
constructor(public translate: TranslateService) {
|
||||
super(WIDGET_CUSTOM, "Custom Widget", "generic", translate);
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
<my-widget-config [widgetComponent]="this">
|
||||
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||
<label class="label-block">
|
||||
Pad Name
|
||||
{{'Pad Name' | translate}}
|
||||
<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
|
||||
{{'Pad URL' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://scalar.vector.im/etherpad/p/MyCoolPadName"
|
||||
[(ngModel)]="widget.dimension.newUrl" name="widget-url-{{widget.id}}"
|
||||
|
@ -5,6 +5,7 @@ import { FE_EtherpadWidget } from "../../../shared/models/integration";
|
||||
import { SessionStorage } from "../../../shared/SessionStorage";
|
||||
import { NameService } from "../../../shared/services/name.service";
|
||||
import * as url from "url";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "etherpad.widget.component.html",
|
||||
@ -14,8 +15,8 @@ export class EtherpadWidgetConfigComponent extends WidgetComponent {
|
||||
|
||||
private etherpadWidget: FE_EtherpadWidget = <FE_EtherpadWidget>SessionStorage.editIntegration;
|
||||
|
||||
constructor(private nameService: NameService) {
|
||||
super(WIDGET_ETHERPAD, "Etherpad", "generic", "etherpad", "padName");
|
||||
constructor(private nameService: NameService, public translate: TranslateService) {
|
||||
super(WIDGET_ETHERPAD, "Notes", "generic", translate ,"etherpad", "padName");
|
||||
}
|
||||
|
||||
protected OnWidgetsDiscovered(widgets: EditableWidget[]): void {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<my-widget-config [widgetComponent]="this">
|
||||
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||
<label class="label-block">
|
||||
Shared Calendar ID
|
||||
{{'Shared Calendar ID' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="en.uk#holiday@group.v.calendar.google.com"
|
||||
[(ngModel)]="widget.dimension.newData.shareId" name="widget-url-{{widget.id}}"
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component";
|
||||
import { EditableWidget, WIDGET_GOOGLE_CALENDAR } from "../../../shared/models/widget";
|
||||
import { Component } from "@angular/core";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "gcal.widget.component.html",
|
||||
styleUrls: ["gcal.widget.component.scss"],
|
||||
})
|
||||
export class GoogleCalendarWidgetConfigComponent extends WidgetComponent {
|
||||
constructor() {
|
||||
super(WIDGET_GOOGLE_CALENDAR, "Google Calendar", DISABLE_AUTOMATIC_WRAPPING, "googleCalendar");
|
||||
constructor(public translate: TranslateService) {
|
||||
super(WIDGET_GOOGLE_CALENDAR, "Google Calendar", DISABLE_AUTOMATIC_WRAPPING, translate , "googleCalendar");
|
||||
}
|
||||
|
||||
protected OnNewWidgetPrepared(widget: EditableWidget) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<my-widget-config [widgetComponent]="this">
|
||||
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||
<label class="label-block">
|
||||
Document URL
|
||||
{{'Document URL' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://docs.google.com/document/d/1V0olL42WJ84LNYn0kFBJaPmlRxQ4Trx97a5wfVMuJC8/edit"
|
||||
[(ngModel)]="widget.dimension.newUrl" name="widget-url-{{widget.id}}"
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { WidgetComponent } from "../widget.component";
|
||||
import { WIDGET_GOOGLE_DOCS } from "../../../shared/models/widget";
|
||||
import { Component } from "@angular/core";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "gdoc.widget.component.html",
|
||||
styleUrls: ["gdoc.widget.component.scss"],
|
||||
})
|
||||
export class GoogleDocsWidgetConfigComponent extends WidgetComponent {
|
||||
constructor() {
|
||||
super(WIDGET_GOOGLE_DOCS, "Google Doc", "generic", "googleDocs");
|
||||
constructor(public translate: TranslateService) {
|
||||
super(WIDGET_GOOGLE_DOCS, "Google Doc", "generic", translate , "googleDocs");
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
<my-widget-config [widgetComponent]="this">
|
||||
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||
<label class="label-block">
|
||||
Grafana URL
|
||||
<span class="text-muted">To get a URL, go to Grafana and click "share" on a graph.</span>
|
||||
{{'Grafana URL' | translate}}
|
||||
<span class="text-muted">{{'To get a URL, go to Grafana and click \'share\' on a graph.' | translate}}</span>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="https://example.com/grafana/dashboard/db/example?orgId=1&panelId=1&fullscreen"
|
||||
[(ngModel)]="widget.dimension.newData.url" name="widget-url-{{widget.id}}"
|
||||
[disabled]="isUpdating"/>
|
||||
</label>
|
||||
<label class="label-block">
|
||||
Widget Name
|
||||
{{'Widget Name' | translate}}
|
||||
<input type="text" class="form-control"
|
||||
placeholder="{{ defaultName }}"
|
||||
[(ngModel)]="widget.dimension.newName" name="widget-name-{{widget.id}}"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user