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