mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-03 12:02:53 +00:00
742 lines
21 KiB
TypeScript
742 lines
21 KiB
TypeScript
import {
|
|
SCAboutPageContentType,
|
|
SCConfigFile,
|
|
SCLanguageSetting,
|
|
SCSettingInputType,
|
|
SCThingOriginType,
|
|
SCThingType,
|
|
SCUserGroupSetting,
|
|
} from '@openstapps/core';
|
|
import {readFileSync} from 'fs';
|
|
import path from 'path';
|
|
|
|
/**
|
|
* Generates a range of numbers that represent consecutive calendric months
|
|
*
|
|
* @param startMonth The month to start with (inclusive)
|
|
* @param endMonth The month to end with (inclusive)
|
|
*/
|
|
export function yearSlice(startMonth: number, endMonth: number) {
|
|
let months = [...Array.from({length: 13}).keys()].slice(1);
|
|
months = [...months, ...months];
|
|
if (!months.includes(startMonth) || !months.includes(endMonth)) {
|
|
throw new Error(`Given months not part of a year! Check ${startMonth} or ${endMonth}!`);
|
|
}
|
|
|
|
const startIndex = months.indexOf(startMonth);
|
|
const endIndex =
|
|
months.indexOf(endMonth) <= startIndex ? months.lastIndexOf(endMonth) : months.indexOf(endMonth);
|
|
|
|
return months.slice(startIndex, endIndex + 1);
|
|
}
|
|
|
|
const sommerRange = yearSlice(3, 8);
|
|
const winterRange = yearSlice(9, 2);
|
|
const month = new Date().getMonth();
|
|
const year = new Date().getFullYear();
|
|
const winterYearOffset = month < winterRange[0] ? -1 : 0;
|
|
const sommerYear = year + (month <= winterRange[winterRange.length] ? -1 : 0);
|
|
const winterYear = `${year + winterYearOffset}/${(year + 1 + winterYearOffset).toString().slice(-2)}`;
|
|
|
|
const wsAcronymShort = `WS ${winterYear}`;
|
|
const ssAcronymShort = `SS ${sommerYear}`;
|
|
const wsAcronymLong = `WiSe ${winterYear}`;
|
|
const ssAcronymLong = `SoSe ${sommerYear}`;
|
|
|
|
const userGroupSetting: SCUserGroupSetting = {
|
|
categories: ['profile'],
|
|
defaultValue: 'students',
|
|
description:
|
|
'The user group the app is going to be used.' +
|
|
'This settings for example is getting used for the predefined price category of mensa meals.',
|
|
inputType: SCSettingInputType.SingleChoice,
|
|
name: 'group',
|
|
order: 1,
|
|
origin: {
|
|
indexed: '2018-09-11T12:30:00Z',
|
|
name: 'SCConfigFile Default Values',
|
|
type: SCThingOriginType.Remote,
|
|
},
|
|
translations: {
|
|
de: {
|
|
description:
|
|
'Mit welcher Benutzergruppe soll die App verwendet werden?' +
|
|
' Die Einstellung wird beispielsweise für die Vorauswahl der Preiskategorie der Mensa verwendet.',
|
|
name: 'Gruppe',
|
|
values: ['Studierende', 'Angestellte', 'Gäste'],
|
|
},
|
|
en: {
|
|
description:
|
|
'The user group the app is going to be used.' +
|
|
' This settings for example is getting used for the predefined price category of mensa meals.',
|
|
name: 'Group',
|
|
values: ['students', 'employees', 'guests'],
|
|
},
|
|
},
|
|
type: SCThingType.Setting,
|
|
uid: '2c97aa36-4aa2-43de-bc5d-a2b2cb3a530e',
|
|
values: ['students', 'employees', 'guests'],
|
|
};
|
|
|
|
const languageSetting: SCLanguageSetting = {
|
|
categories: ['profile'],
|
|
defaultValue: 'en',
|
|
description: 'The language this app is going to use.',
|
|
inputType: SCSettingInputType.SingleChoice,
|
|
name: 'language',
|
|
order: 0,
|
|
origin: {
|
|
indexed: '2018-09-11T12:30:00Z',
|
|
name: 'SCConfigFile Default Values',
|
|
type: SCThingOriginType.Remote,
|
|
},
|
|
translations: {
|
|
de: {
|
|
description: 'Die Sprache in der die App angezeigt wird.',
|
|
name: 'Sprache',
|
|
values: ['Deutsch', 'English'],
|
|
},
|
|
en: {
|
|
description: 'The language this app is going to use.',
|
|
name: 'Language',
|
|
values: ['Deutsch', 'English'],
|
|
},
|
|
},
|
|
type: SCThingType.Setting,
|
|
uid: 'dc9d6dec-6576-45ef-9e35-3598c0d6a662',
|
|
values: ['de', 'en'],
|
|
};
|
|
|
|
/**
|
|
* This is the default configuration for app and backend
|
|
*
|
|
* University specific files can be created with following naming scheme: default-<university license plate>.ts
|
|
*
|
|
* To select your university specific configuration which is merged from this default file and your university specific
|
|
* file, you have to supply the `NODE_APP_INSTANCE` environment variable with your license plate
|
|
*
|
|
* To get more information about the meaning of specific fields please have a look at `@openstapps/core` or use your
|
|
* IDE to read the TSDoc documentation.
|
|
*/
|
|
|
|
const config: SCConfigFile = {
|
|
app: {
|
|
aboutPages: {
|
|
'about': {
|
|
title: 'Über das Open StApps Projekt',
|
|
content: [
|
|
{
|
|
title: 'Verbundprojekt mehrerer Hochschulen für eine generische Studierenden-App',
|
|
content: {
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
value: `
|
|
Open StApps bietet Studierenden aller beteiligten Hochschulen eine qualitativ
|
|
hochwertige App für den Studienalltag. Open StApps-Verbundpartner integrieren
|
|
generalisierbare Studierendenprozesse so in App-Module, dass diese auch
|
|
von anderen Hochschulen verwendet werden können. Die in der Open StApps App
|
|
verwendeten Daten einer Datenquelle sind in einem generalisierten Datenmodell
|
|
so aufbereitet, dass ein Austausch oder Abschaltung der Datenquelle problemlos möglich
|
|
ist und die Open StApps App problemlos weiterhin funktionsfähig bleibt.
|
|
`,
|
|
translations: {
|
|
en: {
|
|
value: `
|
|
Open StApps provides students from all participating universities with a
|
|
high-quality app for everyday study. Open StApps partners integrate
|
|
generalizable student processes into app modules in such a way that they can be
|
|
can be used by other universities. The data of a data source used in the Open StApps app
|
|
is prepared in a generalized data model in a way that the data source can be easily
|
|
exchanged or switched off while the app continues to function without any problems.
|
|
`,
|
|
},
|
|
},
|
|
},
|
|
translations: {
|
|
en: {
|
|
title: 'Collaborative project of multiple universities for a single generic study app',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.SECTION,
|
|
},
|
|
{
|
|
title: 'Universitätskontakt',
|
|
content: {
|
|
rows: [
|
|
[
|
|
{
|
|
value: 'Adresse',
|
|
translations: {
|
|
en: {
|
|
value: 'address',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
{
|
|
value: `
|
|
Nirmasi Universität<br>
|
|
Abteilung für digitale Angelegenheiten (AbtDigi)<br>
|
|
Null Island 1<br>
|
|
999999 Atlantic Ocean
|
|
`,
|
|
translations: {
|
|
en: {
|
|
value: 'This would be the english address',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
value: 'Kontaktinformationen',
|
|
translations: {
|
|
en: {
|
|
value: 'Contact information',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
{
|
|
value: '[mail]()<br>' + '[+49 12 345 67890]()<br>' + '[https://localhost/]()',
|
|
translations: {
|
|
en: {
|
|
value: 'This would be the english contact information',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
],
|
|
],
|
|
type: SCAboutPageContentType.TABLE,
|
|
},
|
|
translations: {
|
|
en: {
|
|
title: 'Nimrasi-Uni Kontakt',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.SECTION,
|
|
},
|
|
{
|
|
icon: 'campaign',
|
|
title: 'Neue Funktionen / Gelöste Probleme',
|
|
link: 'changelog',
|
|
translations: {
|
|
en: {
|
|
title: 'Changelog / Resolved issues',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.ROUTER_LINK,
|
|
},
|
|
{
|
|
icon: 'description',
|
|
title: 'Impressum',
|
|
link: 'imprint',
|
|
translations: {
|
|
en: {
|
|
title: 'Imprint',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.ROUTER_LINK,
|
|
},
|
|
{
|
|
icon: 'policy',
|
|
title: 'Datenschutz',
|
|
link: 'privacy',
|
|
translations: {
|
|
en: {
|
|
title: 'Privacy policy',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.ROUTER_LINK,
|
|
},
|
|
{
|
|
icon: 'copyright',
|
|
title: 'Bibliotheken und Lizenzen',
|
|
link: 'licenses',
|
|
translations: {
|
|
en: {
|
|
title: 'Libraries and licenses',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.ROUTER_LINK,
|
|
},
|
|
],
|
|
translations: {
|
|
en: {
|
|
title: 'About',
|
|
},
|
|
},
|
|
},
|
|
'about/imprint': {
|
|
title: 'Impressum',
|
|
content: [
|
|
{
|
|
title: 'Beteiligte Universitäten',
|
|
card: true,
|
|
content: {
|
|
value: `
|
|
[Johann Wolfgang Goethe-Universität Frankfurt am Main](https://uni-frankfurt.de)<br>
|
|
[Philipps-Universität Marburg](https://www.uni-marburg.de)<br>
|
|
[Technische Hochschule Mittelhessen](https://www.thm.de)<br>
|
|
[Universität Kassel](https://www.uni-kassel.de)<br>
|
|
weitere Hochschulen und Mitarbeitende
|
|
`,
|
|
translations: {
|
|
en: {
|
|
value: `
|
|
[Goethe University Frankfurt](https://uni-frankfurt.de)<br>
|
|
[University of Marburg](https://www.uni-marburg.de)<br>
|
|
[University of Applied Sciences Mittelhessen](https://www.thm.de)<br>
|
|
[University of Kassel](https://www.uni-kassel.de)<br>
|
|
further universities and developers
|
|
`,
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
translations: {
|
|
en: {
|
|
title: 'Collaborating Universities',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.SECTION,
|
|
},
|
|
],
|
|
translations: {
|
|
en: {
|
|
title: 'Imprint',
|
|
},
|
|
},
|
|
},
|
|
'about/privacy': {
|
|
title: 'Datenschutz',
|
|
content: [
|
|
{
|
|
value: 'Hier wäre der Datenschutz',
|
|
translations: {
|
|
en: {
|
|
value: 'This would be the privacy policy',
|
|
},
|
|
},
|
|
type: SCAboutPageContentType.MARKDOWN,
|
|
},
|
|
],
|
|
translations: {
|
|
en: {
|
|
title: 'Privacy Policy',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
campusPolygon: {
|
|
coordinates: [
|
|
[
|
|
[8.660_432_999_690_723, 50.123_027_017_044_436],
|
|
[8.675_496_285_518_358, 50.123_027_017_044_436],
|
|
[8.675_496_285_518_358, 50.130_661_764_486_42],
|
|
[8.660_432_999_690_723, 50.130_661_764_486_42],
|
|
[8.660_432_999_690_723, 50.123_027_017_044_436],
|
|
],
|
|
],
|
|
type: 'Polygon',
|
|
},
|
|
features: {},
|
|
menus: [
|
|
{
|
|
icon: 'home',
|
|
items: [
|
|
{
|
|
icon: 'newspaper',
|
|
route: '/news',
|
|
title: 'news',
|
|
translations: {
|
|
de: {
|
|
title: 'Aktuelles',
|
|
},
|
|
en: {
|
|
title: 'news',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'search',
|
|
route: '/search',
|
|
title: 'search',
|
|
translations: {
|
|
de: {
|
|
title: 'Suche',
|
|
},
|
|
en: {
|
|
title: 'search',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'local_library',
|
|
route: '/hebis-search',
|
|
title: 'library catalog',
|
|
translations: {
|
|
de: {
|
|
title: 'Bibliothekskatalog',
|
|
},
|
|
en: {
|
|
title: 'library catalog',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'inventory_2',
|
|
route: '/catalog',
|
|
title: 'course catalog',
|
|
translations: {
|
|
de: {
|
|
title: 'Vorlesungsverzeichnis',
|
|
},
|
|
en: {
|
|
title: 'course catalog',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
title: 'overview',
|
|
route: '/overview',
|
|
translations: {
|
|
de: {
|
|
title: 'Übersicht',
|
|
},
|
|
en: {
|
|
title: 'overview',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'local_cafe',
|
|
items: [],
|
|
route: '/canteen',
|
|
title: 'canteen',
|
|
translations: {
|
|
de: {
|
|
title: 'Mensa',
|
|
},
|
|
en: {
|
|
title: 'canteen',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'map',
|
|
items: [],
|
|
route: '/map',
|
|
title: 'campus map',
|
|
translations: {
|
|
de: {
|
|
title: 'Campus Karte',
|
|
},
|
|
en: {
|
|
title: 'campus map',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'school',
|
|
items: [
|
|
{
|
|
icon: 'grade',
|
|
route: '/favorites',
|
|
title: 'favorites',
|
|
translations: {
|
|
de: {
|
|
title: 'Favoriten',
|
|
},
|
|
en: {
|
|
title: 'favorites',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'calendar_today',
|
|
route: '/schedule',
|
|
title: 'schedule',
|
|
translations: {
|
|
de: {
|
|
title: 'Stundenplan',
|
|
},
|
|
en: {
|
|
title: 'schedule',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
authProvider: 'paia',
|
|
icon: 'badge',
|
|
route: '/library-account',
|
|
title: 'library account',
|
|
translations: {
|
|
de: {
|
|
title: 'Bibliothekskonto',
|
|
},
|
|
en: {
|
|
title: 'library account',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'settings',
|
|
route: '/settings',
|
|
title: 'settings',
|
|
translations: {
|
|
de: {
|
|
title: 'Einstellungen',
|
|
},
|
|
en: {
|
|
title: 'settings',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'rate_review',
|
|
route: '/feedback',
|
|
title: 'feedback',
|
|
translations: {
|
|
de: {
|
|
title: 'Feedback',
|
|
},
|
|
en: {
|
|
title: 'feedback',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
icon: 'info',
|
|
route: '/about',
|
|
title: 'about',
|
|
translations: {
|
|
de: {
|
|
title: 'Über die App',
|
|
},
|
|
en: {
|
|
title: 'About the App',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
title: 'my app',
|
|
route: '/profile',
|
|
translations: {
|
|
de: {
|
|
title: 'Meine App',
|
|
},
|
|
en: {
|
|
title: 'my app',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
name: 'Goethe-Uni',
|
|
privacyPolicyUrl: 'https://mobile.server.uni-frankfurt.de/_static/privacy.md',
|
|
settings: [userGroupSetting, languageSetting],
|
|
},
|
|
auth: {},
|
|
backend: {
|
|
SCVersion: JSON.parse(readFileSync(path.resolve('.', '.', 'package.json'), 'utf8').toString())
|
|
.dependencies['@openstapps/core'],
|
|
externalRequestTimeout: 5000,
|
|
hiddenTypes: [SCThingType.DateSeries, SCThingType.Diff, SCThingType.Floor],
|
|
mappingIgnoredTags: ['minlength', 'pattern', 'see', 'tjs-format'],
|
|
maxMultiSearchRouteQueries: 5,
|
|
maxRequestBodySize: 512 * 1024,
|
|
name: 'Goethe-Universität Frankfurt am Main',
|
|
namespace: '909a8cbc-8520-456c-b474-ef1525f14209',
|
|
sortableFields: [
|
|
{
|
|
fieldName: 'name',
|
|
sortTypes: ['ducet'],
|
|
},
|
|
{
|
|
fieldName: 'type',
|
|
sortTypes: ['ducet'],
|
|
},
|
|
{
|
|
fieldName: 'categories',
|
|
onlyOnTypes: [
|
|
SCThingType.AcademicEvent,
|
|
SCThingType.Building,
|
|
SCThingType.Catalog,
|
|
SCThingType.Dish,
|
|
SCThingType.PointOfInterest,
|
|
SCThingType.Room,
|
|
],
|
|
sortTypes: ['ducet'],
|
|
},
|
|
{
|
|
fieldName: 'geo',
|
|
onlyOnTypes: [SCThingType.Building, SCThingType.PointOfInterest, SCThingType.Room],
|
|
sortTypes: ['distance'],
|
|
},
|
|
{
|
|
fieldName: 'geo',
|
|
onlyOnTypes: [SCThingType.Building, SCThingType.PointOfInterest, SCThingType.Room],
|
|
sortTypes: ['distance'],
|
|
},
|
|
{
|
|
fieldName: 'inPlace.geo',
|
|
onlyOnTypes: [
|
|
SCThingType.DateSeries,
|
|
SCThingType.Dish,
|
|
SCThingType.Floor,
|
|
SCThingType.Organization,
|
|
SCThingType.PointOfInterest,
|
|
SCThingType.Room,
|
|
SCThingType.Ticket,
|
|
],
|
|
sortTypes: ['distance'],
|
|
},
|
|
{
|
|
fieldName: 'offers',
|
|
onlyOnTypes: [SCThingType.Dish],
|
|
sortTypes: ['price'],
|
|
},
|
|
],
|
|
},
|
|
internal: {
|
|
aggregations: [
|
|
{
|
|
fieldName: 'categories',
|
|
onlyOnTypes: [
|
|
SCThingType.AcademicEvent,
|
|
SCThingType.Article,
|
|
SCThingType.Building,
|
|
SCThingType.Catalog,
|
|
SCThingType.Dish,
|
|
SCThingType.PointOfInterest,
|
|
SCThingType.Room,
|
|
],
|
|
},
|
|
{
|
|
fieldName: 'inPlace.name',
|
|
onlyOnTypes: [
|
|
SCThingType.DateSeries,
|
|
SCThingType.Dish,
|
|
SCThingType.Floor,
|
|
SCThingType.Organization,
|
|
SCThingType.PointOfInterest,
|
|
SCThingType.Room,
|
|
SCThingType.Ticket,
|
|
],
|
|
},
|
|
{
|
|
fieldName: 'academicTerms.acronym',
|
|
onlyOnTypes: [SCThingType.AcademicEvent, SCThingType.SportCourse],
|
|
},
|
|
{
|
|
fieldName: 'academicTerm.acronym',
|
|
onlyOnTypes: [SCThingType.Catalog],
|
|
},
|
|
{
|
|
fieldName: 'majors',
|
|
onlyOnTypes: [SCThingType.AcademicEvent],
|
|
},
|
|
{
|
|
fieldName: 'keywords',
|
|
onlyOnTypes: [SCThingType.Article, SCThingType.Book, SCThingType.Message, SCThingType.Video],
|
|
},
|
|
{
|
|
fieldName: 'type',
|
|
},
|
|
],
|
|
boostings: {
|
|
default: [
|
|
{
|
|
factor: 1,
|
|
fields: {
|
|
'academicTerms.acronym': {
|
|
[ssAcronymShort]: sommerRange.includes(month) ? 1.1 : 1.05,
|
|
[wsAcronymShort]: winterRange.includes(month) ? 1.1 : 1.05,
|
|
[ssAcronymLong]: sommerRange.includes(month) ? 1.1 : 1.05,
|
|
[wsAcronymLong]: winterRange.includes(month) ? 1.1 : 1.05,
|
|
},
|
|
},
|
|
type: SCThingType.AcademicEvent,
|
|
},
|
|
{
|
|
factor: 1,
|
|
fields: {
|
|
categories: {
|
|
'course': 1.08,
|
|
'integrated course': 1.08,
|
|
'introductory class': 1.05,
|
|
'lecture': 1.1,
|
|
'seminar': 1.01,
|
|
'tutorial': 1.05,
|
|
},
|
|
},
|
|
type: SCThingType.AcademicEvent,
|
|
},
|
|
{
|
|
factor: 1.6,
|
|
type: SCThingType.Building,
|
|
},
|
|
{
|
|
factor: 1,
|
|
fields: {
|
|
categories: {
|
|
cafe: 1.1,
|
|
learn: 1.1,
|
|
library: 1.2,
|
|
restaurant: 1.1,
|
|
},
|
|
},
|
|
type: SCThingType.PointOfInterest,
|
|
},
|
|
{
|
|
factor: 1,
|
|
fields: {
|
|
categories: {
|
|
'main dish': 2,
|
|
},
|
|
},
|
|
type: SCThingType.Dish,
|
|
},
|
|
],
|
|
dining: [
|
|
{
|
|
factor: 1,
|
|
fields: {
|
|
categories: {
|
|
'cafe': 2,
|
|
'canteen': 2,
|
|
'restaurant': 2,
|
|
'restroom': 1.2,
|
|
'student canteen': 2,
|
|
},
|
|
},
|
|
type: SCThingType.Building,
|
|
},
|
|
{
|
|
factor: 2,
|
|
type: SCThingType.Dish,
|
|
},
|
|
],
|
|
place: [
|
|
{
|
|
factor: 2,
|
|
type: SCThingType.Building,
|
|
},
|
|
{
|
|
factor: 2,
|
|
type: SCThingType.PointOfInterest,
|
|
},
|
|
{
|
|
factor: 2,
|
|
type: SCThingType.Room,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
uid: 'f-u',
|
|
};
|
|
|
|
// tslint:disable-next-line:no-default-export
|
|
export default config;
|