fix: rename and fix imports
This commit is contained in:
parent
d90cfd2a3b
commit
18ed8620af
|
@ -31,5 +31,8 @@
|
||||||
"extends": ["plugin:@nrwl/nx/javascript"],
|
"extends": ["plugin:@nrwl/nx/javascript"],
|
||||||
"rules": {}
|
"rules": {}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"globals": {
|
||||||
|
"__DEV__": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as eva from '@eva-design/eva'
|
import * as eva from '@eva-design/eva'
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
import CookieManager from '@react-native-community/cookies'
|
import CookieManager from '@react-native-community/cookies'
|
||||||
import { ApiProvider } from '@skolplattformen/api-hooks'
|
import init from '@skolplattformen/api-skolplattformen'
|
||||||
import init from '@skolplattformen/embedded-api'
|
import { ApiProvider } from '@skolplattformen/hooks'
|
||||||
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components'
|
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components'
|
||||||
import { EvaIconsPack } from '@ui-kitten/eva-icons'
|
import { EvaIconsPack } from '@ui-kitten/eva-icons'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
import { useRoute } from '@react-navigation/native'
|
import { useRoute } from '@react-navigation/native'
|
||||||
|
import { useUser } from '@skolplattformen/hooks'
|
||||||
import { fireEvent, waitFor } from '@testing-library/react-native'
|
import { fireEvent, waitFor } from '@testing-library/react-native'
|
||||||
import Mockdate from 'mockdate'
|
import Mockdate from 'mockdate'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useSMS } from '../../utils/SMS'
|
import { useSMS } from '../../utils/SMS'
|
||||||
import { render } from '../../utils/testHelpers'
|
import { render } from '../../utils/testHelpers'
|
||||||
import Absence from '../absence.component'
|
import Absence from '../absence.component'
|
||||||
import { useUser } from '@skolplattformen/api-hooks'
|
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
||||||
|
|
||||||
jest.mock('@react-navigation/native')
|
jest.mock('@react-navigation/native')
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
jest.mock('../../utils/SMS')
|
jest.mock('../../utils/SMS')
|
||||||
|
|
||||||
let sendSMS
|
let sendSMS
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import { render } from '../../utils/testHelpers'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { render } from '../../utils/testHelpers'
|
||||||
import { Auth } from '../auth.component'
|
import { Auth } from '../auth.component'
|
||||||
|
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
jest.mock('react-native-localize')
|
jest.mock('react-native-localize')
|
||||||
|
|
||||||
const setup = () => {
|
const setup = () => {
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
|
import { useNavigation } from '@react-navigation/core'
|
||||||
import {
|
import {
|
||||||
useApi,
|
useApi,
|
||||||
useChildList,
|
|
||||||
useCalendar,
|
useCalendar,
|
||||||
|
useChildList,
|
||||||
|
useClassmates,
|
||||||
|
useMenu,
|
||||||
useNews,
|
useNews,
|
||||||
useNotifications,
|
useNotifications,
|
||||||
useSchedule,
|
useSchedule,
|
||||||
useMenu,
|
|
||||||
useTimetable,
|
useTimetable,
|
||||||
useClassmates,
|
} from '@skolplattformen/hooks'
|
||||||
} from '@skolplattformen/api-hooks'
|
|
||||||
import { render } from '../../utils/testHelpers'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Children } from '../children.component'
|
|
||||||
import { useNavigation } from '@react-navigation/core'
|
|
||||||
import * as RNLocalize from 'react-native-localize'
|
import * as RNLocalize from 'react-native-localize'
|
||||||
|
import { render } from '../../utils/testHelpers'
|
||||||
import { translate } from '../../utils/translation'
|
import { translate } from '../../utils/translation'
|
||||||
|
import { Children } from '../children.component'
|
||||||
|
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
jest.mock('@react-navigation/core')
|
jest.mock('@react-navigation/core')
|
||||||
jest.mock('react-native-localize')
|
jest.mock('react-native-localize')
|
||||||
const setup = () => {
|
const setup = () => {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { useClassmates } from '@skolplattformen/api-hooks'
|
import { useClassmates } from '@skolplattformen/hooks'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '../../utils/testHelpers'
|
import { render } from '../../utils/testHelpers'
|
||||||
import { ChildProvider } from '../childContext.component'
|
import { ChildProvider } from '../childContext.component'
|
||||||
import { Classmates } from '../classmates.component'
|
import { Classmates } from '../classmates.component'
|
||||||
|
|
||||||
jest.mock('@react-navigation/native')
|
jest.mock('@react-navigation/native')
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
|
|
||||||
const defaultClassmates = [
|
const defaultClassmates = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
import { useMenu } from '@skolplattformen/hooks'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '../../utils/testHelpers'
|
import { render } from '../../utils/testHelpers'
|
||||||
import { Menu } from '../menu.component'
|
|
||||||
import { useMenu } from '@skolplattformen/api-hooks'
|
|
||||||
import { translate } from '../../utils/translation'
|
import { translate } from '../../utils/translation'
|
||||||
|
import { Menu } from '../menu.component'
|
||||||
|
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
|
|
||||||
const defaultItemList = [
|
const defaultItemList = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useApi, useNewsDetails } from '@skolplattformen/api-hooks'
|
import { useApi, useNewsDetails } from '@skolplattformen/hooks'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '../../utils/testHelpers'
|
import { render } from '../../utils/testHelpers'
|
||||||
import { NewsItem } from '../newsItem.component'
|
import { NewsItem } from '../newsItem.component'
|
||||||
|
|
||||||
jest.mock('@skolplattformen/api-hooks')
|
jest.mock('@skolplattformen/hooks')
|
||||||
|
|
||||||
const defaultNewsItem = {
|
const defaultNewsItem = {
|
||||||
author: 'Köket',
|
author: 'Köket',
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
import { useNavigation } from '@react-navigation/native'
|
||||||
|
import { fireEvent } from '@testing-library/react-native'
|
||||||
|
import MockDate from 'mockdate'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '../../utils/testHelpers'
|
import { render } from '../../utils/testHelpers'
|
||||||
import { NewsListItem } from '../newsListItem.component'
|
|
||||||
import MockDate from 'mockdate'
|
|
||||||
import { fireEvent } from '@testing-library/react-native'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
|
||||||
import { ChildProvider } from '../childContext.component'
|
import { ChildProvider } from '../childContext.component'
|
||||||
|
import { NewsListItem } from '../newsListItem.component'
|
||||||
|
|
||||||
jest.mock('@react-navigation/native')
|
jest.mock('@react-navigation/native')
|
||||||
jest.mock('@skolplattformen/api-hooks', () => ({
|
jest.mock('@skolplattformen/hooks', () => ({
|
||||||
useApi: jest.fn().mockReturnValue({ api: { getSessionCookie: jest.fn() } }),
|
useApi: jest.fn().mockReturnValue({ api: { getSessionCookie: jest.fn() } }),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { RouteProp, useRoute } from '@react-navigation/native'
|
import { RouteProp, useRoute } from '@react-navigation/native'
|
||||||
|
import { useUser } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
CheckBox,
|
CheckBox,
|
||||||
|
@ -16,6 +17,7 @@ import DateTimePickerModal from 'react-native-modal-datetime-picker'
|
||||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { defaultStackStyling } from '../design/navigationThemes'
|
import { defaultStackStyling } from '../design/navigationThemes'
|
||||||
|
import usePersonalStorage from '../hooks/usePersonalStorage'
|
||||||
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||||
import { studentName } from '../utils/peopleHelpers'
|
import { studentName } from '../utils/peopleHelpers'
|
||||||
import { useSMS } from '../utils/SMS'
|
import { useSMS } from '../utils/SMS'
|
||||||
|
@ -23,8 +25,6 @@ import { translate } from '../utils/translation'
|
||||||
import { AlertIcon } from './icon.component'
|
import { AlertIcon } from './icon.component'
|
||||||
import { RootStackParamList } from './navigation.component'
|
import { RootStackParamList } from './navigation.component'
|
||||||
import { NavigationTitle } from './navigationTitle.component'
|
import { NavigationTitle } from './navigationTitle.component'
|
||||||
import { useUser } from '@skolplattformen/api-hooks'
|
|
||||||
import usePersonalStorage from '../hooks/usePersonalStorage'
|
|
||||||
|
|
||||||
type AbsenceRouteProps = RouteProp<RootStackParamList, 'Absence'>
|
type AbsenceRouteProps = RouteProp<RootStackParamList, 'Absence'>
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { useCalendar } from '@skolplattformen/api-hooks'
|
import { CalendarItem } from '@skolplattformen/api-skolplattformen'
|
||||||
import { CalendarItem } from '@skolplattformen/embedded-api'
|
import { useCalendar } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
Text,
|
|
||||||
StyleService,
|
StyleService,
|
||||||
|
Text,
|
||||||
useStyleSheet,
|
useStyleSheet,
|
||||||
} from '@ui-kitten/components'
|
} from '@ui-kitten/components'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Child } from '@skolplattformen/embedded-api'
|
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||||
import React, { createContext, useContext } from 'react'
|
import React, { createContext, useContext } from 'react'
|
||||||
|
|
||||||
interface ChildProviderProps {
|
interface ChildProviderProps {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
|
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||||
import {
|
import {
|
||||||
useCalendar,
|
useCalendar,
|
||||||
useClassmates,
|
useClassmates,
|
||||||
|
@ -8,8 +9,7 @@ import {
|
||||||
useNews,
|
useNews,
|
||||||
useNotifications,
|
useNotifications,
|
||||||
useSchedule,
|
useSchedule,
|
||||||
} from '@skolplattformen/api-hooks'
|
} from '@skolplattformen/hooks'
|
||||||
import { Child } from '@skolplattformen/embedded-api'
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
StyleService,
|
StyleService,
|
||||||
|
@ -19,9 +19,9 @@ import {
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { TouchableOpacity, useColorScheme, View } from 'react-native'
|
import { TouchableOpacity, useColorScheme, View } from 'react-native'
|
||||||
|
import { useTranslation } from '../hooks/useTranslation'
|
||||||
import { Colors, Layout, Sizing } from '../styles'
|
import { Colors, Layout, Sizing } from '../styles'
|
||||||
import { studentName } from '../utils/peopleHelpers'
|
import { studentName } from '../utils/peopleHelpers'
|
||||||
import { useTranslation } from '../hooks/useTranslation'
|
|
||||||
import { DaySummary } from './daySummary.component'
|
import { DaySummary } from './daySummary.component'
|
||||||
import { AlertIcon, RightArrowIcon } from './icon.component'
|
import { AlertIcon, RightArrowIcon } from './icon.component'
|
||||||
import { RootStackParamList } from './navigation.component'
|
import { RootStackParamList } from './navigation.component'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useNavigation } from '@react-navigation/core'
|
import { useNavigation } from '@react-navigation/core'
|
||||||
import { useApi, useChildList } from '@skolplattformen/api-hooks'
|
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||||
import { Child } from '@skolplattformen/embedded-api'
|
import { useApi, useChildList } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
List,
|
List,
|
||||||
|
@ -44,7 +44,7 @@ export const Children = () => {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
|
|
||||||
const { api } = useApi()
|
const { api } = useApi()
|
||||||
let { data: childList, status, reload } = useChildList()
|
const { data: childList, status, reload } = useChildList()
|
||||||
const reloadChildren = () => {
|
const reloadChildren = () => {
|
||||||
reload()
|
reload()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import React from 'react'
|
import { Classmate } from '@skolplattformen/api-skolplattformen'
|
||||||
import { StyleSheet, ListRenderItemInfo } from 'react-native'
|
import { useClassmates } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
Icon,
|
Icon,
|
||||||
IconProps,
|
IconProps,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
Text,
|
Text,
|
||||||
} from '@ui-kitten/components'
|
} from '@ui-kitten/components'
|
||||||
|
import React from 'react'
|
||||||
|
import { ListRenderItemInfo, StyleSheet } from 'react-native'
|
||||||
import { fullName, guardians, sortByFirstName } from '../utils/peopleHelpers'
|
import { fullName, guardians, sortByFirstName } from '../utils/peopleHelpers'
|
||||||
import { useChild } from './childContext.component'
|
|
||||||
import { useClassmates } from '@skolplattformen/api-hooks'
|
|
||||||
import { ContactMenu } from './contactMenu.component'
|
|
||||||
import { Classmate } from '@skolplattformen/embedded-api'
|
|
||||||
import { translate } from '../utils/translation'
|
import { translate } from '../utils/translation'
|
||||||
|
import { useChild } from './childContext.component'
|
||||||
|
import { ContactMenu } from './contactMenu.component'
|
||||||
|
|
||||||
interface ClassmatesProps {
|
interface ClassmatesProps {
|
||||||
setSelected: (value?: number | null) => void
|
setSelected: (value?: number | null) => void
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
||||||
import { Classmate } from '@skolplattformen/embedded-api'
|
import { Classmate } from '@skolplattformen/api-skolplattformen'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
MenuGroup,
|
MenuGroup,
|
||||||
|
@ -9,6 +9,7 @@ import {
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Linking, StyleSheet } from 'react-native'
|
import { Linking, StyleSheet } from 'react-native'
|
||||||
import { fullName } from '../utils/peopleHelpers'
|
import { fullName } from '../utils/peopleHelpers'
|
||||||
|
import { translate } from '../utils/translation'
|
||||||
import {
|
import {
|
||||||
CallIcon,
|
CallIcon,
|
||||||
EmailIcon,
|
EmailIcon,
|
||||||
|
@ -16,7 +17,6 @@ import {
|
||||||
MoreIcon,
|
MoreIcon,
|
||||||
SMSIcon,
|
SMSIcon,
|
||||||
} from './icon.component'
|
} from './icon.component'
|
||||||
import { translate } from '../utils/translation'
|
|
||||||
|
|
||||||
interface ContactMenuProps {
|
interface ContactMenuProps {
|
||||||
contact: Classmate
|
contact: Classmate
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useTimetable } from '@skolplattformen/api-hooks'
|
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||||
import { Child } from '@skolplattformen/embedded-api'
|
import { useTimetable } from '@skolplattformen/hooks'
|
||||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||||
import moment, { Moment } from 'moment'
|
import moment, { Moment } from 'moment'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Image as ImageBase, ImageStyle, StyleProp } from 'react-native'
|
import { Image as ImageBase, ImageStyle, StyleProp } from 'react-native'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useMenu } from '@skolplattformen/api-hooks'
|
import { MenuItem } from '@skolplattformen/api-skolplattformen'
|
||||||
import { MenuItem } from '@skolplattformen/embedded-api'
|
import { useMenu } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
List,
|
List,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { MenuItem } from '@skolplattformen/embedded-api'
|
import { MenuItem } from '@skolplattformen/api-skolplattformen'
|
||||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Linking, Modal, TouchableOpacity, View } from 'react-native'
|
import { Linking, Modal, TouchableOpacity, View } from 'react-native'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { NavigationContainer } from '@react-navigation/native'
|
import { NavigationContainer } from '@react-navigation/native'
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
|
||||||
import {
|
import {
|
||||||
Child as ChildType,
|
Child as ChildType,
|
||||||
NewsItem as NewsItemType,
|
NewsItem as NewsItemType,
|
||||||
} from '@skolplattformen/embedded-api'
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import { useTheme } from '@ui-kitten/components'
|
import { useTheme } from '@ui-kitten/components'
|
||||||
import { Library } from 'libraries.json'
|
import { Library } from 'libraries.json'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
@ -153,9 +153,7 @@ export const AppNavigator = () => {
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Screen name="Login" component={Auth} options={authRouteOptions} />
|
||||||
<Screen name="Login" component={Auth} options={authRouteOptions} />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<Screen
|
<Screen
|
||||||
name="SetLanguage"
|
name="SetLanguage"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { RouteProp } from '@react-navigation/native'
|
import { RouteProp } from '@react-navigation/native'
|
||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
import { useNewsDetails } from '@skolplattformen/api-hooks'
|
import { useNewsDetails } from '@skolplattformen/hooks'
|
||||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import 'moment/locale/sv'
|
import 'moment/locale/sv'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useNews } from '@skolplattformen/api-hooks'
|
import { useNews } from '@skolplattformen/hooks'
|
||||||
import { Input, List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
import { Input, List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||||
import React, { useMemo, useState } from 'react'
|
import React, { useMemo, useState } from 'react'
|
||||||
import { TouchableOpacity, View } from 'react-native'
|
import { TouchableOpacity, View } from 'react-native'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
import { NewsItem } from '@skolplattformen/embedded-api'
|
import { NewsItem } from '@skolplattformen/api-skolplattformen'
|
||||||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import React, { ReactNode } from 'react'
|
import React, { ReactNode } from 'react'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Notification as NotificationType } from '@skolplattformen/embedded-api'
|
import { Notification as NotificationType } from '@skolplattformen/api-skolplattformen'
|
||||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useNotifications } from '@skolplattformen/api-hooks'
|
import { useNotifications } from '@skolplattformen/hooks'
|
||||||
import { List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
import { List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Sizing } from '../styles'
|
import { Sizing } from '../styles'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { CalendarItem } from '@skolplattformen/embedded-api'
|
import { CalendarItem } from '@skolplattformen/api-skolplattformen'
|
||||||
import { Button, MenuItem, OverflowMenu, Text } from '@ui-kitten/components'
|
import { Button, MenuItem, OverflowMenu, Text } from '@ui-kitten/components'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import RNCalendarEvents from 'react-native-calendar-events'
|
import RNCalendarEvents from 'react-native-calendar-events'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NavigationProp, useNavigation } from '@react-navigation/core'
|
import { NavigationProp, useNavigation } from '@react-navigation/core'
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import { ScrollView } from 'react-native'
|
import { ScrollView } from 'react-native'
|
||||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { useMenu, useTimetable } from '@skolplattformen/api-hooks'
|
import {
|
||||||
import { Child, MenuItem, TimetableEntry } from '@skolplattformen/embedded-api'
|
Child,
|
||||||
|
MenuItem,
|
||||||
|
TimetableEntry,
|
||||||
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
|
import { useMenu, useTimetable } from '@skolplattformen/hooks'
|
||||||
import {
|
import {
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { renderHook, act } from '@testing-library/react-hooks'
|
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
|
import { User } from '@skolplattformen/api-skolplattformen'
|
||||||
|
import { act, renderHook } from '@testing-library/react-hooks'
|
||||||
import usePersonalStorage from '../usePersonalStorage'
|
import usePersonalStorage from '../usePersonalStorage'
|
||||||
import { User } from '@skolplattformen/embedded-api'
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { User } from '@skolplattformen/embedded-api'
|
import { User } from '@skolplattformen/api-skolplattformen'
|
||||||
import useAsyncStorage from './useAsyncStorage'
|
import useAsyncStorage from './useAsyncStorage'
|
||||||
|
|
||||||
export default function usePersonalStorage<T>(
|
export default function usePersonalStorage<T>(
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
/**
|
|
||||||
* @format
|
|
||||||
*/
|
|
||||||
import { AppRegistry } from 'react-native'
|
|
||||||
import 'react-native-gesture-handler'
|
import 'react-native-gesture-handler'
|
||||||
|
import { AppRegistry } from 'react-native'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import { name as appName } from './app.json'
|
import { name as appName } from './app.json'
|
||||||
|
|
||||||
console.log(AppRegistry)
|
|
||||||
|
|
||||||
AppRegistry.registerComponent(appName, () => App)
|
AppRegistry.registerComponent(appName, () => App)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
|
import { User } from '@skolplattformen/api-skolplattformen'
|
||||||
import AppStorage from '../appStorage'
|
import AppStorage from '../appStorage'
|
||||||
import { User } from '@skolplattformen/embedded-api'
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
import { User } from '@skolplattformen/embedded-api'
|
import { User } from '@skolplattformen/api-skolplattformen'
|
||||||
|
|
||||||
export default class AppStorage {
|
export default class AppStorage {
|
||||||
static settingsStorageKeyPrefix = 'appsetting_'
|
static settingsStorageKeyPrefix = 'appsetting_'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Guardian } from '@skolplattformen/embedded-api'
|
import { Guardian } from '@skolplattformen/api-skolplattformen'
|
||||||
|
|
||||||
export const studentName = (name?: string) => name?.replace(/\s?\(\w+\)$/, '')
|
export const studentName = (name?: string) => name?.replace(/\s?\(\w+\)$/, '')
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { useMemo, ReactNode } from 'react'
|
import { NewsItem } from '@skolplattformen/api-skolplattformen'
|
||||||
|
import { useNews } from '@skolplattformen/hooks'
|
||||||
|
import { MatchData, Searcher } from 'fast-fuzzy'
|
||||||
|
import React, { ReactNode, useMemo } from 'react'
|
||||||
import { Text } from 'react-native'
|
import { Text } from 'react-native'
|
||||||
import { useNews } from '@skolplattformen/api-hooks'
|
|
||||||
import { NewsItem } from '@skolplattformen/embedded-api'
|
|
||||||
import { Typography } from '../styles'
|
|
||||||
import { useChild } from '../components/childContext.component'
|
import { useChild } from '../components/childContext.component'
|
||||||
|
import { Typography } from '../styles'
|
||||||
|
|
||||||
// https://github.com/facebook/react-native/issues/14796#issuecomment-389743259
|
// https://github.com/facebook/react-native/issues/14796#issuecomment-389743259
|
||||||
global.Buffer = global.Buffer || require('buffer').Buffer
|
global.Buffer = global.Buffer || require('buffer').Buffer
|
||||||
import { Searcher, MatchData } from 'fast-fuzzy'
|
|
||||||
|
|
||||||
const NUM_CHARS_AROUND_SEARCH_MATCH = 20
|
const NUM_CHARS_AROUND_SEARCH_MATCH = 20
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,7 +16,7 @@ the concrete implementation of fetch and cookie handler must be injected.
|
||||||
#### react-native
|
#### react-native
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import init from '@skolplattformen/embedded-api'
|
import init from '@skolplattformen/api-skolplattformen'
|
||||||
import CookieManager from '@react-native-community/cookies'
|
import CookieManager from '@react-native-community/cookies'
|
||||||
|
|
||||||
const api = init(fetch, () => CookieManager.clearAll())
|
const api = init(fetch, () => CookieManager.clearAll())
|
||||||
|
@ -25,7 +25,7 @@ const api = init(fetch, () => CookieManager.clearAll())
|
||||||
#### node
|
#### node
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import init from '@skolplattformen/embedded-api'
|
import init from '@skolplattformen/api-skolplattformen'
|
||||||
import nodeFetch from 'node-fetch'
|
import nodeFetch from 'node-fetch'
|
||||||
import fetchCookie from 'fetch-cookie/node-fetch'
|
import fetchCookie from 'fetch-cookie/node-fetch'
|
||||||
import { CookieJar } from 'tough-cookie'
|
import { CookieJar } from 'tough-cookie'
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
import { DateTime } from 'luxon'
|
import { Language } from '@skolplattformen/curriculum'
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import { decode } from 'he'
|
import { decode } from 'he'
|
||||||
|
import { DateTime } from 'luxon'
|
||||||
import * as html from 'node-html-parser'
|
import * as html from 'node-html-parser'
|
||||||
import { Language } from '@skolplattformen/curriculum/dist/translations'
|
import * as fake from './fakeData'
|
||||||
import { URLSearchParams } from './URLSearchParams'
|
import wrap, { Fetcher, FetcherOptions } from './fetcher'
|
||||||
import { checkStatus, LoginStatusChecker } from './loginStatus'
|
import { checkStatus, LoginStatusChecker } from './loginStatus'
|
||||||
|
import * as parse from './parse/index'
|
||||||
|
import * as routes from './routes'
|
||||||
import {
|
import {
|
||||||
AuthTicket,
|
AuthTicket,
|
||||||
CalendarItem,
|
CalendarItem,
|
||||||
Classmate,
|
Classmate,
|
||||||
CookieManager,
|
CookieManager,
|
||||||
|
EtjanstChild,
|
||||||
Fetch,
|
Fetch,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
NewsItem,
|
NewsItem,
|
||||||
Notification,
|
Notification,
|
||||||
RequestInit,
|
RequestInit,
|
||||||
ScheduleItem,
|
ScheduleItem,
|
||||||
User,
|
|
||||||
Skola24Child,
|
Skola24Child,
|
||||||
EtjanstChild,
|
|
||||||
SSOSystem,
|
SSOSystem,
|
||||||
TimetableEntry
|
TimetableEntry,
|
||||||
|
User,
|
||||||
} from './types'
|
} from './types'
|
||||||
import * as routes from './routes'
|
import { URLSearchParams } from './URLSearchParams'
|
||||||
import * as parse from './parse/index'
|
|
||||||
import wrap, { Fetcher, FetcherOptions } from './fetcher'
|
|
||||||
import * as fake from './fakeData'
|
|
||||||
|
|
||||||
const fakeResponse = <T>(data: T): Promise<T> =>
|
const fakeResponse = <T>(data: T): Promise<T> =>
|
||||||
new Promise((res) => setTimeout(() => res(data), 200 + Math.random() * 800))
|
new Promise((res) => setTimeout(() => res(data), 200 + Math.random() * 800))
|
||||||
|
@ -33,7 +33,8 @@ const fakeResponse = <T>(data: T): Promise<T> =>
|
||||||
const s24Init = {
|
const s24Init = {
|
||||||
headers: {
|
headers: {
|
||||||
accept: 'application/json, text/javascript, */*; q=0.01',
|
accept: 'application/json, text/javascript, */*; q=0.01',
|
||||||
referer: 'https://fns.stockholm.se/ng/timetable/timetable-viewer/fns.stockholm.se/',
|
referer:
|
||||||
|
'https://fns.stockholm.se/ng/timetable/timetable-viewer/fns.stockholm.se/',
|
||||||
'accept-language': 'en-US,en;q=0.9,sv;q=0.8',
|
'accept-language': 'en-US,en;q=0.9,sv;q=0.8',
|
||||||
'cache-control': 'no-cache',
|
'cache-control': 'no-cache',
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
|
@ -112,7 +113,8 @@ export class Api extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async login(personalNumber?: string): Promise<LoginStatusChecker> {
|
public async login(personalNumber?: string): Promise<LoginStatusChecker> {
|
||||||
if (personalNumber !== undefined && personalNumber.endsWith('1212121212')) return this.fakeMode()
|
if (personalNumber !== undefined && personalNumber.endsWith('1212121212'))
|
||||||
|
return this.fakeMode()
|
||||||
|
|
||||||
this.isFake = false
|
this.isFake = false
|
||||||
|
|
||||||
|
@ -256,7 +258,7 @@ export class Api extends EventEmitter {
|
||||||
public async getSchedule(
|
public async getSchedule(
|
||||||
child: EtjanstChild,
|
child: EtjanstChild,
|
||||||
from: DateTime,
|
from: DateTime,
|
||||||
to: DateTime,
|
to: DateTime
|
||||||
): Promise<ScheduleItem[]> {
|
): Promise<ScheduleItem[]> {
|
||||||
if (this.isFake) return fakeResponse(fake.schedule(child))
|
if (this.isFake) return fakeResponse(fake.schedule(child))
|
||||||
|
|
||||||
|
@ -277,7 +279,10 @@ export class Api extends EventEmitter {
|
||||||
return parse.news(data)
|
return parse.news(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getNewsDetails(child: EtjanstChild, item: NewsItem): Promise<any> {
|
public async getNewsDetails(
|
||||||
|
child: EtjanstChild,
|
||||||
|
item: NewsItem
|
||||||
|
): Promise<any> {
|
||||||
if (this.isFake) {
|
if (this.isFake) {
|
||||||
return fakeResponse(fake.news(child).find((ni) => ni.id === item.id))
|
return fakeResponse(fake.news(child).find((ni) => ni.id === item.id))
|
||||||
}
|
}
|
||||||
|
@ -329,11 +334,13 @@ export class Api extends EventEmitter {
|
||||||
private async readSAMLRequest(targetSystem: string): Promise<string> {
|
private async readSAMLRequest(targetSystem: string): Promise<string> {
|
||||||
const url = routes.ssoRequestUrl(targetSystem)
|
const url = routes.ssoRequestUrl(targetSystem)
|
||||||
const session = this.getRequestInit({
|
const session = this.getRequestInit({
|
||||||
redirect: 'follow',
|
redirect: 'follow',
|
||||||
})
|
})
|
||||||
const response = await this.fetch('samlRequest', url, session)
|
const response = await this.fetch('samlRequest', url, session)
|
||||||
const text = await response.text()
|
const text = await response.text()
|
||||||
const samlRequest = /name="SAMLRequest" value="(\S+)">/gm.exec(text || '')?.[1]
|
const samlRequest = /name="SAMLRequest" value="(\S+)">/gm.exec(
|
||||||
|
text || ''
|
||||||
|
)?.[1]
|
||||||
if (!samlRequest) {
|
if (!samlRequest) {
|
||||||
throw new Error('Could not parse SAML Request')
|
throw new Error('Could not parse SAML Request')
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,12 +352,14 @@ export class Api extends EventEmitter {
|
||||||
const body = new URLSearchParams({ SAMLRequest: samlRequest }).toString()
|
const body = new URLSearchParams({ SAMLRequest: samlRequest }).toString()
|
||||||
const url = routes.ssoResponseUrl
|
const url = routes.ssoResponseUrl
|
||||||
const session = this.getRequestInit({
|
const session = this.getRequestInit({
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
headers: {
|
||||||
redirect: 'follow',
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
},
|
||||||
|
redirect: 'follow',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
const response = await this.fetch('samlResponse', url, session)
|
const response = await this.fetch('samlResponse', url, session)
|
||||||
const text = await response.text()
|
const text = await response.text()
|
||||||
const samlResponse = /name="SAMLResponse" value="(\S+)">/gm.exec(text)?.[1]
|
const samlResponse = /name="SAMLResponse" value="(\S+)">/gm.exec(text)?.[1]
|
||||||
if (!samlResponse) {
|
if (!samlResponse) {
|
||||||
|
@ -366,14 +375,14 @@ export class Api extends EventEmitter {
|
||||||
}
|
}
|
||||||
const samlRequest = await this.readSAMLRequest(targetSystem)
|
const samlRequest = await this.readSAMLRequest(targetSystem)
|
||||||
const samlResponse = await this.submitSAMLRequest(samlRequest)
|
const samlResponse = await this.submitSAMLRequest(samlRequest)
|
||||||
|
|
||||||
const body = new URLSearchParams({ SAMLResponse: samlResponse }).toString()
|
const body = new URLSearchParams({ SAMLResponse: samlResponse }).toString()
|
||||||
const url = routes.samlResponseUrl
|
const url = routes.samlResponseUrl
|
||||||
const session = this.getRequestInit({
|
const session = this.getRequestInit({
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
},
|
},
|
||||||
redirect: 'follow',
|
redirect: 'follow',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
|
@ -383,13 +392,15 @@ export class Api extends EventEmitter {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSkola24Children(): Promise<Skola24Child[]>{
|
public async getSkola24Children(): Promise<Skola24Child[]> {
|
||||||
if (this.isFake) return fakeResponse(fake.skola24Children())
|
if (this.isFake) return fakeResponse(fake.skola24Children())
|
||||||
|
|
||||||
await this.ssoAuthorize('TimetableViewer')
|
await this.ssoAuthorize('TimetableViewer')
|
||||||
const body = { getPersonalTimetablesRequest: {
|
const body = {
|
||||||
hostName: 'fns.stockholm.se'
|
getPersonalTimetablesRequest: {
|
||||||
}}
|
hostName: 'fns.stockholm.se',
|
||||||
|
},
|
||||||
|
}
|
||||||
const session = this.getRequestInit({
|
const session = this.getRequestInit({
|
||||||
...s24Init,
|
...s24Init,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
@ -400,10 +411,8 @@ export class Api extends EventEmitter {
|
||||||
const response = await this.fetch('s24children', url, session)
|
const response = await this.fetch('s24children', url, session)
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
getPersonalTimetablesResponse: {
|
getPersonalTimetablesResponse: { childrenTimetables },
|
||||||
childrenTimetables
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
} = await response.json()
|
} = await response.json()
|
||||||
|
|
||||||
return childrenTimetables as Skola24Child[]
|
return childrenTimetables as Skola24Child[]
|
||||||
|
@ -413,18 +422,24 @@ export class Api extends EventEmitter {
|
||||||
const url = routes.renderKey
|
const url = routes.renderKey
|
||||||
const session = this.getRequestInit(s24Init)
|
const session = this.getRequestInit(s24Init)
|
||||||
const response = await this.fetch('renderKey', url, session)
|
const response = await this.fetch('renderKey', url, session)
|
||||||
const { data: { key } } = await response.json()
|
const {
|
||||||
|
data: { key },
|
||||||
|
} = await response.json()
|
||||||
return key as string
|
return key as string
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getTimetable(child: Skola24Child, week: number, year: number, lang: Language)
|
public async getTimetable(
|
||||||
: Promise<TimetableEntry[]> {
|
child: Skola24Child,
|
||||||
|
week: number,
|
||||||
|
year: number,
|
||||||
|
lang: Language
|
||||||
|
): Promise<TimetableEntry[]> {
|
||||||
if (this.isFake) return fakeResponse(fake.timetable(child))
|
if (this.isFake) return fakeResponse(fake.timetable(child))
|
||||||
|
|
||||||
if(!child.timetableID) {
|
if (!child.timetableID) {
|
||||||
return new Array<TimetableEntry>()
|
return new Array<TimetableEntry>()
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = routes.timetable
|
const url = routes.timetable
|
||||||
const renderKey = await this.getRenderKey()
|
const renderKey = await this.getRenderKey()
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -452,7 +467,11 @@ export class Api extends EventEmitter {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(params),
|
body: JSON.stringify(params),
|
||||||
})
|
})
|
||||||
const response = await this.fetch(`timetable_${child.personGuid}_${year}_${week}`, url, session)
|
const response = await this.fetch(
|
||||||
|
`timetable_${child.personGuid}_${year}_${week}`,
|
||||||
|
url,
|
||||||
|
session
|
||||||
|
)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
|
|
||||||
return parse.timetable(json, year, week, lang)
|
return parse.timetable(json, year, week, lang)
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import parse from '@skolplattformen/curriculum'
|
import parse, { Language } from '@skolplattformen/curriculum'
|
||||||
import { Language } from '@skolplattformen/curriculum/dist/translations'
|
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
import { TimetableEntry } from '../types'
|
import { TimetableEntry } from '../types'
|
||||||
|
|
||||||
const calculateDate = (year: number, weekNumber: number, weekday: number, time: string): string => {
|
const calculateDate = (
|
||||||
|
year: number,
|
||||||
|
weekNumber: number,
|
||||||
|
weekday: number,
|
||||||
|
time: string
|
||||||
|
): string => {
|
||||||
const [hours, minutes, seconds] = time.split(':')
|
const [hours, minutes, seconds] = time.split(':')
|
||||||
return DateTime.local()
|
return DateTime.local()
|
||||||
.set({
|
.set({
|
||||||
|
@ -14,7 +18,8 @@ const calculateDate = (year: number, weekNumber: number, weekday: number, time:
|
||||||
minute: parseInt(minutes, 10),
|
minute: parseInt(minutes, 10),
|
||||||
second: parseInt(seconds, 10),
|
second: parseInt(seconds, 10),
|
||||||
millisecond: 0,
|
millisecond: 0,
|
||||||
}).toISO()
|
})
|
||||||
|
.toISO()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TimetableResponseEntry {
|
interface TimetableResponseEntry {
|
||||||
|
@ -38,11 +43,26 @@ export interface TimetableResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntryParser {
|
interface EntryParser {
|
||||||
(args: TimetableResponseEntry, year: number, week: number, lang: Language): TimetableEntry
|
(
|
||||||
|
args: TimetableResponseEntry,
|
||||||
|
year: number,
|
||||||
|
week: number,
|
||||||
|
lang: Language
|
||||||
|
): TimetableEntry
|
||||||
}
|
}
|
||||||
export const timetableEntry: EntryParser = ({
|
export const timetableEntry: EntryParser = (
|
||||||
guidId, texts: [code, teacher, location], timeStart, timeEnd, dayOfWeekNumber, blockName,
|
{
|
||||||
}, year, week, lang) => ({
|
guidId,
|
||||||
|
texts: [code, teacher, location],
|
||||||
|
timeStart,
|
||||||
|
timeEnd,
|
||||||
|
dayOfWeekNumber,
|
||||||
|
blockName,
|
||||||
|
},
|
||||||
|
year,
|
||||||
|
week,
|
||||||
|
lang
|
||||||
|
) => ({
|
||||||
...parse(code, lang),
|
...parse(code, lang),
|
||||||
id: guidId,
|
id: guidId,
|
||||||
blockName,
|
blockName,
|
||||||
|
@ -55,9 +75,16 @@ export const timetableEntry: EntryParser = ({
|
||||||
dateEnd: calculateDate(year, week, dayOfWeekNumber, timeEnd),
|
dateEnd: calculateDate(year, week, dayOfWeekNumber, timeEnd),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const timetable = (response: TimetableResponse, year: number, week: number, lang: Language) => {
|
export const timetable = (
|
||||||
|
response: TimetableResponse,
|
||||||
|
year: number,
|
||||||
|
week: number,
|
||||||
|
lang: Language
|
||||||
|
) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
throw new Error(response.error)
|
throw new Error(response.error)
|
||||||
}
|
}
|
||||||
return response.data.lessonInfo.map((entry) => timetableEntry(entry, year, week, lang))
|
return response.data.lessonInfo.map((entry) =>
|
||||||
|
timetableEntry(entry, year, week, lang)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "api-skolplattformen",
|
"name": "@skolplattformen/api-skolplattformen",
|
||||||
"version": "0.15.0",
|
"version": "0.15.0",
|
||||||
"description": "Since the proxy was blocked (and also deemed a bad idea by some), this is a reboot of the API running in process in the app(s).",
|
"description": "Since the proxy was blocked (and also deemed a bad idea by some), this is a reboot of the API running in process in the app(s).",
|
||||||
"main": "lib/index.ts",
|
"main": "lib/index.ts",
|
||||||
|
|
|
@ -522,9 +522,9 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
"@skolplattformen/curriculum@^1.4.2":
|
"curriculum@^1.4.2":
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/@skolplattformen/curriculum/-/curriculum-1.4.2.tgz#614e17d51e72f4656ad99cf008a610addb124a14"
|
resolved "https://registry.yarnpkg.com/curriculum/-/curriculum-1.4.2.tgz#614e17d51e72f4656ad99cf008a610addb124a14"
|
||||||
integrity sha512-C81uSvKU5WxCkaAOmaz3qh0iYIOJKhufr0pT0VoMWWfySd9kLSu4Y/7VOgrdd1nAG9tEefDCju2yLBtV6UPAhw==
|
integrity sha512-C81uSvKU5WxCkaAOmaz3qh0iYIOJKhufr0pT0VoMWWfySd9kLSu4Y/7VOgrdd1nAG9tEefDCju2yLBtV6UPAhw==
|
||||||
dependencies:
|
dependencies:
|
||||||
deepmerge "^4.2.2"
|
deepmerge "^4.2.2"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import translate, { Language, Translation } from './translations'
|
import translate, { Language, Translation } from './translations'
|
||||||
|
export { Language } from './translations'
|
||||||
|
|
||||||
export interface Subject {
|
export interface Subject {
|
||||||
code: string
|
code: string
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
# @skolplattformen/api-hooks
|
# hooks
|
||||||
|
|
||||||
1. [Installing](#installing)
|
1. [Installing](#installing)
|
||||||
1. [Login / logout](#login--logout)
|
1. [Login / logout](#login--logout)
|
||||||
1. [Get data](#get-data)
|
1. [Get data](#get-data)
|
||||||
1. [Fake mode](#fake-mode)
|
1. [Fake mode](#fake-mode)
|
||||||
|
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
```npm i -S @skolplattformen/api-hooks @skolplattformen/embedded-api```
|
`npm i -S hooks @skolplattformen/embedded-api`
|
||||||
|
|
||||||
```yarn add @skolplattformen/api-hooks @skolplattformen/embedded-api```
|
`yarn add hooks @skolplattformen/embedded-api`
|
||||||
|
|
||||||
## ApiProvider
|
## ApiProvider
|
||||||
|
|
||||||
|
@ -18,8 +17,8 @@ In order to use api hooks, you must wrap your app in an ApiProvider
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ApiProvider } from '@skolplattformen/api-hooks'
|
import { ApiProvider } from '@skolplattformen/hooks'
|
||||||
import init from '@skolplattformen/embedded-api'
|
import init from '@skolplattformen/api-skolplattformen'
|
||||||
import { CookieManager } from '@react-native-community/cookies'
|
import { CookieManager } from '@react-native-community/cookies'
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||||
import { RootComponent } from './components/root'
|
import { RootComponent } from './components/root'
|
||||||
|
@ -41,7 +40,7 @@ export default () => (
|
||||||
## Login / logout
|
## Login / logout
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function LoginController () {
|
export default function LoginController () {
|
||||||
const { api, isLoggedIn } = useApi()
|
const { api, isLoggedIn } = useApi()
|
||||||
|
@ -90,12 +89,12 @@ export default function LoginController () {
|
||||||
|
|
||||||
The data hooks return a `State<T>` object exposing the following properties:
|
The data hooks return a `State<T>` object exposing the following properties:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
|----------|----------------------------------|
|
| -------- | ------------------------------- |
|
||||||
| `status` | `pending` `loading` `loaded` |
|
| `status` | `pending` `loading` `loaded` |
|
||||||
| `data` | The requested data |
|
| `data` | The requested data |
|
||||||
| `error` | Error from the API call if any |
|
| `error` | Error from the API call if any |
|
||||||
| `reload` | Function that triggers a reload |
|
| `reload` | Function that triggers a reload |
|
||||||
|
|
||||||
The hook will return a useable default for data at first (usually empty `[]`).
|
The hook will return a useable default for data at first (usually empty `[]`).
|
||||||
It then checks the cache (`AsyncStorage`) for any value and, if exists, updates data.
|
It then checks the cache (`AsyncStorage`) for any value and, if exists, updates data.
|
||||||
|
@ -108,11 +107,11 @@ their `status`, `data` and `error` updated.
|
||||||
### useCalendar
|
### useCalendar
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useCalendar } from '@skolplattformen/api-hooks'
|
import { useCalendar } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function CalendarComponent ({ selectedChild }) => {
|
export default function CalendarComponent ({ selectedChild }) => {
|
||||||
const { status, data, error, reload } = useCalendar(selectedChild)
|
const { status, data, error, reload } = useCalendar(selectedChild)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -129,11 +128,11 @@ export default function CalendarComponent ({ selectedChild }) => {
|
||||||
### useChildList
|
### useChildList
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useChildList } from '@skolplattformen/api-hooks'
|
import { useChildList } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function ChildListComponent () => {
|
export default function ChildListComponent () => {
|
||||||
const { status, data, error, reload } = useChildList()
|
const { status, data, error, reload } = useChildList()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -150,11 +149,11 @@ export default function ChildListComponent () => {
|
||||||
### useClassmates
|
### useClassmates
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useClassmates } from '@skolplattformen/api-hooks'
|
import { useClassmates } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function ClassmatesComponent ({ selectedChild }) => {
|
export default function ClassmatesComponent ({ selectedChild }) => {
|
||||||
const { status, data, error, reload } = useClassmates(selectedChild)
|
const { status, data, error, reload } = useClassmates(selectedChild)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -171,11 +170,11 @@ export default function ClassmatesComponent ({ selectedChild }) => {
|
||||||
### useMenu
|
### useMenu
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useMenu } from '@skolplattformen/api-hooks'
|
import { useMenu } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function MenuComponent ({ selectedChild }) => {
|
export default function MenuComponent ({ selectedChild }) => {
|
||||||
const { status, data, error, reload } = useMenu(selectedChild)
|
const { status, data, error, reload } = useMenu(selectedChild)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -192,11 +191,11 @@ export default function MenuComponent ({ selectedChild }) => {
|
||||||
### useNews
|
### useNews
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useNews } from '@skolplattformen/api-hooks'
|
import { useNews } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function NewsComponent ({ selectedChild }) => {
|
export default function NewsComponent ({ selectedChild }) => {
|
||||||
const { status, data, error, reload } = useNews(selectedChild)
|
const { status, data, error, reload } = useNews(selectedChild)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -213,12 +212,12 @@ export default function NewsComponent ({ selectedChild }) => {
|
||||||
To display image from `NewsItem`:
|
To display image from `NewsItem`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function NewsItem ({ item }) => {
|
export default function NewsItem ({ item }) => {
|
||||||
const { api } = useApi()
|
const { api } = useApi()
|
||||||
const cookie = api.getSessionCookie()
|
const cookie = api.getSessionCookie()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ cookie &&
|
{ cookie &&
|
||||||
|
@ -231,11 +230,11 @@ export default function NewsItem ({ item }) => {
|
||||||
### useNotifications
|
### useNotifications
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useNotifications } from '@skolplattformen/api-hooks'
|
import { useNotifications } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function NotificationsComponent ({ selectedChild }) => {
|
export default function NotificationsComponent ({ selectedChild }) => {
|
||||||
const { status, data, error, reload } = useNotifications(selectedChild)
|
const { status, data, error, reload } = useNotifications(selectedChild)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -252,12 +251,12 @@ export default function NotificationsComponent ({ selectedChild }) => {
|
||||||
To show content of `NotificationItem` url:
|
To show content of `NotificationItem` url:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
import { WebView } from 'react-native-webview'
|
import { WebView } from 'react-native-webview'
|
||||||
|
|
||||||
export default function Notification ({ item }) => {
|
export default function Notification ({ item }) => {
|
||||||
const { cookie } = useApi()
|
const { cookie } = useApi()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<WebView source={{ uri: item.url, headers: { cookie }}} />
|
<WebView source={{ uri: item.url, headers: { cookie }}} />
|
||||||
|
@ -270,13 +269,13 @@ export default function Notification ({ item }) => {
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
import { useSchedule } from '@skolplattformen/api-hooks'
|
import { useSchedule } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function ScheduleComponent ({ selectedChild }) => {
|
export default function ScheduleComponent ({ selectedChild }) => {
|
||||||
const from = DateTime.local()
|
const from = DateTime.local()
|
||||||
const to = DateTime.local.plus({ week: 1 })
|
const to = DateTime.local.plus({ week: 1 })
|
||||||
const { status, data, error, reload } = useSchedule(selectedChild, from, to)
|
const { status, data, error, reload } = useSchedule(selectedChild, from, to)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -293,11 +292,11 @@ export default function ScheduleComponent ({ selectedChild }) => {
|
||||||
### useUser
|
### useUser
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useUser } from '@skolplattformen/api-hooks'
|
import { useUser } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function UserComponent () => {
|
export default function UserComponent () => {
|
||||||
const { status, data, error, reload } = useUser()
|
const { status, data, error, reload } = useUser()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{ status === 'loading' && <Spinner />}
|
{ status === 'loading' && <Spinner />}
|
||||||
|
@ -321,10 +320,10 @@ personal numbers: `12121212121212`, `201212121212` or `1212121212`.
|
||||||
The returned login status will have `token` set to `'fake'`.
|
The returned login status will have `token` set to `'fake'`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
|
|
||||||
import { useApi } from '@skolplattformen/api-hooks'
|
import { useApi } from '@skolplattformen/hooks'
|
||||||
|
|
||||||
export default function LoginController () {
|
export default function LoginController () {
|
||||||
const { api, isLoggedIn } = useApi()
|
const { api, isLoggedIn } = useApi()
|
||||||
|
|
|
@ -6,4 +6,4 @@ module.exports = {
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
coverageDirectory: '../../coverage/libs/hooks',
|
coverageDirectory: '../../coverage/libs/hooks',
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@skolplattformen/api-hooks",
|
"name": "@skolplattformen/hooks",
|
||||||
"description": "React hooks for accessing api with cached results",
|
"description": "React hooks for accessing api with cached results",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
import { Child, EtjanstChild, Skola24Child } from '@skolplattformen/embedded-api'
|
import {
|
||||||
|
Child,
|
||||||
|
EtjanstChild,
|
||||||
|
Skola24Child,
|
||||||
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export const merge = (etjanstChildren: EtjanstChild[], skola24Children: Skola24Child[]): Child[] => (
|
export const merge = (
|
||||||
|
etjanstChildren: EtjanstChild[],
|
||||||
|
skola24Children: Skola24Child[]
|
||||||
|
): Child[] =>
|
||||||
etjanstChildren.map((etjanstChild) => {
|
etjanstChildren.map((etjanstChild) => {
|
||||||
const skola24Child: Skola24Child = (
|
const skola24Child: Skola24Child =
|
||||||
skola24Children.find((s24c) => s24c.firstName && etjanstChild.name.startsWith(s24c.firstName)) || {}
|
skola24Children.find(
|
||||||
)
|
(s24c) => s24c.firstName && etjanstChild.name.startsWith(s24c.firstName)
|
||||||
|
) || {}
|
||||||
const child: Child = {
|
const child: Child = {
|
||||||
...etjanstChild,
|
...etjanstChild,
|
||||||
...skola24Child,
|
...skola24Child,
|
||||||
}
|
}
|
||||||
return child
|
return child
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { useDispatch } from 'react-redux'
|
|
||||||
import {
|
import {
|
||||||
Api,
|
Api,
|
||||||
CalendarItem,
|
CalendarItem,
|
||||||
|
@ -13,9 +11,15 @@ import {
|
||||||
Skola24Child,
|
Skola24Child,
|
||||||
TimetableEntry,
|
TimetableEntry,
|
||||||
User,
|
User,
|
||||||
} from '@skolplattformen/embedded-api'
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
|
import { Language } from '@skolplattformen/curriculum'
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
import { Language } from '@skolplattformen/curriculum/dist/translations'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
import { loadAction } from './actions'
|
||||||
|
import { merge } from './childlists'
|
||||||
|
import { useApi } from './context'
|
||||||
|
import store from './store'
|
||||||
import {
|
import {
|
||||||
ApiCall,
|
ApiCall,
|
||||||
EntityHookResult,
|
EntityHookResult,
|
||||||
|
@ -24,10 +28,6 @@ import {
|
||||||
EntityStoreRootState,
|
EntityStoreRootState,
|
||||||
ExtraActionProps,
|
ExtraActionProps,
|
||||||
} from './types'
|
} from './types'
|
||||||
import { useApi } from './context'
|
|
||||||
import { loadAction } from './actions'
|
|
||||||
import store from './store'
|
|
||||||
import { merge } from './childlists'
|
|
||||||
|
|
||||||
interface StoreSelector<T> {
|
interface StoreSelector<T> {
|
||||||
(state: EntityStoreRootState): EntityMap<T>
|
(state: EntityStoreRootState): EntityMap<T>
|
||||||
|
@ -38,13 +38,12 @@ const hook = <T>(
|
||||||
key: string,
|
key: string,
|
||||||
defaultValue: T,
|
defaultValue: T,
|
||||||
selector: StoreSelector<T>,
|
selector: StoreSelector<T>,
|
||||||
apiCaller: (api: Api) => ApiCall<T>,
|
apiCaller: (api: Api) => ApiCall<T>
|
||||||
): EntityHookResult<T> => {
|
): EntityHookResult<T> => {
|
||||||
const {
|
const { api, isLoggedIn, reporter, storage } = useApi()
|
||||||
api, isLoggedIn, reporter, storage,
|
|
||||||
} = useApi()
|
|
||||||
|
|
||||||
const getState = (): EntityStoreRootState => store.getState() as unknown as EntityStoreRootState
|
const getState = (): EntityStoreRootState =>
|
||||||
|
store.getState() as unknown as EntityStoreRootState
|
||||||
const select = (storeState: EntityStoreRootState) => {
|
const select = (storeState: EntityStoreRootState) => {
|
||||||
const stateMap = selector(storeState) || {}
|
const stateMap = selector(storeState) || {}
|
||||||
const state = stateMap[key] || { status: 'pending', data: defaultValue }
|
const state = stateMap[key] || { status: 'pending', data: defaultValue }
|
||||||
|
@ -55,7 +54,11 @@ const hook = <T>(
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
const load = (force = false) => {
|
const load = (force = false) => {
|
||||||
if (isLoggedIn && state.status !== 'loading' && ((force && !api.isFake) || state.status === 'pending')) {
|
if (
|
||||||
|
isLoggedIn &&
|
||||||
|
state.status !== 'loading' &&
|
||||||
|
((force && !api.isFake) || state.status === 'pending')
|
||||||
|
) {
|
||||||
const extra: ExtraActionProps<T> = {
|
const extra: ExtraActionProps<T> = {
|
||||||
key,
|
key,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
@ -71,27 +74,34 @@ const hook = <T>(
|
||||||
if (state.status === 'pending') {
|
if (state.status === 'pending') {
|
||||||
extra.getFromCache = () => storage.getItem(`${pnr}_${key}`)
|
extra.getFromCache = () => storage.getItem(`${pnr}_${key}`)
|
||||||
}
|
}
|
||||||
extra.saveToCache = (value: string) => storage.setItem(`${pnr}_${key}`, value)
|
extra.saveToCache = (value: string) =>
|
||||||
|
storage.setItem(`${pnr}_${key}`, value)
|
||||||
}
|
}
|
||||||
const action = loadAction<T>(entityName, extra)
|
const action = loadAction<T>(entityName, extra)
|
||||||
dispatch(action)
|
dispatch(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
useEffect(() => { load() }, [isLoggedIn])
|
useEffect(() => {
|
||||||
|
load()
|
||||||
|
}, [isLoggedIn])
|
||||||
|
|
||||||
let mounted: boolean
|
let mounted: boolean
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
mounted = true
|
mounted = true
|
||||||
return () => { mounted = false }
|
return () => {
|
||||||
|
mounted = false
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const listener = () => {
|
const listener = () => {
|
||||||
if (!mounted) return
|
if (!mounted) return
|
||||||
|
|
||||||
const newState = select(getState())
|
const newState = select(getState())
|
||||||
if (newState.status !== state.status
|
if (
|
||||||
|| newState.data !== state.data
|
newState.status !== state.status ||
|
||||||
|| newState.error !== state.error) {
|
newState.data !== state.data ||
|
||||||
|
newState.error !== state.error
|
||||||
|
) {
|
||||||
setState(newState)
|
setState(newState)
|
||||||
|
|
||||||
if (newState.error) {
|
if (newState.error) {
|
||||||
|
@ -108,99 +118,117 @@ const hook = <T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEtjanstChildren = () => hook<EtjanstChild[]>(
|
export const useEtjanstChildren = () =>
|
||||||
'ETJANST_CHILDREN',
|
hook<EtjanstChild[]>(
|
||||||
'etjanst_children',
|
'ETJANST_CHILDREN',
|
||||||
[],
|
'etjanst_children',
|
||||||
(s) => s.etjanstChildren,
|
[],
|
||||||
(api) => () => api.getChildren(),
|
(s) => s.etjanstChildren,
|
||||||
)
|
(api) => () => api.getChildren()
|
||||||
|
)
|
||||||
|
|
||||||
export const useSkola24Children = () => hook<Skola24Child[]>(
|
export const useSkola24Children = () =>
|
||||||
'SKOLA24_CHILDREN',
|
hook<Skola24Child[]>(
|
||||||
'skola24_children',
|
'SKOLA24_CHILDREN',
|
||||||
[],
|
'skola24_children',
|
||||||
(s) => s.skola24Children,
|
[],
|
||||||
(api) => () => api.getSkola24Children(),
|
(s) => s.skola24Children,
|
||||||
)
|
(api) => () => api.getSkola24Children()
|
||||||
|
)
|
||||||
|
|
||||||
export const useCalendar = (child: Child) => hook<CalendarItem[]>(
|
export const useCalendar = (child: Child) =>
|
||||||
'CALENDAR',
|
hook<CalendarItem[]>(
|
||||||
`calendar_${child.id}`,
|
'CALENDAR',
|
||||||
[],
|
`calendar_${child.id}`,
|
||||||
(s) => s.calendar,
|
[],
|
||||||
(api) => () => api.getCalendar(child),
|
(s) => s.calendar,
|
||||||
)
|
(api) => () => api.getCalendar(child)
|
||||||
|
)
|
||||||
|
|
||||||
export const useClassmates = (child: Child) => hook<Classmate[]>(
|
export const useClassmates = (child: Child) =>
|
||||||
'CLASSMATES',
|
hook<Classmate[]>(
|
||||||
`classmates_${child.id}`,
|
'CLASSMATES',
|
||||||
[],
|
`classmates_${child.id}`,
|
||||||
(s) => s.classmates,
|
[],
|
||||||
(api) => () => api.getClassmates(child),
|
(s) => s.classmates,
|
||||||
)
|
(api) => () => api.getClassmates(child)
|
||||||
|
)
|
||||||
|
|
||||||
export const useMenu = (child: Child) => hook<MenuItem[]>(
|
export const useMenu = (child: Child) =>
|
||||||
'MENU',
|
hook<MenuItem[]>(
|
||||||
`menu_${child.id}`,
|
'MENU',
|
||||||
[],
|
`menu_${child.id}`,
|
||||||
(s) => s.menu,
|
[],
|
||||||
(api) => () => api.getMenu(child),
|
(s) => s.menu,
|
||||||
)
|
(api) => () => api.getMenu(child)
|
||||||
|
)
|
||||||
|
|
||||||
export const useNews = (child: Child) => hook<NewsItem[]>(
|
export const useNews = (child: Child) =>
|
||||||
'NEWS',
|
hook<NewsItem[]>(
|
||||||
`news_${child.id}`,
|
'NEWS',
|
||||||
[],
|
`news_${child.id}`,
|
||||||
(s) => s.news,
|
[],
|
||||||
(api) => () => api.getNews(child),
|
(s) => s.news,
|
||||||
)
|
(api) => () => api.getNews(child)
|
||||||
|
)
|
||||||
|
|
||||||
export const useNewsDetails = (child: Child, news: NewsItem) => hook<NewsItem>(
|
export const useNewsDetails = (child: Child, news: NewsItem) =>
|
||||||
'NEWS_DETAILS',
|
hook<NewsItem>(
|
||||||
`news_details_${news.id}`,
|
'NEWS_DETAILS',
|
||||||
news,
|
`news_details_${news.id}`,
|
||||||
(s) => s.newsDetails,
|
news,
|
||||||
(api) => () => api.getNewsDetails(child, news),
|
(s) => s.newsDetails,
|
||||||
)
|
(api) => () => api.getNewsDetails(child, news)
|
||||||
|
)
|
||||||
|
|
||||||
export const useNotifications = (child: Child) => hook<Notification[]>(
|
export const useNotifications = (child: Child) =>
|
||||||
'NOTIFICATIONS',
|
hook<Notification[]>(
|
||||||
`notifications_${child.id}`,
|
'NOTIFICATIONS',
|
||||||
[],
|
`notifications_${child.id}`,
|
||||||
(s) => s.notifications,
|
[],
|
||||||
(api) => () => api.getNotifications(child),
|
(s) => s.notifications,
|
||||||
)
|
(api) => () => api.getNotifications(child)
|
||||||
|
)
|
||||||
|
|
||||||
export const useSchedule = (child: Child, from: string, to: string) => hook<ScheduleItem[]>(
|
export const useSchedule = (child: Child, from: string, to: string) =>
|
||||||
'SCHEDULE',
|
hook<ScheduleItem[]>(
|
||||||
`schedule_${child.id}_${from}_${to}`,
|
'SCHEDULE',
|
||||||
[],
|
`schedule_${child.id}_${from}_${to}`,
|
||||||
(s) => s.schedule,
|
[],
|
||||||
(api) => () => api.getSchedule(child, DateTime.fromISO(from), DateTime.fromISO(to)),
|
(s) => s.schedule,
|
||||||
)
|
(api) => () =>
|
||||||
|
api.getSchedule(child, DateTime.fromISO(from), DateTime.fromISO(to))
|
||||||
|
)
|
||||||
|
|
||||||
export const useTimetable = (
|
export const useTimetable = (
|
||||||
child: Skola24Child, week: number, year: number, lang: Language,
|
child: Skola24Child,
|
||||||
) => hook<TimetableEntry[]>(
|
week: number,
|
||||||
'TIMETABLE',
|
year: number,
|
||||||
`timetable_${child.personGuid}_${week}_${year}_${lang}`,
|
lang: Language
|
||||||
[],
|
) =>
|
||||||
(s) => s.timetable,
|
hook<TimetableEntry[]>(
|
||||||
(api) => () => api.getTimetable(child, week, year, lang),
|
'TIMETABLE',
|
||||||
)
|
`timetable_${child.personGuid}_${week}_${year}_${lang}`,
|
||||||
|
[],
|
||||||
|
(s) => s.timetable,
|
||||||
|
(api) => () => api.getTimetable(child, week, year, lang)
|
||||||
|
)
|
||||||
|
|
||||||
export const useUser = () => hook<User>(
|
export const useUser = () =>
|
||||||
'USER',
|
hook<User>(
|
||||||
'user',
|
'USER',
|
||||||
{},
|
'user',
|
||||||
(s) => s.user,
|
{},
|
||||||
(api) => () => api.getUser(),
|
(s) => s.user,
|
||||||
)
|
(api) => () => api.getUser()
|
||||||
|
)
|
||||||
|
|
||||||
export const useChildList = (): EntityHookResult<Child[]> => {
|
export const useChildList = (): EntityHookResult<Child[]> => {
|
||||||
const {
|
const {
|
||||||
data: etjanstData, status, error, reload: etjanstReload,
|
data: etjanstData,
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
reload: etjanstReload,
|
||||||
} = useEtjanstChildren()
|
} = useEtjanstChildren()
|
||||||
const { data: skola24Data, reload: skola24Reload } = useSkola24Children()
|
const { data: skola24Data, reload: skola24Reload } = useSkola24Children()
|
||||||
|
|
||||||
|
@ -216,6 +244,9 @@ export const useChildList = (): EntityHookResult<Child[]> => {
|
||||||
}, [etjanstData, skola24Data])
|
}, [etjanstData, skola24Data])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data, status, error, reload,
|
data,
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
reload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,28 @@
|
||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
/* eslint-disable import/prefer-default-export */
|
/* eslint-disable import/prefer-default-export */
|
||||||
import { Api } from '@skolplattformen/embedded-api'
|
import { Api } from '@skolplattformen/api-skolplattformen'
|
||||||
import React, {
|
import React, { FC, PropsWithChildren, useEffect, useState } from 'react'
|
||||||
FC, PropsWithChildren, useEffect, useState,
|
|
||||||
} from 'react'
|
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { ApiContext } from './context'
|
import { ApiContext } from './context'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import { AsyncStorage, EntityAction, IApiContext, Reporter } from './types'
|
import { AsyncStorage, IApiContext, Reporter } from './types'
|
||||||
|
|
||||||
type TApiProvider = FC<PropsWithChildren<{
|
type TApiProvider = FC<
|
||||||
api: Api,
|
PropsWithChildren<{
|
||||||
storage: AsyncStorage,
|
api: Api
|
||||||
reporter?: Reporter
|
storage: AsyncStorage
|
||||||
}>>
|
reporter?: Reporter
|
||||||
|
}>
|
||||||
|
>
|
||||||
const noopReporter: Reporter = {
|
const noopReporter: Reporter = {
|
||||||
log: () => { },
|
log: () => {},
|
||||||
error: () => { },
|
error: () => {},
|
||||||
}
|
}
|
||||||
export const ApiProvider: TApiProvider = ({
|
export const ApiProvider: TApiProvider = ({
|
||||||
children, api, storage, reporter = noopReporter,
|
children,
|
||||||
|
api,
|
||||||
|
storage,
|
||||||
|
reporter = noopReporter,
|
||||||
}) => {
|
}) => {
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(api.isLoggedIn)
|
const [isLoggedIn, setIsLoggedIn] = useState(api.isLoggedIn)
|
||||||
const [isFake, setIsFake] = useState(api.isFake)
|
const [isFake, setIsFake] = useState(api.isFake)
|
||||||
|
@ -53,9 +56,7 @@ export const ApiProvider: TApiProvider = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApiContext.Provider value={value}>
|
<ApiContext.Provider value={value}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>{children}</Provider>
|
||||||
{children}
|
|
||||||
</Provider>
|
|
||||||
</ApiContext.Provider>
|
</ApiContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@ import {
|
||||||
CalendarItem,
|
CalendarItem,
|
||||||
Classmate,
|
Classmate,
|
||||||
EtjanstChild,
|
EtjanstChild,
|
||||||
Skola24Child,
|
|
||||||
MenuItem,
|
MenuItem,
|
||||||
NewsItem,
|
NewsItem,
|
||||||
Notification,
|
Notification,
|
||||||
ScheduleItem,
|
ScheduleItem,
|
||||||
User,
|
Skola24Child,
|
||||||
TimetableEntry,
|
TimetableEntry,
|
||||||
} from '@skolplattformen/embedded-api'
|
User,
|
||||||
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
import { EntityName, EntityReducer, EntityState } from './types'
|
import { EntityName, EntityReducer, EntityState } from './types'
|
||||||
|
|
||||||
const createReducer = <T>(entity: EntityName): EntityReducer<T> => {
|
const createReducer = <T>(entity: EntityName): EntityReducer<T> => {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import {
|
import {
|
||||||
Api,
|
Api,
|
||||||
EtjanstChild,
|
|
||||||
Skola24Child,
|
|
||||||
User,
|
|
||||||
CalendarItem,
|
CalendarItem,
|
||||||
Classmate,
|
Classmate,
|
||||||
|
EtjanstChild,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
NewsItem,
|
NewsItem,
|
||||||
Notification,
|
Notification,
|
||||||
ScheduleItem,
|
ScheduleItem,
|
||||||
|
Skola24Child,
|
||||||
TimetableEntry,
|
TimetableEntry,
|
||||||
} from '@skolplattformen/embedded-api'
|
User,
|
||||||
|
} from '@skolplattformen/api-skolplattformen'
|
||||||
import { Action, Reducer } from 'redux'
|
import { Action, Reducer } from 'redux'
|
||||||
|
|
||||||
export interface Reporter {
|
export interface Reporter {
|
||||||
|
@ -44,26 +44,28 @@ export interface ExtraActionProps<T> {
|
||||||
getFromCache?: () => Promise<string | null>
|
getFromCache?: () => Promise<string | null>
|
||||||
saveToCache?: (value: string) => Promise<void>
|
saveToCache?: (value: string) => Promise<void>
|
||||||
}
|
}
|
||||||
export type EntityActionType = 'GET_FROM_API'
|
export type EntityActionType =
|
||||||
| 'RESULT_FROM_API'
|
| 'GET_FROM_API'
|
||||||
| 'API_ERROR'
|
| 'RESULT_FROM_API'
|
||||||
| 'GET_FROM_CACHE'
|
| 'API_ERROR'
|
||||||
| 'RESULT_FROM_CACHE'
|
| 'GET_FROM_CACHE'
|
||||||
| 'STORE_IN_CACHE'
|
| 'RESULT_FROM_CACHE'
|
||||||
| 'CLEAR'
|
| 'STORE_IN_CACHE'
|
||||||
export type EntityName = 'USER'
|
| 'CLEAR'
|
||||||
| 'ETJANST_CHILDREN'
|
export type EntityName =
|
||||||
| 'SKOLA24_CHILDREN'
|
| 'USER'
|
||||||
| 'CHILDREN'
|
| 'ETJANST_CHILDREN'
|
||||||
| 'CALENDAR'
|
| 'SKOLA24_CHILDREN'
|
||||||
| 'CLASSMATES'
|
| 'CHILDREN'
|
||||||
| 'MENU'
|
| 'CALENDAR'
|
||||||
| 'NEWS'
|
| 'CLASSMATES'
|
||||||
| 'NEWS_DETAILS'
|
| 'MENU'
|
||||||
| 'NOTIFICATIONS'
|
| 'NEWS'
|
||||||
| 'SCHEDULE'
|
| 'NEWS_DETAILS'
|
||||||
| 'TIMETABLE'
|
| 'NOTIFICATIONS'
|
||||||
| 'ALL'
|
| 'SCHEDULE'
|
||||||
|
| 'TIMETABLE'
|
||||||
|
| 'ALL'
|
||||||
export interface EntityAction<T> extends Action<EntityActionType> {
|
export interface EntityAction<T> extends Action<EntityActionType> {
|
||||||
entity: EntityName
|
entity: EntityName
|
||||||
data?: T
|
data?: T
|
||||||
|
@ -79,14 +81,14 @@ export interface EntityStoreRootState {
|
||||||
etjanstChildren: EntityMap<EtjanstChild[]>
|
etjanstChildren: EntityMap<EtjanstChild[]>
|
||||||
skola24Children: EntityMap<Skola24Child[]>
|
skola24Children: EntityMap<Skola24Child[]>
|
||||||
user: EntityMap<User>
|
user: EntityMap<User>
|
||||||
calendar: EntityMap<CalendarItem[]>,
|
calendar: EntityMap<CalendarItem[]>
|
||||||
classmates: EntityMap<Classmate[]>,
|
classmates: EntityMap<Classmate[]>
|
||||||
menu: EntityMap<MenuItem[]>,
|
menu: EntityMap<MenuItem[]>
|
||||||
news: EntityMap<NewsItem[]>,
|
news: EntityMap<NewsItem[]>
|
||||||
newsDetails: EntityMap<NewsItem>,
|
newsDetails: EntityMap<NewsItem>
|
||||||
notifications: EntityMap<Notification[]>,
|
notifications: EntityMap<Notification[]>
|
||||||
schedule: EntityMap<ScheduleItem[]>,
|
schedule: EntityMap<ScheduleItem[]>
|
||||||
timetable: EntityMap<TimetableEntry[]>,
|
timetable: EntityMap<TimetableEntry[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityHookResult<T> extends EntityState<T> {
|
export interface EntityHookResult<T> extends EntityState<T> {
|
||||||
|
|
|
@ -1304,9 +1304,9 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
"@skolplattformen/curriculum@^1.3.0":
|
"curriculum@^1.3.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@skolplattformen/curriculum/-/curriculum-1.3.0.tgz#841e2ff0095e39e174cffdd0b8a81a17956de7ed"
|
resolved "https://registry.yarnpkg.com/curriculum/-/curriculum-1.3.0.tgz#841e2ff0095e39e174cffdd0b8a81a17956de7ed"
|
||||||
integrity sha512-nuwZX45gHe5JaiYfygDP1HmbhAJOEXuuWwR04tNAnl/PaDGqJscfzKt8YD2SL+MHqi3LARjSKLa4ms4SxVQFyw==
|
integrity sha512-nuwZX45gHe5JaiYfygDP1HmbhAJOEXuuWwR04tNAnl/PaDGqJscfzKt8YD2SL+MHqi3LARjSKLa4ms4SxVQFyw==
|
||||||
|
|
||||||
"@skolplattformen/embedded-api@^5.1.0":
|
"@skolplattformen/embedded-api@^5.1.0":
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@skolplattformen/api-skolplattformen": [
|
"@skolplattformen/api-skolplattformen": [
|
||||||
"libs/api-skolplattformen/src/index.ts"
|
"libs/api-skolplattformen/lib/index.ts"
|
||||||
],
|
],
|
||||||
"@skolplattformen/curriculum": ["libs/curriculum/src/index.ts"],
|
"@skolplattformen/curriculum": ["libs/curriculum/src/index.ts"],
|
||||||
"@skolplattformen/hooks": ["libs/hooks/src/index.ts"]
|
"@skolplattformen/hooks": ["libs/hooks/src/index.ts"]
|
||||||
|
|
Loading…
Reference in New Issue