├── .browserslistrc ├── .dockerignore ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── .vscode └── settings.json ├── DEVELOPMENT.md ├── Dockerfile ├── LICENSE ├── README.md ├── angular.json ├── config ├── default.yaml └── systemd.matrix-dimension.service ├── docker-entrypoint.sh ├── docs ├── bigbluebutton.md ├── custom_stickerpacks.md ├── installing.md ├── local.md ├── notes │ ├── element_widgets.md │ ├── github.md │ └── systemd.md ├── reference │ ├── element_widget_api.md │ ├── scalar_auth.md │ ├── scalar_bot_options.md │ ├── scalar_client_api.md │ └── scalar_server_api.md └── unfederated.md ├── karma.conf.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── proxy.conf.json ├── scripts ├── convert-newlines.js └── stickerpack-to-migration.js ├── src ├── MemoryCache.ts ├── api │ ├── ApiError.ts │ ├── Webserver.ts │ ├── admin │ │ ├── AdminAppserviceService.ts │ │ ├── AdminCustomSimpleBotService.ts │ │ ├── AdminHookshotGithubService.ts │ │ ├── AdminHookshotJiraService.ts │ │ ├── AdminHookshotWebhookService.ts │ │ ├── AdminIntegrationsService.ts │ │ ├── AdminIrcService.ts │ │ ├── AdminNebService.ts │ │ ├── AdminService.ts │ │ ├── AdminSlackService.ts │ │ ├── AdminStickerService.ts │ │ ├── AdminTelegramService.ts │ │ ├── AdminTermsService.ts │ │ ├── AdminUpstreamService.ts │ │ └── AdminWebhooksService.ts │ ├── controllers │ │ ├── AccountController.ts │ │ └── TermsController.ts │ ├── dimension │ │ ├── DimensionBigBlueButtonService.ts │ │ ├── DimensionHealthService.ts │ │ ├── DimensionHookshotGithubService.ts │ │ ├── DimensionHookshotJiraService.ts │ │ ├── DimensionHookshotWebhookService.ts │ │ ├── DimensionIntegrationsService.ts │ │ ├── DimensionIrcService.ts │ │ ├── DimensionMediaService.ts │ │ ├── DimensionSlackService.ts │ │ ├── DimensionStickerService.ts │ │ ├── DimensionTelegramService.ts │ │ ├── DimensionWebhooksService.ts │ │ └── DimensionWidgetService.ts │ ├── matrix │ │ ├── MatrixAccountService.ts │ │ ├── MatrixAppServiceApiService.ts │ │ ├── MatrixTermsService.ts │ │ └── MatrixWellknownService.ts │ ├── scalar │ │ ├── ScalarService.ts │ │ └── ScalarWidgetService.ts │ └── security │ │ └── MatrixSecurity.ts ├── bridges │ ├── HookshotBridge.ts │ ├── HookshotGithubBridge.ts │ ├── HookshotJiraBridge.ts │ ├── HookshotWebhookBridge.ts │ ├── IrcBridge.ts │ ├── SlackBridge.ts │ ├── TelegramBridge.ts │ ├── WebhooksBridge.ts │ └── models │ │ ├── gitter.ts │ │ ├── hookshot.ts │ │ ├── irc.ts │ │ ├── slack.ts │ │ ├── telegram.ts │ │ └── webhooks.ts ├── config.ts ├── db │ ├── AppserviceStore.ts │ ├── BotStore.ts │ ├── BridgeStore.ts │ ├── DimensionStore.ts │ ├── NebStore.ts │ ├── ScalarStore.ts │ ├── WidgetStore.ts │ ├── migrations │ │ ├── 20171218203245-AddTables.ts │ │ ├── 20171218203245-AddWidgets.ts │ │ ├── 20171224122045-AddAppservices.ts │ │ ├── 20171224124645-AddAppserviceUsers.ts │ │ ├── 20171224140745-AddNeb.ts │ │ ├── 20180326185545-AddNebIntegrationConfig.ts │ │ ├── 20180330111645-AddWebhooks.ts │ │ ├── 20180330172445-AddBridges.ts │ │ ├── 20180330211845-AddIrcBridge.ts │ │ ├── 20180512190145-AddStickers.ts │ │ ├── 20180512232045-AddUserStickerPacks.ts │ │ ├── 20180617113345-AddLoadingArtistStickerPack.ts │ │ ├── 20180908155745-AddTelegramBridge.ts │ │ ├── 20180916014545-AddTelegramBridgeRecord.ts │ │ ├── 20181017191645-SplitTelegramPuppetProperties.ts │ │ ├── 20181019205145-AddWebhooksBridge.ts │ │ ├── 20181019205245-AddWebhookBridgeRecord.ts │ │ ├── 20181021012745-AddGitterBridge.ts │ │ ├── 20181021120545-AddGitterBridgeRecord.ts │ │ ├── 20181021144645-AddGrafanaWidget.ts │ │ ├── 20181021152145-AddTradingViewWidget.ts │ │ ├── 20181021164245-AddSpotifyWidget.ts │ │ ├── 20181022185045-AddCustomSimpleBots.ts │ │ ├── 20181024200245-AddSlackBridge.ts │ │ ├── 20181024200545-AddSlackBridgeRecord.ts │ │ ├── 20190320212945-AddTrackingRoomAliasToStickers.ts │ │ ├── 20190417231045-AddSelfBotFlagToUsers.ts │ │ ├── 20190630194345-AddTermsOfService.ts │ │ ├── 20190706154345-AddUserSignedTerms.ts │ │ ├── 20190710213945-AddUpstreamTermsCache.ts │ │ ├── 20200630165247-AddBigBlueButtonWidget.ts │ │ ├── 20201204142645-AddWhiteboardWidget.ts │ │ ├── 20210809223100-ChangeAvatarUrl.ts │ │ ├── 20210906225500-ChangeAvatarUrlForNeb.ts │ │ ├── 20211124135245-RemoveGitterRecord.ts │ │ ├── 20211125150045-AddHookshotGithubBridge.ts │ │ ├── 20211125150145-AddHookshotGithubBridgeRecord.ts │ │ ├── 20211130153845-AddHookshotJiraBridge.ts │ │ ├── 20211130153945-AddHookshotJiraBridgeRecord.ts │ │ ├── 20211202181645-AddHookshotWebhookBridge.ts │ │ ├── 20211202181745-AddHookshotWebhookBridgeRecord.ts │ │ └── 20211202183445-FixLegacyWebhooksBridgeName.ts │ └── models │ │ ├── AppService.ts │ │ ├── AppServiceUser.ts │ │ ├── BridgeRecord.ts │ │ ├── CustomSimpleBotRecord.ts │ │ ├── HookshotGithubBridgeRecord.ts │ │ ├── HookshotJiraBridgeRecord.ts │ │ ├── HookshotWebhookBridgeRecord.ts │ │ ├── IHookshotBridgeRecord.ts │ │ ├── IntegrationRecord.ts │ │ ├── IrcBridgeNetwork.ts │ │ ├── IrcBridgeRecord.ts │ │ ├── NebBotUser.ts │ │ ├── NebConfiguration.ts │ │ ├── NebIntegration.ts │ │ ├── NebIntegrationConfig.ts │ │ ├── NebNotificationUser.ts │ │ ├── SlackBridgeRecord.ts │ │ ├── Sticker.ts │ │ ├── StickerPack.ts │ │ ├── TelegramBridgeRecord.ts │ │ ├── TermsRecord.ts │ │ ├── TermsSignedRecord.ts │ │ ├── TermsTextRecord.ts │ │ ├── TermsUpstreamRecord.ts │ │ ├── Upstream.ts │ │ ├── User.ts │ │ ├── UserScalarToken.ts │ │ ├── UserStickerPack.ts │ │ ├── Webhook.ts │ │ ├── WebhookBridgeRecord.ts │ │ └── WidgetRecord.ts ├── index.ts ├── integrations │ ├── Bridge.ts │ ├── ComplexBot.ts │ ├── Integration.ts │ ├── SimpleBot.ts │ └── Widget.ts ├── matrix │ ├── MatrixAppserviceClient.ts │ ├── MatrixLiteClient.ts │ ├── MatrixOpenIdClient.ts │ ├── MatrixStickerBot.ts │ └── helpers.ts ├── models │ ├── MatrixEvent.ts │ ├── ModularResponses.ts │ ├── OpenId.ts │ ├── ScalarResponses.ts │ ├── Widget.ts │ ├── WidgetResponses.ts │ └── neb.ts ├── neb │ ├── NebClient.ts │ ├── NebProxy.ts │ └── models │ │ ├── client.ts │ │ └── service.ts ├── scalar │ └── ScalarClient.ts ├── utils │ ├── LicenseMap.ts │ ├── StickerpackMetadataDownloader.ts │ ├── TelegramBot.ts │ ├── common-constants.ts │ └── hashing.ts └── version.ts ├── tsconfig.app.json ├── tsconfig.backend.json ├── tsconfig.json ├── tsconfig.spec.json └── web ├── app ├── admin │ ├── admin.component.html │ ├── admin.component.scss │ ├── admin.component.ts │ ├── bridges │ │ ├── bridges.component.html │ │ ├── bridges.component.scss │ │ ├── bridges.component.ts │ │ ├── hookshot-github │ │ │ ├── hookshot-github.component.html │ │ │ ├── hookshot-github.component.scss │ │ │ ├── hookshot-github.component.ts │ │ │ └── manage-selfhosted │ │ │ │ ├── manage-selfhosted.component.html │ │ │ │ ├── manage-selfhosted.component.scss │ │ │ │ └── manage-selfhosted.component.ts │ │ ├── hookshot-jira │ │ │ ├── hookshot-jira.component.html │ │ │ ├── hookshot-jira.component.scss │ │ │ ├── hookshot-jira.component.ts │ │ │ └── manage-selfhosted │ │ │ │ ├── manage-selfhosted.component.html │ │ │ │ ├── manage-selfhosted.component.scss │ │ │ │ └── manage-selfhosted.component.ts │ │ ├── hookshot-webhook │ │ │ ├── hookshot-webhook.component.html │ │ │ ├── hookshot-webhook.component.scss │ │ │ ├── hookshot-webhook.component.ts │ │ │ └── manage-selfhosted │ │ │ │ ├── manage-selfhosted.component.html │ │ │ │ ├── manage-selfhosted.component.scss │ │ │ │ └── manage-selfhosted.component.ts │ │ ├── irc │ │ │ ├── add-selfhosted │ │ │ │ ├── add-selfhosted.component.html │ │ │ │ ├── add-selfhosted.component.scss │ │ │ │ └── add-selfhosted.component.ts │ │ │ ├── irc.component.html │ │ │ ├── irc.component.scss │ │ │ ├── irc.component.ts │ │ │ └── networks │ │ │ │ ├── networks.component.html │ │ │ │ ├── networks.component.scss │ │ │ │ └── networks.component.ts │ │ ├── slack │ │ │ ├── manage-selfhosted │ │ │ │ ├── manage-selfhosted.component.html │ │ │ │ ├── manage-selfhosted.component.scss │ │ │ │ └── manage-selfhosted.component.ts │ │ │ ├── slack.component.html │ │ │ ├── slack.component.scss │ │ │ └── slack.component.ts │ │ ├── telegram │ │ │ ├── manage-selfhosted │ │ │ │ ├── manage-selfhosted.component.html │ │ │ │ ├── manage-selfhosted.component.scss │ │ │ │ └── manage-selfhosted.component.ts │ │ │ ├── telegram.component.html │ │ │ ├── telegram.component.scss │ │ │ └── telegram.component.ts │ │ └── webhooks │ │ │ ├── manage-selfhosted │ │ │ ├── manage-selfhosted.component.html │ │ │ ├── manage-selfhosted.component.scss │ │ │ └── manage-selfhosted.component.ts │ │ │ ├── webhooks.component.html │ │ │ ├── webhooks.component.scss │ │ │ └── webhooks.component.ts │ ├── custom-bots │ │ ├── add │ │ │ ├── add.component.html │ │ │ ├── add.component.scss │ │ │ └── add.component.ts │ │ ├── custom-bots.component.html │ │ ├── custom-bots.component.scss │ │ └── custom-bots.component.ts │ ├── home │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ └── logout-confirmation │ │ │ ├── logout-confirmation.component.html │ │ │ ├── logout-confirmation.component.scss │ │ │ └── logout-confirmation.component.ts │ ├── neb │ │ ├── add-selfhosted │ │ │ ├── add-selfhosted.component.html │ │ │ ├── add-selfhosted.component.scss │ │ │ └── add-selfhosted.component.ts │ │ ├── appservice-config │ │ │ ├── appservice-config.component.html │ │ │ ├── appservice-config.component.scss │ │ │ └── appservice-config.component.ts │ │ ├── config │ │ │ ├── config-context.ts │ │ │ ├── config-dialog.scss │ │ │ ├── giphy │ │ │ │ ├── giphy.component.html │ │ │ │ ├── giphy.component.scss │ │ │ │ └── giphy.component.ts │ │ │ ├── google │ │ │ │ ├── google.component.html │ │ │ │ ├── google.component.scss │ │ │ │ └── google.component.ts │ │ │ ├── guggy │ │ │ │ ├── guggy.component.html │ │ │ │ ├── guggy.component.scss │ │ │ │ └── guggy.component.ts │ │ │ └── imgur │ │ │ │ ├── imgur.component.html │ │ │ │ ├── imgur.component.scss │ │ │ │ └── imgur.component.ts │ │ ├── edit │ │ │ ├── edit.component.html │ │ │ ├── edit.component.scss │ │ │ └── edit.component.ts │ │ ├── neb.component.html │ │ ├── neb.component.scss │ │ └── neb.component.ts │ ├── sticker-packs │ │ ├── preview │ │ │ ├── preview.component.html │ │ │ ├── preview.component.scss │ │ │ └── preview.component.ts │ │ ├── sticker-packs.component.html │ │ ├── sticker-packs.component.scss │ │ └── sticker-packs.component.ts │ ├── terms │ │ ├── new-edit │ │ │ ├── new-edit.component.html │ │ │ ├── new-edit.component.scss │ │ │ ├── new-edit.component.ts │ │ │ └── publish │ │ │ │ ├── publish.component.html │ │ │ │ ├── publish.component.scss │ │ │ │ └── publish.component.ts │ │ ├── terms.component.html │ │ ├── terms.component.scss │ │ └── terms.component.ts │ └── widgets │ │ ├── config-dialog.scss │ │ ├── etherpad │ │ ├── etherpad.component.html │ │ ├── etherpad.component.scss │ │ └── etherpad.component.ts │ │ ├── jitsi │ │ ├── jitsi.component.html │ │ ├── jitsi.component.scss │ │ └── jitsi.component.ts │ │ ├── whiteboard │ │ ├── whiteboard.component.html │ │ ├── whiteboard.component.scss │ │ └── whiteboard.component.ts │ │ ├── widgets.component.html │ │ ├── widgets.component.scss │ │ └── widgets.component.ts ├── app.animations.ts ├── app.component.html ├── app.component.scss ├── app.component.ts ├── app.module.ts ├── app.routing.ts ├── configs │ ├── bridge │ │ ├── bridge.component.ts │ │ ├── config-screen │ │ │ ├── config-screen.bridge.component.html │ │ │ ├── config-screen.bridge.component.scss │ │ │ └── config-screen.bridge.component.ts │ │ ├── hookshot-github │ │ │ ├── hookshot-github.bridge.component.html │ │ │ ├── hookshot-github.bridge.component.scss │ │ │ └── hookshot-github.bridge.component.ts │ │ ├── hookshot-jira │ │ │ ├── hookshot-jira.bridge.component.html │ │ │ ├── hookshot-jira.bridge.component.scss │ │ │ └── hookshot-jira.bridge.component.ts │ │ ├── hookshot-webhook │ │ │ ├── hookshot-webhook.bridge.component.html │ │ │ ├── hookshot-webhook.bridge.component.scss │ │ │ └── hookshot-webhook.bridge.component.ts │ │ ├── irc │ │ │ ├── irc.bridge.component.html │ │ │ ├── irc.bridge.component.scss │ │ │ └── irc.bridge.component.ts │ │ ├── slack │ │ │ ├── slack.bridge.component.html │ │ │ ├── slack.bridge.component.scss │ │ │ └── slack.bridge.component.ts │ │ ├── telegram │ │ │ ├── ask-unbridge │ │ │ │ ├── ask-unbridge.component.html │ │ │ │ ├── ask-unbridge.component.scss │ │ │ │ └── ask-unbridge.component.ts │ │ │ ├── cannot-unbridge │ │ │ │ ├── cannot-unbridge.component.html │ │ │ │ ├── cannot-unbridge.component.scss │ │ │ │ └── cannot-unbridge.component.ts │ │ │ ├── telegram.bridge.component.html │ │ │ ├── telegram.bridge.component.scss │ │ │ └── telegram.bridge.component.ts │ │ └── webhooks │ │ │ ├── webhooks.bridge.component.html │ │ │ ├── webhooks.bridge.component.scss │ │ │ └── webhooks.bridge.component.ts │ ├── complex-bot │ │ ├── complex-bot.component.ts │ │ ├── config-screen │ │ │ ├── config-screen.complex-bot.component.html │ │ │ ├── config-screen.complex-bot.component.scss │ │ │ └── config-screen.complex-bot.component.ts │ │ ├── rss │ │ │ ├── rss.complex-bot.component.html │ │ │ ├── rss.complex-bot.component.scss │ │ │ └── rss.complex-bot.component.ts │ │ └── travisci │ │ │ ├── travisci.complex-bot.component.html │ │ │ ├── travisci.complex-bot.component.scss │ │ │ └── travisci.complex-bot.component.ts │ ├── stickerpicker │ │ ├── stickerpicker.component.html │ │ ├── stickerpicker.component.scss │ │ └── stickerpicker.component.ts │ └── widget │ │ ├── bigbluebutton │ │ ├── bigbluebutton.widget.component.html │ │ ├── bigbluebutton.widget.component.scss │ │ └── bigbluebutton.widget.component.ts │ │ ├── config-screen │ │ ├── config-screen.widget.component.html │ │ ├── config-screen.widget.component.scss │ │ └── config-screen.widget.component.ts │ │ ├── custom │ │ ├── custom.widget.component.html │ │ ├── custom.widget.component.scss │ │ └── custom.widget.component.ts │ │ ├── etherpad │ │ ├── etherpad.widget.component.html │ │ ├── etherpad.widget.component.scss │ │ └── etherpad.widget.component.ts │ │ ├── google-calendar │ │ ├── gcal.widget.component.html │ │ ├── gcal.widget.component.scss │ │ └── gcal.widget.component.ts │ │ ├── google-docs │ │ ├── gdoc.widget.component.html │ │ ├── gdoc.widget.component.scss │ │ └── gdoc.widget.component.ts │ │ ├── grafana │ │ ├── grafana.widget.component.html │ │ ├── grafana.widget.component.scss │ │ └── grafana.widget.component.ts │ │ ├── jitsi │ │ ├── jitsi.widget.component.html │ │ ├── jitsi.widget.component.scss │ │ └── jitsi.widget.component.ts │ │ ├── spotify │ │ ├── spotify.widget.component.html │ │ ├── spotify.widget.component.scss │ │ └── spotify.widget.component.ts │ │ ├── tradingview │ │ ├── tradingview.widget.component.html │ │ ├── tradingview.widget.component.scss │ │ └── tradingview.widget.component.ts │ │ ├── twitch │ │ ├── twitch.widget.component.html │ │ ├── twitch.widget.component.scss │ │ └── twitch.widget.component.ts │ │ ├── whiteboard │ │ ├── whiteboard.widget.component.html │ │ ├── whiteboard.widget.component.scss │ │ └── whiteboard.widget.component.ts │ │ ├── widget.component.ts │ │ └── youtube │ │ ├── youtube.widget.component.html │ │ ├── youtube.widget.component.scss │ │ └── youtube.widget.component.ts ├── element │ ├── element-home │ │ ├── home.component.html │ │ ├── home.component.scss │ │ └── home.component.ts │ ├── element.component.html │ ├── element.component.scss │ ├── element.component.ts │ └── scalar-close │ │ ├── scalar-close.component.html │ │ ├── scalar-close.component.scss │ │ └── scalar-close.component.ts ├── elements │ ├── field │ │ ├── field.component.html │ │ ├── field.component.scss │ │ └── field.component.ts │ ├── fullscreen-button │ │ ├── fullscreen-button.component.html │ │ ├── fullscreen-button.component.scss │ │ └── fullscreen-button.component.ts │ ├── ibox │ │ ├── ibox.component.html │ │ ├── ibox.component.scss │ │ └── ibox.component.ts │ └── spinner │ │ ├── spinner.component.html │ │ ├── spinner.component.scss │ │ └── spinner.component.ts ├── home │ ├── home.component.html │ ├── home.component.scss │ └── home.component.ts ├── integration-bag │ ├── integration-bag.component.html │ ├── integration-bag.component.scss │ └── integration-bag.component.ts ├── page-header │ ├── page-header.component.html │ ├── page-header.component.scss │ └── page-header.component.ts ├── shared │ ├── SessionStorage.ts │ ├── directives │ │ ├── screenshot-capable.directive.ts │ │ └── toggle-fullscreen.directive.ts │ ├── helpers │ │ └── SimpleBotController.ts │ ├── models │ │ ├── admin-responses.ts │ │ ├── dimension-responses.ts │ │ ├── hookshot_github.ts │ │ ├── hookshot_jira.ts │ │ ├── hookshot_webhook.ts │ │ ├── integration.ts │ │ ├── irc.ts │ │ ├── neb.ts │ │ ├── scalar-server-responses.ts │ │ ├── scalar-widget-actions.ts │ │ ├── server-client-responses.ts │ │ ├── slack.ts │ │ ├── telegram.ts │ │ ├── terms.ts │ │ ├── webhooks.ts │ │ └── widget.ts │ ├── registry │ │ ├── integrations.registry.ts │ │ └── locator.service.ts │ └── services │ │ ├── admin │ │ ├── admin-api.service.ts │ │ ├── admin-appservice-api.service.ts │ │ ├── admin-custom-simple-bots-api.service.ts │ │ ├── admin-hookshot-github-api.service.ts │ │ ├── admin-hookshot-jira-api.service.ts │ │ ├── admin-hookshot-webhook-api.service.ts │ │ ├── admin-integrations-api.service.ts │ │ ├── admin-irc-api.service.ts │ │ ├── admin-neb-api.service.ts │ │ ├── admin-slack-api.service.ts │ │ ├── admin-stickers-api-service.ts │ │ ├── admin-telegram-api.service.ts │ │ ├── admin-terms-api.service.ts │ │ ├── admin-upstream-api.service.ts │ │ └── admin-webhooks-api.service.ts │ │ ├── authed-api.ts │ │ ├── integrations │ │ ├── bigbluebutton-api.service.ts │ │ ├── hookshot-github-api.service.ts │ │ ├── hookshot-jira-api.service.ts │ │ ├── hookshot-webhook-api.service.ts │ │ ├── integrations-api.service.ts │ │ ├── irc-api.service.ts │ │ ├── slack-api.service.ts │ │ ├── sticker-api.service.ts │ │ ├── telegram-api.service.ts │ │ ├── webhooks-api.service.ts │ │ └── widget-api.service.ts │ │ ├── media.service.ts │ │ ├── name.service.ts │ │ └── scalar │ │ ├── scalar-client-api.service.ts │ │ ├── scalar-server-api.service.ts │ │ └── scalar-widget.api.ts └── widget-wrappers │ ├── bigbluebutton │ ├── bigbluebutton.component.html │ ├── bigbluebutton.component.scss │ └── bigbluebutton.component.ts │ ├── capable-widget.ts │ ├── fullpage-iframe │ ├── fullpage-iframe.component.html │ └── fullpage-iframe.component.scss │ ├── gcal │ └── gcal.component.ts │ ├── generic-fullscreen │ └── generic-fullscreen.component.ts │ ├── generic │ ├── generic.component.html │ ├── generic.component.scss │ └── generic.component.ts │ ├── jitsi │ ├── jitsi.component.html │ ├── jitsi.component.scss │ └── jitsi.component.ts │ ├── manager-test │ ├── manager-test.component.html │ ├── manager-test.component.scss │ └── manager-test.component.ts │ ├── reauth-example │ ├── reauth-example.component.html │ ├── reauth-example.component.scss │ └── reauth-example.component.ts │ ├── spotify │ └── spotify.component.ts │ ├── sticker-picker │ ├── sticker-picker.component.html │ ├── sticker-picker.component.scss │ └── sticker-picker.component.ts │ ├── terms │ ├── terms.component.html │ ├── terms.component.scss │ └── terms.component.ts │ ├── tradingview │ ├── tradingview.component.html │ ├── tradingview.component.scss │ └── tradingview.component.ts │ └── video │ └── video.component.ts ├── assets ├── fonts │ ├── Inter-Black.ttf │ ├── Inter-Bold.ttf │ ├── Inter-ExtraBold.ttf │ ├── Inter-ExtraLight.ttf │ ├── Inter-Light.ttf │ ├── Inter-Medium.ttf │ ├── Inter-Regular.ttf │ ├── Inter-SemiBold.ttf │ ├── Inter-Thin.ttf │ └── inter.scss ├── i18n │ ├── de.json │ ├── en.json │ └── template.json ├── img │ ├── avatars │ │ ├── bigbluebutton.png │ │ ├── custombots.png │ │ ├── customwidget.png │ │ ├── echo.png │ │ ├── etherpad.png │ │ ├── giphy.png │ │ ├── github.png │ │ ├── gitter.png │ │ ├── google.png │ │ ├── googlecalendar.png │ │ ├── googledocs.png │ │ ├── grafana.png │ │ ├── guggy.png │ │ ├── imgur.png │ │ ├── irc.png │ │ ├── jira.png │ │ ├── jitsi.png │ │ ├── rssbot.png │ │ ├── slack.png │ │ ├── spotify.png │ │ ├── telegram.png │ │ ├── tradingview.png │ │ ├── travisci.png │ │ ├── twitch.png │ │ ├── webhooks.png │ │ ├── whiteboard.png │ │ ├── wikipedia.png │ │ └── youtube.png │ ├── element │ │ ├── chevron-left.svg │ │ ├── close.svg │ │ └── cog.svg │ ├── enter-fullscreen.png │ ├── exit-fullscreen.png │ ├── infrastructure.png │ ├── logo │ │ ├── banner-sm.png │ │ ├── favicon │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── browserconfig.xml │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ ├── mstile-150x150.png │ │ │ ├── safari-pinned-tab.svg │ │ │ └── site.webmanifest │ │ └── made-for-matrix.svg │ ├── no_stickers.png │ ├── screenshot.png │ └── slack_auth_button.png └── licenses │ ├── cc_by-nc-sa_4.0.txt │ ├── cc_by-nc_4.0.txt │ ├── cc_by-sa_4.0.txt │ ├── cc_by_4.0.txt │ ├── general-imported.txt │ ├── gpl-v3.0.txt │ └── telegram-import.txt ├── environments ├── environment.prod.ts └── environment.ts ├── index.html ├── main.ts ├── polyfills.ts ├── style ├── _riot.scss ├── app.scss ├── components │ ├── bootstrap_override.scss │ ├── dialog.scss │ ├── element.scss │ ├── ibox.scss │ └── icons.scss └── themes │ ├── _themes.scss │ ├── dark.scss │ └── light.scss └── vendor.ts /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | build 5 | # don't lint nyc coverage output 6 | coverage -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | env: 5 | - NODE_ENV=development 6 | before_install: 7 | - npm i -g npm 8 | - npm i -g typescript 9 | install: 10 | - npm install 11 | script: 12 | - npm run build 13 | - npm run lint 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /config/systemd.matrix-dimension.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Integrations server for Matrix.org 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/usr/local/bin/npm run start:app 7 | WorkingDirectory=/home/matrix-dimension/git/matrix-dimension 8 | Environment=NODE_ENV=production 9 | 10 | # Restart timing 11 | Restart=always 12 | RestartSec=60 13 | 14 | # Output to syslog 15 | StandardOutput=syslog 16 | StandardError=syslog 17 | SyslogIdentifier=matrix-dimension 18 | 19 | # User & group to run service as 20 | User=matrix-dimension 21 | Group=matrix-dimension 22 | 23 | [Install] 24 | WantedBy=default.target 25 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Starting matrix-dimension" 4 | 5 | if [ -f "/data/config.yaml" ]; then 6 | cp /data/config.yaml /home/node/matrix-dimension/config/production.yaml 7 | NODE_ENV=production exec node build/app/index.js 8 | else 9 | cp /home/node/matrix-dimension/config/default.yaml /data/config.yaml 10 | echo "A default config file has been placed in the /data/ volume please review and make any required changes and start the container again" 11 | fi 12 | -------------------------------------------------------------------------------- /docs/notes/element_widgets.md: -------------------------------------------------------------------------------- 1 | # Element Widgets 2 | 3 | Element uses some special interaction with the integration manager to make for a clean user experience. 4 | 5 | 6 | ### Edit Widget button 7 | 8 | Ends up calling `$scalar_ui_url?integ_id=...&screen=...` alongside the standard parameters for the scalar token and room ID. 9 | 10 | **`screen` known values**: 11 | * `type_jitsi` 12 | * `type_etherpad` 13 | * `type_grafana` 14 | * `type_youtube` 15 | * `type_googledocs` - may be a bug? See [vector-im/riot-web#4917](https://github.com/vector-im/riot-web/issues/4917) 16 | * `type_customwidget` 17 | 18 | ### Permissions 19 | 20 | * Creators of widgets do not get prompted for permission to load 21 | * Only people with permission to add widgets can remove widgets (otherwise it just revokes permission) 22 | * Only creators of widgets can edit them 23 | -------------------------------------------------------------------------------- /docs/notes/github.md: -------------------------------------------------------------------------------- 1 | # Config dialog 2 | 3 | * Can enable bot without auth. 4 | * Can set default repo without auth. 5 | * Auth is only required for repository notifications. 6 | * Auth URL generation should use Dimension as the final redirect. Use param to indicate config dialog to open on success 7 | * Use current iframe (if possible) for auth. Avoid popups. 8 | 9 | 10 | **Note**: In-chat auth links won't work. That's [#2](https://github.com/turt2live/matrix-dimension/issues/2). -------------------------------------------------------------------------------- /docs/reference/scalar_bot_options.md: -------------------------------------------------------------------------------- 1 | # Github 2 | 3 | ``` 4 | { 5 | "origin_server_ts": 1497154926816, 6 | "sender": "@travis:t2l.io", 7 | "event_id": "$149715492632WnrSF:t2l.io", 8 | "age": 135686, 9 | "unsigned": { 10 | "age": 135686 11 | }, 12 | "state_key": "_@_neb_github:matrix.org", 13 | "content": { 14 | "github": { 15 | "default_repo": "turt2live/matrix-dimension" 16 | } 17 | }, 18 | "room_id": "!JmvocvDuPTYUfuvKgs:t2l.io", 19 | "user_id": "@travis:t2l.io", 20 | "type": "m.room.bot.options" 21 | } 22 | ``` -------------------------------------------------------------------------------- /docs/unfederated.md: -------------------------------------------------------------------------------- 1 | ## Running Dimension in a private/non-federated environment 2 | 3 | Using the Synapse documentation, start building your homeserver's configuration. Where the default 4 | configuration enables a `federation` listener, use `openid` instead. For example, your `listeners` 5 | may look something like this: 6 | ```yaml 7 | listeners: 8 | - port: 8008 9 | bind_addresses: ['::1', '127.0.0.1'] 10 | type: http 11 | x_forwarded: true 12 | resources: 13 | - names: [client, openid] 14 | compress: false 15 | ``` 16 | 17 | Afterwards, either configure your homeserver as though federation was enabled (create SRV records, for 18 | example) or make use of Dimension's `federationUrl` configuration option to point directly at the 19 | listener configured in Synapse. 20 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'postcss-scss', 3 | plugins: { 4 | 'postcss-import': {}, 5 | 'postcss-cssnext': {browsers: ['last 2 version'], warnForDuplicates: false}, 6 | 'cssnano': {zindex: false} 7 | } 8 | }; -------------------------------------------------------------------------------- /proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost:8184", 4 | "secure": false 5 | }, 6 | "/_matrix": { 7 | "target": "http://localhost:8184", 8 | "secure": false 9 | }, 10 | "/.well-known": { 11 | "target": "http://localhost:8184", 12 | "secure": false 13 | } 14 | } -------------------------------------------------------------------------------- /scripts/convert-newlines.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const util = require('util'); 3 | 4 | (async function () { 5 | if (process.argv.length !== 3) { 6 | console.error('Wrong number of arguments'); 7 | process.exit(-1); 8 | } 9 | 10 | const filePath = process.argv.pop(); 11 | 12 | const fileExists = await util.promisify(fs.exists)(filePath); 13 | 14 | if (fileExists) { 15 | const file = await fs.promises.readFile(filePath, { encoding: 'utf-8' }); 16 | await fs.promises.writeFile( 17 | filePath, 18 | file 19 | .replace(/\r\n/g, '\n') 20 | .replace(/\r/, '\n'), 21 | ); 22 | } 23 | })(); -------------------------------------------------------------------------------- /src/api/dimension/DimensionHealthService.ts: -------------------------------------------------------------------------------- 1 | import { GET, Path } from "typescript-rest"; 2 | import { LogService } from "matrix-bot-sdk"; 3 | 4 | /** 5 | * API for the health of Dimension 6 | */ 7 | @Path("/api/v1/dimension/health") 8 | export class DimensionHealthService { 9 | 10 | @GET 11 | @Path("heartbeat") 12 | public async heartbeat(): Promise { 13 | LogService.info("DimensionHealthService", "Heartbeat called"); 14 | return {}; // 200 OK 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/api/dimension/DimensionMediaService.ts: -------------------------------------------------------------------------------- 1 | import { GET, Path, PathParam, QueryParam, Return } from "typescript-rest"; 2 | import { MatrixLiteClient } from "../../matrix/MatrixLiteClient"; 3 | import config from "../../config"; 4 | 5 | /** 6 | * API for interacting with matrix media 7 | */ 8 | @Path("/api/v1/dimension/media") 9 | export class DimensionMediaService { 10 | 11 | @GET 12 | @Path("thumbnail/:serverName/:contentId") 13 | public async getThumbnail(@PathParam("serverName") serverName: string, @PathParam("contentId") contentId: string, @QueryParam("width") width: number, @QueryParam("height") height: number, @QueryParam("method") method: "scale" | "crop" = "scale", @QueryParam("animated") isAnimated = true): Promise { 14 | const client = new MatrixLiteClient(config.homeserver.accessToken); 15 | const url = await client.getThumbnailUrl(serverName, contentId, width, height, method, isAnimated); 16 | return new Return.MovedTemporarily(url); 17 | } 18 | } -------------------------------------------------------------------------------- /src/api/matrix/MatrixTermsService.ts: -------------------------------------------------------------------------------- 1 | import { Context, GET, Path, POST, Security, ServiceContext } from "typescript-rest"; 2 | import { ROLE_USER } from "../security/MatrixSecurity"; 3 | import TermsController, { ITermsResponse } from "../controllers/TermsController"; 4 | 5 | export interface SignTermsRequest { 6 | user_accepts: string[]; 7 | } 8 | 9 | /** 10 | * API for account management 11 | */ 12 | @Path("/_matrix/integrations/v1/terms") 13 | export class MatrixTermsService { 14 | 15 | @Context 16 | private context: ServiceContext; 17 | 18 | @GET 19 | @Path("") 20 | public async getAllTerms(): Promise { 21 | return new TermsController().getAvailableTerms(); 22 | } 23 | 24 | @POST 25 | @Path("") 26 | @Security(ROLE_USER) 27 | public async signTerms(request: SignTermsRequest): Promise { 28 | await new TermsController().signTermsMatching(this.context.request.user, request.user_accepts); 29 | return {}; 30 | } 31 | } -------------------------------------------------------------------------------- /src/api/matrix/MatrixWellknownService.ts: -------------------------------------------------------------------------------- 1 | import { GET, Path } from "typescript-rest"; 2 | import { URL } from "url"; 3 | import config from "../../config"; 4 | 5 | interface WellknownResponse { 6 | "m.integrations_widget": { 7 | url: string; 8 | data: { 9 | api_url: string; 10 | }; 11 | }; 12 | } 13 | 14 | /** 15 | * Serving of the .well-known file 16 | */ 17 | @Path("/.well-known/matrix") 18 | export class MatrixWellknownService { 19 | 20 | @GET 21 | @Path("integrations") 22 | public async getIntegrations(): Promise { 23 | const parsed = new URL(config.dimension.publicUrl); 24 | 25 | parsed.pathname = '/element'; 26 | const uiUrl = parsed.toString(); 27 | 28 | parsed.pathname = '/api/v1/scalar'; 29 | const apiUrl = parsed.toString(); 30 | 31 | return { 32 | "m.integrations_widget": { 33 | url: uiUrl, 34 | data: { 35 | api_url: apiUrl, 36 | }, 37 | }, 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/bridges/models/gitter.ts: -------------------------------------------------------------------------------- 1 | export interface GetBotUserIdResponse { 2 | bot_user_id: string; 3 | } 4 | 5 | export interface BridgedRoomResponse { 6 | matrix_room_id: string; 7 | remote_room_name: string; 8 | } -------------------------------------------------------------------------------- /src/bridges/models/irc.ts: -------------------------------------------------------------------------------- 1 | export interface QueryNetworksResponse { 2 | servers: { 3 | network_id: string; 4 | bot_user_id: string; 5 | desc: string; 6 | fields: { 7 | domain: string; 8 | }; 9 | }[]; 10 | } 11 | 12 | export interface ListLinksResponseItem { 13 | matrix_room_id: string; 14 | remote_room_channel: string; 15 | remote_room_server: string; 16 | } 17 | 18 | export interface ListOpsResponse { 19 | operators: string[]; 20 | } -------------------------------------------------------------------------------- /src/bridges/models/slack.ts: -------------------------------------------------------------------------------- 1 | export interface GetBotUserIdResponse { 2 | bot_user_id: string; 3 | } 4 | 5 | export interface BridgedChannelResponse { 6 | matrix_room_id: string; 7 | auth_url?: string; 8 | inbound_uri?: string; 9 | isWebhook: boolean; 10 | slack_webhook_uri?: string; 11 | status: "pending" | "ready"; 12 | slack_channel_name?: string; 13 | team_id?: string; 14 | slack_channel_id: string; 15 | } 16 | 17 | export interface TeamsResponse { 18 | teams: SlackTeam[]; 19 | } 20 | 21 | export interface SlackTeam { 22 | id: string; 23 | name: string; 24 | slack_id: string; 25 | } 26 | 27 | export interface ChannelsResponse { 28 | channels: SlackChannel[]; 29 | } 30 | 31 | export interface SlackChannel { 32 | id: string; 33 | name: string; 34 | purpose: { 35 | creator: string; 36 | last_set: number; 37 | value: string; 38 | }; 39 | topic: { 40 | creator: string; 41 | last_set: number; 42 | value: string; 43 | }; 44 | } 45 | 46 | export interface AuthUrlResponse { 47 | auth_uri: string; 48 | } -------------------------------------------------------------------------------- /src/bridges/models/telegram.ts: -------------------------------------------------------------------------------- 1 | export interface PortalInformationResponse { 2 | mxid: string; 3 | chat_id: number; 4 | peer_type: string; 5 | megagroup: boolean; 6 | username: string; 7 | title: string; 8 | about: string; 9 | can_unbridge: boolean; 10 | } 11 | 12 | export interface UserInformationResponse { 13 | mxid: string; 14 | permissions: string; 15 | telegram?: { 16 | id: number; 17 | username: string; 18 | first_name: string; 19 | last_name: string; 20 | phone: number; 21 | is_bot: boolean; 22 | }; 23 | } 24 | 25 | export interface UserChatResponse { 26 | id: number; 27 | title: string; 28 | } 29 | 30 | export interface BridgeInfoResponse { 31 | relaybot_username: string; 32 | } -------------------------------------------------------------------------------- /src/bridges/models/webhooks.ts: -------------------------------------------------------------------------------- 1 | export interface WebhookConfiguration { 2 | id: string; 3 | label: string; 4 | url: string; 5 | userId: string; 6 | roomId: string; 7 | type: "incoming"; 8 | } 9 | 10 | export interface ListWebhooksResponse extends SuccessResponse { 11 | results: WebhookConfiguration[]; 12 | } 13 | 14 | export interface WebhookResponse extends WebhookConfiguration, SuccessResponse { 15 | } 16 | 17 | export interface WebhookOptions { 18 | label: string; 19 | } 20 | 21 | export interface SuccessResponse { 22 | success: boolean; 23 | } 24 | 25 | export interface WebhookBridgeInfo { 26 | botUserId: string; 27 | } -------------------------------------------------------------------------------- /src/db/migrations/20171224122045-AddAppservices.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_appservice", { 8 | "id": {type: DataType.STRING, primaryKey: true, allowNull: false}, 9 | "hsToken": {type: DataType.STRING, allowNull: false}, 10 | "asToken": {type: DataType.STRING, allowNull: false}, 11 | "userPrefix": {type: DataType.STRING, allowNull: false}, 12 | })); 13 | }, 14 | down: (queryInterface: QueryInterface) => { 15 | return queryInterface.dropTable("dimension_appservice"); 16 | } 17 | } -------------------------------------------------------------------------------- /src/db/migrations/20171224124645-AddAppserviceUsers.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_appservice_users", { 8 | "id": {type: DataType.STRING, primaryKey: true, allowNull: false}, 9 | "appserviceId": { 10 | type: DataType.STRING, allowNull: false, 11 | references: {model: "dimension_appservice", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "accessToken": {type: DataType.STRING, allowNull: false}, 15 | "displayName": {type: DataType.STRING, allowNull: true}, 16 | "avatarUrl": {type: DataType.STRING, allowNull: true}, 17 | })); 18 | }, 19 | down: (queryInterface: QueryInterface) => { 20 | return queryInterface.dropTable("dimension_appservice_users"); 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/migrations/20180326185545-AddNebIntegrationConfig.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_neb_integration_config", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "integrationId": { 10 | type: DataType.INTEGER, allowNull: false, 11 | references: {model: "dimension_neb_integrations", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "roomId": {type: DataType.STRING, allowNull: false}, 15 | "jsonContent": {type: DataType.STRING, allowNull: false}, 16 | })); 17 | }, 18 | down: (queryInterface: QueryInterface) => { 19 | return Promise.resolve() 20 | .then(() => queryInterface.dropTable("dimension_neb_integration_config")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/migrations/20180330111645-AddWebhooks.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_webhooks", { 8 | "hookId": {type: DataType.STRING, primaryKey: true, allowNull: false}, 9 | "ownerUserId": { 10 | type: DataType.STRING, allowNull: false, 11 | references: {model: "dimension_users", key: "userId"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "purposeId": {type: DataType.STRING, allowNull: false}, 15 | "targetUrl": {type: DataType.STRING, allowNull: true}, 16 | })); 17 | }, 18 | down: (queryInterface: QueryInterface) => { 19 | return Promise.resolve() 20 | .then(() => queryInterface.dropTable("dimension_webhooks")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/migrations/20180512232045-AddUserStickerPacks.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return queryInterface.createTable("dimension_user_sticker_packs", { 7 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 8 | "packId": { 9 | type: DataType.INTEGER, allowNull: false, 10 | references: {model: "dimension_sticker_packs", key: "id"}, 11 | onUpdate: "cascade", onDelete: "cascade", 12 | }, 13 | "userId": { 14 | type: DataType.STRING, allowNull: false, 15 | references: {model: "dimension_users", key: "userId"}, 16 | onUpdate: "cascade", onDelete: "cascade", 17 | }, 18 | "isSelected": {type: DataType.BOOLEAN, allowNull: false}, 19 | }) 20 | }, 21 | down: (queryInterface: QueryInterface) => { 22 | return queryInterface.dropTable("dimension_user_sticker_packs"); 23 | } 24 | } -------------------------------------------------------------------------------- /src/db/migrations/20180916014545-AddTelegramBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "telegram", 9 | name: "Telegram Bridge", 10 | avatarUrl: "/img/avatars/telegram.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Bridges Telegram chats and channels to rooms on Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "telegram", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181017191645-SplitTelegramPuppetProperties.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.removeColumn("dimension_telegram_bridges", "allowPuppets")) 8 | .then(() => queryInterface.addColumn("dimension_telegram_bridges", "allowTgPuppets", DataType.BOOLEAN)) 9 | .then(() => queryInterface.addColumn("dimension_telegram_bridges", "allowMxPuppets", DataType.BOOLEAN)); 10 | }, 11 | down: (queryInterface: QueryInterface) => { 12 | return Promise.resolve() 13 | .then(() => queryInterface.removeColumn("dimension_telegram_bridges", "allowTgPuppets")) 14 | .then(() => queryInterface.removeColumn("dimension_telegram_bridges", "allowMxPuppets")) 15 | .then(() => queryInterface.addColumn("dimension_telegram_bridges", "allowPuppets", DataType.BOOLEAN)); 16 | } 17 | } -------------------------------------------------------------------------------- /src/db/migrations/20181019205145-AddWebhooksBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_webhook_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "sharedSecret": {type: DataType.STRING, allowNull: true}, 16 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 17 | })); 18 | }, 19 | down: (queryInterface: QueryInterface) => { 20 | return Promise.resolve() 21 | .then(() => queryInterface.dropTable("dimension_webhook_bridges")); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181019205245-AddWebhookBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "webhooks", 9 | name: "Webhook Bridge", 10 | avatarUrl: "/img/avatars/webhooks.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Slack-compatible webhooks for your room", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "webhooks", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181021012745-AddGitterBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_gitter_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 16 | })); 17 | }, 18 | down: (queryInterface: QueryInterface) => { 19 | return Promise.resolve() 20 | .then(() => queryInterface.dropTable("dimension_gitter_bridges")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/migrations/20181021120545-AddGitterBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "gitter", 9 | name: "Gitter Bridge", 10 | avatarUrl: "/img/avatars/gitter.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Bridges Gitter rooms to Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "gitter", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181021144645-AddGrafanaWidget.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_widgets", [ 7 | { 8 | type: "grafana", 9 | name: "Grafana", 10 | avatarUrl: "/img/avatars/grafana.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Embed a graph in the room", 14 | } 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_widgets", { 20 | type: "grafana", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181021152145-AddTradingViewWidget.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_widgets", [ 7 | { 8 | type: "tradingview", 9 | name: "TradingView", 10 | avatarUrl: "/img/avatars/tradingview.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Monitor your favourite cryptocurrencies", 14 | } 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_widgets", { 20 | type: "tradingview", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181021164245-AddSpotifyWidget.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_widgets", [ 7 | { 8 | type: "spotify", 9 | name: "Spotify", 10 | avatarUrl: "/img/avatars/spotify.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Share music with the room", 14 | } 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_widgets", { 20 | type: "spotify", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20181024200245-AddSlackBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_slack_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 16 | })); 17 | }, 18 | down: (queryInterface: QueryInterface) => { 19 | return Promise.resolve() 20 | .then(() => queryInterface.dropTable("dimension_slack_bridges")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/migrations/20181024200545-AddSlackBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "slack", 9 | name: "Slack Bridge", 10 | avatarUrl: "/img/avatars/slack.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Bridges Slack channels to Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "slack", 21 | })); 22 | } 23 | } -------------------------------------------------------------------------------- /src/db/migrations/20190320212945-AddTrackingRoomAliasToStickers.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.addColumn("dimension_sticker_packs", "trackingRoomAlias", { 8 | type: DataType.STRING, 9 | allowNull: true 10 | })); 11 | }, 12 | down: (queryInterface: QueryInterface) => { 13 | return Promise.resolve() 14 | .then(() => queryInterface.removeColumn("dimension_sticker_packs", "trackingRoomAlias")); 15 | } 16 | } -------------------------------------------------------------------------------- /src/db/migrations/20190417231045-AddSelfBotFlagToUsers.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.addColumn("dimension_users", "isSelfBot", { 8 | type: DataType.BOOLEAN, 9 | allowNull: false, 10 | defaultValue: false, 11 | })); 12 | }, 13 | down: (queryInterface: QueryInterface) => { 14 | return Promise.resolve() 15 | .then(() => queryInterface.removeColumn("dimension_users", "isSelfBot")); 16 | } 17 | } -------------------------------------------------------------------------------- /src/db/migrations/20190706154345-AddUserSignedTerms.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_terms_signed", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "termsId": { 10 | type: DataType.INTEGER, allowNull: false, 11 | references: {model: "dimension_terms", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "userId": { 15 | type: DataType.STRING, allowNull: false, 16 | references: {model: "dimension_users", key: "userId"}, 17 | onUpdate: "cascade", onDelete: "cascade", 18 | }, 19 | })); 20 | }, 21 | down: (queryInterface: QueryInterface) => { 22 | return Promise.resolve() 23 | .then(() => queryInterface.dropTable("dimension_terms_signed")); 24 | } 25 | } -------------------------------------------------------------------------------- /src/db/migrations/20190710213945-AddUpstreamTermsCache.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_terms_upstream", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: false, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "url": {type: DataType.STRING, allowNull: false}, 15 | })); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.dropTable("dimension_terms_upstream")); 20 | } 21 | } -------------------------------------------------------------------------------- /src/db/migrations/20200630165247-AddBigBlueButtonWidget.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_widgets", [ 7 | { 8 | type: "bigbluebutton", 9 | name: "BigBlueButton", 10 | avatarUrl: "/img/avatars/bigbluebutton.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Embed a BigBlueButton conference", 14 | } 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_widgets", { 20 | type: "bigbluebutton", 21 | })); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20201204142645-AddWhiteboardWidget.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_widgets", [ 7 | { 8 | type: "whiteboard", 9 | name: "Whiteboard", 10 | avatarUrl: "/img/avatars/whiteboard.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "A whiteboard app embedded in the room.", 14 | optionsJson: '{"defaultUrl":"https://cloud13.de/testwhiteboard/?whiteboardid=$roomId_$boardName"}', 15 | } 16 | ])); 17 | }, 18 | down: (queryInterface: QueryInterface) => { 19 | return Promise.resolve() 20 | .then(() => queryInterface.bulkDelete("dimension_widgets", { 21 | type: "whiteboard", 22 | })); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/db/migrations/20211124135245-RemoveGitterRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 7 | type: "gitter", 8 | })); 9 | }, 10 | down: (queryInterface: QueryInterface) => { 11 | return Promise.resolve() 12 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 13 | { 14 | type: "gitter", 15 | name: "Gitter Bridge", 16 | avatarUrl: "/assets/img/avatars/gitter.png", 17 | isEnabled: true, 18 | isPublic: true, 19 | description: "Bridges Gitter rooms to Matrix", 20 | }, 21 | ])); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211125150045-AddHookshotGithubBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_hookshot_github_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "sharedSecret": {type: DataType.STRING, allowNull: true}, 16 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 17 | })); 18 | }, 19 | down: (queryInterface: QueryInterface) => { 20 | return Promise.resolve() 21 | .then(() => queryInterface.dropTable("dimension_hookshot_github_bridges")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211125150145-AddHookshotGithubBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "hookshot_github", 9 | name: "Github Bridge", 10 | avatarUrl: "/assets/img/avatars/github.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Bridges Github issues to Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "hookshot_github", 21 | })); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211130153845-AddHookshotJiraBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_hookshot_jira_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "sharedSecret": {type: DataType.STRING, allowNull: true}, 16 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 17 | })); 18 | }, 19 | down: (queryInterface: QueryInterface) => { 20 | return Promise.resolve() 21 | .then(() => queryInterface.dropTable("dimension_hookshot_jira_bridges")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211130153945-AddHookshotJiraBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "hookshot_jira", 9 | name: "Jira Bridge", 10 | avatarUrl: "/assets/img/avatars/jira.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Bridges Jira issues to Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "hookshot_jira", 21 | })); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211202181645-AddHookshotWebhookBridge.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | import { DataType } from "sequelize-typescript"; 3 | 4 | export default { 5 | up: (queryInterface: QueryInterface) => { 6 | return Promise.resolve() 7 | .then(() => queryInterface.createTable("dimension_hookshot_webhook_bridges", { 8 | "id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false}, 9 | "upstreamId": { 10 | type: DataType.INTEGER, allowNull: true, 11 | references: {model: "dimension_upstreams", key: "id"}, 12 | onUpdate: "cascade", onDelete: "cascade", 13 | }, 14 | "provisionUrl": {type: DataType.STRING, allowNull: true}, 15 | "sharedSecret": {type: DataType.STRING, allowNull: true}, 16 | "isEnabled": {type: DataType.BOOLEAN, allowNull: false}, 17 | })); 18 | }, 19 | down: (queryInterface: QueryInterface) => { 20 | return Promise.resolve() 21 | .then(() => queryInterface.dropTable("dimension_hookshot_webhook_bridges")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211202181745-AddHookshotWebhookBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkInsert("dimension_bridges", [ 7 | { 8 | type: "hookshot_webhook", 9 | name: "Webhooks Bridge", 10 | avatarUrl: "/assets/img/avatars/webhooks.png", 11 | isEnabled: true, 12 | isPublic: true, 13 | description: "Webhooks to Matrix", 14 | }, 15 | ])); 16 | }, 17 | down: (queryInterface: QueryInterface) => { 18 | return Promise.resolve() 19 | .then(() => queryInterface.bulkDelete("dimension_bridges", { 20 | type: "hookshot_webhook", 21 | })); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/db/migrations/20211202183445-FixLegacyWebhooksBridgeName.ts: -------------------------------------------------------------------------------- 1 | import { QueryInterface } from "sequelize"; 2 | 3 | export default { 4 | up: (queryInterface: QueryInterface) => { 5 | return Promise.resolve() 6 | .then(() => queryInterface.bulkUpdate("dimension_bridges", { 7 | name: "Webhooks Bridge", 8 | }, { type: "webhooks" })); 9 | }, 10 | down: (queryInterface: QueryInterface) => { 11 | return Promise.resolve() 12 | .then(() => queryInterface.bulkUpdate("dimension_bridges", { 13 | name: "Webhook Bridge", 14 | }, { type: "webhooks" })); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/db/models/AppService.ts: -------------------------------------------------------------------------------- 1 | import { Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | 3 | @Table({ 4 | tableName: "dimension_appservice", 5 | underscored: false, 6 | timestamps: false, 7 | }) 8 | export default class AppService extends Model { 9 | @PrimaryKey 10 | @Column 11 | id: string; 12 | 13 | @Column 14 | hsToken: string; 15 | 16 | @Column 17 | asToken: string; 18 | 19 | @Column 20 | userPrefix: string; 21 | } -------------------------------------------------------------------------------- /src/db/models/AppServiceUser.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import AppService from "./AppService"; 3 | 4 | @Table({ 5 | tableName: "dimension_appservice_users", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class AppServiceUser extends Model { 10 | @PrimaryKey 11 | @Column 12 | id: string; 13 | 14 | @Column 15 | accessToken: string; 16 | 17 | @AllowNull 18 | @Column 19 | avatarUrl?: string; 20 | 21 | @AllowNull 22 | @Column 23 | displayName?: string; 24 | 25 | @Column 26 | @ForeignKey(() => AppService) 27 | appserviceId: string; 28 | } -------------------------------------------------------------------------------- /src/db/models/BridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import { IntegrationRecord } from "./IntegrationRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_bridges", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class BridgeRecord extends Model implements IntegrationRecord { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | type: string; 17 | 18 | @Column 19 | name: string; 20 | 21 | @Column 22 | avatarUrl: string; 23 | 24 | @Column 25 | description: string; 26 | 27 | @Column 28 | isEnabled: boolean; 29 | 30 | @Column 31 | isPublic: boolean; 32 | } -------------------------------------------------------------------------------- /src/db/models/CustomSimpleBotRecord.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import { IntegrationRecord } from "./IntegrationRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_custom_simple_bots", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class CustomSimpleBotRecord extends Model implements IntegrationRecord { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | type: string; 17 | 18 | @Column 19 | name: string; 20 | 21 | @Column 22 | avatarUrl: string; 23 | 24 | @Column 25 | description: string; 26 | 27 | @Column 28 | isEnabled: boolean; 29 | 30 | @Column 31 | isPublic: boolean; 32 | 33 | @Column 34 | userId: string; 35 | 36 | @Column 37 | accessToken: string; 38 | } -------------------------------------------------------------------------------- /src/db/models/HookshotGithubBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | import { IHookshotBridgeRecord } from "./IHookshotBridgeRecord"; 4 | 5 | @Table({ 6 | tableName: "dimension_hookshot_github_bridges", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class HookshotGithubBridgeRecord extends Model implements IHookshotBridgeRecord { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @AllowNull 17 | @Column 18 | @ForeignKey(() => Upstream) 19 | upstreamId?: number; 20 | 21 | @AllowNull 22 | @Column 23 | provisionUrl?: string; 24 | 25 | @AllowNull 26 | @Column 27 | sharedSecret?: string; 28 | 29 | @Column 30 | isEnabled: boolean; 31 | } 32 | -------------------------------------------------------------------------------- /src/db/models/HookshotJiraBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | import { IHookshotBridgeRecord } from "./IHookshotBridgeRecord"; 4 | 5 | @Table({ 6 | tableName: "dimension_hookshot_jira_bridges", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class HookshotJiraBridgeRecord extends Model implements IHookshotBridgeRecord { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @AllowNull 17 | @Column 18 | @ForeignKey(() => Upstream) 19 | upstreamId?: number; 20 | 21 | @AllowNull 22 | @Column 23 | provisionUrl?: string; 24 | 25 | @AllowNull 26 | @Column 27 | sharedSecret?: string; 28 | 29 | @Column 30 | isEnabled: boolean; 31 | } 32 | -------------------------------------------------------------------------------- /src/db/models/HookshotWebhookBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | import { IHookshotBridgeRecord } from "./IHookshotBridgeRecord"; 4 | 5 | @Table({ 6 | tableName: "dimension_hookshot_webhook_bridges", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class HookshotWebhookBridgeRecord extends Model implements IHookshotBridgeRecord { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @AllowNull 17 | @Column 18 | @ForeignKey(() => Upstream) 19 | upstreamId?: number; 20 | 21 | @AllowNull 22 | @Column 23 | provisionUrl?: string; 24 | 25 | @AllowNull 26 | @Column 27 | sharedSecret?: string; 28 | 29 | @Column 30 | isEnabled: boolean; 31 | } 32 | -------------------------------------------------------------------------------- /src/db/models/IHookshotBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | export interface IHookshotBridgeRecord { 2 | upstreamId?: number; 3 | provisionUrl?: string; 4 | sharedSecret?: string; 5 | isEnabled: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/db/models/IntegrationRecord.ts: -------------------------------------------------------------------------------- 1 | export interface IntegrationRecord { 2 | type: string; 3 | name: string; 4 | avatarUrl: string; 5 | description: string; 6 | isEnabled: boolean; 7 | isPublic: boolean; 8 | } -------------------------------------------------------------------------------- /src/db/models/IrcBridgeNetwork.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import IrcBridgeRecord from "./IrcBridgeRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_irc_bridge_networks", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class IrcBridgeNetwork extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @AllowNull 16 | @Column 17 | @ForeignKey(() => IrcBridgeRecord) 18 | bridgeId: number; 19 | 20 | @Column 21 | isEnabled: boolean; 22 | 23 | @Column 24 | bridgeNetworkId: string; // the real ID as given by /querynetworks 25 | 26 | @Column 27 | bridgeUserId: string; 28 | 29 | @Column 30 | displayName: string; 31 | 32 | @Column 33 | domain: string; 34 | } -------------------------------------------------------------------------------- /src/db/models/IrcBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | 4 | @Table({ 5 | tableName: "dimension_irc_bridges", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class IrcBridgeRecord extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @AllowNull 16 | @Column 17 | @ForeignKey(() => Upstream) 18 | upstreamId?: number; 19 | 20 | @AllowNull 21 | @Column 22 | provisionUrl?: string; 23 | 24 | @Column 25 | isEnabled: boolean; 26 | } -------------------------------------------------------------------------------- /src/db/models/NebBotUser.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import AppServiceUser from "./AppServiceUser"; 3 | import NebIntegration from "./NebIntegration"; 4 | 5 | @Table({ 6 | tableName: "dimension_neb_bot_users", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class NebBotUser extends Model { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @Column 17 | serviceId: string; 18 | 19 | @Column 20 | @ForeignKey(() => AppServiceUser) 21 | appserviceUserId: string; 22 | 23 | @Column 24 | @ForeignKey(() => NebIntegration) 25 | integrationId: number; 26 | } -------------------------------------------------------------------------------- /src/db/models/NebConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | import AppService from "./AppService"; 4 | 5 | @Table({ 6 | tableName: "dimension_neb_configurations", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class NebConfiguration extends Model { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @AllowNull 17 | @Column 18 | adminUrl?: string; 19 | 20 | @AllowNull 21 | @Column 22 | @ForeignKey(() => AppService) 23 | appserviceId?: string; 24 | 25 | @AllowNull 26 | @Column 27 | @ForeignKey(() => Upstream) 28 | upstreamId?: number; 29 | } -------------------------------------------------------------------------------- /src/db/models/NebIntegration.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import { IntegrationRecord } from "./IntegrationRecord"; 3 | import NebConfiguration from "./NebConfiguration"; 4 | 5 | @Table({ 6 | tableName: "dimension_neb_integrations", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class NebIntegration extends Model implements IntegrationRecord { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @Column 17 | type: string; 18 | 19 | @Column 20 | name: string; 21 | 22 | @Column 23 | avatarUrl: string; 24 | 25 | @Column 26 | description: string; 27 | 28 | @Column 29 | isEnabled: boolean; 30 | 31 | @Column 32 | isPublic: boolean; 33 | 34 | @Column 35 | @ForeignKey(() => NebConfiguration) 36 | nebId: number; 37 | } -------------------------------------------------------------------------------- /src/db/models/NebIntegrationConfig.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import NebIntegration from "./NebIntegration"; 3 | 4 | @Table({ 5 | tableName: "dimension_neb_integration_config", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class NebIntegrationConfig extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | @ForeignKey(() => NebIntegration) 17 | integrationId: string; 18 | 19 | @Column 20 | roomId: string; 21 | 22 | @Column 23 | jsonContent: string; 24 | } -------------------------------------------------------------------------------- /src/db/models/NebNotificationUser.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import AppServiceUser from "./AppServiceUser"; 3 | import NebIntegration from "./NebIntegration"; 4 | import User from "./User"; 5 | 6 | @Table({ 7 | tableName: "dimension_neb_notification_users", 8 | underscored: false, 9 | timestamps: false, 10 | }) 11 | export default class NebNotificationUser extends Model { 12 | @PrimaryKey 13 | @AutoIncrement 14 | @Column 15 | id: number; 16 | 17 | @Column 18 | serviceId: string; 19 | 20 | @Column 21 | @ForeignKey(() => User) 22 | ownerId: string; 23 | 24 | @Column 25 | @ForeignKey(() => AppServiceUser) 26 | appserviceUserId: string; 27 | 28 | @Column 29 | @ForeignKey(() => NebIntegration) 30 | integrationId: number; 31 | } -------------------------------------------------------------------------------- /src/db/models/SlackBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | 4 | @Table({ 5 | tableName: "dimension_slack_bridges", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class SlackBridgeRecord extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @AllowNull 16 | @Column 17 | @ForeignKey(() => Upstream) 18 | upstreamId?: number; 19 | 20 | @AllowNull 21 | @Column 22 | provisionUrl?: string; 23 | 24 | @Column 25 | isEnabled: boolean; 26 | } 27 | -------------------------------------------------------------------------------- /src/db/models/Sticker.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import StickerPack from "./StickerPack"; 3 | 4 | @Table({ 5 | tableName: "dimension_stickers", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class Sticker extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | name: string; 17 | 18 | @Column 19 | description: string; 20 | 21 | @Column 22 | imageMxc: string; 23 | 24 | @Column 25 | thumbnailMxc: string; 26 | 27 | @Column 28 | thumbnailWidth: number; 29 | 30 | @Column 31 | thumbnailHeight: number; 32 | 33 | @Column 34 | mimetype: string; 35 | 36 | @Column 37 | @ForeignKey(() => StickerPack) 38 | packId: number; 39 | } -------------------------------------------------------------------------------- /src/db/models/StickerPack.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import { IntegrationRecord } from "./IntegrationRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_sticker_packs", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class StickerPack extends Model implements IntegrationRecord { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | type: string; 17 | 18 | @Column 19 | name: string; 20 | 21 | @Column 22 | avatarUrl: string; 23 | 24 | @Column 25 | description: string; 26 | 27 | @Column 28 | isEnabled: boolean; 29 | 30 | @Column 31 | isPublic: boolean; 32 | 33 | @Column 34 | authorType: string; 35 | 36 | @Column 37 | authorReference: string; 38 | 39 | @Column 40 | authorName: string; 41 | 42 | @Column 43 | license: string; 44 | 45 | @Column 46 | licensePath: string; 47 | 48 | @AllowNull 49 | @Column 50 | trackingRoomAlias: string; 51 | } -------------------------------------------------------------------------------- /src/db/models/TelegramBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | 4 | @Table({ 5 | tableName: "dimension_telegram_bridges", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class TelegramBridgeRecord extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @AllowNull 16 | @Column 17 | @ForeignKey(() => Upstream) 18 | upstreamId?: number; 19 | 20 | @AllowNull 21 | @Column 22 | provisionUrl?: string; 23 | 24 | @AllowNull 25 | @Column 26 | sharedSecret?: string; 27 | 28 | @AllowNull 29 | @Column 30 | allowTgPuppets?: boolean; 31 | 32 | @AllowNull 33 | @Column 34 | allowMxPuppets?: boolean; 35 | 36 | @Column 37 | isEnabled: boolean; 38 | } -------------------------------------------------------------------------------- /src/db/models/TermsRecord.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, HasMany, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import TermsTextRecord from "./TermsTextRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_terms", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class TermsRecord extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | shortcode: string; 17 | 18 | @Column 19 | version: string; 20 | 21 | @HasMany(() => TermsTextRecord) 22 | texts: TermsTextRecord[]; 23 | } -------------------------------------------------------------------------------- /src/db/models/TermsSignedRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import User from "./User"; 3 | import TermsRecord from "./TermsRecord"; 4 | 5 | @Table({ 6 | tableName: "dimension_terms_signed", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class TermsSignedRecord extends Model { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @AllowNull 17 | @Column 18 | @ForeignKey(() => TermsRecord) 19 | termsId?: number; 20 | 21 | @AllowNull 22 | @Column 23 | @ForeignKey(() => User) 24 | userId?: string; 25 | } -------------------------------------------------------------------------------- /src/db/models/TermsTextRecord.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AllowNull, 3 | AutoIncrement, 4 | BelongsTo, 5 | Column, 6 | ForeignKey, 7 | Model, 8 | PrimaryKey, 9 | Table 10 | } from "sequelize-typescript"; 11 | import TermsRecord from "./TermsRecord"; 12 | 13 | @Table({ 14 | tableName: "dimension_terms_text", 15 | underscored: false, 16 | timestamps: false, 17 | }) 18 | export default class TermsTextRecord extends Model { 19 | @PrimaryKey 20 | @AutoIncrement 21 | @Column 22 | id: number; 23 | 24 | @AllowNull 25 | @Column 26 | @ForeignKey(() => TermsRecord) 27 | termsId?: number; 28 | 29 | @BelongsTo(() => TermsRecord) 30 | terms: TermsRecord; 31 | 32 | @Column 33 | language: string; 34 | 35 | @Column 36 | url: string; 37 | 38 | @Column 39 | name: string; 40 | 41 | @AllowNull 42 | @Column 43 | text?: string; 44 | } -------------------------------------------------------------------------------- /src/db/models/TermsUpstreamRecord.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AllowNull, 3 | AutoIncrement, 4 | BelongsTo, 5 | Column, 6 | ForeignKey, 7 | Model, 8 | PrimaryKey, 9 | Table 10 | } from "sequelize-typescript"; 11 | import Upstream from "./Upstream"; 12 | 13 | @Table({ 14 | tableName: "dimension_terms_upstream", 15 | underscored: false, 16 | timestamps: false, 17 | }) 18 | export default class TermsUpstreamRecord extends Model { 19 | @PrimaryKey 20 | @AutoIncrement 21 | @Column 22 | id: number; 23 | 24 | @AllowNull 25 | @Column 26 | @ForeignKey(() => Upstream) 27 | upstreamId?: number; 28 | 29 | @BelongsTo(() => Upstream) 30 | upstream: Upstream; 31 | 32 | @Column 33 | url: string; 34 | } -------------------------------------------------------------------------------- /src/db/models/Upstream.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | 3 | @Table({ 4 | tableName: "dimension_upstreams", 5 | underscored: false, 6 | timestamps: false, 7 | }) 8 | export default class Upstream extends Model { 9 | @PrimaryKey 10 | @AutoIncrement 11 | @Column 12 | id: number; 13 | 14 | @Column 15 | name: string; 16 | 17 | @Column 18 | type: string; 19 | 20 | @Column 21 | scalarUrl: string; 22 | 23 | @Column 24 | apiUrl: string; 25 | } -------------------------------------------------------------------------------- /src/db/models/User.ts: -------------------------------------------------------------------------------- 1 | import { Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | 3 | @Table({ 4 | tableName: "dimension_users", 5 | underscored: false, 6 | timestamps: false, 7 | }) 8 | export default class User extends Model { 9 | // This is really just a holding class to keep foreign keys alive 10 | 11 | @PrimaryKey 12 | @Column 13 | userId: string; 14 | 15 | @Column 16 | isSelfBot: boolean; 17 | } -------------------------------------------------------------------------------- /src/db/models/UserScalarToken.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AllowNull, 3 | AutoIncrement, 4 | BelongsTo, 5 | Column, 6 | ForeignKey, 7 | Model, 8 | PrimaryKey, 9 | Table 10 | } from "sequelize-typescript"; 11 | import User from "./User"; 12 | import Upstream from "./Upstream"; 13 | 14 | @Table({ 15 | tableName: "dimension_scalar_tokens", 16 | underscored: false, 17 | timestamps: false, 18 | }) 19 | export default class UserScalarToken extends Model { 20 | @PrimaryKey 21 | @AutoIncrement 22 | @Column 23 | id: number; 24 | 25 | @Column 26 | @ForeignKey(() => User) 27 | userId: string; 28 | 29 | @BelongsTo(() => User) 30 | user: User; 31 | 32 | @Column 33 | scalarToken: string; 34 | 35 | @Column 36 | isDimensionToken: boolean; 37 | 38 | @AllowNull 39 | @Column 40 | @ForeignKey(() => Upstream) 41 | upstreamId?: number; 42 | 43 | @BelongsTo(() => Upstream) 44 | upstream: Upstream; 45 | } -------------------------------------------------------------------------------- /src/db/models/UserStickerPack.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import StickerPack from "./StickerPack"; 3 | import User from "./User"; 4 | 5 | @Table({ 6 | tableName: "dimension_user_sticker_packs", 7 | underscored: false, 8 | timestamps: false, 9 | }) 10 | export default class UserStickerPack extends Model { 11 | @PrimaryKey 12 | @AutoIncrement 13 | @Column 14 | id: number; 15 | 16 | @Column 17 | @ForeignKey(() => StickerPack) 18 | packId: number; 19 | 20 | @Column 21 | @ForeignKey(() => User) 22 | userId: string; 23 | 24 | @Column 25 | isSelected: boolean; 26 | } -------------------------------------------------------------------------------- /src/db/models/Webhook.ts: -------------------------------------------------------------------------------- 1 | import { Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import User from "./User"; 3 | 4 | @Table({ 5 | tableName: "dimension_webhooks", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class Webhook extends Model { 10 | // This is really just a holding class to keep foreign keys alive 11 | 12 | @PrimaryKey 13 | @Column 14 | hookId: string; 15 | 16 | @Column 17 | @ForeignKey(() => User) 18 | ownerUserId: string; 19 | 20 | @Column 21 | purposeId: string; 22 | 23 | @Column 24 | targetUrl: string; 25 | } -------------------------------------------------------------------------------- /src/db/models/WebhookBridgeRecord.ts: -------------------------------------------------------------------------------- 1 | import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import Upstream from "./Upstream"; 3 | 4 | @Table({ 5 | tableName: "dimension_webhook_bridges", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class WebhookBridgeRecord extends Model { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @AllowNull 16 | @Column 17 | @ForeignKey(() => Upstream) 18 | upstreamId?: number; 19 | 20 | @AllowNull 21 | @Column 22 | provisionUrl?: string; 23 | 24 | @AllowNull 25 | @Column 26 | sharedSecret?: string; 27 | 28 | @Column 29 | isEnabled: boolean; 30 | } -------------------------------------------------------------------------------- /src/db/models/WidgetRecord.ts: -------------------------------------------------------------------------------- 1 | import { AutoIncrement, Column, Model, PrimaryKey, Table } from "sequelize-typescript"; 2 | import { IntegrationRecord } from "./IntegrationRecord"; 3 | 4 | @Table({ 5 | tableName: "dimension_widgets", 6 | underscored: false, 7 | timestamps: false, 8 | }) 9 | export default class WidgetRecord extends Model implements IntegrationRecord { 10 | @PrimaryKey 11 | @AutoIncrement 12 | @Column 13 | id: number; 14 | 15 | @Column 16 | type: string; 17 | 18 | @Column 19 | name: string; 20 | 21 | @Column 22 | avatarUrl: string; 23 | 24 | @Column 25 | description: string; 26 | 27 | @Column 28 | isEnabled: boolean; 29 | 30 | @Column 31 | isPublic: boolean; 32 | 33 | @Column 34 | optionsJson: string; 35 | } -------------------------------------------------------------------------------- /src/integrations/ComplexBot.ts: -------------------------------------------------------------------------------- 1 | import { Integration } from "./Integration"; 2 | import NebIntegration from "../db/models/NebIntegration"; 3 | 4 | export class ComplexBot extends Integration { 5 | constructor(bot: NebIntegration, public notificationUserId: string, public botUserId: string, public config: any) { 6 | super(bot); 7 | this.category = "complex-bot"; 8 | this.requirements = []; 9 | 10 | // Notification bots are technically supported in e2e rooms 11 | this.isEncryptionSupported = true; 12 | } 13 | } 14 | 15 | export interface RssBotConfiguration { 16 | feeds: { 17 | [url: string]: { 18 | addedByUserId: string; 19 | }; 20 | }; 21 | } 22 | 23 | export interface TravisCiConfiguration { 24 | webhookId: string; 25 | repos: { 26 | [repoKey: string]: { 27 | addedByUserId: string; 28 | template: string; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/integrations/SimpleBot.ts: -------------------------------------------------------------------------------- 1 | import { Integration } from "./Integration"; 2 | import { CachedSimpleBot } from "../db/BotStore"; 3 | import { IntegrationRecord } from "../db/models/IntegrationRecord"; 4 | import NebIntegration from "../db/models/NebIntegration"; 5 | 6 | export class SimpleBot extends Integration { 7 | private constructor(bot: IntegrationRecord, public userId: string) { 8 | super(bot); 9 | this.category = "bot"; 10 | this.requirements = []; 11 | 12 | // We're going to go ahead and claim that none of the bots are supported in e2e rooms 13 | this.isEncryptionSupported = false; 14 | } 15 | 16 | public static fromCached(bot: CachedSimpleBot) { 17 | delete bot.accessToken; 18 | return new SimpleBot(bot, bot.userId); 19 | } 20 | 21 | public static fromNeb(bot: NebIntegration, userId: string) { 22 | return new SimpleBot(bot, userId); 23 | } 24 | } -------------------------------------------------------------------------------- /src/integrations/Widget.ts: -------------------------------------------------------------------------------- 1 | import { Integration } from "./Integration"; 2 | import WidgetRecord from "../db/models/WidgetRecord"; 3 | 4 | export interface EtherpadWidgetOptions { 5 | defaultUrl: string; 6 | } 7 | 8 | export interface WhiteboardWidgetOptions { 9 | defaultUrl: string; 10 | } 11 | 12 | export interface JitsiWidgetOptions { 13 | jitsiDomain: string; 14 | scriptUrl: string; 15 | useDomainAsDefault: boolean; 16 | } 17 | 18 | export class Widget extends Integration { 19 | public options: any; 20 | 21 | constructor(widgetRecord: WidgetRecord) { 22 | super(widgetRecord); 23 | this.category = "widget"; 24 | this.options = widgetRecord.optionsJson ? JSON.parse(widgetRecord.optionsJson) : {}; 25 | this.requirements = [{ 26 | condition: "canSendEventTypes", 27 | argument: [{isState: true, type: "im.vector.widget"}], 28 | expectedValue: true, 29 | }]; 30 | 31 | // Technically widgets are supported in encrypted rooms, although at risk. 32 | this.isEncryptionSupported = true; 33 | } 34 | } -------------------------------------------------------------------------------- /src/matrix/MatrixOpenIdClient.ts: -------------------------------------------------------------------------------- 1 | import { doFederatedApiCall } from "./helpers"; 2 | import { OpenId } from "../models/OpenId"; 3 | 4 | export class MatrixOpenIdClient { 5 | 6 | constructor(private openId: OpenId) { 7 | } 8 | 9 | public async getUserId(): Promise { 10 | // TODO: Implement/prefer https://github.com/matrix-org/matrix-doc/issues/1115 11 | // #1115 also means this should become a client API call, not a federated one (finally) 12 | const response = await doFederatedApiCall( 13 | "GET", 14 | this.openId.matrix_server_name, 15 | "/_matrix/federation/v1/openid/userinfo", 16 | {access_token: this.openId.access_token} 17 | ); 18 | return response['sub']; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/models/MatrixEvent.ts: -------------------------------------------------------------------------------- 1 | export interface SimplifiedMatrixEvent { 2 | age: number; 3 | content: any; 4 | event_id: string; 5 | origin_server_ts: number; 6 | room_id: string; 7 | sender: string; 8 | type: string; 9 | unsigned: any; 10 | 11 | // Other keys would be stuff related to the actual event, like membership and state_key 12 | } -------------------------------------------------------------------------------- /src/models/ModularResponses.ts: -------------------------------------------------------------------------------- 1 | export interface ModularIntegrationInfoResponse { 2 | bot_user_id: string; 3 | integrations?: any[]; 4 | } 5 | 6 | export interface ModularIrcResponse { 7 | replies: { 8 | rid: string; 9 | response: T; 10 | }[]; 11 | } 12 | 13 | export interface ModularSlackResponse { 14 | replies: { 15 | rid: string; 16 | response: T; 17 | }[]; 18 | } 19 | -------------------------------------------------------------------------------- /src/models/OpenId.ts: -------------------------------------------------------------------------------- 1 | export interface OpenId { 2 | access_token: string; 3 | matrix_server_name: string; 4 | expires_in: number; 5 | token_type: 'Bearer'; 6 | } -------------------------------------------------------------------------------- /src/models/ScalarResponses.ts: -------------------------------------------------------------------------------- 1 | export interface ScalarRegisterResponse { 2 | scalar_token: string; 3 | } 4 | 5 | export interface ScalarAccountResponse { 6 | user_id: string; 7 | // credit: number; // present on scalar-web 8 | } 9 | 10 | export interface ScalarLogoutResponse { 11 | // Nothing of interest 12 | } -------------------------------------------------------------------------------- /src/models/Widget.ts: -------------------------------------------------------------------------------- 1 | export interface BigBlueButtonGetJoinUrlRequest { 2 | // The display name of the user attempting to join the meeting. 3 | // Will be combined with userId and passed to BigBlueButton. 4 | displayName: string; 5 | // The user ID of the user attempting to join the meeting. 6 | // Will be combined with displayName and passed to BigBlueButton. 7 | userId: string; 8 | // Optional. The avatar of the user attempting to join the meeting. 9 | // Will be passed to BigBlueButton. 10 | avatarUrl: string; 11 | // The ID of the meeting to join. 12 | meetingId: string; 13 | // The password to join the meeting with. 14 | meetingPassword: string; 15 | } 16 | -------------------------------------------------------------------------------- /src/models/WidgetResponses.ts: -------------------------------------------------------------------------------- 1 | export interface BigBlueButtonJoinResponse { 2 | // The meeting URL the client should load to join the meeting 3 | url: string; 4 | } 5 | 6 | export interface BigBlueButtonCreateAndJoinMeetingResponse { 7 | // The meeting URL the client should load to join the meeting 8 | url: string; 9 | } 10 | 11 | export interface BigBlueButtonWidgetResponse { 12 | widget_id: string; 13 | widget: { 14 | creatorUserId: string; 15 | id: string; 16 | type: string; 17 | waitForIframeLoad: boolean; 18 | name: string; 19 | avatar_url: string; 20 | url: string; 21 | data: { 22 | title: string; 23 | } 24 | }; 25 | layout: { 26 | container: string; 27 | index: number; 28 | width: number; 29 | height: number; 30 | }; 31 | } -------------------------------------------------------------------------------- /src/models/neb.ts: -------------------------------------------------------------------------------- 1 | import NebConfiguration from "../db/models/NebConfiguration"; 2 | import { Integration } from "../integrations/Integration"; 3 | import NebIntegration from "../db/models/NebIntegration"; 4 | 5 | export class NebConfig { 6 | public id: number; 7 | public adminUrl?: string; 8 | public appserviceId?: string; 9 | public upstreamId?: number; 10 | public integrations: Integration[]; 11 | public dbIntegrations: NebIntegration[]; 12 | 13 | public constructor(config: NebConfiguration, integrations: NebIntegration[]) { 14 | this.id = config.id; 15 | this.adminUrl = config.adminUrl; 16 | this.appserviceId = config.appserviceId; 17 | this.upstreamId = config.upstreamId; 18 | this.integrations = integrations.map(i => new Integration(i)); 19 | this.dbIntegrations = integrations; 20 | } 21 | } -------------------------------------------------------------------------------- /src/neb/models/client.ts: -------------------------------------------------------------------------------- 1 | export interface Client { 2 | UserID: string; 3 | HomeserverURL: string; 4 | AccessToken: string; 5 | Sync: boolean; 6 | AutoJoinRooms?: boolean; 7 | DisplayName?: string; 8 | } 9 | 10 | export interface ConfigureClientResponse { 11 | OldClient?: Client; 12 | NewClient: Client; 13 | } -------------------------------------------------------------------------------- /src/neb/models/service.ts: -------------------------------------------------------------------------------- 1 | export interface Service { 2 | ID: string; 3 | UserID: string; 4 | Type: string; 5 | Config: any; 6 | } 7 | 8 | export interface ConfigureServiceResponse { 9 | ID: string; 10 | Type: string; 11 | OldConfig?: any; 12 | NewConfig: any; 13 | } -------------------------------------------------------------------------------- /src/utils/LicenseMap.ts: -------------------------------------------------------------------------------- 1 | export interface License { 2 | name: string; 3 | url: string; 4 | } 5 | 6 | class _LicenseMap { 7 | public readonly LICENSE_IMPORTED = "Imported"; 8 | 9 | private map: { [shortcode: string]: string } = { 10 | "Imported": "/assets/licenses/general-imported.txt", 11 | "telegram": "/assets/licenses/telegram-imported.txt", 12 | "GPL v3.0": "/assets/licenses/gpl-v3.0.txt", 13 | "CC BY-NC-SA 4.0": "/assets/licenses/cc_by-nc-sa_4.0.txt", 14 | "CC BY-NC 4.0": "/assets/licenses/cc_by-nc_4.0.txt", 15 | "CC BY-SA 4.0": "/assets/licenses/cc_by-sa_4.0.txt", 16 | "CC BY 4.0": "/assets/licenses/cc_by_4.0.txt", 17 | }; 18 | 19 | public find(name: string): License { 20 | for (const licenseName of Object.keys(this.map)) { 21 | if (licenseName.toLowerCase() === name.toLowerCase()) { 22 | return {name: licenseName, url: this.map[licenseName]}; 23 | } 24 | } 25 | 26 | return null; 27 | } 28 | } 29 | 30 | export const LicenseMap = new _LicenseMap(); -------------------------------------------------------------------------------- /src/utils/StickerpackMetadataDownloader.ts: -------------------------------------------------------------------------------- 1 | import * as request from "request-promise"; 2 | 3 | export interface StickerpackMetadata { 4 | creatorId: string; 5 | roomId: string; 6 | roomAlias: string; 7 | } 8 | 9 | export class StickerpackMetadataDownloader { 10 | public static getMetadata(packUrl: string): Promise { 11 | return request({ 12 | uri: packUrl, 13 | headers: { 14 | 'Accept': 'application/json', 15 | }, 16 | json: true, 17 | }).then(body => { 18 | if (!body || !body["io.t2bot.dimension"]) { 19 | throw new Error("Failed to locate Dimension metadata"); 20 | } 21 | 22 | return body["io.t2bot.dimension"]; 23 | }); 24 | } 25 | } -------------------------------------------------------------------------------- /src/utils/TelegramBot.ts: -------------------------------------------------------------------------------- 1 | import config from "../config"; 2 | import * as path from "path"; 3 | import { Telegraf, Telegram } from "telegraf"; 4 | 5 | export interface TelegramStickerPack { 6 | name: string; 7 | description: string; 8 | stickers: { 9 | url: string; 10 | emoji: string; 11 | }[]; 12 | } 13 | 14 | export class TelegramBot { 15 | 16 | private bot: Telegram; 17 | 18 | constructor() { 19 | const tg = new Telegraf(config.telegram.botToken); 20 | this.bot = tg.telegram; 21 | } 22 | 23 | public async getStickerPack(packUrl: string): Promise { 24 | const set = await this.bot.getStickerSet(path.basename(packUrl)); 25 | const pack: TelegramStickerPack = { 26 | name: set.name, 27 | description: set.title, 28 | stickers: [], 29 | }; 30 | 31 | for (const tgSticker of set.stickers) { 32 | pack.stickers.push({ 33 | url: await (await this.bot.getFileLink(tgSticker.file_id)).toString(), 34 | emoji: tgSticker.emoji, 35 | }); 36 | } 37 | 38 | return pack; 39 | } 40 | } -------------------------------------------------------------------------------- /src/utils/common-constants.ts: -------------------------------------------------------------------------------- 1 | export const SCALAR_API_VERSION = "1.1"; -------------------------------------------------------------------------------- /src/utils/hashing.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from "crypto"; 2 | 3 | export function md5(text: string): string { 4 | return crypto.createHash("md5").update(text).digest('hex').toLowerCase(); 5 | } 6 | 7 | export function sha256(text: string): string { 8 | return crypto.createHash("sha256").update(text).digest('hex').toLowerCase(); 9 | } 10 | -------------------------------------------------------------------------------- /src/version.ts: -------------------------------------------------------------------------------- 1 | import * as child_process from 'child_process'; 2 | import * as readPkgUp from 'read-pkg-up'; 3 | 4 | const packageVersion = readPkgUp.sync().packageJson.version; 5 | let version = packageVersion ? "v" + packageVersion : "Unknown"; 6 | let gitHash = null; 7 | 8 | if ( 9 | process.env.NODE_ENV === "development" || 10 | process.env.TS_NODE_DEV === "true" 11 | ) { 12 | try { 13 | gitHash = child_process 14 | .execSync('git rev-parse --short HEAD') 15 | .toString().trim() 16 | } catch (error) { 17 | // The log service isn't set up by the time we require this file 18 | console.error("version", error); 19 | } 20 | } 21 | 22 | export const CURRENT_VERSION = version + (gitHash ? "-" + gitHash : ""); 23 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./web", 5 | "outDir": "./build/web", 6 | "types": ["bluebird", "body-parser", "jquery", "validator"] 7 | }, 8 | "files": [ 9 | "web/main.ts", 10 | "web/polyfills.ts" 11 | ], 12 | "include": [ 13 | "web/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.backend.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./src", 5 | "outDir": "./build/app", 6 | "module": "CommonJS", 7 | "types": ["bluebird", "body-parser", "jquery", "validator"], 8 | "allowSyntheticDefaultImports": true, 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "moduleResolution": "node", 12 | "sourceMap": false, 13 | "target": "es2015", 14 | }, 15 | "include": [ 16 | "./src/**/*" 17 | ], 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./build", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "strictNullChecks": false, // TODO: Should be fixed 9 | "noImplicitAny": false, // TODO: Should be fixed 10 | "noImplicitReturns": false, // TODO: Should be fixed 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "declaration": false, 14 | "downlevelIteration": true, 15 | "experimentalDecorators": true, 16 | "emitDecoratorMetadata": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2017", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictDomEventTypes": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictPropertyInitialization": false, 32 | "strictTemplates": true, 33 | "types" : ["node"] 34 | }, 35 | "exclude":[ 36 | "./node_modules" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": ["jasmine", "bluebird", "body-parser", "jquery", "validator"] 6 | }, 7 | "files": [ 8 | "web/test.ts", 9 | "web/polyfills.ts" 10 | ], 11 | "include": [ 12 | "web/**/*.spec.ts", 13 | "web/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /web/app/admin/admin.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
  • {{'Dashboard' | translate}}
  • 3 |
  • {{'Widgets' | translate}}
  • 4 |
  • {{'go-neb' | translate}}
  • 5 |
  • {{'Custom Bots' | translate}}
  • 6 |
  • {{'Bridges' | translate}}
  • 7 |
  • {{'Sticker Packs' | translate}}
  • 8 |
  • {{'Terms of Service' | translate}}
  • 9 |
10 | {{ version }} 11 | 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /web/app/admin/bridges/bridges.component.scss: -------------------------------------------------------------------------------- 1 | tr td:last-child { 2 | vertical-align: middle; 3 | } 4 | 5 | .appsvcConfigButton, 6 | .editButton { 7 | cursor: pointer; 8 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-github/hookshot-github.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-github/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/hookshot-github/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-jira/hookshot-jira.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-jira/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/hookshot-jira/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-webhook/hookshot-webhook.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/hookshot-webhook/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/hookshot-webhook/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/irc/irc.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/irc/networks/networks.component.scss: -------------------------------------------------------------------------------- 1 | table tr th:last-child, 2 | table tr td:last-child { 3 | text-align: center; 4 | width: 100px; 5 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/slack/slack.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/telegram/telegram.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/bridges/webhooks/webhooks.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/custom-bots/add/add.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/custom-bots/add/add.component.scss -------------------------------------------------------------------------------- /web/app/admin/custom-bots/custom-bots.component.scss: -------------------------------------------------------------------------------- 1 | tr td:last-child { 2 | vertical-align: middle; 3 | } 4 | 5 | .editButton { 6 | cursor: pointer; 7 | vertical-align: middle; 8 | } 9 | -------------------------------------------------------------------------------- /web/app/admin/home/home.component.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | padding-left: 25px; 3 | } -------------------------------------------------------------------------------- /web/app/admin/home/logout-confirmation/logout-confirmation.component.html: -------------------------------------------------------------------------------- 1 | 5 | 10 | 18 | -------------------------------------------------------------------------------- /web/app/admin/home/logout-confirmation/logout-confirmation.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/home/logout-confirmation/logout-confirmation.component.scss -------------------------------------------------------------------------------- /web/app/admin/home/logout-confirmation/logout-confirmation.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; 3 | 4 | export interface LogoutConfirmationDialogContext { 5 | } 6 | 7 | @Component({ 8 | templateUrl: "./logout-confirmation.component.html", 9 | styleUrls: ["./logout-confirmation.component.scss"], 10 | }) 11 | export class AdminLogoutConfirmationDialogComponent { 12 | 13 | constructor(public modal: NgbActiveModal) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web/app/admin/neb/add-selfhosted/add-selfhosted.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/neb/add-selfhosted/add-selfhosted.component.scss -------------------------------------------------------------------------------- /web/app/admin/neb/appservice-config/appservice-config.component.html: -------------------------------------------------------------------------------- 1 | 5 | 8 | 14 | 22 | -------------------------------------------------------------------------------- /web/app/admin/neb/appservice-config/appservice-config.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/themes/themes"; 2 | 3 | @include themifyComponent() { 4 | pre { 5 | margin-top: 10px; 6 | padding: 5px; 7 | border: 1px solid themed(appserviceConfigPreBorderColor); 8 | background-color: themed(appserviceConfigPreBgColor); 9 | } 10 | } -------------------------------------------------------------------------------- /web/app/admin/neb/config/config-context.ts: -------------------------------------------------------------------------------- 1 | import { FE_NebConfiguration } from "../../../shared/models/admin-responses"; 2 | import { FE_Integration } from "../../../shared/models/integration"; 3 | 4 | export interface NebBotConfigurationDialogContext { 5 | integration: FE_Integration; 6 | neb: FE_NebConfiguration; 7 | } -------------------------------------------------------------------------------- /web/app/admin/neb/config/config-dialog.scss: -------------------------------------------------------------------------------- 1 | .label-block { 2 | margin-bottom: 15px; 3 | } -------------------------------------------------------------------------------- /web/app/admin/neb/config/giphy/giphy.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/neb/config/giphy/giphy.component.scss -------------------------------------------------------------------------------- /web/app/admin/neb/config/google/google.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/neb/config/google/google.component.scss -------------------------------------------------------------------------------- /web/app/admin/neb/config/guggy/guggy.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/neb/config/guggy/guggy.component.scss -------------------------------------------------------------------------------- /web/app/admin/neb/config/imgur/imgur.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/neb/config/imgur/imgur.component.scss -------------------------------------------------------------------------------- /web/app/admin/neb/edit/edit.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | vertical-align: text-bottom; 4 | } -------------------------------------------------------------------------------- /web/app/admin/neb/neb.component.scss: -------------------------------------------------------------------------------- 1 | tr td:last-child { 2 | vertical-align: middle; 3 | } 4 | 5 | .appsvcConfigButton, 6 | .editButton { 7 | cursor: pointer; 8 | } -------------------------------------------------------------------------------- /web/app/admin/sticker-packs/preview/preview.component.html: -------------------------------------------------------------------------------- 1 | 5 | 14 | 17 | -------------------------------------------------------------------------------- /web/app/admin/sticker-packs/preview/preview.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/themes/themes"; 2 | 3 | @include themifyComponent() { 4 | .sticker { 5 | margin: 20px; 6 | padding: 5px; 7 | background-color: themed(stickerPreviewBgColor); 8 | 9 | .caption { 10 | display: inline-block; 11 | vertical-align: middle; 12 | margin-left: 20px; 13 | 14 | .name { 15 | font-size: 1.1em; 16 | font-weight: bold; 17 | display: block; 18 | } 19 | 20 | .description { 21 | color: themed(stickerPreviewFgColor); 22 | display: block; 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /web/app/admin/sticker-packs/preview/preview.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { FE_StickerPack } from "../../../shared/models/integration"; 3 | import { MediaService } from "../../../shared/services/media.service"; 4 | import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; 5 | 6 | export class StickerPackPreviewMoadlInstance { 7 | public pack: FE_StickerPack; 8 | } 9 | 10 | @Component({ 11 | templateUrl: "./preview.component.html", 12 | styleUrls: ["./preview.component.scss"], 13 | }) 14 | export class AdminStickerPackPreviewComponent { 15 | 16 | pack: FE_StickerPack; 17 | 18 | constructor(public modal: NgbActiveModal, private media: MediaService) { 19 | 20 | } 21 | 22 | public getThumbnailUrl(mxc: string, width: number, height: number, method: "crop" | "scale" = "scale"): string { 23 | return this.media.getThumbnailUrl(mxc, width, height, method, true); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /web/app/admin/sticker-packs/sticker-packs.component.scss: -------------------------------------------------------------------------------- 1 | tr td:last-child { 2 | vertical-align: middle; 3 | } 4 | 5 | .previewButton { 6 | cursor: pointer; 7 | vertical-align: middle; 8 | } 9 | 10 | .removeButton { 11 | cursor: pointer; 12 | vertical-align: middle; 13 | } 14 | 15 | .telegram-import { 16 | margin-bottom: 15px; 17 | } 18 | -------------------------------------------------------------------------------- /web/app/admin/terms/new-edit/new-edit.component.scss: -------------------------------------------------------------------------------- 1 | .buttons button { 2 | margin-right: 5px; 3 | } 4 | 5 | .buttons select { 6 | max-width: 200px; 7 | margin-bottom: 5px; 8 | } -------------------------------------------------------------------------------- /web/app/admin/terms/new-edit/publish/publish.component.html: -------------------------------------------------------------------------------- 1 | 5 | 12 | 20 | -------------------------------------------------------------------------------- /web/app/admin/terms/new-edit/publish/publish.component.scss: -------------------------------------------------------------------------------- 1 | button { 2 | margin-right: 5px; 3 | } -------------------------------------------------------------------------------- /web/app/admin/terms/new-edit/publish/publish.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ToasterService } from "angular2-toaster"; 3 | import { TranslateService } from "@ngx-translate/core"; 4 | import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; 5 | 6 | export interface AdminTermsNewEditPublishDialogContext { 7 | } 8 | 9 | @Component({ 10 | templateUrl: "./publish.component.html", 11 | styleUrls: ["./publish.component.scss"], 12 | }) 13 | export class AdminTermsNewEditPublishDialogComponent { 14 | 15 | public version: string; 16 | 17 | constructor(public modal: NgbActiveModal, private toaster: ToasterService, public translate: TranslateService) { 18 | } 19 | 20 | public publish() { 21 | if (!this.version || !this.version.trim()) { 22 | this.translate.get('Please enter a version number').subscribe((res: string) => { 23 | this.toaster.pop("warning", res); 24 | }); 25 | return; 26 | } 27 | this.modal.close(this.version); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /web/app/admin/terms/terms.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /web/app/admin/widgets/config-dialog.scss: -------------------------------------------------------------------------------- 1 | .label-block { 2 | margin-bottom: 15px; 3 | } -------------------------------------------------------------------------------- /web/app/admin/widgets/etherpad/etherpad.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/widgets/etherpad/etherpad.component.scss -------------------------------------------------------------------------------- /web/app/admin/widgets/jitsi/jitsi.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/widgets/jitsi/jitsi.component.scss -------------------------------------------------------------------------------- /web/app/admin/widgets/whiteboard/whiteboard.component.html: -------------------------------------------------------------------------------- 1 | 5 | 14 | -------------------------------------------------------------------------------- /web/app/admin/widgets/whiteboard/whiteboard.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/admin/widgets/whiteboard/whiteboard.component.scss -------------------------------------------------------------------------------- /web/app/admin/widgets/widgets.component.scss: -------------------------------------------------------------------------------- 1 | .editButton { 2 | cursor: pointer; 3 | vertical-align: text-bottom; 4 | } 5 | 6 | tr td:last-child { 7 | vertical-align: middle; 8 | } -------------------------------------------------------------------------------- /web/app/app.animations.ts: -------------------------------------------------------------------------------- 1 | import { animate, style, transition, trigger } from "@angular/animations"; 2 | 3 | export const ANIMATION_FADE_IN_NOT_OUT = 4 | trigger('fadeInNotOutAnimation', [ 5 | transition(':enter', [ 6 | style({opacity: 0}), 7 | animate('200ms', style({opacity: 1})), 8 | ]), 9 | // transition(':leave', [ 10 | // style({opacity: 1}), 11 | // animate('100ms', style({opacity: 0})), 12 | // ]), 13 | ]); -------------------------------------------------------------------------------- /web/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /web/app/app.component.scss: -------------------------------------------------------------------------------- 1 | // styles applied on :host are applied on the current component, "app" in this case 2 | :host { 3 | display: block; 4 | } 5 | 6 | main { 7 | font-family: 'Inter', Arial, sans-serif; 8 | display: block; 9 | } 10 | -------------------------------------------------------------------------------- /web/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import "../style/app.scss"; 3 | import { TranslateService } from "@ngx-translate/core"; 4 | import { HttpClient } from "@angular/common/http"; 5 | 6 | @Component({ 7 | selector: "my-app", // 8 | templateUrl: "./app.component.html", 9 | styleUrls: ["./app.component.scss"], 10 | }) 11 | export class AppComponent { 12 | constructor(public translate: TranslateService, public http: HttpClient) { 13 | translate.addLangs(["en", "de"]); 14 | translate.setDefaultLang("en"); 15 | if (navigator.language === "de") { 16 | translate.use("de"); 17 | } else { 18 | translate.use("en"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/app/configs/bridge/config-screen/config-screen.bridge.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
-------------------------------------------------------------------------------- /web/app/configs/bridge/config-screen/config-screen.bridge.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/bridge/config-screen/config-screen.bridge.component.scss -------------------------------------------------------------------------------- /web/app/configs/bridge/config-screen/config-screen.bridge.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ContentChild, Input, TemplateRef } from "@angular/core"; 2 | import { BridgeComponent } from "../bridge.component"; 3 | 4 | @Component({ 5 | selector: "my-bridge-config", 6 | templateUrl: "config-screen.bridge.component.html", 7 | styleUrls: ["config-screen.bridge.component.scss"], 8 | }) 9 | export class ConfigScreenBridgeComponent { 10 | @Input() bridgeComponent: BridgeComponent; 11 | @ContentChild(TemplateRef, { static: false }) 12 | bridgeParamsTemplate: TemplateRef; 13 | 14 | constructor() {} 15 | } 16 | -------------------------------------------------------------------------------- /web/app/configs/bridge/hookshot-github/hookshot-github.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /web/app/configs/bridge/hookshot-jira/hookshot-jira.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /web/app/configs/bridge/hookshot-webhook/hookshot-webhook.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .webhook-url { 2 | word-break: break-word; 3 | } -------------------------------------------------------------------------------- /web/app/configs/bridge/irc/irc.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } -------------------------------------------------------------------------------- /web/app/configs/bridge/slack/slack.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } 5 | 6 | .slack-auth-button { 7 | width: 170px; 8 | height: 40px; 9 | } -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/ask-unbridge/ask-unbridge.component.html: -------------------------------------------------------------------------------- 1 | 5 | 8 | 16 | -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/ask-unbridge/ask-unbridge.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/bridge/telegram/ask-unbridge/ask-unbridge.component.scss -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/ask-unbridge/ask-unbridge.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; 3 | 4 | export interface AskUnbridgeDialogContext { 5 | } 6 | 7 | @Component({ 8 | templateUrl: "./ask-unbridge.component.html", 9 | styleUrls: ["./ask-unbridge.component.scss"], 10 | }) 11 | export class TelegramAskUnbridgeComponent { 12 | 13 | constructor(public modal: NgbActiveModal) { 14 | } 15 | 16 | public unbridgeAndContinue(): void { 17 | this.modal.close({unbridge: true}); 18 | } 19 | 20 | public cancel(): void { 21 | this.modal.close({unbridge: false}); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/cannot-unbridge/cannot-unbridge.component.html: -------------------------------------------------------------------------------- 1 | 5 | 8 | 13 | -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/cannot-unbridge/cannot-unbridge.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/bridge/telegram/cannot-unbridge/cannot-unbridge.component.scss -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/cannot-unbridge/cannot-unbridge.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; 3 | 4 | export interface CannotUnbridgeDialogContext { 5 | } 6 | 7 | @Component({ 8 | templateUrl: "./cannot-unbridge.component.html", 9 | styleUrls: ["./cannot-unbridge.component.scss"], 10 | }) 11 | export class TelegramCannotUnbridgeComponent { 12 | 13 | constructor(public modal: NgbActiveModal) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web/app/configs/bridge/telegram/telegram.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } -------------------------------------------------------------------------------- /web/app/configs/bridge/webhooks/webhooks.bridge.component.scss: -------------------------------------------------------------------------------- 1 | .webhook-url { 2 | word-break: break-word; 3 | } -------------------------------------------------------------------------------- /web/app/configs/complex-bot/config-screen/config-screen.complex-bot.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
-------------------------------------------------------------------------------- /web/app/configs/complex-bot/config-screen/config-screen.complex-bot.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/complex-bot/config-screen/config-screen.complex-bot.component.scss -------------------------------------------------------------------------------- /web/app/configs/complex-bot/config-screen/config-screen.complex-bot.component.ts: -------------------------------------------------------------------------------- 1 | import { ComplexBotComponent } from "../complex-bot.component"; 2 | import { Component, ContentChild, Input, TemplateRef } from "@angular/core"; 3 | 4 | @Component({ 5 | selector: "my-complex-bot-config", 6 | templateUrl: "config-screen.complex-bot.component.html", 7 | styleUrls: ["config-screen.complex-bot.component.scss"], 8 | }) 9 | export class ConfigScreenComplexBotComponent { 10 | @Input() botComponent: ComplexBotComponent; 11 | @ContentChild(TemplateRef, { static: false }) 12 | botParamsTemplate: TemplateRef; 13 | 14 | constructor() {} 15 | } 16 | -------------------------------------------------------------------------------- /web/app/configs/complex-bot/rss/rss.complex-bot.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } -------------------------------------------------------------------------------- /web/app/configs/complex-bot/travisci/travisci.complex-bot.component.scss: -------------------------------------------------------------------------------- 1 | .actions-col { 2 | width: 120px; 3 | text-align: center; 4 | } 5 | 6 | .repo-template { 7 | white-space: nowrap; // Force scrollbars 8 | width: 100%; 9 | } -------------------------------------------------------------------------------- /web/app/configs/stickerpicker/stickerpicker.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/themes/themes"; 2 | 3 | @include themifyComponent() { 4 | .pack { 5 | display: flex; 6 | margin: 20px; 7 | padding: 5px; 8 | background-color: themed(stickerpackBgColor); 9 | color: themed(stickerpackFgColor); 10 | 11 | .caption { 12 | flex: 1; 13 | margin-left: 20px; 14 | padding-top: 20px; 15 | 16 | .name { 17 | font-size: 1.1em; 18 | font-weight: bold; 19 | display: block; 20 | } 21 | 22 | .description { 23 | color: themed(stickerpackDescriptionColor); 24 | display: block; 25 | } 26 | 27 | .toggle-switch { 28 | margin-top: 20px; 29 | margin-right: 10px; 30 | float: right; 31 | } 32 | 33 | .author, .license { 34 | font-size: 0.8em; 35 | color: themed(stickerpackAuthorLicenseColor); 36 | 37 | a { 38 | color: themed(stickerpackAuthorLicenseColor); 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /web/app/configs/widget/bigbluebutton/bigbluebutton.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/bigbluebutton/bigbluebutton.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/bigbluebutton/bigbluebutton.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/config-screen/config-screen.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/config-screen/config-screen.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/config-screen/config-screen.widget.component.ts: -------------------------------------------------------------------------------- 1 | import { WidgetComponent } from "../widget.component"; 2 | import { Component, ContentChild, Input, TemplateRef } from "@angular/core"; 3 | 4 | @Component({ 5 | selector: "my-widget-config", 6 | templateUrl: "config-screen.widget.component.html", 7 | styleUrls: ["config-screen.widget.component.scss"], 8 | }) 9 | export class ConfigScreenWidgetComponent { 10 | @Input() widgetComponent: WidgetComponent; 11 | @Input() addTitle: string; 12 | @Input() editTitle: string; 13 | @ContentChild(TemplateRef, { static: false }) widgetParamsTemplate: TemplateRef; 14 | 15 | constructor() {} 16 | } 17 | -------------------------------------------------------------------------------- /web/app/configs/widget/custom/custom.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /web/app/configs/widget/custom/custom.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/custom/custom.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/custom/custom.widget.component.ts: -------------------------------------------------------------------------------- 1 | import { WidgetComponent } from "../widget.component"; 2 | import { WIDGET_CUSTOM } from "../../../shared/models/widget"; 3 | import { Component } from "@angular/core"; 4 | import { TranslateService } from "@ngx-translate/core"; 5 | 6 | @Component({ 7 | templateUrl: "custom.widget.component.html", 8 | styleUrls: ["custom.widget.component.scss"], 9 | }) 10 | export class CustomWidgetConfigComponent extends WidgetComponent { 11 | constructor(public translate: TranslateService) { 12 | super(WIDGET_CUSTOM, "Custom Widget", "generic", translate); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/etherpad/etherpad.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /web/app/configs/widget/etherpad/etherpad.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/etherpad/etherpad.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/google-calendar/gcal.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/google-calendar/gcal.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/google-calendar/gcal.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/google-docs/gdoc.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/google-docs/gdoc.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/google-docs/gdoc.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/google-docs/gdoc.widget.component.ts: -------------------------------------------------------------------------------- 1 | import { WidgetComponent } from "../widget.component"; 2 | import { WIDGET_GOOGLE_DOCS } from "../../../shared/models/widget"; 3 | import { Component } from "@angular/core"; 4 | import { TranslateService } from "@ngx-translate/core"; 5 | 6 | @Component({ 7 | templateUrl: "gdoc.widget.component.html", 8 | styleUrls: ["gdoc.widget.component.scss"], 9 | }) 10 | export class GoogleDocsWidgetConfigComponent extends WidgetComponent { 11 | constructor(public translate: TranslateService) { 12 | super(WIDGET_GOOGLE_DOCS, "Google Doc", "generic", translate , "googleDocs"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/grafana/grafana.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 |

{{'To get a URL, go to Grafana and click \'share\' on a graph.' | translate}}

8 | 14 | 20 |
21 |
22 | -------------------------------------------------------------------------------- /web/app/configs/widget/grafana/grafana.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/grafana/grafana.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/jitsi/jitsi.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/jitsi/jitsi.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/jitsi/jitsi.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/spotify/spotify.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 |

{{'Click \'share\' from your favourite playlist, artist, track, or album and paste the Spotify URI here.' | translate}}

8 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /web/app/configs/widget/spotify/spotify.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/spotify/spotify.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/tradingview/tradingview.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /web/app/configs/widget/tradingview/tradingview.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/tradingview/tradingview.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/twitch/twitch.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/twitch/twitch.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/twitch/twitch.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/whiteboard/whiteboard.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /web/app/configs/widget/whiteboard/whiteboard.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/whiteboard/whiteboard.widget.component.scss -------------------------------------------------------------------------------- /web/app/configs/widget/youtube/youtube.widget.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/app/configs/widget/youtube/youtube.widget.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/configs/widget/youtube/youtube.widget.component.scss -------------------------------------------------------------------------------- /web/app/element/element-home/home.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | @import "../../../style/themes/themes"; 3 | 4 | @include themifyComponent() { 5 | h3 { 6 | font-size: 1.12em; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /web/app/element/element.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
6 | 7 |
8 | 9 |
10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /web/app/element/element.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | .page-content { 3 | padding: 0 32px 32px; 4 | } 5 | -------------------------------------------------------------------------------- /web/app/element/element.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { SessionStorage } from "../shared/SessionStorage"; 3 | 4 | @Component({ 5 | selector: "my-element", 6 | templateUrl: "./element.component.html", 7 | styleUrls: ["./element.component.scss"], 8 | }) 9 | export class ElementComponent { 10 | constructor() {} 11 | 12 | public isAdmin(): boolean { 13 | return SessionStorage.isAdmin; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web/app/element/scalar-close/scalar-close.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | -------------------------------------------------------------------------------- /web/app/element/scalar-close/scalar-close.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/app/element/scalar-close/scalar-close.component.scss -------------------------------------------------------------------------------- /web/app/element/scalar-close/scalar-close.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service"; 3 | 4 | @Component({ 5 | selector: "my-scalar-close", 6 | templateUrl: "./scalar-close.component.html", 7 | styleUrls: ["./scalar-close.component.scss"], 8 | }) 9 | export class ScalarCloseComponent { 10 | constructor(private scalar: ScalarClientApiService) {} 11 | 12 | public closeScalar() { 13 | console.log("Closing Dimension..."); 14 | this.scalar.close(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/app/elements/field/field.component.html: -------------------------------------------------------------------------------- 1 |
2 | 12 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /web/app/elements/field/field.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, forwardRef, Input, Output } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "my-field", 5 | templateUrl: "./field.component.html", 6 | styleUrls: ["./field.component.scss"], 7 | }) 8 | export class FieldComponent{ 9 | @Input() type = "text"; 10 | @Input() value: string; 11 | @Output() valueChange = new EventEmitter(); 12 | @Input() placeholder?: string; 13 | @Input() label: string; 14 | @Input() disabled?: boolean; 15 | @Input() maxlength?: number; 16 | @Input() asSelect?: boolean; 17 | @Input() selectOptions?: ({key: string, value?: string}|string)[]; 18 | 19 | public id = `${new Date().getTime()}-field-${Math.random()}`; 20 | 21 | public get options(): {key: string, value: string}[] { 22 | return this.selectOptions.map(p => { 23 | if (typeof(p) === 'string') { 24 | return {key: p, value: p}; 25 | } 26 | return {key: p.key, value: p.value ?? p.key}; 27 | }); 28 | } 29 | 30 | public onValueChange() { 31 | this.valueChange.emit(this.value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /web/app/elements/fullscreen-button/fullscreen-button.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/app/elements/fullscreen-button/fullscreen-button.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | button { 3 | border: none; 4 | background: none; 5 | } 6 | 7 | button img { 8 | width: 24px; 9 | height: 24px; 10 | opacity: 0.6; 11 | } 12 | 13 | button img:hover { 14 | opacity: 1; 15 | } -------------------------------------------------------------------------------- /web/app/elements/fullscreen-button/fullscreen-button.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit } from "@angular/core"; 2 | import * as screenfull from "screenfull"; 3 | 4 | @Component({ 5 | selector: "my-fullscreen-button", 6 | templateUrl: "fullscreen-button.component.html", 7 | styleUrls: ["fullscreen-button.component.scss"], 8 | }) 9 | export class FullscreenButtonComponent implements OnDestroy, OnInit { 10 | public isFullscreen = false; 11 | 12 | private listener = null; 13 | 14 | constructor() { 15 | // Do stuff 16 | } 17 | 18 | public ngOnInit(): void { 19 | // @ts-ignore 20 | this.listener = screenfull.on("change", () => { 21 | // @ts-ignore 22 | this.isFullscreen = screenfull.isFullscreen; 23 | }); 24 | // @ts-ignore 25 | this.isFullscreen = screenfull.isFullscreen; 26 | } 27 | 28 | public ngOnDestroy(): void { 29 | if (this.listener) { 30 | // @ts-ignore 31 | screenfull.off(this.listener); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/app/elements/ibox/ibox.component.html: -------------------------------------------------------------------------------- 1 |
2 |
5 |
6 | {{ boxTitle }} 7 |
8 | 9 | 10 | 11 |
12 |
13 | 14 |
15 |
-------------------------------------------------------------------------------- /web/app/elements/ibox/ibox.component.scss: -------------------------------------------------------------------------------- 1 | // The styles for iboxes are applied at an app level -------------------------------------------------------------------------------- /web/app/elements/ibox/ibox.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnInit } from "@angular/core"; 2 | import { ANIMATION_FADE_IN_NOT_OUT } from "../../app.animations"; 3 | 4 | @Component({ 5 | selector: "my-ibox", 6 | templateUrl: "./ibox.component.html", 7 | styleUrls: ["./ibox.component.scss"], 8 | animations: [ANIMATION_FADE_IN_NOT_OUT], 9 | }) 10 | export class IboxComponent implements OnInit { 11 | @Input() boxTitle: string; 12 | @Input() isCollapsible: boolean; 13 | @Input() defaultCollapsed: boolean; 14 | @Input() hasTitle = true; 15 | 16 | public collapsed = false; 17 | 18 | public ngOnInit(): void { 19 | this.collapsed = this.defaultCollapsed; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/app/elements/spinner/spinner.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /web/app/elements/spinner/spinner.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/themes/themes"; 2 | 3 | @include themifyComponent() { 4 | .container { 5 | position: relative; 6 | } 7 | 8 | .container .spinner { 9 | height: 30px; 10 | width: 30px; 11 | animation: rotate 2s linear infinite; 12 | transform-origin: center center; 13 | position: absolute; 14 | top: 0; 15 | bottom: 0; 16 | left: 0; 17 | right: 0; 18 | margin: auto; 19 | } 20 | 21 | .container .spinner .path { 22 | stroke-dasharray: 1, 200; 23 | stroke-dashoffset: 0; 24 | animation: dash 1.5s ease-in-out infinite; 25 | stroke-linecap: round; 26 | stroke: themed(defaultFgColor); 27 | } 28 | 29 | @keyframes rotate { 30 | 100% { 31 | transform: rotate(360deg); 32 | } 33 | } 34 | 35 | @keyframes dash { 36 | 0% { 37 | stroke-dasharray: 1, 200; 38 | stroke-dashoffset: 0; 39 | } 40 | 50% { 41 | stroke-dasharray: 89, 200; 42 | stroke-dashoffset: -35px; 43 | } 44 | 100% { 45 | stroke-dasharray: 89, 200; 46 | stroke-dashoffset: -124px; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /web/app/elements/spinner/spinner.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "my-spinner", 5 | templateUrl: "./spinner.component.html", 6 | styleUrls: ["./spinner.component.scss"], 7 | }) 8 | export class SpinnerComponent {} 9 | -------------------------------------------------------------------------------- /web/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "my-home", 5 | templateUrl: "./home.component.html", 6 | styleUrls: ["./home.component.scss"], 7 | }) 8 | export class HomeComponent { 9 | public hostname: string = window.location.origin; 10 | public showPromoPage = this.hostname === "https://dimension.t2bot.io"; 11 | 12 | public integrationsConfig = 13 | `` + 14 | `"integrations_ui_url": "${this.hostname}/element",\n` + 15 | `"integrations_rest_url": "${this.hostname}/api/v1/scalar",\n` + 16 | `"integrations_widgets_urls": ["${this.hostname}/widgets"],\n` + 17 | `"integrations_jitsi_widget_url": "${this.hostname}/widgets/jitsi",\n`; 18 | 19 | constructor() { 20 | // Do stuff 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/app/integration-bag/integration-bag.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
{{integration.displayName | translate}}
5 |
{{ integration.description | translate }}
6 |
7 |
8 | 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /web/app/page-header/page-header.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{ 'Browse integrations' | translate }} 5 |
6 |

{{ pageName | translate }}

7 |
8 |
9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /web/app/page-header/page-header.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | @import "../../style/themes/themes"; 3 | 4 | @include themifyComponent() { 5 | .header { 6 | width: 100%; 7 | padding: 32px; 8 | background-color: themed(headerBgColor); 9 | } 10 | 11 | .header .title { 12 | margin: 0; 13 | width: 83.333333%; // col-sm-10 14 | display: inline-block; 15 | } 16 | 17 | .header .title .pageName { 18 | font-weight: 600; 19 | padding: 0; 20 | margin: 0; 21 | font-size: 1.5em; 22 | } 23 | 24 | .header .quickAction { 25 | padding: 0; 26 | margin: 0; 27 | float: right; 28 | text-align: right; 29 | display: inline-block; 30 | width: 15.666667%; // col-sm-2 31 | position: relative; 32 | } 33 | 34 | .back-btn { 35 | cursor: pointer; 36 | margin-bottom: 16px; 37 | } 38 | 39 | .back-btn > span:not(.dim-icon) { 40 | margin-left: 4px; 41 | line-height: 1em; 42 | font-size: 0.9em; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /web/app/shared/SessionStorage.ts: -------------------------------------------------------------------------------- 1 | import { FE_Integration } from "./models/integration"; 2 | 3 | export class SessionStorage { 4 | 5 | private static _scalarToken: string; 6 | 7 | public static get scalarToken(): string { 8 | if (this._scalarToken) return this._scalarToken; 9 | this.scalarToken = localStorage.getItem("dimension_scalar_token"); 10 | return this._scalarToken; 11 | } 12 | 13 | public static set scalarToken(val: string) { 14 | this._scalarToken = val; 15 | if (val) { 16 | localStorage.setItem("dimension_scalar_token", val); 17 | } 18 | } 19 | 20 | public static userId: string; 21 | public static roomId: string; 22 | public static isAdmin: boolean; 23 | public static editIntegration: FE_Integration; 24 | public static editIntegrationId: string; 25 | public static editsRequested = 0; 26 | 27 | private constructor() { 28 | } 29 | } -------------------------------------------------------------------------------- /web/app/shared/directives/toggle-fullscreen.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, HostListener } from "@angular/core"; 2 | import * as screenfull from "screenfull"; 3 | 4 | @Directive({ 5 | selector: "[myToggleFullscreen]", 6 | }) 7 | export class ToggleFullscreenDirective { 8 | 9 | @HostListener("click") 10 | onClick() { 11 | // HACK: This should be behind a service in the event the library changes 12 | // @ts-ignore 13 | if (screenfull.isEnabled) { 14 | // @ts-ignore 15 | screenfull.toggle(); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /web/app/shared/models/dimension-responses.ts: -------------------------------------------------------------------------------- 1 | import { FE_Bridge, FE_Widget } from "./integration"; 2 | 3 | export interface FE_IntegrationsResponse { 4 | widgets: FE_Widget[]; 5 | bridges: FE_Bridge[]; 6 | } -------------------------------------------------------------------------------- /web/app/shared/models/hookshot_github.ts: -------------------------------------------------------------------------------- 1 | export interface FE_HookshotGithubBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | sharedSecret?: string; 6 | isEnabled: boolean; 7 | } 8 | 9 | export interface FE_HookshotGithubConnection { 10 | config: { 11 | org: string; 12 | repo: string; 13 | commandPrefix?: string; 14 | }; 15 | } 16 | 17 | export interface FE_HookshotGithubRepo { 18 | name: string; 19 | owner: string; 20 | fullName: string; 21 | avatarUrl: string; 22 | description: string; 23 | } 24 | 25 | export interface FE_HookshotGithubAuthUrls { 26 | userUrl: string; 27 | orgUrl: string; 28 | } 29 | 30 | export interface FE_HookshotGithubOrg { 31 | name: string; 32 | avatarUrl: string; 33 | } 34 | 35 | export interface FE_HookshotGithubOrgReposDto { 36 | organization: FE_HookshotGithubOrg; 37 | repositories: FE_HookshotGithubRepo[]; 38 | changeSelectionUrl?: string; 39 | } 40 | -------------------------------------------------------------------------------- /web/app/shared/models/hookshot_jira.ts: -------------------------------------------------------------------------------- 1 | export interface FE_HookshotJiraBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | sharedSecret?: string; 6 | isEnabled: boolean; 7 | } 8 | 9 | export interface FE_HookshotJiraConnection { 10 | config: { 11 | url: string; 12 | commandPrefix?: string; 13 | }; 14 | } 15 | 16 | export interface FE_HookshotJiraInstance { 17 | name: string; 18 | url: string; 19 | } 20 | 21 | export interface FE_HookshotJiraProject { 22 | key: string; 23 | name: string; 24 | url: string; 25 | } 26 | -------------------------------------------------------------------------------- /web/app/shared/models/hookshot_webhook.ts: -------------------------------------------------------------------------------- 1 | export interface FE_HookshotWebhookBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | sharedSecret?: string; 6 | isEnabled: boolean; 7 | } 8 | 9 | export interface FE_HookshotWebhookConnection { 10 | id: string; 11 | config: { 12 | name?: string; 13 | url: string; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /web/app/shared/models/irc.ts: -------------------------------------------------------------------------------- 1 | export interface FE_IrcBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | isEnabled: boolean; 6 | isOnline: boolean; 7 | availableNetworks: FE_IrcBridgeAvailableNetworks; 8 | } 9 | 10 | export interface FE_IrcBridgeAvailableNetworks { 11 | [networkId: string]: { 12 | name: string; 13 | domain: string; 14 | bridgeUserId: string; 15 | isEnabled: boolean; 16 | }; 17 | } -------------------------------------------------------------------------------- /web/app/shared/models/neb.ts: -------------------------------------------------------------------------------- 1 | export const NEB_HAS_CONFIG = [ 2 | "giphy", 3 | "guggy", 4 | "github", 5 | "google", 6 | "imgur", 7 | ]; 8 | 9 | export const NEB_IS_COMPLEX = [ 10 | "rss", 11 | "travisci", 12 | ]; -------------------------------------------------------------------------------- /web/app/shared/models/scalar-server-responses.ts: -------------------------------------------------------------------------------- 1 | export interface FE_ScalarAccountResponse { 2 | user_id: string; 3 | } 4 | 5 | export interface FE_ScalarRegisterResponse { 6 | scalar_token: string; 7 | } 8 | 9 | export interface FE_ScalarOpenIdRequestBody { 10 | access_token: string; 11 | expires_in: number; 12 | matrix_server_name: string; 13 | token_type: string; 14 | } -------------------------------------------------------------------------------- /web/app/shared/models/scalar-widget-actions.ts: -------------------------------------------------------------------------------- 1 | export interface ScalarToWidgetRequest { 2 | api: "to_widget"; 3 | action: "supported_api_versions" | "screenshot" | "capabilities" | "send_event" | "visibility" | "openid_credentials" | string; 4 | requestId: string; 5 | widgetId: string; 6 | data?: any; 7 | } 8 | 9 | export interface ScalarFromWidgetResponse { 10 | api: "from_widget"; 11 | action: "get_openid" | string; 12 | requestId: string; 13 | widgetId: string; 14 | data?: any; 15 | response: any; 16 | } -------------------------------------------------------------------------------- /web/app/shared/models/slack.ts: -------------------------------------------------------------------------------- 1 | export interface FE_SlackBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | isEnabled: boolean; 6 | } 7 | 8 | export interface FE_SlackLink { 9 | roomId: string; 10 | isWebhook: boolean; 11 | channelName: string; 12 | channelId: string; 13 | teamId: string; 14 | } 15 | 16 | export interface FE_SlackTeam { 17 | id: string; 18 | name: string; 19 | } 20 | 21 | export interface FE_SlackChannel { 22 | id: string; 23 | name: string; 24 | } -------------------------------------------------------------------------------- /web/app/shared/models/telegram.ts: -------------------------------------------------------------------------------- 1 | export interface FE_TelegramBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | sharedSecret?: string; 6 | isEnabled: boolean; 7 | options?: FE_TelegramBridgeOptions; 8 | } 9 | 10 | export interface FE_PortalInfo { 11 | bridged: boolean; 12 | chatId: number; 13 | roomId: string; 14 | canUnbridge: boolean; 15 | chatName: string; 16 | } 17 | 18 | export interface FE_TelegramBridgeOptions { 19 | allowTgPuppets: boolean; 20 | allowMxPuppets: boolean; 21 | } -------------------------------------------------------------------------------- /web/app/shared/models/terms.ts: -------------------------------------------------------------------------------- 1 | export interface FE_TermsEditable { 2 | shortcode: string; 3 | version: string; 4 | languages: { 5 | [lang: string]: { 6 | name: string; 7 | url: string; 8 | text?: string; 9 | }; 10 | }; 11 | } 12 | 13 | export interface FE_MinimalTerms { 14 | name: string; 15 | text: string; 16 | } -------------------------------------------------------------------------------- /web/app/shared/models/webhooks.ts: -------------------------------------------------------------------------------- 1 | export interface FE_WebhooksBridge { 2 | id: number; 3 | upstreamId?: number; 4 | provisionUrl?: string; 5 | sharedSecret?: string; 6 | isEnabled: boolean; 7 | } 8 | 9 | export interface FE_Webhook { 10 | id: string; 11 | label: string; 12 | url: string; 13 | userId: string; 14 | roomId: string; 15 | type: "incoming"; 16 | } 17 | 18 | export interface FE_WebhookOptions { 19 | label: string; 20 | } -------------------------------------------------------------------------------- /web/app/shared/registry/locator.service.ts: -------------------------------------------------------------------------------- 1 | import { Injector } from "@angular/core"; 2 | 3 | export class ServiceLocator { 4 | static injector: Injector; 5 | } -------------------------------------------------------------------------------- /web/app/shared/services/admin/admin-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { FE_DimensionConfig, FE_DimensionVersion } from "../../models/admin-responses"; 4 | import { HttpClient } from "@angular/common/http"; 5 | 6 | @Injectable() 7 | export class AdminApiService extends AuthedApi { 8 | constructor(http: HttpClient) { 9 | super(http); 10 | } 11 | 12 | public isAdmin(): Promise { 13 | return this.authedGet("/api/v1/dimension/admin/check").toPromise(); 14 | } 15 | 16 | public getConfig(): Promise { 17 | return this.authedGet("/api/v1/dimension/admin/config").toPromise(); 18 | } 19 | 20 | public getVersion(): Promise { 21 | return this.authedGet("/api/v1/dimension/admin/version").toPromise(); 22 | } 23 | 24 | public logoutAll(): Promise { 25 | return this.authedPost("/api/v1/dimension/admin/sessions/logout/all").toPromise(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web/app/shared/services/admin/admin-upstream-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { FE_Upstream } from "../../models/admin-responses"; 4 | import { HttpClient } from "@angular/common/http"; 5 | 6 | @Injectable() 7 | export class AdminUpstreamApiService extends AuthedApi { 8 | constructor(http: HttpClient) { 9 | super(http); 10 | } 11 | 12 | public getUpstreams(): Promise { 13 | return this.authedGet("/api/v1/dimension/admin/upstreams/all").toPromise(); 14 | } 15 | 16 | public newUpstream(name: string, type: string, scalarUrl: string, apiUrl: string): Promise { 17 | return this.authedPost("/api/v1/dimension/admin/upstreams/new", { 18 | name: name, 19 | type: type, 20 | scalarUrl: scalarUrl, 21 | apiUrl: apiUrl, 22 | }).toPromise(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /web/app/shared/services/integrations/hookshot-webhook-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { HttpClient } from "@angular/common/http"; 4 | import { FE_HookshotWebhookConnection } from "../../models/hookshot_webhook"; 5 | 6 | @Injectable() 7 | export class HookshotWebhookApiService extends AuthedApi { 8 | constructor(http: HttpClient) { 9 | super(http); 10 | } 11 | 12 | public createWebhook(roomId: string, name: string): Promise { 13 | return this.authedPost("/api/v1/dimension/hookshot/webhook/room/" + roomId + "/connect", { 14 | name, 15 | }).toPromise(); 16 | } 17 | 18 | public deleteWebhook(roomId: string, webhookId: string): Promise { 19 | return this.authedDelete("/api/v1/dimension/hookshot/webhook/room/" + roomId + "/connection/" + encodeURIComponent(webhookId) + "/disconnect").toPromise(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /web/app/shared/services/integrations/irc-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { HttpClient } from "@angular/common/http"; 4 | 5 | @Injectable() 6 | export class IrcApiService extends AuthedApi { 7 | constructor(http: HttpClient) { 8 | super(http); 9 | } 10 | 11 | public getOperators(networkId: string, channelNoHash: string): Promise { 12 | return this.authedGet("/api/v1/dimension/irc/" + networkId + "/channel/" + channelNoHash + "/ops").toPromise(); 13 | } 14 | 15 | public requestLink(roomId: string, networkId: string, channelNoHash: string, op: string): Promise { 16 | return this.authedPost("/api/v1/dimension/irc/" + networkId + "/channel/" + channelNoHash + "/link/" + roomId, {op: op}).toPromise(); 17 | } 18 | 19 | public removeLink(roomId: string, networkId: string, channelNoHash: string): Promise { 20 | return this.authedPost("/api/v1/dimension/irc/" + networkId + "/channel/" + channelNoHash + "/unlink/" + roomId).toPromise(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/app/shared/services/integrations/telegram-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { FE_PortalInfo } from "../../models/telegram"; 4 | import { HttpClient } from "@angular/common/http"; 5 | 6 | @Injectable() 7 | export class TelegramApiService extends AuthedApi { 8 | constructor(http: HttpClient) { 9 | super(http); 10 | } 11 | 12 | public getPortalInfo(chatId: number, roomId: string): Promise { 13 | return this.authedGet("/api/v1/dimension/telegram/chat/" + chatId, {roomId: roomId}).toPromise(); 14 | } 15 | 16 | public bridgeRoom(roomId: string, chatId: number, unbridgeOtherPortals = false): Promise { 17 | return this.authedPost("/api/v1/dimension/telegram/chat/" + chatId + "/room/" + roomId, {unbridgeOtherPortals}).toPromise(); 18 | } 19 | 20 | public unbridgeRoom(roomId: string): Promise { 21 | return this.authedDelete("/api/v1/dimension/telegram/room/" + roomId).toPromise(); 22 | } 23 | } -------------------------------------------------------------------------------- /web/app/shared/services/integrations/webhooks-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { AuthedApi } from "../authed-api"; 3 | import { FE_Webhook, FE_WebhookOptions } from "../../models/webhooks"; 4 | import { HttpClient } from "@angular/common/http"; 5 | 6 | @Injectable() 7 | export class WebhooksApiService extends AuthedApi { 8 | constructor(http: HttpClient) { 9 | super(http); 10 | } 11 | 12 | public createWebhook(roomId: string, options: FE_WebhookOptions): Promise { 13 | return this.authedPost("/api/v1/dimension/webhooks/room/" + roomId + "/webhooks/new", options).toPromise(); 14 | } 15 | 16 | public updateWebhook(roomId: string, hookId: string, options: FE_WebhookOptions): Promise { 17 | return this.authedPost("/api/v1/dimension/webhooks/room/" + roomId + "/webhooks/" + hookId, options).toPromise(); 18 | } 19 | 20 | public deleteWebhook(roomId: string, hookId: string): Promise { 21 | return this.authedDelete("/api/v1/dimension/webhooks/room/" + roomId + "/webhooks/" + hookId).toPromise(); 22 | } 23 | } -------------------------------------------------------------------------------- /web/app/shared/services/media.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | 3 | @Injectable() 4 | export class MediaService { 5 | public getThumbnailUrl(mxc: string, width: number, height: number, method: "scale" | "crop" = "scale", isAnimated = true): string { 6 | mxc = mxc.substring("mxc://".length).split('?')[0]; 7 | return `/api/v1/dimension/media/thumbnail/${mxc}?width=${width}&height=${height}&method=${method}&animated=${isAnimated}`; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/app/shared/services/name.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import * as gobyInit from "goby"; 3 | 4 | const goby = gobyInit.init({ 5 | // Converts words to a url-safe name 6 | // Ie: "hello world how-are you" becomes "HelloWorldHowAreYou" 7 | decorator: parts => parts.map(p => p ? p.split('-').map(p2 => p2 ? p2[0].toUpperCase() + p2.substring(1).toLowerCase() : '').join('') : '').join(''), 8 | }); 9 | 10 | @Injectable() 11 | export class NameService { 12 | constructor() { 13 | } 14 | 15 | public getHumanReadableName(): string { 16 | return goby.generate(["adj", "pre", "suf"]); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/app/shared/services/scalar/scalar-server-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { 3 | FE_ScalarAccountResponse, 4 | FE_ScalarOpenIdRequestBody, 5 | FE_ScalarRegisterResponse 6 | } from "../../models/scalar-server-responses"; 7 | import { AuthedApi } from "../authed-api"; 8 | import { SCALAR_API_VERSION } from "../../../../../src/utils/common-constants"; 9 | import { HttpClient } from "@angular/common/http"; 10 | 11 | @Injectable() 12 | export class ScalarServerApiService extends AuthedApi { 13 | constructor(http: HttpClient) { 14 | super(http) 15 | } 16 | 17 | public ping(): Promise { 18 | return this.http.get("/api/v1/scalar/ping").toPromise(); 19 | } 20 | 21 | public getAccount(): Promise { 22 | return this.authedGet("/api/v1/scalar/account", {v: SCALAR_API_VERSION}).toPromise(); 23 | } 24 | 25 | public register(openId: FE_ScalarOpenIdRequestBody): Promise { 26 | return this.http.post("/api/v1/scalar/register", openId, { 27 | params: {v: SCALAR_API_VERSION}, 28 | }).toPromise(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/bigbluebutton/bigbluebutton.component.html: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 |
14 |
15 |

16 |
17 | 18 |
19 |

{{'BigBlueButton Conference' | translate}}

20 | 23 |
24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/bigbluebutton/bigbluebutton.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | @import "../../../style/themes/themes"; 3 | 4 | @include themifyComponent() { 5 | #bigBlueButtonContainer { 6 | position: fixed; 7 | top: 0; 8 | bottom: 0; 9 | left: 0; 10 | right: 0; 11 | } 12 | 13 | .join-conference-wrapper { 14 | display: table; 15 | position: absolute; 16 | height: 100%; 17 | width: 100%; 18 | background-color: themed(widgetWelcomeBgColor); 19 | } 20 | 21 | .join-conference-boat { 22 | display: table-cell; 23 | vertical-align: middle; 24 | } 25 | 26 | .join-conference-prompt { 27 | margin-left: auto; 28 | margin-right: auto; 29 | width: 90%; 30 | text-align: center; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/fullpage-iframe/fullpage-iframe.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/fullpage-iframe/fullpage-iframe.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | iframe { 3 | position: absolute; 4 | top: 0; 5 | bottom: 0; 6 | left: 0; 7 | right: 0; 8 | width: 100%; 9 | height: 100%; 10 | } -------------------------------------------------------------------------------- /web/app/widget-wrappers/gcal/gcal.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ActivatedRoute } from "@angular/router"; 3 | import { DomSanitizer, SafeUrl } from "@angular/platform-browser"; 4 | 5 | @Component({ 6 | selector: "my-gcal-widget-wrapper", 7 | templateUrl: "../fullpage-iframe/fullpage-iframe.component.html", 8 | styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"], 9 | }) 10 | export class GCalWidgetWrapperComponent { 11 | public embedUrl: SafeUrl = null; 12 | 13 | constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) { 14 | const params: any = activatedRoute.snapshot.queryParams; 15 | const embedUrl = 16 | "https://calendar.google.com/calendar/embed?src=" + params.calendarId; 17 | this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(embedUrl); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/generic-fullscreen/generic-fullscreen.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ActivatedRoute } from "@angular/router"; 3 | import { DomSanitizer, SafeUrl } from "@angular/platform-browser"; 4 | 5 | @Component({ 6 | selector: "my-generic-fullscreen-widget-wrapper", 7 | templateUrl: "../fullpage-iframe/fullpage-iframe.component.html", 8 | styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"], 9 | }) 10 | export class GenericFullscreenWidgetWrapperComponent { 11 | public embedUrl: SafeUrl = null; 12 | 13 | constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) { 14 | const params: any = activatedRoute.snapshot.queryParams; 15 | // Note: we don't do an embeddable check (as we would in a generic wrapper) 16 | // because the Grafana dashboard might be private. 17 | this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/generic/generic.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |

8 |

{{'Sorry, this content cannot be embedded' | translate}}

9 |
10 |
11 | 12 | 13 |
14 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/generic/generic.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | @import "../../../style/themes/themes"; 3 | 4 | @include themifyComponent() { 5 | .control-page { 6 | position: fixed; 7 | top: 0; 8 | bottom: 0; 9 | left: 0; 10 | right: 0; 11 | margin: 0; 12 | padding: 0; 13 | background-color: themed(genericControlBgColor); 14 | color: themed(genericControlFgColor); 15 | } 16 | 17 | .loading-badge { 18 | text-align: center; 19 | font-size: 20px; 20 | position: relative; 21 | top: calc(50% - 10px); 22 | } 23 | 24 | .embed-failed { 25 | text-align: center; 26 | position: relative; 27 | height: 300px; 28 | top: calc(50% - 150px); 29 | } 30 | 31 | .embed-failed .ban { 32 | font-size: 145px; 33 | color: themed(widgetBannedSymbolColor); 34 | } 35 | 36 | iframe { 37 | position: absolute; 38 | top: 0; 39 | bottom: 0; 40 | left: 0; 41 | right: 0; 42 | width: 100%; 43 | height: 100%; 44 | } 45 | 46 | .toggleFullscreen { 47 | position: fixed; 48 | bottom: 10px; 49 | right: 10px; 50 | } 51 | } -------------------------------------------------------------------------------- /web/app/widget-wrappers/jitsi/jitsi.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |

Jitsi Video Conference

8 |
11 | 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/jitsi/jitsi.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | @import "../../../style/themes/themes"; 3 | 4 | @include themifyComponent() { 5 | #jitsiContainer { 6 | position: fixed; 7 | top: 0; 8 | bottom: 0; 9 | left: 0; 10 | right: 0; 11 | display: none; 12 | } 13 | 14 | .join-conference-wrapper { 15 | display: table; 16 | position: absolute; 17 | height: 100%; 18 | width: 100%; 19 | background-color: themed(widgetWelcomeBgColor); 20 | } 21 | 22 | .join-conference-boat { 23 | display: table-cell; 24 | vertical-align: middle; 25 | } 26 | 27 | .join-conference-prompt { 28 | margin-left: auto; 29 | margin-right: auto; 30 | width: 90%; 31 | text-align: center; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/reauth-example/reauth-example.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 |
7 |

{{'User ID:' | translate}} {{userId}}

8 |
9 |
10 |

{{stateMessage}}

11 |

{{'You have blocked this widget from receiving credentials.' | translate}}

12 |

{{'An error has occurred - see logs for details' | translate}}

13 | Widget ID: {{widgetId}} 14 |
15 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/reauth-example/reauth-example.component.scss: -------------------------------------------------------------------------------- 1 | .reauth-container { 2 | padding-top: 20px; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/spotify/spotify.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ActivatedRoute } from "@angular/router"; 3 | import * as spotifyUri from "spotify-uri"; 4 | import { DomSanitizer, SafeUrl } from "@angular/platform-browser"; 5 | 6 | @Component({ 7 | selector: "my-spotify-widget-wrapper", 8 | templateUrl: "../fullpage-iframe/fullpage-iframe.component.html", 9 | styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"], 10 | }) 11 | export class SpotifyWidgetWrapperComponent { 12 | public embedUrl: SafeUrl = null; 13 | 14 | constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) { 15 | const params: any = activatedRoute.snapshot.queryParams; 16 | const spotifyUrl = spotifyUri.parse(params.uri); 17 | const spotifyEmbedUrl = spotifyUri.formatEmbedURL(spotifyUrl); 18 | this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(spotifyEmbedUrl); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /web/app/widget-wrappers/terms/terms.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
-------------------------------------------------------------------------------- /web/app/widget-wrappers/terms/terms.component.scss: -------------------------------------------------------------------------------- 1 | .terms { 2 | width: 90%; 3 | max-width: 1000px; 4 | margin: 70px auto; 5 | background-color: white; 6 | box-shadow: #7d7d7d 10px 10px 20px; 7 | padding: 20px; 8 | border: 1px solid #909090; 9 | } -------------------------------------------------------------------------------- /web/app/widget-wrappers/tradingview/tradingview.component.html: -------------------------------------------------------------------------------- 1 |
2 |
-------------------------------------------------------------------------------- /web/app/widget-wrappers/tradingview/tradingview.component.scss: -------------------------------------------------------------------------------- 1 | // component styles are encapsulated and only applied to their components 2 | #tradingviewContainer { 3 | position: fixed; 4 | top: 0; 5 | bottom: 0; 6 | left: 0; 7 | right: 0; 8 | } -------------------------------------------------------------------------------- /web/app/widget-wrappers/video/video.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { ActivatedRoute } from "@angular/router"; 3 | import { DomSanitizer, SafeUrl } from "@angular/platform-browser"; 4 | 5 | @Component({ 6 | selector: "my-video-widget-wrapper", 7 | templateUrl: "../fullpage-iframe/fullpage-iframe.component.html", 8 | styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"], 9 | }) 10 | export class VideoWidgetWrapperComponent { 11 | public embedUrl: SafeUrl = null; 12 | 13 | constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) { 14 | const params: any = activatedRoute.snapshot.queryParams; 15 | this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(params.url); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Black.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Bold.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-ExtraBold.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-ExtraLight.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Light.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Regular.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-SemiBold.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Inter-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/fonts/Inter-Thin.ttf -------------------------------------------------------------------------------- /web/assets/img/avatars/bigbluebutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/bigbluebutton.png -------------------------------------------------------------------------------- /web/assets/img/avatars/custombots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/custombots.png -------------------------------------------------------------------------------- /web/assets/img/avatars/customwidget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/customwidget.png -------------------------------------------------------------------------------- /web/assets/img/avatars/echo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/echo.png -------------------------------------------------------------------------------- /web/assets/img/avatars/etherpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/etherpad.png -------------------------------------------------------------------------------- /web/assets/img/avatars/giphy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/giphy.png -------------------------------------------------------------------------------- /web/assets/img/avatars/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/github.png -------------------------------------------------------------------------------- /web/assets/img/avatars/gitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/gitter.png -------------------------------------------------------------------------------- /web/assets/img/avatars/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/google.png -------------------------------------------------------------------------------- /web/assets/img/avatars/googlecalendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/googlecalendar.png -------------------------------------------------------------------------------- /web/assets/img/avatars/googledocs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/googledocs.png -------------------------------------------------------------------------------- /web/assets/img/avatars/grafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/grafana.png -------------------------------------------------------------------------------- /web/assets/img/avatars/guggy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/guggy.png -------------------------------------------------------------------------------- /web/assets/img/avatars/imgur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/imgur.png -------------------------------------------------------------------------------- /web/assets/img/avatars/irc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/irc.png -------------------------------------------------------------------------------- /web/assets/img/avatars/jira.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/jira.png -------------------------------------------------------------------------------- /web/assets/img/avatars/jitsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/jitsi.png -------------------------------------------------------------------------------- /web/assets/img/avatars/rssbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/rssbot.png -------------------------------------------------------------------------------- /web/assets/img/avatars/slack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/slack.png -------------------------------------------------------------------------------- /web/assets/img/avatars/spotify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/spotify.png -------------------------------------------------------------------------------- /web/assets/img/avatars/telegram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/telegram.png -------------------------------------------------------------------------------- /web/assets/img/avatars/tradingview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/tradingview.png -------------------------------------------------------------------------------- /web/assets/img/avatars/travisci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/travisci.png -------------------------------------------------------------------------------- /web/assets/img/avatars/twitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/twitch.png -------------------------------------------------------------------------------- /web/assets/img/avatars/webhooks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/webhooks.png -------------------------------------------------------------------------------- /web/assets/img/avatars/whiteboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/whiteboard.png -------------------------------------------------------------------------------- /web/assets/img/avatars/wikipedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/wikipedia.png -------------------------------------------------------------------------------- /web/assets/img/avatars/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/avatars/youtube.png -------------------------------------------------------------------------------- /web/assets/img/element/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/assets/img/element/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/assets/img/enter-fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/enter-fullscreen.png -------------------------------------------------------------------------------- /web/assets/img/exit-fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/exit-fullscreen.png -------------------------------------------------------------------------------- /web/assets/img/infrastructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/infrastructure.png -------------------------------------------------------------------------------- /web/assets/img/logo/banner-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/banner-sm.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/favicon.ico -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/logo/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | Created by potrace 1.11, written by Peter Selinger 2001-2013 -------------------------------------------------------------------------------- /web/assets/img/logo/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /web/assets/img/no_stickers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/no_stickers.png -------------------------------------------------------------------------------- /web/assets/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/screenshot.png -------------------------------------------------------------------------------- /web/assets/img/slack_auth_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turt2live/matrix-dimension/2f9f848fb082af2eb717c7efe52807d99acbd51a/web/assets/img/slack_auth_button.png -------------------------------------------------------------------------------- /web/assets/licenses/cc_by-nc-sa_4.0.txt: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) 2 | This is a human-readable summary of (and not a substitute for) the license. (https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode) 3 | 4 | You are free to: 5 | Share — copy and redistribute the material in any medium or format 6 | Adapt — remix, transform, and build upon the material 7 | 8 | The licensor cannot revoke these freedoms as long as you follow the license terms. 9 | 10 | Under the following terms: 11 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 12 | 13 | NonCommercial — You may not use the material for commercial purposes. 14 | 15 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 16 | 17 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 18 | -------------------------------------------------------------------------------- /web/assets/licenses/cc_by-nc_4.0.txt: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) 2 | This is a human-readable summary of (and not a substitute for) the license. (https://creativecommons.org/licenses/by-nc/4.0/legalcode) 3 | 4 | You are free to: 5 | Share — copy and redistribute the material in any medium or format 6 | Adapt — remix, transform, and build upon the material 7 | 8 | The licensor cannot revoke these freedoms as long as you follow the license terms. 9 | 10 | Under the following terms: 11 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 12 | 13 | NonCommercial — You may not use the material for commercial purposes. 14 | 15 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 16 | -------------------------------------------------------------------------------- /web/assets/licenses/cc_by-sa_4.0.txt: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) 2 | This is a human-readable summary of (and not a substitute for) the license. (https://creativecommons.org/licenses/by-sa/4.0/legalcode) 3 | 4 | You are free to: 5 | Share — copy and redistribute the material in any medium or format 6 | Adapt — remix, transform, and build upon the material for any purpose, even commercially. 7 | 8 | The licensor cannot revoke these freedoms as long as you follow the license terms. 9 | 10 | Under the following terms: 11 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 12 | 13 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 14 | 15 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 16 | -------------------------------------------------------------------------------- /web/assets/licenses/cc_by_4.0.txt: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International (CC BY 4.0) 2 | This is a human-readable summary of (and not a substitute for) the license. (https://creativecommons.org/licenses/by/4.0/legalcode) 3 | 4 | You are free to: 5 | Share — copy and redistribute the material in any medium or format 6 | Adapt — remix, transform, and build upon the material for any purpose, even commercially. 7 | 8 | The licensor cannot revoke these freedoms as long as you follow the license terms. 9 | 10 | Under the following terms: 11 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 12 | 13 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 14 | -------------------------------------------------------------------------------- /web/assets/licenses/general-imported.txt: -------------------------------------------------------------------------------- 1 | The sticker pack was created by a Matrix user, however the license is unavailable. Sorry. 2 | -------------------------------------------------------------------------------- /web/assets/licenses/telegram-import.txt: -------------------------------------------------------------------------------- 1 | The sticker pack was imported from Telegram, and therefore a license is unavailable, sorry. 2 | -------------------------------------------------------------------------------- /web/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /web/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /web/style/_riot.scss: -------------------------------------------------------------------------------- 1 | // The CSS for the Element breadcrumb is specified here to ensure that it's style can be overridden. 2 | // In it's current position (as a component), the component-level stylesheet cannot access the 3 | // elements, so we specify it in a more generic location. 4 | @import "themes/themes"; 5 | 6 | .main-app { 7 | @include themify() { 8 | .xng-breadcrumb-link { 9 | text-decoration: none; 10 | } 11 | 12 | .xng-breadcrumb-root { 13 | color: inherit; 14 | } 15 | 16 | .xng-breadcrumb-seperator, 17 | .xng-breadcrumb-trail { 18 | color: themed(activeBreadcrumbColor); 19 | } 20 | 21 | .header .quickAction .closeButton .scalarClose { 22 | position: absolute; 23 | top: 0px; 24 | right: 0px; 25 | } 26 | 27 | .header .quickAction .adminButton { 28 | position: absolute; 29 | top: 0px; 30 | right: 26px; 31 | } 32 | 33 | .header .quickAction .headerButton { 34 | width: 20px; 35 | height: 20px; 36 | cursor: pointer; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/style/components/bootstrap_override.scss: -------------------------------------------------------------------------------- 1 | @import "../themes/themes"; 2 | 3 | @include themifyRoot() { 4 | .main-app { 5 | a { 6 | color: themed(anchorColor); 7 | text-decoration: none; 8 | } 9 | 10 | table, td, th { 11 | border-color: themed(tableBorderColor); 12 | color: themed(defaultFgColor); 13 | } 14 | 15 | code { 16 | background-color: themed(codeBgColor); 17 | } 18 | 19 | *.text-muted { 20 | color: themed(altMutedColor) !important; 21 | } 22 | 23 | .form-control { 24 | color: themed(formControlFgColor); 25 | background-color: themed(formControlBgColor); 26 | } 27 | 28 | .form-control::placeholder { 29 | color: themed(formControlPlaceholderColor); 30 | } 31 | 32 | .toast:not(.show) { 33 | display: flex; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/style/components/dialog.scss: -------------------------------------------------------------------------------- 1 | @import "../themes/themes"; 2 | 3 | @include themifyRoot() { 4 | .modal-content { 5 | background-color: themed(dialogBgColor); 6 | color: themed(dialogFgColor); 7 | 8 | .modal-header { 9 | padding: 20px; 10 | border-bottom: 1px solid themed(dialogBorderColor); 11 | } 12 | 13 | .dialog-footer { 14 | border-top: 1px solid themed(dialogFooterBorderColor); 15 | background-color: themed(dialogFooterBackgroundColor); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/style/components/element.scss: -------------------------------------------------------------------------------- 1 | @import "../themes/themes"; 2 | 3 | .main-app { 4 | @include themify() { 5 | .element-btn { 6 | outline: none; 7 | border: none; 8 | background: themed(buttonAccentColor); 9 | color: themed(buttonPrimaryColor); 10 | text-align: center; 11 | padding: 4px 18px; 12 | border-radius: 8px; 13 | font-size: 0.9em; 14 | 15 | &.element-btn-danger-link { 16 | background: themed(buttonPrimaryColor); 17 | color: themed(buttonDangerColor); 18 | } 19 | 20 | &.element-btn-danger { 21 | background: themed(buttonDangerColor); 22 | } 23 | 24 | &:disabled { 25 | opacity: 0.3; 26 | } 27 | } 28 | 29 | .element-btn-row { 30 | margin-top: 25px; 31 | 32 | button { 33 | margin-right: 8px; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /web/style/components/ibox.scss: -------------------------------------------------------------------------------- 1 | @import "../themes/themes"; 2 | 3 | .main-app { 4 | @include themify() { 5 | .ibox { 6 | background-color: themed('containerBgColor'); 7 | padding: 0; 8 | margin-bottom: 30px; 9 | box-shadow: 0 2px 4px themed('containerShadowColor'); 10 | } 11 | 12 | .ibox .ibox-title { 13 | padding: 5px; 14 | border-bottom: 1px solid themed('containerBorderColor'); 15 | border-top: 2px solid themed('containerBorderColor'); 16 | } 17 | 18 | .ibox .ibox-title h5 { 19 | display: inline; 20 | font-size: 1.1em; 21 | padding: 5px; 22 | margin: 0; 23 | } 24 | 25 | .ibox .ibox-content { 26 | padding: 15px; 27 | } 28 | 29 | .ibox .ibox-title .ibox-icon { 30 | float: right; 31 | margin-top: 4px; 32 | margin-right: 5px; 33 | cursor: pointer; 34 | } 35 | 36 | .ibox .ibox-title.ibox-title-collapsible { 37 | cursor: pointer; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /web/style/components/icons.scss: -------------------------------------------------------------------------------- 1 | @import "../themes/themes"; 2 | 3 | @mixin dim-icon { 4 | display: inline-block; 5 | mask-position: center; 6 | mask-size: contain; 7 | mask-repeat: no-repeat; 8 | } 9 | 10 | @include themifyRoot() { 11 | .dim-icon { 12 | &.dim-chevron-left { 13 | @include dim-icon(); 14 | width: 10px; 15 | height: 10px; 16 | mask-image: url('/assets/img/element/chevron-left.svg'); 17 | background-color: themed(defaultFgColor); 18 | } 19 | &.dim-cog { 20 | @include dim-icon(); 21 | width: 20px; 22 | height: 20px; 23 | mask-image: url('/assets/img/element/cog.svg'); 24 | background-color: themed(mutedColor); 25 | } 26 | &.dim-close { 27 | @include dim-icon(); 28 | width: 20px; 29 | height: 20px; 30 | mask-image: url('/assets/img/element/close.svg'); 31 | background-color: themed(mutedColor); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/vendor.ts: -------------------------------------------------------------------------------- 1 | import "@angular/platform-browser"; 2 | import "@angular/platform-browser-dynamic"; 3 | import "@angular/core"; 4 | import "@angular/common"; 5 | import "@angular/router"; 6 | import "rxjs"; 7 | import "@angularclass/hmr"; 8 | import fontawesome from '@fortawesome/fontawesome'; 9 | import solid from '@fortawesome/fontawesome-free-solid'; 10 | import regular from '@fortawesome/fontawesome-free-regular'; 11 | import brands from '@fortawesome/fontawesome-free-brands'; 12 | 13 | fontawesome.library.add(regular, solid, brands); --------------------------------------------------------------------------------