diff --git a/app/javascript/gabsocial/actions/links.js b/app/javascript/gabsocial/actions/links.js index 4954ef1f..44ff2135 100644 --- a/app/javascript/gabsocial/actions/links.js +++ b/app/javascript/gabsocial/actions/links.js @@ -4,6 +4,8 @@ export const LINK_FETCH_REQUEST = 'LINK_FETCH_REQUEST' export const LINK_FETCH_SUCCESS = 'LINK_FETCH_SUCCESS' export const LINK_FETCH_FAIL = 'LINK_FETCH_FAIL' +export const IMPORT_LINK_CARDS = 'IMPORT_LINK_CARDS' + export const fetchLinkCard = (cardId) => (dispatch, getState) => { dispatch(fetchLinkCardRequest(cardId)) @@ -27,4 +29,9 @@ export const fetchLinkCardFail = (error, cardId) => ({ type: LINK_FETCH_FAIL, error, cardId, +}) + +export const importLinkCards = (cards) => ({ + type: IMPORT_LINK_CARDS, + cards, }) \ No newline at end of file diff --git a/app/javascript/gabsocial/actions/search.js b/app/javascript/gabsocial/actions/search.js index 5ca88cb8..e98af32a 100644 --- a/app/javascript/gabsocial/actions/search.js +++ b/app/javascript/gabsocial/actions/search.js @@ -1,7 +1,11 @@ import api from '../api'; import { fetchRelationships } from './accounts'; import { fetchGroupsSuccess, fetchGroupRelationships } from './groups' -import { importFetchedAccounts, importFetchedStatuses } from './importer'; +import { + importFetchedAccounts, + importFetchedStatuses, +} from './importer'; +import { importLinkCards } from './links' import { SEARCH_FILTERS } from '../constants' export const SEARCH_CHANGE = 'SEARCH_CHANGE'; @@ -52,6 +56,10 @@ export function submitSearch() { dispatch(importFetchedStatuses(response.data.statuses)); } + if (response.data.links) { + dispatch(importLinkCards(response.data.links)); + } + if (response.data.groups) { dispatch(fetchGroupsSuccess(response.data.groups)) dispatch(fetchGroupRelationships(response.data.groups.map(item => item.id))) @@ -99,4 +107,4 @@ export function setFilter(path, value, shouldSubmit) { }) if (shouldSubmit) dispatch(submitSearch()) } -} +} \ No newline at end of file diff --git a/app/javascript/gabsocial/reducers/links.js b/app/javascript/gabsocial/reducers/links.js index 518f97f8..7b2ec9ff 100644 --- a/app/javascript/gabsocial/reducers/links.js +++ b/app/javascript/gabsocial/reducers/links.js @@ -7,6 +7,7 @@ import { LINK_FETCH_REQUEST, LINK_FETCH_SUCCESS, LINK_FETCH_FAIL, + IMPORT_LINK_CARDS, } from '../actions/links' const initialState = ImmutableMap({ @@ -27,6 +28,13 @@ export default function links(state = initialState, action) { mutable.set('isFetched', false) mutable.set('isError', false) }) + case IMPORT_LINK_CARDS: + return state.withMutations((mutable) => { + action.cards.forEach((card) => mutable.setIn(['items', `${card.id}`], fromJS(card))) + mutable.set('isLoading', false) + mutable.set('isFetched', false) + mutable.set('isError', false) + }) case LINK_FETCH_FAIL: return state.withMutations((mutable) => { mutable.set('isLoading', false) diff --git a/app/javascript/gabsocial/reducers/search.js b/app/javascript/gabsocial/reducers/search.js index 0d3437ed..b464d321 100644 --- a/app/javascript/gabsocial/reducers/search.js +++ b/app/javascript/gabsocial/reducers/search.js @@ -60,6 +60,7 @@ export default function search(state = initialState, action) { return state.set('results', ImmutableMap({ accounts: ImmutableList(action.results.accounts.map(item => item.id)), statuses: ImmutableList(action.results.statuses.map(item => item.id)), + links: ImmutableList(action.results.links.map(item => item.id)), hashtags: fromJS(action.results.hashtags), groups: fromJS(action.results.groups), })).set('submitted', true).set('isLoading', false).set('isError', false); diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index d774a31a..8366bef4 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -57,6 +57,14 @@ class PreviewCard < ApplicationRecord end class << self + def search_for(term, limit = 100, offset = 0) + pattern = '%' + sanitize_sql_like(term.strip) + '%' + + PreviewCard.where( + "lower(title) LIKE lower('#{pattern}') OR lower(description) LIKE lower('#{pattern}') OR lower(url) LIKE lower('#{pattern}')" + ).order('updated_at DESC').limit(limit).offset(offset) + end + private def image_styles(f) diff --git a/app/models/search.rb b/app/models/search.rb index fe5e1eb1..aafc54e5 100644 --- a/app/models/search.rb +++ b/app/models/search.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class Search < ActiveModelSerializers::Model - attributes :accounts, :statuses, :hashtags, :groups + attributes :accounts, :statuses, :hashtags, :groups, :links end diff --git a/app/serializers/rest/search_serializer.rb b/app/serializers/rest/search_serializer.rb index 769b0700..f82cbd89 100644 --- a/app/serializers/rest/search_serializer.rb +++ b/app/serializers/rest/search_serializer.rb @@ -6,6 +6,7 @@ class REST::SearchSerializer < ActiveModel::Serializer has_many :accounts, serializer: REST::AccountSerializer has_many :statuses, serializer: REST::StatusSerializer has_many :groups, serializer: REST::GroupSerializer + has_many :links, serializer: REST::PreviewCardSerializer def hashtags object.hashtags.map(&:name) diff --git a/app/serializers/rest/v2/search_serializer.rb b/app/serializers/rest/v2/search_serializer.rb index 61c531ea..14fa6be0 100644 --- a/app/serializers/rest/v2/search_serializer.rb +++ b/app/serializers/rest/v2/search_serializer.rb @@ -5,4 +5,5 @@ class REST::V2::SearchSerializer < ActiveModel::Serializer has_many :statuses, serializer: REST::StatusSerializer has_many :hashtags, serializer: REST::TagSerializer has_many :groups, serializer: REST::GroupSerializer + has_many :links, serializer: REST::PreviewCardSerializer end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 106b4997..181b26a9 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -19,6 +19,7 @@ class SearchService < BaseService results[:accounts] = perform_accounts_search! if account_searchable? results[:statuses] = perform_statuses_search! if full_text_searchable? && !account.nil? results[:hashtags] = perform_hashtags_search! if hashtag_searchable? && !account.nil? + results[:links] = perform_links_search! if !account.nil? results[:groups] = perform_groups_search! end end @@ -45,6 +46,14 @@ class SearchService < BaseService ) end + def perform_links_search! + PreviewCard.search_for( + @query.gsub(/\A#/, ''), + @limit, + @offset + ) + end + def perform_statuses_search! definition = StatusesIndex.filter(term: { searchable_by: @account.id }) .query(multi_match: { type: 'most_fields', query: @query, operator: 'and', fields: %w(text text.stemmed) }) @@ -79,7 +88,7 @@ class SearchService < BaseService end def default_results - { accounts: [], hashtags: [], statuses: [] } + { accounts: [], hashtags: [], statuses: [], links: [], groups: [] } end def url_query?