import React from "react" ; import { Link } from "react-router-dom" ; import { Menu, MenuList, MenuButton, MenuItem } from "@reach/menu-button" ; import { ArticleSearchResult2 } from "./ArticleSearchResult2.js" ; import "./ArticleSearchResult.css" ; import { PublisherSearchResult } from "./PublisherSearchResult.js" ; import { PublicationSearchResult } from "./PublicationSearchResult.js" ; import { PreviewableImage } from "./PreviewableImage.js" ; import { RatingStars } from "./RatingStars.js" ; import { gAppRef } from "./App.js" ; import { makeScenarioDisplayName, updateRecord, makeCommaList, isLink } from "./utils.js" ; const axios = require( "axios" ) ; // -------------------------------------------------------------------- export class ArticleSearchResult extends React.Component { render() { // prepare the basic details const display_title = this.props.data[ "article_title!" ] || this.props.data.article_title ; const display_subtitle = this.props.data[ "article_subtitle!" ] || this.props.data.article_subtitle ; const display_snippet = PreviewableImage.adjustHtmlForPreviewableImages( this.props.data[ "article_snippet!" ] || this.props.data.article_snippet ) ; const parent_pub = this.props.data._parent_pub ; const parent_publ = this.props.data._parent_publ ; const image_url = gAppRef.makeFlaskImageUrl( "article", this.props.data.article_image_id ) ; // prepare the article's URL let article_url = this.props.data.article_url ; if ( article_url ) { if ( ! isLink( article_url ) ) article_url = gAppRef.makeExternalDocUrl( article_url ) ; } else if ( parent_pub && parent_pub.pub_url ) { article_url = gAppRef.makeExternalDocUrl( parent_pub.pub_url ) ; if ( article_url.substr( article_url.length-4 ) === ".pdf" && this.props.data.article_pageno ) article_url += "#page=" + this.props.data.article_pageno ; } // prepare the authors let authors = [] ; const author_names_hilite = this.props.data[ "authors!" ] ; for ( let i=0 ; i < this.props.data.article_authors.length ; ++i ) { const author = this.props.data.article_authors[ i ] ; const author_name = author_names_hilite ? author_names_hilite[i] : author.author_name ; authors.push( ) ; } // prepare the scenarios let scenarios = [] ; const scenario_names_hilite = this.props.data[ "scenarios!" ] ; for ( let i=0 ; i < this.props.data.article_scenarios.length ; ++i ) { const scenario = this.props.data.article_scenarios[ i ] ; const scenario_display_name = scenario_names_hilite ? scenario_names_hilite[i] : makeScenarioDisplayName(scenario) ; scenarios.push( ) ; } // prepare the tags let tags = [] ; if ( this.props.data[ "tags!" ] ) { // the backend has provided us with a list of tags (possibly highlighted) - use them directly // NOTE: We don't normally show HTML in tags, but in this case we need to, in order to be able to highlight // matching search terms. This will have the side-effect of rendering any HTML that may be in the tag, // but we can live with that. for ( let i=0 ; i < this.props.data["tags!"].length ; ++i ) { const tag = this.props.data.article_tags[ i ] ; // nb: this is the actual tag (without highlights) tags.push( ) ; } } else { if ( this.props.data.article_tags ) { this.props.data.article_tags.map( tag => tags.push( {tag} ) ) ; } } // prepare the menu const menu = ( this.onEditArticle() } > Edit. Edit this.onDeleteArticle() } > Delete. Delete ) ; // NOTE: The "title" field is also given the CSS class "name" so that the normal CSS will apply to it. // Some tests also look for a generic ".name" class name when checking search results. const pub_display_name = parent_pub ? PublicationSearchResult.makeDisplayName( parent_pub ) : null ; const publ_display_name = parent_publ ? PublisherSearchResult.makeDisplayName( parent_publ ) : null ; return (
gAppRef.setTestAttribute( r, "article_id", this.props.data.article_id ) } >
{menu} { pub_display_name && } { publ_display_name && } { article_url && Open article. } { display_subtitle &&
}
{ image_url && }
{ authors.length > 0 &&
By {makeCommaList(authors)}
} { this.props.data.article_date &&
{this.props.data.article_date}
} { scenarios.length > 0 &&
Scenarios: {makeCommaList(scenarios)}
} { tags.length > 0 &&
Tags: {tags}
}
) ; } componentDidMount() { PreviewableImage.activatePreviewableImages( this ) ; } onRatingChange( newRating, onFailed ) { axios.post( gAppRef.makeFlaskUrl( "/article/update-rating", null ), { article_id: this.props.data.article_id, rating: newRating, } ).catch( err => { gAppRef.showErrorMsg(
Couldn't update the rating:
{err.toString()}
) ; if ( onFailed ) onFailed() ; } ) ; } static onNewArticle() { gAppRef.dataCache.get( [ "publishers", "publications", "authors", "scenarios", "tags" ], () => { ArticleSearchResult2._doEditArticle( {}, (newVals,refs) => { axios.post( gAppRef.makeFlaskUrl( "/article/create" ), newVals ).then( resp => { gAppRef.dataCache.refresh( [ "authors", "scenarios", "tags" ] ) ; // update the UI const newArticle = resp.data.record ; gAppRef.prependSearchResult( newArticle ) ; if ( newArticle._parent_pub ) gAppRef.updatePublication( newArticle._parent_pub.pub_id ) ; else if ( newArticle._parent_publ ) gAppRef.updatePublisher( newArticle._parent_publ.publ_id ) ; // update the UI if ( resp.data.warnings ) gAppRef.showWarnings( "The new article was created OK.", resp.data.warnings ) ; else gAppRef.showInfoToast(
The new article was created OK.
) ; gAppRef.closeModalForm() ; } ).catch( err => { gAppRef.showErrorMsg(
Couldn't create the article:
{err.toString()}
) ; } ) ; } ) ; } ) ; } onEditArticle() { gAppRef.dataCache.get( [ "publishers", "publications", "authors", "scenarios", "tags" ], () => { ArticleSearchResult2._doEditArticle( this.props.data, (newVals,refs) => { // send the updated details to the server newVals.article_id = this.props.data.article_id ; axios.post( gAppRef.makeFlaskUrl( "/article/update" ), newVals ).then( resp => { gAppRef.dataCache.refresh( [ "authors", "scenarios", "tags" ] ) ; // update the UI const article = resp.data.record ; const orig_parent_pub = this.props.data._parent_pub ; const orig_parent_publ = this.props.data._parent_publ ; updateRecord( this.props.data, article ) ; if ( article._parent_pub ) gAppRef.updatePublication( article._parent_pub.pub_id ) ; else if ( article._parent_publ ) gAppRef.updatePublisher( article._parent_publ.publ_id ) ; if ( orig_parent_pub ) gAppRef.updatePublication( orig_parent_pub.pub_id ) ; if ( orig_parent_publ ) gAppRef.updatePublisher( orig_parent_publ.publ_id ) ; // update the UI if ( newVals.imageData ) gAppRef.forceFlaskImageReload( "article", newVals.article_id ) ; this.forceUpdate() ; PreviewableImage.activatePreviewableImages( this ) ; // update the UI if ( resp.data.warnings ) gAppRef.showWarnings( "The article was updated OK.", resp.data.warnings ) ; else gAppRef.showInfoToast(
The article was updated OK.
) ; gAppRef.closeModalForm() ; } ).catch( err => { gAppRef.showErrorMsg(
Couldn't update the article:
{err.toString()}
) ; } ) ; } ); } ) ; } onDeleteArticle() { // confirm the operation const content = (
Delete this article?
) ; gAppRef.ask( content, "ask", { "OK": () => { // delete the article on the server axios.get( gAppRef.makeFlaskUrl( "/article/delete/" + this.props.data.article_id ) ).then( resp => { gAppRef.dataCache.refresh( [ "authors", "tags" ] ) ; // update the UI this.props.onDelete( "article_id", this.props.data.article_id ) ; if ( this.props.data._parent_pub ) gAppRef.updatePublication( this.props.data._parent_pub.pub_id ) ; else if ( this.props.data._parent_publ ) gAppRef.updatePublisher( this.props.data._parent_publ.publ_id ) ; // update the UI if ( resp.data.warnings ) gAppRef.showWarnings( "The article was deleted.", resp.data.warnings ) ; else gAppRef.showInfoToast(
The article was deleted.
) ; } ).catch( err => { gAppRef.showErrorToast(
Couldn't delete the article:
{err.toString()}
) ; } ) ; }, "Cancel": null, } ) ; } }