mirror of
https://github.com/Mueller-Patrick/DHBW-Service-App.git
synced 2026-05-26 12:38:05 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d7f078cc88 | |||
| 805495fb81 | |||
| f5756cd650 | |||
| ba0d4da657 | |||
| b689a7bbf1 | |||
| f50ba8f19d | |||
| e5ecb6bb60 | |||
| a3871f87da | |||
| 5e177eedd5 | |||
| 797046ddcc | |||
| 3323dcac5a |
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Device Information:**
|
||||||
|
- Device: [e.g. iPhone 12]
|
||||||
|
- OS: [e.g. iOS 14.1]
|
||||||
|
- App Version [e.g. 1.0]
|
||||||
|
|
||||||
|
**Beta Information:**
|
||||||
|
If you are participating in the TestFlight Beta program, please provide the following information:
|
||||||
|
- Build No.: [e.g. 1.0.12]
|
||||||
|
- Have you already submitted feedback via TestFlight? [yes/no]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[REQ]"
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
CD2FC0C625A869FE00963178 /* dhbw-standard-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C125A869FE00963178 /* dhbw-standard-icon@3x.png */; };
|
CD2FC0C625A869FE00963178 /* dhbw-standard-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C125A869FE00963178 /* dhbw-standard-icon@3x.png */; };
|
||||||
CD2FC0C725A869FE00963178 /* alpaca-alt-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C325A869FE00963178 /* alpaca-alt-icon@2x.png */; };
|
CD2FC0C725A869FE00963178 /* alpaca-alt-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C325A869FE00963178 /* alpaca-alt-icon@2x.png */; };
|
||||||
CD2FC0C825A869FE00963178 /* alpaca-alt-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C425A869FE00963178 /* alpaca-alt-icon@3x.png */; };
|
CD2FC0C825A869FE00963178 /* alpaca-alt-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2FC0C425A869FE00963178 /* alpaca-alt-icon@3x.png */; };
|
||||||
|
CD67FB2A25D45A3300069CDB /* RaPlaEvent+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD67FB2925D45A3300069CDB /* RaPlaEvent+CoreDataProperties.swift */; };
|
||||||
CD730A35259A860E00E0BB69 /* SettingsAcknowledgements.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD730A34259A860E00E0BB69 /* SettingsAcknowledgements.swift */; };
|
CD730A35259A860E00E0BB69 /* SettingsAcknowledgements.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD730A34259A860E00E0BB69 /* SettingsAcknowledgements.swift */; };
|
||||||
CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8555BD25C47AE500C4ACD6 /* RaPlaFetcher.swift */; };
|
CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8555BD25C47AE500C4ACD6 /* RaPlaFetcher.swift */; };
|
||||||
CD8555C325C47B5300C4ACD6 /* ApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8555C225C47B5300C4ACD6 /* ApiService.swift */; };
|
CD8555C325C47B5300C4ACD6 /* ApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8555C225C47B5300C4ACD6 /* ApiService.swift */; };
|
||||||
@@ -23,10 +24,15 @@
|
|||||||
CD9FAB8D258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD9FAB8B258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld */; };
|
CD9FAB8D258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD9FAB8B258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld */; };
|
||||||
CD9FAB98258EC60600D6D0C5 /* DHBW_ServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9FAB97258EC60600D6D0C5 /* DHBW_ServiceTests.swift */; };
|
CD9FAB98258EC60600D6D0C5 /* DHBW_ServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9FAB97258EC60600D6D0C5 /* DHBW_ServiceTests.swift */; };
|
||||||
CD9FABA3258EC60600D6D0C5 /* DHBW_ServiceUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9FABA2258EC60600D6D0C5 /* DHBW_ServiceUITests.swift */; };
|
CD9FABA3258EC60600D6D0C5 /* DHBW_ServiceUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9FABA2258EC60600D6D0C5 /* DHBW_ServiceUITests.swift */; };
|
||||||
|
CDA1CBAE25D4591000DB2AE5 /* User+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA1CBA825D4591000DB2AE5 /* User+CoreDataProperties.swift */; };
|
||||||
|
CDA1CBB025D4591000DB2AE5 /* Lecturer+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA1CBAA25D4591000DB2AE5 /* Lecturer+CoreDataProperties.swift */; };
|
||||||
CDCD721A25912E1200FBF2F5 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD721925912E1200FBF2F5 /* HomeView.swift */; };
|
CDCD721A25912E1200FBF2F5 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD721925912E1200FBF2F5 /* HomeView.swift */; };
|
||||||
CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD72232591316500FBF2F5 /* LocalSettings.swift */; };
|
CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD72232591316500FBF2F5 /* LocalSettings.swift */; };
|
||||||
CDCD7230259135C500FBF2F5 /* FirstOpeningSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD722F259135C500FBF2F5 /* FirstOpeningSettings.swift */; };
|
CDCD7230259135C500FBF2F5 /* FirstOpeningSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCD722F259135C500FBF2F5 /* FirstOpeningSettings.swift */; };
|
||||||
CDD39B4B259A64150078D05F /* SettingsMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD39B4A259A64150078D05F /* SettingsMain.swift */; };
|
CDD39B4B259A64150078D05F /* SettingsMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD39B4A259A64150078D05F /* SettingsMain.swift */; };
|
||||||
|
CDD970DD25D453D90061755E /* User+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD970D725D453D90061755E /* User+CoreDataClass.swift */; };
|
||||||
|
CDD970DF25D453D90061755E /* Lecturer+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD970D925D453D90061755E /* Lecturer+CoreDataClass.swift */; };
|
||||||
|
CDD970E125D453D90061755E /* RaPlaEvent+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD970DB25D453D90061755E /* RaPlaEvent+CoreDataClass.swift */; };
|
||||||
CDDCF47B2591FE550027CDC5 /* UtilityFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF47A2591FE550027CDC5 /* UtilityFunctions.swift */; };
|
CDDCF47B2591FE550027CDC5 /* UtilityFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF47A2591FE550027CDC5 /* UtilityFunctions.swift */; };
|
||||||
CDDCF4842592028A0027CDC5 /* Localizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF4832592028A0027CDC5 /* Localizer.swift */; };
|
CDDCF4842592028A0027CDC5 /* Localizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF4832592028A0027CDC5 /* Localizer.swift */; };
|
||||||
CDDCF493259203390027CDC5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF495259203390027CDC5 /* Localizable.strings */; };
|
CDDCF493259203390027CDC5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF495259203390027CDC5 /* Localizable.strings */; };
|
||||||
@@ -59,6 +65,7 @@
|
|||||||
CD2FC0C125A869FE00963178 /* dhbw-standard-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dhbw-standard-icon@3x.png"; sourceTree = "<group>"; };
|
CD2FC0C125A869FE00963178 /* dhbw-standard-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dhbw-standard-icon@3x.png"; sourceTree = "<group>"; };
|
||||||
CD2FC0C325A869FE00963178 /* alpaca-alt-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "alpaca-alt-icon@2x.png"; sourceTree = "<group>"; };
|
CD2FC0C325A869FE00963178 /* alpaca-alt-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "alpaca-alt-icon@2x.png"; sourceTree = "<group>"; };
|
||||||
CD2FC0C425A869FE00963178 /* alpaca-alt-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "alpaca-alt-icon@3x.png"; sourceTree = "<group>"; };
|
CD2FC0C425A869FE00963178 /* alpaca-alt-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "alpaca-alt-icon@3x.png"; sourceTree = "<group>"; };
|
||||||
|
CD67FB2925D45A3300069CDB /* RaPlaEvent+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RaPlaEvent+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||||
CD730A34259A860E00E0BB69 /* SettingsAcknowledgements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAcknowledgements.swift; sourceTree = "<group>"; };
|
CD730A34259A860E00E0BB69 /* SettingsAcknowledgements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAcknowledgements.swift; sourceTree = "<group>"; };
|
||||||
CD8555BD25C47AE500C4ACD6 /* RaPlaFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RaPlaFetcher.swift; sourceTree = "<group>"; };
|
CD8555BD25C47AE500C4ACD6 /* RaPlaFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RaPlaFetcher.swift; sourceTree = "<group>"; };
|
||||||
CD8555C225C47B5300C4ACD6 /* ApiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiService.swift; sourceTree = "<group>"; };
|
CD8555C225C47B5300C4ACD6 /* ApiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiService.swift; sourceTree = "<group>"; };
|
||||||
@@ -76,10 +83,15 @@
|
|||||||
CD9FAB9E258EC60600D6D0C5 /* DHBW-ServiceUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DHBW-ServiceUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
CD9FAB9E258EC60600D6D0C5 /* DHBW-ServiceUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DHBW-ServiceUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
CD9FABA2258EC60600D6D0C5 /* DHBW_ServiceUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DHBW_ServiceUITests.swift; sourceTree = "<group>"; };
|
CD9FABA2258EC60600D6D0C5 /* DHBW_ServiceUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DHBW_ServiceUITests.swift; sourceTree = "<group>"; };
|
||||||
CD9FABA4258EC60600D6D0C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
CD9FABA4258EC60600D6D0C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
CDA1CBA825D4591000DB2AE5 /* User+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "User+CoreDataProperties.swift"; path = "DHBW-Service/CoreData/Models/User+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
|
CDA1CBAA25D4591000DB2AE5 /* Lecturer+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Lecturer+CoreDataProperties.swift"; path = "DHBW-Service/CoreData/Models/Lecturer+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
CDCD721925912E1200FBF2F5 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
CDCD721925912E1200FBF2F5 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
||||||
CDCD72232591316500FBF2F5 /* LocalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalSettings.swift; sourceTree = "<group>"; };
|
CDCD72232591316500FBF2F5 /* LocalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalSettings.swift; sourceTree = "<group>"; };
|
||||||
CDCD722F259135C500FBF2F5 /* FirstOpeningSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstOpeningSettings.swift; sourceTree = "<group>"; };
|
CDCD722F259135C500FBF2F5 /* FirstOpeningSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstOpeningSettings.swift; sourceTree = "<group>"; };
|
||||||
CDD39B4A259A64150078D05F /* SettingsMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMain.swift; sourceTree = "<group>"; };
|
CDD39B4A259A64150078D05F /* SettingsMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMain.swift; sourceTree = "<group>"; };
|
||||||
|
CDD970D725D453D90061755E /* User+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||||
|
CDD970D925D453D90061755E /* Lecturer+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Lecturer+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||||
|
CDD970DB25D453D90061755E /* RaPlaEvent+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RaPlaEvent+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||||
CDDCF47A2591FE550027CDC5 /* UtilityFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityFunctions.swift; sourceTree = "<group>"; };
|
CDDCF47A2591FE550027CDC5 /* UtilityFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityFunctions.swift; sourceTree = "<group>"; };
|
||||||
CDDCF4832592028A0027CDC5 /* Localizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Localizer.swift; sourceTree = "<group>"; };
|
CDDCF4832592028A0027CDC5 /* Localizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Localizer.swift; sourceTree = "<group>"; };
|
||||||
CDDCF494259203390027CDC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
CDDCF494259203390027CDC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
@@ -115,6 +127,19 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
CD1ED26325D33B590030B647 /* Models */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CDD970D925D453D90061755E /* Lecturer+CoreDataClass.swift */,
|
||||||
|
CDA1CBAA25D4591000DB2AE5 /* Lecturer+CoreDataProperties.swift */,
|
||||||
|
CDD970DB25D453D90061755E /* RaPlaEvent+CoreDataClass.swift */,
|
||||||
|
CD67FB2925D45A3300069CDB /* RaPlaEvent+CoreDataProperties.swift */,
|
||||||
|
CDD970D725D453D90061755E /* User+CoreDataClass.swift */,
|
||||||
|
CDA1CBA825D4591000DB2AE5 /* User+CoreDataProperties.swift */,
|
||||||
|
);
|
||||||
|
path = Models;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
CD2FC0BD25A869F000963178 /* res */ = {
|
CD2FC0BD25A869F000963178 /* res */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -239,6 +264,7 @@
|
|||||||
CDCD721125912D5400FBF2F5 /* CoreData */ = {
|
CDCD721125912D5400FBF2F5 /* CoreData */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CD1ED26325D33B590030B647 /* Models */,
|
||||||
CD9FAB8B258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld */,
|
CD9FAB8B258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld */,
|
||||||
CD9FAB89258EC60600D6D0C5 /* Persistence.swift */,
|
CD9FAB89258EC60600D6D0C5 /* Persistence.swift */,
|
||||||
);
|
);
|
||||||
@@ -443,19 +469,25 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
CDDCF4842592028A0027CDC5 /* Localizer.swift in Sources */,
|
CDDCF4842592028A0027CDC5 /* Localizer.swift in Sources */,
|
||||||
|
CDD970DF25D453D90061755E /* Lecturer+CoreDataClass.swift in Sources */,
|
||||||
CDCD7230259135C500FBF2F5 /* FirstOpeningSettings.swift in Sources */,
|
CDCD7230259135C500FBF2F5 /* FirstOpeningSettings.swift in Sources */,
|
||||||
|
CDA1CBB025D4591000DB2AE5 /* Lecturer+CoreDataProperties.swift in Sources */,
|
||||||
CD9FAB8A258EC60600D6D0C5 /* Persistence.swift in Sources */,
|
CD9FAB8A258EC60600D6D0C5 /* Persistence.swift in Sources */,
|
||||||
CD730A35259A860E00E0BB69 /* SettingsAcknowledgements.swift in Sources */,
|
CD730A35259A860E00E0BB69 /* SettingsAcknowledgements.swift in Sources */,
|
||||||
CD9FAB83258EC60200D6D0C5 /* ContentView.swift in Sources */,
|
CD9FAB83258EC60200D6D0C5 /* ContentView.swift in Sources */,
|
||||||
CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */,
|
CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */,
|
||||||
|
CDD970E125D453D90061755E /* RaPlaEvent+CoreDataClass.swift in Sources */,
|
||||||
|
CDD970DD25D453D90061755E /* User+CoreDataClass.swift in Sources */,
|
||||||
CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.swift in Sources */,
|
CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.swift in Sources */,
|
||||||
CDEA70C025C85999001CFE28 /* LecturePlanItem.swift in Sources */,
|
CDEA70C025C85999001CFE28 /* LecturePlanItem.swift in Sources */,
|
||||||
CD8555C325C47B5300C4ACD6 /* ApiService.swift in Sources */,
|
CD8555C325C47B5300C4ACD6 /* ApiService.swift in Sources */,
|
||||||
CD9FAB8D258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld in Sources */,
|
CD9FAB8D258EC60600D6D0C5 /* DHBW_Service.xcdatamodeld in Sources */,
|
||||||
CDCD721A25912E1200FBF2F5 /* HomeView.swift in Sources */,
|
CDCD721A25912E1200FBF2F5 /* HomeView.swift in Sources */,
|
||||||
CDD39B4B259A64150078D05F /* SettingsMain.swift in Sources */,
|
CDD39B4B259A64150078D05F /* SettingsMain.swift in Sources */,
|
||||||
|
CD67FB2A25D45A3300069CDB /* RaPlaEvent+CoreDataProperties.swift in Sources */,
|
||||||
CDEA70B225C6054F001CFE28 /* LecturePlanList.swift in Sources */,
|
CDEA70B225C6054F001CFE28 /* LecturePlanList.swift in Sources */,
|
||||||
CDDCF47B2591FE550027CDC5 /* UtilityFunctions.swift in Sources */,
|
CDDCF47B2591FE550027CDC5 /* UtilityFunctions.swift in Sources */,
|
||||||
|
CDA1CBAE25D4591000DB2AE5 /* User+CoreDataProperties.swift in Sources */,
|
||||||
CD9FAB81258EC60200D6D0C5 /* DHBW_ServiceApp.swift in Sources */,
|
CD9FAB81258EC60200D6D0C5 /* DHBW_ServiceApp.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17709" systemVersion="20D62" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17709" systemVersion="20D62" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="RaPlaEvent" representedClassName="RaPlaEvent" syncable="YES" codeGenerationType="class">
|
<entity name="Lecturer" representedClassName="Lecturer" syncable="YES">
|
||||||
|
<attribute name="email" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="name" optional="YES" attributeType="String"/>
|
||||||
|
<relationship name="event" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RaPlaEvent" inverseName="lecturers" inverseEntity="RaPlaEvent"/>
|
||||||
|
</entity>
|
||||||
|
<entity name="RaPlaEvent" representedClassName="RaPlaEvent" syncable="YES">
|
||||||
<attribute name="category" optional="YES" attributeType="String"/>
|
<attribute name="category" optional="YES" attributeType="String"/>
|
||||||
<attribute name="descr" optional="YES" attributeType="String"/>
|
<attribute name="descr" optional="YES" attributeType="String"/>
|
||||||
<attribute name="endDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="endDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
@@ -9,14 +14,16 @@
|
|||||||
<attribute name="startDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="startDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="summary" optional="YES" attributeType="String"/>
|
<attribute name="summary" optional="YES" attributeType="String"/>
|
||||||
<attribute name="uid" optional="YES" attributeType="String"/>
|
<attribute name="uid" optional="YES" attributeType="String"/>
|
||||||
|
<relationship name="lecturers" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Lecturer" inverseName="event" inverseEntity="Lecturer"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="User" representedClassName="User" syncable="YES" codeGenerationType="class">
|
<entity name="User" representedClassName="User" syncable="YES">
|
||||||
<attribute name="course" optional="YES" attributeType="String"/>
|
<attribute name="course" optional="YES" attributeType="String"/>
|
||||||
<attribute name="director" optional="YES" attributeType="String"/>
|
<attribute name="director" optional="YES" attributeType="String"/>
|
||||||
<attribute name="name" optional="YES" attributeType="String"/>
|
<attribute name="name" optional="YES" attributeType="String"/>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="RaPlaEvent" positionX="-63" positionY="9" width="128" height="149"/>
|
<element name="Lecturer" positionX="-351" positionY="99" width="128" height="74"/>
|
||||||
<element name="User" positionX="-63" positionY="-9" width="128" height="74"/>
|
<element name="RaPlaEvent" positionX="-271.3642578125" positionY="83.64776611328125" width="128" height="164"/>
|
||||||
|
<element name="User" positionX="-428.6358032226562" positionY="2.067169189453125" width="128" height="74"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// Lecturer+CoreDataClass.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
@objc(Lecturer)
|
||||||
|
public class Lecturer: NSManagedObject {
|
||||||
|
// MARK: Access methods
|
||||||
|
@nonobjc public class func getAll() -> [Lecturer] {
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(Lecturer.fetchRequest())
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [Lecturer]{
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
let fetchRequest: NSFetchRequest = Lecturer.fetchRequest()
|
||||||
|
|
||||||
|
fetchRequest.sortDescriptors = sortDescriptors
|
||||||
|
if(searchPredicate != nil) {
|
||||||
|
fetchRequest.predicate = searchPredicate
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(fetchRequest)
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Wrappers
|
||||||
|
public var wrappedName: String {
|
||||||
|
name ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
|
public var wrappedEmail: String {
|
||||||
|
email ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Lecturer+CoreDataProperties.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
|
extension Lecturer {
|
||||||
|
|
||||||
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<Lecturer> {
|
||||||
|
return NSFetchRequest<Lecturer>(entityName: "Lecturer")
|
||||||
|
}
|
||||||
|
|
||||||
|
@NSManaged public var email: String?
|
||||||
|
@NSManaged public var name: String?
|
||||||
|
@NSManaged public var event: RaPlaEvent?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Lecturer : Identifiable {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// RaPlaEvent+CoreDataClass.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
@objc(RaPlaEvent)
|
||||||
|
public class RaPlaEvent: NSManagedObject {
|
||||||
|
|
||||||
|
// MARK: Access methods
|
||||||
|
@nonobjc public class func getAll() -> [RaPlaEvent] {
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(RaPlaEvent.fetchRequest())
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [RaPlaEvent]{
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
let fetchRequest: NSFetchRequest = RaPlaEvent.fetchRequest()
|
||||||
|
|
||||||
|
fetchRequest.sortDescriptors = sortDescriptors
|
||||||
|
if(searchPredicate != nil) {
|
||||||
|
fetchRequest.predicate = searchPredicate
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(fetchRequest)
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Wrappers
|
||||||
|
public var lecturerList: [Lecturer] {
|
||||||
|
let set = lecturers as? Set<Lecturer> ?? []
|
||||||
|
return set.sorted {
|
||||||
|
$0.wrappedName < $1.wrappedName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// RaPlaEvent+CoreDataProperties.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
|
extension RaPlaEvent {
|
||||||
|
|
||||||
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<RaPlaEvent> {
|
||||||
|
return NSFetchRequest<RaPlaEvent>(entityName: "RaPlaEvent")
|
||||||
|
}
|
||||||
|
|
||||||
|
@NSManaged public var category: String?
|
||||||
|
@NSManaged public var descr: String?
|
||||||
|
@NSManaged public var endDate: Date?
|
||||||
|
@NSManaged public var isHidden: Bool
|
||||||
|
@NSManaged public var location: String?
|
||||||
|
@NSManaged public var startDate: Date?
|
||||||
|
@NSManaged public var summary: String?
|
||||||
|
@NSManaged public var uid: String?
|
||||||
|
@NSManaged public var lecturers: NSSet?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Generated accessors for lecturers
|
||||||
|
extension RaPlaEvent {
|
||||||
|
|
||||||
|
@objc(addLecturersObject:)
|
||||||
|
@NSManaged public func addToLecturers(_ value: Lecturer)
|
||||||
|
|
||||||
|
@objc(removeLecturersObject:)
|
||||||
|
@NSManaged public func removeFromLecturers(_ value: Lecturer)
|
||||||
|
|
||||||
|
@objc(addLecturers:)
|
||||||
|
@NSManaged public func addToLecturers(_ values: NSSet)
|
||||||
|
|
||||||
|
@objc(removeLecturers:)
|
||||||
|
@NSManaged public func removeFromLecturers(_ values: NSSet)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RaPlaEvent : Identifiable {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// User+CoreDataClass.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
@objc(User)
|
||||||
|
public class User: NSManagedObject {
|
||||||
|
@nonobjc public class func getAll() -> [User] {
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(User.fetchRequest())
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [User]{
|
||||||
|
let managedContext =
|
||||||
|
PersistenceController.shared.context
|
||||||
|
|
||||||
|
let fetchRequest: NSFetchRequest = User.fetchRequest()
|
||||||
|
|
||||||
|
fetchRequest.sortDescriptors = sortDescriptors
|
||||||
|
if(searchPredicate != nil) {
|
||||||
|
fetchRequest.predicate = searchPredicate
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try managedContext.fetch(fetchRequest)
|
||||||
|
} catch let error as NSError {
|
||||||
|
print("Could not fetch. \(error), \(error.userInfo)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// User+CoreDataProperties.swift
|
||||||
|
// DHBW-Service
|
||||||
|
//
|
||||||
|
// Created by Patrick Müller on 10.02.21.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
|
extension User {
|
||||||
|
|
||||||
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<User> {
|
||||||
|
return NSFetchRequest<User>(entityName: "User")
|
||||||
|
}
|
||||||
|
|
||||||
|
@NSManaged public var course: String?
|
||||||
|
@NSManaged public var director: String?
|
||||||
|
@NSManaged public var name: String?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension User : Identifiable {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -65,39 +65,42 @@ struct PersistenceController {
|
|||||||
let viewContext = result.container.viewContext
|
let viewContext = result.container.viewContext
|
||||||
|
|
||||||
// set mock user
|
// set mock user
|
||||||
let userEntity = NSEntityDescription.entity(forEntityName: "User", in: PersistenceController.shared.context)!
|
let user = User(context: PersistenceController.shared.context)
|
||||||
let user = NSManagedObject(entity: userEntity, insertInto: PersistenceController.shared.context)
|
user.name = "Max Mustermann"
|
||||||
user.setValue("Max Mustermann", forKey: "name")
|
user.course = "TINF19B4"
|
||||||
user.setValue("TINF19B4", forKey: "course")
|
user.director = "Prof. Dr. Mustermann"
|
||||||
user.setValue("Dr. Mustermann", forKey: "director")
|
|
||||||
|
|
||||||
// Generate mock events
|
// Generate mock events
|
||||||
let eventEntity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)!
|
let normalEvent1 = RaPlaEvent(context: PersistenceController.shared.context)
|
||||||
let normalEvent1 = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context)
|
let normalEvent2 = RaPlaEvent(context: PersistenceController.shared.context)
|
||||||
let normalEvent2 = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context)
|
let examEvent = RaPlaEvent(context: PersistenceController.shared.context)
|
||||||
let examEvent = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context)
|
normalEvent1.summary = "Mock Event 1"
|
||||||
normalEvent1.setValue("Mock Event 1", forKey: "summary")
|
normalEvent2.summary = "Mock Event 2"
|
||||||
normalEvent2.setValue("Mock Event 2", forKey: "summary")
|
examEvent.summary = "Exam Event"
|
||||||
examEvent.setValue("Exam Event", forKey: "summary")
|
|
||||||
normalEvent1.setValue("Mock Event 1 Description", forKey: "descr")
|
normalEvent1.descr = "Mock Event 1 description"
|
||||||
normalEvent2.setValue("Mock Event 2 Description", forKey: "descr")
|
normalEvent2.descr = "Mock Event 2 description"
|
||||||
examEvent.setValue("Exam Event Description", forKey: "descr")
|
examEvent.descr = "Exam Event description"
|
||||||
normalEvent1.setValue("E207 INF Hörsaal", forKey: "location")
|
|
||||||
normalEvent2.setValue("A306 WI Hörsaal", forKey: "location")
|
normalEvent1.location = "E207 INF Hörsaal"
|
||||||
examEvent.setValue("Audimax A", forKey: "location")
|
normalEvent2.location = "A306 WI Hörsaal"
|
||||||
normalEvent1.setValue("Lehrveranstaltung", forKey: "category")
|
examEvent.location = "Audimax A"
|
||||||
normalEvent2.setValue("Lehrveranstaltung", forKey: "category")
|
|
||||||
examEvent.setValue("Prüfung", forKey: "category")
|
normalEvent1.category = "Lehrveranstaltung"
|
||||||
|
normalEvent2.category = "Lehrveranstaltung"
|
||||||
|
examEvent.category = "Prüfung"
|
||||||
|
|
||||||
var currentDate = Date()
|
var currentDate = Date()
|
||||||
currentDate.addTimeInterval(1*60*60);normalEvent1.setValue(currentDate, forKey: "startDate")
|
currentDate.addTimeInterval(1*60*60);normalEvent1.startDate = currentDate
|
||||||
currentDate.addTimeInterval(1*60*60);normalEvent2.setValue(currentDate, forKey: "startDate")
|
currentDate.addTimeInterval(1*60*60);normalEvent2.startDate = currentDate
|
||||||
currentDate.addTimeInterval(1*60*60);examEvent.setValue(currentDate, forKey: "startDate")
|
currentDate.addTimeInterval(1*60*60);examEvent.startDate = currentDate
|
||||||
currentDate.addTimeInterval(1*60*60);normalEvent1.setValue(currentDate, forKey: "endDate")
|
currentDate.addTimeInterval(1*60*60);normalEvent1.endDate = currentDate
|
||||||
currentDate.addTimeInterval(1*60*60);normalEvent2.setValue(currentDate, forKey: "endDate")
|
currentDate.addTimeInterval(1*60*60);normalEvent2.endDate = currentDate
|
||||||
currentDate.addTimeInterval(1*60*60);examEvent.setValue(currentDate, forKey: "endDate")
|
currentDate.addTimeInterval(1*60*60);examEvent.endDate = currentDate
|
||||||
normalEvent1.setValue("totalUniqueId1", forKey: "uid")
|
|
||||||
normalEvent2.setValue("totalUniqueId2", forKey: "uid")
|
normalEvent1.uid = "totalUniqueId1"
|
||||||
examEvent.setValue("totalUniqueId3", forKey: "uid")
|
normalEvent2.uid = "totalUniqueId2"
|
||||||
|
examEvent.uid = "totalUniqueId3"
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -6,6 +6,30 @@
|
|||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIcons</key>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleAlternateIcons</key>
|
||||||
|
<dict>
|
||||||
|
<key>Alpaca-Alt-Icon</key>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>alpaca-alt-icon</string>
|
||||||
|
</array>
|
||||||
|
<key>UIPrerenderedIcon</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>CFBundlePrimaryIcon</key>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>dhbw-standard-icon</string>
|
||||||
|
</array>
|
||||||
|
<key>UIPrerenderedIcon</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
@@ -44,29 +68,5 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleIcons</key>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundlePrimaryIcon</key>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleIconFiles</key>
|
|
||||||
<array>
|
|
||||||
<string>dhbw-standard-icon</string>
|
|
||||||
</array>
|
|
||||||
<key>UIPrerenderedIcon</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
<key>CFBundleAlternateIcons</key>
|
|
||||||
<dict>
|
|
||||||
<key>Alpaca-Alt-Icon</key>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleIconFiles</key>
|
|
||||||
<array>
|
|
||||||
<string>alpaca-alt-icon</string>
|
|
||||||
</array>
|
|
||||||
<key>UIPrerenderedIcon</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
"hey" = "Hey 👋🏻";
|
"hey" = "Hey 👋🏻";
|
||||||
|
"information" = "Deine Informationen";
|
||||||
"today" = "Heute";
|
"today" = "Heute";
|
||||||
"tomorrow" = "Morgen";
|
"tomorrow" = "Morgen";
|
||||||
"upcomingExams" = "Nächste Klausuren";
|
"upcomingExams" = "Nächste Klausuren";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
"hey" = "Hey 👋🏻";
|
"hey" = "Hey 👋🏻";
|
||||||
|
"information" = "Your Information";
|
||||||
"today" = "Today";
|
"today" = "Today";
|
||||||
"tomorrow" = "Tomorrow";
|
"tomorrow" = "Tomorrow";
|
||||||
"upcomingExams" = "Upcoming exams";
|
"upcomingExams" = "Upcoming exams";
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ class RaPlaFetcher {
|
|||||||
var location: String = "" //LOCATION
|
var location: String = "" //LOCATION
|
||||||
var category: String = "" //CATEGORIES
|
var category: String = "" //CATEGORIES
|
||||||
var uid: String = "" //UID
|
var uid: String = "" //UID
|
||||||
|
var lecturers: [LecturerObj] = [] //ATTENDEE
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LecturerObj {
|
||||||
|
var name: String = ""
|
||||||
|
var email: String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the RaPla file from the given URL and save the events to CoreData
|
// Get the RaPla file from the given URL and save the events to CoreData
|
||||||
@@ -68,9 +74,24 @@ class RaPlaFetcher {
|
|||||||
var events: [iCalEvent] = []
|
var events: [iCalEvent] = []
|
||||||
|
|
||||||
for eventString in eventStrings {
|
for eventString in eventStrings {
|
||||||
let lines = eventString.components(separatedBy: .newlines)
|
var lines = eventString.components(separatedBy: .newlines)
|
||||||
|
// Remove all blank lines that somehow are generated by the .components function
|
||||||
|
lines = removeBlankLines(lines: lines)
|
||||||
|
|
||||||
let evt = iCalEvent()
|
let evt = iCalEvent()
|
||||||
|
|
||||||
|
// Iterate over all lines and merge lines that have been split by rapla first
|
||||||
|
for lineNr in 0...lines.count-1 {
|
||||||
|
if(lines[lineNr].hasPrefix(" ")){
|
||||||
|
lines[lineNr] = String(lines[lineNr].dropFirst())
|
||||||
|
lines[lineNr-1].append(lines[lineNr])
|
||||||
|
lines[lineNr] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all blank lines again as we produced some while merging the lines
|
||||||
|
lines = removeBlankLines(lines: lines)
|
||||||
|
|
||||||
for line in lines {
|
for line in lines {
|
||||||
var lineWithoutPrefix = line
|
var lineWithoutPrefix = line
|
||||||
if(!line.contains(":")) {
|
if(!line.contains(":")) {
|
||||||
@@ -82,7 +103,7 @@ class RaPlaFetcher {
|
|||||||
//Date format: 20181101T080000
|
//Date format: 20181101T080000
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
if(lineWithoutPrefix.contains("Z")){
|
if(lineWithoutPrefix.contains("Z")){
|
||||||
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmssZ"
|
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'"
|
||||||
} else {
|
} else {
|
||||||
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
|
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
|
||||||
}
|
}
|
||||||
@@ -91,7 +112,7 @@ class RaPlaFetcher {
|
|||||||
} else if(line.hasPrefix("DTEND")){
|
} else if(line.hasPrefix("DTEND")){
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
if(lineWithoutPrefix.contains("Z")){
|
if(lineWithoutPrefix.contains("Z")){
|
||||||
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmssZ"
|
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'"
|
||||||
} else {
|
} else {
|
||||||
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
|
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
|
||||||
}
|
}
|
||||||
@@ -107,6 +128,22 @@ class RaPlaFetcher {
|
|||||||
evt.category = lineWithoutPrefix
|
evt.category = lineWithoutPrefix
|
||||||
} else if(line.hasPrefix("UID")){
|
} else if(line.hasPrefix("UID")){
|
||||||
evt.uid = lineWithoutPrefix
|
evt.uid = lineWithoutPrefix
|
||||||
|
} else if(line.hasPrefix("ATTENDEE;ROLE=REQ-PARTICIPANT;")) {
|
||||||
|
var lecturerName = line
|
||||||
|
|
||||||
|
let begin = lecturerName.firstIndex(of: "\"")!
|
||||||
|
lecturerName.removeSubrange(lecturerName.startIndex...begin)
|
||||||
|
|
||||||
|
let end = lecturerName.lastIndex(of: "\"")!
|
||||||
|
lecturerName = String(lecturerName[..<end])
|
||||||
|
|
||||||
|
let lecturerEmail = String(lineWithoutPrefix[String.Index(utf16Offset: 7, in: lineWithoutPrefix)..<lineWithoutPrefix.endIndex])
|
||||||
|
|
||||||
|
let lecturer = LecturerObj()
|
||||||
|
lecturer.name = lecturerName
|
||||||
|
lecturer.email = lecturerEmail
|
||||||
|
|
||||||
|
evt.lecturers.append(lecturer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,32 +156,37 @@ class RaPlaFetcher {
|
|||||||
// Save the given iCalEvent objects to CoreData
|
// Save the given iCalEvent objects to CoreData
|
||||||
// Updates the events if they already exist and deletes old (/invalid) ones
|
// Updates the events if they already exist and deletes old (/invalid) ones
|
||||||
private class func saveToCoreData(eventObjects: [iCalEvent]) -> Bool{
|
private class func saveToCoreData(eventObjects: [iCalEvent]) -> Bool{
|
||||||
let existingEvents = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: [])
|
let existingEvents: [RaPlaEvent] = RaPlaEvent.getAll()
|
||||||
var existingEventsDict: [String:NSManagedObject] = [:]
|
var existingEventsDict: [String:RaPlaEvent] = [:]
|
||||||
for event in existingEvents {
|
for event in existingEvents {
|
||||||
existingEventsDict[event.value(forKey: "uid") as! String] = event
|
existingEventsDict[event.uid!] = event
|
||||||
}
|
}
|
||||||
let newEventUIDs = eventObjects.map{$0.uid}
|
let newEventUIDs = eventObjects.map{$0.uid}
|
||||||
|
|
||||||
for event in eventObjects {
|
for event in eventObjects {
|
||||||
// If the event already exists locally, update it. Otherwise, create a new record
|
// If the event already exists locally, update it. Otherwise, create a new record
|
||||||
let evt: NSManagedObject
|
let evt: RaPlaEvent
|
||||||
if existingEventsDict.keys.contains(event.uid) {
|
if existingEventsDict.keys.contains(event.uid) {
|
||||||
evt = existingEventsDict[event.uid]!
|
evt = existingEventsDict[event.uid]!
|
||||||
} else {
|
} else {
|
||||||
let entity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)!
|
evt = RaPlaEvent(context: PersistenceController.shared.context)
|
||||||
evt = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context)
|
|
||||||
|
|
||||||
// Set default values for new object
|
// Set default values for new object
|
||||||
evt.setValue(false, forKey: "isHidden")
|
evt.isHidden = false
|
||||||
|
}
|
||||||
|
evt.startDate = event.startDate
|
||||||
|
evt.endDate = event.endDate
|
||||||
|
evt.summary = event.summary
|
||||||
|
evt.descr = event.description
|
||||||
|
evt.location = event.location
|
||||||
|
evt.category = event.category
|
||||||
|
evt.uid = event.uid
|
||||||
|
for lecturer in event.lecturers {
|
||||||
|
let lect = Lecturer(context: PersistenceController.shared.context)
|
||||||
|
lect.name = lecturer.name
|
||||||
|
lect.email = lecturer.email
|
||||||
|
lect.event = evt
|
||||||
}
|
}
|
||||||
evt.setValue(event.startDate, forKey: "startDate")
|
|
||||||
evt.setValue(event.endDate, forKey: "endDate")
|
|
||||||
evt.setValue(event.summary, forKey: "summary")
|
|
||||||
evt.setValue(event.description, forKey: "descr")
|
|
||||||
evt.setValue(event.location, forKey: "location")
|
|
||||||
evt.setValue(event.category, forKey: "category")
|
|
||||||
evt.setValue(event.uid, forKey: "uid")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we also have to delete locally stored events that have been deleted from RaPla
|
// Now we also have to delete locally stored events that have been deleted from RaPla
|
||||||
@@ -160,4 +202,17 @@ class RaPlaFetcher {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class func removeBlankLines(lines: [String]) -> [String] {
|
||||||
|
var newLines = lines
|
||||||
|
|
||||||
|
// Remove all blank lines that somehow are generated by the .components function
|
||||||
|
for line in newLines {
|
||||||
|
if(line.isEmpty){
|
||||||
|
newLines.remove(at: newLines.firstIndex(of: line)!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newLines
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
class UtilityFunctions {
|
class UtilityFunctions {
|
||||||
|
// DEPRECATED, replaced by the respective getSpecified() method of each CoreData object
|
||||||
public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [NSManagedObject]{
|
public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [NSManagedObject]{
|
||||||
let managedContext =
|
let managedContext =
|
||||||
PersistenceController.shared.context
|
PersistenceController.shared.context
|
||||||
|
|||||||
@@ -96,11 +96,10 @@ extension FirstOpeningSettings{
|
|||||||
print("Deleting old user data status: \(status)")
|
print("Deleting old user data status: \(status)")
|
||||||
|
|
||||||
// Insert new user data
|
// Insert new user data
|
||||||
let entity = NSEntityDescription.entity(forEntityName: "User", in: PersistenceController.shared.context)!
|
let user = User(context: PersistenceController.shared.context)
|
||||||
let user = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context)
|
user.name = name
|
||||||
user.setValue(name, forKey: "name")
|
user.course = course
|
||||||
user.setValue(course, forKey: "course")
|
user.director = director
|
||||||
user.setValue(director, forKey: "director")
|
|
||||||
|
|
||||||
self.settings.isFirstOpening = !self.settings.isFirstOpening
|
self.settings.isFirstOpening = !self.settings.isFirstOpening
|
||||||
PersistenceController.shared.save()
|
PersistenceController.shared.save()
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ struct HomeView: View {
|
|||||||
@State private var name: String = ""
|
@State private var name: String = ""
|
||||||
@State private var course: String = ""
|
@State private var course: String = ""
|
||||||
@State private var director: String = ""
|
@State private var director: String = ""
|
||||||
@State private var todaysEvents: [NSManagedObject] = []
|
@State private var todaysEvents: [RaPlaEvent] = []
|
||||||
@State private var tomorrowsEvents: [NSManagedObject] = []
|
@State private var tomorrowsEvents: [RaPlaEvent] = []
|
||||||
@State private var upcomingExams: [NSManagedObject] = []
|
@State private var upcomingExams: [RaPlaEvent] = []
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
@@ -37,6 +37,32 @@ struct HomeView: View {
|
|||||||
)
|
)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
VStack {
|
||||||
|
Text("information".localized(tableName: "HomeView", plural: false))
|
||||||
|
.font(.title3)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
HStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("course".localized(tableName: "General", plural: false) + ": ")
|
||||||
|
Text("director".localized(tableName: "General", plural: false) + ": ")
|
||||||
|
}
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(self.course)
|
||||||
|
.bold()
|
||||||
|
Text(self.director)
|
||||||
|
.bold()
|
||||||
|
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.fill(Color.gray)
|
||||||
|
)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
Text("course".localized(tableName: "General", plural: false) + ": ")
|
Text("course".localized(tableName: "General", plural: false) + ": ")
|
||||||
@@ -89,25 +115,25 @@ struct HomeView: View {
|
|||||||
extension HomeView{
|
extension HomeView{
|
||||||
// Read required data from CoreData and save it to the appropriate variables
|
// Read required data from CoreData and save it to the appropriate variables
|
||||||
func readFromCoreData() {
|
func readFromCoreData() {
|
||||||
let fetchedData = UtilityFunctions.getCoreDataObject(entity: "User")
|
let fetchedData = User.getAll()
|
||||||
|
|
||||||
if(!fetchedData.isEmpty) {
|
if(!fetchedData.isEmpty) {
|
||||||
let user = fetchedData[0]
|
let user = fetchedData[0]
|
||||||
self.name = user.value(forKey: "name") as! String
|
self.name = user.name!
|
||||||
self.course = user.value(forKey: "course") as! String
|
self.course = user.course!
|
||||||
self.director = user.value(forKey: "director") as! String
|
self.director = user.director!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 0...2 of todays lectures from RaPla
|
// Get 0...2 of todays lectures from RaPla
|
||||||
// Returns a list of RaPlaEvent NSManagedObjects
|
// Returns a list of RaPlaEvent NSManagedObjects
|
||||||
func getTodaysEvents() -> [NSManagedObject] {
|
func getTodaysEvents() -> [RaPlaEvent] {
|
||||||
let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')")
|
let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')")
|
||||||
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
||||||
var predicates = [searchPredicate, hiddenPredicate]
|
var predicates = [searchPredicate, hiddenPredicate]
|
||||||
predicates.append(contentsOf: getDayPredicates(today: true))
|
predicates.append(contentsOf: getDayPredicates(today: true))
|
||||||
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
|
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
|
||||||
let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: compoundPredicate)
|
let events = RaPlaEvent.getSpecified(searchPredicate: compoundPredicate)
|
||||||
if(!events.isEmpty) {
|
if(!events.isEmpty) {
|
||||||
return Array(events[...min(1, events.count-1)])
|
return Array(events[...min(1, events.count-1)])
|
||||||
} else {
|
} else {
|
||||||
@@ -117,13 +143,13 @@ extension HomeView{
|
|||||||
|
|
||||||
// Get 0...2 of tomorrows lectures from RaPla
|
// Get 0...2 of tomorrows lectures from RaPla
|
||||||
// Returns a list of RaPlaEvent NSManagedObjects
|
// Returns a list of RaPlaEvent NSManagedObjects
|
||||||
func getTomorrowsEvents() -> [NSManagedObject] {
|
func getTomorrowsEvents() -> [RaPlaEvent] {
|
||||||
let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')")
|
let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')")
|
||||||
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
||||||
var predicates = [searchPredicate, hiddenPredicate]
|
var predicates = [searchPredicate, hiddenPredicate]
|
||||||
predicates.append(contentsOf: getDayPredicates(tomorrow: true))
|
predicates.append(contentsOf: getDayPredicates(tomorrow: true))
|
||||||
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
|
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
|
||||||
let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: compoundPredicate)
|
let events = RaPlaEvent.getSpecified(searchPredicate: compoundPredicate)
|
||||||
if(!events.isEmpty) {
|
if(!events.isEmpty) {
|
||||||
return Array(events[...min(1, events.count-1)])
|
return Array(events[...min(1, events.count-1)])
|
||||||
} else {
|
} else {
|
||||||
@@ -133,13 +159,13 @@ extension HomeView{
|
|||||||
|
|
||||||
// Get 0...2 of upcoming exams from RaPla
|
// Get 0...2 of upcoming exams from RaPla
|
||||||
// Returns a list of RaPlaEvent NSManagedObjects
|
// Returns a list of RaPlaEvent NSManagedObjects
|
||||||
func getUpcomingExams() -> [NSManagedObject] {
|
func getUpcomingExams() -> [RaPlaEvent] {
|
||||||
let searchPredicate = NSPredicate(format: "category == %@", "Prüfung")
|
let searchPredicate = NSPredicate(format: "category == %@", "Prüfung")
|
||||||
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
|
||||||
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [searchPredicate, hiddenPredicate])
|
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [searchPredicate, hiddenPredicate])
|
||||||
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
||||||
let sortDescriptors = [sectionSortDescriptor]
|
let sortDescriptors = [sectionSortDescriptor]
|
||||||
let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors, searchPredicate: compoundPredicate)
|
let events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors, searchPredicate: compoundPredicate)
|
||||||
if(!events.isEmpty) {
|
if(!events.isEmpty) {
|
||||||
return Array(events[...min(1, events.count-1)])
|
return Array(events[...min(1, events.count-1)])
|
||||||
} else {
|
} else {
|
||||||
@@ -196,7 +222,7 @@ extension HomeView{
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct UpcomingLecturesBlock: View {
|
struct UpcomingLecturesBlock: View {
|
||||||
let eventsList: [NSManagedObject]
|
let eventsList: [RaPlaEvent]
|
||||||
let titleKey: String
|
let titleKey: String
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -207,7 +233,7 @@ struct UpcomingLecturesBlock: View {
|
|||||||
VStack {
|
VStack {
|
||||||
if(!eventsList.isEmpty){
|
if(!eventsList.isEmpty){
|
||||||
ForEach(eventsList, id: \.self) { exam in
|
ForEach(eventsList, id: \.self) { exam in
|
||||||
Text(exam.value(forKey: "summary") as! String)
|
Text(exam.summary!)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -225,7 +251,7 @@ struct UpcomingLecturesBlock: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct UpcomingExamsBlock: View {
|
struct UpcomingExamsBlock: View {
|
||||||
let examsList: [NSManagedObject]
|
let examsList: [RaPlaEvent]
|
||||||
let titleKey: String
|
let titleKey: String
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -236,7 +262,7 @@ struct UpcomingExamsBlock: View {
|
|||||||
VStack {
|
VStack {
|
||||||
if(!examsList.isEmpty){
|
if(!examsList.isEmpty){
|
||||||
ForEach(examsList, id: \.self) { exam in
|
ForEach(examsList, id: \.self) { exam in
|
||||||
Text(exam.value(forKey: "summary") as! String)
|
Text(exam.summary!)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,34 +9,89 @@ import SwiftUI
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
struct LecturePlanItem: View {
|
struct LecturePlanItem: View {
|
||||||
@State var event: NSManagedObject
|
@State var event: RaPlaEvent
|
||||||
@State var isHidden = false
|
@State var isHidden = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Text(event.value(forKey: "summary") as! String)
|
HStack {
|
||||||
Button(action: {
|
Spacer()
|
||||||
event.setValue(!isHidden, forKey: "isHidden")
|
VStack {
|
||||||
self.isHidden = !isHidden
|
Text(event.summary!)
|
||||||
PersistenceController.shared.save()
|
.font(.title3)
|
||||||
}){
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
if(self.isHidden){
|
Text(event.descr!)
|
||||||
Text("Show")
|
.bold()
|
||||||
} else {
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
Text("Hide")
|
Divider()
|
||||||
|
HStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("When")
|
||||||
|
Text("Where")
|
||||||
|
Text("Who")
|
||||||
|
}
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(getDateAndTimeAsString(date: event.startDate!)
|
||||||
|
+ " to "
|
||||||
|
+ getTimeAsString(date: event.endDate!))
|
||||||
|
.bold()
|
||||||
|
Text(event.location!)
|
||||||
|
.bold()
|
||||||
|
Text(!event.lecturerList.isEmpty ? event.lecturerList[0].wrappedName : "")
|
||||||
|
.bold()
|
||||||
|
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
Divider()
|
||||||
|
HStack {
|
||||||
|
Button(action: {
|
||||||
|
event.isHidden = !isHidden
|
||||||
|
self.isHidden = !isHidden
|
||||||
|
PersistenceController.shared.save()
|
||||||
|
}){
|
||||||
|
if(self.isHidden){
|
||||||
|
Text("Show")
|
||||||
|
} else {
|
||||||
|
Text("Hide")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.background(Color.blue)
|
||||||
|
.cornerRadius(15)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.padding()
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.fill(Color.gray)
|
||||||
|
)
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding()
|
.frame(maxWidth: .infinity)
|
||||||
.foregroundColor(.white)
|
Spacer()
|
||||||
.background(Color.blue)
|
|
||||||
.cornerRadius(15)
|
|
||||||
}
|
}
|
||||||
.onAppear{
|
.onAppear{
|
||||||
self.isHidden = event.value(forKey: "isHidden") as! Bool
|
self.isHidden = event.isHidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDateAndTimeAsString(date: Date) -> String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateStyle = .short
|
||||||
|
formatter.timeStyle = .short
|
||||||
|
|
||||||
|
return formatter.string(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimeAsString(date: Date) -> String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.timeStyle = .short
|
||||||
|
|
||||||
|
return formatter.string(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
struct LecturePlanItem_Previews: PreviewProvider {
|
struct LecturePlanItem_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
LecturePlanItem(event: getPreviewEvent())
|
LecturePlanItem(event: getPreviewEvent())
|
||||||
@@ -52,7 +107,7 @@ struct LecturePlanItem_Previews: PreviewProvider {
|
|||||||
return settings
|
return settings
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getPreviewEvent() -> NSManagedObject {
|
static func getPreviewEvent() -> RaPlaEvent {
|
||||||
return UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: [])[0]
|
return RaPlaEvent.getSpecified(sortDescriptors: [])[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import SwiftUI
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
struct LecturePlanList: View {
|
struct LecturePlanList: View {
|
||||||
@State private var events: [NSManagedObject] = []
|
@State private var events: [RaPlaEvent] = []
|
||||||
@State private var sortingAscending = true
|
@State private var sortingAscending = true
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -18,14 +18,14 @@ struct LecturePlanList: View {
|
|||||||
ForEach(events, id: \.self) { event in
|
ForEach(events, id: \.self) { event in
|
||||||
NavigationLink(destination: LecturePlanItem(event: event)){
|
NavigationLink(destination: LecturePlanItem(event: event)){
|
||||||
HStack {
|
HStack {
|
||||||
Text(formatDate(date: event.value(forKeyPath: "startDate") as! Date))
|
Text(formatDate(date: event.startDate!))
|
||||||
.foregroundColor(getEventForegroundColor(for: event))
|
.foregroundColor(getEventForegroundColor(for: event))
|
||||||
Text(event.value(forKeyPath: "summary") as! String)
|
Text(event.summary!)
|
||||||
.foregroundColor(getEventForegroundColor(for: event))
|
.foregroundColor(getEventForegroundColor(for: event))
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if(event.value(forKey: "isHidden") as! Bool) {
|
if(event.isHidden) {
|
||||||
Image(systemName: "eye.slash")
|
Image(systemName: "eye.slash")
|
||||||
.foregroundColor(.red)
|
.foregroundColor(.red)
|
||||||
} else {
|
} else {
|
||||||
@@ -38,7 +38,7 @@ struct LecturePlanList: View {
|
|||||||
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
||||||
let sortDescriptors = [sectionSortDescriptor]
|
let sortDescriptors = [sectionSortDescriptor]
|
||||||
self.events = []
|
self.events = []
|
||||||
self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
|
self.events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ struct LecturePlanList: View {
|
|||||||
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
|
||||||
let sortDescriptors = [sectionSortDescriptor]
|
let sortDescriptors = [sectionSortDescriptor]
|
||||||
self.events = []
|
self.events = []
|
||||||
self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
|
self.events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,9 +89,9 @@ extension LecturePlanList {
|
|||||||
return formatter.string(from: date)
|
return formatter.string(from: date)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getEventForegroundColor(for event: NSManagedObject) -> Color {
|
private func getEventForegroundColor(for event: RaPlaEvent) -> Color {
|
||||||
var textColor: Color = .primary
|
var textColor: Color = .primary
|
||||||
if(event.value(forKeyPath: "category") as! String == "Prüfung") {
|
if(event.category! == "Prüfung") {
|
||||||
textColor = Color.red
|
textColor = Color.red
|
||||||
} else {
|
} else {
|
||||||
textColor = Color.primary
|
textColor = Color.primary
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# DHBW-Service-App
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
This is a project by two students of the Cooperative State University in Karlsruhe (DHBW Karlsruhe).
|
||||||
|
The goal is to develop a native iOS app providing easy and straightforward access to services like RaPla, Dualis and the canteen plan.
|
||||||
|
|
||||||
|
<b>Disclaimer:</b> This project is not affiliated with the DHBW Karlsruhe
|
||||||
|
|
||||||
|
## Build it yourself
|
||||||
|
As the app is not yet available on the App Store, you can build and install it yourself if you have a Mac with Xcode installed.
|
||||||
|
Just clone the repository, then open the project in Xcode and navigate to the project settings. In the target section, select
|
||||||
|
the iOS target. Then you have to select your own development team in the dropdown or create a new one.
|
||||||
|
If you completed these steps, you should be able to install a development version of the app on your own devices.
|
||||||
Reference in New Issue
Block a user