#441 Rewrite the Library widget
Merged 6 years ago by abompard. Opened 6 years ago by abompard.
abompard/fedora-hubs feature/library-rework  into  develop

@@ -57,9 +57,11 @@ 

                  <div className="modal-body">

                    {this.props.children}

                  </div>

-                 <div className="modal-footer">

-                   {this.props.footer}

-                 </div>

+                 { this.props.footer &&

+                   <div className="modal-footer">

+                     {this.props.footer}

+                   </div>

+                 }

              </div>

            </div>

          </div>

@@ -3,7 +3,7 @@ 

  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 @@ 

    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 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);

        }

@@ -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 = (

+         <SelectLinkForm

+           onSelect={this.selectUrl}

+           isLoading={this.state.isLoading}

+           error={this.state.error}

+           />

+       );

+     } else {

+       content = (

+         <EditLinkForm

+           onSubmit={this.addLink}

+           isLoading={this.isLoading}

+           error={this.props.addError}

+           link={this.state.linkData}

+           submitText="Add link"

+           />

+       );

+     }

+     return (

+       <Modal

+         title="Add a link"

+         onCloseClicked={this.props.onCloseClicked}

+         isLarge={Boolean(this.state.linkData)}

+         cssClass="AddLink"

+         >

+         {content}

+       </Modal>

+     );

+   }

+ }

@@ -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 (

+     <SimpleWidgetConfig {...filteredProps} />

+   );

+ }

@@ -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 (

+       <Modal

+         title="Edit link"

+         onCloseClicked={this.props.onCloseClicked}

+         isLarge={true}

+         cssClass="EditLink"

+         >

+         <EditLinkForm

+           onSubmit={this.props.editLink}

+           error={this.props.error}

+           link={this.props.link}

+           submitText="Edit link"

+           />

+       </Modal>

+     );

+   }

+ }

@@ -0,0 +1,95 @@ 

+ import React from 'react';

+ import PropTypes from 'prop-types';

+ import Spinner from "../../components/Spinner";

+ import MissingThumb from "./library-missing-thumb-large.png";

+ 

+ 

+ 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 (

+       <form

+         onSubmit={this.onSubmit}

+         >

+         <div className="row">

+           <div className="col-12 text-truncate">

+             <span title={this.state.url}>

+               {this.state.url}

+             </span>

+           </div>

+         </div>

+         <div className="row">

+           <div className="col-3">

+             <img

+               alt="preview"

+               src={this.state.image || MissingThumb}

+               title="Preview"

+               className="link-preview border border-secondary mt-2"

+               />

+           </div>

+           <div className="col-9">

+             <div className="form-group">

+               <label className="col-form-label" htmlFor="title">

+                 Title

+               </label>

+               <input

+                 type="text"

+                 className="form-control"

+                 name="title"

+                 value={this.state.title}

+                 onChange={this.onChange}

+                 />

+             </div>

+             <div className="form-group">

+               <label className="col-form-label" htmlFor="description">

+                 Description

+               </label>

+               <textarea

+                 name="description"

+                 className="form-control"

+                 value={this.state.description}

+                 rows="3"

+                 onChange={this.onChange}

+                 />

+             </div>

+             <div className="form-group">

+               <button

+                 className="btn btn-primary"

+                 type="submit"

+                 disabled={this.props.isLoading}

+                 >

+                 {this.props.submitText}

+               </button>

+               { this.props.isLoading &&

+                 <Spinner />

+               }

+             </div>

+           </div>

+         </div>

+         { this.props.error &&

+             <div className="alert alert-warning">

+               {this.props.error}

+             </div>

+         }

+       </form>

+     );

+   }

+ }

@@ -0,0 +1,80 @@ 

+ import React from 'react';

+ import PropTypes from 'prop-types';

+ import MissingThumb from "./library-missing-thumb.png";

+ 

+ 

+ export default class Link extends React.Component {

+ 

+   render() {

+     return (

+       <li className="Link media py-2">

+         <div className="mr-2 link-preview">

+           <img

+             className="link-preview mt-2"

+             src={this.props.image || MissingThumb}

+             />

+         </div>

+         <div className={`media-body ${this.props.showDropdown ? "pr-3" : ""}`}>

+           { this.props.showDropdown &&

+             <div

+               className="dropdown"

+               >

+               <a

+                 className="text-secondary dropdown-toggle"

+                 href="#"

+                 role="button"

+                 data-toggle="dropdown"

+                 aria-haspopup="true"

+                 aria-expanded="false"

+                 >

+               </a>

+               <div

+                 className="dropdown-menu dropdown-menu-right"

+                 aria-labelledby="dropdownMenuLink"

+                 >

+                 <a

+                   className="dropdown-item"

+                   href="#"

+                   onClick={this.props.onEdit}

+                   >

+                   Edit item

+                 </a>

+                 <a

+                   className="dropdown-item"

+                   href="#"

+                   onClick={this.props.onDelete}

+                   >

+                   Delete

+                 </a>

+               </div>

+             </div>

+           }

+           <a

+             href={this.props.url}

+             className="d-block"

+             target="_blank"

+             >

+             {this.props.title}

+           </a>

+           <p className="mb-0 description">

+             <small>

+               {this.props.description}

+             </small>

+           </p>

+         </div>

+       </li>

+     );

+   }

+ }

+ Link.propTypes = {

+   showDropDown: PropTypes.bool,

+   url: PropTypes.string.isRequired,

+   title: PropTypes.string.isRequired,

+   description: PropTypes.string,

+   onEdit: PropTypes.func,

+   onDelete: PropTypes.func,

+ }

+ Link.defaultProps = {

+   showDropDown: false,

+   description: null,

+ }

@@ -0,0 +1,60 @@ 

+ import React from 'react';

+ import PropTypes from 'prop-types';

+ import Spinner from "../../components/Spinner";

+ 

+ 

+ export default class SelectLinkForm extends React.Component {

+ 

+   constructor(props) {

+     super(props);

+     this.state = {

+       url: "",

+     };

+     this.onInputChange = this.onInputChange.bind(this);

+     this.onSelect = this.onSelect.bind(this);

+   }

+ 

+   onInputChange(e) {

+     const value = e.target.value;

+     this.setState({url: value});

+   }

+ 

+   onSelect(e) {

+     e.preventDefault();

+     this.props.onSelect(this.state.url);

+   }

+ 

+   render() {

+     return (

+       <div>

+         <form className="form-inline" onSubmit={this.onSelect}>

+           <label className="sr-only" htmlFor="url">URL</label>

+           <input

+             type="text"

+             name="url"

+             className="form-control"

+             autoFocus={true}

+             placeholder="Enter an URL..."

+             value={this.state.url}

+             onChange={this.onInputChange}

+             />

+           <button

+             className="btn btn-primary mx-3"

+             type="submit"

+             disabled={this.props.isLoading}

+             >

+             Fetch URL

+           </button>

+           { this.props.isLoading &&

+             <Spinner circle={true} />

+           }

+         </form>

+         { this.props.error &&

+           <div className="alert alert-warning mt-3">

+             {this.props.error}

+           </div>

+         }

+       </div>

+     );

+   }

+ }

@@ -0,0 +1,243 @@ 

+ import React from 'react';

+ import PropTypes from 'prop-types';

+ import { connect } from 'react-redux';

+ import { apiCall } from '../../core/utils';

+ import WidgetChrome from '../../components/WidgetChrome';

+ import "./library.css";

+ import Link from "./Link";

+ import AddLinkDialog from "./AddLinkDialog";

+ import EditLinkDialog from "./EditLinkDialog";

+ import Pagination from "../../components/Pagination";

+ 

+ 

+ class LibraryWidget extends React.Component {

+ 

+   constructor(props) {

+     super(props);

+     this.state = {

+       links: [],

+       page: null,

+       error: null,

+       isLoading: false,

+       isAddDialogOpened: false,

+       editingLink: false,

+     };

+     this.loadFromServer = this.loadFromServer.bind(this);

+     this.changePage = this.changePage.bind(this);

+     this.onAddDialogOpen = this.onAddDialogOpen.bind(this);

+     this.onAddDialogClose = this.onAddDialogClose.bind(this);

+     this.addLink = this.addLink.bind(this);

+     this.onEditDialogClose = this.onEditDialogClose.bind(this);

+     this.saveEditedLink = this.saveEditedLink.bind(this);

+     this.clearError = this.clearError.bind(this);

+   }

+ 

+   componentDidMount() {

+     if (!this.props.editMode) {

+       this.loadFromServer();

+     }

+   }

+ 

+   loadFromServer(pageNr=1) {

+     const url = `${this.props.widget.urls.data}?page=${pageNr}`;

+     apiCall(url, {}, false).then(

+       (result) => {

+         this.setState({

+           links: result.data,

+           page: result.page,

+           error: null,

+         });

+       },

+       (error) => {

+         console.log(error);

+         this.setState({

+           error: error.message

+         });

+       }

+     );

+   }

+ 

+   changePage(pageNr) {

+     this.loadFromServer(pageNr);

+   }

+ 

+   onAddDialogOpen(e) {

+     this.setState({isAddDialogOpened: true});

+   }

+ 

+   onAddDialogClose(e) {

+     this.setState({isAddDialogOpened: false});

+   }

+ 

+   addLink(link) {

+     const body = JSON.stringify(link);

+     apiCall(this.props.widget.urls.data, {method: "POST", body}).then(

+       (result) => {

+         this.setState((prevState, props) => ({

+             links: [...prevState.links, link], // Optimistic update.

+             isAddDialogOpened: false,

+             error: null,

+           })

+         );

+         this.loadFromServer();

+       },

+       (error) => {

+         console.log(error);

+         this.setState({

+           error: error.message

+         });

+       }

+     );

+   }

+ 

+   editLink(index, e) {

+     e.preventDefault();

+     this.setState((prevState, props) => ({

+       editingLink: prevState.links[index]

+     }));

+   }

+ 

+   onEditDialogClose(e) {

+     this.setState({editingLink: false});

+   }

+ 

+   saveEditedLink(link) {

+     const body = JSON.stringify(link);

+     apiCall(this.props.widget.urls.data, {method: "PUT", body}).then(

+       (result) => {

+         this.setState((prevState, props) => ({

+             links: prevState.links.map((l) => {

+               if (l.url === link.url) {

+                 return link;

+               }

+               return l;

+             }),

+             editingLink: false,

+             error: null,

+           })

+         );

+         this.loadFromServer();

+       },

+       (error) => {

+         console.log(error);

+         this.setState({

+           error: error.message

+         });

+       }

+     );

+   }

+ 

+   deleteLink(index, e) {

+     e.preventDefault();

+     const link = this.state.links[index];

+     const body = JSON.stringify(link);

+     apiCall(this.props.widget.urls.data, {method: "DELETE", body}).then(

+       (result) => {

+         this.setState((prevState, props) => ({

+             links: prevState.links.filter((l) => (l.url !== link.url)),

+             editingLink: false,

+           })

+         );

+         this.loadFromServer();

+       },

+       (error) => {

+         console.log(error);

+         this.setState({

+           error: error.message

+         });

+       }

+     );

+   }

+ 

+   clearError(e) {

+     e.preventDefault();

+     this.setState({error: null});

+   }

+ 

+   render() {

+     const links = this.state.links.map((link, index) => (

+       <Link

+         key={link.url}

+         {...link}

+         onEdit={this.editLink.bind(this, index)}

+         onDelete={this.deleteLink.bind(this, index)}

+         showDropdown={this.props.currentUser.perms.config_hub}

+         />

+       )

+     );

+     return (

+       <WidgetChrome

+         widget={this.props.widget}

+         editMode={this.props.editMode}

+         >

+         <div className="widget-library p-2">

+           { this.state.error &&

+             <div className="alert alert-warning">

+               {this.state.error}

+               <button

+                 type="button"

+                 className="close"

+                 aria-label="Close"

+                 onClick={this.clearError}

+                 >

+                 <span aria-hidden="true">&times;</span>

+               </button>

+             </div>

+           }

+           { links.length > 0 ?

+             <div>

+               <ul className="list-unstyled">

+                 {links}

+               </ul>

+               { this.state.page.total_pages > 1 &&

+                 <Pagination

+                   page={this.state.page}

+                   onPageChange={this.changePage}

+                   className="mt-2 justify-content-center pagination-sm"

+                   />

+               }

+             </div>

+             :

+             <p className="text-secondary">

+               <em>No links yet.</em>

+             </p>

+           }

+           {this.props.currentUser.perms.config_hub &&

+             <div>

+               <div className="text-center">

+                 <button

+                   className="btn btn-secondary btn-sm"

+                   onClick={this.onAddDialogOpen}

+                   >

+                   Add a New Item

+                 </button>

+               </div>

+               {this.state.isAddDialogOpened &&

+                 <AddLinkDialog

+                   onCloseClicked={this.onAddDialogClose}

+                   addLink={this.addLink}

+                   addError={this.state.error}

+                   url={this.props.widget.urls.getLink}

+                   />

+               }

+             </div>

+           }

+           <EditLinkDialog

+             link={this.state.editingLink}

+             editLink={this.saveEditedLink}

+             onCloseClicked={this.onEditDialogClose}

+             error={this.props.error}

+             />

+         </div>

+       </WidgetChrome>

+     );

+   }

+ }

+ 

+ const mapStateToProps = (state) => {

+   return {

+     currentUser: state.currentUser,

+   }

+ };

+ 

+ export default connect(mapStateToProps)(LibraryWidget);

@@ -0,0 +1,99 @@ 

+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>

+ <!-- Created with Inkscape (http://www.inkscape.org/) -->

+ 

+ <svg

+    xmlns:dc="http://purl.org/dc/elements/1.1/"

+    xmlns:cc="http://creativecommons.org/ns#"

+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

+    xmlns:svg="http://www.w3.org/2000/svg"

+    xmlns="http://www.w3.org/2000/svg"

+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"

+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

+    width="72"

+    height="72"

+    viewBox="0 0 0.75 0.75"

+    version="1.1"

+    id="svg80330"

+    sodipodi:docname="library-item-no-thumb-filler.svg"

+    inkscape:version="0.92.2 5c3e80d, 2017-08-06">

+   <defs

+      id="defs80323" />

+   <sodipodi:namedview

+      inkscape:document-units="px"

+      pagecolor="#ffffff"

+      bordercolor="#666666"

+      borderopacity="1.0"

+      inkscape:pageopacity="0.0"

+      inkscape:pageshadow="2"

+      inkscape:zoom="1"

+      inkscape:cx="68.999847"

+      inkscape:cy="-247.61716"

+      inkscape:current-layer="layer1"

+      id="namedview80325"

+      showgrid="false"

+      inkscape:window-width="1280"

+      inkscape:window-height="1376"

+      inkscape:window-x="1280"

+      inkscape:window-y="27"

+      inkscape:window-maximized="0"

+      units="px"

+      width="1080px"

+      inkscape:pagecheckerboard="false"

+      objecttolerance="2"

+      inkscape:snap-path-clip="false"

+      inkscape:snap-path-mask="false"

+      gridtolerance="2"

+      guidetolerance="10"

+      inkscape:snap-perpendicular="true"

+      inkscape:snap-tangential="true"

+      fit-margin-top="0"

+      fit-margin-left="0"

+      fit-margin-right="0"

+      fit-margin-bottom="0" />

+   <metadata

+      id="metadata80327">

+     <rdf:RDF>

+       <cc:Work

+          rdf:about="">

+         <dc:format>image/svg+xml</dc:format>

+         <dc:type

+            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />

+         <dc:title></dc:title>

+         <dc:creator>

+           <cc:Agent>

+             <dc:title>Máirín Duffy &lt;duffy@redhat.com&gt;</dc:title>

+           </cc:Agent>

+         </dc:creator>

+       </cc:Work>

+     </rdf:RDF>

+   </metadata>

+   <g

+      inkscape:label="Layer 1"

+      inkscape:groupmode="layer"

+      id="layer1"

+      transform="translate(-8.5833349,2.9855955)">

+     <rect

+        inkscape:export-ydpi="226.66672"

+        inkscape:export-xdpi="226.66672"

+        inkscape:export-filename="/home/duffy/library-missing-thumb.png"

+        y="-2.9855955"

+        x="8.5833349"

+        height="0.75"

+        width="0.75"

+        id="rect817585"

+        style="opacity:1;fill:#58595b;fill-opacity:1;stroke:none;stroke-width:0.01041667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952" />

+     <g

+        id="use819155"

+        style="fill:#e7e8e9;fill-opacity:1;stroke-width:0.01486988"

+        transform="matrix(0.00729709,0,0,0.00729709,8.6781267,-2.9375051)">

+       <title

+          id="title918616">Globe</title>

+       <path

+          inkscape:connector-curvature="0"

+          id="path918618"

+          d="m 768,1408 q 209,0 385.5,-103 Q 1330,1202 1433,1025.5 1536,849 1536,640 1536,431 1433,254.5 1330,78 1153.5,-25 977,-128 768,-128 559,-128 382.5,-25 206,78 103,254.5 0,431 0,640 0,849 103,1025.5 206,1202 382.5,1305 559,1408 768,1408 Z m 274,-521 q -2,-1 -9.5,-9.5 -7.5,-8.5 -13.5,-9.5 2,0 4.5,5 2.5,5 5,11 2.5,6 3.5,7 6,7 22,15 14,6 52,12 34,8 51,-11 -2,2 9.5,13 11.5,11 14.5,12 3,2 15,4.5 12,2.5 15,7.5 l 2,22 q -12,-1 -17.5,7 -5.5,8 -6.5,21 0,-2 -6,-8 0,7 -4.5,8 -4.5,1 -11.5,-1 -7,-2 -9,-1 -10,3 -15,7.5 -5,4.5 -8,16.5 -3,12 -4,15 -2,5 -9.5,10.5 -7.5,5.5 -9.5,10.5 -1,2 -2.5,5.5 -1.5,3.5 -3,6.5 -1.5,3 -4,5.5 -2.5,2.5 -5.5,2.5 -3,0 -7,-5 -4,-5 -7.5,-10 -3.5,-5 -4.5,-5 -3,2 -6,1.5 -3,-0.5 -4.5,-1 -1.5,-0.5 -4.5,-3 -3,-2.5 -5,-3.5 -3,-2 -8.5,-3 -5.5,-1 -8.5,-2 15,5 -1,11 -10,4 -16,3 9,4 7.5,12 -1.5,8 -8.5,14 h 5 q -1,4 -8.5,8.5 -7.5,4.5 -17.5,8.5 -10,4 -13,6 -8,5 -34,9.5 -26,4.5 -33,0.5 -5,-6 -4.5,-10.5 0.5,-4.5 4,-14 3.5,-9.5 3.5,-12.5 1,-6 -5.5,-13 -6.5,-7 -6.5,-12 0,-7 14,-15.5 14,-8.5 10,-21.5 -3,-8 -16,-16 -13,-8 -16,-12 -5,-8 -1.5,-18.5 Q 907,958 914,952 q 2,-2 1.5,-4 -0.5,-2 -3.5,-4.5 -3,-2.5 -5.5,-4 Q 904,938 900,936 l -3,-2 q -11,-5 -20.5,6 -9.5,11 -13.5,26 -7,25 -16,30 -23,8 -29,-1 -5,13 -41,26 -25,9 -58,4 6,1 0,15 -7,15 -19,12 3,6 4,17.5 1,11.5 1,13.5 3,13 12,23 1,1 7,8.5 6,7.5 9.5,13.5 3.5,6 0.5,6 35,-4 50,11 5,5 11.5,17 6.5,12 10.5,17 9,6 14,5.5 5,-0.5 14.5,-5.5 9.5,-5 14.5,-5 14,-1 15.5,11 1.5,12 -7.5,20 12,-1 3,17 -5,7 -8,9 -12,4 -27,-5 -8,-4 2,-8 -1,1 -9.5,-10.5 Q 809,1196 801,1190 q -8,-6 -16,5 -1,1 -5.5,13.5 -4.5,12.5 -9.5,13.5 -8,0 -16,-15 3,8 -11,15 -14,7 -24,8 19,12 -8,27 -7,4 -20.5,5 -13.5,1 -19.5,-4 -5,-7 -5.5,-11.5 -0.5,-4.5 5,-8 5.5,-3.5 10.5,-5.5 5,-2 11.5,-4 6.5,-2 8.5,-3 14,-10 8,-14 -2,-1 -8.5,-3.5 -6.5,-2.5 -11.5,-4.5 -5,-2 -6,-4 -3,-4 0,-14 3,-10 -2,-14 -5,5 -9,17.5 -4,12.5 -7,16.5 7,-9 -25,-6 l -10,1 q -4,0 -16,-2 -12,-2 -20.5,-1 -8.5,1 -13.5,8 -4,8 0,20 1,4 4,2 -4,3 -11,9.5 -7,6.5 -10,8.5 -46,-15 -94,-41 6,-1 12,1 5,2 13,6.5 8,4.5 10,5.5 34,14 42,7 l 5,5 q 14,-16 20,-25 -7,4 -30,1 -20,-6 -22,-12 7,-12 5,-18 -4,3 -11.5,10 -7.5,7 -14.5,11 -7,4 -15,5 -16,0 -22,-1 -146,-80 -235,-222 7,-7 12,-8 4,-1 5,-9 1,-8 2.5,-11 1.5,-3 11.5,3 9,-8 3,-19 1,1 44,-27 19,-17 21,-21 3,-11 -10,-18 -1,2 -9,9 -8,7 -9,4 -3,-5 0.5,-18.5 Q 301,850 308,851 301,851 298.5,835 296,819 296,799.5 296,780 295,776 l 2,-1 q -3,-12 5.5,-34.5 Q 311,718 324,721 q -13,-3 20,-43 6,-8 8,-9 3,-2 12,-7.5 9,-5.5 15,-10 6,-4.5 10,-10.5 4,-5 10,-22.5 6,-17.5 14,-23.5 -2,-6 9.5,-20 11.5,-14 10.5,-23 -1,0 -2.5,-1 -1.5,-1 -2.5,-1 3,-7 15.5,-14 12.5,-7 15.5,-13 1,-3 2,-10 1,-7 3,-11 2,-4 8,-2 2,20 -24,62 -15,25 -17,29 -3,5 -5.5,15.5 -2.5,10.5 -4.5,14.5 2,0 6,-1.5 4,-1.5 8.5,-3.5 4.5,-2 7.5,-4 3,-2 2,-3 -3,-7 2,-17.5 5,-10.5 12,-18.5 7,-8 17,-19 10,-11 12,-13 6,-6 14,-19.5 8,-13.5 0,-13.5 9,0 20,-10 11,-10 17,-20 5,-8 8,-26 3,-18 5,-24 2,-7 8.5,-13.5 Q 567,408 573,405 l 16,-8 q 0,0 13,-7 5,-2 18.5,-10.5 Q 634,371 642,368 q 10,-4 16,-4 6,0 14.5,2.5 8.5,2.5 13.5,3.5 15,2 29,-15 14,-17 21,-21 36,-19 55,-11 -2,-1 0.5,-7.5 2.5,-6.5 8,-15.5 5.5,-9 9,-14.5 3.5,-5.5 5.5,-8.5 5,-6 18,-15 13,-9 18,-15 6,4 7,9 -3,-8 7,-20 10,-12 18,-10 14,3 14,32 -31,-15 -49,18 0,1 -2.5,5.5 -2.5,4.5 -4,8.5 -1.5,4 -2.5,8.5 -1,4.5 0,7.5 1,3 5,3 9,0 10,3.5 1,3.5 -2,12.5 -3,9 -4,13 -1,8 -11,20 -10,12 -12,15 -5,-9 -16,-8 -11,1 -16,9 0,-1 -1.5,-5.5 -1.5,-4.5 -1.5,-6.5 -13,0 -15,1 1,3 2.5,17.5 1.5,14.5 3.5,22.5 1,4 5.5,12 4.5,8 7.5,14.5 3,6.5 4,12.5 1,6 -4.5,9.5 -5.5,3.5 -17.5,2.5 -19,-1 -26,-20 -1,-3 -3,-10.5 -2,-7.5 -5,-11.5 -3,-4 -9,-7 -7,-3 -24,-2 -17,1 -24,5 -13,8 -22.5,29 -9.5,21 -9.5,37 0,10 2.5,26.5 2.5,16.5 3,25 0.5,8.5 -5.5,24.5 3,2 9,9.5 6,7.5 10,10.5 2,1 4.5,1.5 2.5,0.5 4.5,0 2,-0.5 4,1.5 2,2 3,6 -1,1 -4,3 -3,3 -4,3 7,-3 28.5,1.5 21.5,4.5 27.5,-1.5 15,-11 22,2 0,1 -2.5,9.5 -2.5,8.5 -0.5,13.5 5,-27 29,-9 3,-3 15.5,-5 12.5,-2 17.5,-5 3,-2 7,-5.5 4,-3.5 5.5,-4.5 1.5,-1 5,0.5 3.5,1.5 8.5,6.5 10,-14 12,-24 11,-40 19,-44 7,-3 11,-2 4,1 4.5,9.5 0.5,8.5 0,14 Q 888,547 887,554 l -1,8 v 18 l -1,8 q -15,3 -18.5,12 -3.5,9 1.5,18.5 5,9.5 15,18.5 1,1 8,3.5 7,2.5 15.5,6.5 8.5,4 12.5,8 21,19 15,35 7,0 11,9 -1,0 -5,3 -4,3 -7.5,5 -3.5,2 -4.5,2 9,5 2,16 5,3 7.5,11 2.5,8 7.5,10 9,-12 21,-2 7,8 1,16 5,7 20.5,10.5 15.5,3.5 18.5,9.5 7,-2 8,2 1,4 1,12 0,8 3,12 4,5 15,9 11,4 13,5 l 17,11 q 3,4 0,4 18,-2 31,11 10,11 -6,20 3,6 -3,9.5 -6,3.5 -15,5.5 3,1 11.5,0.5 8.5,-0.5 10.5,1.5 15,10 -7,16 -17,5 -43,-12 z M 879,10 q 206,36 351,189 -3,3 -12.5,4.5 -9.5,1.5 -12.5,3.5 -18,7 -24,8 1,7 -2.5,13 -3.5,6 -8,9 -4.5,3 -12.5,8 -8,5 -11,7 -2,2 -7,6 -5,4 -7,5.5 -2,1.5 -7.5,4.5 -5.5,3 -8.5,2 -3,-1 -10,-1 l -3,-1 q -3,-1 -5.5,-2.5 -2.5,-1.5 -5.5,-3 -3,-1.5 -4,-3 -1,-1.5 0,-2.5 -21,17 -36,22 -5,1 -11,5.5 -6,4.5 -10.5,7 -4.5,2.5 -10,1.5 -5.5,-1 -11.5,-7 -5,-5 -6,-15 -1,-10 -2,-13 -7,5 0,17.5 7,12.5 2,18.5 -3,6 -10.5,4.5 -7.5,-1.5 -12,-4.5 -4.5,-3 -11.5,-8.5 -7,-5.5 -9,-6.5 -2,-1 -8.5,-5.5 -6.5,-4.5 -8.5,-7.5 -3,-4 -6,-12 -3,-8 -5,-11 -2,4 -11.5,6.5 -9.5,2.5 -9.5,5.5 2,-10 4,-35 2,-25 5,-38 7,-31 -12,-48 -27,-25 -29,-40 -4,-22 12,-26 0,-7 -8,-20.5 -8,-13.5 -7,-21.5 0,-6 2,-16 z"

+          transform="matrix(0.05,0,0,-0.05,0,76.8)"

+          style="stroke-width:0.01486988" />

+     </g>

+   </g>

+ </svg>

@@ -0,0 +1,21 @@ 

+ .widget-library div.link-preview {

+   max-width: 25%;

+ }

+ .widget-library img.link-preview {

+   width: 100%;

+   display: inline-block;

+ }

+ 

+ 

+ .widget-library .Link {

+     border-bottom: 1px solid #eee;

+ }

+ 

+ .widget-library .Link .dropdown {

+     position: absolute;

+     right: .5em;

+ }

+ 

+ .widget-library .Link .description {

+     line-height: 1;

+ }

@@ -0,0 +1,771 @@ 

+ interactions:

+ - request:

+     body: null

+     headers:

+       Accept: ['*/*']

+       Accept-Encoding: ['gzip, deflate']

+       Connection: [keep-alive]

+       User-Agent: [python-requests/2.18.4]

+     method: GET

+     uri: http://fedoraproject.org/wiki/Design

+   response:

+     body:

+       string: !!binary |

+         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

+     headers:

+       accept-ranges: [bytes]

+       age: ['395956']

+       appserver: [proxy07.fedoraproject.org]

+       apptime: [D=7073]

+       cache-control: ['s-maxage=432000, must-revalidate, max-age=0']

+       connection: [Keep-Alive]

+       content-encoding: [gzip]

+       content-language: [en]

+       content-length: ['10650']

+       content-type: [text/html; charset=UTF-8]

+       date: ['Sat, 11 Nov 2017 02:13:08 GMT']

+       etag: ['W/"fpo-mediawiki-en_:pcache:idhash:20616-0!1!0!!en!2!edit=0--20170923153854-gzip"']

+       keep-alive: ['timeout=15, max=500']

+       last-modified: ['Fri, 13 Oct 2017 18:45:55 GMT']

+       referrer-policy: [same-origin]

+       server: [Apache/2.2.15 (Red Hat)]

+       vary: ['Accept-Encoding,Cookie,User-Agent']

+       via: [1.1 varnish-v4]

+       x-content-type-options: [nosniff, nosniff]

+       x-frame-options: [SAMEORIGIN]

+       x-powered-by: [PHP/5.3.3]

+       x-varnish: [2983663 1540191]

+       x-xss-protection: [1; mode=block]

+     status: {code: 200, message: OK}

+ - request:

+     body: null

+     headers:

+       Accept: ['*/*']

+       Accept-Encoding: ['gzip, deflate']

+       Connection: [keep-alive]

+       User-Agent: [python-requests/2.18.4]

+     method: GET

+     uri: http://blog.linuxgrrl.com/

+   response:

+     body:

+       string: !!binary |

+         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

+         WgBY+sjpIDDVeIv/s2oxT/4FGg/saQWOAQA=

+     headers:

+       connection: [Keep-Alive]

+       content-encoding: [gzip]

+       content-type: [text/html; charset=UTF-8]

+       date: ['Wed, 15 Nov 2017 16:16:07 GMT']

+       keep-alive: ['timeout=2, max=100']

+       link: ['<http://blog.linuxgrrl.com/wp-json/>; rel="https://api.w.org/", <https://wp.me/1E19J>;

+           rel=shortlink']

+       server: [Apache]

+       vary: [Accept-Encoding]

+     status: {code: 200, message: OK}

+ version: 1

@@ -1,26 +1,101 @@ 

  from __future__ import unicode_literals

  

+ import json

+ 

+ from hubs.app import app

  from hubs.tests import FakeAuthorization, widget_instance

  from . import WidgetTest

  

  

  class TestLibrary(WidgetTest):

      plugin = 'library'  # The name in hubs.widgets.registry

+     maxDiff = None

  

      def test_data_simple(self):

          widget = widget_instance('ralph', self.plugin)

          user = FakeAuthorization('ralph')

          response = self.check_url(

-             '/ralph/w/%s/%i/' % (self.plugin, widget.idx), user)

+             '/ralph/w/%s/%i/data' % (self.plugin, widget.idx), user)

          expected_dict = {

-             "urls": [

-                 "<a href=\"ralph/\">ralph/</a>"

-             ],

-             'edit_mode': False,

-             'widget': widget.module,

-             'widget_instance': widget,

+             'data': [],

+             'page': {

+                 'has_next': False,

+                 'has_prev': False,

+                 'nr': 1,

+                 'total_entries': 0,

+                 'total_pages': 1

+             },

+             'status': 'OK',

          }

-         self.assertDictEqual(response.context, expected_dict)

+         data = json.loads(response.get_data(as_text=True))

+         self.assertDictEqual(data, expected_dict)

  

-     def test_view_authz(self):

-         self._test_view_authz()

+     def test_props(self):

+         widget = widget_instance('ralph', self.plugin)

+         with app.test_request_context('/'):

+             props = widget.get_props()

+         self.assertDictEqual(props, {

+             'component': 'library',

+             'config': {'links': [], 'per_page': 4},

+             'cssClass': None,

+             'hiddenIfEmpty': False,

+             'idx': widget.idx,

+             'index': 51,

+             'isReact': True,

+             'isLarge': False,

+             'label': 'Library',

+             'name': 'library',

+             'params': [

+                 {'default': [],

+                  'help': 'A JSON list of dicts with `url`, `title`, '

+                          '`description`, and `image` keys.',

+                  'label': 'Links',

+                  'name': 'links',

+                  'renderTag': 'input',

+                  'renderAttributes': {'type': 'text'},

+                  },

+                 {'default': 4,

+                  'help': 'The number of links per page to display.',

+                  'label': 'Links per page',

+                  'name': 'per_page',

+                  'renderTag': 'input',

+                  'renderAttributes': {'type': 'text'},

+                  },

+             ],

+             'position': 'right',

+             'selfUrl': '/api/hubs/ralph/widgets/{}/'.format(widget.idx),

+             'title': 'Library',

+             'urls': {

+                 'data': '/ralph/w/library/{}/data'.format(widget.idx),

+                 'getLink': '/ralph/w/library/{}/get-link'.format(

+                     widget.idx),

+             }

+         })

+ 

+     def test_get_link(self):

+         widget = widget_instance('ralph', self.plugin)

+         user = FakeAuthorization('ralph')

+         backend_url = "/ralph/w/{}/{}/get-link".format(self.plugin, widget.idx)

+         test_urls = [

+             {

+                 'url': 'http://fedoraproject.org/wiki/Design',

+                 'description': "",

+                 'image': None,

+                 'title': 'Design - FedoraProject',

+             }, {

+                 'url': 'http://blog.linuxgrrl.com/',

+                 'description': 'Open design forever.',

+                 'image': 'https://s0.wp.com/i/blank.jpg',

+                 'title': 'M\xe1ir\xedn Duffy',

+             },

+         ]

+         for test_url in test_urls:

+             response = self.check_url(

+                 "{}?url={}".format(backend_url, test_url["url"]),

+                 user)

+             expected_dict = {

+                 'data': test_url,

+                 'status': 'OK'

+             }

+             data = json.loads(response.get_data(as_text=True))

+             self.assertDictEqual(expected_dict, data)

file modified
+4 -2
@@ -143,8 +143,10 @@ 

      for param in widget_instance.module.get_parameters():

          val = widget_config.get(param.name)

          if not val:

-             raise WidgetConfigError(

-                 'You must provide a value for: %s' % param.name)

+             if param.default is None:

+                 raise WidgetConfigError(

+                     'You must provide a value for: %s' % param.name)

+             val = param.default

          values[param.name] = val

      try:

          config = widget_instance.module.validate_parameters(values)

file modified
+1
@@ -80,6 +80,7 @@ 

          """

          config = {}

          for param in self.get_parameters():

+             print(param.name, param.validator, values[param.name])

              config[param.name] = param.validator(values[param.name])

          return config

  

@@ -1,32 +1,40 @@ 

  from __future__ import unicode_literals

  

- from hubs.widgets import clean_input, validators

+ import flask

+ 

+ from hubs.widgets import validators

  from hubs.widgets.base import Widget

- from hubs.widgets.view import RootWidgetView

  

  

  class Library(Widget):

  

      name = "library"

      position = "both"

-     parameters = [dict(

-         name="urls",

-         label="URLs",

-         default=None,

-         validator=validators.Text,

-         help="A comma separated list of URLs to add to the library. "

-              "External links must include the whole link "

-              "(starting with http...)."

+     parameters = [

+         dict(

+             name="links",

+             label="Links",

+             default=[],

+             help="A JSON list of dicts with `url`, `title`, `description`, "

+                  "and `image` keys."

+         ), dict(

+             name="per_page",

+             label="Links per page",

+             default=4,

+             validator=validators.Integer,

+             help="The number of links per page to display.",

          )]

+     is_react = True

+     views_module = ".views"

  

- 

- class BaseView(RootWidgetView):

- 

-     def get_context(self, instance, *args, **kwargs):

-         urls = [

-             clean_input.clean(

-                 '<a href="{0}">{0}</a>'.format(u.strip()))

-             for u in instance.config.get('urls', '').split(',')

-             if u.strip()

-         ]

-         return dict(urls=urls)

+     def get_props(self, instance, *args, **kwargs):

+         props = super(Library, self).get_props(instance, *args, **kwargs)

+         if instance is not None:

+             hub_name = instance.hub.name

+             props["urls"] = dict(

+                 data=flask.url_for(

+                     "library_data", hub=hub_name, idx=instance.idx),

+                 getLink=flask.url_for(

+                     "library_get_link", hub=hub_name, idx=instance.idx),

+                 )

+         return props

@@ -1,11 +0,0 @@ 

- <div class="rules-container">

-   <div class="row">

-     <ul>

-     {% for url in urls %}

-     <li>

-       {{ url }}

-     </li>

-     {% endfor %}

-     </ul>

-   </div>

- </div>

@@ -0,0 +1,114 @@ 

+ from __future__ import unicode_literals

+ 

+ import flask

+ import requests

+ from bs4 import BeautifulSoup

+ 

+ from hubs.utils.pagination import paginate

+ from hubs.widgets.view import WidgetView

+ from hubs.utils.views import check_hub_access

+ 

+ 

+ class LinkValidationError(Exception):

+ 

+     def __init__(self, message):

+         self.message = message

+ 

+ 

+ def validate_link(link):

+     if not link["url"]:

+         raise LinkValidationError("The link must have an URL")

+     if not link["title"]:

+         raise LinkValidationError("The link must have a title")

+ 

+ 

+ class DataView(WidgetView):

+ 

+     name = "data"

+     url_rules = ["data"]

+     methods = ['GET', 'POST', 'PUT', 'DELETE']

+     json = True

+ 

+     def get_context(self, instance, *args, **kwargs):

+         if flask.request.method in ["POST", "PUT", "DELETE"]:

+             # Updating in-place is not supported, it's a class property.

+             config = instance.config.copy()

+             try:

+                 if flask.request.method == "POST":

+                     check_hub_access(instance.hub, "config", json=True)

+                     new_link = flask.request.get_json()

+                     validate_link(new_link)

+                     if new_link["url"] in [l["url"] for l in config["links"]]:

+                         raise LinkValidationError(

+                             "This URL is already in the library")

+                     config["links"].append(new_link)

+                 elif flask.request.method == "PUT":

+                     check_hub_access(instance.hub, "config", json=True)

+                     link = flask.request.get_json()

+                     config["links"] = list(map(

+                         lambda l: link if l["url"] == link["url"] else l,

+                         config["links"]))

+                 elif flask.request.method == "DELETE":

+                     check_hub_access(instance.hub, "config", json=True)

+                     link = flask.request.get_json()

+                     config["links"] = list(filter(

+                         lambda l: l["url"] != link["url"],

+                         config["links"]))

+             except LinkValidationError as e:

+                 return dict(

+                     status="ERROR",

+                     message=e.message,

+                     )

+             instance.config = config

+             flask.g.db.commit()

+             return {"status": "OK"}

+         links, page_data = paginate(

+             instance.config["links"], instance.config["per_page"])

+         return dict(status="OK", data=links, page=page_data)

+ 

+ 

+ class GetLinkView(WidgetView):

+     """XXX

+     """

+ 

+     name = "get_link"

+     url_rules = ["get-link"]

+     json = True

+ 

+     def get_context(self, instance, *args, **kwargs):

+         url = flask.request.values.get("url")

+         if not url:

+             return dict(status="ERROR", message="No URL.")

+         try:

+             response = requests.get(url, timeout=10)

+         except requests.exceptions.Timeout:

+             return dict(status="ERROR", message="Connection timed out.")

+         if not response.ok:

+             return dict(

+                 status="ERROR",

+                 message="Could not fetch this URL: error {}.".format(

+                     response.status_code)

+                 )

+         soup = BeautifulSoup(response.text, 'html.parser')

+         # Title

+         title = soup.head.find("meta", property="og:title")

+         if title is None:

+             title = soup.head.title.string

+         else:

+             title = title["content"]

+         # Description

+         desc = soup.head.find("meta", property="og:description")

+         if desc is None:

+             desc = soup.head.find("meta", attrs={"name": "description"})

+         else:

+             desc = desc["content"]

+         # Image

+         image = soup.head.find("meta", property="og:image")

+         if image is not None:

+             image = image["content"]

+         return dict(status="OK", data=dict(

+             url=url,

+             title=title or "",

+             description=desc or "",

+             image=image,

+         ))

file modified
+1
@@ -1,5 +1,6 @@ 

  alembic

  arrow

+ beautifulsoup4

  bleach<2.0.0

  blinker

  python-dateutil

Rewrite the Library widget to implement the mockup in issue #433.

Looks good to me :thumbsup:

Hey I tried this out but couldn't get a fedora wiki link to work when adding to library - i get this -

15:29:55 web.1 | File "/usr/lib/python2.7/site-packages/requests/models.py", line 355, in prepare_url
15:29:55 web.1 | raise MissingSchema(error)
15:29:55 web.1 | MissingSchema: Invalid URL 'fedoraproject.org/wiki/Design': No schema supplied. Perhaps you meant http://fedoraproject.org/wiki/Design?

The UI gives some spew about schema as well:

<html> <head> <title>TypeError: find() got multiple values for keyword argument 'name' // Werkzeug Debugger</title> <link rel="stylesheet" href="?__debugger__=yes&cmd=resource&f=style.css" type="text/css"> <link rel="shortcut icon" href="?__debugger__=yes&cmd=resource&f=console.png"> <script src="?__debugger__=yes&cmd=resource&f=jquery.js"></script> <script src="?__debugger__=yes&cmd=resource&f=debugger.js"></script> <script type="text/javascript"> var TRACEBACK = 140068757756176, CONSOLE_MODE = false, EVALEX = true, EVALEX_TRUSTED = false, SECRET = "OHzrwdHYr01DDcdK97qU"; </script> </head> <body>

TypeError

TypeError: find() got multiple values for keyword argument 'name'

Traceback (most recent call last)

  • File "/usr/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__

     error = None
     ctx.auto_pop(error)
     
     def __call__(self, environ, start_response):
     """Shortcut for :attr:`wsgi_app`."""
     return self.wsgi_app(environ, start_response)
     
     def __repr__(self):
     return '<%s %r>' % (

    The URLs I tried to add and got this error for are:

    http://fedoraproject.org/wiki/Design
    http://pagure.io/design
    http://sparkleshare.org

    I also tried with https.

Just an idea - can file this as an issue if useful - we should have a default 'no thumbnail' image to use for sites that don't have one. I encountered this when trying to add my blog to my hub -

http://blog.linuxgrrl.com/

I have an image you can use for this, PR comments dont seem to allow for attaching images so i'll attach to #433

@sayanchowdhury Ah, the XXX is there because I meant to add documentation but forgot ;-)

@duffy good catch with the error, I'll fix it. I'll also add the placeholder image, thanks.

Actually @duffy, your blog metadata says it has an image, but it points to https://s0.wp.com/i/blank.jpg which, as the name says, is blank.

I'll add the placeholder anyway for the URLs that don't set a metadata image, but I'm not sure I can do much for blank images (except allowing uploads but that's probably not for the MVP).

Also, @duffy could you make a higher resolution of the placeholder image? Something around 170px would look better in the "link edit" modal.

rebased onto 6fbdf05f518600217071c93690eca8f1f1229241

6 years ago

rebased onto dfbe155f51f2118c9624cb7e4aaf9cfe8ff859d4

6 years ago

rebased onto f7d1f7da04ee9f3cfb64974943d79bb8869eeeb9

6 years ago

Since this PR has already been reviewed I'll just merge it.

rebased onto 66e7033

6 years ago

Pull-Request has been merged by abompard

6 years ago