From 7813d181fb0992de4d682fc4d3841290e2cb4b1c Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Nov 30 2017 10:17:15 +0000 Subject: Library widget rework Fixes #433 --- diff --git a/hubs/static/client/app/core/utils.js b/hubs/static/client/app/core/utils.js index 4499b04..f3ee5bd 100644 --- a/hubs/static/client/app/core/utils.js +++ b/hubs/static/client/app/core/utils.js @@ -3,7 +3,7 @@ import fetch from 'isomorphic-fetch'; import universal from 'react-universal-component' -export function backendCall(url, fetchConfig, json=false) { +export function backendCall(url, fetchConfig) { console.log("Calling backend:", url, fetchConfig); const baseFetchConfig = { credentials: "same-origin", @@ -12,10 +12,12 @@ export function backendCall(url, fetchConfig, json=false) { fetchConfig = Object.assign({}, baseFetchConfig, fetchConfig); return fetch(url, {...baseFetchConfig, ...fetchConfig}).then( (response) => { - let resultPromise = json ? response.json() : response.text(); + const contentType = response.headers.get("content-type"); + const isJson = (contentType && contentType.includes("application/json")) + let resultPromise = isJson ? response.json() : response.text(); if (!response.ok) { resultPromise = resultPromise.then((content) => { - if (json) { + if (isJson) { // It's an object describing the error. throw content; } else { @@ -30,11 +32,15 @@ export function backendCall(url, fetchConfig, json=false) { } -export function apiCall(url, fetchConfig) { - return backendCall(url, fetchConfig, true).then( +export function apiCall(url, fetchConfig, extractData=true) { + return backendCall(url, fetchConfig).then( result => { if (result.status === "OK") { - return result.data; + if (extractData) { + return result.data; + } else { + return result; + } } else { throw new Error(result.message); } diff --git a/hubs/static/client/app/widgets/library/AddLinkDialog.js b/hubs/static/client/app/widgets/library/AddLinkDialog.js new file mode 100644 index 0000000..f8c4c30 --- /dev/null +++ b/hubs/static/client/app/widgets/library/AddLinkDialog.js @@ -0,0 +1,78 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { apiCall } from '../../core/utils'; +import Modal from '../../components/Modal'; +import SelectLinkForm from "./SelectLinkForm"; +import EditLinkForm from "./EditLinkForm"; + + +export default class AddLinkDialog extends React.Component { + + constructor(props) { + super(props); + this.state = { + linkData: undefined, + error: null, + isLoading: false, + }; + this.selectUrl = this.selectUrl.bind(this); + this.fetchLinkData = this.fetchLinkData.bind(this); + this.addLink = this.addLink.bind(this); + } + + selectUrl(url) { + this.fetchLinkData(url); + } + + fetchLinkData(url) { + const serverUrl = `${this.props.url}?url=${url}`; + this.setState({isLoading: true}); + apiCall(serverUrl).then( + (linkData) => { + this.setState({ + linkData, isLoading: false}); + }, + (error) => { + this.setState({ + error: error.message, isLoading: false}); + } + ); + } + + addLink(link) { + this.props.addLink(link); + } + + render() { + let content = null; + if (!this.state.linkData) { + content = ( + + ); + } else { + content = ( + + ); + } + return ( + + {content} + + ); + } +} diff --git a/hubs/static/client/app/widgets/library/Config.js b/hubs/static/client/app/widgets/library/Config.js new file mode 100644 index 0000000..2aca0b2 --- /dev/null +++ b/hubs/static/client/app/widgets/library/Config.js @@ -0,0 +1,19 @@ +import React from 'react'; +import SimpleWidgetConfig from '../../components/SimpleWidgetConfig'; + + +// Use the default configuration, but filter out the "links" parameter. + +export default function Config(props) { + const widgetParams = props.widget.params.filter((param) => (param.name !== "links")); + const filteredProps = { + ...props, + widget: { + ...props.widget, + params: widgetParams, + } + }; + return ( + + ); +} diff --git a/hubs/static/client/app/widgets/library/EditLinkDialog.js b/hubs/static/client/app/widgets/library/EditLinkDialog.js new file mode 100644 index 0000000..cd4a990 --- /dev/null +++ b/hubs/static/client/app/widgets/library/EditLinkDialog.js @@ -0,0 +1,29 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Modal from '../../components/Modal'; +import EditLinkForm from "./EditLinkForm"; + + +export default class EditLinkDialog extends React.Component { + + render() { + if (!this.props.link) { + return null; + } + return ( + + + + ); + } +} diff --git a/hubs/static/client/app/widgets/library/EditLinkForm.js b/hubs/static/client/app/widgets/library/EditLinkForm.js new file mode 100644 index 0000000..637d370 --- /dev/null +++ b/hubs/static/client/app/widgets/library/EditLinkForm.js @@ -0,0 +1,100 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Spinner from "../../components/Spinner"; + + +export default class EditLinkForm extends React.Component { + + constructor(props) { + super(props); + this.state = this.props.link; + this.onChange = this.onChange.bind(this); + this.onSubmit = this.onSubmit.bind(this); + } + + onChange(e) { + const name = e.target.name; + const value = e.target.value; + this.setState({[name]: value}); + } + + onSubmit(e) { + e.preventDefault(); + this.props.onSubmit(this.state); + } + + render() { + return ( +
+
+
+ + {this.state.url} + +
+
+
+
+ {this.state.image ? + preview + : +

+ (no image preview) +

+ } +
+
+
+ + +
+
+ +