diff --git a/components/Navbar.js b/components/Navbar.js index 6c8b3bb05d..19b1118fa6 100644 --- a/components/Navbar.js +++ b/components/Navbar.js @@ -23,7 +23,7 @@ import InviteToHubModal from "../components/modal/InviteToHubModal"; import LoginModal from "../components/modal/LoginModal"; import PermissionNotificationWrapper from "./PermissionNotificationWrapper"; import Reputation from "./Reputation"; -import Search from "./Search"; +import Search from "./Search/Search"; import TransactionModal from "../components/modal/TransactionModal"; import UploadPaperModal from "../components/modal/UploadPaperModal"; import Notification from "./Notifications/Notification"; diff --git a/components/Search/Highlight.js b/components/Search/Highlight.js new file mode 100644 index 0000000000..472eeb9d01 --- /dev/null +++ b/components/Search/Highlight.js @@ -0,0 +1,90 @@ +import React, { Fragment } from "react"; +import { StyleSheet, css } from "aphrodite"; + +// Config +import { doesNotExist } from "~/config/utils"; + +const Highlight = (props) => { + const { result, attribute } = props; + const { highlight } = result.meta; + + const highlightSpan = formatHighlightByAttribute(); + + function formatHighlightByAttribute() { + switch (attribute) { + case "authors": + return transformAuthors(); + case "abstract": + case "first_name": + case "last_name": + case "title": + default: + return parseHighlight(); + } + } + + function parseHighlight(_text) { + if ( + doesNotExist(_text) && + (doesNotExist(highlight) || doesNotExist(highlight[attribute])) + ) + return result[attribute]; + + const text = _text ? _text : highlight[attribute][0]; + const parts = text.split(/([^<]+<\/em>)/); + const parsedString = parts.map((part) => { + if (part.includes("")) { + let replaced = part.replace("", ""); + replaced = replaced.replace("", ""); + return {replaced}; + } + return {part}; + }); + + return parsedString; + } + + function transformAuthors() { + const authors = + highlight && highlight.authors ? highlight.authors : result.authors; + + return ( +
+ {"by "} + {authors.map((author, i) => { + let isLast = i === authors.length - 1; + let result = parseHighlight(author); + + if (isLast) { + return result; + } + + return ( + + {result} + {", "} + + ); + })} +
+ ); + } + + return highlightSpan ? highlightSpan : null; +}; + +const styles = StyleSheet.create({ + authors: { + fontSize: 12, + fontWeight: 400, + color: "#918F9B", + marginTop: 5, + }, + highlight: { + backgroundColor: "#f6e653", + padding: "2px 1px 2px 1px", + fontStyle: "italic", + }, +}); + +export default Highlight; diff --git a/components/Search.js b/components/Search/Search.js similarity index 68% rename from components/Search.js rename to components/Search/Search.js index 9bb5c23f52..f64b7f30dd 100644 --- a/components/Search.js +++ b/components/Search/Search.js @@ -1,17 +1,19 @@ -import React, { Component } from "react"; +import React, { Component, Fragment } from "react"; import { css, StyleSheet } from "aphrodite"; import ReactPlaceholder from "react-placeholder"; import InfiniteScroll from "react-infinite-scroller"; import SearchEntry from "./SearchEntry"; -import HubSearchResult from "./HubSearchResult"; +import HubSearchResult from "../HubSearchResult"; import Loader from "~/components/Loader/Loader"; // Config -import { RHLogo } from "~/config/themes/icons"; +import colors from "../../config/themes/colors"; import API from "~/config/api"; import { Helpers } from "@quantfive/js-web-config"; +const SEARCH_TIMEOUT = 400; + export default class Search extends Component { searchTimeout = -1; dropdownTimeout = -1; @@ -19,7 +21,8 @@ export default class Search extends Component { scrollParent; state = { showDropdown: this.props.showDropdown, - finished: true, + searching: false, + searchMade: false, results: [], query: "", next: null, @@ -32,14 +35,6 @@ export default class Search extends Component { document.addEventListener("click", this); } - componentDidUpdate(prevProps, prevState) { - if (prevProps.showDropdown !== this.props.showDropdown) { - this.setState({ - showDropdown: this.props.showDropdown, - }); - } - } - componentWillUnmount() { clearTimeout(this.searchTimeout); clearTimeout(this.dropdownTimeout); @@ -47,23 +42,27 @@ export default class Search extends Component { } onSearchChange = (e) => { - clearTimeout(this.searchTimeout); + const { query } = this.state; + const ignoreTimeout = query.length >= 7 && query.length % 7 === 0; // call search at 7th keystroke and every multiple of 7 thereafter + + if (!ignoreTimeout) { + clearTimeout(this.searchTimeout); + } const value = e.target.value; if (!value) { - this.setState({ + return this.setState({ + searching: false, + searchMade: false, showDropdown: false, - finished: true, query: "", }); - - return; } else { this.setState({ showDropdown: true, - finished: false, query: value, + searching: true, }); } @@ -72,19 +71,18 @@ export default class Search extends Component { route: "all", }; - // TODO: add pagination - // Params to the search for pagination would be page fetch(API.SEARCH({ search: value, config }), API.GET_CONFIG()) .then(Helpers.checkStatus) .then(Helpers.parseJSON) .then((resp) => { this.setState({ results: resp.results, - finished: true, next: resp.next, + searchMade: true, + searching: false, }); }); - }, 200); + }, SEARCH_TIMEOUT); }; fetchNextPage = () => { @@ -105,20 +103,58 @@ export default class Search extends Component { }; renderSearchResults = () => { - let universityCount = 0; - let prevType; - const results = this.state.results.map((result, index) => { - result.meta.index === "university" && universityCount++; + const { results, searching, searchMade } = this.state; + + if (!searchMade && results.length === 0) { + return ( + + ); + } + + if (searchMade && results.length === 0) { + return ( +
+ +

+ We can't find what you're looking for!{"\n"} + {searching ? ( +
+ Please try another search + +
+ ) : ( + "Please try another search." + )} +

+
+ ); + } + + let prevType; // used to add result type header + + return results.map((result, index) => { let firstOfItsType = prevType !== result.meta.index; prevType = result.meta.index; return (
{ this.dropdownTimeout = setTimeout( this.setState({ showDropdown: false }), @@ -130,57 +166,22 @@ export default class Search extends Component {
); }); - - if (results.length === 0 || universityCount === results.length) { - return ( -
-

- We can't find what you're looking for! Please try another search. -

- -
- ); - } - - return results; }; getResultComponent = (result, index, firstOfItsType) => { const indexName = result.meta.index; - + const props = { + indexName, + result, + clearSearch: this.clearQuery, + firstOfItsType, + query: this.state.query, + }; switch (indexName) { - // case "author": - // return ( - // - // ); + case "author": case "crossref_paper": case "paper": - return ( - - ); - // case "discussion_thread": - // let data = thread(result); - // if (data.isPublic) { - // data = this.populateThreadData(data, result); - // data.meta = result.meta; - // return ( - // - // ); - // } + return ; case "hub": return ( ); case "university": - // return ; return null; default: break; @@ -249,28 +249,22 @@ export default class Search extends Component { hasMore={this.state.next} loadMore={this.fetchNextPage} loader={ - +
+ +
} useWindow={false} getScrollParent={() => this.scrollParent} initialLoad={false} threshold={20} > - - {this.renderSearchResults()} - + {this.renderSearchResults()} )} @@ -327,29 +321,48 @@ const styles = StyleSheet.create({ position: "absolute", zIndex: 10, top: 60, - maxHeight: 400, left: "50%", transform: "translateX(-50%)", background: "#fff", overflow: "scroll", + overflowX: "hidden", padding: 16, boxSizing: "border-box", boxShadow: "0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)", minWidth: 400, + maxHeight: 400, + color: colors.BLACK(), }, + searchResult: { borderBottom: "1px solid rgb(235, 235, 235)", }, emptyResults: { - textAlign: "center", - letterSpacing: 0.7, + padding: "15px 0", + width: "100%", display: "flex", - flexDirection: "column", alignItems: "center", + justifyContent: "center", + color: colors.BLACK(), + boxSizing: "border-box", }, emptyTitle: { - fontWeight: 400, - fontSize: 22, + fontWeight: 500, + fontSize: 18, + whiteSpace: "pre-wrap", + marginLeft: 15, + lineHeight: 1.5, + height: 55, + "@media only screen and (max-width: 415px)": { + height: 45, + fontSize: 16, + }, + }, + logo: { + height: 55, + "@media only screen and (max-width: 415px)": { + height: 45, + }, }, searchResultPaper: { border: "none", @@ -357,4 +370,8 @@ const styles = StyleSheet.create({ hide: { display: "none", }, + loaderStyle: { + paddingTop: 2, + paddingLeft: 1, + }, }); diff --git a/components/Search/SearchEntry.js b/components/Search/SearchEntry.js new file mode 100644 index 0000000000..d79b78244c --- /dev/null +++ b/components/Search/SearchEntry.js @@ -0,0 +1,554 @@ +import React, { Fragment } from "react"; +import { StyleSheet, css } from "aphrodite"; +import { connect } from "react-redux"; +import Router from "next/router"; +import numeral from "numeral"; + +// Redux +import { MessageActions } from "~/redux/message"; + +// Components +import Highlight from "~/components/Search/Highlight"; + +// Config +import colors from "../../config/themes/colors"; +import icons from "~/config/themes/icons"; +import { + formatDateStandard, + formatPaperSlug, + createUserSummary, +} from "~/config/utils"; +import { transformDate } from "~/redux/utils"; + +const search_fields = [ + "title", + "text", + "first_name", + "last_name", + "authors", + "name", + "summary", +]; + +class SearchEntry extends React.Component { + constructor(props) { + super(props); + this.state = { + indexName: false, + hidden: false, + activeFields: 1, + }; + } + + configureLink() { + // create link + } + + /** + * We want to take the user to the appropriate page when they click a search result + */ + handleClick = () => { + const { indexName, result, clearSearch, onClickCallBack } = this.props; + const { id, slug, paper } = result; + const paperSlug = slug ? slug : formatPaperSlug(result.title); + clearSearch && clearSearch(); + if (indexName === "author") { + Router.push("/user/[authorId]/[tabName]", `/user/${id}/contributions`); + } else if (indexName === "paper") { + Router.push("/paper/[paperId]/[paperName]", `/paper/${id}/${paperSlug}`); + } + onClickCallBack && onClickCallBack(); + }; + + parseTitleHighlight = (highlight, key) => { + const text = highlight[key][0]; + const parts = text.split(/([^<]+<\/em>)/); + return parts.map((part) => { + if (part.includes("")) { + let replaced = part.replace("", ""); + replaced = replaced.replace("", ""); + return {replaced}; + } + return {part}; + }); + }; + + convertDate = (date) => { + return formatDateStandard(transformDate(date)); + }; + + // transformAuthors = () => { + // const { result } = this.props; + // const { authors, meta } = result; + // if (result.meta.highlight && result.meta.highlight.authors) { + // return ( + //
+ // {"by "} + // {this.parseTitleHighlight(result.meta.highlight, "authors")} + //
+ // ); + // } else { + // return ( + //
+ // {"by "} + // {authors.map((author, i) => { + // if (i !== authors.length - 1) { + // return ( + // + // + // {", "} + // + // ); + // } else { + // return ( + // + // ); + // } + // })} + //
+ // ); + // } + // }; + + renderMainText = () => { + const { indexName, result } = this.props; + const { authors } = result; + + switch (indexName) { + case "author": + return ( + + + + + + + ); + case "paper": + return ( + + + + + {authors && authors.length > 0 ? ( + + ) : ( +
No attributed author
+ )} +
+ ); + default: + return null; + } + }; + + renderMetaDataOne = () => { + const { indexName, result, query } = this.props; + + switch (indexName) { + case "author": + const userSummary = createUserSummary(result); + + if (userSummary) { + return ( + + {userSummary} + + ); + } + break; + case "paper": + return ( + + + + ); + default: + return null; + } + }; + + renderCount = () => { + const { indexName, result } = this.props; + if (indexName === "paper") { + const count = + indexName === "paper" ? result.discussion_count : result.commentCount; + return ( +
+ {icons.chat} + + {count} + {count > 1 ? "comments" : count === 0 ? "comments" : "comment"} + +
+ ); + } + }; + + renderBulletPoints = () => { + const { indexName, result } = this.props; + if (indexName === "paper") { + const { hubs, paper_publish_date } = result; + return ( + +
{this.renderCount()}
+
+
+ {icons.hub} + + {hubs && ( + + {hubs.length} + hub{(hubs.length > 1 || hubs.length === 0) && "s"} + + )} + +
+
+
+
+ {icons.date} + + {paper_publish_date + ? this.convertDate(paper_publish_date) + : "No publish date"} + +
+
+
+ ); + } + }; + + renderHeader = () => { + const { indexName } = this.props; + return
{indexName + "s"}
; + }; + + renderScore = () => { + const { indexName, result, hideBullets, score } = this.props; + + switch (indexName) { + case "author": + return ( +
+ {result.profile_image ? ( + + ) : ( + + )} +
+ ); + case "paper": + return ( +
+ {numeral(score || 0).format("0a")} +
+ ); + default: + return; + } + }; + + render() { + const { indexName, result, hideBullets, firstOfItsType } = this.props; + + return ( + + {firstOfItsType && this.renderHeader()} +
+
+ {this.renderScore()} +
+
+
{this.renderMainText()}
+
+ {this.renderMetaDataOne()} +
+
+ {!hideBullets && ( +
+ {this.renderBulletPoints()} +
+ )} +
+
+ ); + } +} + +const styles = StyleSheet.create({ + searchEntryCard: { + display: "flex", + justifyContent: "flex-start", + alignItems: "center", + minHeight: 130, + width: "calc(100%)", + padding: "15px 20px", + position: "relative", + boxSizing: "border-box", + cursor: "pointer", + ":hover": { + backgroundColor: "#FAFAFA", + }, + }, + authorEntryCard: { + minHeight: 80, + }, + customStyles: { + border: "1px solid #EDEDED", + }, + column: { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "flex-start", + }, + left: { + marginRight: 20, + }, + fullWidth: { + width: "calc(100% - 50px)", + paddingBottom: 20, + }, + mid: { + justifyContent: "center", + width: "73%", + marginRight: 20, + "@media only screen and (max-width: 1300px)": { + width: "calc(100% - 40px)", + margin: 0, + }, + }, + right: { + justifyContent: "space-between", + alignItems: "flex-start", + "@media only screen and (max-width: 1300px)": { + display: "none", + }, + }, + spaced: { + justifyContent: "space-between", + "@media only screen and (max-width: 1200px)": { + width: "calc(100% - 50px)", + margin: 0, + }, + }, + mobilePadding: { + justifyContent: "space-between", + "@media only screen and (max-width: 1200px)": { + width: "calc(100% - 50px)", + margin: 0, + paddingBottom: 25, + }, + }, + avatarDisplay: { + display: "flex", + justifyContent: "center", + alignItems: "center", + }, + voteDisplay: { + color: "rgb(100, 196, 143)", + fontWeight: "bold", + background: "rgb(233, 250, 234)", + borderRadius: "50%", + height: 50, + width: 50, + display: "flex", + justifyContent: "center", + alignItems: "center", + "@media only screen and (max-width: 1300px)": { + height: 40, + width: 40, + }, + }, + smallVoteDisplay: { + height: 40, + width: 40, + borderRadius: "50%", + }, + highlight: { + backgroundColor: "#f6e653", + padding: "2px 1px 2px 1px", + }, + mainText: { + fontSize: 16, + color: "rgb(35, 32, 56)", + fontWeight: "500", + flexWrap: "wrap", + wordBreak: "break-word", + lineHeight: 1.2, + marginBottom: 8, + textOverflow: "ellipsis", + "@media only screen and (max-width: 1080px)": { + fontSize: 16, + }, + }, + metaDataOne: { + flexWrap: "wrap", + display: "flex", + "@media only screen and (max-width: 1200px)": { + width: "100%", + }, + }, + userHeadline: { + fontSize: 13, + fontWeight: 400, + color: "#918F9B", + }, + metaDataTwo: { + fontSize: 16, + flexWrap: "wrap", + display: "flex", + }, + avatar: { + height: 40, + width: 40, + borderRadius: "50%", + objectFit: "contain", + display: "flex", + justifyContent: "center", + alignItems: "center", + boxShadow: "0px 2px 4px rgba(185, 185, 185, 0.25)", + }, + defaultAvatar: { + color: "#aaa", + fontSize: 40, + borderRadius: "50%", + boxShadow: "unset", + border: "1px solid #FAFAFA", + }, + indexTag: { + position: "absolute", + textTransform: "uppercase", + right: 20, + bottom: 10, + color: colors.BLUE(1), + fontSize: 14, + "@media only screen and (max-width: 1080px)": { + fontSize: 12, + }, + }, + publishDate: { + fontSize: 14, + fontWeight: 400, + color: "#918F9B", + }, + authors: { + fontSize: 12, + fontWeight: 400, + color: "#918F9B", + marginTop: 5, + }, + abstract: { + fontSize: 13, + fontWeight: 400, + color: colors.BLACK(0.9), + }, + discText: { + fontSize: 12, + wordBreak: "break-word", + "@media only screen and (max-width: 1200px)": { + width: "calc(100% - 50px)", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden", + }, + }, + tagline: { + fontSize: 12, + wordBreak: "break-word", + "@media only screen and (max-width: 1200px)": { + width: "calc(100% - 50px)", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden", + }, + }, + icon: { + minWidth: 20, + maxWidth: 20, + color: colors.YELLOW(), + fontSize: 14, + }, + paperIcon: { + color: colors.BLUE(), + marginRight: 5, + }, + bullet: {}, + discussion: { + display: "flex", + justifyContent: "flex-start", + alignItems: "center", + paddingTop: 5, + }, + discussionCount: { + color: colors.BLACK(1), + marginLeft: 7, + fontSize: 13, + paddingBottom: 2, + }, + count: { + color: colors.BLACK(1), + fontWeight: "bold", + }, + section: { + width: "100%", + textTransform: "uppercase", + fontSize: 13, + fontWeight: 500, + letterSpacing: 1.2, + borderBottom: "1px solid #DAE0E6", + padding: "10px 0", + }, + first_name: { + marginRight: 3, + }, +}); + +const mapStateToProps = (state) => ({}); + +const mapDispatchToProps = { + showMessage: MessageActions.showMessage, + setMessage: MessageActions.setMessage, +}; +export default connect( + mapStateToProps, + mapDispatchToProps +)(SearchEntry); diff --git a/components/SearchEntry.js b/components/SearchEntry.js deleted file mode 100644 index db54d6f110..0000000000 --- a/components/SearchEntry.js +++ /dev/null @@ -1,665 +0,0 @@ -import React, { Fragment } from "react"; -import { StyleSheet, css } from "aphrodite"; -import { connect } from "react-redux"; -import Router from "next/router"; - -// Redux -import { MessageActions } from "~/redux/message"; - -// Components -import University from "./University"; -import AuthorAvatar from "~/components/AuthorAvatar"; - -// Config -import colors from "../config/themes/colors"; -import icons from "~/config/themes/icons"; -import { formatDateStandard, formatPaperSlug } from "~/config/utils"; -import { transformDate } from "~/redux/utils"; - -const search_fields = [ - "title", - "text", - "first_name", - "last_name", - "authors", - "name", - "summary", -]; - -class SearchEntry extends React.Component { - constructor(props) { - super(props); - this.state = { - indexName: false, - hidden: false, - activeFields: 1, - }; - } - - configureLink() { - // create link - } - - /** - * We want to take the user to the appropriate page when they click a search result - */ - handleClick = () => { - let { indexName, result, clearSearch, onClickCallBack } = this.props; - let { id, slug } = result; - let paperSlug = slug ? slug : formatPaperSlug(result.title); - clearSearch && clearSearch(); - if (indexName === "author") { - Router.push("/user/[authorId]/[tabName]", `/user/${id}/contributions`); - } else if (indexName === "paper") { - Router.push("/paper/[paperId]/[paperName]", `/paper/${id}/${paperSlug}`); - } else if (indexName === "discussion_thread") { - let { paper } = result; - Router.push( - "/paper/[paperId]/[paperName]/[discussionThreadId]", - `/paper/${paper}/${paperSlug}/${id}` - ); - } - setTimeout(() => onClickCallBack && onClickCallBack(), 400); - }; - - parseTitleHighlight = (highlight, key) => { - const text = highlight[key][0]; - const parts = text.split(/([^<]+<\/em>)/); - return parts.map((part) => { - if (part.includes("")) { - let replaced = part.replace("", ""); - replaced = replaced.replace("", ""); - return {replaced}; - } - return {part}; - }); - }; - - // parseHighlightField = (highlight, key) => { - // let { indexName, result } = this.props; - // let textArr = highlight[key][0].split(" "); - // let highlightedIndex = {}; - - // textArr.forEach((text, i, arr) => { - // if (text[0] === "<") { - // if (text.split("").length > 1) { - // let splitArr = text - // .slice(4) - // .split("") - // .filter((el) => el !== ""); - // let highlighted = splitArr[0]; - // arr[i] = highlighted; - - // if (splitArr.length > 1) { - // let normal = splitArr[1].slice(4); - // textArr.splice(i + 1, 0, normal); - // highlightedIndex[i + 1] = true; - // } - // } else { - // arr[i] = text.slice(4, text.length - 5); - // } - // highlightedIndex[i] = true; - // } - // }); - - // let transformedText = textArr.map((text, i) => { - // if (highlightedIndex[i]) { - // return ( - // - // {highlightedIndex[i - 1] ? " " : ""} - // {text} - // - // ); - // } else { - // return `${highlightedIndex[i - 1] ? " " : ""}${text}${ - // i !== textArr.length - 1 ? " " : "" - // }`; - // } - // }); - - // if (key === "tagline") { - // transformedText.push("..."); - // } - // return transformedText; - // }; - - convertDate = (date) => { - return formatDateStandard(transformDate(date)); - }; - - transformAuthors = () => { - let { result } = this.props; - let { authors, meta } = result; - if (result.meta.highlight && result.meta.highlight.authors) { - return ( -
- {"by "} - {this.parseTitleHighlight(result.meta.highlight, "authors")} -
- ); - } else { - return ( -
- {"by "} - {authors.map((author, i) => { - if (i !== authors.length - 1) { - return `${author}, `; - } else { - return author; - } - })} -
- ); - } - }; - - renderMainText = () => { - let { indexName, result } = this.props; - if (indexName === "author") { - let { first_name, last_name, meta } = result; - let highlight = meta.highlight; - return ( - - - {first_name && first_name} - - - {last_name && ` ${last_name}`} - - - ); - } else if (indexName === "paper") { - let { meta, title, authors } = result; - let highlight = meta.highlight; - return ( - - {highlight && highlight.title - ? this.parseTitleHighlight(highlight, "title") - : title} - {authors && authors.length > 0 ? ( - this.transformAuthors() - ) : ( -
No attributed author
- )} -
- ); - } else if (indexName === "discussion_thread") { - let { meta, title, paperTitle } = result; - let highlight = meta.highlight; - return ( - - {highlight && highlight.title - ? this.parseTitleHighlight(highlight, "title") - : title} - {paperTitle && ( -
- - {icons.file} - {" "} - {paperTitle} -
- )} -
- ); - } - }; - - renderMetaDataOne = () => { - let { indexName, result } = this.props; - if (indexName === "author") { - let { university } = result; - if (Object.keys(university).length) { - return ( - - - - ); - } - } else if (indexName === "paper") { - let { tagline } = result; - let highlight = result.meta.highlight; - if (tagline) { - return ( -
- {highlight && highlight.tagline - ? this.parseTitleHighlight(highlight, "tagline") - : tagline} -
- ); - } - } else if (indexName === "discussion_thread") { - let highlight = result.meta.highlight; - let { plainText } = result; - return ( -
- {highlight && highlight.plain_text - ? this.parseTitleHighlight(highlight, "plain_text") - : plainText} -
- ); - } - }; - - renderMetaDataTwo = () => { - let { indexName, result } = this.props; - if (indexName === "author") { - return; - } else if (indexName === "paper") { - } else if (indexName === "discussion_thread") { - } - }; - - renderCount = () => { - let { indexName, result } = this.props; - if (indexName === "paper" || indexName === "discussion_thread") { - let count = - indexName === "paper" ? result.discussion_count : result.commentCount; - return ( -
- {icons.chat} - - {indexName === "paper" ? ( - - - {result.discussion_count}{" "} - - {count > 1 ? "comments" : count === 0 ? "comments" : "comment"} - - ) : ( - - - {result.commentCount}{" "} - - {count > 1 ? "comments" : count === 0 ? "comments" : "comment"} - - )} - -
- ); - } else { - return; - } - }; - - renderBulletPoints = () => { - let { indexName, result } = this.props; - if (indexName === "paper") { - let { hubs, paper_publish_date } = result; - return ( - -
{this.renderCount()}
-
-
- {icons.hub} - - {hubs && ( - - {hubs.length} - hub{(hubs.length > 1 || hubs.length === 0) && "s"} - - )} - -
-
-
-
- {icons.date} - - {paper_publish_date - ? this.convertDate(paper_publish_date) - : "No publish date"} - -
-
-
- ); - } else if (indexName === "discussion_thread") { - let { createdBy, createdDate } = result; - let { firstName, lastName } = createdBy; - return ( - -
{this.renderCount()}
-
-
- {icons.simpleUser} - - {`${firstName} ${lastName}`} - -
-
-
-
- {icons.date} - - {createdDate && this.convertDate(createdDate)} - -
-
-
- ); - } - }; - - renderHeader = () => { - return
Papers
; - }; - - render() { - let { indexName, result, hideBullets, firstOfItsType } = this.props; - let { score, tagline, plainText } = result; - let isPaper = indexName === "paper"; - let isDisc = indexName === "discussion_thread"; - - return ( - - {firstOfItsType && this.renderHeader()} -
-
- {indexName === "author" ? ( -
- {result.profile_image ? ( - - ) : ( - - )} -
- ) : ( -
- {(score && score) || 0} -
- )} -
-
= 100 - ? styles.mobilePadding - : styles.spaced - : null, - isDisc && plainText - ? plainText.length >= 100 - ? styles.mobilePadding - : styles.spaced - : null, - hideBullets && styles.fullWidth - )} - > -
{this.renderMainText()}
-
- {this.renderMetaDataOne()} -
-
- {this.renderMetaDataTwo()} -
-
- {/*
- {indexName === "discussion_thread" ? "disc." : indexName} -
*/} - {!hideBullets && ( -
- {this.renderBulletPoints()} -
- )} -
-
- ); - } -} - -const styles = StyleSheet.create({ - searchEntryCard: { - display: "flex", - justifyContent: "flex-start", - alignItems: "center", - minHeight: 130, - width: "calc(100%)", - padding: "15px 20px", - position: "relative", - boxSizing: "border-box", - cursor: "pointer", - ":hover": { - backgroundColor: "#FAFAFA", - }, - }, - customStyles: { - border: "1px solid #EDEDED", - }, - column: { - display: "flex", - flexDirection: "column", - justifyContent: "center", - alignItems: "flex-start", - }, - left: { - marginRight: 20, - }, - fullWidth: { - width: "calc(100% - 50px)", - paddingBottom: 20, - }, - mid: { - justifyContent: "center", - width: "calc(calc(100% - 50px) * 0.7)", - marginRight: 20, - "@media only screen and (max-width: 1200px)": { - width: "calc(100% - 50px)", - margin: 0, - }, - }, - right: { - justifyContent: "space-between", - alignItems: "flex-start", - width: "calc(calc(100% - 50px) * 0.3)", - "@media only screen and (max-width: 1200px)": { - display: "none", - }, - }, - spaced: { - justifyContent: "space-between", - "@media only screen and (max-width: 1200px)": { - width: "calc(100% - 50px)", - margin: 0, - }, - }, - mobilePadding: { - justifyContent: "space-between", - "@media only screen and (max-width: 1200px)": { - width: "calc(100% - 50px)", - margin: 0, - paddingBottom: 25, - }, - }, - avatarDisplay: { - display: "flex", - justifyContent: "center", - alignItems: "center", - }, - voteDisplay: { - color: "rgb(100, 196, 143)", - fontWeight: "bold", - background: "rgb(233, 250, 234)", - borderRadius: "50%", - height: 50, - width: 50, - display: "flex", - justifyContent: "center", - alignItems: "center", - }, - smallVoteDisplay: { - height: 40, - width: 40, - borderRadius: "50%", - }, - highlight: { - backgroundColor: "#f6e653", - padding: "2px 1px 2px 1px", - }, - mainText: { - fontSize: 18, - color: "rgb(35, 32, 56)", - fontWeight: "500", - flexWrap: "wrap", - wordBreak: "break-word", - lineHeight: 1.6, - marginBottom: 10, - textOverflow: "ellipsis", - "@media only screen and (max-width: 1080px)": { - fontSize: 16, - }, - }, - metaDataOne: { - fontSize: 16, - flexWrap: "wrap", - display: "flex", - "@media only screen and (max-width: 1200px)": { - width: "100%", - }, - }, - paddedContainer: {}, - metaDataTwo: { - fontSize: 16, - flexWrap: "wrap", - display: "flex", - }, - avatar: { - height: 55, - width: 55, - borderRadius: 27.5, - objectFit: "contain", - display: "flex", - justifyContent: "center", - alignItems: "center", - }, - defaultAvatar: { - color: "#aaa", - fontSize: 50, - }, - indexTag: { - position: "absolute", - textTransform: "uppercase", - right: 20, - bottom: 10, - color: colors.BLUE(1), - fontSize: 14, - "@media only screen and (max-width: 1080px)": { - fontSize: 12, - }, - }, - publishDate: { - fontSize: 14, - fontWeight: 400, - color: "#918F9B", - }, - authors: { - fontSize: 13, - fontWeight: 400, - color: "#918F9B", - }, - discText: { - fontSize: 12, - // maxHeight: 49, - wordBreak: "break-word", - "@media only screen and (max-width: 1200px)": { - width: "calc(100% - 50px)", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - overflow: "hidden", - }, - }, - tagline: { - fontSize: 12, - wordBreak: "break-word", - "@media only screen and (max-width: 1200px)": { - width: "calc(100% - 50px)", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - overflow: "hidden", - }, - }, - icon: { - minWidth: 20, - maxWidth: 20, - color: colors.YELLOW(), - fontSize: 14, - }, - paperIcon: { - color: colors.BLUE(1), - marginRight: 5, - }, - bullet: {}, - discussion: { - display: "flex", - justifyContent: "flex-start", - alignItems: "center", - paddingTop: 5, - }, - discussionCount: { - color: colors.BLACK(1), - marginLeft: 7, - fontSize: 14, - paddingBottom: 2, - }, - count: { - color: colors.BLACK(1), - fontWeight: "bold", - }, - section: { - width: "100%", - textTransform: "uppercase", - fontSize: 13, - fontWeight: 500, - letterSpacing: 1.2, - borderBottom: "1px solid #DAE0E6", - padding: "10px 0", - // color: 'rgb(167, 166, 176)' - }, -}); - -const mapStateToProps = (state) => ({}); - -const mapDispatchToProps = { - showMessage: MessageActions.showMessage, - setMessage: MessageActions.setMessage, -}; -export default connect( - mapStateToProps, - mapDispatchToProps -)(SearchEntry); diff --git a/components/modal/UploadPaperModal.js b/components/modal/UploadPaperModal.js index f298ad5505..ed1c0375b0 100644 --- a/components/modal/UploadPaperModal.js +++ b/components/modal/UploadPaperModal.js @@ -15,8 +15,6 @@ import { MessageActions } from "../../redux/message"; // Component import BaseModal from "../modal/BaseModal"; -import SearchEntry from "../SearchEntry"; -import PaperMetaData from "../SearchSuggestion/PaperMetaData"; import PaperEntryCard from "../Hubs/PaperEntryCard"; // Config diff --git a/static/icons/search-empty.png b/static/icons/search-empty.png new file mode 100644 index 0000000000..55ce292d78 Binary files /dev/null and b/static/icons/search-empty.png differ