Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ type Report implements CommentableInterface {
id: ID!
status: ReportStatus!
summary: String
traineeId: ID!
week: Int!
year: Int!
reportAccepted: String
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ export type GqlReport = GqlCommentableInterface & {
reportAccepted?: Maybe<Scalars['String']['output']>;
status: GqlReportStatus;
summary?: Maybe<Scalars['String']['output']>;
traineeId: Scalars['ID']['output'];
week: Scalars['Int']['output'];
year: Scalars['Int']['output'];
};
Expand Down Expand Up @@ -979,6 +980,7 @@ export type GqlReportResolvers<ContextType = Context, ParentType extends GqlReso
reportAccepted?: Resolver<Maybe<GqlResolversTypes['String']>, ParentType, ContextType>;
status?: Resolver<GqlResolversTypes['ReportStatus'], ParentType, ContextType>;
summary?: Resolver<Maybe<GqlResolversTypes['String']>, ParentType, ContextType>;
traineeId?: Resolver<GqlResolversTypes['ID'], ParentType, ContextType>;
week?: Resolver<GqlResolversTypes['Int'], ParentType, ContextType>;
year?: Resolver<GqlResolversTypes['Int'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
Expand Down
32 changes: 32 additions & 0 deletions packages/backend/seeds/users.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,38 @@
"type": "Trainee",
"trainerId": "456"
},
{
"id": "1234",
"companyId": "expGermany",
"course": "Trainee Course",
"createdAt": "2019-08-01T11:25:18.000Z",
"email": "trainee@exampleCompany.com",
"firstName": "Trainee",
"lastName": "Traineeson",
"language": "de",
"startDate": "2022-08-01T22:00:00.000Z",
"endDate": "2027-07-31T22:00:00.000Z",
"theme": "light",
"token": "123",
"type": "Trainee",
"trainerId": "456"
},
{
"id": "12345",
"companyId": "expGermany",
"course": "Trainee Course",
"createdAt": "2019-08-01T11:25:18.000Z",
"email": "trainee@exampleCompany.com",
"firstName": "Trainee",
"lastName": "Traineeson",
"language": "de",
"startDate": "2022-08-01T22:00:00.000Z",
"endDate": "2027-07-31T22:00:00.000Z",
"theme": "light",
"token": "123",
"type": "Trainee",
"trainerId": "456"
},
{
"id": "456",
"companyId": "expGermany",
Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const permissions = shield<unknown, Context>(
alexaLinkingUrl: authenticated,

// Trainee queries
reports: and(authenticated, trainee),
reports: and(authenticated, or(trainee, trainer)),
suggestions: and(authenticated, trainee),
reportForYearAndWeek: and(authenticated, trainee),
print: and(authenticated, trainee),
Expand All @@ -53,9 +53,9 @@ export const permissions = shield<unknown, Context>(

// Trainer and Admin Queries
trainees: and(authenticated, or(trainer, admin)),
getUser: and(authenticated, or(admin, trainer)),

// Admin Queris
getUser: and(authenticated, admin),
trainers: and(authenticated, admin),
admins: and(authenticated, admin),
},
Expand Down
22 changes: 16 additions & 6 deletions packages/backend/src/resolvers/report.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import { AuthenticatedContext, GqlResolvers, Report, Trainee, TraineeContext } f

import { isTrainee, isTrainer } from '../permissions'
import { reportById, reportByYearAndWeek, saveReport, updateReport } from '../repositories/report.repo'
import { traineeByReportId } from '../repositories/trainee.repo'
import { traineeByReportId, traineesByTrainerId } from '../repositories/trainee.repo'
import { sendNotificationMail } from '../services/email.service'
import {
isReportStatus,
reportDate,
reportsWithinApprenticeship,
reportsForTrainer,
validateStatusUpdate,
} from '../services/report.service'
import { endOfToolUsage, generateReports, startOfToolUsage } from '../services/trainee.service'
Expand Down Expand Up @@ -50,14 +51,26 @@ export const reportTraineeResolver: GqlResolvers<TraineeContext> = {
return `/report/${getISOWeekYear(prevWeek)}/${getISOWeek(prevWeek)}`
},
},
}

export const reportResolver: GqlResolvers<AuthenticatedContext> = {
Query: {
reports: async (_parent, { statuses }, { currentUser }) => {
// Generate reports if executed local
if (IS_OFFLINE) {
if (IS_OFFLINE && isTrainee(currentUser)) {
await generateReports(currentUser)
}

return reportsWithinApprenticeship(currentUser, statuses)
if (isTrainee(currentUser)) {
return reportsWithinApprenticeship(currentUser, statuses)
}

if (isTrainer(currentUser)) {
const trainees = await traineesByTrainerId(currentUser.id)
return reportsForTrainer(trainees, statuses)
}

return []
},
reportForYearAndWeek: async (_parent, { week, year }, { currentUser }) => {
let report = await reportByYearAndWeek(year, week, currentUser.id)
Expand Down Expand Up @@ -92,9 +105,6 @@ export const reportTraineeResolver: GqlResolvers<TraineeContext> = {
return report
},
},
}

export const reportResolver: GqlResolvers<AuthenticatedContext> = {
Mutation: {
updateReport: async (_parent, { id, department, status: newStatus, summary }, { currentUser }) => {
let report: Report | undefined
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/services/report.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ export const reportsWithinApprenticeship = async (
)
}

export const reportsForTrainer = async (trainees: Trainee[], statuses?: GqlReportStatus[]): Promise<Report[]> => {
const allReports = await Promise.all(trainees.map((trainee) => reportsWithinApprenticeship(trainee, statuses)))

return sortReportsByDate(allReports.flat())
}

const DANGEROUSLY_reportsForTraineeAndStatuses = async (
traineeId: string,
statuses: GqlReportStatus[]
Expand Down
9 changes: 9 additions & 0 deletions packages/components/src/trainee-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ export const StyledHeader = styled(NavLink)`
flex-grow: 1;
`

export const StyledHeaderSpan = styled.span`
display: flex;
align-items: center;
text-decoration: none;
flex-grow: 1;
padding: 16px;
cursor: pointer;
`

export const StyledName = styled.span`
font-size: ${FontSizes.copy};
font-weight: bold;
Expand Down
3 changes: 3 additions & 0 deletions packages/frontend/src/components/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ const Navigation: React.FC = () => {
<StyledNavItem to="/trainees" onClick={toggleMenu} isMobile={isMobile}>
{strings.navigation.trainees}
</StyledNavItem>
<StyledNavItem to="/archive" onClick={toggleMenu} isMobile={isMobile}>
{strings.navigation.archive}
</StyledNavItem>
<StyledNavItem to="/settings" onClick={toggleMenu} isMobile={isMobile}>
{strings.navigation.settings}
</StyledNavItem>
Expand Down
33 changes: 33 additions & 0 deletions packages/frontend/src/components/trainee-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react'
import { StyledName, StyledWrapper, Flex, StyledHeaderSpan } from '@lara/components'

import { Trainee } from '../graphql'
import Avatar from './avatar'

interface TraineeSelectorProps {
trainee: Pick<Trainee, 'id' | 'firstName' | 'lastName'>
onVariableChange: (traineeId: string) => void
}

const TraineeSelector: React.FunctionComponent<TraineeSelectorProps> = (props) => {
const { trainee, onVariableChange } = props

const handleClick = () => {
onVariableChange(trainee.id)
}

return (
<StyledWrapper onClick={handleClick}>
<Flex justifyContent="center" alignItems="space-between">
<StyledHeaderSpan>
<Avatar size={44} id={trainee.id} />
<StyledName>
{trainee.firstName} {trainee.lastName}
</StyledName>
</StyledHeaderSpan>
</Flex>
</StyledWrapper>
)
}

export default TraineeSelector
4 changes: 3 additions & 1 deletion packages/frontend/src/graphql/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ export type Report = CommentableInterface & {
reportAccepted?: Maybe<Scalars['String']['output']>;
status: ReportStatus;
summary?: Maybe<Scalars['String']['output']>;
traineeId: Scalars['ID']['output'];
week: Scalars['Int']['output'];
year: Scalars['Int']['output'];
};
Expand Down Expand Up @@ -965,7 +966,7 @@ export type AlexaLinkingUrlQuery = { __typename?: 'Query', alexaLinkingUrl?: str
export type ArchivePageDataQueryVariables = Exact<{ [key: string]: never; }>;


export type ArchivePageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, summary?: string | undefined, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time: number, text: string }> }> } | undefined> };
export type ArchivePageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, summary?: string | undefined, traineeId: string, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time: number, text: string }> }> } | undefined> };

export type AvatarSettingsDataQueryVariables = Exact<{ [key: string]: never; }>;

Expand Down Expand Up @@ -1952,6 +1953,7 @@ export const ArchivePageDataDocument = gql`
status
department
summary
traineeId
days {
status
entries {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ query ArchivePageData {
status
department
summary
traineeId
days {
status
entries {
Expand Down
5 changes: 4 additions & 1 deletion packages/frontend/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,14 @@ const germanTranslation: Translation = {
},
initial: {
title: 'Hier gibt es noch nichts',
caption: 'Deine Berichtshefte erscheinen hier sobald sie akzeptiert wurden und stehen dann zum Export bereit.',
caption_trainee:
'Deine Berichtshefte erscheinen hier sobald sie akzeptiert wurden und stehen dann zum Export bereit.',
caption_trainer: 'Du hast keine Azubis, die Archive der Azubis werden hier erscheinen sobald sie da sind.',
},
},
exportTitle: 'Export gestartet',
export: 'Du erhältst in Kürze eine E-mail mit den exportierten Berichten.',
back: 'Zurück',
},
report: {
title: 'Bericht für',
Expand Down
4 changes: 3 additions & 1 deletion packages/frontend/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ const englishTranslation: Translation = {
},
initial: {
title: "There's nothing here yet.",
caption: 'Your reports appear here as soon as they have been accepted and are then ready for export.',
caption_trainee: 'Your reports appear here as soon as they have been accepted and are then ready for export.',
caption_trainer: 'You have no Trainees, their archives will appear here when available.',
},
},
exportTitle: 'export started',
export: 'Shortly you will receive an email with your exported reports.',
back: 'Back',
},
report: {
title: 'Report for',
Expand Down
4 changes: 3 additions & 1 deletion packages/frontend/src/locales/translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ export default interface Translation {
}
initial: {
title: string
caption: string
caption_trainee: string
caption_trainer: string
}
}
exportTitle: string
export: string
back: string
}
report: {
title: string
Expand Down
Loading