Skip to content

Commit

Permalink
Merge branch 'main' into undocumented/env-vars-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
henrycatalinismith committed Dec 29, 2024
2 parents b04f1f8 + bd663a7 commit 0e1a520
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 40 deletions.
4 changes: 2 additions & 2 deletions docs/environment-variables/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ running.
Just about every page component in `src/pages/` uses the `scaffold()` function
to generate its [`getServerSideProps()`](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props) function.

The [`ScaffoldedEnvVars`](../types/ScaffoldedEnvVars.html) type alias is the
place to look first when adding a new runtime environment variable to pages
The [`ClientContextEnvVars`](../types/ScaffoldedEnvVars.html) type alias is also
the place to look first when adding a new runtime environment variable to pages
router code.

## Further Reading
Expand Down
1 change: 0 additions & 1 deletion docs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ export { default as ZUIFuture, type ZUIFutureProps } from 'zui/ZUIFuture';
export { type IFuture } from 'core/caching/futures';
export { removeOffset } from 'utils/dateUtils';
export { type ClientContextEnvVars } from 'core/env/ClientContext';
export { type ScaffoldedEnvVars } from 'utils/next';
7 changes: 7 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ export default async function RootLayout({
<AppRouterCacheProvider>
<ClientContext
envVars={{
FEAT_AREAS: process.env.FEAT_AREAS || null,
INSTANCE_OWNER_HREF: process.env.INSTANCE_OWNER_HREF || null,
INSTANCE_OWNER_NAME: process.env.INSTANCE_OWNER_NAME || null,
MUIX_LICENSE_KEY: process.env.MUIX_LICENSE_KEY || null,
ZETKIN_APP_DOMAIN: process.env.ZETKIN_APP_DOMAIN || null,
ZETKIN_GEN2_ORGANIZE_URL:
process.env.ZETKIN_GEN2_ORGANZE_URL || null,

This comment has been minimized.

Copy link
@xela1601

xela1601 Dec 31, 2024

Collaborator

Hey @henrycatalinismith

while i was looking for the reason, my local devserver is not working anymore, I found out you made a typo here 🙈

process.env.ZETKIN_GEN2_ORGANIZE_URL
ZETKIN_PRIVACY_POLICY_LINK:
process.env.ZETKIN_PRIVACY_POLICY_LINK || null,
}}
headers={headersObject}
lang={lang}
Expand Down
19 changes: 15 additions & 4 deletions src/core/env/ClientContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,28 @@ declare module '@mui/styles/defaultTheme' {
}

/**
* Defines the set of runtime environment variables available to [app
* router](https://nextjs.org/docs/app) code via `ClientContext`.
* Defines the runtime environment variables available to client-side code.
*
* Environment variables specified here must be passed to the `ClientContext`
* provider in `<RootLayout>`.
* These are made available to [app router](https://nextjs.org/docs/app) code
* via `ClientContext` and to [pages router](https://nextjs.org/docs/pages) code
* via `scaffold()`.
*
* We use the same type alias for both routers in order to
* keep the runtime environment variables aligned across this architectural
* boundary. Keeping them aligned in this way is intended to facilitate gradual
* adoption of the app router by minimising friction related to environment
* variables.
*
* @category Environment Variables
*/
export type ClientContextEnvVars = {
FEAT_AREAS: string | null;
INSTANCE_OWNER_HREF: string | null;
INSTANCE_OWNER_NAME: string | null;
MUIX_LICENSE_KEY: string | null;
ZETKIN_APP_DOMAIN: string | null;
ZETKIN_GEN2_ORGANIZE_URL: string | null;
ZETKIN_PRIVACY_POLICY_LINK: string | null;
};

type ClientContextProps = {
Expand Down
2 changes: 2 additions & 0 deletions src/core/env/Environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import IApiClient from 'core/api/client/IApiClient';

type EnvVars = {
FEAT_AREAS?: string | null;
INSTANCE_OWNER_HREF?: string | null;
INSTANCE_OWNER_NAME?: string | null;
MUIX_LICENSE_KEY: string | null;
ZETKIN_APP_DOMAIN: string | null;
ZETKIN_GEN2_ORGANIZE_URL?: string | null;
Expand Down
30 changes: 17 additions & 13 deletions src/features/surveys/components/surveyForm/SurveyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
ZetkinSurveyFormStatus,
ZetkinUser,
} from 'utils/types/zetkin';
import ZUIPublicFooter from 'zui/ZUIPublicFooter';

export type SurveyFormProps = {
survey: ZetkinSurveyExtended;
Expand All @@ -47,19 +48,22 @@ const SurveyForm: FC<SurveyFormProps> = ({ survey, user }) => {
>
<SurveyHeading status={status} survey={survey as ZetkinSurveyExtended} />
{(status === 'editing' || status === 'error') && (
<form action={action as unknown as string}>
<input name="orgId" type="hidden" value={survey.organization.id} />
<input name="surveyId" type="hidden" value={survey.id} />
<Box display="flex" flexDirection="column" gap={4}>
<SurveyElements survey={survey as ZetkinSurveyExtended} />
<SurveySignature
survey={survey as ZetkinSurveyExtended}
user={user}
/>
<SurveyPrivacyPolicy survey={survey as ZetkinSurveyExtended} />
<SurveySubmitButton />
</Box>
</form>
<>
<form action={action as unknown as string}>
<input name="orgId" type="hidden" value={survey.organization.id} />
<input name="surveyId" type="hidden" value={survey.id} />
<Box display="flex" flexDirection="column" gap={4}>
<SurveyElements survey={survey as ZetkinSurveyExtended} />
<SurveySignature
survey={survey as ZetkinSurveyExtended}
user={user}
/>
<SurveyPrivacyPolicy survey={survey as ZetkinSurveyExtended} />
<SurveySubmitButton />
</Box>
</form>
<ZUIPublicFooter />
</>
)}
{status === 'submitted' && <SurveySuccess survey={survey} />}
</Box>
Expand Down
27 changes: 7 additions & 20 deletions src/utils/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ZetkinZ } from './types/sdk';
import { ApiFetch, createApiFetch } from './apiFetch';
import { ZetkinSession, ZetkinUser } from './types/zetkin';
import { hasFeature } from './featureFlags';
import { ClientContextEnvVars } from 'core/env/ClientContext';

//TODO: Create module definition and revert to import.
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -26,25 +27,8 @@ type RegularProps = {
[key: string]: any;
};

/**
* Defines the set of runtime environment variables available to [pages
* router](https://nextjs.org/docs/pages) code via
* [`getServerSideProps`](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props).
*
* Environment variables specified here must be included in the `ScaffoldedProps`
* object returned by `scaffold()`.
*
* @category Environment Variables
*/
export type ScaffoldedEnvVars = {
FEAT_AREAS: string | null;
MUIX_LICENSE_KEY: string | null;
ZETKIN_APP_DOMAIN: string | null;
ZETKIN_GEN2_ORGANIZE_URL: string | null;
};

export type ScaffoldedProps = RegularProps & {
envVars: ScaffoldedEnvVars;
envVars: ClientContextEnvVars;
lang: string;
messages: Record<string, string>;
user: ZetkinUser | null;
Expand Down Expand Up @@ -223,10 +207,13 @@ export const scaffold =
...result.props,
envVars: {
FEAT_AREAS: process.env.FEAT_AREAS || null,
INSTANCE_OWNER_HREF: process.env.INSTANCE_OWNER_HREF || null,
INSTANCE_OWNER_NAME: process.env.INSTANCE_OWNER_NAME || null,
MUIX_LICENSE_KEY: process.env.MUIX_LICENSE_KEY || null,
ZETKIN_APP_DOMAIN: process.env.ZETKIN_APP_DOMAIN || null,
ZETKIN_GEN2_ORGANIZE_URL:
process.env.ZETKIN_GEN2_ORGANIZE_URL || null,
ZETKIN_GEN2_ORGANIZE_URL: process.env.ZETKIN_GEN2_ORGANZE_URL || null,
ZETKIN_PRIVACY_POLICY_LINK:
process.env.ZETKIN_PRIVACY_POLICY_LINK || null,
},
lang,
messages,
Expand Down
120 changes: 120 additions & 0 deletions src/zui/ZUIPublicFooter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { FC, useMemo } from 'react';
import { Box, List, ListItem, Typography } from '@mui/material';
import Image from 'next/image';
import Link from 'next/link';

import messageIds from 'zui/l10n/messageIds';
import { Msg, useMessages } from 'core/i18n';
import theme from 'theme';
import { useEnv } from 'core/hooks';

const ZUIPublicFooter: FC = () => {
const env = useEnv();
const messages = useMessages(messageIds);

const links = useMemo(
() => [
{
href: 'https://zetkin.org/',
text: messages.publicFooter.links.foundation(),
},
{
href:
typeof env.vars.ZETKIN_PRIVACY_POLICY_LINK === 'string'
? env.vars.ZETKIN_PRIVACY_POLICY_LINK
: messages.publicFooter.privacyPolicyLink(),
text: messages.publicFooter.links.privacy(),
},
...(typeof env.vars.INSTANCE_OWNER_NAME === 'string' &&
typeof env.vars.INSTANCE_OWNER_HREF === 'string'
? [
{
href: env.vars.INSTANCE_OWNER_HREF as string,
text: env.vars.INSTANCE_OWNER_NAME as string,
},
]
: []),
],
[messages]
);

return (
<Box component="footer" px={2} py={8}>
<Box alignItems="center" display="flex" flexDirection="column">
<Box flex={1} maxWidth="sm" width="100%">
<Box pb={4}>
<Typography
color={theme.palette.secondary.light}
component="p"
fontSize="1rem"
textAlign="center"
>
<Msg id={messageIds.publicFooter.text} />
</Typography>
</Box>
{typeof env.vars.INSTANCE_OWNER_NAME === 'string' && (
<Box pb={4}>
<Typography
color={theme.palette.secondary.light}
component="p"
fontSize="1rem"
textAlign="center"
>
<Msg
id={messageIds.publicFooter.hostingOrganization}
values={{
name: env.vars.INSTANCE_OWNER_NAME,
}}
/>
</Typography>
</Box>
)}
<Box display="flex" justifyContent="center" py={4}>
<Image
alt=""
className="Footer-logo"
height={64}
src="/logo-zetkin.png"
width={64}
/>
</Box>
<List
sx={{
columnGap: theme.spacing(1),
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
}}
>
{links.map((link) => (
<ListItem
key={link.href}
sx={{
'&:not(:last-child)': {
borderRightColor: theme.palette.divider,
borderRightStyle: 'solid',
borderRightWidth: 1,
paddingRight: theme.spacing(1),
},
padding: 0,
width: 'inherit',
}}
>
<Link
href={link.href}
style={{ color: theme.palette.secondary.light }}
target="_blank"
>
{link.text}
</Link>
</ListItem>
))}
</List>
</Box>
</Box>
</Box>
);
};

export default ZUIPublicFooter;
13 changes: 13 additions & 0 deletions src/zui/l10n/messageIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ export default makeMessages('zui', {
search: m('Type to start searching'),
searching: m('Searching...'),
},
publicFooter: {
hostingOrganization: m<{ name: string }>(
'This instance of Zetkin is hosted and managed by {name}.'
),
links: {
foundation: m('Zetkin Foundation'),
privacy: m('Privacy Policy'),
},
privacyPolicyLink: m('https://zetkin.org/privacy'),
text: m(
'Zetkin is a platform for organizing activism. Zetkin is developed by Zetkin Foundation, with a mission to work for radical change in society in a socialist, feminist, antiracist and sustainable direction.'
),
},
snackbar: {
error: m('Oh dear, something went wrong'),
info: m(''),
Expand Down

0 comments on commit 0e1a520

Please sign in to comment.