This commit is contained in:
Jim Myers 2020-09-30 17:25:50 -04:00
parent b2bbc6b955
commit 730f24a797
6 changed files with 150 additions and 51 deletions

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>flipside.js</title> <title>flipside.js</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="flipside-v1.16.0.js"></script> <script src="flipside-v1.16.1.js"></script>
<style> <style>
body { body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
@ -60,19 +60,19 @@
<div id="chart"></div> <div id="chart"></div>
</div> </div>
<div class="wrapper dark" style="background-color: #000000;"> <div class="wrapper dark" style="background-color: #000000">
<div id="chart2"></div> <div id="chart2"></div>
</div> </div>
<div class="wrapper"><div id="score"></div></div> <div class="wrapper"><div id="score"></div></div>
<div class="wrapper"><div id="widget-0" style="width: 289px;"></div></div> <div class="wrapper"><div id="widget-0" style="width: 289px"></div></div>
<div class="wrapper" style="background-color: #000000;"> <div class="wrapper" style="background-color: #000000">
<div id="widget-1" style="width: 289px;"></div> <div id="widget-1" style="width: 289px"></div>
</div> </div>
<div class="wrapper" style="background-color: #33435e;"> <div class="wrapper" style="background-color: #33435e">
<div id="widget-2"></div> <div id="widget-2"></div>
</div> </div>

View File

@ -1,6 +1,6 @@
{ {
"name": "flipside-js", "name": "flipside-js",
"version": "1.16.0", "version": "1.16.1",
"description": "FlipsideJS provides a library embeddable widgets that display data from the Flipside Platform API, including FCAS.", "description": "FlipsideJS provides a library embeddable widgets that display data from the Flipside Platform API, including FCAS.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -49,11 +49,11 @@ class Chart extends Component<Props> {
static defaultProps: Partial<Props> = { static defaultProps: Partial<Props> = {
axisTitles: [], axisTitles: [],
mode: "light", mode: "light",
exportingEnabled: false exportingEnabled: false,
}; };
state = { state = {
loading: true loading: true,
}; };
container: HTMLElement; container: HTMLElement;
@ -75,7 +75,7 @@ class Chart extends Component<Props> {
data = await api.fetchTimeseries({ data = await api.fetchTimeseries({
series: apiSeries, series: apiSeries,
start_date: startDate, start_date: startDate,
end_date: endDate end_date: endDate,
}); });
if (data.data.data.length > 0) { if (data.data.data.length > 0) {
this.setState({ loading: false, data: data.data.data }); this.setState({ loading: false, data: data.data.data });
@ -103,24 +103,24 @@ class Chart extends Component<Props> {
{ {
series: loadedSeries, series: loadedSeries,
chart: { chart: {
renderTo: this.container renderTo: this.container,
}, },
title: { title: {
text: this.props.title, text: this.props.title,
style: { color: textColor } style: { color: textColor },
}, },
legend: { legend: {
enabled: series && series.length > 1, enabled: series && series.length > 1,
itemStyle: { color: textColor }, itemStyle: { color: textColor },
itemHoverStyle: { color: textColor } itemHoverStyle: { color: textColor },
}, },
tooltip: { tooltip: {
backgroundColor: tooltipBackground, backgroundColor: tooltipBackground,
style: { style: {
color: textColor color: textColor,
} },
}, },
rangeSelector: { rangeSelector: {
@ -128,16 +128,16 @@ class Chart extends Component<Props> {
states: { states: {
select: { select: {
style: { style: {
color: mode === "dark" ? "#fff" : "#000" color: mode === "dark" ? "#fff" : "#000",
} },
} },
} },
} },
}, },
xAxis: { xAxis: {
lineColor: gridLineColor, lineColor: gridLineColor,
tickColor: gridLineColor tickColor: gridLineColor,
}, },
yAxis: [ yAxis: [
@ -145,18 +145,18 @@ class Chart extends Component<Props> {
gridLineColor, gridLineColor,
title: { title: {
text: this.props.axisTitles[0], text: this.props.axisTitles[0],
style: { color: textColor } style: { color: textColor },
} },
}), }),
merge({}, DEFAULT_YAXIS, { merge({}, DEFAULT_YAXIS, {
opposite: true, opposite: true,
gridLineColor, gridLineColor,
title: { title: {
text: this.props.axisTitles[1], text: this.props.axisTitles[1],
style: { color: textColor } style: { color: textColor },
} },
}) }),
] ],
}, },
rest rest
); );
@ -175,7 +175,7 @@ class Chart extends Component<Props> {
theme: { theme: {
fill: "transparent", fill: "transparent",
cursor: "pointer", cursor: "pointer",
states: { hover: { fill: "transparent", opacity: 0.7 } } states: { hover: { fill: "transparent", opacity: 0.7 } },
}, },
menuItems: [ menuItems: [
"downloadCSV", "downloadCSV",
@ -185,10 +185,10 @@ class Chart extends Component<Props> {
"downloadPNG", "downloadPNG",
"downloadJPEG", "downloadJPEG",
"downloadPDF", "downloadPDF",
"downloadSVG" "downloadSVG",
] ],
} },
} },
}; };
} else { } else {
options.exporting = { enabled: false }; options.exporting = { enabled: false };
@ -208,7 +208,7 @@ class Chart extends Component<Props> {
style={{ display: "block", textAlign: "right" }} style={{ display: "block", textAlign: "right" }}
/> />
)} )}
<div ref={el => (this.container = el)} /> <div ref={(el) => (this.container = el)} />
</div> </div>
); );
} }

View File

@ -24,7 +24,58 @@ type State = {
class CustomLinks extends Component<Props, State> { class CustomLinks extends Component<Props, State> {
state: State = { state: State = {
links: [] links: [],
};
topLinkref: any = null;
setTopLinkRef = (dom: any) => (this.topLinkref = dom);
rightLinkref: any = null;
setRightLinkRef = (dom: any) => (this.rightLinkref = dom);
leftLinkref: any = null;
setLeftLinkRef = (dom: any) => (this.leftLinkref = dom);
sendParentMessage = (link: string) => {
parent.postMessage(
{
flipside: {
type: "linkAction",
linkAction: { href: link },
},
},
"*"
);
};
onClickLink = (e: any) => {
e.stopPropagation();
e.cancelBubble;
let href;
if (!e.target || (e.target && !e.target.getAttribute)) {
href = "https://flipsidecrypto.com";
} else {
href = e.target.getAttribute("href");
}
try {
this.sendParentMessage(href);
} catch (e) {
console.log(e);
}
window.location.assign(href);
};
handleLink = (ref: any, linkType: string) => {
const linkParent = ref;
if (!linkParent) return;
const link = linkParent.children[0];
if (!link) return;
link.removeEventListener("click", this.onClickLink);
link.addEventListener("click", this.onClickLink);
}; };
async componentDidMount() { async componentDidMount() {
@ -34,6 +85,14 @@ class CustomLinks extends Component<Props, State> {
} }
const res = await this.props.api.fetchWidgetLinks(this.props.widget); const res = await this.props.api.fetchWidgetLinks(this.props.widget);
this.setState({ links: res.data }); this.setState({ links: res.data });
let that = this;
let interval = setInterval(() => {
that.handleLink(this.topLinkref, "top");
that.handleLink(this.rightLinkref, "right");
that.handleLink(this.leftLinkref, "left");
}, 100);
setTimeout(() => clearInterval(interval), 5000);
} }
render(props: Props, state: State) { render(props: Props, state: State) {
@ -42,7 +101,17 @@ class CustomLinks extends Component<Props, State> {
return ( return (
<div class={css.wrapper} style={props.style}> <div class={css.wrapper} style={props.style}>
<span class={linkClass}> <span class={linkClass}>
<a href="https://flipsidecrypto.com/fcas">What's this?</a> <a
href="https://flipsidecrypto.com/fcas"
onClick={(e) => {
e.stopPropagation();
e.cancelBubble;
this.sendParentMessage("https://flipsidecrypto.com/fcas");
window.location.assign("https://flipsidecrypto.com/fcas");
}}
>
What's this?
</a>
</span> </span>
</div> </div>
); );
@ -51,22 +120,26 @@ class CustomLinks extends Component<Props, State> {
const leftLink = find(state.links, { name: "left_link" }); const leftLink = find(state.links, { name: "left_link" });
const rightLink = find(state.links, { name: "right_link" }); const rightLink = find(state.links, { name: "right_link" });
const topLink = find(state.links, { name: "top_link" }); const topLink = find(state.links, { name: "top_link" });
return ( return (
<div class={css.wrapper} style={props.style}> <div class={css.wrapper} style={props.style}>
{topLink && ( {topLink && (
<span <span
ref={this.setTopLinkRef}
class={linkClass} class={linkClass}
dangerouslySetInnerHTML={{ __html: topLink.link_html }} dangerouslySetInnerHTML={{ __html: topLink.link_html }}
/> />
)} )}
{leftLink && ( {leftLink && (
<span <span
ref={this.setLeftLinkRef}
class={linkClass} class={linkClass}
dangerouslySetInnerHTML={{ __html: leftLink.link_html }} dangerouslySetInnerHTML={{ __html: leftLink.link_html }}
/> />
)} )}
{rightLink && ( {rightLink && (
<span <span
ref={this.setRightLinkRef}
class={linkClass} class={linkClass}
dangerouslySetInnerHTML={{ __html: rightLink.link_html }} dangerouslySetInnerHTML={{ __html: rightLink.link_html }}
/> />

View File

@ -2,6 +2,7 @@ import loadJS from "load-js";
import API from "../api"; import API from "../api";
import template from "lodash/template"; import template from "lodash/template";
import mapValues from "lodash/mapValues"; import mapValues from "lodash/mapValues";
import { stringify } from "querystring";
type DynamicOpts = { type DynamicOpts = {
widgetId: string; widgetId: string;
@ -42,7 +43,7 @@ function interpolateConfig(functionConfigTemplate: Object, data: Object): any {
const walk = (d: any): any => { const walk = (d: any): any => {
if (typeof d === "string") { if (typeof d === "string") {
let n = parseInt(d); let n = parseInt(d);
if (!n) return d; if (!n || (n && JSON.stringify(n).length != d.length)) return d;
return n; return n;
} }

View File

@ -4,15 +4,18 @@ type Props = {
apiKey: string; apiKey: string;
mode: string; mode: string;
url: string; url: string;
width?: number; width?: string;
height?: number; height?: string;
data?: any; data?: any;
messageKey?: string; messageKey?: string;
messagePayloadType?: string; messagePayloadType?: string;
messagePayloadActionKey?: string; messagePayloadActionKey?: string;
}; };
type State = {}; type State = {
height: string;
width: string;
};
export default class Frame extends Component<Props, State> { export default class Frame extends Component<Props, State> {
static defaultProps = { static defaultProps = {
@ -28,6 +31,10 @@ export default class Frame extends Component<Props, State> {
ref: any = null; ref: any = null;
setRef = (dom: any) => (this.ref = dom); setRef = (dom: any) => (this.ref = dom);
handleResize = (height: string, width: string) => {
this.setState({ height: height, width: width });
};
handleMessage = (e: any) => { handleMessage = (e: any) => {
const eventData = e.data; const eventData = e.data;
if (!eventData) return; if (!eventData) return;
@ -39,8 +46,16 @@ export default class Frame extends Component<Props, State> {
} = this.props; } = this.props;
const message = eventData[messageKey]; const message = eventData[messageKey];
if (!message) return; if (!message) return;
if (message.type == "sizeAction") {
return this.handleResize(
message["sizeAction"].height,
message["sizeAction"].width
);
}
if (message.type !== messagePayloadType) return; if (message.type !== messagePayloadType) return;
const payload = message[messagePayloadType]; const payload = message[messagePayloadType];
@ -52,10 +67,15 @@ export default class Frame extends Component<Props, State> {
window.location.assign(messageAction); window.location.assign(messageAction);
}; };
componentDidMount() { componentWillMount() {
window.addEventListener("message", this.handleMessage, false); window.addEventListener("message", this.handleMessage, false);
if (!this.ref) return; if (!this.ref) return;
this.setState({
height: this.props.height,
width: this.props.width,
});
const widgetData = { const widgetData = {
mode: this.props.mode, mode: this.props.mode,
data: this.props.data, data: this.props.data,
@ -73,15 +93,19 @@ export default class Frame extends Component<Props, State> {
}, },
}, },
}; };
this.ref.contentWindow.postMessage( let that = this;
{ let interval = setInterval(() => {
flipsidePartner: { that.ref.contentWindow.postMessage(
type: "widgetData", {
widgetData: widgetData, flipsidePartner: {
type: "widgetData",
widgetData: widgetData,
},
}, },
}, "*"
"*" );
); }, 200);
setTimeout(() => clearInterval(interval), 5000);
} }
componentWillUnmount() { componentWillUnmount() {
@ -98,6 +122,7 @@ export default class Frame extends Component<Props, State> {
) { ) {
urlParams = { ...props.data, ...urlParams }; urlParams = { ...props.data, ...urlParams };
} }
const urlEncodedParams = new URLSearchParams(urlParams).toString(); const urlEncodedParams = new URLSearchParams(urlParams).toString();
url = `${url}?${urlEncodedParams}`; url = `${url}?${urlEncodedParams}`;
@ -105,9 +130,9 @@ export default class Frame extends Component<Props, State> {
<iframe <iframe
ref={this.setRef} ref={this.setRef}
src={url} src={url}
style={{ width: props.width, height: props.height, border: 0 }} style={{ width: state.width, height: state.height, border: 0 }}
width={props.width} width={state.width}
height={props.height} height={state.height}
/> />
); );
} }