Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
Release Notes
=============

Version 0.19.1
--------------

- fix adornment color (#1578)
- fix homepage testimonials font (#1568)
- properly add Mit-AdornmentButton class (#1574)
- fixing cache clear method (#1573)
- add SignupPopover to learning resource drawer bookmark button (#1565)
- Delivery and availability fields for runs (#1470)
- add caching to remaining views (#1555)
- Fix refreshes and deterministic sort order (#1564)
- align items center (#1566)
- add noindex setting (#1559)
- always use dfs_query_then_fetch (#1558)
- updated OLL csv file (#1557)
- input / search input styling updates (#1545)
- Update dependency pytest to v8 (#1548)

Version 0.19.0 (Released September 16, 2024)
--------------

Expand Down
4 changes: 4 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@
"description": "Shared secret for JWT auth tokens",
"required": false
},
"MITOL_NOINDEX": {
"description": "Prevent search engines from indexing the site",
"required": false
},
"MITOL_SECURE_SSL_REDIRECT": {
"description": "Application-level SSL redirect setting.",
"value": "True",
Expand Down
19 changes: 19 additions & 0 deletions articles/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.conf import settings
from django.utils.decorators import method_decorator
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import viewsets
from rest_framework.pagination import LimitOffsetPagination
Expand All @@ -6,6 +8,7 @@
from articles.models import Article
from articles.serializers import ArticleSerializer
from main.constants import VALID_HTTP_METHODS
from main.utils import cache_page_for_all_users, clear_search_cache

# Create your views here.

Expand Down Expand Up @@ -37,3 +40,19 @@ class ArticleViewSet(viewsets.ModelViewSet):

permission_classes = [IsAdminUser]
http_method_names = VALID_HTTP_METHODS

@method_decorator(
cache_page_for_all_users(
settings.SEARCH_PAGE_CACHE_DURATION, cache="redis", key_prefix="search"
)
)
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)

def create(self, request, *args, **kwargs):
clear_search_cache()
return super().create(request, *args, **kwargs)

def destroy(self, request, *args, **kwargs):
clear_search_cache()
return super().destroy(request, *args, **kwargs)
15 changes: 13 additions & 2 deletions channels/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,8 +483,14 @@ def test_channel_counts_view(client):
)


def test_channel_counts_view_is_cached_for_anonymous_users(client):
def test_channel_counts_view_is_cached_for_anonymous_users(client, settings):
"""Test the channel counts view is cached for anonymous users"""
settings.CACHES["redis"] = {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": settings.CELERY_BROKER_URL,
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
}

channel_count = 5
channels = ChannelFactory.create_batch(channel_count, channel_type="unit")
url = reverse(
Expand All @@ -499,8 +505,13 @@ def test_channel_counts_view_is_cached_for_anonymous_users(client):
assert len(response) == channel_count


def test_channel_counts_view_is_cached_for_authenticated_users(client):
def test_channel_counts_view_is_cached_for_authenticated_users(client, settings):
"""Test the channel counts view is cached for authenticated users"""
settings.CACHES["redis"] = {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": settings.CELERY_BROKER_URL,
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
}
channel_count = 5
channel_user = UserFactory.create()
client.force_login(channel_user)
Expand Down
9 changes: 9 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ def prevent_requests(mocker, request): # noqa: PT004
autospec=True,
side_effect=DoNotUseRequestException,
)


@pytest.fixture(autouse=True)
def _use_dummy_redis_cache_backend(settings):
new_cache_settings = settings.CACHES.copy()
new_cache_settings["redis"] = {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
}
settings.CACHES = new_cache_settings
133 changes: 24 additions & 109 deletions frontends/api/src/generated/v1/api.ts

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions frontends/api/src/test-utils/factories/learningResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import type {
VideoResource,
} from "api"
import {
AvailabilityEnum,
DeliveryEnum,
ResourceTypeEnum,
LearningResourceRunLevelInnerCodeEnum,
PlatformEnum,
Expand Down Expand Up @@ -177,6 +179,13 @@ const learningResourceRun: Factory<LearningResourceRun> = (overrides = {}) => {
languages: maybe(() => repeat(language, { min: 0, max: 3 })),
start_date: start.toISOString(),
end_date: end.toISOString(),
availability: faker.helpers.arrayElement(Object.values(AvailabilityEnum)),
delivery: [
{
code: faker.helpers.arrayElement(Object.values(DeliveryEnum)),
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
level: [
{
code: faker.helpers.arrayElement(
Expand Down
3 changes: 3 additions & 0 deletions frontends/mit-learn/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<% if (MITOL_NOINDEX) { %>
<meta name="robots" content="noindex" />
<% } %>
<!--
Font files for Adobe Neue Haas Grotesk.
WARNING: This is linked to chudzick@mit.edu's Adobe account.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
LearningResourceListCard,
LearningResourceListCardCondensed,
} from "ol-components"
import { ResourceListCard } from "@/page-components/ResourceCard/ResourceCard"
import { ResourceCard } from "@/page-components/ResourceCard/ResourceCard"
import { useListItemMove } from "api/hooks/learningResources"

const EmptyMessage = styled.p({
Expand Down Expand Up @@ -153,9 +153,10 @@ const ItemsListing: React.FC<ItemsListingProps> = ({
<StyledPlainList itemSpacing={condensed ? 1 : 2}>
{items.map((item) => (
<li key={item.id}>
<ResourceListCard
<ResourceCard
resource={item.resource}
condensed={condensed}
list
/>
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,23 @@ describe("LearningResourceDrawer", () => {
isLearningPathEditor: true,
isAuthenticated: true,
expectAddToLearningPathButton: true,
expectAddToUserListButton: true,
},
{
isLearningPathEditor: false,
isAuthenticated: true,
expectAddToLearningPathButton: false,
expectAddToUserListButton: true,
},
{
isLearningPathEditor: false,
isAuthenticated: false,
expectAddToLearningPathButton: false,
expectAddToUserListButton: false,
},
])(
"Renders info section list buttons correctly",
async ({
isLearningPathEditor,
isAuthenticated,
expectAddToLearningPathButton,
expectAddToUserListButton,
}) => {
const resource = factories.learningResources.resource({
resource_type: ResourceTypeEnum.Course,
Expand Down Expand Up @@ -159,24 +155,14 @@ describe("LearningResourceDrawer", () => {
.closest("section")
invariant(section)

if (!isAuthenticated) {
const buttons = within(section).queryAllByRole("button")
expect(buttons).toHaveLength(0)
return
} else {
const buttons = within(section).getAllByRole("button")
const expectedButtons =
expectAddToLearningPathButton && expectAddToUserListButton ? 2 : 1
expect(buttons).toHaveLength(expectedButtons)
expect(
!!within(section).queryByRole("button", {
name: "Add to Learning Path",
}),
).toBe(expectAddToLearningPathButton)
expect(
!!within(section).queryByRole("button", { name: "Add to User List" }),
).toBe(expectAddToUserListButton)
}
const buttons = within(section).getAllByRole("button")
const expectedButtons = expectAddToLearningPathButton ? 2 : 1
expect(buttons).toHaveLength(expectedButtons)
expect(
!!within(section).queryByRole("button", {
name: "Add to Learning Path",
}),
).toBe(expectAddToLearningPathButton)
},
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
AddToLearningPathDialog,
AddToUserListDialog,
} from "../Dialogs/AddToListDialog"
import * as urls from "@/common/urls"

const RESOURCE_DRAWER_PARAMS = [RESOURCE_DRAWER_QUERY_PARAM] as const

Expand Down Expand Up @@ -64,6 +65,7 @@ const unsafe_html2plaintext = (text: string) => {
const DrawerContent: React.FC<{
resourceId: number
}> = ({ resourceId }) => {
const loc = useLocation()
const resource = useLearningResourcesDetail(Number(resourceId))
const { data: user } = useUserMe()
const handleAddToLearningPathClick: LearningResourceCardProps["onAddToLearningPathClick"] =
Expand Down Expand Up @@ -101,6 +103,10 @@ const DrawerContent: React.FC<{
user={user}
onAddToLearningPathClick={handleAddToLearningPathClick}
onAddToUserListClick={handleAddToUserListClick}
signupUrl={urls.login({
pathname: loc.pathname,
search: loc.search,
})}
/>
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
expectProps,
} from "../../test-utils"
import type { User } from "../../test-utils"
import { ResourceCard, ResourceListCard } from "./ResourceCard"
import { ResourceCard } from "./ResourceCard"
import {
AddToLearningPathDialog,
AddToUserListDialog,
Expand Down Expand Up @@ -39,14 +39,14 @@ jest.mock("@ebay/nice-modal-react", () => {

describe.each([
{
CardComponent: ResourceCard,
BaseComponent: LearningResourceCard,
isList: false,
},
{
CardComponent: ResourceListCard,
BaseComponent: LearningResourceListCard,
isList: true,
},
])("$CardComponent", ({ CardComponent, BaseComponent }) => {
])("$CardComponent", ({ BaseComponent, isList }) => {
const makeResource = factories.learningResources.resource
type SetupOptions = {
user?: Partial<User>
Expand All @@ -60,7 +60,7 @@ describe.each([
setMockResponse.get(urls.userMe.get(), {}, { code: 403 })
}
const { view, location } = renderWithProviders(
<CardComponent {...props} resource={resource} />,
<ResourceCard {...props} resource={resource} list={isList} />,
)
return { resource, view, location }
}
Expand Down
Loading