ESLint config, fix easy eslint errors

This commit is contained in:
Tony Stipanic 2021-09-02 01:01:01 +02:00
parent 87d15d8e01
commit f06ead08d8
No known key found for this signature in database
GPG Key ID: 3026BCCB6C9CC6BD
81 changed files with 1625 additions and 1115 deletions

View File

@ -14,6 +14,9 @@
],
"createDefaultProgram": true
},
"plugins": [
"@typescript-eslint"
],
"extends": [
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
@ -34,7 +37,74 @@
"prefix": "app",
"style": "kebab-case"
}
]
],
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/indent": "error",
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/member-ordering": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/quotes": "off",
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "error",
"brace-style": [
"error",
"1tbs"
],
"curly": "off",
"eol-last": "off",
"eqeqeq": [
"error",
"always"
],
"guard-for-in": "off",
"id-blacklist": "off",
"id-match": "off",
"max-len": "off",
"no-bitwise": "off",
"no-caller": "error",
"no-console": "off",
"no-debugger": "error",
"no-empty": "off",
"no-eval": "error",
"no-fallthrough": "error",
"no-new-wrappers": "error",
"no-redeclare": "error",
"no-shadow": [
"error",
{
"hoist": "all"
}
],
"no-trailing-spaces": "error",
"no-underscore-dangle": "off",
"no-unused-labels": "error",
"no-var": "error",
"radix": "error"
}
},
{

View File

@ -9,13 +9,12 @@
"start:web": "ng serve --configuration development --port 8082",
"start:app": "npm run-script build && node build/app/index.js",
"start:apponly": "ts-node-dev --respawn --transpile-only --project tsconfig.backend.json ./src/index.ts",
"node:start:apponly": "npm run-script build:app && node build/app/index.js",
"build": "npm run-script build:web && npm run-script build:app",
"build:web": "rimraf build/web && ng build --configuration production",
"build:app": "rimraf build/app && tsc -p tsconfig.backend.json",
"lint": "npm run-script lint:app && npm run-script lint:web",
"lint:app": "tslint --project ./tsconfig.app.json",
"lint:web": "tslint --project ./tsconfig.json",
"lint": "eslint .",
"lint:app": "eslint src",
"lint:web": "eslint web",
"i18n": "npm run-script i18n:init && npm run-script i18n:extract",
"i18n:init": "ngx-translate-extract --input ./web --output ./web/public/assets/i18n/template.json --key-as-default-value --replace --format json",
"i18n:extract": "ngx-translate-extract --input ./web --output ./web/public/assets/i18n/en.json --clean --format json"

View File

@ -111,7 +111,7 @@ export class DimensionBigBlueButtonService {
@Path("join")
public async join(
@QueryParam("greenlightUrl") greenlightURL: string,
@QueryParam("fullName") fullName: string,
@QueryParam("fullName") fullName: string,
): Promise<BigBlueButtonJoinResponse|ApiError> {
// Parse the greenlight url and retrieve the path
const greenlightMeetingID = new URL(greenlightURL).pathname;
@ -139,7 +139,7 @@ export class DimensionBigBlueButtonService {
// than following it ourselves
// Add authenticity token and full name to the query parameters
let queryParams = {authenticity_token: authenticityToken};
const queryParams = {authenticity_token: authenticityToken};
queryParams[`${greenlightMeetingID}[join_name]`] = fullName;
// Request the updated URL
@ -239,7 +239,7 @@ export class DimensionBigBlueButtonService {
}
},
"layout": {
"container": "top",
"container": "top",
"index": 0,
"width": 65,
"height": 50,
@ -259,7 +259,7 @@ export class DimensionBigBlueButtonService {
getJoinUrlRequest: BigBlueButtonGetJoinUrlRequest,
): Promise<BigBlueButtonCreateAndJoinMeetingResponse|ApiError> {
// Check if the meeting exists and is running. If not, return an error for each case
let getMeetingInfoParameters = {
const getMeetingInfoParameters = {
meetingID: getJoinUrlRequest.meetingId,
}
@ -290,7 +290,7 @@ export class DimensionBigBlueButtonService {
fullName = getJoinUrlRequest.userId;
}
let joinQueryParameters = {
const joinQueryParameters = {
meetingID: getJoinUrlRequest.meetingId,
password: getJoinUrlRequest.meetingPassword,
fullName: fullName,

View File

@ -88,7 +88,7 @@ class _DimensionStore {
// Adjust the migration from the new signature to the v2 signature, making easier to upgrade to v3
const migration = require(path)
return { name, up: async () => migration.default.up(context), down: async () => migration.default.down(context) }
}
}
},
context: this.sequelize.getQueryInterface(),
storage: new SequelizeStorage({ sequelize: this.sequelize }),

View File

@ -1,30 +1,30 @@
import { QueryInterface } from "sequelize";
export default {
up: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_widgets SET avatarUrl = REPLACE(avatarUrl, '/img/', '/assets/img/')"
)
)
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_bridges SET avatarUrl = REPLACE(avatarUrl, '/img/', '/assets/img/')"
)
);
},
down: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_widgets SET avatarUrl = REPLACE(avatarUrl, '/assets/img/', '/img/')"
)
)
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_bridges SET avatarUrl = REPLACE(avatarUrl, '/assets/img/', '/img/')"
)
);
},
up: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_widgets SET avatarUrl = REPLACE(avatarUrl, '/img/', '/assets/img/')"
)
)
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_bridges SET avatarUrl = REPLACE(avatarUrl, '/img/', '/assets/img/')"
)
);
},
down: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_widgets SET avatarUrl = REPLACE(avatarUrl, '/assets/img/', '/img/')"
)
)
.then(() =>
queryInterface.sequelize.query(
"UPDATE dimension_bridges SET avatarUrl = REPLACE(avatarUrl, '/assets/img/', '/img/')"
)
);
},
};

View File

@ -9,12 +9,12 @@ import User from "./db/models/User";
import { ILoggedInUser } from "./api/security/MatrixSecurity";
declare global {
namespace Express {
interface User extends ILoggedInUser {
userId: string;
token: string;
namespace Express {
interface User extends ILoggedInUser {
userId: string;
token: string;
}
}
}
}
LogService.configure(config.logging);
@ -30,8 +30,8 @@ BotSdk.LogService.setLogger({
});
async function startup() {
const schemas = await DimensionStore.updateSchema();
LogService.info("DimensionStore", schemas);
const schemas = await DimensionStore.updateSchema();
LogService.info("DimensionStore", schemas);
const webserver = new Webserver();
await webserver.start();

View File

@ -12,8 +12,8 @@ try {
try {
gitHash = child_process
.execSync('git rev-parse --short HEAD')
.toString().trim()
.execSync('git rev-parse --short HEAD')
.toString().trim()
} catch (error) {
// The log service isn't set up by the time we require this file
console.error("version", error);

View File

@ -14,7 +14,7 @@ export class AdminBridgesComponent implements OnInit {
public bridges: FE_Bridge<any>[];
constructor(private adminIntegrations: AdminIntegrationsApiService,
private toaster: ToasterService, public translate: TranslateService) {
private toaster: ToasterService, public translate: TranslateService) {
this.translate = translate;
}
@ -24,7 +24,9 @@ export class AdminBridgesComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load bridges').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -19,21 +19,25 @@ export class AdminIrcBridgeAddSelfhostedComponent {
public provisionUrl: string;
constructor(public modal: NgbActiveModal,
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
public add() {
this.isSaving = true;
this.ircApi.newSelfhosted(this.provisionUrl).then(() => {
this.translate.get('IRC Bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('IRC Bridge added').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to create IRC bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to create IRC bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -25,10 +25,10 @@ export class AdminIrcBridgeComponent implements OnInit {
private upstreams: FE_Upstream[];
constructor(private upstreamApi: AdminUpstreamApiService,
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -50,7 +50,9 @@ export class AdminIrcBridgeComponent implements OnInit {
}
} catch (err) {
console.error(err);
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading bridges').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
}
@ -69,13 +71,17 @@ export class AdminIrcBridgeComponent implements OnInit {
const createBridge = (upstream: FE_Upstream) => {
return this.ircApi.newFromUpstream(upstream).then(bridge => {
this.configurations.push(bridge);
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.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.translate.get('Error adding matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
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");
@ -87,7 +93,9 @@ export class AdminIrcBridgeComponent implements OnInit {
createBridge(upstream);
}).catch(err => {
console.error(err);
this.translate.get('Error creating matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating matrix.org\'s IRC Bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
} else createBridge(vectorUpstreams[0]);
}
@ -102,7 +110,9 @@ export class AdminIrcBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
})
}
@ -117,7 +127,9 @@ export class AdminIrcBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
})
const selfhostedInstance = selfhostedRef.componentInstance as IrcNetworksDialogContext;

View File

@ -28,9 +28,9 @@ export class AdminIrcBridgeNetworksComponent {
public networks: LocalNetwork[];
constructor(public modal: NgbActiveModal,
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private ircApi: AdminIrcApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
const networkIds = Object.keys(this.bridge.availableNetworks);
this.networks = networkIds.map(i => {
@ -51,13 +51,17 @@ export class AdminIrcBridgeNetworksComponent {
this.isUpdating = true;
this.ircApi.setNetworkEnabled(this.bridge.id, network.id, network.isEnabled).then(() => {
this.isUpdating = false;
this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Network " + (network.isEnabled ? res[0] : res[1])); });
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.translate.get('Failed to update network').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to update network').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -22,9 +22,9 @@ export class AdminSlackBridgeManageSelfhostedComponent {
public isAdding = true;
constructor(public modal: NgbActiveModal,
private slackApi: AdminSlackApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private slackApi: AdminSlackApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -32,12 +32,16 @@ export class AdminSlackBridgeManageSelfhostedComponent {
this.isSaving = true;
if (this.isAdding) {
this.slackApi.newSelfhosted(this.provisionUrl).then(() => {
this.translate.get('Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Slack bridge added').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to create Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
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(() => {
@ -46,7 +50,9 @@ export class AdminSlackBridgeManageSelfhostedComponent {
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to update Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to update Slack bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -24,10 +24,10 @@ export class AdminSlackBridgeComponent implements OnInit {
private upstreams: FE_Upstream[];
constructor(private slackApi: AdminSlackApiService,
private upstreamApi: AdminUpstreamApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private upstreamApi: AdminUpstreamApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -41,7 +41,9 @@ export class AdminSlackBridgeComponent implements OnInit {
this.configurations = await this.slackApi.getBridges();
} catch (err) {
console.error(err);
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading bridges').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
}
@ -51,12 +53,16 @@ export class AdminSlackBridgeComponent implements OnInit {
const createBridge = (upstream: FE_Upstream) => {
return this.slackApi.newFromUpstream(upstream).then(bridge => {
this.configurations.push(bridge);
this.translate.get('matrix.org\'s Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error adding matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error adding matrix.org\'s Slack Bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
};
@ -69,7 +75,9 @@ export class AdminSlackBridgeComponent implements OnInit {
createBridge(upstream);
}).catch(err => {
console.error(err);
this.translate.get('Error creating matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating matrix.org\'s Slack Bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
} else createBridge(vectorUpstreams[0]);
}
@ -84,7 +92,9 @@ export class AdminSlackBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedSlackBridgeDialogContext;
@ -101,7 +111,9 @@ export class AdminSlackBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedSlackBridgeDialogContext;

View File

@ -28,9 +28,9 @@ export class AdminTelegramBridgeManageSelfhostedComponent {
isAdding = true;
constructor(public modal: NgbActiveModal,
private telegramApi: AdminTelegramApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private telegramApi: AdminTelegramApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -42,21 +42,29 @@ export class AdminTelegramBridgeManageSelfhostedComponent {
};
if (this.isAdding) {
this.telegramApi.newSelfhosted(this.provisionUrl, this.sharedSecret, options).then(() => {
this.translate.get('Telegram bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Telegram bridge added').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to create Telegram bridge').subscribe((res: string) => { this.toaster.pop("error", res); });
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.translate.get('Telegram bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Telegram bridge updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to update Telegram bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to update Telegram bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -20,9 +20,9 @@ export class AdminTelegramBridgeComponent implements OnInit {
public configurations: FE_TelegramBridge[] = [];
constructor(private telegramApi: AdminTelegramApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -35,7 +35,9 @@ export class AdminTelegramBridgeComponent implements OnInit {
this.configurations = await this.telegramApi.getBridges();
} catch (err) {
console.error(err);
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading bridges').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
}
@ -49,7 +51,9 @@ export class AdminTelegramBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
})
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedTelegramBridgeDialogContext;
@ -76,7 +80,9 @@ export class AdminTelegramBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
})
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedTelegramBridgeDialogContext;

View File

@ -28,9 +28,9 @@ export class AdminWebhooksBridgeManageSelfhostedComponent {
public isAdding = true;
constructor(public modal: NgbActiveModal,
private webhooksApi: AdminWebhooksApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private webhooksApi: AdminWebhooksApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -38,21 +38,29 @@ export class AdminWebhooksBridgeManageSelfhostedComponent {
this.isSaving = true;
if (this.isAdding) {
this.webhooksApi.newSelfhosted(this.provisionUrl, this.sharedSecret).then(() => {
this.translate.get('Webhook bridge added').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Webhook bridge added').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to create Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get('Webhook bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Webhook bridge updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Failed to update Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to update Webhook bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -20,9 +20,9 @@ export class AdminWebhooksBridgeComponent implements OnInit {
public configurations: FE_WebhooksBridge[] = [];
constructor(private webhooksApi: AdminWebhooksApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -35,7 +35,9 @@ export class AdminWebhooksBridgeComponent implements OnInit {
this.configurations = await this.webhooksApi.getBridges();
} catch (err) {
console.error(err);
this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading bridges').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
}
@ -49,7 +51,9 @@ export class AdminWebhooksBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedWebhooksBridgeDialogContext;
@ -69,7 +73,9 @@ export class AdminWebhooksBridgeComponent implements OnInit {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
const selfhostedInstance = selfhostedRef.componentInstance as ManageSelfhostedWebhooksBridgeDialogContext;

View File

@ -23,9 +23,9 @@ export class AdminAddCustomBotComponent {
private lastProfile: FE_UserProfile;
constructor(public modal: NgbActiveModal,
private botApi: AdminCustomSimpleBotsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private botApi: AdminCustomSimpleBotsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -46,23 +46,33 @@ export class AdminAddCustomBotComponent {
public add() {
if (!this.bot.name) {
this.translate.get('Please enter a name for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter a name for the bot').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
if (!this.bot.avatarUrl) {
this.translate.get('Please enter an avatar URL for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
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.translate.get('Please enter a user ID for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
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.translate.get('Please enter a description for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter a description for the bot').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
if (!this.bot.accessToken) {
this.translate.get('Please enter an access token for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter an access token for the bot').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
@ -86,12 +96,16 @@ export class AdminAddCustomBotComponent {
}
promise.then(() => {
this.translate.get('Bot updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Bot updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(error => {
this.isSaving = false;
console.error(error);
this.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating bot').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -17,14 +17,16 @@ export class AdminCustomBotsComponent {
public isUpdating = false;
constructor(private botApi: AdminCustomSimpleBotsApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
this.reload().then(() => this.isLoading = false).catch(error => {
console.error(error);
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -45,7 +47,9 @@ export class AdminCustomBotsComponent {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
}
@ -60,7 +64,9 @@ export class AdminCustomBotsComponent {
this.reload()
} catch (err) {
console.error(err);
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
const selfhostedInstance = selfhostedRef.componentInstance as AddCustomBotDialogContext;
@ -73,11 +79,15 @@ export class AdminCustomBotsComponent {
bot.isEnabled = !bot.isEnabled;
this.botApi.updateBot(bot.id, bot).then(() => {
this.isUpdating = false;
this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Bot " + (bot.isEnabled ? res[0] : res[1])); });
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.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating bot').subscribe((res: string) => {
this.toaster.pop("error", res);
});
})
}
}

View File

@ -18,9 +18,9 @@ export class AdminHomeComponent {
public config: FE_DimensionConfig;
constructor(private adminApi: AdminApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
adminApi.getConfig().then(config => {
this.config = config;
@ -35,11 +35,15 @@ export class AdminHomeComponent {
selfhostedRef.result.then(async () => {
try {
await this.adminApi.logoutAll();
this.translate.get('Everyone has been logged out').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error logging everyone out').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error logging everyone out').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
}

View File

@ -22,12 +22,12 @@ export class AdminAddSelfhostedNebComponent {
public adminUrl = "http://localhost:4050";
constructor(private asApi: AdminAppserviceApiService,
private nebApi: AdminNebApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
private nebApi: AdminNebApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -36,7 +36,9 @@ export class AdminAddSelfhostedNebComponent {
this.asApi.createAppservice(this.userPrefix).then(appservice => {
return this.nebApi.newAppserviceConfiguration(this.adminUrl, appservice);
}).then(neb => {
this.translate.get('New go-neb created').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('New go-neb created').subscribe((res: string) => {
this.toaster.pop("success", res);
});
const selfhostedRef = this.modal.open(AdminNebAppserviceConfigComponent, {
backdrop: 'static',
@ -48,7 +50,9 @@ export class AdminAddSelfhostedNebComponent {
}).catch(err => {
console.error(err);
this.isSaving = false;
this.translate.get('Error creating appservice').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating appservice').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -20,16 +20,18 @@ export class AdminNebAppserviceConfigComponent {
public appservice: FE_Appservice;
constructor(public modal: NgbActiveModal,
private adminAppserviceApi: AdminAppserviceApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminAppserviceApi: AdminAppserviceApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
this.adminAppserviceApi.getAppservice(this.neb.appserviceId).then(appservice => {
this.appservice = appservice;
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Could not load appservice configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Could not load appservice configuration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -50,10 +52,14 @@ export class AdminNebAppserviceConfigComponent {
public test() {
this.adminAppserviceApi.test(this.neb.appserviceId).then(() => {
this.translate.get('The appservice appears to be correctly set up').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('The appservice is not correctly set up').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('The appservice is not correctly set up').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -24,9 +24,9 @@ export class AdminNebGiphyConfigComponent implements OnInit {
public neb: FE_NebConfiguration;
constructor(public modal: NgbActiveModal,
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -36,19 +36,25 @@ export class AdminNebGiphyConfigComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Configuration updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating integration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -24,9 +24,9 @@ export class AdminNebGoogleConfigComponent implements OnInit {
public neb: FE_NebConfiguration;
constructor(public modal: NgbActiveModal,
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -36,19 +36,25 @@ export class AdminNebGoogleConfigComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Configuration updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating integration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -23,9 +23,9 @@ export class AdminNebGuggyConfigComponent implements OnInit {
public neb: FE_NebConfiguration;
constructor(public modal: NgbActiveModal,
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -35,19 +35,25 @@ export class AdminNebGuggyConfigComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Configuration updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating integration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -24,9 +24,9 @@ export class AdminNebImgurConfigComponent implements OnInit {
public neb: FE_NebConfiguration;
constructor(public modal: NgbActiveModal,
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminNebApi: AdminNebApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -36,19 +36,25 @@ export class AdminNebImgurConfigComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Configuration updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating integration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -28,10 +28,10 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
private overlappingTypes: string[] = [];
constructor(private nebApi: AdminNebApiService,
private route: ActivatedRoute,
private modal: NgbModal,
private toaster: ToasterService,
public translate: TranslateService) {
private route: ActivatedRoute,
private modal: NgbModal,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -60,12 +60,16 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
try {
await this.nebApi.toggleIntegration(this.nebConfig.id, bot.type, bot.isEnabled);
this.isUpdating = false;
this.translate.get('Integration updated').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating integration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
return;
}
@ -78,7 +82,9 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
await this.nebApi.setIntegrationConfiguration(this.nebConfig.id, bot.type, {});
} catch (err) {
console.error(err);
this.translate.get(['Failed to configure the integration', 'Manual troubleshooting may be requred' ]).subscribe((res: string) => {this.toaster.pop("warning", res[0], res[1]); });
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;
}
}
@ -122,7 +128,9 @@ export class AdminEditNebComponent implements OnInit, OnDestroy {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Could not get go-neb configuration').subscribe((res: string) => {this.toaster.pop('error', res); });
this.translate.get('Could not get go-neb configuration').subscribe((res: string) => {
this.toaster.pop('error', res);
});
});
}
}

View File

@ -26,18 +26,20 @@ export class AdminNebComponent {
public configurations: FE_NebConfiguration[];
constructor(private nebApi: AdminNebApiService,
private upstreamApi: AdminUpstreamApiService,
private appserviceApi: AdminAppserviceApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
private upstreamApi: AdminUpstreamApiService,
private appserviceApi: AdminAppserviceApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
this.reload().then(() => this.isLoading = false).catch(error => {
console.error(error);
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -100,13 +102,17 @@ export class AdminNebComponent {
const createNeb = (upstream: FE_Upstream) => {
return this.nebApi.newUpstreamConfiguration(upstream).then(neb => {
this.configurations.push(neb);
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.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.translate.get('Error adding matrix.org\'s go-neb').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error adding matrix.org\'s go-neb').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
};
@ -119,7 +125,9 @@ export class AdminNebComponent {
createNeb(upstream);
}).catch(err => {
console.error(err);
this.translate.get('Error creating matrix.org go-neb').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating matrix.org go-neb').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
} else createNeb(vectorUpstreams[0]);
}

View File

@ -19,9 +19,9 @@ export class AdminStickerPacksComponent implements OnInit {
public isImporting = false;
constructor(private adminStickers: AdminStickersApiService,
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
@ -31,7 +31,9 @@ export class AdminStickerPacksComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -40,12 +42,16 @@ export class AdminStickerPacksComponent implements OnInit {
this.isUpdating = true;
this.adminStickers.togglePack(pack.id, pack.isEnabled).then(() => {
this.isUpdating = false;
this.translate.get('Sticker pack updated').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error updating sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating sticker pack').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -62,11 +68,15 @@ export class AdminStickerPacksComponent implements OnInit {
this.isImporting = false;
this.tgUrl = "";
this.packs.push(pack);
this.translate.get('Telegram sticker pack imported').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Telegram sticker pack imported').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(err => {
console.error(err);
this.isImporting = false;
this.translate.get('Error importing sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error importing sticker pack').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}

View File

@ -63,16 +63,16 @@ export class AdminNewEditTermsComponent implements OnInit {
}
constructor(private adminTerms: AdminTermsApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
private modal: NgbModal,
public translate: TranslateService) {
this.translate = translate;
}
public ngOnInit() {
let params = this.activatedRoute.snapshot.params;
const params = this.activatedRoute.snapshot.params;
this.shortcode = params.shortcode;
this.isEditing = !!this.shortcode;
@ -96,7 +96,9 @@ export class AdminNewEditTermsComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load policy').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load policy').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
} else {
this.adminTerms.getAllPolicies().then(policies => {
@ -104,7 +106,9 @@ export class AdminNewEditTermsComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load policies').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}
@ -135,11 +139,15 @@ export class AdminNewEditTermsComponent implements OnInit {
});
await this.adminTerms.publishDraft(this.shortcode, val);
this.translate.get('Policy published').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error publishing policy').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error publishing policy').subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isUpdating = false;
}
});
@ -148,11 +156,15 @@ export class AdminNewEditTermsComponent implements OnInit {
public async create() {
for (const languageCode in this.languages) {
if (this.languages[languageCode].name.trim().length <= 0) {
this.translate.get('Please enter a name for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); });
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.translate.get('Please enter text for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter text for all policies').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
}
@ -166,11 +178,15 @@ export class AdminNewEditTermsComponent implements OnInit {
text: this.languages['en'].text,
url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/draft`,
});
this.translate.get('Draft saved').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error saving policy').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error saving policy').subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isUpdating = false;
}
return;
@ -189,11 +205,15 @@ export class AdminNewEditTermsComponent implements OnInit {
text: this.languages['en'].text,
url: `${window.location.origin}/widgets/terms/${shortcode}/en/draft`,
});
this.translate.get('Draft created').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error creating document').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating document').subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isUpdating = false;
}
}

View File

@ -19,7 +19,9 @@ export class AdminTermsNewEditPublishDialogComponent {
public publish() {
if (!this.version || !this.version.trim()) {
this.translate.get('Please enter a version number').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter a version number').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
this.modal.close(this.version);

View File

@ -26,7 +26,7 @@
<td class="text-center">
<span class="editButton" [routerLink]="['edit', policy.shortcode]" title="edit draft"
*ngIf="policy.version == 'draft'">
*ngIf="policy.version === 'draft'">
<i class="fa fa-pencil-alt"></i>
</span>
</td>

View File

@ -18,10 +18,10 @@ export class AdminTermsComponent implements OnInit {
public policies: FE_TermsEditable[];
constructor(private adminTerms: AdminTermsApiService,
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
public translate: TranslateService) {
private toaster: ToasterService,
private router: Router,
private activatedRoute: ActivatedRoute,
public translate: TranslateService) {
this.translate = translate;
}
@ -34,7 +34,9 @@ export class AdminTermsComponent implements OnInit {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load policies').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}

View File

@ -16,9 +16,9 @@ export class AdminWidgetEtherpadConfigComponent implements OnInit {
private originalWidget = <FE_EtherpadWidget>{};
constructor(public modal: NgbActiveModal,
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
@ -31,12 +31,16 @@ export class AdminWidgetEtherpadConfigComponent implements OnInit {
this.isUpdating = true;
this.adminIntegrationsApi.setIntegrationOptions(this.widget.category, this.widget.type, this.widget.options).then(() => {
this.originalWidget.options = this.widget.options;
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Widget updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating widget').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -16,10 +16,10 @@ export class AdminWidgetJitsiConfigComponent implements OnInit {
private originalWidget = <FE_JitsiWidget>{};
constructor(public modal: NgbActiveModal,
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}
ngOnInit() {
@ -34,12 +34,16 @@ export class AdminWidgetJitsiConfigComponent implements OnInit {
this.isUpdating = true;
this.adminIntegrationsApi.setIntegrationOptions(this.widget.category, this.widget.type, this.widget.options).then(() => {
this.originalWidget.options = this.widget.options;
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Widget updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.modal.close();
}).catch(err => {
this.isUpdating = false;
console.error(err);
this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating widget').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}

View File

@ -16,9 +16,9 @@ export class AdminWidgetWhiteboardConfigComponent implements OnInit {
private originalWidget: FE_WhiteBoardWidget;
constructor(public modal: NgbActiveModal,
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
private adminIntegrationsApi: AdminIntegrationsApiService,
private toaster: ToasterService,
public translate: TranslateService) {
this.translate = translate;
}

View File

@ -29,7 +29,9 @@ export class AdminWidgetsComponent {
this.widgets = widgets;
}).catch(err => {
console.error(err);
this.translate.get('Failed to load widgets').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load widgets').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -38,12 +40,16 @@ export class AdminWidgetsComponent {
this.isUpdating = true;
this.adminIntegrationsApi.toggleIntegration(widget.category, widget.type, widget.isEnabled).then(() => {
this.isUpdating = false;
this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating widget').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -56,7 +62,9 @@ export class AdminWidgetsComponent {
if (!component) {
console.error("No known dialog component for " + widget.type);
this.translate.get('Error opening configuration page').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error opening configuration page').subscribe((res: string) => {
this.toaster.pop("error", res);
});
return;
}

View File

@ -4,19 +4,18 @@ import { TranslateService } from "@ngx-translate/core";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "my-app", // <my-app></my-app>
selector: "app-app", // <my-app></my-app>
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent {
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');
translate.addLangs(["en", "de"]);
translate.setDefaultLang("de");
if (navigator.language === "de") {
translate.use("de");
} else {
translate.use("en");
}
}
}

View File

@ -122,7 +122,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
return new TranslateHttpLoader(http);
}
@NgModule({
@ -286,27 +286,27 @@ export function HttpLoaderFactory(http: HttpClient) {
]
})
export class AppModule {
constructor(public appRef: ApplicationRef, injector: Injector) {
ServiceLocator.injector = injector;
}
constructor(public appRef: ApplicationRef, injector: Injector) {
ServiceLocator.injector = injector;
}
hmrOnInit(store) {
console.log("HMR store", store);
}
hmrOnInit(store) {
console.log("HMR store", store);
}
hmrOnDestroy(store) {
let cmpLocation = this.appRef.components.map(
(cmp) => cmp.location.nativeElement
);
// recreate elements
store.disposeOldHosts = createNewHosts(cmpLocation);
// remove styles
removeNgStyles();
}
hmrOnDestroy(store) {
const cmpLocation = this.appRef.components.map(
(cmp) => cmp.location.nativeElement
);
// recreate elements
store.disposeOldHosts = createNewHosts(cmpLocation);
// remove styles
removeNgStyles();
}
hmrAfterDestroy(store) {
hmrAfterDestroy(store) {
// display new elements
store.disposeOldHosts();
delete store.disposeOldHosts;
}
store.disposeOldHosts();
delete store.disposeOldHosts;
}
}

View File

@ -52,19 +52,25 @@ export class BridgeComponent<T> implements OnInit, OnDestroy {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get("Error updating configuration").subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isUpdating = false;
});
}

View File

@ -2,15 +2,14 @@ import { Component, ContentChild, Input, TemplateRef } from "@angular/core";
import { BridgeComponent } from "../bridge.component";
@Component({
selector: "my-bridge-config",
selector: "app-bridge-config",
templateUrl: "config-screen.bridge.component.html",
styleUrls: ["config-screen.bridge.component.scss"],
})
export class ConfigScreenBridgeComponent {
@Input() bridgeComponent: BridgeComponent<any>;
@ContentChild(TemplateRef, {static: false}) bridgeParamsTemplate: TemplateRef<any>;
@ContentChild(TemplateRef, { static: false })
bridgeParamsTemplate: TemplateRef<any>;
constructor() {
}
}
constructor() {}
}

View File

@ -57,7 +57,9 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
public loadOps() {
if (!this.channel.trim()) {
this.translate.get('Please enter a channel name').subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get('Please enter a channel name').subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
@ -70,7 +72,9 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
}).catch(err => {
console.error(err);
this.loadingOps = false;
this.translate.get('Error loading channel operators').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error loading channel operators').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -88,7 +92,9 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
} catch (err) {
console.error(err);
this.requestingBridge = false;
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]); });
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;
}
@ -101,11 +107,15 @@ export class IrcBridgeConfigComponent extends BridgeComponent<IrcConfig> {
pending: true,
});
this.resetForm();
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]); });
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.translate.get('Failed to request a link').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to request a link').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -135,10 +145,14 @@ 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.translate.get('Link removed').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Link removed').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(err => {
console.error(err);
this.translate.get('Failed to remove link').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to remove link').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -60,7 +60,9 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
this.loadingTeams = false;
}).catch(error2 => {
console.error(error2);
this.translate.get('Error getting Slack authorization information').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error getting Slack authorization information').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
this.timerId = setInterval(() => {
@ -69,7 +71,9 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
}
} else {
console.error(error);
this.translate.get('Error getting teams').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error getting teams').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
});
}
@ -86,7 +90,9 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
this.isBusy = false;
}).catch(error => {
console.error(error);
this.translate.get('Error getting channels for team').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error getting channels for team').subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isBusy = false;
});
}
@ -100,7 +106,9 @@ 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.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error inviting bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
return;
}
}
@ -108,11 +116,15 @@ 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.translate.get('Bridge requested').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Bridge requested').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(error => {
this.isBusy = false;
console.error(error);
this.translate.get('Error requesting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error requesting bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -121,11 +133,15 @@ export class SlackBridgeConfigComponent extends BridgeComponent<SlackConfig> imp
this.slack.unbridgeRoom(this.roomId).then(() => {
this.bridge.config.link = null;
this.isBusy = false;
this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Bridge removed').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(error => {
this.isBusy = false;
console.error(error);
this.translate.get('Error removing bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error removing bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -106,7 +106,9 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
this.bridge.config.portalInfo = loadedPortalInfo;
this.bridge.config.linked = [loadedPortalInfo.chatId];
this.isUpdating = false;
this.translate.get('Bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Bridge updated').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(error => {
this.isUpdating = false;
console.error(error);
@ -118,8 +120,10 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
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); });
}
this.translate.get(message).subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -129,7 +133,9 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
this.bridge.config.portalInfo = portalInfo;
this.bridge.config.linked = [];
this.isUpdating = false;
this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Bridge removed').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(error => {
this.isUpdating = false;
console.error(error);
@ -139,7 +145,9 @@ export class TelegramBridgeConfigComponent extends BridgeComponent<TelegramConfi
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.translate.get(message).subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get(message).subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -32,7 +32,9 @@ 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.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error inviting bridge').subscribe((res: string) => {
this.toaster.pop("error", res);
});
return;
}
}
@ -41,11 +43,15 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent<WebhooksConfi
this.newConfig.webhooks.push(hook);
this.isBusy = false;
this.webhookName = "";
this.translate.get('Webhook created').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Webhook created').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(err => {
console.error(err);
this.isBusy = false;
this.translate.get('Error creating webhook').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error creating webhook').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -55,11 +61,15 @@ 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.translate.get('Webhook deleted').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Webhook deleted').subscribe((res: string) => {
this.toaster.pop("success", res);
});
}).catch(err => {
console.error(err);
this.isBusy = false;
this.translate.get('Error deleting webhook').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error deleting webhook').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -53,20 +53,26 @@ export class ComplexBotComponent<T> implements OnInit, OnDestroy {
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
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.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get("Error updating configuration").subscribe((res: string) => {
this.toaster.pop("error", res);
});
this.isUpdating = false;
});
}

View File

@ -2,15 +2,14 @@ import { ComplexBotComponent } from "../complex-bot.component";
import { Component, ContentChild, Input, TemplateRef } from "@angular/core";
@Component({
selector: "my-complex-bot-config",
selector: "app-complex-bot-config",
templateUrl: "config-screen.complex-bot.component.html",
styleUrls: ["config-screen.complex-bot.component.scss"],
})
export class ConfigScreenComplexBotComponent {
@Input() botComponent: ComplexBotComponent<any>;
@ContentChild(TemplateRef, {static: false}) botParamsTemplate: TemplateRef<any>;
@ContentChild(TemplateRef, { static: false })
botParamsTemplate: TemplateRef<any>;
constructor() {
}
}
constructor() {}
}

View File

@ -32,7 +32,9 @@ export class RssComplexBotConfigComponent extends ComplexBotComponent<RssConfig>
public addFeed(): void {
if (!this.newFeedUrl.trim()) {
this.translate.get('Please enter a feed URL').subscribe((res: string) => {this.toaster.pop('warning', res); });
this.translate.get('Please enter a feed URL').subscribe((res: string) => {
this.toaster.pop('warning', res);
});
return;
}

View File

@ -52,7 +52,9 @@ export class TravisCiComplexBotConfigComponent extends ComplexBotComponent<Travi
public addRepo(): void {
if (!this.newRepoKey.trim()) {
this.translate.get('Please enter a repository').subscribe((res: string) => {this.toaster.pop('warning', res); });
this.translate.get('Please enter a repository').subscribe((res: string) => {
this.toaster.pop('warning', res);
});
return;
}

View File

@ -22,10 +22,10 @@ export class ConfigSimpleBotComponent implements OnInit {
private roomId: string;
constructor(public modal: NgbActiveModal,
private toaster: ToasterService,
private scalar: ScalarClientApiService,
private integrationsApi: IntegrationsApiService,
public translate: TranslateService) {
private toaster: ToasterService,
private scalar: ScalarClientApiService,
private integrationsApi: IntegrationsApiService,
public translate: TranslateService) {
this.translate = translate;
}
@ -44,9 +44,13 @@ export class ConfigSimpleBotComponent implements OnInit {
promise.then(() => {
this.bot._isUpdating = false;
if (this.bot._inRoom) {
this.translate.get('was invited to the room').subscribe((res: string) => {this.toaster.pop("success", this.bot.displayName + res); });
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); });
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
@ -57,7 +61,9 @@ export class ConfigSimpleBotComponent implements OnInit {
if (err.json) errorMessage = err.json().error;
if (err.response && err.response.error) errorMessage = err.response.error.message;
if (!errorMessage) errorMessage = "";
this.translate.get('Could not update integration status').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Could not update integration status').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -25,11 +25,11 @@ export class StickerpickerComponent implements OnInit {
public stickerBot: string;
constructor(private stickerApi: StickerApiService,
private media: MediaService,
private scalarClient: ScalarClientApiService,
private toaster: ToasterService,
private window: Window,
public translate?: TranslateService) {
private media: MediaService,
private scalarClient: ScalarClientApiService,
private toaster: ToasterService,
private window: Window,
public translate?: TranslateService) {
this.translate = translate;
this.isLoading = true;
this.isUpdating = false;
@ -41,7 +41,9 @@ export class StickerpickerComponent implements OnInit {
this.isLoading = false;
} catch (e) {
console.error(e);
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Failed to load sticker packs').subscribe((res: string) => {
this.toaster.pop("error", res);
});
}
this.stickerApi.getConfig().then(config => {
@ -58,12 +60,16 @@ export class StickerpickerComponent implements OnInit {
this.packs.splice(0, 0, pack);
this.packUrl = "";
this.isImporting = false;
this.translate.get('Stickerpack added').subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get('Stickerpack added').subscribe((res: string) => {
this.toaster.pop("success", res);
});
this.addWidget();
}).catch(err => {
console.error(err);
this.isImporting = false;
this.translate.get('Error adding stickerpack').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error adding stickerpack').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
@ -76,13 +82,17 @@ export class StickerpickerComponent implements OnInit {
this.isUpdating = true;
this.stickerApi.togglePackSelection(pack.id, pack.isSelected).then(() => {
this.isUpdating = false;
this.translate.get('Stickers updated').subscribe((res: string) => {this.toaster.pop("success", res); });
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.translate.get('Error updating stickers').subscribe((res: string) => {this.toaster.pop("error", res); });
this.translate.get('Error updating stickers').subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}

View File

@ -2,15 +2,14 @@ import { WidgetComponent } from "../widget.component";
import { Component, ContentChild, Input, TemplateRef } from "@angular/core";
@Component({
selector: "my-widget-config",
selector: "app-widget-config",
templateUrl: "config-screen.widget.component.html",
styleUrls: ["config-screen.widget.component.scss"],
})
export class ConfigScreenWidgetComponent {
@Input() widgetComponent: WidgetComponent;
@ContentChild(TemplateRef, {static: false}) widgetParamsTemplate: TemplateRef<any>;
@ContentChild(TemplateRef, { static: false })
widgetParamsTemplate: TemplateRef<any>;
constructor() {
}
}
constructor() {}
}

View File

@ -33,11 +33,11 @@ export class WidgetComponent implements OnInit {
private scalarApi = ServiceLocator.injector.get(ScalarClientApiService);
constructor(@Inject(String) private widgetTypes: string[],
@Inject(String) public defaultName: string,
@Inject(String) private wrapperId = "generic",
public translate: TranslateService,
@Inject(String) private scalarWrapperId = null,
@Inject(String) private scalarWrapperUrlParamName = "url") {
@Inject(String) public defaultName: string,
@Inject(String) private wrapperId = "generic",
public translate: TranslateService,
@Inject(String) private scalarWrapperId = null,
@Inject(String) private scalarWrapperUrlParamName = "url") {
this.translate = translate;
this.isLoading = true;
@ -49,7 +49,7 @@ export class WidgetComponent implements OnInit {
this.wrapperUrl = this.window.location.origin + "/widgets/" + this.wrapperId + "?url=";
if (!this.scalarWrapperId) this.scalarWrapperId = this.wrapperId;
for (let widgetLink of SCALAR_WIDGET_LINKS) {
for (const widgetLink of SCALAR_WIDGET_LINKS) {
const wrapperLink = widgetLink
.replace("__TYPE__", this.scalarWrapperId)
.replace("__PNAME__", this.scalarWrapperUrlParamName);
@ -60,7 +60,7 @@ export class WidgetComponent implements OnInit {
this.prepareNewWidget();
this.getWidgetsOfType(this.widgetTypes).then(widgets => {
this.widgets = widgets;
for (let widget of this.widgets) {
for (const widget of this.widgets) {
this.unpackWidget(widget);
}
@ -70,15 +70,15 @@ export class WidgetComponent implements OnInit {
// We reset after discovering to ensure that the widget component can correctly
// set the state of the widget prior to us unpacking it (again)
for (let widget of this.widgets) {
for (const widget of this.widgets) {
this.resetWidget(widget);
}
// See if we should request editing a particular widget
if (SessionStorage.editIntegrationId && SessionStorage.editsRequested === 1) {
let editWidget: EditableWidget = null;
let otherWidgets: EditableWidget[] = [];
for (let widget of this.widgets) {
const otherWidgets: EditableWidget[] = [];
for (const widget of this.widgets) {
if (widget.id === SessionStorage.editIntegrationId) {
editWidget = widget;
} else otherWidgets.push(widget);
@ -186,7 +186,7 @@ export class WidgetComponent implements OnInit {
if (!this.wrapperUrl) return url;
const urls = [this.wrapperUrl].concat(this.scalarWrapperUrls);
for (let scalarUrl of urls) {
for (const scalarUrl of urls) {
if (url.startsWith(scalarUrl)) {
return decodeURIComponent(url.substring(scalarUrl.length));
}
@ -263,12 +263,16 @@ export class WidgetComponent implements OnInit {
try {
this.OnWidgetBeforeAdd(this.newWidget);
} catch (error) {
this.translate.get(error.message).subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get(error.message).subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
if (!this.newWidget.dimension.newUrl || this.newWidget.dimension.newUrl.trim().length === 0) {
this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {this.toaster.pop("warning", res ); });
this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {
this.toaster.pop("warning", res );
});
return;
}
@ -281,7 +285,9 @@ export class WidgetComponent implements OnInit {
this.isUpdating = false;
this.OnWidgetAfterAdd(this.newWidget);
this.prepareNewWidget();
this.translate.get("Widget added!").subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get("Widget added!").subscribe((res: string) => {
this.toaster.pop("success", res);
});
})
.catch(err => {
this.isUpdating = false;
@ -305,7 +311,9 @@ export class WidgetComponent implements OnInit {
}
if (!widget.dimension.newUrl || widget.dimension.newUrl.trim().length === 0) {
this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {this.toaster.pop("warning", res); });
this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {
this.toaster.pop("warning", res);
});
return;
}
@ -316,7 +324,9 @@ export class WidgetComponent implements OnInit {
.then(() => {
this.isUpdating = false;
this.OnWidgetAfterEdit(widget);
this.translate.get("Widget updated!").subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get("Widget updated!").subscribe((res: string) => {
this.toaster.pop("success", res);
});
})
.catch(err => {
this.isUpdating = false;
@ -338,7 +348,9 @@ export class WidgetComponent implements OnInit {
.then(() => {
this.isUpdating = false;
this.OnWidgetAfterDelete(widget);
this.translate.get("Widget deleted!").subscribe((res: string) => {this.toaster.pop("success", res); });
this.translate.get("Widget deleted!").subscribe((res: string) => {
this.toaster.pop("success", res);
});
})
.catch(err => {
this.isUpdating = false;

View File

@ -47,12 +47,16 @@ export class YoutubeWidgetConfigComponent extends WidgetComponent {
private setVideoUrl(widget: EditableWidget) {
if (!widget.dimension.newData.videoUrl || widget.dimension.newData.videoUrl.trim().length === 0) {
this.translate.get('Please enter a video URL').subscribe((res: string) => {throw new Error(res); });
this.translate.get('Please enter a video URL').subscribe((res: string) => {
throw new Error(res);
});
}
const videoUrl = this.getRealVideoUrl(widget.dimension.newData.videoUrl);
if (!videoUrl) {
this.translate.get('Please enter a YouTube, Vimeo, or DailyMotion video URL').subscribe((res: string) => {throw new Error(res); });
this.translate.get('Please enter a YouTube, Vimeo, or DailyMotion video URL').subscribe((res: string) => {
throw new Error(res);
});
}
widget.dimension.newUrl = videoUrl;

View File

@ -2,22 +2,21 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
import * as screenfull from "screenfull";
@Component({
selector: "my-fullscreen-button",
selector: "app-fullscreen-button",
templateUrl: "fullscreen-button.component.html",
styleUrls: ["fullscreen-button.component.scss"],
})
export class FullscreenButtonComponent implements OnDestroy, OnInit {
public isFullscreen = false;
private listener = null;
constructor() {
// Do stuff
// Do stuff
}
public ngOnInit(): void {
// @ts-ignore
// @ts-ignore
this.listener = screenfull.on("change", () => {
// @ts-ignore
this.isFullscreen = screenfull.isFullscreen;

View File

@ -2,7 +2,7 @@ import { Component, Input, OnInit } from "@angular/core";
import { ANIMATION_FADE_IN_NOT_OUT } from "../../app.animations";
@Component({
selector: "my-ibox",
selector: "app-ibox",
templateUrl: "./ibox.component.html",
styleUrls: ["./ibox.component.scss"],
animations: [ANIMATION_FADE_IN_NOT_OUT],

View File

@ -1,9 +1,8 @@
import { Component } from "@angular/core";
@Component({
selector: "my-spinner",
selector: "app-spinner",
templateUrl: "./spinner.component.html",
styleUrls: ["./spinner.component.scss"],
})
export class SpinnerComponent {
}
export class SpinnerComponent {}

View File

@ -1,23 +1,22 @@
import { Component } from "@angular/core";
@Component({
selector: "my-home",
selector: "app-home",
templateUrl: "./home.component.html",
styleUrls: ["./home.component.scss"],
})
export class HomeComponent {
public hostname: string = window.location.origin;
public showPromoPage = this.hostname === "https://dimension.t2bot.io";
public integrationsConfig = `` +
`"integrations_ui_url": "${this.hostname}/element",\n` +
`"integrations_rest_url": "${this.hostname}/api/v1/scalar",\n` +
`"integrations_widgets_urls": ["${this.hostname}/widgets"],\n` +
`"integrations_jitsi_widget_url": "${this.hostname}/widgets/jitsi",\n`;
public integrationsConfig =
`` +
`"integrations_ui_url": "${this.hostname}/element",\n` +
`"integrations_rest_url": "${this.hostname}/api/v1/scalar",\n` +
`"integrations_widgets_urls": ["${this.hostname}/widgets"],\n` +
`"integrations_jitsi_widget_url": "${this.hostname}/widgets/jitsi",\n`;
constructor() {
// Do stuff
// Do stuff
}
}

View File

@ -1,27 +1,40 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChange, SimpleChanges } from "@angular/core";
import {
Component,
EventEmitter,
Input,
OnChanges,
Output,
SimpleChange,
SimpleChanges,
} from "@angular/core";
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
import { FE_Integration } from "../shared/models/integration";
import { MediaService } from "../shared/services/media.service";
@Component({
selector: "my-integration-bag",
selector: "app-integration-bag",
templateUrl: "./integration-bag.component.html",
styleUrls: ["./integration-bag.component.scss"],
})
export class IntegrationBagComponent implements OnChanges {
@Input() integrations: FE_Integration[];
@Output() integrationClicked: EventEmitter<FE_Integration> = new EventEmitter<FE_Integration>();
@Output() integrationClicked: EventEmitter<FE_Integration> =
new EventEmitter<FE_Integration>();
constructor(private sanitizer: DomSanitizer, private media: MediaService) {
}
constructor(private sanitizer: DomSanitizer, private media: MediaService) {}
public ngOnChanges(changes: SimpleChanges) {
const change: SimpleChange = changes.integrations;
(<FE_Integration[]>change.currentValue).map(async (i) => {
if (i.avatarUrl.startsWith("mxc://")) {
i.avatarUrl = await this.media.getThumbnailUrl(i.avatarUrl, 128, 128, "scale", true);
i.avatarUrl = await this.media.getThumbnailUrl(
i.avatarUrl,
128,
128,
"scale",
true
);
}
});
}

View File

@ -1,37 +1,52 @@
import { Component } from "@angular/core";
import { ActivatedRoute, NavigationEnd, PRIMARY_OUTLET, Router } from "@angular/router";
import {
ActivatedRoute,
NavigationEnd,
PRIMARY_OUTLET,
Router,
} from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
import { filter } from "rxjs/operators";
@Component({
selector: "my-page-header",
selector: "app-page-header",
templateUrl: "./page-header.component.html",
styleUrls: ["./page-header.component.scss"],
})
export class PageHeaderComponent {
public pageName: string;
constructor(private router: Router, private activatedRoute: ActivatedRoute, public translate: TranslateService) {
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
public translate: TranslateService
) {
this.translate = translate;
this.router.events.pipe(filter(ev => ev instanceof NavigationEnd)).subscribe((ev) => {
let currentRoute = this.activatedRoute.root;
let url = "";
const event = ev as NavigationEnd;
this.router.events
.pipe(filter((ev) => ev instanceof NavigationEnd))
.subscribe((ev) => {
let currentRoute = this.activatedRoute.root;
let url = "";
const event = ev as NavigationEnd;
while (currentRoute.children.length > 0) {
const children = currentRoute.children;
children.forEach(route => {
if (route.snapshot.data['breadcrumb']) {
this.translate.get(route.snapshot.data['breadcrumb']).subscribe((res: string) => {route.snapshot.data['breadcrumb'] = res});
}
currentRoute = route;
url += "/" + route.snapshot.url.map(s => s.path).join("/");
if (route.outlet !== PRIMARY_OUTLET) return;
if (!route.routeConfig || !route.routeConfig.data) return;
if (url === event.urlAfterRedirects.split("?")[0]) this.pageName = route.snapshot.data.name;
});
}
});
while (currentRoute.children.length > 0) {
const children = currentRoute.children;
children.forEach((route) => {
if (route.snapshot.data["breadcrumb"]) {
this.translate
.get(route.snapshot.data["breadcrumb"])
.subscribe((res: string) => {
route.snapshot.data["breadcrumb"] = res;
});
}
currentRoute = route;
url += "/" + route.snapshot.url.map((s) => s.path).join("/");
if (route.outlet !== PRIMARY_OUTLET) return;
if (!route.routeConfig || !route.routeConfig.data) return;
if (url === event.urlAfterRedirects.split("?")[0])
this.pageName = route.snapshot.data.name;
});
}
});
}
}

View File

@ -4,17 +4,17 @@ import { ScalarClientApiService } from "../../shared/services/scalar/scalar-clie
import * as _ from "lodash";
import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service";
import {
FE_Integration,
FE_IntegrationRequirement,
FE_SimpleBot,
FE_Integration,
FE_IntegrationRequirement,
FE_SimpleBot,
} from "../../shared/models/integration";
import { IntegrationsRegistry } from "../../shared/registry/integrations.registry";
import { SessionStorage } from "../../shared/SessionStorage";
import { AdminApiService } from "../../shared/services/admin/admin-api.service";
import { IntegrationsApiService } from "../../shared/services/integrations/integrations-api.service";
import {
ConfigSimpleBotComponent,
SimpleBotConfigDialogContext,
ConfigSimpleBotComponent,
SimpleBotConfigDialogContext,
} from "../../configs/simple-bot/simple-bot.component";
import { ToasterService } from "angular2-toaster";
import { StickerApiService } from "../../shared/services/integrations/sticker-api.service";
@ -22,462 +22,462 @@ import { TranslateService } from "@ngx-translate/core";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
const CATEGORY_MAP = {
Widgets: ["widget"],
Bots: ["complex-bot", "bot"],
Bridges: ["bridge"],
Widgets: ["widget"],
Bots: ["complex-bot", "bot"],
Bridges: ["bridge"],
};
@Component({
selector: "my-riot-home",
templateUrl: "./home.component.html",
styleUrls: ["./home.component.scss"],
selector: "app-riot-home",
templateUrl: "./home.component.html",
styleUrls: ["./home.component.scss"],
})
export class RiotHomeComponent {
public isLoading = true;
public isError = false;
public errorMessage: string;
public isRoomEncrypted: boolean;
public hasStickerPacks = false;
public isLoading = true;
public isError = false;
public errorMessage: string;
public isRoomEncrypted: boolean;
public hasStickerPacks = false;
private roomId: string;
private userId: string;
private requestedScreen: string = null;
private requestedIntegrationId: string = null;
public integrationsForCategory: { [category: string]: FE_Integration[] } = {};
private categoryMap: { [categoryName: string]: string[] } = CATEGORY_MAP;
private roomId: string;
private userId: string;
private requestedScreen: string = null;
private requestedIntegrationId: string = null;
public integrationsForCategory: { [category: string]: FE_Integration[] } = {};
private categoryMap: { [categoryName: string]: string[] } = CATEGORY_MAP;
constructor(
private activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private scalar: ScalarClientApiService,
private integrationsApi: IntegrationsApiService,
private stickerApi: StickerApiService,
private adminApi: AdminApiService,
private router: Router,
private modal: NgbModal,
private toaster: ToasterService,
public translate: TranslateService
) {
this.translate = translate;
let params: any = this.activatedRoute.snapshot.queryParams;
constructor(
private activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private scalar: ScalarClientApiService,
private integrationsApi: IntegrationsApiService,
private stickerApi: StickerApiService,
private adminApi: AdminApiService,
private router: Router,
private modal: NgbModal,
private toaster: ToasterService,
public translate: TranslateService
) {
this.translate = translate;
const params: any = this.activatedRoute.snapshot.queryParams;
this.requestedScreen = params.screen;
this.requestedIntegrationId = params.integ_id;
this.requestedScreen = params.screen;
this.requestedIntegrationId = params.integ_id;
if (SessionStorage.roomId && SessionStorage.userId) {
this.roomId = SessionStorage.roomId;
this.userId = SessionStorage.userId;
console.log(
"Already checked scalar token and other params - continuing startup"
);
this.prepareIntegrations();
return;
}
if (SessionStorage.roomId && SessionStorage.userId) {
this.roomId = SessionStorage.roomId;
this.userId = SessionStorage.userId;
console.log(
"Already checked scalar token and other params - continuing startup"
);
this.prepareIntegrations();
return;
}
if (!params.scalar_token || !params.room_id) {
console.error(
"Unable to load Dimension. Missing room ID or scalar token."
);
this.isError = true;
this.isLoading = false;
this.translate
.get("Unable to load Dimension - missing room ID or token.")
.subscribe((res: string) => {
this.errorMessage = res;
});
} else {
this.roomId = params.room_id;
SessionStorage.scalarToken = params.scalar_token;
SessionStorage.roomId = this.roomId;
this.scalarApi
.getAccount()
.then((response) => {
const userId = response.user_id;
SessionStorage.userId = userId;
if (!userId) {
if (!params.scalar_token || !params.room_id) {
console.error(
"No user returned for token. Is the token registered in Dimension?"
"Unable to load Dimension. Missing room ID or scalar token."
);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!"
)
.subscribe((res: string) => {
this.errorMessage = res;
});
} else {
this.userId = userId;
console.log("Scalar token belongs to " + userId);
this.checkAdmin();
this.prepareIntegrations();
}
})
.catch((err) => {
console.error(err);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Unable to communicate with Dimension due to an unknown error."
)
.subscribe((res: string) => {
this.errorMessage = res;
});
});
}
}
.get("Unable to load Dimension - missing room ID or token.")
.subscribe((res: string) => {
this.errorMessage = res;
});
} else {
this.roomId = params.room_id;
SessionStorage.scalarToken = params.scalar_token;
SessionStorage.roomId = this.roomId;
private checkAdmin() {
this.adminApi
.isAdmin()
.then(() => {
console.log(
SessionStorage.userId + " is an admin for this Dimension instance"
);
SessionStorage.isAdmin = true;
})
.catch(() => (SessionStorage.isAdmin = false));
}
public hasIntegrations(): boolean {
for (const category of this.getCategories()) {
if (this.getIntegrationsIn(category).length > 0) return true;
this.scalarApi
.getAccount()
.then((response) => {
const userId = response.user_id;
SessionStorage.userId = userId;
if (!userId) {
console.error(
"No user returned for token. Is the token registered in Dimension?"
);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!"
)
.subscribe((res: string) => {
this.errorMessage = res;
});
} else {
this.userId = userId;
console.log("Scalar token belongs to " + userId);
this.checkAdmin();
this.prepareIntegrations();
}
})
.catch((err) => {
console.error(err);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Unable to communicate with Dimension due to an unknown error."
)
.subscribe((res: string) => {
this.errorMessage = res;
});
});
}
}
return false;
}
public getCategories(): string[] {
return Object.keys(this.categoryMap);
}
public getIntegrationsIn(category: string): FE_Integration[] {
return this.integrationsForCategory[category];
}
private getIntegrations(): FE_Integration[] {
const result: FE_Integration[] = [];
for (const category of this.getCategories()) {
for (const integration of this.getIntegrationsIn(category)) {
result.push(integration);
}
private checkAdmin() {
this.adminApi
.isAdmin()
.then(() => {
console.log(
SessionStorage.userId + " is an admin for this Dimension instance"
);
SessionStorage.isAdmin = true;
})
.catch(() => (SessionStorage.isAdmin = false));
}
return result;
}
public hasIntegrations(): boolean {
for (const category of this.getCategories()) {
if (this.getIntegrationsIn(category).length > 0) return true;
}
public modifyIntegration(integration: FE_Integration) {
if (!integration._isSupported) {
console.log(
this.userId +
return false;
}
public getCategories(): string[] {
return Object.keys(this.categoryMap);
}
public getIntegrationsIn(category: string): FE_Integration[] {
return this.integrationsForCategory[category];
}
private getIntegrations(): FE_Integration[] {
const result: FE_Integration[] = [];
for (const category of this.getCategories()) {
for (const integration of this.getIntegrationsIn(category)) {
result.push(integration);
}
}
return result;
}
public modifyIntegration(integration: FE_Integration) {
if (!integration._isSupported) {
console.log(
this.userId +
" tried to modify " +
integration.displayName +
" with error: " +
integration._notSupportedReason
);
this.translate
.get(
"You do not appear to have permission to modify widgets in this room"
)
.subscribe((res: string) => {
const reason =
);
this.translate
.get(
"You do not appear to have permission to modify widgets in this room"
)
.subscribe((res: string) => {
const reason =
integration.category === "widget"
? res
: integration._notSupportedReason;
this.toaster.pop("error", reason);
});
return;
}
? res
: integration._notSupportedReason;
this.toaster.pop("error", reason);
});
return;
}
SessionStorage.editIntegration = integration;
SessionStorage.editsRequested++;
console.log(
this.userId + " is trying to modify " + integration.displayName
);
SessionStorage.editIntegration = integration;
SessionStorage.editsRequested++;
console.log(
this.userId + " is trying to modify " + integration.displayName
);
if (integration.category === "bot") {
const widgetConfigRef = this.modal.open(ConfigSimpleBotComponent, {
backdrop: "static",
size: "lg",
});
const widgetConfigInterface =
if (integration.category === "bot") {
const widgetConfigRef = this.modal.open(ConfigSimpleBotComponent, {
backdrop: "static",
size: "lg",
});
const widgetConfigInterface =
widgetConfigRef.componentInstance as SimpleBotConfigDialogContext;
widgetConfigInterface.bot = <FE_SimpleBot>integration;
widgetConfigInterface.roomId = this.roomId;
} else {
console.log(
"Navigating to edit screen for " +
widgetConfigInterface.bot = <FE_SimpleBot>integration;
widgetConfigInterface.roomId = this.roomId;
} else {
console.log(
"Navigating to edit screen for " +
integration.category +
" " +
integration.type
);
this.router.navigate(
["riot-app", integration.category, integration.type],
{ queryParams: { roomId: this.roomId } }
);
);
this.router.navigate(
["riot-app", integration.category, integration.type],
{ queryParams: { roomId: this.roomId } }
);
}
}
}
private prepareIntegrations() {
this.scalar
.isRoomEncrypted(this.roomId)
.then((payload) => {
this.isRoomEncrypted = payload.response;
return this.integrationsApi.getIntegrations(this.roomId);
})
.then((response) => {
const integrations: FE_Integration[] = _.flatten(
Object.keys(response).map((k) => response[k])
);
const supportedIntegrations: FE_Integration[] = _.filter(
integrations,
(i) => IntegrationsRegistry.isSupported(i)
);
private prepareIntegrations() {
this.scalar
.isRoomEncrypted(this.roomId)
.then((payload) => {
this.isRoomEncrypted = payload.response;
return this.integrationsApi.getIntegrations(this.roomId);
})
.then((response) => {
const integrations: FE_Integration[] = _.flatten(
Object.keys(response).map((k) => response[k])
);
const supportedIntegrations: FE_Integration[] = _.filter(
integrations,
(i) => IntegrationsRegistry.isSupported(i)
);
// Flag integrations that aren't supported in encrypted rooms
if (this.isRoomEncrypted) {
for (const integration of supportedIntegrations) {
if (!integration.isEncryptionSupported) {
integration._isSupported = false;
integration._notSupportedReason =
// Flag integrations that aren't supported in encrypted rooms
if (this.isRoomEncrypted) {
for (const integration of supportedIntegrations) {
if (!integration.isEncryptionSupported) {
integration._isSupported = false;
integration._notSupportedReason =
"This integration is not supported in encrypted rooms";
}
}
}
}
}
// Set up the categories
for (const category of Object.keys(this.categoryMap)) {
const supportedTypes = this.categoryMap[category];
this.integrationsForCategory[category] = _.filter(
supportedIntegrations,
(i) => supportedTypes.indexOf(i.category) !== -1
);
}
const promises = supportedIntegrations.map((i) =>
this.updateIntegrationState(i)
);
return Promise.all(promises);
})
.then(() => {
this.isLoading = false;
// HACK: We wait for the digest cycle so we actually have components to look at
setTimeout(() => this.tryOpenConfigScreen(), 20);
})
.catch((err) => {
console.error(err);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server."
)
.subscribe((res: string) => {
this.errorMessage = res;
});
});
this.stickerApi
.getPacks()
.then((packs) => {
this.hasStickerPacks = packs.length > 0;
})
.catch((err) => {
console.error(err);
});
}
private tryOpenConfigScreen() {
let category = null;
let type = null;
if (!this.requestedScreen) return;
if (this.requestedScreen === "type_m.stickerpicker") {
console.log(
"Intercepting config screen handling to open sticker picker config"
);
this.router.navigate(["riot-app", "stickerpicker"]);
return;
}
// Set up the categories
for (const category of Object.keys(this.categoryMap)) {
const supportedTypes = this.categoryMap[category];
this.integrationsForCategory[category] = _.filter(
supportedIntegrations,
(i) => supportedTypes.indexOf(i.category) !== -1
);
}
let promises = supportedIntegrations.map((i) =>
this.updateIntegrationState(i)
const targetIntegration = IntegrationsRegistry.getIntegrationForScreen(
this.requestedScreen
);
return Promise.all(promises);
})
.then(() => {
this.isLoading = false;
if (targetIntegration) {
category = targetIntegration.category;
type = targetIntegration.type;
} else {
console.log("Unknown screen requested: " + this.requestedScreen);
}
// HACK: We wait for the digest cycle so we actually have components to look at
setTimeout(() => this.tryOpenConfigScreen(), 20);
})
.catch((err) => {
console.error(err);
this.isError = true;
this.isLoading = false;
this.translate
.get(
"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server."
)
.subscribe((res: string) => {
this.errorMessage = res;
});
});
this.stickerApi
.getPacks()
.then((packs) => {
this.hasStickerPacks = packs.length > 0;
})
.catch((err) => {
console.error(err);
});
}
private tryOpenConfigScreen() {
let category = null;
let type = null;
if (!this.requestedScreen) return;
if (this.requestedScreen === "type_m.stickerpicker") {
console.log(
"Intercepting config screen handling to open sticker picker config"
);
this.router.navigate(["riot-app", "stickerpicker"]);
return;
}
const targetIntegration = IntegrationsRegistry.getIntegrationForScreen(
this.requestedScreen
);
if (targetIntegration) {
category = targetIntegration.category;
type = targetIntegration.type;
} else {
console.log("Unknown screen requested: " + this.requestedScreen);
}
console.log("Searching for integration for requested screen");
for (const integration of this.getIntegrations()) {
if (integration.category === category && integration.type === type) {
console.log(
"Configuring integration " +
console.log("Searching for integration for requested screen");
for (const integration of this.getIntegrations()) {
if (integration.category === category && integration.type === type) {
console.log(
"Configuring integration " +
this.requestedIntegrationId +
" category=" +
category +
" type=" +
type
);
SessionStorage.editIntegration = integration;
SessionStorage.editIntegrationId = this.requestedIntegrationId;
this.modifyIntegration(integration);
return;
}
}
);
SessionStorage.editIntegration = integration;
SessionStorage.editIntegrationId = this.requestedIntegrationId;
this.modifyIntegration(integration);
return;
}
}
console.log(
"Failed to find integration component for category=" +
console.log(
"Failed to find integration component for category=" +
category +
" type=" +
type
);
}
private async updateIntegrationState(integration: FE_Integration) {
if (!integration.isOnline) {
integration._isSupported = false;
this.translate
.get("This integration is offline or unavailable")
.subscribe((res: string) => {
integration._notSupportedReason = res;
});
return;
}
if (!integration.requirements) return;
let promises = integration.requirements.map((r) =>
this.checkRequirement(r)
);
if (integration.category === "bot") {
const state = await this.scalar.getMembershipState(
this.roomId,
(<FE_SimpleBot>integration).userId
);
if (state && state.response && state.response.membership) {
integration._inRoom =
["join", "invite"].indexOf(state.response.membership) !== -1;
} else integration._inRoom = false;
}
return Promise.all(promises).then(
() => {
integration._isSupported = true;
integration._notSupportedReason = null;
},
(error) => {
console.error(error);
integration._isSupported = false;
integration._notSupportedReason = error;
}
);
}
private checkRequirement(requirement: FE_IntegrationRequirement) {
switch (requirement.condition) {
case "publicRoom":
return this.scalar.getJoinRule(this.roomId).then((payload) => {
if (!payload.response) {
let message: string;
this.translate
.get("Could not communicate with Element")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
const isPublic = payload.response.join_rule === "public";
if (isPublic !== requirement.expectedValue) {
let message: string;
let message1: string;
this.translate
.get(["The room must be", "to use this integration"])
.subscribe((res: string) => {
message = res[0];
message1 = res[1];
});
return Promise.reject(
message + (isPublic ? "non-public" : "public") + message1
);
} else return Promise.resolve();
});
case "canSendEventTypes":
const processPayload = (payload) => {
const response = <any>payload.response;
if (response === true) return Promise.resolve();
if (response.error || response.error.message) {
let message: string;
this.translate
.get("You cannot modify widgets in this room")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
let message: string;
this.translate
.get("Error communicating with Element")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
};
let promiseChain = Promise.resolve();
requirement.argument.forEach(
(e) =>
(promiseChain = promiseChain.then(() =>
this.scalar
.canSendEvent(this.roomId, e.type, e.isState)
.then(processPayload)
.catch(processPayload)
))
);
return promiseChain
.then(() => {
if (!requirement.expectedValue) {
let message: string;
this.translate
.get("Expected to not be able to send specific event types")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
})
.catch((err) => {
console.error(err);
if (requirement.expectedValue) {
let message: string;
this.translate
.get("Expected to be able to send specific event types")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
});
case "userInRoom":
// TODO: Implement
default:
let message: string;
let message1: string;
this.translate
.get(["Requirement", "not found"])
.subscribe((res: string) => {
message = res[0];
message1 = res[1];
});
return Promise.reject(message + requirement.condition + message1);
}
}
private async updateIntegrationState(integration: FE_Integration) {
if (!integration.isOnline) {
integration._isSupported = false;
this.translate
.get("This integration is offline or unavailable")
.subscribe((res: string) => {
integration._notSupportedReason = res;
});
return;
}
if (!integration.requirements) return;
const promises = integration.requirements.map((r) =>
this.checkRequirement(r)
);
if (integration.category === "bot") {
const state = await this.scalar.getMembershipState(
this.roomId,
(<FE_SimpleBot>integration).userId
);
if (state && state.response && state.response.membership) {
integration._inRoom =
["join", "invite"].indexOf(state.response.membership) !== -1;
} else integration._inRoom = false;
}
return Promise.all(promises).then(
() => {
integration._isSupported = true;
integration._notSupportedReason = null;
},
(error) => {
console.error(error);
integration._isSupported = false;
integration._notSupportedReason = error;
}
);
}
private checkRequirement(requirement: FE_IntegrationRequirement) {
switch (requirement.condition) {
case "publicRoom":
return this.scalar.getJoinRule(this.roomId).then((payload) => {
if (!payload.response) {
let message: string;
this.translate
.get("Could not communicate with Element")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
const isPublic = payload.response.join_rule === "public";
if (isPublic !== requirement.expectedValue) {
let message: string;
let message1: string;
this.translate
.get(["The room must be", "to use this integration"])
.subscribe((res: string) => {
message = res[0];
message1 = res[1];
});
return Promise.reject(
message + (isPublic ? "non-public" : "public") + message1
);
} else return Promise.resolve();
});
case "canSendEventTypes":
const processPayload = (payload) => {
const response = payload.response;
if (response === true) return Promise.resolve();
if (response.error || response.error.message) {
let message: string;
this.translate
.get("You cannot modify widgets in this room")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
let message: string;
this.translate
.get("Error communicating with Element")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
};
let promiseChain = Promise.resolve();
requirement.argument.forEach(
(e) =>
(promiseChain = promiseChain.then(() =>
this.scalar
.canSendEvent(this.roomId, e.type, e.isState)
.then(processPayload)
.catch(processPayload)
))
);
return promiseChain
.then(() => {
if (!requirement.expectedValue) {
let message: string;
this.translate
.get("Expected to not be able to send specific event types")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
})
.catch((err) => {
console.error(err);
if (requirement.expectedValue) {
let message: string;
this.translate
.get("Expected to be able to send specific event types")
.subscribe((res: string) => {
message = res;
});
return Promise.reject(message);
}
});
case "userInRoom":
// TODO: Implement
default:
let message: string;
let message1: string;
this.translate
.get(["Requirement", "not found"])
.subscribe((res: string) => {
message = res[0];
message1 = res[1];
});
return Promise.reject(message + requirement.condition + message1);
}
}
}

View File

@ -2,14 +2,12 @@ import { Component } from "@angular/core";
import { SessionStorage } from "../shared/SessionStorage";
@Component({
selector: "my-riot",
selector: "app-riot",
templateUrl: "./riot.component.html",
styleUrls: ["./riot.component.scss"],
})
export class RiotComponent {
constructor() {
}
constructor() {}
public isAdmin(): boolean {
return SessionStorage.isAdmin;

View File

@ -2,14 +2,12 @@ import { Component } from "@angular/core";
import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service";
@Component({
selector: "my-scalar-close",
selector: "app-scalar-close",
templateUrl: "./scalar-close.component.html",
styleUrls: ["./scalar-close.component.scss"],
})
export class ScalarCloseComponent {
constructor(private scalar: ScalarClientApiService) {
}
constructor(private scalar: ScalarClientApiService) {}
public closeScalar() {
console.log("Closing scalar...");

View File

@ -30,7 +30,9 @@ export class ScreenshotCapableDirective implements OnInit, OnDestroy {
private takeScreenshot(request: ScalarToWidgetRequest) {
if (this.el.nativeElement.tagName === "IFRAME") {
console.error("Attempted to take a screenshot of an iframe");
this.translate.get('Failed to take screenshot: iframe not supported').subscribe((res: string) => {ScalarWidgetApi.replyError(request, new Error("Cannot take screenshot of iframe"), res); });
this.translate.get('Failed to take screenshot: iframe not supported').subscribe((res: string) => {
ScalarWidgetApi.replyError(request, new Error("Cannot take screenshot of iframe"), res);
});
} else {
domtoimage.toBlob(this.el.nativeElement).then(b => {
if (!b) {
@ -40,7 +42,9 @@ export class ScreenshotCapableDirective implements OnInit, OnDestroy {
ScalarWidgetApi.replyScreenshot(request, b);
}).catch(error => {
console.error(error);
this.translate.get('Failed to take screenshot').subscribe((res: string) => {ScalarWidgetApi.replyError(request, error, res); });
this.translate.get('Failed to take screenshot').subscribe((res: string) => {
ScalarWidgetApi.replyError(request, error, res);
});
});
}
}

View File

@ -84,9 +84,9 @@ export interface EditableWidget {
* @return {EditableWidget[]} The Dimension widgets
*/
export function convertScalarWidgetsToDtos(scalarResponse: WidgetsResponse): EditableWidget[] {
let widgets = [];
const widgets = [];
for (let event of scalarResponse.response) {
for (const event of scalarResponse.response) {
widgets.push({
id: event.state_key,
type: event.content.type,

View File

@ -18,7 +18,7 @@ export class ScalarClientApiService {
private static actionMap: { [key: string]: { resolve: (obj: any) => void, reject: (obj: any) => void } } = {};
public static getAndRemoveActionHandler(requestKey: string): { resolve: (obj: any) => void, reject: (obj: any) => void } {
let handler = ScalarClientApiService.actionMap[requestKey];
const handler = ScalarClientApiService.actionMap[requestKey];
ScalarClientApiService.actionMap[requestKey] = null;
return handler;
}
@ -121,7 +121,7 @@ export class ScalarClientApiService {
}
private callAction(action, payload): Promise<any> {
let requestKey = randomString({length: 20});
const requestKey = randomString({length: 20});
return new Promise((resolve, reject) => {
if (!window.opener) {
// Mimic an error response from scalar
@ -134,7 +134,7 @@ export class ScalarClientApiService {
reject: reject
};
let request = JSON.parse(JSON.stringify(payload));
const request = JSON.parse(JSON.stringify(payload));
request["request_id"] = requestKey;
request["action"] = action;
@ -147,10 +147,10 @@ export class ScalarClientApiService {
window.addEventListener("message", event => {
if (!event.data) return;
let requestKey = event.data["request_id"];
const requestKey = event.data["request_id"];
if (!requestKey) return;
let action = ScalarClientApiService.getAndRemoveActionHandler(requestKey);
const action = ScalarClientApiService.getAndRemoveActionHandler(requestKey);
if (!action) return;
if (event.data.response && event.data.response.error) action.reject(event.data);

View File

@ -23,9 +23,9 @@ export class ScalarWidgetApi {
}
public static replyCapabilities(request: ScalarToWidgetRequest,
capabilities: (
"m.text" | "m.image" | "m.sticker" | "m.capability.screenshot" | "m.capability.request_data" |
"m.capability.request_messages" | "m.capability.room_membership" | string)[]
capabilities: (
"m.text" | "m.image" | "m.sticker" | "m.capability.screenshot" | "m.capability.request_data" |
"m.capability.request_messages" | "m.capability.room_membership" | string)[]
): void {
ScalarWidgetApi.replyEvent(request, {capabilities: capabilities});
}
@ -97,7 +97,7 @@ export class ScalarWidgetApi {
return;
}
let request = JSON.parse(JSON.stringify(payload));
const request = JSON.parse(JSON.stringify(payload));
request["api"] = "fromWidget";
request["widgetId"] = ScalarWidgetApi.widgetId;
request["action"] = action;
@ -114,7 +114,7 @@ export class ScalarWidgetApi {
return;
}
let requestClone = JSON.parse(JSON.stringify(request));
const requestClone = JSON.parse(JSON.stringify(request));
requestClone["response"] = payload;
console.log("[Dimension] Sending postMessage response: ", request);

View File

@ -5,21 +5,25 @@ import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api"
import { CapableWidget } from "../capable-widget";
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
import { BigBlueButtonApiService } from "../../shared/services/integrations/bigbluebutton-api.service";
import { FE_BigBlueButtonCreateAndJoinMeeting, FE_BigBlueButtonJoin } from "../../shared/models/integration";
import {
FE_BigBlueButtonCreateAndJoinMeeting,
FE_BigBlueButtonJoin,
} from "../../shared/models/integration";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "my-bigbluebutton-widget-wrapper",
selector: "app-bigbluebutton-widget-wrapper",
templateUrl: "bigbluebutton.component.html",
styleUrls: ["bigbluebutton.component.scss"],
})
export class BigBlueButtonWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
export class BigBlueButtonWidgetWrapperComponent
extends CapableWidget
implements OnInit, OnDestroy {
public canEmbed = true;
/**
* User metadata passed to us by the client
*/
* User metadata passed to us by the client
*/
private conferenceUrl: string;
private displayName: string;
private userId: string;
@ -28,57 +32,59 @@ export class BigBlueButtonWidgetWrapperComponent extends CapableWidget implement
private meetingPassword: string;
/**
*
* The name to join the BigBlueButton meeting with. Made up of metadata the client passes to us.
*/
*
* The name to join the BigBlueButton meeting with. Made up of metadata the client passes to us.
*/
private joinName: string;
/**
* Whether we expect the meeting to be created on command.
*
* True if we'd like the meeting to be created, false if we have a greenlight URL leading to an existing meeting
* and would like Dimension to translate that to a BigBlueButton meeting URL.
*/
* Whether we expect the meeting to be created on command.
*
* True if we'd like the meeting to be created, false if we have a greenlight URL leading to an existing meeting
* and would like Dimension to translate that to a BigBlueButton meeting URL.
*/
private createMeeting: boolean;
/**
* The ID of the room, required if createMeeting is true.
*/
* The ID of the room, required if createMeeting is true.
*/
private roomId: string;
/**
* The poll period in ms while waiting for a meeting to start
*/
* The poll period in ms while waiting for a meeting to start
*/
private pollIntervalMillis = 5000;
/**
* Subscriber for messages from the client via the postMessage API
*/
* Subscriber for messages from the client via the postMessage API
*/
private bigBlueButtonApiSubscription: Subscription;
/**
* A status message to display to the user in the widget, typically for loading messages
*/
* A status message to display to the user in the widget, typically for loading messages
*/
public statusMessage: string;
/**
* Whether we are currently in a meeting
*/
* Whether we are currently in a meeting
*/
private inMeeting = false;
/**
* The URL to embed into the iframe
*/
* The URL to embed into the iframe
*/
public embedUrl: SafeUrl = null;
constructor(activatedRoute: ActivatedRoute,
private bigBlueButtonApi: BigBlueButtonApiService,
private sanitizer: DomSanitizer,
public translate: TranslateService) {
constructor(
activatedRoute: ActivatedRoute,
private bigBlueButtonApi: BigBlueButtonApiService,
private sanitizer: DomSanitizer,
public translate: TranslateService
) {
super();
this.supportsAlwaysOnScreen = true;
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
this.roomId = params.roomId;
this.createMeeting = params.createMeeting;
@ -144,63 +150,85 @@ export class BigBlueButtonWidgetWrapperComponent extends CapableWidget implement
// Ask Dimension to create a meeting (or use an existing one) for this room and return the embeddable meeting URL
private async joinThroughDimension() {
console.log("BigBlueButton: Joining meeting created by Dimension with meeting ID: " + this.meetingId);
console.log(
"BigBlueButton: Joining meeting created by Dimension with meeting ID: " +
this.meetingId
);
this.bigBlueButtonApi.getJoinUrl(this.displayName, this.userId, this.avatarUrl, this.meetingId, this.meetingPassword).then((response) => {
console.log("The response");
console.log(response);
if ("errorCode" in response) {
// This is an instance of ApiError
if (response.errorCode === "UNKNOWN_MEETING_ID") {
// This meeting ID is invalid.
// Inform the user that they should try and start a new meeting
this.statusMessage = "This meeting has ended or otherwise does not exist.<br>Please start a new meeting.";
return;
this.bigBlueButtonApi
.getJoinUrl(
this.displayName,
this.userId,
this.avatarUrl,
this.meetingId,
this.meetingPassword
)
.then((response) => {
console.log("The response");
console.log(response);
if ("errorCode" in response) {
// This is an instance of ApiError
if (response.errorCode === "UNKNOWN_MEETING_ID") {
// This meeting ID is invalid.
// Inform the user that they should try and start a new meeting
this.statusMessage =
"This meeting has ended or otherwise does not exist.<br>Please start a new meeting.";
return;
}
if (response.errorCode === "MEETING_HAS_ENDED") {
// It's likely that everyone has left the meeting, and it's been garbage collected.
// Inform the user that they should try and start a new meeting
this.statusMessage =
"This meeting has ended.<br>Please start a new meeting.";
return;
}
// Otherwise this is a generic error
this.statusMessage = "An error occurred while loading the meeting";
}
if (response.errorCode === "MEETING_HAS_ENDED") {
// It's likely that everyone has left the meeting, and it's been garbage collected.
// Inform the user that they should try and start a new meeting
this.statusMessage = "This meeting has ended.<br>Please start a new meeting.";
return;
}
// Otherwise this is a generic error
this.statusMessage = "An error occurred while loading the meeting";
}
// Retrieve and embed the meeting URL
const joinUrl = (response as FE_BigBlueButtonCreateAndJoinMeeting).url;
this.embedMeetingWithUrl(joinUrl);
});
// Retrieve and embed the meeting URL
const joinUrl = (response as FE_BigBlueButtonCreateAndJoinMeeting).url;
this.embedMeetingWithUrl(joinUrl);
});
}
// Hand Dimension a Greenlight URL and receive a translated, embeddable meeting URL in response
private joinThroughGreenlightUrl() {
console.log("BigBlueButton: joining via greenlight url:", this.conferenceUrl);
this.bigBlueButtonApi.joinMeetingWithGreenlightUrl(this.conferenceUrl, this.joinName).then((response) => {
if ("errorCode" in response) {
// This is an instance of ApiError
if (response.errorCode === "WAITING_FOR_MEETING_START") {
// The meeting hasn't started yet
this.statusMessage = "Waiting for conference to start...";
console.log(
"BigBlueButton: joining via greenlight url:",
this.conferenceUrl
);
this.bigBlueButtonApi
.joinMeetingWithGreenlightUrl(this.conferenceUrl, this.joinName)
.then((response) => {
if ("errorCode" in response) {
// This is an instance of ApiError
if (response.errorCode === "WAITING_FOR_MEETING_START") {
// The meeting hasn't started yet
this.statusMessage = "Waiting for conference to start...";
// Poll until it has
setTimeout(this.joinConference.bind(this), this.pollIntervalMillis, false);
return;
// Poll until it has
setTimeout(
this.joinConference.bind(this),
this.pollIntervalMillis,
false
);
return;
}
// Otherwise this is a generic error
this.statusMessage = "An error occurred while loading the meeting";
}
// Otherwise this is a generic error
this.statusMessage = "An error occurred while loading the meeting";
}
// Retrieve and embed the meeting URL
const joinUrl = (response as FE_BigBlueButtonJoin).url;
this.embedMeetingWithUrl(joinUrl);
});
// Retrieve and embed the meeting URL
const joinUrl = (response as FE_BigBlueButtonJoin).url;
this.embedMeetingWithUrl(joinUrl);
});
}
private embedMeetingWithUrl(url: string) {
// Hide widget-related UI
// Hide widget-related UI
this.statusMessage = null;
// Embed the return meeting URL, joining the meeting
@ -212,7 +240,8 @@ export class BigBlueButtonWidgetWrapperComponent extends CapableWidget implement
}
public ngOnDestroy() {
if (this.bigBlueButtonApiSubscription) this.bigBlueButtonApiSubscription.unsubscribe();
if (this.bigBlueButtonApiSubscription)
this.bigBlueButtonApiSubscription.unsubscribe();
}
protected onCapabilitiesSent(): void {
@ -221,5 +250,4 @@ export class BigBlueButtonWidgetWrapperComponent extends CapableWidget implement
// Don't set alwaysOnScreen until we start a meeting
ScalarWidgetApi.sendSetAlwaysOnScreen(false);
}
}

View File

@ -3,17 +3,17 @@ import { ActivatedRoute } from "@angular/router";
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
@Component({
selector: "my-gcal-widget-wrapper",
selector: "app-gcal-widget-wrapper",
templateUrl: "../fullpage-iframe/fullpage-iframe.component.html",
styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"],
})
export class GCalWidgetWrapperComponent {
public embedUrl: SafeUrl = null;
constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) {
let params: any = activatedRoute.snapshot.queryParams;
const embedUrl = "https://calendar.google.com/calendar/embed?src=" + params.calendarId;
const params: any = activatedRoute.snapshot.queryParams;
const embedUrl =
"https://calendar.google.com/calendar/embed?src=" + params.calendarId;
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(embedUrl);
}
}

View File

@ -3,16 +3,15 @@ import { ActivatedRoute } from "@angular/router";
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
@Component({
selector: "my-generic-fullscreen-widget-wrapper",
selector: "app-generic-fullscreen-widget-wrapper",
templateUrl: "../fullpage-iframe/fullpage-iframe.component.html",
styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"],
})
export class GenericFullscreenWidgetWrapperComponent {
public embedUrl: SafeUrl = null;
constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) {
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
// Note: we don't do an embeddable check (as we would in a generic wrapper)
// because the Grafana dashboard might be private.
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url);

View File

@ -4,27 +4,33 @@ import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
import { WidgetApiService } from "../../shared/services/integrations/widget-api.service";
@Component({
selector: "my-generic-widget-wrapper",
selector: "app-generic-widget-wrapper",
templateUrl: "generic.component.html",
styleUrls: ["generic.component.scss"],
})
export class GenericWidgetWrapperComponent {
public isLoading = true;
public canEmbed = false;
public embedUrl: SafeUrl = null;
constructor(widgetApi: WidgetApiService, activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) {
let params: any = activatedRoute.snapshot.queryParams;
constructor(
widgetApi: WidgetApiService,
activatedRoute: ActivatedRoute,
sanitizer: DomSanitizer
) {
const params: any = activatedRoute.snapshot.queryParams;
widgetApi.isEmbeddable(params.url).then(result => {
this.canEmbed = result.canEmbed;
this.isLoading = false;
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url);
}).catch(err => {
console.error(err);
this.canEmbed = false;
this.isLoading = false;
});
widgetApi
.isEmbeddable(params.url)
.then((result) => {
this.canEmbed = result.canEmbed;
this.isLoading = false;
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url);
})
.catch((err) => {
console.error(err);
this.canEmbed = false;
this.isLoading = false;
});
}
}

View File

@ -7,15 +7,16 @@ import { Subscription } from "rxjs/Subscription";
import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api";
import { CapableWidget } from "../capable-widget";
declare var JitsiMeetExternalAPI: any;
declare let JitsiMeetExternalAPI: any;
@Component({
selector: "my-jitsi-widget-wrapper",
selector: "app-jitsi-widget-wrapper",
templateUrl: "jitsi.component.html",
styleUrls: ["jitsi.component.scss"],
})
export class JitsiWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
export class JitsiWidgetWrapperComponent
extends CapableWidget
implements OnInit, OnDestroy {
public isJoined = false;
public toggleVideo = false;
@ -28,18 +29,21 @@ export class JitsiWidgetWrapperComponent extends CapableWidget implements OnInit
private jitsiApiObj: any;
private jitsiApiSubscription: Subscription;
constructor(activatedRoute: ActivatedRoute, private widgetApi: WidgetApiService) {
constructor(
activatedRoute: ActivatedRoute,
private widgetApi: WidgetApiService
) {
super();
this.supportsAlwaysOnScreen = true;
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
this.domain = params.domain;
this.conferenceId = params.conferenceId || params.confId;
this.displayName = params.displayName;
this.avatarUrl = params.avatarUrl;
this.userId = params.userId || params.email; // Element uses `email` when placing a conference call
this.isAudioOnly = params.isAudioOnly === 'true';
this.isAudioOnly = params.isAudioOnly === "true";
this.toggleVideo = !this.isAudioOnly;
// Set the widget ID if we have it
@ -48,47 +52,51 @@ export class JitsiWidgetWrapperComponent extends CapableWidget implements OnInit
public ngOnInit() {
super.ngOnInit();
this.widgetApi.getWidget("jitsi").then(integration => {
this.widgetApi.getWidget("jitsi").then((integration) => {
const widget = <FE_JitsiWidget>integration;
$.getScript(widget.options.scriptUrl);
if (!this.domain) {
// Always fall back to jitsi.riot.im to maintain compatibility with widgets created by Element.
this.domain = widget.options.useDomainAsDefault ? widget.options.jitsiDomain : "jitsi.riot.im";
this.domain = widget.options.useDomainAsDefault
? widget.options.jitsiDomain
: "jitsi.riot.im";
}
});
this.jitsiApiSubscription = ScalarWidgetApi.requestReceived.subscribe(request => {
if (!this.isJoined) {
return;
}
switch (request.action) {
case "audioToggle":
this.jitsiApiObj.executeCommand('toggleAudio');
break;
case "audioMute":
this.jitsiApiObj.isAudioMuted().then((muted) => {
// Toggle audio if Jitsi is not currently muted
if (!muted) {
this.jitsiApiObj.executeCommand('toggleAudio');
}
});
break;
case "audioUnmute":
this.jitsiApiObj.isAudioMuted().then((muted) => {
// Toggle audio if Jitsi is currently muted
if (muted) {
this.jitsiApiObj.executeCommand('toggleAudio');
}
});
break;
default:
// Unknown command sent
this.jitsiApiSubscription = ScalarWidgetApi.requestReceived.subscribe(
(request) => {
if (!this.isJoined) {
return;
}
}
ScalarWidgetApi.replyAcknowledge(request);
});
switch (request.action) {
case "audioToggle":
this.jitsiApiObj.executeCommand("toggleAudio");
break;
case "audioMute":
this.jitsiApiObj.isAudioMuted().then((muted) => {
// Toggle audio if Jitsi is not currently muted
if (!muted) {
this.jitsiApiObj.executeCommand("toggleAudio");
}
});
break;
case "audioUnmute":
this.jitsiApiObj.isAudioMuted().then((muted) => {
// Toggle audio if Jitsi is currently muted
if (muted) {
this.jitsiApiObj.executeCommand("toggleAudio");
}
});
break;
default:
// Unknown command sent
return;
}
ScalarWidgetApi.replyAcknowledge(request);
}
);
}
public joinConference() {
@ -107,12 +115,15 @@ export class JitsiWidgetWrapperComponent extends CapableWidget implements OnInit
SHOW_WATERMARK_FOR_GUESTS: false,
MAIN_TOOLBAR_BUTTONS: [],
VIDEO_LAYOUT_FIT: "height",
}
},
});
if (this.displayName) this.jitsiApiObj.executeCommand("displayName", this.displayName);
if (this.avatarUrl) this.jitsiApiObj.executeCommand("avatarUrl", this.avatarUrl.toString());
if (this.displayName)
this.jitsiApiObj.executeCommand("displayName", this.displayName);
if (this.avatarUrl)
this.jitsiApiObj.executeCommand("avatarUrl", this.avatarUrl.toString());
if (this.userId) this.jitsiApiObj.executeCommand("email", this.userId);
if (this.isAudioOnly === this.toggleVideo) this.jitsiApiObj.executeCommand("toggleVideo");
if (this.isAudioOnly === this.toggleVideo)
this.jitsiApiObj.executeCommand("toggleVideo");
this.jitsiApiObj.on("readyToClose", () => {
this.isJoined = false;
@ -132,5 +143,4 @@ export class JitsiWidgetWrapperComponent extends CapableWidget implements OnInit
super.onCapabilitiesSent();
ScalarWidgetApi.sendSetAlwaysOnScreen(false);
}
}

View File

@ -6,15 +6,16 @@ import { ScalarServerApiService } from "../../shared/services/scalar/scalar-serv
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "my-reauth-example-widget-wrapper",
selector: "app-reauth-example-widget-wrapper",
templateUrl: "manager-test.component.html",
styleUrls: ["manager-test.component.scss"],
})
export class ManagerTestWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
public readonly STATE_NEUTRAL = 'neutral';
public readonly STATE_OK = 'ok';
public readonly STATE_ERROR = 'error';
export class ManagerTestWidgetWrapperComponent
extends CapableWidget
implements OnInit, OnDestroy {
public readonly STATE_NEUTRAL = "neutral";
public readonly STATE_OK = "ok";
public readonly STATE_ERROR = "error";
public isBusy = true;
public isSupported = true;
@ -23,22 +24,30 @@ export class ManagerTestWidgetWrapperComponent extends CapableWidget implements
public homeserverState = this.STATE_NEUTRAL;
public message: string;
constructor(activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private changeDetector: ChangeDetectorRef,
public translate: TranslateService) {
constructor(
activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private changeDetector: ChangeDetectorRef,
public translate: TranslateService
) {
super();
this.translate = translate;
this.translate.get('Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.').subscribe((res: string) => {this.message = res});
this.translate
.get(
"Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver."
)
.subscribe((res: string) => {
this.message = res;
});
const params: any = activatedRoute.snapshot.queryParams;
ScalarWidgetApi.widgetId = params.widgetId;
}
protected onSupportedVersionsFound(): void {
super.onSupportedVersionsFound();
this.isSupported = this.doesSupportAtLeastVersion(WIDGET_API_VERSION_OPENID);
this.isSupported = this.doesSupportAtLeastVersion(
WIDGET_API_VERSION_OPENID
);
this.isBusy = false;
if (!this.isSupported) {
this.selfState = this.STATE_ERROR;
@ -50,41 +59,73 @@ export class ManagerTestWidgetWrapperComponent extends CapableWidget implements
this.selfState = this.STATE_NEUTRAL;
this.managerState = this.STATE_NEUTRAL;
this.homeserverState = this.STATE_NEUTRAL;
this.translate.get('Please accept the prompt to verify your identity.').subscribe((res: string) => {this.message = res});
this.translate
.get("Please accept the prompt to verify your identity.")
.subscribe((res: string) => {
this.message = res;
});
this.isBusy = true;
const response = await this.getOpenIdInfo();
if (response.blocked) {
this.isBusy = false;
this.selfState = this.STATE_ERROR;
this.translate.get('You have blocked this widget from verifying your identity.').subscribe((res: string) => {this.message = res});
this.translate
.get("You have blocked this widget from verifying your identity.")
.subscribe((res: string) => {
this.message = res;
});
return;
}
this.selfState = this.STATE_OK;
this.translate.get('Checking connectivity to integration manager...').subscribe((res: string) => {this.message = res});
this.translate
.get("Checking connectivity to integration manager...")
.subscribe((res: string) => {
this.message = res;
});
try {
await this.scalarApi.ping();
this.managerState = this.STATE_OK;
this.translate.get('Checking connectivity to homeserver...').subscribe((res: string) => {this.message = res});
this.translate
.get("Checking connectivity to homeserver...")
.subscribe((res: string) => {
this.message = res;
});
} catch (e) {
console.error(e);
this.isBusy = false;
this.managerState = this.STATE_ERROR;
this.translate.get('Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.').subscribe((res: string) => {this.message = res});
this.translate
.get(
"Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline."
)
.subscribe((res: string) => {
this.message = res;
});
return;
}
try {
await this.scalarApi.register(response.openId);
this.homeserverState = this.STATE_OK;
this.translate.get('You\'re all set! Click the button below to re-run the test.').subscribe((res: string) => {this.message = res});
this.translate
.get("You're all set! Click the button below to re-run the test.")
.subscribe((res: string) => {
this.message = res;
});
this.isBusy = false;
} catch (e) {
this.isBusy = false;
this.homeserverState = this.STATE_ERROR;
this.translate.get('Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver\'s documentation for how to set up federation.').subscribe((res: string) => {this.message = res});
this.translate
.get(
"Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver's documentation for how to set up federation."
)
.subscribe((res: string) => {
this.message = res;
});
}
}
}

View File

@ -8,12 +8,13 @@ import { FE_ScalarOpenIdRequestBody } from "../../shared/models/scalar-server-re
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "my-reauth-example-widget-wrapper",
selector: "app-reauth-example-widget-wrapper",
templateUrl: "reauth-example.component.html",
styleUrls: ["reauth-example.component.scss"],
})
export class ReauthExampleWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
export class ReauthExampleWidgetWrapperComponent
extends CapableWidget
implements OnInit, OnDestroy {
public busy = true; // busy until we load supported versions
public hasOpenId = false;
public userId: string;
@ -21,13 +22,19 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement
public error = false;
public stateMessage: string;
constructor(activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private changeDetector: ChangeDetectorRef,
public translate: TranslateService) {
constructor(
activatedRoute: ActivatedRoute,
private scalarApi: ScalarServerApiService,
private changeDetector: ChangeDetectorRef,
public translate: TranslateService
) {
super();
this.translate = translate;
this.translate.get('Checking client version...').subscribe((res: string) => {this.stateMessage = res});
this.translate
.get("Checking client version...")
.subscribe((res: string) => {
this.stateMessage = res;
});
const params: any = activatedRoute.snapshot.queryParams;
ScalarWidgetApi.widgetId = params.widgetId;
@ -44,7 +51,11 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement
this.error = true;
this.hasOpenId = false;
this.blocked = false;
this.translate.get('Your client is too old to use this widget, sorry').subscribe((res: string) => {this.stateMessage = res});
this.translate
.get("Your client is too old to use this widget, sorry")
.subscribe((res: string) => {
this.stateMessage = res;
});
} else {
this.busy = false;
this.error = false;
@ -60,7 +71,11 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement
this.error = false;
this.blocked = false;
this.hasOpenId = false;
this.translate.get('Please accept the prompt to verify your identity').subscribe((res: string) => {this.stateMessage = res});
this.translate
.get("Please accept the prompt to verify your identity")
.subscribe((res: string) => {
this.stateMessage = res;
});
const response = await this.getOpenIdInfo();
if (response.blocked) {

View File

@ -4,19 +4,17 @@ import * as spotifyUri from "spotify-uri";
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
@Component({
selector: "my-spotify-widget-wrapper",
selector: "app-spotify-widget-wrapper",
templateUrl: "../fullpage-iframe/fullpage-iframe.component.html",
styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"],
})
export class SpotifyWidgetWrapperComponent {
public embedUrl: SafeUrl = null;
constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) {
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
const spotifyUrl = spotifyUri.parse(params.uri);
const spotifyEmbedUrl = spotifyUri.formatEmbedURL(spotifyUrl);
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(spotifyEmbedUrl);
}
}

View File

@ -3,50 +3,53 @@ import {
state,
style,
transition,
trigger
} from '@angular/animations';
import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core";
trigger,
} from "@angular/animations";
import {
AfterViewInit,
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
} from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { CapableWidget, WIDGET_API_VERSION_OPENID } from "../capable-widget";
import { fromEvent } from 'rxjs';
import { fromEvent } from "rxjs";
import {
distinctUntilChanged,
filter,
map,
pairwise,
share,
throttleTime
} from 'rxjs/operators';
distinctUntilChanged,
filter,
map,
pairwise,
share,
throttleTime,
} from "rxjs/operators";
import { Subscription } from "rxjs/Subscription";
import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api";
import { StickerApiService } from "../../shared/services/integrations/sticker-api.service";
import { SessionStorage } from "../../shared/SessionStorage";
import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service";
import { FE_Sticker, FE_UserStickerPack } from "../../shared/models/integration";
import {
FE_Sticker,
FE_UserStickerPack,
} from "../../shared/models/integration";
import { MediaService } from "../../shared/services/media.service";
import { WIDGET_STICKER_PICKER } from "../../shared/models/widget";
@Component({
selector: "my-generic-widget-wrapper",
selector: "app-generic-widget-wrapper",
templateUrl: "sticker-picker.component.html",
styleUrls: ["sticker-picker.component.scss"],
animations: [
trigger('hideList', [
state(
'hidden',
style({ opacity: 0, transform: 'translateY(100%)' })
),
state(
'visible',
style({ opacity: 1, transform: 'translateY(0)' })
),
transition('* => *', animate('200ms ease-in'))
])
]
trigger("hideList", [
state("hidden", style({ opacity: 0, transform: "translateY(100%)" })),
state("visible", style({ opacity: 1, transform: "translateY(0)" })),
transition("* => *", animate("200ms ease-in")),
]),
],
})
export class StickerPickerWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy, AfterViewInit {
export class StickerPickerWidgetWrapperComponent
extends CapableWidget
implements OnInit, OnDestroy, AfterViewInit {
public isLoading = true;
public isListVisible = true;
public authError = false;
@ -54,15 +57,17 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
private stickerWidgetApiSubscription: Subscription;
constructor(activatedRoute: ActivatedRoute,
private media: MediaService,
private scalarApi: ScalarServerApiService,
private stickerApi: StickerApiService,
private changeDetector: ChangeDetectorRef) {
constructor(
activatedRoute: ActivatedRoute,
private media: MediaService,
private scalarApi: ScalarServerApiService,
private stickerApi: StickerApiService,
private changeDetector: ChangeDetectorRef
) {
super();
this.supportsStickers = true;
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
let token = params.scalar_token;
if (!token) token = localStorage.getItem("dim-scalar-token");
@ -85,50 +90,53 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
public ngOnInit() {
super.ngOnInit();
this.stickerWidgetApiSubscription = ScalarWidgetApi.requestReceived.subscribe(request => {
if (request.action === "visibility") {
if ((<any>request).visible) this.loadStickers();
ScalarWidgetApi.replyAcknowledge(request);
}
});
this.stickerWidgetApiSubscription =
ScalarWidgetApi.requestReceived.subscribe((request) => {
if (request.action === "visibility") {
if ((<any>request).visible) this.loadStickers();
ScalarWidgetApi.replyAcknowledge(request);
}
});
this.loadStickers();
}
public ngOnDestroy() {
super.ngOnDestroy();
if (this.stickerWidgetApiSubscription) this.stickerWidgetApiSubscription.unsubscribe();
if (this.stickerWidgetApiSubscription)
this.stickerWidgetApiSubscription.unsubscribe();
}
public ngAfterViewInit() {
const scroll$ = fromEvent(window, 'scroll').pipe(
throttleTime(10),
map(() => window.pageYOffset),
pairwise(),
map(([y1, y2]): string => (y2 < y1 ? 'up' : 'down')),
distinctUntilChanged(),
share()
const scroll$ = fromEvent(window, "scroll").pipe(
throttleTime(10),
map(() => window.pageYOffset),
pairwise(),
map(([y1, y2]): string => (y2 < y1 ? "up" : "down")),
distinctUntilChanged(),
share()
);
const scrollUp$ = scroll$.pipe(
filter(direction => direction === 'up')
);
const scrollUp$ = scroll$.pipe(filter((direction) => direction === "up"));
const scrollDown = scroll$.pipe(
filter(direction => direction === 'down')
filter((direction) => direction === "down")
);
scrollUp$.subscribe(() => (this.isListVisible = true));
scrollDown.subscribe(() => (this.isListVisible = false));
}
}
protected onSupportedVersionsFound(): void {
super.onSupportedVersionsFound();
if (this.authError && this.doesSupportAtLeastVersion(WIDGET_API_VERSION_OPENID)) {
if (
this.authError &&
this.doesSupportAtLeastVersion(WIDGET_API_VERSION_OPENID)
) {
this.isLoading = true;
this.changeDetector.detectChanges();
this.getOpenIdInfo().then(async response => {
this.getOpenIdInfo().then(async (response) => {
if (response.blocked) {
this.isLoading = false;
this.authError = true;
@ -137,8 +145,13 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
}
try {
const registerResponse = await this.scalarApi.register(response.openId);
localStorage.setItem("dim-scalar-token", registerResponse.scalar_token);
const registerResponse = await this.scalarApi.register(
response.openId
);
localStorage.setItem(
"dim-scalar-token",
registerResponse.scalar_token
);
SessionStorage.scalarToken = registerResponse.scalar_token;
this.authError = !SessionStorage.scalarToken;
this.isLoading = false;
@ -154,7 +167,12 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
}
}
public getThumbnailUrl(mxc: string, width: number, height: number, method: "crop" | "scale" = "scale"): string {
public getThumbnailUrl(
mxc: string,
width: number,
height: number,
method: "crop" | "scale" = "scale"
): string {
return this.media.getThumbnailUrl(mxc, width, height, method, true);
}
@ -165,7 +183,9 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
try {
const info = await this.scalarApi.getAccount();
SessionStorage.userId = info.user_id;
console.log("Dimension scalar_token belongs to " + SessionStorage.userId);
console.log(
"Dimension scalar_token belongs to " + SessionStorage.userId
);
} catch (e) {
console.error(e);
this.authError = true;
@ -177,8 +197,14 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
console.log("Attempting to load available stickers...");
try {
const packs = await this.stickerApi.getPacks();
this.packs = packs.filter(p => p.isSelected);
console.log("User has " + this.packs.length + "/" + packs.length + " sticker packs selected");
this.packs = packs.filter((p) => p.isSelected);
console.log(
"User has " +
this.packs.length +
"/" +
packs.length +
" sticker packs selected"
);
this.isLoading = false;
this.changeDetector.markForCheck();
} catch (e) {
@ -187,13 +213,14 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
}
public scrollHorizontal(event: WheelEvent): void {
document.getElementsByClassName('sticker-pack-list')[0].scrollLeft += event.deltaY;
document.getElementsByClassName("sticker-pack-list")[0].scrollLeft +=
event.deltaY;
event.preventDefault();
}
public scrollToPack(id: string) {
const el = document.getElementById(id);
el.scrollIntoView({behavior: 'smooth'});
el.scrollIntoView({ behavior: "smooth" });
}
public sendSticker(sticker: FE_Sticker, pack: FE_UserStickerPack) {
@ -201,6 +228,9 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
}
public openIntegrationManager() {
ScalarWidgetApi.openIntegrationManager(WIDGET_STICKER_PICKER[0], ScalarWidgetApi.widgetId);
ScalarWidgetApi.openIntegrationManager(
WIDGET_STICKER_PICKER[0],
ScalarWidgetApi.widgetId
);
}
}

View File

@ -6,32 +6,38 @@ import { ToasterService } from "angular2-toaster";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "my-terms-widget-wrapper",
selector: "app-terms-widget-wrapper",
templateUrl: "terms.component.html",
styleUrls: ["terms.component.scss"],
})
export class TermsWidgetWrapperComponent implements OnInit {
public isLoading = true;
public html: SafeHtml;
constructor(private activatedRoute: ActivatedRoute,
private sanitizer: DomSanitizer,
private toaster: ToasterService,
private widgetApi: WidgetApiService,
public translate: TranslateService) {
constructor(
private activatedRoute: ActivatedRoute,
private sanitizer: DomSanitizer,
private toaster: ToasterService,
private widgetApi: WidgetApiService,
public translate: TranslateService
) {
this.translate = translate;
}
public ngOnInit(): void {
const params: any = this.activatedRoute.snapshot.params;
this.widgetApi.getTerms(params.shortcode, params.lang, params.version).then(terms => {
this.html = this.sanitizer.bypassSecurityTrustHtml(terms.text);
this.isLoading = false;
}).catch(err => {
console.error(err);
this.translate.get('Error loading policy').subscribe((res: string) => {this.toaster.pop("error", res); });
});
this.widgetApi
.getTerms(params.shortcode, params.lang, params.version)
.then((terms) => {
this.html = this.sanitizer.bypassSecurityTrustHtml(terms.text);
this.isLoading = false;
})
.catch((err) => {
console.error(err);
this.translate.get("Error loading policy").subscribe((res: string) => {
this.toaster.pop("error", res);
});
});
}
}

View File

@ -2,20 +2,19 @@ import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import * as $ from "jquery";
declare var TradingView: any;
declare let TradingView: any;
@Component({
selector: "my-tradingview-widget-wrapper",
selector: "app-tradingview-widget-wrapper",
templateUrl: "tradingview.component.html",
styleUrls: ["tradingview.component.scss"],
})
export class TradingViewWidgetWrapperComponent implements OnInit {
private symbol: string;
private interval: string;
constructor(activatedRoute: ActivatedRoute) {
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
this.symbol = params.pair;
this.interval = params.interval;
@ -24,18 +23,18 @@ export class TradingViewWidgetWrapperComponent implements OnInit {
public ngOnInit() {
$.getScript("https://s3.tradingview.com/tv.js", () => {
const widget = new TradingView.widget({
"autosize": true,
"symbol": this.symbol,
"interval": this.interval,
"timezone": "Etc/UTC",
"theme": "Light",
"style": "1",
"locale": "en",
"toolbar_bg": "#f1f3f6",
"enable_publishing": false,
"hide_top_toolbar": true,
"hide_legend": true,
"container_id": "tradingviewContainer",
autosize: true,
symbol: this.symbol,
interval: this.interval,
timezone: "Etc/UTC",
theme: "Light",
style: "1",
locale: "en",
toolbar_bg: "#f1f3f6",
enable_publishing: false,
hide_top_toolbar: true,
hide_legend: true,
container_id: "tradingviewContainer",
});
console.log("Created widget: " + widget);
});

View File

@ -3,17 +3,15 @@ import { ActivatedRoute } from "@angular/router";
import { DomSanitizer, SafeUrl } from "@angular/platform-browser";
@Component({
selector: "my-video-widget-wrapper",
selector: "app-video-widget-wrapper",
templateUrl: "../fullpage-iframe/fullpage-iframe.component.html",
styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"],
})
export class VideoWidgetWrapperComponent {
public embedUrl: SafeUrl = null;
constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) {
let params: any = activatedRoute.snapshot.queryParams;
const params: any = activatedRoute.snapshot.queryParams;
this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url);
}
}

View File

@ -1,4 +1,3 @@
export const environment = {
production: true
};
};

View File

@ -4,14 +4,13 @@
export const environment = {
production: false
};
/*
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.