Skip to content
This repository has been archived by the owner on Nov 2, 2024. It is now read-only.

Commit

Permalink
🐛 Fix issues regarding nolla page scroll and hidden stab (#1228)
Browse files Browse the repository at this point in the history
* Make "#main-container" scroll on nolla pages

* Only hide stab for non-admin users

* Also allow anyone with nolla:see_stab access to see stab

* Move scroll container to actual content

* Fix how "Staben" is shown on frontend author signatures
  • Loading branch information
Macludde authored Aug 22, 2023
1 parent 82042fc commit edda14a
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,12 @@ export default async function insertApiAccessPolicies(knex: Knex) {
{ api_name: 'core:mail:alias:update', role: '*' },
{ api_name: 'governing_document:read', role: '*' },
{ api_name: 'governing_document:write', role: '_' },
{ api_name: 'nolla:news', role: 'dsek.infu.dwww' },
{ api_name: 'nolla:news', role: 'dsek.noll' },
{ api_name: 'nolla:events', role: 'dsek.noll' },
{ api_name: 'nolla:events', role: 'dsek.infu.dwww' },
{ api_name: 'nolla:admin', role: 'dsek.infu.dwww' },
{ api_name: 'nolla:admin', role: 'dsek.noll.stab' },
{ api_name: 'nolla:see_stab', role: 'dsek.noll.stab' },
]);
}
9 changes: 6 additions & 3 deletions backend/services/core/src/datasources/Mandate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource {
const res = (await this.knex<sql.Mandate>('mandates').select('*').where({ id }))[0];

if (!res) { return undefined; }
if (await this.isStabHidden() && STAB_IDS.includes(res.position_id)) {
// Returns undefined for stab mandates during the nollning.
if (await this.isStabHiddenForUser(ctx, res.member_id) && STAB_IDS.includes(res.position_id)) {
return undefined;
}
return convertMandate(res);
Expand Down Expand Up @@ -65,7 +66,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource {
}
}
}
if (await this.isStabHidden()) {
// Removes all mandates that are stab mandates, during the nollning.
if (await this.isStabHiddenForUser(ctx)) {
filtered = filtered.whereNotIn('position_id', STAB_IDS); // hide ALL stab mandates (even old ones)
// Remove active stab members from the list, even their other/old mandates
filtered = filtered
Expand Down Expand Up @@ -109,7 +111,8 @@ export default class MandateAPI extends dbUtils.KnexDataSource {
query = query.andWhereRaw('CURRENT_DATE BETWEEN start_date AND end_date');
}
const res = await query;
if (await this.isStabHidden()) {
// Remove stab info
if (await this.isStabHiddenForUser(ctx, memberId)) {
// if user has an active stab mandate, hide all other mandates
if (res.some((m) => m.end_date > new Date() && STAB_IDS.includes(m.position_id))) {
return [];
Expand Down
4 changes: 2 additions & 2 deletions backend/services/core/src/datasources/Position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class PositionAPI extends dbUtils.KnexDataSource {
return undefined;
}

if (await this.isStabHidden() && STAB_IDS.includes(position.id)) {
if (await this.isStabHiddenForUser(ctx) && STAB_IDS.includes(position.id)) {
return undefined;
}
if (!position.active) {
Expand Down Expand Up @@ -62,7 +62,7 @@ export default class PositionAPI extends dbUtils.KnexDataSource {
...filter,
});
}
if (await this.isStabHidden()) {
if (await this.isStabHiddenForUser(ctx)) {
STAB_IDS.forEach((id) => {
query = query.whereNot({ id });
});
Expand Down
25 changes: 24 additions & 1 deletion backend/services/core/src/shared/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { slugify } from './utils';

attachPaginate();

const ONE_DAY_IN_SECONDS = 1000 * 60 * 60 * 24;

type Keycloak = {
keycloak_id: string,
member_id: UUID,
Expand Down Expand Up @@ -242,6 +244,9 @@ export class KnexDataSource extends DataSource<UserContext> {
// used to cache the stab hidden setting
private stabHidden = false;

/**
* last time stab hidden setting was checked in milliseconds
*/
private lastStabHiddenCheck = 0;

private async checkStabHiddenSetting() {
Expand Down Expand Up @@ -271,11 +276,29 @@ export class KnexDataSource extends DataSource<UserContext> {
async isStabHidden() {
// check max once per day if stab is hidden
const now = Date.now();
if (now - this.lastStabHiddenCheck > 1000 * 60 * 60 * 24) {
if (now - this.lastStabHiddenCheck > ONE_DAY_IN_SECONDS * 1000) {
await this.checkStabHiddenSetting();
}
return this.stabHidden;
}

/**
* Checks admin settings if stab is currently hidden.
* Admin users can see stab even if it is hidden.
* User's can always see themselves.
* @param ctx Context for logged in user
* @param memberId Relevant memberId of the member which might be hidden, if applicable
* @returns true if should be hidden
*/
async isStabHiddenForUser(ctx: UserContext, memberId?: string) {
if (!(await this.isStabHidden())) {
return false;
}
if (await this.hasAccess(['nolla:admin', 'nolla:see_stab', 'admin:settings:update', 'core:admin'], ctx, memberId)) {
return false;
}
return true;
}
}

export default knex(knexConfig);
11 changes: 3 additions & 8 deletions frontend/components/News/articleSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,9 @@ export default function ArticleSet({
},
});
const { t } = useTranslation('news');
const [articles, setArticles] = useState(data?.news?.articles);
useEffect(() => {
if (data?.news?.articles) {
setArticles(data.news.articles);
}
}, [data]);
const articles = data?.news?.articles;

if (!articles || loading) {
if (loading) {
return (
<>
<ArticleSkeleton />
Expand All @@ -57,7 +52,7 @@ export default function ArticleSet({

return (
<>

Check failure on line 54 in frontend/components/News/articleSet.tsx

View workflow job for this annotation

GitHub Actions / linter_check

Fragments should contain more than one child - otherwise, there’s no need for a Fragment at all
{articles.map((article) =>
{articles?.map((article) =>
(article ? (
<Article
key={article.id}
Expand Down
14 changes: 1 addition & 13 deletions frontend/components/Nolla/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import selectTranslation from '~/functions/selectTranslation';
import {
ArticleQuery,
ArticleRequestStatus,
Author,
} from '~/generated/graphql';
import { hasAccess, useApiAccess } from '~/providers/ApiAccessProvider';
import { useUser } from '~/providers/UserProvider';
Expand All @@ -35,17 +34,6 @@ type ArticleProps = {
article: ArticleQuery['article'];
};

const getNollaNewsAuthor = (i18n: any, author: Partial<Author>) => {
if (author.__typename === 'Member') {
return getSignature(author);
}
if (author.position?.name === 'Stabsmedlem') {
return 'Staben';
}

return getSignature(author);
};

export default function Article({ article }: ArticleProps) {
const classes = articleStyles();
const { t, i18n } = useTranslation('common');
Expand Down Expand Up @@ -79,7 +67,7 @@ export default function Article({ article }: ArticleProps) {
}}
/>
<Stack spacing={0.5} alignItems="flex-start">
{getNollaNewsAuthor(i18n, article.author)}
{getSignature(article.author)}
<Typography>{timeAgo(date)}</Typography>
</Stack>
</Stack>
Expand Down
125 changes: 68 additions & 57 deletions frontend/components/Nolla/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ function NollaLayout({

return (
<Box
id="main-container"
component="span"
className={styles.nolla}
sx={{
display: 'flex',
Expand All @@ -150,12 +148,13 @@ function NollaLayout({
background: 'hsl(317, 82%, 56%)',
color: 'white',
},
minHeight: '100vh',
height: '100vh',
}}
>
<AppBar
position="relative"
sx={{
position: 'sticky',
flex: 0,
background: 'linear-gradient(90deg, #AA28A7 0%, #DC2A8A 100%)',
}}
>
Expand Down Expand Up @@ -213,62 +212,74 @@ function NollaLayout({
{drawer}
</Drawer>
</Box>
<Box
id="main-container"
component="main"
sx={{
flex: 1,
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
}}
>

<Container maxWidth={maxWidth} sx={{ my: 5, flexGrow: 1 }}>
{children}
</Container>
<Container maxWidth={maxWidth} sx={{ my: 5, flexGrow: 1 }}>
{children}
</Container>

<Paper component="footer" sx={{ py: 3, borderRadius: 0 }}>
<Container
maxWidth="md"
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
rowGap: 1,
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Logo src="/images/nolla/d_logo_new.png" alt="D-sek logo" />
<Typography variant="body2" sx={{ textAlign: 'center' }}>
{translate('footer')}
</Typography>
<Paper component="footer" sx={{ py: 3, borderRadius: 0 }}>
<Container
maxWidth="md"
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
rowGap: 1,
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Logo src="/images/nolla/d_logo_new.png" alt="D-sek logo" />
<Typography variant="body2" sx={{ textAlign: 'center' }}>
{translate('footer')}
</Typography>

<Stack spacing={1} direction="row">
<Link href="https://instagram.com/dseklth/" newTab>
<IconButton>
<InstagramIcon />
</IconButton>
</Link>
<Link href="https://facebook.com/Dsektionen/" newTab>
<IconButton>
<FacebookIcon />
</IconButton>
</Link>
<Link
href="https://youtube.com/channel/UCqBtN7xlh4_VvywKaRiGfkw/"
newTab
>
<IconButton>
<YouTubeIcon />
</IconButton>
</Link>
<Link href="https://github.com/Dsek-LTH/" newTab>
<IconButton>
<GitHubIcon />
</IconButton>
</Link>
<Link
href="https://linkedin.com/company/datatekniksektionen-vid-tlth/"
newTab
>
<IconButton>
<LinkedInIcon />
</IconButton>
</Link>
</Stack>
</Container>
</Paper>
<Stack spacing={1} direction="row">
<Link href="https://instagram.com/dseklth/" newTab>
<IconButton>
<InstagramIcon />
</IconButton>
</Link>
<Link href="https://facebook.com/Dsektionen/" newTab>
<IconButton>
<FacebookIcon />
</IconButton>
</Link>
<Link
href="https://youtube.com/channel/UCqBtN7xlh4_VvywKaRiGfkw/"
newTab
>
<IconButton>
<YouTubeIcon />
</IconButton>
</Link>
<Link href="https://github.com/Dsek-LTH/" newTab>
<IconButton>
<GitHubIcon />
</IconButton>
</Link>
<Link
href="https://linkedin.com/company/datatekniksektionen-vid-tlth/"
newTab
>
<IconButton>
<LinkedInIcon />
</IconButton>
</Link>
</Stack>
</Container>
</Paper>

</Box>
</Box>
);
}
Expand Down
4 changes: 4 additions & 0 deletions frontend/functions/authorFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const getSignature = (author: Partial<Author>): string => {
return getFullName(author as Member);
}
const mandate = (author as Mandate);
if (mandate.position?.id?.startsWith('dsek.noll.stab')) {
return 'Staben';
}

return `${getFullName(mandate.member)}, ${mandate.position.name}`;
};

Expand Down
9 changes: 0 additions & 9 deletions frontend/pages/members/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,6 @@ export default function MemberPage() {
if (!member) {
return <>{t('member:memberError')}</>;
}
if (
member.activeMandates.some(
(m) => m.position.id === 'dsek.noll.stab.mdlm',
)
&& member.id !== user?.id
&& !hasAccess('nolla:admin')
) {
return <>{t('member:memberError')}</>;
}
return (
<NoTitleLayout>
<Paper className={classes.innerContainer}>
Expand Down

0 comments on commit edda14a

Please sign in to comment.