mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Add TradingView widget
Fixes https://github.com/turt2live/matrix-dimension/issues/132
This commit is contained in:
parent
9bdba2d474
commit
ea834d826a
@ -1,5 +1,4 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
23
src/db/migrations/20181021152145-AddTradingViewWidget.ts
Normal file
23
src/db/migrations/20181021152145-AddTradingViewWidget.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { QueryInterface } from "sequelize";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => queryInterface.bulkInsert("dimension_widgets", [
|
||||||
|
{
|
||||||
|
type: "tradingview",
|
||||||
|
name: "TradingView",
|
||||||
|
avatarUrl: "/img/avatars/tradingview.png",
|
||||||
|
isEnabled: true,
|
||||||
|
isPublic: true,
|
||||||
|
description: "Monitor your favourite cryptocurrencies",
|
||||||
|
}
|
||||||
|
]));
|
||||||
|
},
|
||||||
|
down: (queryInterface: QueryInterface) => {
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => queryInterface.bulkDelete("dimension_widgets", {
|
||||||
|
type: "tradingview",
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -97,6 +97,8 @@ import { GitterBridgeConfigComponent } from "./configs/bridge/gitter/gitter.brid
|
|||||||
import { GitterApiService } from "./shared/services/integrations/gitter-api.service";
|
import { GitterApiService } from "./shared/services/integrations/gitter-api.service";
|
||||||
import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/generic-fullscreen/generic-fullscreen.component";
|
import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/generic-fullscreen/generic-fullscreen.component";
|
||||||
import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component";
|
import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component";
|
||||||
|
import { TradingViewWidgetConfigComponent } from "./configs/widget/tradingview/tradingview.widget.component";
|
||||||
|
import { TradingViewWidgetWrapperComponent } from "./widget-wrappers/tradingview/tradingview.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -177,6 +179,8 @@ import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.w
|
|||||||
GitterBridgeConfigComponent,
|
GitterBridgeConfigComponent,
|
||||||
GenericFullscreenWidgetWrapperComponent,
|
GenericFullscreenWidgetWrapperComponent,
|
||||||
GrafanaWidgetConfigComponent,
|
GrafanaWidgetConfigComponent,
|
||||||
|
TradingViewWidgetConfigComponent,
|
||||||
|
TradingViewWidgetWrapperComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
|
@ -35,6 +35,8 @@ import { AdminGitterBridgeComponent } from "./admin/bridges/gitter/gitter.compon
|
|||||||
import { GitterBridgeConfigComponent } from "./configs/bridge/gitter/gitter.bridge.component";
|
import { GitterBridgeConfigComponent } from "./configs/bridge/gitter/gitter.bridge.component";
|
||||||
import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/generic-fullscreen/generic-fullscreen.component";
|
import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/generic-fullscreen/generic-fullscreen.component";
|
||||||
import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component";
|
import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component";
|
||||||
|
import { TradingViewWidgetConfigComponent } from "./configs/widget/tradingview/tradingview.widget.component";
|
||||||
|
import { TradingViewWidgetWrapperComponent } from "./widget-wrappers/tradingview/tradingview.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -167,6 +169,11 @@ const routes: Routes = [
|
|||||||
component: GrafanaWidgetConfigComponent,
|
component: GrafanaWidgetConfigComponent,
|
||||||
data: {breadcrumb: "Grafana Widgets", name: "Grafana Widgets"},
|
data: {breadcrumb: "Grafana Widgets", name: "Grafana Widgets"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "tradingview",
|
||||||
|
component: TradingViewWidgetConfigComponent,
|
||||||
|
data: {breadcrumb: "TradingView Widgets", name: "TradingView Widgets"},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -225,6 +232,7 @@ const routes: Routes = [
|
|||||||
{path: "gcal", component: GCalWidgetWrapperComponent},
|
{path: "gcal", component: GCalWidgetWrapperComponent},
|
||||||
{path: "stickerpicker", component: StickerPickerWidgetWrapperComponent},
|
{path: "stickerpicker", component: StickerPickerWidgetWrapperComponent},
|
||||||
{path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent},
|
{path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent},
|
||||||
|
{path: "tradingview", component: TradingViewWidgetWrapperComponent},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -38,6 +38,6 @@ export class GoogleCalendarWidgetConfigComponent extends WidgetComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const encodedId = encodeURIComponent(widget.dimension.newData.src);
|
const encodedId = encodeURIComponent(widget.dimension.newData.src);
|
||||||
widget.dimension.newUrl = window.location.origin + "/widget/gcal?calendarId=" + encodedId;
|
widget.dimension.newUrl = window.location.origin + "/widgets/gcal?calendarId=" + encodedId;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<my-widget-config [widgetComponent]="this">
|
||||||
|
<ng-template #widgetParamsTemplate let-widget="widget">
|
||||||
|
<label class="label-block">
|
||||||
|
Trading Pair
|
||||||
|
<select class="form-control form-control-sm" [(ngModel)]="widget.dimension.newData.pair" [disabled]="isUpdating" name="widget-pair-{{widget.id}}">
|
||||||
|
<option *ngFor="let pair of pairs" [ngValue]="pair.value">
|
||||||
|
{{ pair.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="label-block">
|
||||||
|
Interval
|
||||||
|
<select class="form-control form-control-sm" [(ngModel)]="widget.dimension.newData.interval" [disabled]="isUpdating" name="widget-interval-{{widget.id}}">
|
||||||
|
<option *ngFor="let interval of intervals" [ngValue]="interval.value">
|
||||||
|
{{ interval.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</ng-template>
|
||||||
|
</my-widget-config>
|
@ -0,0 +1,98 @@
|
|||||||
|
import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component";
|
||||||
|
import { EditableWidget, WIDGET_TRADINGVIEW } from "../../../shared/models/widget";
|
||||||
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "tradingview.widget.component.html",
|
||||||
|
styleUrls: ["tradingview.widget.component.scss"],
|
||||||
|
})
|
||||||
|
export class TradingViewWidgetConfigComponent extends WidgetComponent {
|
||||||
|
|
||||||
|
public readonly intervals = [
|
||||||
|
{value: '1', label: '1 Minute'},
|
||||||
|
{value: '3', label: '3 Minutes'},
|
||||||
|
{value: '5', label: '5 Minutes'},
|
||||||
|
{value: '15', label: '15 Minutes'},
|
||||||
|
{value: '30', label: '30 Minutes'},
|
||||||
|
{value: '60', label: '1 Hour'},
|
||||||
|
{value: '120', label: '2 Hours'},
|
||||||
|
{value: '180', label: '3 Hours'},
|
||||||
|
{value: '240', label: '4 Hours'},
|
||||||
|
{value: 'D', label: '1 Day'},
|
||||||
|
{value: 'W', label: '1 Week'},
|
||||||
|
];
|
||||||
|
|
||||||
|
public readonly pairs = [
|
||||||
|
// USD
|
||||||
|
{value: 'COINBASE:BTCUSD', label: 'Bitcoin / US Dollar'},
|
||||||
|
{value: 'COINBASE:ETHUSD', label: 'Ethereum / US Dollar'},
|
||||||
|
{value: 'COINBASE:LTCUSD', label: 'Litecoin / US Dollar'},
|
||||||
|
{value: 'BITTREX:SNTUSD', label: 'Status Network Token / US Dollar'},
|
||||||
|
{value: 'BITTREX:ETCUSD', label: 'Ethereum Classic / US Dollar'},
|
||||||
|
{value: 'BITFINEX:BTGUSD', label: 'BTG / US Dollar'},
|
||||||
|
{value: 'BITTREX:DASHUSD', label: 'Dash / US Dollar'},
|
||||||
|
{value: 'BITFINEX:EOSUSD', label: 'EOS / US Dollar'},
|
||||||
|
{value: 'BITFINEX:IOTUSD', label: 'IOTA / US Dollar'},
|
||||||
|
{value: 'BITTREX:LSKUSD', label: 'Lisk / US Dollar'},
|
||||||
|
{value: 'BITTREX:OMGUSD', label: 'OmiseGo / US Dollar'},
|
||||||
|
{value: 'BITTREX:NEOUSD', label: 'NEO / US Dollar'},
|
||||||
|
{value: 'BITTREX:XRPUSD', label: 'Ripple / US Dollar'},
|
||||||
|
{value: 'BITFINEX:ZECUSD', label: 'Zcash / US Dollar'},
|
||||||
|
{value: 'BITFINEX:XMRUSD', label: 'Monero / US Dollar'},
|
||||||
|
|
||||||
|
// Euro / GBP
|
||||||
|
{value: 'COINBASE:BTCEUR', label: 'Bitcoin / Euro'},
|
||||||
|
{value: 'COINBASE:ETHEUR', label: 'Ethereum / Euro'},
|
||||||
|
{value: 'COINBASE:LTCEUR', label: 'Litecoin / Euro'},
|
||||||
|
{value: 'COINBASE:BTCGBP', label: 'Bitcoin / GBP'},
|
||||||
|
|
||||||
|
// Bitcoin
|
||||||
|
{value: 'COINBASE:ETHBTC', label: 'Ethereum / Bitcoin'},
|
||||||
|
{value: 'COINBASE:LTCBTC', label: 'Litecoin / Bitcoin'},
|
||||||
|
{value: 'BITTREX:SNTBTC', label: 'Status Network Token / Bitcoin'},
|
||||||
|
{value: 'BITTREX:BCCBTC', label: 'Bitcoin Cash / Bitcoin'},
|
||||||
|
{value: 'BITTREX:ADABTC', label: 'Ada / Bitcoin'},
|
||||||
|
{value: 'BITTREX:ARKBTC', label: 'Ark / Bitcoin'},
|
||||||
|
{value: 'BITTREX:EMC2BTC', label: 'Einsteinium / Bitcoin'},
|
||||||
|
{value: 'BITFINEX:IOTBTC', label: 'IOTA / Bitcoin'},
|
||||||
|
{value: 'BITTREX:LSKBTC', label: 'Lisk / Bitcoin'},
|
||||||
|
{value: 'BITTREX:NEOBTC', label: 'Neo / Bitcoin'},
|
||||||
|
{value: 'BITTREX:OMGBTC', label: 'OmiseGO / Bitcoin'},
|
||||||
|
{value: 'BITTREX:POWRBTC', label: 'PowerLedger / Bitcoin'},
|
||||||
|
{value: 'BITTREX:STRATBTC', label: 'Stratis / Bitcoin'},
|
||||||
|
{value: 'BITTREX:TRIGBTC', label: 'TRIG Token / Bitcoin'},
|
||||||
|
{value: 'BITTREX:VTCBTC', label: 'Vertcoin / Bitcoin'},
|
||||||
|
{value: 'BITTREX:XLMBTC', label: 'Lumen / Bitcoin'},
|
||||||
|
{value: 'BITTREX:XRPBTC', label: 'Ripple / Bitcoin'},
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
{value: 'BITTREX:BTCUSDT', label: 'Bitcoin / Tether USD'},
|
||||||
|
{value: 'BITTREX:ETHUSDT', label: 'Ethereum / Tether USD'},
|
||||||
|
{value: 'BITTREX:SNTETH', label: 'Status Network Token / Ethereum'},
|
||||||
|
{value: 'BITTREX:BCCUSDT', label: 'Bitcoin Cash / Tether USD'},
|
||||||
|
{value: 'BITTREX:NEOUSDT', label: 'Neo / Tether'},
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(WIDGET_TRADINGVIEW, "TradingView Chart", DISABLE_AUTOMATIC_WRAPPING, "tradingView");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OnNewWidgetPrepared(widget: EditableWidget): void {
|
||||||
|
widget.dimension.newData.interval = "D"; // 1 day
|
||||||
|
widget.dimension.newData.pair = this.pairs[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OnWidgetBeforeAdd(widget: EditableWidget): void {
|
||||||
|
this.setViewUrl(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OnWidgetBeforeEdit(widget: EditableWidget) {
|
||||||
|
this.setViewUrl(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setViewUrl(widget: EditableWidget) {
|
||||||
|
const pair = this.pairs.find(p => p.value === widget.dimension.newData.pair);
|
||||||
|
widget.dimension.newTitle = pair ? pair.label : null;
|
||||||
|
widget.dimension.newUrl = window.location.origin + "/widgets/tradingview?pair=$pair&interval=$interval";
|
||||||
|
}
|
||||||
|
}
|
@ -40,8 +40,8 @@
|
|||||||
<span>Etherpad</span>
|
<span>Etherpad</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="integration">
|
<div class="integration">
|
||||||
<img src="/img/avatars/grafana.png">
|
<img src="/img/avatars/tradingview.png">
|
||||||
<span>Grafana</span>
|
<span>TradingView</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="integration">
|
<div class="integration">
|
||||||
<img src="/img/avatars/youtube.png">
|
<img src="/img/avatars/youtube.png">
|
||||||
@ -51,6 +51,10 @@
|
|||||||
<img src="/img/avatars/twitch.png">
|
<img src="/img/avatars/twitch.png">
|
||||||
<span>Twitch Livestream</span>
|
<span>Twitch Livestream</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="integration">
|
||||||
|
<img src="/img/avatars/grafana.png">
|
||||||
|
<span>Grafana</span>
|
||||||
|
</div>
|
||||||
<div class="integration">
|
<div class="integration">
|
||||||
<img src="/img/avatars/googledocs.png">
|
<img src="/img/avatars/googledocs.png">
|
||||||
<span>Google Docs</span>
|
<span>Google Docs</span>
|
||||||
|
@ -9,6 +9,7 @@ export const WIDGET_YOUTUBE = ["youtube", "dimension-youtube"];
|
|||||||
export const WIDGET_GRAFANA = ["grafana", "dimension-grafana"];
|
export const WIDGET_GRAFANA = ["grafana", "dimension-grafana"];
|
||||||
export const WIDGET_TWITCH = ["twitch", "dimension-twitch"];
|
export const WIDGET_TWITCH = ["twitch", "dimension-twitch"];
|
||||||
export const WIDGET_STICKER_PICKER = ["m.stickerpicker"];
|
export const WIDGET_STICKER_PICKER = ["m.stickerpicker"];
|
||||||
|
export const WIDGET_TRADINGVIEW = ["tradingview", "dimension-tradingview"];
|
||||||
|
|
||||||
export interface EditableWidget {
|
export interface EditableWidget {
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
WIDGET_GOOGLE_DOCS,
|
WIDGET_GOOGLE_DOCS,
|
||||||
WIDGET_GRAFANA,
|
WIDGET_GRAFANA,
|
||||||
WIDGET_JITSI,
|
WIDGET_JITSI,
|
||||||
|
WIDGET_TRADINGVIEW,
|
||||||
WIDGET_TWITCH,
|
WIDGET_TWITCH,
|
||||||
WIDGET_YOUTUBE
|
WIDGET_YOUTUBE
|
||||||
} from "../models/widget";
|
} from "../models/widget";
|
||||||
@ -51,7 +52,10 @@ export class IntegrationsRegistry {
|
|||||||
},
|
},
|
||||||
"grafana": {
|
"grafana": {
|
||||||
types: WIDGET_GRAFANA,
|
types: WIDGET_GRAFANA,
|
||||||
}
|
},
|
||||||
|
"tradingview": {
|
||||||
|
types: WIDGET_TRADINGVIEW,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
<div id="tradingviewContainer">
|
||||||
|
</div>
|
@ -0,0 +1,8 @@
|
|||||||
|
// component styles are encapsulated and only applied to their components
|
||||||
|
#tradingviewContainer {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
42
web/app/widget-wrappers/tradingview/tradingview.component.ts
Normal file
42
web/app/widget-wrappers/tradingview/tradingview.component.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import * as $ from "jquery";
|
||||||
|
|
||||||
|
declare var TradingView: any;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "my-tradingview-widget-wrapper",
|
||||||
|
templateUrl: "tradingview.component.html",
|
||||||
|
styleUrls: ["tradingview.component.scss"],
|
||||||
|
})
|
||||||
|
export class TradingViewWidgetWrapperComponent implements OnInit {
|
||||||
|
|
||||||
|
private symbol: string;
|
||||||
|
private interval: string;
|
||||||
|
|
||||||
|
constructor(activatedRoute: ActivatedRoute) {
|
||||||
|
let params: any = activatedRoute.snapshot.queryParams;
|
||||||
|
|
||||||
|
this.symbol = params.pair;
|
||||||
|
this.interval = params.interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit() {
|
||||||
|
$.getScript("https://s3.tradingview.com/tv.js", () => {
|
||||||
|
new TradingView.widget({
|
||||||
|
"autosize": true,
|
||||||
|
"symbol": this.symbol,
|
||||||
|
"interval": this.interval,
|
||||||
|
"timezone": "Etc/UTC",
|
||||||
|
"theme": "Light",
|
||||||
|
"style": "1",
|
||||||
|
"locale": "en",
|
||||||
|
"toolbar_bg": "#f1f3f6",
|
||||||
|
"enable_publishing": false,
|
||||||
|
"hide_top_toolbar": true,
|
||||||
|
"hide_legend": true,
|
||||||
|
"container_id": "tradingviewContainer",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
BIN
web/public/img/avatars/tradingview.png
Normal file
BIN
web/public/img/avatars/tradingview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
Loading…
Reference in New Issue
Block a user