Skip to content

Commit 21cc012

Browse files
committed
Merge branch 'master' into dependabot/npm_and_yarn/compose/neurosynth-frontend/multi-81f6ed4da7
2 parents faa0632 + a6b7c8c commit 21cc012

File tree

9 files changed

+442
-135
lines changed

9 files changed

+442
-135
lines changed

.github/workflows/deploy-to-staging.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ jobs:
7070
# Wait for PostgreSQL to be ready
7171
until docker compose exec store_pgsql pg_isready; do sleep 5; done
7272
73-
docker compose exec store flask db migrate
74-
docker compose exec store flask db upgrade
73+
docker compose exec neurostore flask db migrate
74+
docker compose exec neurostore flask db upgrade
7575
'
7676
7777
- name: Run Docker commands in compose directory if changes detected
Lines changed: 63 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,79 @@
1-
import Close from "@mui/icons-material/Close";
2-
import { IconButton } from "@mui/material";
3-
import { AxiosError } from "axios";
4-
import useGoogleAnalytics from "hooks/useGoogleAnalytics";
5-
import { SnackbarKey, SnackbarProvider } from "notistack";
6-
import { useEffect, useRef } from "react";
7-
import { QueryCache, QueryClient, QueryClientProvider } from "react-query";
8-
import Navbar from "components/Navbar/Navbar";
9-
import useGetToken from "./hooks/useGetToken";
10-
import BaseNavigation from "pages/BaseNavigation/BaseNavigation";
11-
import { useLocation } from "react-router-dom";
12-
import Downbanner from "components/Downbanner";
1+
import Close from '@mui/icons-material/Close';
2+
import { IconButton } from '@mui/material';
3+
import { AxiosError } from 'axios';
4+
import useGoogleAnalytics from 'hooks/useGoogleAnalytics';
5+
import { SnackbarKey, SnackbarProvider } from 'notistack';
6+
import { useEffect, useRef } from 'react';
7+
import { QueryCache, QueryClient, QueryClientProvider } from 'react-query';
8+
import Navbar from 'components/Navbar/Navbar';
9+
import useGetToken from './hooks/useGetToken';
10+
import BaseNavigation from 'pages/BaseNavigation/BaseNavigation';
11+
import { useLocation } from 'react-router-dom';
1312

1413
const queryClient = new QueryClient({
15-
defaultOptions: {
16-
queries: {
17-
retry: 0,
18-
refetchOnWindowFocus: false,
19-
// staleTime: 5000, // https://tkdodo.eu/blog/practical-react-query#the-defaults-explained
14+
defaultOptions: {
15+
queries: {
16+
retry: 0,
17+
refetchOnWindowFocus: false,
18+
// staleTime: 5000, // https://tkdodo.eu/blog/practical-react-query#the-defaults-explained
19+
},
2020
},
21-
},
22-
queryCache: new QueryCache({
23-
onError: (error) => {
24-
console.log({ error });
25-
const responseStatus = (error as AxiosError)?.response?.status;
26-
if (responseStatus && responseStatus === 404) {
27-
console.error("could not find resource");
28-
}
29-
},
30-
}),
21+
queryCache: new QueryCache({
22+
onError: (error) => {
23+
console.log({ error });
24+
const responseStatus = (error as AxiosError)?.response?.status;
25+
if (responseStatus && responseStatus === 404) {
26+
console.error('could not find resource');
27+
}
28+
},
29+
}),
3130
});
3231

3332
declare global {
34-
interface Window {
35-
gtag?: (
36-
type: "event" | "config" | "get" | "set" | "consent",
37-
action: "login" | "page_view",
38-
options?: any
39-
) => void;
40-
}
33+
interface Window {
34+
gtag?: (
35+
type: 'event' | 'config' | 'get' | 'set' | 'consent',
36+
action: 'login' | 'page_view',
37+
options?: any
38+
) => void;
39+
}
4140
}
4241

4342
function App() {
44-
const notistackRef = useRef<SnackbarProvider>(null);
45-
useGetToken();
46-
useGoogleAnalytics();
43+
const notistackRef = useRef<SnackbarProvider>(null);
44+
useGetToken();
45+
useGoogleAnalytics();
4746

48-
const location = useLocation();
49-
useEffect(() => {
50-
if (window.gtag) {
51-
window.gtag("event", "page_view", {
52-
page_path: `${location.pathname}${location.search}`,
53-
});
54-
}
55-
}, [location]);
47+
const location = useLocation();
48+
useEffect(() => {
49+
if (window.gtag) {
50+
window.gtag('event', 'page_view', {
51+
page_path: `${location.pathname}${location.search}`,
52+
});
53+
}
54+
}, [location]);
5655

57-
const handleCloseSnackbar =
58-
(key: SnackbarKey) => (_event: React.MouseEvent) => {
59-
if (notistackRef?.current?.closeSnackbar)
60-
notistackRef.current?.closeSnackbar(key);
56+
const handleCloseSnackbar = (key: SnackbarKey) => (_event: React.MouseEvent) => {
57+
if (notistackRef?.current?.closeSnackbar) notistackRef.current?.closeSnackbar(key);
6158
};
6259

63-
return (
64-
<QueryClientProvider client={queryClient}>
65-
<SnackbarProvider
66-
ref={notistackRef}
67-
autoHideDuration={8000}
68-
action={(key) => (
69-
<IconButton onClick={handleCloseSnackbar(key)}>
70-
<Close sx={{ color: "white" }} />
71-
</IconButton>
72-
)}
73-
>
74-
<Downbanner />
75-
<Navbar />
76-
<BaseNavigation />
77-
</SnackbarProvider>
78-
</QueryClientProvider>
79-
);
60+
return (
61+
<QueryClientProvider client={queryClient}>
62+
<SnackbarProvider
63+
ref={notistackRef}
64+
autoHideDuration={8000}
65+
action={(key) => (
66+
<IconButton onClick={handleCloseSnackbar(key)}>
67+
<Close sx={{ color: 'white' }} />
68+
</IconButton>
69+
)}
70+
>
71+
{/* <Banner /> */}
72+
<Navbar />
73+
<BaseNavigation />
74+
</SnackbarProvider>
75+
</QueryClientProvider>
76+
);
8077
}
8178

8279
export default App;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Cancel } from '@mui/icons-material';
2+
import EmojiPeopleIcon from '@mui/icons-material/EmojiPeople';
3+
import { Box, IconButton, Link } from '@mui/material';
4+
import BaseNavigationStyles from 'pages/BaseNavigation/BaseNavigation.styles';
5+
import { useState } from 'react';
6+
7+
const localStorageBannerKey = 'hide-banner-nov-20-2024';
8+
9+
const Banner: React.FC = () => {
10+
const shouldHide = !!localStorage.getItem(localStorageBannerKey);
11+
const [hideBanner, setHideBanner] = useState(shouldHide);
12+
13+
if (hideBanner) return <></>;
14+
15+
return (
16+
<Box
17+
sx={{
18+
backgroundColor: 'primary.dark',
19+
color: 'primary.contrastText',
20+
width: '100%',
21+
paddingY: '0.5rem',
22+
}}
23+
>
24+
<Box
25+
sx={[
26+
BaseNavigationStyles.pagesContainer,
27+
{
28+
marginY: '0',
29+
display: 'flex',
30+
alignItems: 'center',
31+
justifyContent: 'space-between',
32+
},
33+
]}
34+
>
35+
<Box display="flex" alignItems="center">
36+
<EmojiPeopleIcon sx={{ mr: '1rem' }} />
37+
Join us next Wednesday, December 4th 2024 at 10:00 ET for the Neurosynth Compose Virtual Town Hall!{' '}
38+
<Link
39+
color="primary.contrastText"
40+
sx={{ marginLeft: '4px' }}
41+
href="https://tally.so/r/nWePVR"
42+
target="_blank"
43+
>
44+
Click here to register
45+
</Link>
46+
</Box>
47+
<IconButton
48+
onClick={() => {
49+
localStorage.setItem(localStorageBannerKey, 'true');
50+
setHideBanner(true);
51+
}}
52+
sx={{
53+
padding: 0,
54+
':hover': { backgroundColor: 'gray' },
55+
}}
56+
>
57+
<Cancel />
58+
</IconButton>
59+
</Box>
60+
</Box>
61+
);
62+
};
63+
64+
export default Banner;

compose/neurosynth-frontend/src/components/Downbanner.tsx

Lines changed: 0 additions & 65 deletions
This file was deleted.

store/neurostore/resources/base.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from flask import abort, request, current_app # jsonify
99
from flask.views import MethodView
1010

11+
from psycopg2 import errors
12+
1113
import sqlalchemy as sa
1214
import sqlalchemy.sql.expression as sae
1315
from sqlalchemy.orm import (
@@ -21,7 +23,7 @@
2123

2224
from ..core import cache
2325
from ..database import db
24-
from .utils import get_current_user
26+
from .utils import get_current_user, validate_search_query, pubmed_to_tsquery
2527
from ..models import (
2628
StudysetStudy,
2729
AnnotationAnalysis,
@@ -613,7 +615,11 @@ def search(self):
613615
if s is not None and s.isdigit():
614616
q = q.filter_by(pmid=s)
615617
elif s is not None and self._fulltext_fields:
616-
tsquery = sa.func.websearch_to_tsquery("english", s)
618+
try:
619+
validate_search_query(s)
620+
except errors.SyntaxError as e:
621+
abort(400, description=e.args[0])
622+
tsquery = func.to_tsquery('english', pubmed_to_tsquery(s))
617623
q = q.filter(m._ts_vector.op("@@")(tsquery))
618624

619625
# Alternatively (or in addition), search on individual fields.

0 commit comments

Comments
 (0)