Verified Commit 5c049ace authored by Sandro Lutz's avatar Sandro Lutz
Browse files

Add dynamic imports (performance boost)

parent f9033f63
......@@ -7,11 +7,17 @@ module.exports = {
browser: true,
node: true,
},
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
},
rules: {
'no-multi-str': 0,
'no-underscore-dangle': 0,
'no-console': 0,
'import/prefer-default-export': 0,
'import/no-extraneous-dependencies': ['warning', {'peerDependencies': true}],
'camelcase': 0,
'prettier/prettier': 'error',
},
......
This diff is collapsed.
import m from 'mithril';
import { Button } from 'polythene-mithril';
import { Button } from 'polythene-mithril-button';
import { ButtonCSS } from 'polythene-css';
ButtonCSS.addStyle('.blue-button', {
......
import m from 'mithril';
import { Checkbox } from 'polythene-mithril';
import { Checkbox } from 'polythene-mithril-checkbox';
/**
* Generic Checkbox component
......
import m from 'mithril';
import { apiUrl } from 'config';
import { Card } from 'polythene-mithril';
import { Spinner } from 'amiv-web-ui-components';
import { Card } from 'polythene-mithril-card';
import Spinner from 'amiv-web-ui-components/src/spinner';
export default class EventCard {
/**
......
import m from 'mithril';
import { Search, Shadow, IconButton } from 'polythene-mithril';
import { RadioGroup } from 'amiv-web-ui-components';
import { Search } from 'polythene-mithril-search';
import { Shadow } from 'polythene-mithril-shadow';
import { IconButton } from 'polythene-mithril-icon-button';
import RadioGroup from 'amiv-web-ui-components/src/radioGroup';
import debounce from 'amiv-web-ui-components/src/debounce';
import icons from 'amiv-web-ui-components/src/icons';
import Button from './Button';
......
import m from 'mithril';
import { Tabs } from 'polythene-mithril';
import { Tabs } from 'polythene-mithril-tabs';
/**
* Generic Tab component
......
import m from 'mithril';
import { TextField } from 'polythene-mithril';
import { TextField } from 'polythene-mithril-textfield';
/**
* Generic TextField component
......
// src/index.js
import m from 'mithril';
import Raven from 'raven-js';
import { Button } from 'polythene-mithril-button';
import { sentryUrl, sentryEnvironment } from 'config';
import { loadLanguage, currentLanguage, isLanguageValid } from './models/language';
import Spinner from 'amiv-web-ui-components/src/spinner';
import { loadLanguage, currentLanguage, isLanguageValid, i18n } from './models/language';
import { Error404, Error401 } from './views/errors';
import { isLoggedIn, checkLogin } from './models/auth';
import studydocList from './views/studydocs/studydocList';
import studydocNew from './views/studydocs/studydocNew';
import eventList from './views/events/eventList';
import profile from './views/profile';
import layout from './views/layout';
import frontpage from './views/frontpage';
import logout from './views/logout';
import about from './views/amiv/about';
import board from './views/amiv/board';
import teams from './views/amiv/teams';
import jobOfferList from './views/jobs/jobofferList';
import logout from './views/logout';
import legalNotice from './views/legalNotice';
import './styles/base.less';
......@@ -44,21 +39,21 @@ Raven.context(() => {
{
url: '/:language/studydocuments',
reason: 'studydocs.accessDenied',
view: () => m(studydocList),
viewAsync: './views/studydocs/studydocList',
},
{
url: '/:language/studydocuments/new',
reason: 'studydocs.accessDenied',
view: () => m(studydocNew),
viewAsync: './views/studydocs/studydocNew',
},
{
url: '/:language/studydocuments/:documentId',
reason: 'studydocs.accessDenied',
view: vnode => m(studydocList, vnode.attrs),
viewAsync: './views/studydocs/studydocList',
},
{
url: '/:language/profile',
view: vnode => m(profile, vnode.attrs),
viewAsync: './views/profile',
},
];
......@@ -70,11 +65,11 @@ Raven.context(() => {
},
{
url: '/:language/board',
view: () => m(board),
viewAsync: './views/amiv/board',
},
{
url: '/:language/teams',
view: () => m(teams),
viewAsync: './views/amiv/teams',
},
{
url: '/:language/about',
......@@ -86,19 +81,19 @@ Raven.context(() => {
},
{
url: '/:language/events',
view: () => m(eventList),
viewAsync: './views/events/eventList',
},
{
url: '/:language/events/:eventId',
view: vnode => m(eventList, vnode.attrs),
viewAsync: './views/events/eventList',
},
{
url: '/:language/jobs',
view: () => m(jobOfferList),
viewAsync: './views/jobs/jobofferList',
},
{
url: '/:language/jobs/:offerId',
view: vnode => m(jobOfferList, vnode.attrs),
viewAsync: './views/jobs/jobofferList',
},
{
url: '/:language/legal-notice',
......@@ -108,8 +103,46 @@ Raven.context(() => {
function onmatch(args, route) {
if (isLanguageValid(args.language)) {
if (route.view) {
return { view: vnode => m(layout, route.view(vnode)) };
}
return {
oninit() {
this.error = false;
import(/* webpackInclude: /\.js$/ */ `${route.viewAsync}`)
.then(loadedModule => {
this.loadedModule = loadedModule;
m.redraw();
})
.catch(() => {
this.error = true;
});
},
view(vnode) {
if (this.loadedModule) {
return m(layout, m(this.loadedModule.default, vnode.attrs));
}
if (this.error) {
return m(
layout,
m('.error', [
m('p', i18n('error.loadingPage')),
m(Button, {
className: 'blue-button',
name: 'retry',
label: i18n('retry'),
events: {
onclick: () => window.location.reload(),
},
}),
])
);
}
return m(layout, m('.loading', m(Spinner, { show: true, size: '96px' })));
},
};
}
return {
view() {
return m(layout, m(Error404));
......
......@@ -251,5 +251,6 @@ export default {
notFound: 'Die gewünschte Seite konnte nicht gefunden werden.',
translationUnavailable: 'Übersetzung nicht verfügbar.',
shownLanguage: 'Zeige Text in {{shown_language}}.',
loadingPage: 'Die gewünschte Seite konnte nicht geladen werden.',
},
};
......@@ -251,5 +251,6 @@ export default {
notFound: 'The page you are looking for could not be found.',
translationUnavailable: 'Translation not available.',
shownLanguage: 'Showing text in {{shown_language}}.',
loadingPage: 'Could not load the requested page.',
},
};
......@@ -67,6 +67,7 @@ section {
}
main {
position: relative;
width: 100%;
> * {
......@@ -74,6 +75,23 @@ main {
padding: 0 1em;
margin: 0 auto;
}
> .loading {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
> .error {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
text-align: center;
font-size: 2em;
color: rgba(0, 0, 0, .54);
}
}
h1 {
......
......@@ -64,3 +64,16 @@
margin-right: 1em;
}
}
.event-loading {
position: relative;
width: 100%;
height: 96px;
> * {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
}
import m from 'mithril';
import { currentLanguage } from '../../models/language';
import { Button } from 'polythene-mithril-button';
import Spinner from 'amiv-web-ui-components/src/spinner';
import { currentLanguage, i18n } from '../../models/language';
import contentUrlEnglish from '../../content/amiv/markdown/about.en.md';
import contentUrlGerman from '../../content/amiv/markdown/about.de.md';
// ensure that all markdown files are compiled
require.context('../../content/amiv/markdown');
export default class AMIV {
export default class Amiv {
oninit() {
this.content = '';
this._load();
this.content = null;
this.loaded = false;
this.constructor
._load()
.then(response => {
this.content = response;
})
.catch(() => {
this.error = true;
});
}
view() {
if (this.content) {
return m('div#about', m.trust(this.content));
}
async _load() {
if (this.content) return;
if (this.error) {
return m('.error', [
m('p', i18n('error.loadingPage')),
m(Button, {
className: 'blue-button',
name: 'retry',
label: i18n('retry'),
events: {
onclick: () => window.location.reload(),
},
}),
]);
}
return m('.loading', m(Spinner, { show: true, size: '96px' }));
}
this.content = await m.request({
url: `/amiv/about.${currentLanguage()}.html`,
static _load() {
return m.request({
url: `/${currentLanguage === 'de' ? contentUrlGerman : contentUrlEnglish}`,
method: 'GET',
deserialize: response => response,
});
......
import m from 'mithril';
import marked from 'marked';
import escape from 'html-escape';
import { Tabs } from '../../components';
import Tabs from '../../components/Tabs';
import { boardPortraits, boardImage } from '../../content/amiv/data/board_portraits';
import { boardTaskDescriptions } from '../../content/amiv/data/board_roles';
import { i18n, currentLanguage } from '../../models/language';
......@@ -49,7 +49,7 @@ class ImageGroup {
activeSelected: true,
autofit: true,
element: 'tab',
selectedTab: this._selectedTabIndex,
selectedTabIndex: this._selectedTabIndex,
onChange: data => {
this._selectedTabIndex = data.index;
},
......
import m from 'mithril';
import marked from 'marked';
import escape from 'html-escape';
import { Card, IconButton, Icon } from 'polythene-mithril';
import { Card } from 'polythene-mithril-card';
import { IconButton } from 'polythene-mithril-icon-button';
import { Icon } from 'polythene-mithril-icon';
import logos from '../../images/logos';
import { data as data_ressorts } from '../../content/amiv/data/ressorts';
import { data as data_commissions } from '../../content/amiv/data/commissions';
......
......@@ -2,7 +2,7 @@ import m from 'mithril';
import { Icon } from 'polythene-mithril';
import { i18n } from '../models/language';
import { login } from '../models/auth';
import { Button } from '../components';
import Button from '../components/Button';
import icons from '../images/icons';
/**
......
......@@ -2,11 +2,13 @@ import m from 'mithril';
import { Icon } from 'polythene-mithril';
import marked from 'marked';
import escape from 'html-escape';
import { Form, TextInput, Spinner } from 'amiv-web-ui-components';
import Form from 'amiv-web-ui-components/src/form';
import { TextInput } from 'amiv-web-ui-components/src/inputFields';
import Spinner from 'amiv-web-ui-components/src/spinner';
import { Infobox } from '../errors';
import { log } from '../../models/log';
import { isLoggedIn, login } from '../../models/auth';
import { Button } from '../../components';
import Button from '../../components/Button';
import { i18n, currentLocale } from '../../models/language';
import icons from '../../images/icons';
......
import m from 'mithril';
import { Icon } from 'polythene-mithril';
import { apiUrl } from 'config';
import { ExpansionPanel } from 'amiv-web-ui-components';
import ExpansionPanel from 'amiv-web-ui-components/src/expansionPanel';
import Spinner from 'amiv-web-ui-components/src/spinner';
import logos from '../../images/logos';
import { i18n, currentLocale } from '../../models/language';
import { EventController } from '../../models/events';
import { FilteredListPage, FilteredListDataStore } from '../filteredListPage';
import EventDetails from './eventDetails';
const controller = new EventController({}, true);
const dataStore = new FilteredListDataStore();
let eventDetailsModule;
/**
* EventList class
*
......@@ -204,7 +205,17 @@ export default class EventList extends FilteredListPage {
]),
content: ({ expanded }) => {
if (expanded) {
return m(EventDetails, { event });
if (eventDetailsModule) {
return m(eventDetailsModule.default, { event });
}
import(/* webpackInclude: /\.js$/ */ /* webpackChunkName: "event" */ './eventDetails').then(
loadedModule => {
eventDetailsModule = loadedModule;
m.redraw();
}
);
return m('.event-loading', m(Spinner, { show: true, size: '48px' }));
}
return m('');
},
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment