Skip to content

Commit

Permalink
Persist language when crossing plans
Browse files Browse the repository at this point in the history
  • Loading branch information
woodwoerk committed Oct 9, 2023
1 parent 3cc732c commit cb14fb9
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 56 deletions.
12 changes: 12 additions & 0 deletions common/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { stripTrailingSlash } from 'common/utils';

describe('stripTrailingSlash', () => {
it('strips trailing slashes', () => {
expect(stripTrailingSlash('/')).toBe('');
expect(stripTrailingSlash('foobar/')).toBe('foobar');
expect(stripTrailingSlash('foobar/lorem')).toBe('foobar/lorem');
expect(stripTrailingSlash('https://www.foobar.com/foobar/lorem/')).toBe(
'https://www.foobar.com/foobar/lorem'
);
});
});
19 changes: 19 additions & 0 deletions common/hooks/localize-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useTranslation } from 'common/i18n';
import { stripTrailingSlash } from 'common/utils';
import { usePlan } from 'context/plan';

/**
* Applies the locale to the end of the link, this can't
* yet be used in cases where the locale should be injected
* to the middle of the path e.g. /<plan>/<locale>/actions/
*/
export const useLocalizedLink = (link: string) => {
const { i18n } = useTranslation();
const plan = usePlan();

if (plan.primaryLanguage === i18n.language) {
return link;
}

return `${stripTrailingSlash(link)}/${i18n.language}`;
};
2 changes: 2 additions & 0 deletions common/utils.js → common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ export function splitLines(text, lineSeparator = '<br>') {

return lines.map((l) => l.join(' ')).join(lineSeparator);
}

export const stripTrailingSlash = (path: string) => path.replace(/\/$/, '');
2 changes: 1 addition & 1 deletion components/plans/PlanChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes, { string } from 'prop-types';
import { transparentize } from 'polished';
import styled from 'styled-components';
import { Theme } from 'common/theme';
import { Theme } from '@kausal/themes/types';

const Tag = styled.div<{ minWidth: string }>`
display: flex;
Expand Down
59 changes: 59 additions & 0 deletions components/plans/PlanLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import styled from 'styled-components';

import { PlanContextType } from 'context/plan';
import { useTheme } from 'common/theme';
import PlanChip from './PlanChip';
import { useLocalizedLink } from 'common/hooks/localize-link';

const PlanDropdownItem = styled.a`
display: block;
padding: 0.25rem 0;
margin: 0 0.5rem 0.5rem;
border: 1px solid ${(props) => props.theme.themeColors.light};
border-radius: 0.5rem;
text-decoration: none !important;
&:last-child {
margin-bottom: 0;
}
&:hover {
background: ${(props) => props.theme.themeColors.light};
border-color: ${(props) => props.theme.themeColors.light};
text-decoration: none;
}
`;

interface Props {
plan: PlanContextType | NonNullable<PlanContextType['allRelatedPlans'][0]>;
}

const PlanLink = ({ plan }: Props) => {
const theme = useTheme();
const localizedPlanUrl = useLocalizedLink(plan.viewUrl ?? '');

if (!plan.viewUrl) {
return null;
}

return (
<PlanDropdownItem
key={plan.identifier}
href={localizedPlanUrl}
type="button"
tabIndex={0}
role="menuitem"
>
<PlanChip
planImage={plan.image?.rendition?.src}
planShortName={plan.shortName}
organization={
theme.settings?.multiplan?.hideLongPlanNames ? undefined : plan.name
}
size="md"
/>
</PlanDropdownItem>
);
};

export default PlanLink;
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import styled from 'styled-components';
import { transparentize } from 'polished';
import { UncontrolledDropdown, DropdownToggle, DropdownMenu } from 'reactstrap';
import { usePlan } from 'context/plan';
import { useTheme } from 'common/theme';
import Icon from 'components/common/Icon';
import PlanChip from './PlanChip';
import { useTranslation } from 'common/i18n';
import PlanLink from './PlanLink';

const PlanSelect = styled.div`
display: flex;
Expand All @@ -31,26 +31,6 @@ const PlanAvatar = styled.img`
const PlanTitle = styled.div`
margin-left: 0.5rem;
font-size: ${(props) => props.theme.fontSizeSm};
font-weight: ${(props) => props.theme[props.weight]};
`;

const PlanDropdownItem = styled.a`
display: block;
padding: 0.25rem 0;
margin: 0 0.5rem 0.5rem;
border: 1px solid ${(props) => props.theme.themeColors.light};
border-radius: 0.5rem;
text-decoration: none !important;
&:last-child {
margin-bottom: 0;
}
&:hover {
background: ${(props) => props.theme.themeColors.light};
border-color: ${(props) => props.theme.themeColors.light};
text-decoration: none;
}
`;

const StyledDropdownToggle = styled(DropdownToggle)`
Expand Down Expand Up @@ -82,52 +62,29 @@ const StyledDropdownToggle = styled(DropdownToggle)`
}
`;

const PlanSelector = (props) => {
const PlanSelector = () => {
const plan = usePlan();
const theme = useTheme();
//console.log(theme)
const { allRelatedPlans } = plan;
if (!allRelatedPlans.length) return null;

const selectablePlans = plan.allRelatedPlans.filter(
(pl) => pl.id !== plan.parent?.id
);
if (!plan.children.length) {
selectablePlans.unshift({
...plan,
viewUrl: '/',
});
}
const selectablePlans = [
{ ...plan, viewUrl: '/' },
...plan.allRelatedPlans.filter((pl) => pl?.id !== plan.parent?.id),
];

return (
<PlanSelect>
<PlanDivider />
<UncontrolledDropdown>
<StyledDropdownToggle data-toggle="dropdown" tag="button">
<PlanAvatar src={plan.image?.small.src} alt="" />
<PlanAvatar src={plan.image?.small?.src} alt="" />
<PlanTitle>{plan.shortName || plan.name}</PlanTitle>
<Icon name="angle-down" />
</StyledDropdownToggle>
<DropdownMenu>
{selectablePlans.map((pl) => (
<PlanDropdownItem
href={pl.viewUrl}
key={pl.identifier}
type="button"
tabIndex={0}
role="menuitem"
>
<PlanChip
planImage={pl.image?.rendition.src}
planShortName={pl.shortName}
organization={
theme.settings?.multiplan?.hideLongPlanNames
? undefined
: pl.name
}
size="md"
/>
</PlanDropdownItem>
))}
{selectablePlans.map(
(plan) => !!plan && <PlanLink key={plan?.id} plan={plan} />
)}
</DropdownMenu>
</UncontrolledDropdown>
</PlanSelect>
Expand Down

0 comments on commit cb14fb9

Please sign in to comment.