Skip to content

Commit

Permalink
Merge 0908018 into 4b4e28e
Browse files Browse the repository at this point in the history
  • Loading branch information
willdurand committed Oct 12, 2018
2 parents 4b4e28e + 0908018 commit 32aafa0
Show file tree
Hide file tree
Showing 35 changed files with 182 additions and 544 deletions.
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -233,7 +233,6 @@
"mozilla-hybrid-content-telemetry": "1.2.1",
"mozilla-version-comparator": "1.0.2",
"normalize.css": "8.0.0",
"normalizr": "3.2.2",
"pino": "5.7.0",
"pino-mozlog": "1.2.0",
"prop-types": "15.6.2",
Expand Down
22 changes: 0 additions & 22 deletions src/amo/actions/featured.js

This file was deleted.

8 changes: 4 additions & 4 deletions src/amo/components/AddonReview/index.js
Expand Up @@ -22,7 +22,7 @@ import UserRating from 'ui/components/UserRating';
import type { UserReviewType } from 'amo/actions/reviews';
import type { SubmitReviewParams } from 'amo/api/reviews';
import type { AppState } from 'amo/store';
import { loadAddons } from 'core/reducers/addons';
import { loadAddonResults } from 'core/reducers/addons';
import type { ApiState } from 'core/reducers/api';
import type { ErrorHandler as ErrorHandlerType } from 'core/errorHandler';
import type { ElementEvent } from 'core/types/dom';
Expand Down Expand Up @@ -283,9 +283,9 @@ export const mapDispatchToProps = (
refreshAddon:
ownProps.refreshAddon ||
(({ addonSlug, apiState }) => {
return fetchAddon({ slug: addonSlug, api: apiState }).then(
({ entities }) => dispatch(loadAddons(entities)),
);
return fetchAddon({ slug: addonSlug, api: apiState }).then((addon) => {
dispatch(loadAddonResults({ addons: [addon] }));
});
}),
setInternalReview: (review) => {
dispatch(_setInternalReview(review));
Expand Down
18 changes: 3 additions & 15 deletions src/amo/reducers/home.js
Expand Up @@ -57,18 +57,9 @@ export const fetchHomeAddons = ({
};
};

type ExternalAddonMap = {
[addonSlug: string]: ExternalAddonType,
};

type ApiAddonsResponse = {|
result: {|
count: number,
results: Array<string>,
|},
entities: {|
addons: ExternalAddonMap,
|},
count: number,
results: Array<ExternalAddonType>,
|};

type LoadHomeAddonsParams = {|
Expand Down Expand Up @@ -109,10 +100,7 @@ type Action = FetchHomeAddonsAction | LoadHomeAddonsAction;
const createInternalAddons = (
response: ApiAddonsResponse,
): Array<AddonType> => {
const { result, entities } = response;
return result.results.map((slug) =>
createInternalAddon(entities.addons[slug]),
);
return response.results.map((addon) => createInternalAddon(addon));
};

const reducer = (
Expand Down
6 changes: 3 additions & 3 deletions src/amo/reducers/landing.js
Expand Up @@ -29,9 +29,9 @@ export default function landing(state = initialState, action) {
['featured', 'highlyRated', 'trending'].forEach((key) => {
if (payload[key]) {
newState[key] = {
count: payload[key].result.count,
results: payload[key].result.results.map((slug) =>
createInternalAddon(payload[key].entities.addons[slug]),
count: payload[key].count,
results: payload[key].results.map((addon) =>
createInternalAddon(addon),
),
};
}
Expand Down
7 changes: 2 additions & 5 deletions src/amo/sagas/addonsByAuthors.js
Expand Up @@ -39,15 +39,12 @@ export function* fetchAddonsByAuthors({ payload }) {
},
});

// TODO: remove the line below and pass `response.addons` directly once
// https://github.com/mozilla/addons-frontend/issues/2917 is done.
const addons = Object.values(response.entities.addons || {});
const { count } = response.result;
const { count, results } = response;

yield put(
loadAddonsByAuthors({
addonType,
addons,
addons: results,
authorUsernames,
count,
forAddonSlug,
Expand Down
6 changes: 4 additions & 2 deletions src/amo/sagas/categories.js
Expand Up @@ -14,8 +14,10 @@ export function* fetchCategories({ payload: { errorHandlerId } }) {
const errorHandler = createErrorHandler(errorHandlerId);
try {
const state = yield select(getState);
const response = yield call(categoriesApi, { api: state.api });
yield put(categoriesLoad(response));

const results = yield call(categoriesApi, { api: state.api });

yield put(categoriesLoad({ results }));
} catch (error) {
log.warn('Categories failed to load:', error);
yield put(errorHandler.createErrorAction(error));
Expand Down
4 changes: 2 additions & 2 deletions src/core/actions/categories.js
Expand Up @@ -10,9 +10,9 @@ export function categoriesFetch({ errorHandlerId } = {}) {
};
}

export function categoriesLoad(response) {
export function categoriesLoad({ results }) {
return {
type: CATEGORIES_LOAD,
payload: { result: response.result },
payload: { results },
};
}
12 changes: 1 addition & 11 deletions src/core/api/index.js
Expand Up @@ -3,7 +3,6 @@
import url from 'url';

import utf8 from 'utf8';
import { schema as normalizrSchema, normalize } from 'normalizr';
import { oneLine } from 'common-tags';
import config from 'config';

Expand All @@ -21,13 +20,9 @@ import type { LocalizedString, PaginatedApiResponse } from 'core/types/api';
import type { ReactRouterLocationType } from 'core/types/router';

const API_BASE = `${config.get('apiHost')}${config.get('apiPath')}`;
const { Entity } = normalizrSchema;

export const DEFAULT_API_PAGE_SIZE = 25;

export const addon = new Entity('addons', {}, { idAttribute: 'slug' });
export const category = new Entity('categories', {}, { idAttribute: 'slug' });

export function makeQueryString(query: { [key: string]: any }) {
const resolvedQuery = { ...query };
Object.keys(resolvedQuery).forEach((key) => {
Expand Down Expand Up @@ -80,15 +75,13 @@ type CallApiParams = {|
errorHandler?: ErrorHandlerType,
method?: 'GET' | 'POST' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PUT' | 'PATCH',
params?: Object,
schema?: Object,
_config?: typeof config,
version?: string,
_log?: typeof log,
|};

export function callApi({
endpoint,
schema,
params = {},
auth = false,
apiState = initialApiState,
Expand Down Expand Up @@ -227,8 +220,7 @@ export function callApi({
}
throw fetchError;
},
)
.then((response) => (schema ? normalize(response, schema) : response));
);
}

export type FetchAddonParams = {|
Expand All @@ -250,7 +242,6 @@ export function fetchAddon({ api, slug }: FetchAddonParams) {
app: clientApp,
appversion: appVersion,
}),
schema: addon,
auth: true,
apiState: api,
});
Expand Down Expand Up @@ -281,7 +272,6 @@ export function startLoginUrl({
export function categories({ api }: {| api: ApiState |}) {
return callApi({
endpoint: 'addons/categories',
schema: { results: [category] },
apiState: api,
});
}
Expand Down
3 changes: 1 addition & 2 deletions src/core/api/search.js
@@ -1,5 +1,5 @@
/* @flow */
import { addon, callApi } from 'core/api';
import { callApi } from 'core/api';
import {
addVersionCompatibilityToFilters,
convertFiltersToQueryParams,
Expand Down Expand Up @@ -35,7 +35,6 @@ export function search({ api, auth = false, filters = {} }: SearchParams) {

return callApi({
endpoint: 'addons/search',
schema: { results: [addon] },
params: convertFiltersToQueryParams(newFilters),
apiState: api,
auth,
Expand Down
39 changes: 4 additions & 35 deletions src/core/reducers/addons.js
Expand Up @@ -14,40 +14,11 @@ import type {
ThemeData,
} from 'core/types/addons';

export const LOAD_ADDONS: 'LOAD_ADDONS' = 'LOAD_ADDONS';
export const FETCH_ADDON: 'FETCH_ADDON' = 'FETCH_ADDON';
export const LOAD_ADDON_RESULTS: 'LOAD_ADDON_RESULTS' = 'LOAD_ADDON_RESULTS';

type AddonID = number;

export type ExternalAddonMap = {
[addonSlug: string]: ExternalAddonType,
};

export type LoadAddonsAction = {|
payload: {| addons: ExternalAddonMap |},
type: typeof LOAD_ADDONS,
|};

// TODO: We should remove this method and move all calls to `loadAddonResults`.
// This function relies on normalizr messing with our response data.
// See: https://github.com/mozilla/addons-frontend/issues/2917
export function loadAddons(entities: {
addons: ExternalAddonMap,
}): LoadAddonsAction {
if (!entities) {
throw new Error('the entities parameter cannot be empty');
}
return {
type: LOAD_ADDONS,
// TODO: after https://github.com/mozilla/addons-frontend/issues/2917
// hopefully this can be a little less fragile. Right now if the
// caller passes in an incorrect `entities` then we have no way of
// throwing an error.
payload: { addons: entities.addons || {} },
};
}

type FetchAddonParams = {|
errorHandler: ErrorHandlerType,
slug: string,
Expand Down Expand Up @@ -78,11 +49,11 @@ export function fetchAddon({
}

type LoadAddonResultsParams = {|
addons: ExternalAddonMap,
addons: Array<ExternalAddonType>,
|};

export type LoadAddonResultsAction = {|
payload: {| addons: ExternalAddonMap |},
payload: LoadAddonResultsParams,
type: typeof LOAD_ADDON_RESULTS,
|};

Expand Down Expand Up @@ -328,7 +299,6 @@ export const getAllAddons = (state: AppState): Array<AddonType> => {

type Action =
| FetchAddonAction
| LoadAddonsAction
| LoadAddonResultsAction
| UnloadAddonReviewsAction;

Expand All @@ -347,7 +317,6 @@ export default function addonsReducer(
},
};
}
case LOAD_ADDONS:
case LOAD_ADDON_RESULTS: {
const { addons: loadedAddons } = action.payload;

Expand All @@ -356,8 +325,8 @@ export default function addonsReducer(
const bySlug = { ...state.bySlug };
const loadingBySlug = { ...state.loadingBySlug };

Object.keys(loadedAddons).forEach((key) => {
const addon = createInternalAddon(loadedAddons[key]);
loadedAddons.forEach((loadedAddon) => {
const addon = createInternalAddon(loadedAddon);
// Flow wants hash maps with string keys.
// See: https://zhenyong.github.io/flowtype/docs/objects.html#objects-as-maps
byID[`${addon.id}`] = addon;
Expand Down
2 changes: 1 addition & 1 deletion src/core/reducers/categories.js
Expand Up @@ -33,7 +33,7 @@ export default function categories(state = initialState, action) {
return { ...initialState, loading: true };
case CATEGORIES_LOAD: {
const categoryList = emptyCategoryList();
Object.values(payload.result).forEach((category) => {
Object.values(payload.results).forEach((category) => {
// This category has no data, so skip it.
if (!category || !category.application) {
log.warn('category or category.application was false-y.', category);
Expand Down
29 changes: 11 additions & 18 deletions src/core/reducers/search.js
Expand Up @@ -79,14 +79,9 @@ export function searchStart({
}

type SearchLoadParams = {|
entities: {|
addons: { [slug: string]: ExternalAddonType },
|},
result: {|
count: number,
page_size: number,
results: Array<string>,
|},
count: number,
pageSize: number,
results: Array<ExternalAddonType>,
|};

type SearchLoadAction = {|
Expand All @@ -95,15 +90,15 @@ type SearchLoadAction = {|
|};

export function searchLoad({
entities,
result,
count,
pageSize,
results,
}: SearchLoadParams): SearchLoadAction {
invariant(entities, 'entities are required');
invariant(result, 'result is required');
invariant(results, 'results are required');

return {
type: SEARCH_LOADED,
payload: { entities, result },
payload: { count, pageSize, results },
};
}

Expand Down Expand Up @@ -134,12 +129,10 @@ export default function search(

return {
...state,
count: payload.result.count,
count: payload.count,
loading: false,
pageSize: payload.result.page_size,
results: payload.result.results.map((slug) =>
createInternalAddon(payload.entities.addons[slug]),
),
pageSize: payload.pageSize,
results: payload.results.map((addon) => createInternalAddon(addon)),
};
}
case SEARCH_ABORTED:
Expand Down
6 changes: 3 additions & 3 deletions src/core/sagas/addons.js
Expand Up @@ -7,7 +7,7 @@ import { call, put, select, takeEvery } from 'redux-saga/effects';
/* eslint-enable import/order */

import { fetchAddon as fetchAddonFromApi } from 'core/api';
import { FETCH_ADDON, loadAddons } from 'core/reducers/addons';
import { FETCH_ADDON, loadAddonResults } from 'core/reducers/addons';
import log from 'core/logger';
import type { FetchAddonParams } from 'core/api';
import type { FetchAddonAction } from 'core/reducers/addons';
Expand All @@ -23,9 +23,9 @@ export function* fetchAddon({
const state = yield select(getState);

const params: FetchAddonParams = { api: state.api, slug };
const response = yield call(fetchAddonFromApi, params);
const addon = yield call(fetchAddonFromApi, params);

yield put(loadAddons(response.entities));
yield put(loadAddonResults({ addons: [addon] }));
} catch (error) {
log.warn(`Failed to load add-on with slug ${slug}: ${error}`);
yield put(errorHandler.createErrorAction(error));
Expand Down
4 changes: 2 additions & 2 deletions src/core/sagas/search.js
Expand Up @@ -25,9 +25,9 @@ export function* fetchSearchResults({ payload }) {
auth: true,
filters,
});
const { entities, result } = response;
const { count, page_size: pageSize, results } = response;

yield put(searchLoad({ entities, result }));
yield put(searchLoad({ count, pageSize, results }));
} catch (error) {
log.warn(`Search results failed to load: ${error}`);
yield put(errorHandler.createErrorAction(error));
Expand Down

0 comments on commit 32aafa0

Please sign in to comment.