Skip to content

Commit faa92aa

Browse files
feat: edx endpoint API added, search options added in collection API (#1204)
* fix(deps): update dependency webpack-bundle-tracker to v3.2.0 (#1218) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix: Collection API updated to support search by video fields * feat: Folder structure added for Collection page with search functionality * test: edxEndpoint tests fixed * test: CollectionListPage tests fixed and new tests added * fix: Show all collections button even there is no endpoint --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent 4b40110 commit faa92aa

20 files changed

+748
-31
lines changed

odl_video/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"django.contrib.messages",
7373
"django.contrib.staticfiles",
7474
"rest_framework",
75+
"django_filters",
7576
"hijack",
7677
"hijack.contrib.admin",
7778
"encrypted_model_fields",

poetry.lock

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ structlog-sentry = "^1.2.2"
4545
urllib3 = "^1.24.2"
4646
uwsgi = "2.0.29"
4747
mitol-django-transcoding = "^2025.5.21"
48+
django-filter = "^25.1"
4849

4950

5051
[tool.poetry.group.dev.dependencies]

static/js/actions/collectionsPagination.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,25 @@ actionCreators.receiveGetPageFailure = createAction(
2020
constants.RECEIVE_GET_PAGE_FAILURE
2121
)
2222

23+
constants.RESET_PAGES = qualifiedName("RESET_PAGES")
24+
actionCreators.resetPages = createAction(constants.RESET_PAGES)
25+
2326
actionCreators.getPage = (opts: { page: number }) => {
2427
const { page } = opts
2528
const thunk = async (dispatch: Dispatch) => {
29+
// Get filters from URL parameters
30+
const params = new URLSearchParams(window.location.search)
31+
const searchQuery = params.get('search')
32+
const edxEndpointId = params.get('edx_endpoint')
33+
34+
// Construct query parameters
35+
const queryParams = { page }
36+
if (searchQuery) queryParams.search = searchQuery
37+
if (edxEndpointId) queryParams.edx_endpoint = edxEndpointId
38+
2639
dispatch(actionCreators.requestGetPage({ page }))
2740
try {
28-
const response = await api.getCollections({ pagination: { page } })
41+
const response = await api.getCollections({ pagination: queryParams })
2942
// @TODO: ideally we would dispatch an action here to save collections to
3043
// a single place in state (e.g. state.collections).
3144
// However, it take a non-trivial refactor to implement this schema

static/js/actions/edxEndpoints.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// @flow
2+
import { createAction } from "redux-actions"
3+
import type { Dispatch } from "redux"
4+
import * as api from "../lib/api"
5+
6+
const qualifiedName = (name: string) => `EDX_ENDPOINTS_${name}`
7+
const constants = {}
8+
const actionCreators = {}
9+
10+
constants.REQUEST_GET_ENDPOINTS = qualifiedName("REQUEST_GET_ENDPOINTS")
11+
actionCreators.requestGetEndpoints = createAction(constants.REQUEST_GET_ENDPOINTS)
12+
13+
constants.RECEIVE_GET_ENDPOINTS_SUCCESS = qualifiedName("RECEIVE_GET_ENDPOINTS_SUCCESS")
14+
actionCreators.receiveGetEndpointsSuccess = createAction(
15+
constants.RECEIVE_GET_ENDPOINTS_SUCCESS
16+
)
17+
18+
constants.RECEIVE_GET_ENDPOINTS_FAILURE = qualifiedName("RECEIVE_GET_ENDPOINTS_FAILURE")
19+
actionCreators.receiveGetEndpointsFailure = createAction(
20+
constants.RECEIVE_GET_ENDPOINTS_FAILURE
21+
)
22+
23+
actionCreators.getEndpoints = () => {
24+
const thunk = async (dispatch: Dispatch) => {
25+
dispatch(actionCreators.requestGetEndpoints())
26+
try {
27+
const response = await api.getEdxEndpoints()
28+
dispatch(
29+
actionCreators.receiveGetEndpointsSuccess({
30+
endpoints: response
31+
})
32+
)
33+
return response
34+
} catch (error) {
35+
dispatch(
36+
actionCreators.receiveGetEndpointsFailure({
37+
error
38+
})
39+
)
40+
}
41+
}
42+
return thunk
43+
}
44+
45+
export { actionCreators, constants }
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// @flow
2+
import { assert } from "chai"
3+
import sinon from "sinon"
4+
import configureTestStore from "redux-asserts"
5+
6+
import rootReducer from "../reducers"
7+
import { actions } from "../actions"
8+
import * as api from "../lib/api"
9+
import { makeEdxEndpointList } from "../factories/edxEndpoints"
10+
import * as edxEndpointActions from "./edxEndpoints"
11+
12+
describe("edxEndpoints actions", () => {
13+
let sandbox, store, dispatchThen
14+
15+
beforeEach(() => {
16+
sandbox = sinon.createSandbox()
17+
store = configureTestStore(rootReducer)
18+
dispatchThen = store.createDispatchThen(state => state.edxEndpoints)
19+
})
20+
21+
afterEach(() => {
22+
sandbox.restore()
23+
})
24+
25+
describe("getEndpoints", () => {
26+
it("fetches endpoints", async () => {
27+
const endpoints = makeEdxEndpointList()
28+
const getEndpointsStub = sandbox
29+
.stub(api, "getEdxEndpoints")
30+
.returns(Promise.resolve(endpoints))
31+
32+
const { data } = await dispatchThen(actions.edxEndpoints.getEndpoints(), [
33+
edxEndpointActions.constants.REQUEST_GET_ENDPOINTS,
34+
edxEndpointActions.constants.RECEIVE_GET_ENDPOINTS_SUCCESS
35+
])
36+
assert.deepEqual(data, endpoints)
37+
sinon.assert.calledWith(getEndpointsStub)
38+
})
39+
40+
it("handles errors", async () => {
41+
const errorMessage = "Error fetching endpoints"
42+
sandbox
43+
.stub(api, "getEdxEndpoints")
44+
.returns(Promise.reject(new Error(errorMessage)))
45+
46+
const { error } = await dispatchThen(actions.edxEndpoints.getEndpoints(), [
47+
edxEndpointActions.constants.REQUEST_GET_ENDPOINTS,
48+
edxEndpointActions.constants.RECEIVE_GET_ENDPOINTS_FAILURE
49+
])
50+
assert.equal(error.message, errorMessage)
51+
})
52+
})
53+
})

static/js/actions/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { endpoints } from "../lib/redux_rest"
66
import * as collectionsPagination from "./collectionsPagination"
77
import * as videoUi from "./videoUi"
88
import * as toast from "./toast"
9+
import * as edxEndpoints from "./edxEndpoints"
910

1011
const actions: Object = {
1112
collectionsPagination: collectionsPagination.actionCreators,
13+
edxEndpoints: edxEndpoints.actionCreators,
1214
videoUi: videoUi.actionCreators,
13-
toast: toast.actionCreators
15+
toast: toast.actionCreators,
1416
}
1517

1618
endpoints.forEach(endpoint => {

0 commit comments

Comments
 (0)