diff --git a/asl_articles/tests/test_image_preview.py b/asl_articles/tests/test_image_preview.py
new file mode 100644
index 0000000..16811cc
--- /dev/null
+++ b/asl_articles/tests/test_image_preview.py
@@ -0,0 +1,74 @@
+""" Test previewing images. """
+
+import os
+
+from selenium.common.exceptions import ElementClickInterceptedException
+
+from asl_articles.search import SEARCH_ALL_PUBLISHERS, SEARCH_ALL_PUBLICATIONS, SEARCH_ALL_ARTICLES
+from asl_articles.tests.test_publishers import create_publisher, edit_publisher
+from asl_articles.tests.test_publications import create_publication, edit_publication
+from asl_articles.tests.test_articles import create_article, edit_article
+from asl_articles.tests.utils import init_tests, find_child, find_children, wait_for, \
+ do_search, get_search_results, call_with_retry
+
+# ---------------------------------------------------------------------
+
+def test_image_preview( webdriver, flask_app, dbconn ):
+ """Test previewing images."""
+
+ # initialize
+ init_tests( webdriver, flask_app, dbconn )
+
+ def do_test( create, edit, refresh ):
+
+ # create a new object
+ webdriver.refresh()
+ create()
+ results = get_search_results()
+ assert len(results) == 1
+ sr = results[0]
+
+ # add images to the object
+ # NOTE: We're testing that images in an object already on-screen is updated correctly.
+ fname = os.path.join( os.path.split(__file__)[0], "fixtures/images/1.gif" )
+ description = 'foo bar'
+ edit( sr, fname, description )
+ _check_previewable_images( sr )
+
+ # refresh the object
+ # NOTE: We're testing that images in an object loaded afresh is set up correctly.
+ webdriver.refresh()
+ wait_for( 2, lambda: find_child( "#search-form" ) )
+ results = refresh()
+ assert len(results) == 1
+ _check_previewable_images( results[0] )
+
+ # do the tests
+ do_test(
+ lambda: create_publisher( { "name": "Test publisher" } ),
+ lambda sr, fname, description: edit_publisher( sr, { "image": fname, "description": description } ),
+ lambda: do_search( SEARCH_ALL_PUBLISHERS )
+ )
+ do_test(
+ lambda: create_publication( { "name": "Test publication" } ),
+ lambda sr, fname, description: edit_publication( sr, { "image": fname, "description": description } ),
+ lambda: do_search( SEARCH_ALL_PUBLICATIONS )
+ )
+ do_test(
+ lambda: create_article( { "title": "Test article" } ),
+ lambda sr, fname, description: edit_article( sr, { "image": fname, "snippet": description } ),
+ lambda: do_search( SEARCH_ALL_ARTICLES )
+ )
+
+# ---------------------------------------------------------------------
+
+def _check_previewable_images( sr ):
+ """Check that previewable images are working correctly."""
+ images = list( find_children( "a.preview img", sr ) )
+ assert len(images) == 2
+ for img in images:
+ assert find_child( ".jquery-image-zoom" ) is None
+ img.click()
+ preview = wait_for( 2, lambda: find_child( ".jquery-image-zoom" ) )
+ call_with_retry( preview.click, [ElementClickInterceptedException] )
+ wait_for( 2, lambda: find_child( ".jquery-image-zoom" ) is None )
diff --git a/asl_articles/tests/utils.py b/asl_articles/tests/utils.py
index c793a43..8aa09c7 100644
--- a/asl_articles/tests/utils.py
+++ b/asl_articles/tests/utils.py
@@ -2,6 +2,7 @@
import os
import json
+import time
import itertools
import uuid
import base64
@@ -469,6 +470,18 @@ def get_article_row( dbconn, article_id, fields ):
# ---------------------------------------------------------------------
+def call_with_retry( func, expected_exceptions, max_retries=10, delay=0.1 ):
+ """Try to call a function, with retries if it fails."""
+ for _ in range(0,max_retries):
+ try:
+ return func()
+ except Exception as exc: #pylint: disable=broad-except
+ if type(exc) not in expected_exceptions: #pylint: disable=unidiomatic-typecheck
+ raise
+ time.sleep( delay )
+ continue
+ assert False
+
def change_image( dlg, fname ):
"""Click on an image to change it."""
# NOTE: This is a bit tricky since we started overlaying the image with the "remove image" icon :-/
diff --git a/web/package-lock.json b/web/package-lock.json
index 1e52950..573f0bb 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -8091,6 +8091,11 @@
}
}
},
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ },
"js-levenshtein": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
diff --git a/web/package.json b/web/package.json
index ea43dd5..0b0adcb 100644
--- a/web/package.json
+++ b/web/package.json
@@ -7,6 +7,7 @@
"@reach/menu-button": "^0.7.2",
"axios": "^0.19.0",
"http-proxy-middleware": "^0.20.0",
+ "jquery": "^3.4.1",
"lodash.clone": "^4.5.0",
"lodash.clonedeep": "^4.5.0",
"lodash.isequal": "^4.5.0",
diff --git a/web/public/jQuery/imageZoom/jquery.imageZoom.css b/web/public/jQuery/imageZoom/jquery.imageZoom.css
new file mode 100644
index 0000000..c5af1cc
--- /dev/null
+++ b/web/public/jQuery/imageZoom/jquery.imageZoom.css
@@ -0,0 +1,48 @@
+div.jquery-image-zoom {
+ line-height: 0;
+ font-size: 0;
+
+ z-index: 10;
+
+ border: 5px solid #fff;
+ background: #eee; /* TM 25jan15: Added this to make it easier to see images with transparent backgrounds. */
+ margin: -5px;
+
+ -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+}
+
+div.jquery-image-zoom a {
+ background: url(/jQuery/imageZoom/jquery.imageZoom.png) no-repeat;
+
+ display: block;
+ width: 25px;
+ height: 25px;
+
+ position: absolute;
+ left: -17px;
+ top: -17px;
+ /* IE-users are prolly used to close-link in right-hand corner */
+ *left: auto;
+ *right: -17px;
+
+ text-decoration: none;
+ text-indent: -100000px;
+ outline: 0;
+
+ z-index: 11;
+}
+
+div.jquery-image-zoom a:hover {
+ background-position: left -25px;
+}
+
+div.jquery-image-zoom img,
+div.jquery-image-zoom embed,
+div.jquery-image-zoom object,
+div.jquery-image-zoom div {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+}
diff --git a/web/public/jQuery/imageZoom/jquery.imageZoom.js b/web/public/jQuery/imageZoom/jquery.imageZoom.js
new file mode 100644
index 0000000..f49a94a
--- /dev/null
+++ b/web/public/jQuery/imageZoom/jquery.imageZoom.js
@@ -0,0 +1,195 @@
+/***
+@title:
+Image Zoom
+
+@version:
+2.0
+
+@author:
+Andreas Lagerkvist
+
+@date:
+2008-08-31
+
+@url:
+http://andreaslagerkvist.com/jquery/image-zoom/
+
+@license:
+http://creativecommons.org/licenses/by/3.0/
+
+@copyright:
+2008 Andreas Lagerkvist (andreaslagerkvist.com)
+
+@requires:
+jquery, jquery.imageZoom.css, jquery.imageZoom.png
+
+@does:
+This plug-in makes links pointing to images open in the "Image Zoom". Clicking a link will zoom out the clicked image to its target-image. Click anywhere on the image or the close-button to zoom the image back in. Only ~3k minified.
+
+@howto:
+jQuery(document.body).imageZoom(); Would make every link pointing to an image in the document open in the zoom.
+
+@exampleHTML:
+
+
+
+
+@exampleJS:
+// I don't run it because my site already uses imgZoom
+// jQuery(document.body).imageZoom();
+***/
+jQuery.fn.imageZoom = function (conf) {
+ // Some config. If you set dontFadeIn: 0 and hideClicked: 0 imgzoom will act exactly like fancyzoom
+ var config = jQuery.extend({
+ speed: 200, // Animation-speed of zoom
+ dontFadeIn: 1, // 1 = Do not fade in, 0 = Do fade in
+ hideClicked: 1, // Whether to hide the image that was clicked to bring up the imgzoom
+ imageMargin: 30, // Margin from image-edge to window-edge if image is larger than screen
+ className: 'jquery-image-zoom',
+ loading: 'Loading...'
+ }, conf);
+ config.doubleSpeed = config.speed / 4; // Used for fading in the close-button
+
+ return this.click(function(e) {
+ // Make sure the target-element is a link (or an element inside a link)
+ var clickedElement = jQuery(e.target); // The element that was actually clicked
+ var clickedLink = clickedElement.is('a') ? clickedElement : clickedElement.parents('a'); // If it's not an a, check if any of its parents is
+ // TM MAR/20: Removed the check on the filename extension (it was looking for an image-type extension).
+ clickedLink = (clickedLink && clickedLink.is('a')) ? clickedLink : false; // If it was an a or child of an a, make sure it points to an image
+ var clickedImg = (clickedLink && clickedLink.find('img').length) ? clickedLink.find('img') : false; // See if the clicked link contains and image
+
+ // Only continue if a link pointing to an image was clicked
+ if (clickedLink) {
+ // These functions are used when the imaeg starts and stops loading (displays either 'loading..' or fades out the clicked img slightly)
+ clickedLink.oldText = clickedLink.text();
+
+ clickedLink.setLoadingImg = function () {
+ if (clickedImg) {
+ clickedImg.css({opacity: '0.5'});
+ }
+ else {
+ clickedLink.text(config.loading);
+ }
+ };
+
+ clickedLink.setNotLoadingImg = function () {
+ if (clickedImg) {
+ clickedImg.css({opacity: '1'});
+ }
+ else {
+ clickedLink.text(clickedLink.oldText);
+ }
+ };
+
+ // The URI to the image we are going to display
+ var displayImgSrc = clickedLink.attr('href');
+
+ // If an imgzoom wiv this image is already open dont do nathin
+ if (jQuery('div.' + config.className + ' img[src="' + displayImgSrc + '"]').length) {
+ return false;
+ }
+
+ // This function is run once the displayImgSrc-img has loaded (below)
+ var preloadOnload = function (pload) {
+ // The clicked-link is faded out during loading, fade it back in
+ clickedLink.setNotLoadingImg();
+
+ // Now set some vars we need
+ var dimElement = clickedImg ? clickedImg : clickedLink; // The element used to retrieve dimensions of imgzoom before zoom (either clicked link or img inside)
+ var hideClicked = clickedImg ? config.hideClicked : 0; // Whether to hide clicked link (set in config but always true for non-image-links)
+ var offset = dimElement.offset(); // Offset of clicked link (or image inside)
+ var imgzoomBefore = { // The dimensions of the imgzoom _before_ it is zoomed out
+ width: dimElement.outerWidth(),
+ height: dimElement.outerHeight(),
+ left: offset.left,
+ top: offset.top/*,
+ opacity: config.dontFadeIn*/
+ };
+ var imgzoom = jQuery('').css('position', 'absolute').appendTo(document.body); // We don't want any class-name or any other contents part from the image when we calculate the new dimensions of the imgzoom
+ var imgzoomAfter = { // The dimensions of the imgzoom _after_ it is zoomed out
+ width: pload.width,
+ height: pload.height/*,
+ opacity: 1*/
+ };
+ var windowDim = {
+ width: jQuery(window).width(),
+ height: jQuery(window).height()
+ };
+ // Make sure imgzoom isn't wider than screen
+ if (imgzoomAfter.width > (windowDim.width - config.imageMargin * 2)) {
+ var nWidth = windowDim.width - config.imageMargin * 2;
+ imgzoomAfter.height = (nWidth / imgzoomAfter.width) * imgzoomAfter.height;
+ imgzoomAfter.width = nWidth;
+ }
+ // Now make sure it isn't taller
+ if (imgzoomAfter.height > (windowDim.height - config.imageMargin * 2)) {
+ var nHeight = windowDim.height - config.imageMargin * 2;
+ imgzoomAfter.width = (nHeight / imgzoomAfter.height) * imgzoomAfter.width;
+ imgzoomAfter.height = nHeight;
+ }
+ // Center imgzoom
+ imgzoomAfter.left = (windowDim.width - imgzoomAfter.width) / 2 + jQuery(window).scrollLeft();
+ imgzoomAfter.top = (windowDim.height - imgzoomAfter.height) / 2 + jQuery(window).scrollTop();
+ var closeButton = jQuery('Close').appendTo(imgzoom).hide(); // The button that closes the imgzoom (we're adding this after the calculation of the dimensions)
+
+ // Hide the clicked link if set so in config
+ if (hideClicked) {
+ clickedLink.css('visibility', 'hidden');
+ }
+
+ // Now animate the imgzoom from its small size to its large size, and then fade in the close-button
+ imgzoom.addClass(config.className).css(imgzoomBefore).animate(imgzoomAfter, config.speed, function () {
+ closeButton.fadeIn(config.doubleSpeed);
+ });
+
+ // This function closes the imgzoom
+ var hideImgzoom = function () {
+ closeButton.fadeOut(config.doubleSpeed, function () {
+ imgzoom.animate(imgzoomBefore, config.speed, function () {
+ clickedLink.css('visibility', 'visible');
+ imgzoom.remove();
+ });
+ });
+
+ return false;
+ };
+
+ // Close imgzoom when you click the closeButton or the imgzoom
+ imgzoom.click(hideImgzoom);
+ closeButton.click(hideImgzoom);
+ };
+
+ // Preload image
+ var preload = new Image();
+
+ preload.src = displayImgSrc;
+
+ if (preload.complete) {
+ preloadOnload(preload);
+ }
+ else {
+ clickedLink.setLoadingImg();
+
+ preload.onload = function () {
+ preloadOnload(preload);
+ };
+ }
+
+ // Finally return false from the click so the browser doesn't actually follow the link...
+ return false;
+ }
+ });
+};
+
+// NOTE: We used to close up on ESC, but we want to do this on *any* keypress (e.g. if the user
+// starts typing in the search query box) or click (e.g. if the user clicks on a menu).
+$(document).keydown( () => { $("div.jquery-image-zoom a").click() ; } ) ;
+$(document).click( () => { $("div.jquery-image-zoom a").click() ; } ) ;
diff --git a/web/public/jQuery/imageZoom/jquery.imageZoom.png b/web/public/jQuery/imageZoom/jquery.imageZoom.png
new file mode 100644
index 0000000..2f5a381
Binary files /dev/null and b/web/public/jQuery/imageZoom/jquery.imageZoom.png differ
diff --git a/web/src/App.js b/web/src/App.js
index 5f4e4db..27d4d7c 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -12,12 +12,14 @@ import { PublicationSearchResult } from "./PublicationSearchResult" ;
import { ArticleSearchResult } from "./ArticleSearchResult" ;
import ModalForm from "./ModalForm";
import AskDialog from "./AskDialog" ;
+import { PreviewableImage } from "./PreviewableImage" ;
import { makeSmartBulletList } from "./utils.js" ;
import { APP_NAME } from "./constants.js" ;
import "./App.css" ;
const axios = require( "axios" ) ;
const queryString = require( "query-string" ) ;
+window.$ = window.jQuery = require( "jquery" ) ;
export let gAppRef = null ;
@@ -147,7 +149,9 @@ export class App extends React.Component
}
componentDidMount() {
- // install our key handler
+
+ // initialize
+ PreviewableImage.initPreviewableImages() ;
window.addEventListener( "keydown", this.onKeyDown.bind( this ) ) ;
// check if the server started up OK
diff --git a/web/src/ArticleSearchResult.js b/web/src/ArticleSearchResult.js
index 3aa2adc..2937630 100644
--- a/web/src/ArticleSearchResult.js
+++ b/web/src/ArticleSearchResult.js
@@ -4,6 +4,7 @@ import { Menu, MenuList, MenuButton, MenuItem } from "@reach/menu-button" ;
import { ArticleSearchResult2 } from "./ArticleSearchResult2.js" ;
import "./ArticleSearchResult.css" ;
import { PublicationSearchResult } from "./PublicationSearchResult.js" ;
+import { PreviewableImage } from "./PreviewableImage.js" ;
import { RatingStars } from "./RatingStars.js" ;
import { gAppRef } from "./App.js" ;
import { makeScenarioDisplayName, applyUpdatedVals, removeSpecialFields, makeCommaList, isLink } from "./utils.js" ;
@@ -20,7 +21,9 @@ export class ArticleSearchResult extends React.Component
// 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 = this.props.data[ "article_snippet!" ] || this.props.data.article_snippet ;
+ const display_snippet = PreviewableImage.adjustHtmlForPreviewableImages(
+ this.props.data[ "article_snippet!" ] || this.props.data.article_snippet
+ ) ;
const pub = gAppRef.caches.publications[ this.props.data.pub_id ] ;
const image_url = gAppRef.makeFlaskImageUrl( "article", this.props.data.article_image_id ) ;
@@ -141,7 +144,7 @@ export class ArticleSearchResult extends React.Component
{ display_subtitle && }
- { image_url &&
}
+ { image_url &&
}
@@ -152,6 +155,10 @@ export class ArticleSearchResult extends React.Component
) ;
}
+ componentDidMount() {
+ PreviewableImage.activatePreviewableImages( this ) ;
+ }
+
onRatingChange( newRating, onFailed ) {
axios.post( gAppRef.makeFlaskUrl( "/article/update-rating", null ), {
article_id: this.props.data.article_id,
@@ -205,6 +212,7 @@ export class ArticleSearchResult extends React.Component
if ( newVals.imageData )
gAppRef.forceFlaskImageReload( "article", newVals.article_id ) ;
this.forceUpdate() ;
+ PreviewableImage.activatePreviewableImages( this ) ;
if ( resp.data.warnings )
gAppRef.showWarnings( "The article was updated OK.", resp.data.warnings ) ;
else
diff --git a/web/src/PreviewableImage.js b/web/src/PreviewableImage.js
new file mode 100644
index 0000000..c671b02
--- /dev/null
+++ b/web/src/PreviewableImage.js
@@ -0,0 +1,72 @@
+import React from "react" ;
+import ReactDOM from "react-dom" ;
+import $ from "jquery" ;
+
+// --------------------------------------------------------------------
+
+export class PreviewableImage extends React.Component
+{
+ // NOTE: While the "react-modal-image" component seems to work nicely, how can we use it
+ // on arbitrary images in user-defined content?
+ // This class is a wrapper around the jQuery-based imageZoom plugin.
+
+ render() {
+ return (
+
+ ) ;
+ }
+
+ static initPreviewableImages() {
+ // load the imageZoom script
+ $.getScript( "/jQuery/imageZoom/jquery.imageZoom.js" ) ;
+ // load the imageZoom CSS
+ let cssNode = document.createElement( "link" ) ;
+ cssNode.type = "text/css" ;
+ cssNode.rel = "stylesheet" ;
+ cssNode.href = "/jQuery/imageZoom/jquery.imageZoom.css" ;
+ let headNode = document.getElementsByTagName( "head" )[0] ;
+ headNode.appendChild( cssNode ) ;
+ }
+
+ static adjustHtmlForPreviewableImages( html ) {
+ // FUDGE! The imageZoom plugin requires images to be wrapped with a tag.
+ // I was hoping to be able to let the user enable the preview functionality for images
+ // by simply adding a "preview" attribute to their tags, then locating them after render
+ // and dynamically wrapping them with the necessary tag, but React doesn't
+ // seem to like that :-/
+ // We instead look for such images in the HTML returned to us by the backend server, and fix it up
+ // before rendering it.
+
+ // initialize
+ if ( ! html )
+ return "" ;
+
+ // locate tags with a class of "preview", and wrap them in a .
+ let buf=[], pos=0 ;
+ const img_regex = /]*class\s*=\s*["']preview["'][^>]*>/g ;
+ const url_regex = /src\s*=\s*["'](.*?)['"]/
+ for ( const match of html.matchAll( img_regex ) ) {
+ buf.push( html.substr( pos, match.index-pos ) ) ;
+ const match2 = url_regex.exec( match[0] ) ;
+ if ( match2 ) {
+ buf.push(
+ "",
+ match[0],
+ ""
+ ) ;
+ } else
+ buf.push( match[0] ) ;
+ pos = match.index + match[0].length ;
+ }
+ buf.push( html.substr( pos ) ) ;
+
+ return buf.join( "" ) ;
+ }
+
+ static activatePreviewableImages( rootNode ) {
+ // locate images marked as previewable and activate them
+ let $elems = $( ReactDOM.findDOMNode( rootNode ) ).find( "a.preview" ) ;
+ $elems.imageZoom() ;
+ }
+
+}
diff --git a/web/src/PublicationSearchResult.js b/web/src/PublicationSearchResult.js
index 172bad6..9ab3ee1 100644
--- a/web/src/PublicationSearchResult.js
+++ b/web/src/PublicationSearchResult.js
@@ -3,6 +3,7 @@ import { Link } from "react-router-dom" ;
import { Menu, MenuList, MenuButton, MenuItem } from "@reach/menu-button" ;
import "./PublicationSearchResult.css" ;
import { PublicationSearchResult2 } from "./PublicationSearchResult2.js" ;
+import { PreviewableImage } from "./PreviewableImage.js" ;
import { PUBLICATION_EXCESS_ARTICLE_THRESHOLD } from "./constants.js" ;
import { gAppRef } from "./App.js" ;
import { makeCollapsibleList, pluralString, applyUpdatedVals, removeSpecialFields, isLink } from "./utils.js" ;
@@ -17,7 +18,9 @@ export class PublicationSearchResult extends React.Component
render() {
// prepare the basic details
- const display_description = this.props.data[ "pub_description!" ] || this.props.data.pub_description ;
+ const display_description = PreviewableImage.adjustHtmlForPreviewableImages(
+ this.props.data[ "pub_description!" ] || this.props.data.pub_description
+ ) ;
const publ = gAppRef.caches.publishers[ this.props.data.publ_id ] ;
const image_url = PublicationSearchResult.makeImageUrl( this.props.data ) ;
@@ -108,7 +111,7 @@ export class PublicationSearchResult extends React.Component
}
- { image_url &&
}
+ { image_url &&
}
{ makeCollapsibleList( "Articles", articles, PUBLICATION_EXCESS_ARTICLE_THRESHOLD, {float:"left",marginBottom:"0.25em"} ) }
@@ -119,6 +122,10 @@ export class PublicationSearchResult extends React.Component
) ;
}
+ componentDidMount() {
+ PreviewableImage.activatePreviewableImages( this ) ;
+ }
+
static onNewPublication( notify ) {
PublicationSearchResult2._doEditPublication( {}, null, (newVals,refs) => {
axios.post( gAppRef.makeFlaskUrl( "/publication/create", {list:1} ), newVals )
@@ -163,6 +170,7 @@ export class PublicationSearchResult extends React.Component
if ( newVals.imageData )
gAppRef.forceFlaskImageReload( "publication", newVals.pub_id ) ;
this.forceUpdate() ;
+ PreviewableImage.activatePreviewableImages( this ) ;
if ( resp.data.warnings )
gAppRef.showWarnings( "The publication was updated OK.", resp.data.warnings ) ;
else
diff --git a/web/src/PublisherSearchResult.js b/web/src/PublisherSearchResult.js
index 0b07d60..882e11a 100644
--- a/web/src/PublisherSearchResult.js
+++ b/web/src/PublisherSearchResult.js
@@ -4,6 +4,7 @@ import { Menu, MenuList, MenuButton, MenuItem } from "@reach/menu-button" ;
import { PublisherSearchResult2 } from "./PublisherSearchResult2.js"
import "./PublisherSearchResult.css" ;
import { PublicationSearchResult } from "./PublicationSearchResult.js"
+import { PreviewableImage } from "./PreviewableImage.js" ;
import { PUBLISHER_EXCESS_PUBLICATION_THRESHOLD } from "./constants.js" ;
import { gAppRef } from "./App.js" ;
import { makeCollapsibleList, pluralString, applyUpdatedVals, removeSpecialFields } from "./utils.js" ;
@@ -19,7 +20,9 @@ export class PublisherSearchResult extends React.Component
// prepare the basic details
const display_name = this.props.data[ "publ_name!" ] || this.props.data.publ_name ;
- const display_description = this.props.data[ "publ_description!" ] || this.props.data.publ_description ;
+ const display_description = PreviewableImage.adjustHtmlForPreviewableImages(
+ this.props.data[ "publ_description!" ] || this.props.data.publ_description
+ ) ;
const image_url = gAppRef.makeFlaskImageUrl( "publisher", this.props.data.publ_image_id ) ;
// prepare the publications
@@ -72,13 +75,17 @@ export class PublisherSearchResult extends React.Component
}
- { image_url &&
}
+ { image_url &&
}
{ makeCollapsibleList( "Publications", pubs, PUBLISHER_EXCESS_PUBLICATION_THRESHOLD, {float:"left",marginBottom:"0.25em"} ) }
) ;
}
+ componentDidMount() {
+ PreviewableImage.activatePreviewableImages( this ) ;
+ }
+
static onNewPublisher( notify ) {
PublisherSearchResult2._doEditPublisher( {}, (newVals,refs) => {
axios.post( gAppRef.makeFlaskUrl( "/publisher/create", {list:1} ), newVals )
@@ -115,6 +122,7 @@ export class PublisherSearchResult extends React.Component
if ( newVals.imageData )
gAppRef.forceFlaskImageReload( "publisher", newVals.publ_id ) ;
this.forceUpdate() ;
+ PreviewableImage.activatePreviewableImages( this ) ;
if ( resp.data.warnings )
gAppRef.showWarnings( "The publisher was updated OK.", resp.data.warnings ) ;
else