Skip to content

Commit

Permalink
Merge branch 'new-postsfn-home' of https://bbpgitlab.epfl.ch/project/…
Browse files Browse the repository at this point in the history
…sbo/core-web-app into new-postsfn-home
  • Loading branch information
loris-maru committed Oct 24, 2024
2 parents fce7d5c + f02983a commit 79d3f7d
Show file tree
Hide file tree
Showing 133 changed files with 2,979 additions and 848 deletions.
6 changes: 5 additions & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,10 @@ deploy-aws-prod:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: pk_test_51P6uAFFE4Bi50cLlatJIc0fUPsP0jQkaCCJ8TTkIYOOLIrLzxX1M9p1kVD11drNqsF9p7yiaumWJ8UHb3ptJJRXB00y3qjYReV
NEXT_PUBLIC_BBS_ML_PRIVATE_BASE_URL: http://internal-sbo-poc-private-alb-1398645643.us-east-1.elb.amazonaws.com:3000/api/literature
NEXT_PUBLIC_CELL_SVC_BASE_URL: https://openbluebrain.com/api/circuit
SENTRY_AUTH_TOKEN: $SENTRY_AUTH_TOKEN
NEXT_PUBLIC_BLUE_NAAS_URL: https://openbluebrain.com/api/bluenaas
SENTRY_AUTH_TOKEN: $SENTRY_AUTH_TOKEN
MAILCHIMP_API_KEY: $MAILCHIMP_API_KEY
MAILCHIMP_AUDIENCE_ID: $MAILCHIMP_AUDIENCE_ID
KANIKO_EXTRA_ARGS: >
--build-arg=NEXT_PUBLIC_BASE_PATH
--build-arg=NEXT_PUBLIC_ENVIRONMENT
Expand All @@ -168,6 +170,8 @@ deploy-aws-prod:
--build-arg=NEXT_PUBLIC_CELL_SVC_BASE_URL
--build-arg=NEXT_PUBLIC_BLUE_NAAS_URL
--build-arg=NODE_OPTIONS
--build-arg=MAILCHIMP_API_KEY
--build-arg=MAILCHIMP_AUDIENCE_ID
only:
- develop

Expand Down
11 changes: 8 additions & 3 deletions __tests__/Literature/GenerativeQAInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ describe('GenerativeQAInput', () => {
await selectSuggestion('Paper');
await selectSuggestion('Journal Paper');

expectOptionsToBeSelected(['paper', 'journal paper'].map(startCase));
expectOptionsNotToBeSelected(['abstract'].map(startCase));
expectOptionsToBeSelected(['paper', 'journal-paper']);
expectOptionsNotToBeSelected(['abstract']);
});

test('shows journal suggestions even if user has not started typing', async () => {
Expand Down Expand Up @@ -379,7 +379,12 @@ describe('GenerativeQAInput', () => {

const expectOptionsToBeSelected = (options: string[]) => {
options.forEach((option) => {
expect(screen.getByText(option, { selector: selectedOptionsSelector })).toBeVisible();
expect(
// Exact match for "option" but ignore case.
screen.getByText(new RegExp(`^${option}$`, 'i'), {
selector: selectedOptionsSelector,
})
).toBeVisible();
});
};

Expand Down
Binary file not shown.
Binary file not shown.
Binary file added public/downloads/intro_to_digital_brains.pdf
Binary file not shown.
Binary file not shown.
Binary file added public/images/about/BBOP_image_origin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/about/hippocampus_background.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions public/images/about/icon_downloadable_document.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added public/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 29 additions & 10 deletions src/app/about/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import { ReactNode } from 'react';
import { Alert } from 'antd';
import { useQueryState } from 'nuqs';

import { Gabarito } from 'next/font/google';

Expand All @@ -19,24 +21,41 @@ const gabarito = Gabarito({
});

export default function AboutPageLayout({ children }: Props) {
const [warning, setWarning] = useQueryState('warning', {
clearOnDefault: true,
defaultValue: '',
});
return (
<div
className={classNames(
'relative flex min-h-screen flex-col gap-20 bg-primary-9 p-8 text-white',
'relative flex min-h-screen flex-col bg-primary-9 text-white',
gabarito.className
)}
>
<nav className="flex w-full justify-between">
<OBPLogo color="text-white" />
<LoginButton
label="Log-in"
link="/login"
type="link"
className="fixed right-12 top-12 z-[200]"
{warning === 'yes' && (
<Alert
className="fixed left-0 top-0 z-[99999] h-28 w-full md:hidden"
banner
closable
message={
<div className="text-justify text-base font-light">
You are currently using a mobile device. Some features are only available on the
desktop version. Please switch to a desktop for a better experience!
</div>
}
onClose={() => setWarning('')}
/>
)}
<nav
className={classNames(
'fixed z-[200] flex w-full items-center justify-between px-6 py-6 backdrop-blur md:px-12 md:py-8',
warning === 'yes' ? 'top-28 md:top-0' : 'top-0'
)}
>
<OBPLogo color="text-white" />
<LoginButton label="Log in" link="/log-in" type="link" />
</nav>

{children}
<div className="relative">{children}</div>
</div>
);
}
111 changes: 111 additions & 0 deletions src/app/api/marketing/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { captureException } from '@sentry/nextjs';
import { env } from '@/env.mjs';

type RequestBody = {
firstName: string;
lastName: string;
email: string;
};

const API_KEY = env.MAILCHIMP_API_KEY;
const AUDIENCE_ID = env.MAILCHIMP_AUDIENCE_ID;
const DATACENTER = API_KEY && API_KEY.split('-')[1];

export const POST = async (req: Request) => {
const { firstName, lastName, email } = (await req.json()) as RequestBody;

if (!email || !firstName || !lastName) {
return new Response('Missing required fields', {
status: 400,
statusText: 'Missing required fields',
});
}

const data = {
members: [
{
email_address: email,
status: 'subscribed',
merge_fields: {
FNAME: firstName,
LNAME: lastName,
},
},
],
update_existing: true,
};

const url = `https://${DATACENTER}.api.mailchimp.com/3.0/lists/${AUDIENCE_ID}`;

const options = {
method: 'POST',
headers: {
Authorization: `apikey ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
};

try {
const response = await fetch(url, options);

if (!response.ok) {
captureException(response.statusText, {
tags: {
section: 'marketing',
},
extra: {
data,
},
});
return new Response('Bad Request!', {
status: 400,
statusText: 'Bad Request',
});
}
const result = await response.json();

if (result.error_count > 0) {
captureException(response.statusText, {
tags: {
section: 'marketing',
},
extra: {
data,
errors: result.errors,
},
});

return new Response(
JSON.stringify({
message: 'Bad Request',
errors: result.errors,
}),
{
status: 400,
statusText: 'Error encountered in email service',
}
);
}

return Response.json({
message: 'user successfully added to bbop audiance',
data: {
created: result.total_created,
},
});
} catch (error) {
captureException(error, {
tags: {
section: 'marketing',
},
extra: {
data,
},
});
return new Response('ServerError: Adding user to bbop audiance failed', {
status: 500,
statusText: 'Internal Server Error',
});
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CloneConfigButton from '@/components/build-section/cell-model-assignment/
import useLiteratureCleanNavigate from '@/components/explore-section/Literature/useLiteratureCleanNavigate';
import EditConfigButton from '@/components/build-section/cell-model-assignment/e-model/EditConfigButton';
import { useSessionAtomValue } from '@/hooks/hooks';
import { nexus } from '@/config';

const baseBannerStyle = 'flex h-full items-center justify-center text-4xl';

Expand All @@ -27,7 +28,13 @@ export default function ConfigurationPage() {
body = (
<div>
<div className="h-[80vh] overflow-auto p-6">
<EModelView />
<EModelView
params={{
id: selectedEModel.id,
projectId: nexus.project,
virtualLabId: nexus.org,
}}
/>
</div>
{selectedEModel.isOptimizationConfig ? <EditConfigButton /> : <CloneConfigButton />}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ export default function EModelDetailPage() {
return (
<Suspense fallback={<CentralLoadingSpinner />}>
<If id="configuration" condition={activeTab === 'configuration'}>
<Configuration />
<Configuration
params={{
id: '',
projectId: '',
virtualLabId: '',
}}
/>
</If>
<If id="analysis" condition={activeTab === 'analysis'}>
<Analysis />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default function ElectrophysiologyPage({ params }: Params) {
<div className="h-full px-10" id="explore-table-container-for-observable">
<ExploreSectionListingView
dataType={DataType.CircuitEModel}
dataScope={ExploreDataScope.SelectedBrainRegion}
dataScope={ExploreDataScope.BuildSelectedBrainRegion}
onCellClick={onCellClick}
selectionType="radio"
virtualLabInfo={{ virtualLabId: params.virtualLabId, projectId: params.projectId }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function BuildMEModelLayout({ children }: GenericLayoutProps) {
return (
<div className="grid grid-cols-[min-content_auto] bg-white">
<ErrorBoundary FallbackComponent={SimpleErrorComponent}>
<BrainRegionsSidebar />
<BrainRegionsSidebar scope="build" />
</ErrorBoundary>

<div className="flex flex-col">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function ReconstrucedMorphologyPage({ params }: Params) {
<div className="h-full" id="explore-table-container-for-observable">
<ExploreSectionListingView
dataType={DataType.ExperimentalNeuronMorphology}
dataScope={ExploreDataScope.SelectedBrainRegion}
dataScope={ExploreDataScope.BuildSelectedBrainRegion}
onCellClick={onCellClick}
selectionType="radio"
renderButton={({ selectedRows }) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@ import MorphologyCard from '@/components/build-section/virtual-lab/me-model/Morp
import EModelCard from '@/components/build-section/virtual-lab/me-model/EModelCard';
// import { usePendingValidationModal } from '@/components/build-section/virtual-lab/me-model/pending-validation-modal-hook';
import { createMEModelAtom, meModelDetailsAtom } from '@/state/virtual-lab/build/me-model-setter';
import { selectedEModelAtom, selectedMModelAtom } from '@/state/virtual-lab/build/me-model';
import {
selectedEModelAtom,
selectedEModelConfigurationAtom,
selectedMModelAtom,
} from '@/state/virtual-lab/build/me-model';
import { virtualLabProjectUsersAtomFamily } from '@/state/virtual-lab/projects';
import { classNames } from '@/util/utils';
import { detailUrlWithinLab } from '@/util/common';
import { BookmarkTabsName } from '@/types/virtual-lab/bookmark';
import { ModelTypeNames } from '@/constants/explore-section/data-types/model-data-types';
import { DisplayMessages } from '@/constants/display-messages';
import { ensureArray } from '@/util/nexus';
import { queryAtom } from '@/state/explore-section/list-view-atoms';
import { ExploreDataScope } from '@/types/explore-section/application';
import { DataType } from '@/constants/explore-section/list-views';

type Params = {
params: {
Expand Down Expand Up @@ -95,6 +102,15 @@ export default function NewMEModelPage({ params: { projectId, virtualLabId } }:
const router = useRouter();
const selectedMModel = useAtomValue(selectedMModelAtom);
const selectedEModel = useAtomValue(selectedEModelAtom);
const selectedEModelConfiguration = useAtomValue(selectedEModelConfigurationAtom);
const refreshMeModels = useSetAtom(
queryAtom({
dataType: DataType.CircuitMEModel,
dataScope: ExploreDataScope.NoScope,
virtualLabInfo: { virtualLabId, projectId },
})
);

const createMEModel = useSetAtom(createMEModelAtom);
const [meModelCreating, setMeModelCreating] = useState<boolean>(false);

Expand Down Expand Up @@ -122,8 +138,10 @@ export default function NewMEModelPage({ params: { projectId, virtualLabId } }:
ModelTypeNames.ME_MODEL
);
notification.success({
duration: 7,
message: 'ME-model created successfully',
});
refreshMeModels();
setMeModelCreating(false);
router.push(redirectionUrl);
})
Expand Down Expand Up @@ -168,7 +186,14 @@ export default function NewMEModelPage({ params: { projectId, virtualLabId } }:
<NewMEModelHeader projectId={projectId} virtualLabId={virtualLabId} />
<div className="flex flex-col gap-4">
<MorphologyCard reselectLink />
<EModelCard reselectLink />
<EModelCard
exemplarMorphology={
selectedEModelConfiguration?.uses.find(
({ '@type': type }) => type === 'NeuronMorphology'
)?.name
}
reselectLink
/>
</div>
</div>
{validateTrigger}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useAtomValue, useSetAtom } from 'jotai';
import { useRouter } from 'next/navigation';
import {
brainRegionsWithRepresentationAtom,
setSelectedBrainRegionAtom,
setSelectedBrainRegionAtomGetter,
} from '@/state/brain-regions';
import { meModelDetailsAtom } from '@/state/virtual-lab/build/me-model-setter';
import { virtualLabProjectUsersAtomFamily } from '@/state/virtual-lab/projects';
Expand All @@ -26,7 +26,7 @@ export default function NewMEModelPage({ params: { projectId, virtualLabId } }:
const contributors = useAtomValue(virtualLabProjectUsersAtomFamily({ projectId, virtualLabId }));
const [isFormValid, setIsFormValid] = useState(false);
const brainRegions = useAtomValue(brainRegionsWithRepresentationAtom);
const setBrainRegion = useSetAtom(setSelectedBrainRegionAtom);
const setBrainRegion = useSetAtom(setSelectedBrainRegionAtomGetter('build'));
const [form] = Form.useForm();
const router = useRouter();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import { useEffect } from 'react';
import { useSetAtom } from 'jotai';

import { ModelTypeNames } from '@/constants/explore-section/data-types/model-data-types';
import MEModelDetailView from '@/components/explore-section/MEModel/DetailView/View';
import { backToListPathAtom } from '@/state/explore-section/detail-view-atoms';
import { generateVlProjectUrl } from '@/util/virtual-lab/urls';
import Nav from '@/components/build-section/virtual-lab/me-model/Nav';

type Params = {
params: {
id: string;
modelType: ModelTypeNames;
projectId: string;
virtualLabId: string;
};
Expand Down
Loading

0 comments on commit 79d3f7d

Please sign in to comment.