@stackend/api
Version:
JS bindings to api.stackend.com
250 lines (225 loc) • 7.77 kB
text/typescript
// @flow
import { find } from 'lodash';
import { QnaSearchType, ContentType, getCategories, search as _search, QnaTypeConverter } from './index';
import * as Search from '../search';
import * as searchActions from '../search/searchActions';
import {
CHANGE_QNA_PAGE,
CHANGE_FILTER,
SET_QNA_AVAILABLE_FILTERS,
RECEIVE_SEARCH_RESULT,
QnaActions
} from './qnaReducer';
import { isRunningInBrowser, Thunk, XcapJsonResult } from '../api';
import { Request, getRequest } from '../request';
import { AnyAction } from 'redux';
//Action Creator to change qnaPage using pageType, eg. "ViewForumThread" and permalink to question
export function changeQnaPage(pageType: string, forumThreadPermalink: string): QnaActions {
return {
type: CHANGE_QNA_PAGE,
pageType,
forumThreadPermalink
};
}
//Action Creator to set qna backend server
/*export function setServer(server: string) {
return {
type: SET_QNA_SERVER,
server
}
}*/
export interface ChangeFilter {
filter: {
(filterName: string): string; //filterName is the filter group (currently only issue), and the value is selected filter
searchType?: QnaSearchType;
updateUrl?: 'qna' | 'search'; //if qna or search, reducer will use browserHistory to push url of new filter
issue?: string; //not-really needed,
};
contentType: ContentType;
triggerSearch?: boolean; //option to disable search trigger
}
//Action Creator to change selected filter in reduxStoreName
export function changeFilter({ filter, contentType, triggerSearch = true }: ChangeFilter): Thunk<void> {
return (dispatch: any, getState: any): void => {
dispatch(_changeFilter({ filter, contentType }));
const request: Request = dispatch(getRequest());
if (filter.updateUrl === 'qna') {
//const filterUrlString = !!filter.searchType ? filter.searchType.toLocaleLowerCase() : '';
//browserHistory.push(getQnaUrl({ request }) + '/' + filterUrlString);
} else if (filter.updateUrl === 'search') {
const { search, qnaSelectedFilters } = getState();
//On SearchPage when changing qnaSortOrder get the full url and update it with the new filter
const type = search.filter ? '/' + search.filter : '';
let sortOrder = '';
if (
!!filter.searchType &&
!!qnaSelectedFilters.searchSearchInput.searchType &&
filter.searchType !== qnaSelectedFilters.searchSearchInput.searchType
) {
//set using new searchType
sortOrder = '/' + filter.searchType.toLocaleLowerCase();
} else if (qnaSelectedFilters.searchSearchInput.searchType) {
//set using previous state
sortOrder = '/' + qnaSelectedFilters.searchSearchInput.searchType.toLocaleLowerCase();
} else if (filter.searchType) {
sortOrder = '/' + filter.searchType.toLocaleLowerCase();
}
let _filter = '';
if (!!filter.issue && filter.issue !== qnaSelectedFilters.searchSearchInput.issue) {
//set using new issue
_filter = '/' + filter.issue;
} else if (qnaSelectedFilters.searchSearchInput.issue) {
//set using previous state
_filter = '/' + qnaSelectedFilters.searchSearchInput.issue.toLocaleLowerCase();
}
const newPath = Search.getSearchBaseUrl({ request }) + type + sortOrder + _filter;
if (!!filter.updateUrl && isRunningInBrowser() && newPath !== request.location.pathname) {
// FIXME: browserHistory
//browserHistory.push(newPath);
}
//Also dispatch a new search
if (triggerSearch) {
dispatch(
searchActions.search({
reduxStorageUrl: search.searchType,
searchParams: {
q: search.q,
selectedFilters: qnaSelectedFilters.searchSearchInput,
p: 1,
gameId: 16 /* FIXME: hardcoded id */
}
})
);
}
}
};
}
function _changeFilter({ filter, contentType }: ChangeFilter): AnyAction {
return {
type: CHANGE_FILTER,
filter,
contentType
};
}
export function getAvailableFilters(): Thunk<Promise<XcapJsonResult>> {
return async (dispatch: any): Promise<XcapJsonResult> => {
const categoryInfo = await dispatch(getCategories({}));
if (typeof categoryInfo.error !== 'undefined') {
dispatch(
setAvailableFilters({
filterGames: [],
filterPlatforms: [],
filterIssues: [],
filterDevices: [],
filterError: categoryInfo.error
})
);
} else {
dispatch(
setAvailableFilters({
filterGames: categoryInfo.gameTagCategories,
filterPlatforms: categoryInfo.gamePlatformCategories,
filterIssues: categoryInfo.gameIssueCategories,
filterDevices: categoryInfo.gameDeviceCategories,
filterError: false
})
);
}
return categoryInfo;
};
}
//Action Creator to change selected filter in reduxStoreName
function setAvailableFilters(filters: {
filterGames: Array<any>;
filterPlatforms: Array<any>;
filterIssues: Array<any>;
filterDevices: Array<any>;
filterError: any;
}): AnyAction {
return {
type: SET_QNA_AVAILABLE_FILTERS,
filters
};
}
function receiveSearchResult(result: {
entries: Array<any>;
relatedObjects: Array<any>;
categoryCounts: { [key: number]: any };
error: boolean;
}): AnyAction {
return {
type: RECEIVE_SEARCH_RESULT,
result
};
}
export function searchQna({ searchString, selectedFilters, game }: any): Thunk<Promise<any>> {
//Load questions using search and filters from King Care
return async (dispatch: any, getState: any): Promise<any> => {
const qo = generateQueryObject(searchString, selectedFilters, getState().qnaAvailableFilters);
const searchResult = await dispatch(_search({ ...qo, game }));
if (typeof searchResult.error !== 'undefined') {
return dispatch(
receiveSearchResult({
entries: [],
relatedObjects: [],
categoryCounts: {},
error: searchResult.error
})
);
} else {
return dispatch(
receiveSearchResult({
entries: searchResult.results.entries,
relatedObjects: searchResult.__relatedObjects,
categoryCounts: searchResult.categoryCounts,
error: false
})
);
}
};
}
function generateQueryObject(searchString = '', selectedFilters: any, availableFilters: any): any {
const qo = {};
const searchType = selectedFilters.searchType
? QnaTypeConverter(selectedFilters.searchType.substring(selectedFilters.searchType.lastIndexOf('/') + 1))
: undefined;
// FIXME: Fix this
const platform = selectedFilters.platform
? // @ts-ignore
find(
availableFilters.filterPlatforms,
{ id: selectedFilters.platform },
// @ts-ignore
{ partOfPermalink: undefined }
).partOfPermalink
: undefined;
const issue = selectedFilters.issue
? // @ts-ignore
find(
availableFilters.filterIssues,
{ id: selectedFilters.issue },
// @ts-ignore
{ partOfPermalink: undefined }
).partOfPermalink
: undefined;
const device = selectedFilters.device
? // @ts-ignore
find(
availableFilters.filterDevices,
{ id: selectedFilters.device },
// @ts-ignore
{ partOfPermalink: undefined }
).partOfPermalink
: undefined;
// FIXME:
// @ts-ignore
qo.q = searchString;
return { ...qo, ...selectedFilters, searchType, platform, issue, device };
}
//Action Creator to lock selected game to a specific game eg. {id: 4, name: "papa-pear-saga"}
/*export function setGame(game: {id: number, name: string}) {
return {
type: SET_QNA_GAME,
game
}
}*/