Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fd6fd7c
do not transform mailto links in markdown
Feb 23, 2025
41627e7
Fix styling of More button in the Nav header
kshxtij May 1, 2025
878456c
Merge branch 'fix-opacity-more-navbar' into 'master'
yutotakano Nov 27, 2025
6de80aa
Fix light mode TopHeader using --mantine-color-anchor instead of pare…
yutotakano Dec 2, 2025
2b0fe61
Fix listmetacategories being fetched freshly for every meta category …
yutotakano Dec 2, 2025
f46774f
Merge branch 'fix-topnav-lightmode-color' into 'master'
yutotakano Dec 3, 2025
2f6a63b
Merge branch 'fix-excessive-listmetacategories' into 'master'
yutotakano Dec 3, 2025
c66a538
Fix lacking permission checks for image deletion API
yutotakano Jan 1, 2026
30f1c05
Merge branch 'fix-image-deletion-permission' into 'master'
yutotakano Jan 1, 2026
e3693f1
Fix tab closing due to call to undefined 'close' calling window.close()
yutotakano Jan 1, 2026
b4dedbe
Merge branch 'fix-391' into 'master'
burakemirsezen Jan 1, 2026
70bfc27
only transform image urls on img tags
michaelstambach Jan 1, 2026
5b19fb6
Merge branch 'master' into fix-md-mailto
michaelstambach Jan 1, 2026
11a92a9
Fix document list not refreshing when navigating between categories
yutotakano Jan 2, 2026
13fe923
Merge branch 'fix-md-mailto' into 'master'
yutotakano Jan 2, 2026
4166e2b
Merge branch 'fix-stale-documents' into 'master'
yutotakano Jan 4, 2026
eed402e
Fix extraneous arrow showing on home page if Meta 2 is empty string
yutotakano Nov 26, 2025
51a5804
Merge branch 'fix-arrow-meta-categories' into 'master'
burakemirsezen Jan 5, 2026
5ec36c5
Merge remote-tracking branch 'ethz/master' into upstream-integration
yutotakano Jan 25, 2026
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
43 changes: 43 additions & 0 deletions backend/images/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,46 @@ def test_wrong_file_extension(self):
res = self.post('/api/image/upload/', {
'file': f,
}, status_code=400)


class TestRemoveImage(ComsolTest):
filename = None

def mySetUp(self):
# Upload an image as user 0
self.user = self.loginUsers[0]
with open("static/test_uploadrm.svg", "rb") as f:
res = self.post(
"/api/image/upload/",
{
"file": f,
},
)

self.get(f"/api/image/get/{res['filename']}/", as_json=False, status_code=200)

self.filename = res["filename"]

def test_cannot_remove_non_owned_image(self):
# If different non-admin user, shouldn't be able to remove image
self.user = self.loginUsers[1]
self.user["admin"] = False

self.post(f"/api/image/remove/{self.filename}/", {}, status_code=403)
self.get(f"/api/image/get/{self.filename}/", as_json=False, status_code=200)

def test_can_delete_owned_image(self):
# If same user, should be able to remove image
self.user = self.loginUsers[0]
self.user["admin"] = False

self.post(f"/api/image/remove/{self.filename}/", {}, status_code=200)
self.get(f"/api/image/get/{self.filename}/", as_json=False, status_code=404)

def test_admin_can_delete_non_owned_image(self):
# If admin, should be able to delete other people's images too
self.user = self.loginUsers[1]
self.user["admin"] = True

self.post(f"/api/image/remove/{self.filename}/", {}, status_code=200)
self.get(f"/api/image/get/{self.filename}/", as_json=False, status_code=404)
4 changes: 4 additions & 0 deletions backend/images/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def upload_image(request):
@auth_check.require_login
def remove_image(request, filename):
image = get_object_or_404(Image, filename=filename)

if not (image.owner == request.user or auth_check.has_admin_rights(request)):
return response.not_allowed()

s3_util.delete_file(settings.COMSOL_IMAGE_DIR, filename)
image.delete()
return response.success()
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/api/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ export const loadMetaCategories = async () => {
.value as MetaCategory[];
};
export const useMetaCategories = () => {
const { error, loading, data, mutate } = useRequest(loadMetaCategories);
const { error, loading, data, mutate } = useRequest(loadMetaCategories, {
cacheKey: "listmetacategories",
});
return [error, loading, data, mutate] as const;
};
export const loadList = async (slug: string) => {
Expand Down Expand Up @@ -477,6 +479,7 @@ export const loadDocuments = async (categorySlug: string) => {
export const useDocuments = (categorySlug: string) => {
const { data } = useRequest(() => loadDocuments(categorySlug), {
cacheKey: `documents-${categorySlug}`,
refreshDeps: [categorySlug],
});
return [data] as const;
};
Expand Down
8 changes: 2 additions & 6 deletions frontend/src/components/Navbar/BottomHeader.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
height: 3.5rem;
box-sizing: border-box;
border-bottom: 2px solid var(--mantine-color-gray-2);
color: var(--mantine-color-anchor);
background: var(--mantine-color-body);
position: fixed;
top: 0;
width: 100%;
z-index: var(--mantine-z-index-app);
/* box-shadow: var(--mantine-shadow-xs); */

/* Add a margin left equal to the width of the scorllbar, so the navbar doesn't
shift around depending on page length. A similar style is applied to the body.*/
Expand All @@ -38,11 +38,7 @@
.title {
display: flex;
text-decoration: none;
color: rgba(51, 51, 51, 1);
font-weight: 400;
font-size: 1.25rem;

@mixin dark {
color: rgba(255, 255, 255, 0.8);
}
color: inherit; /* don't try to apply default mantine link styles */
}
10 changes: 8 additions & 2 deletions frontend/src/components/Navbar/ExternalNav.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
.navItem {
padding-left: 0rem;
padding-right: 0rem;
padding-left: 0;
padding-right: 0;
text-align: right;
display: initial;
cursor: pointer;
font-size: 1.125rem;
line-height: 1.75rem;
text-transform: uppercase;
white-space: nowrap;
font-weight: 500;
/* don't use mantine-color-anchor (applied to all Anchor elements) but instead
* use any color set by parent. This is a fix for text becoming black on light
* mode even on dark background
*/
color: inherit;

@media (max-width: $mantine-breakpoint-md) {
text-align: left;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Navbar/ExternalNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const ExternalNavElement: React.FC<Props> = ({
component="div"
size="lg"
className={clsx(classes.navItem, classes.link, textClassName)}
display="flex"
style={{
display: "flex",
padding: 0,
cursor: "pointer",
}}
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/Navbar/MobileHeader.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
.navbar {
min-height: 3.5rem;
color: var(--mantine-color-text);
color: var(--mantine-color-anchor);
width: 100%;
box-sizing: border-box;
border-bottom: 2px solid var(--mantine-color-gray-2);
@mixin dark {
border-bottom: 2px solid var(--mantine-color-dark-6);
}
}

.navItem {
color: var(--mantine-color-text);
color: var(--mantine-color-anchor);
}

.logoLine {
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/components/Navbar/QuickSearch/QuickSearchBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ export const QuickSearchBox: React.FC = () => {
type="categories"
results={categoryResults}
currentSelection={currentSelection}
onClick={close}
/>
{!searchResults.loading && searchResults.error && (
<Text c="dimmed" mx="auto">
Expand All @@ -397,21 +398,25 @@ export const QuickSearchBox: React.FC = () => {
type="examNames"
results={networkResults.examNames}
currentSelection={currentSelection}
onClick={close}
/>
<QuickSearchResults
type="examPages"
results={networkResults.examPages}
currentSelection={currentSelection}
onClick={close}
/>
<QuickSearchResults
type="answers"
results={networkResults.answers}
currentSelection={currentSelection}
onClick={close}
/>
<QuickSearchResults
type="comments"
results={networkResults.comments}
currentSelection={currentSelection}
onClick={close}
/>
<Divider variant="dashed" label="More" labelPosition="left" />
<QuickSearchResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type QuickSeachResultsProps = {
| undefined;
index: number;
};
onClick: () => void;
} & (
| {
type: "categories";
Expand Down Expand Up @@ -61,6 +62,7 @@ export const QuickSearchResults = ({
type,
results,
currentSelection,
onClick,
}: QuickSeachResultsProps) => {
// Memoize the expensive rendering of result content so we don't try to
// re-render the content if only the current selection index changes
Expand Down Expand Up @@ -166,7 +168,7 @@ export const QuickSearchResults = ({
isSelected={isSelected}
key={key}
link={link}
onClick={close}
onClick={onClick}
>
{element}
</QuickSearchResult>
Expand All @@ -189,7 +191,7 @@ export const QuickSearchResults = ({
isSelected={isSelected}
key={key}
link={link}
onClick={close}
onClick={onClick}
>
{element}
</QuickSearchResult>
Expand All @@ -212,7 +214,7 @@ export const QuickSearchResults = ({
isSelected={isSelected}
key={key}
link={link}
onClick={close}
onClick={onClick}
>
{element}
</QuickSearchResult>
Expand All @@ -235,7 +237,7 @@ export const QuickSearchResults = ({
isSelected={isSelected}
key={key}
link={link}
onClick={close}
onClick={onClick}
>
{element}
</QuickSearchResult>
Expand All @@ -258,7 +260,7 @@ export const QuickSearchResults = ({
isSelected={isSelected}
key={key}
link={link}
onClick={close}
onClick={onClick}
>
{element}
</QuickSearchResult>
Expand All @@ -268,5 +270,5 @@ export const QuickSearchResults = ({
);

return <></>;
}, [results.length, type, contents, currentSelection]);
}, [results.length, type, contents, currentSelection, onClick]);
};
9 changes: 7 additions & 2 deletions frontend/src/components/markdown-text.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ReactMarkdown, { Components, defaultUrlTransform } from "react-markdown";
import ReactMarkdown, { Components, defaultUrlTransform } from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
Expand Down Expand Up @@ -163,7 +163,12 @@ const errorMessage = (
</Alert>
);

const MarkdownText: React.FC<Props> = ({ value, highlight_matches, localLinkBase, ignoreHtml }) => {
const MarkdownText: React.FC<Props> = ({
value,
highlight_matches,
localLinkBase,
ignoreHtml,
}) => {
// Make sure we don't generate a RegExp with empty text, as that will match
// everything (including the empty string) and can cause mayhem with
// highlighting.
Expand Down
Loading