API Docs for: 0.25.0
Show:

File: addon/components/search-result/component.js

import Ember from 'ember';
import layout from './template';
import Analytics from '../../mixins/analytics';
import hostAppName from '../../mixins/host-app-name';
import providerRegex from 'ember-osf/const/providerRegex';
import moment from 'moment';

/**
 * Adapted from Ember-SHARE and Ember Preprints
 * Used for search results on discover page.
 *
 * ```handlebars
 * {{search-result
 *      detailRoute=detailRoute
 *      addFilter='addFilter'
 *      result=result
 *      queryParamsState=queryParamsState
 *      filterReplace=filterReplace
 *      updateFilters=(action 'updateFilters')
 * }}
 * ```
 * @class search-result
 */
export default Ember.Component.extend(Analytics, hostAppName, {
    layout,
    maxTags: 10,
    maxSubjects: 10,
    maxCreators: 10,
    maxDescription: 300,
    showBody: false,
    i18n: Ember.inject.service(),
    /**
     * Array of query params being used in consuming app
     * @property {Array} queryParamsState
     */
    queryParamsState: null,
    /**
     * Search result from SHARE
     * @property {Object} result
     */
    result: null,
    providerUrlRegex: providerRegex,
    /**
     * Name of detail route for consuming application, if you want search result to link to a route in the consuming spp
     * @property {String} detailRoute
     */
     detailRoute: null,
    /**
     * Provider loaded from theme service. Passed in from consuming application.
    * @property {Object} themeProvider
    */
    themeProvider: null,
    domainRedirectProviders: [],
    lineage: Ember.computed('result', function() {
        return this.get('result.lists.lineage');
    }),
    footerIcon: Ember.computed('showBody', function() {
        return this.get('showBody') ? 'caret-up' : 'caret-down';
    }),
    type: Ember.computed('result.type', function() {
        return this.get('result.type').replace(/\w\S*/g, function(str) {return str.capitalize();});
    }),
    abbreviated: Ember.computed('result.description', function() {
        return this.get('result.description').length > this.get('maxDescription');
    }),
    abbreviation: Ember.computed('result.description', function() {
        let desc = this.get('result.description');
        if (desc) {
            return this.get('result.description').slice(0, this.get('maxDescription'));
        }
    }),
    allCreators: Ember.computed('result.lists.contributors', function() {
        return (this.get('result.lists.contributors') || []).filter(contrib => contrib.relation === 'creator').sort(function(a, b) {
            return a.order_cited - b.order_cited;
        });
    }),
    extraCreators: Ember.computed('allCreators', function() {
        return this.get('allCreators').slice(this.get('maxCreators'));
    }),
    creators: Ember.computed('allCreators', function() {
        return this.get('allCreators').slice(0, this.get('maxCreators'));
    }),
    extraTags: Ember.computed('result.tags', function() {
        return (this.get('result.tags') || []).slice(this.get('maxTags'));
    }),
    identifiers: Ember.computed('result.identifiers', function() {
        return this.get('result.identifiers');
    }),
    tags: Ember.computed('result.tags', function() {
        return (this.get('result.tags') || []).slice(0, this.get('maxTags'));
    }),
    subjects: Ember.computed('result.subjects', 'result.subject_synonyms', 'themeProvider', function() {
        let subs = this.get('themeProvider.id') === 'osf' && this.get('result.subject_synonyms').length ? this.get('result.subject_synonyms') : this.get('result.subjects');
        let uniqueSubs = {}
        subs.map(e => {
            let tax, subjects;
            [tax, ...subjects] = e.text.split('|');
            if (subjects.length) { //accounting for non-custom taxonomy subjects, if we ever get back to that
                for (var i = 0; i < subjects.length; i++) {
                    uniqueSubs[subjects[i]] = {
                        text: subjects[i],
                        value: [tax, ...subjects.slice(0, i+1)].join('|'),
                        taxonomy: tax
                    }
                }
            } else {
                uniqueSubs[e.text] = {
                    text: e.text,
                    value: e.text,
                    taxonomy: null
                };
            }
        });
        uniqueSubs = Object.keys(uniqueSubs).map(e => uniqueSubs[e]);
        return (uniqueSubs || []).slice(0, this.get('maxSubjects'));
    }),
    extraSubjects: Ember.computed('result.subjects', function() {
        return (this.get('result.subjects') || []).slice(this.get('maxSubjects'));
    }),
    retractionId: Ember.computed('result.lists.retractions[]', function() {
        const retractions = this.get('result.lists.retractions');
        if (retractions && retractions.length) {
            return retractions[0].id;
        }
        return null;
    }),
    osfID: Ember.computed('result', function() {
        let re = /osf.io\/(\w+)\/$/;
        // NOTE / TODO : This will have to be removed later. Currently the only "true" preprints are solely from the OSF
        // socarxiv and the like sometimes get picked up by as part of OSF, which is technically true. This will prevent
        // broken links to things that aren't really preprints.
        if (this.get('result.providers.length') === 1 && this.get('result.providers').find(provider => provider.name === 'OSF'))
            for (let i = 0; i < this.get('result.identifiers.length'); i++)
                if (re.test(this.get('result.identifiers')[i]))
                    return re.exec(this.get('result.identifiers')[i])[1];
        return false;
    }),
    hyperlink: Ember.computed('result', function() {
        const urlRegex = /^https?:\/\/([^\/]+)\/(.+)$/;
        const domainRedirectList = this.get('domainRedirectProviders');
        const identifiers = this.get('result.identifiers').filter(ident => ident.startsWith('http://') || ident.startsWith('https://') );
        for (let identifier of identifiers) {
            let url = identifier.match(urlRegex);
            if (url) {
                const domainRegex = new RegExp("^https?://" + url[1] + "/");
                for (let domain of domainRedirectList) {
                    if (domainRegex.test(domain)) {
                        // If the domain matches use the path from the identifier concatentated to the domain
                        return domain + url[2];
                    }
                }
            }
        }
        let re = this.providerUrlRegex.OSF;
        for (let provider of this.get('result.providers')) {
            // If the result has multiple providers and one of them matches use the first one found
            if (this.providerUrlRegex.hasOwnProperty(provider.name)) {
                re = this.providerUrlRegex[provider.name];
                break;
            }
        }
        for (let identifier of identifiers) {
            if (re.test(identifier)) {
                return identifier;
            }
        }
        return identifiers[0];
    }),
    // Determines whether tags in search results should be links - preprints and registries are not using tag filter right now.
    // NEW: Preprint providers with additionalProviders are using tags, however.
    tagsInQueryParams: Ember.computed('queryParamsState', 'themeProvider', function() {
        return this.get('queryParamsState.tags') && (this.get('themeProvider.additionalProviders') || []).length;
    }),
    dateUpdated: Ember.computed('result.date_updated', function() {
        return moment(this.get('result.date_updated')).utc().format('ll');
    }),
    didRender() {
        MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.$()[0]]);  // jshint ignore: line
    },
    compare(first, second, param) {
        if (first[param] < second[param]) {
            return -1;
        } else if (first[param] > second[param]) {
            return 1;
        } else {
            return 0;
        }
    },
    actions: {
        addFilter(type, filter) {
            this.sendAction('addFilter', type, filter);
        },
        toggleShowBody() {
            this.toggleProperty('showBody');
            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'result',
                    action: !this.showBody ? 'contract' : 'expand',
                    label: `Discover - ${this.result.title}`,
                    extra: this.result.id
                });
        },
        select(item) {
            this.attrs.select(item);
        }

    }
});