Adding option to hide RaPla events

- Also made changes to home view, lecture plan list view, and added lecture plan item view
This commit is contained in:
Patrick Müller 2021-02-01 23:17:15 +01:00 committed by Patrick Müller
parent ea0b759007
commit b8c6d44000
7 changed files with 214 additions and 32 deletions

View File

@ -31,6 +31,7 @@
CDDCF493259203390027CDC5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF495259203390027CDC5 /* Localizable.strings */; }; CDDCF493259203390027CDC5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF495259203390027CDC5 /* Localizable.strings */; };
CDDCF4A2259203B40027CDC5 /* General.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF4A4259203B40027CDC5 /* General.strings */; }; CDDCF4A2259203B40027CDC5 /* General.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDDCF4A4259203B40027CDC5 /* General.strings */; };
CDEA70B225C6054F001CFE28 /* LecturePlanList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */; }; CDEA70B225C6054F001CFE28 /* LecturePlanList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */; };
CDEA70C025C85999001CFE28 /* LecturePlanItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEA70BF25C85999001CFE28 /* LecturePlanItem.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -83,6 +84,7 @@
CDDCF4A3259203B40027CDC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/General.strings; sourceTree = "<group>"; }; CDDCF4A3259203B40027CDC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/General.strings; sourceTree = "<group>"; };
CDDCF4A8259203B80027CDC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/General.strings; sourceTree = "<group>"; }; CDDCF4A8259203B80027CDC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/General.strings; sourceTree = "<group>"; };
CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LecturePlanList.swift; sourceTree = "<group>"; }; CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LecturePlanList.swift; sourceTree = "<group>"; };
CDEA70BF25C85999001CFE28 /* LecturePlanItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LecturePlanItem.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -257,6 +259,7 @@
CDCD721925912E1200FBF2F5 /* HomeView.swift */, CDCD721925912E1200FBF2F5 /* HomeView.swift */,
CDD39B4A259A64150078D05F /* SettingsMain.swift */, CDD39B4A259A64150078D05F /* SettingsMain.swift */,
CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */, CDEA70B125C6054F001CFE28 /* LecturePlanList.swift */,
CDEA70BF25C85999001CFE28 /* LecturePlanItem.swift */,
CD730A33259A85F500E0BB69 /* SettingsSubViews */, CD730A33259A85F500E0BB69 /* SettingsSubViews */,
); );
path = Tabs; path = Tabs;
@ -441,6 +444,7 @@
CD9FAB83258EC60200D6D0C5 /* ContentView.swift in Sources */, CD9FAB83258EC60200D6D0C5 /* ContentView.swift in Sources */,
CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */, CDCD72242591316500FBF2F5 /* LocalSettings.swift in Sources */,
CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.swift in Sources */, CD8555BE25C47AE500C4ACD6 /* RaPlaFetcher.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 */,

View File

@ -7,6 +7,7 @@
<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"/>
<attribute name="isHidden" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="location" optional="YES" attributeType="String"/> <attribute name="location" optional="YES" attributeType="String"/>
<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"/>
@ -19,7 +20,7 @@
</entity> </entity>
<elements> <elements>
<element name="Item" positionX="-63" positionY="-18" width="128" height="44"/> <element name="Item" positionX="-63" positionY="-18" width="128" height="44"/>
<element name="RaPlaEvent" positionX="-63" positionY="9" width="128" height="134"/> <element name="RaPlaEvent" positionX="-63" positionY="9" width="128" height="149"/>
<element name="User" positionX="-63" positionY="-9" width="128" height="74"/> <element name="User" positionX="-63" positionY="-9" width="128" height="74"/>
</elements> </elements>
</model> </model>

View File

@ -134,6 +134,9 @@ class RaPlaFetcher {
} else { } else {
let entity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)! let entity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)!
evt = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context) evt = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context)
// Set default values for new object
evt.setValue(false, forKey: "isHidden")
} }
evt.setValue(event.startDate, forKey: "startDate") evt.setValue(event.startDate, forKey: "startDate")
evt.setValue(event.endDate, forKey: "endDate") evt.setValue(event.endDate, forKey: "endDate")
@ -150,7 +153,6 @@ class RaPlaFetcher {
// Locally stored event does not exist in RaPla anymore, delete it // Locally stored event does not exist in RaPla anymore, delete it
let evt = existingEventsDict[localUid] let evt = existingEventsDict[localUid]
PersistenceController.shared.context.delete(evt!) PersistenceController.shared.context.delete(evt!)
print("Deleted " + localUid)
} }
} }

View File

@ -9,13 +9,16 @@ import Foundation
import CoreData import CoreData
class UtilityFunctions { class UtilityFunctions {
public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor]) -> [NSManagedObject]{ public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [NSManagedObject]{
let managedContext = let managedContext =
PersistenceController.shared.context PersistenceController.shared.context
let fetchRequest = let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: entity) NSFetchRequest<NSManagedObject>(entityName: entity)
fetchRequest.sortDescriptors = sortDescriptors fetchRequest.sortDescriptors = sortDescriptors
if(searchPredicate != nil) {
fetchRequest.predicate = searchPredicate
}
do { do {
return try managedContext.fetch(fetchRequest) return try managedContext.fetch(fetchRequest)

View File

@ -13,8 +13,12 @@ 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 tomorrowsEvents: [NSManagedObject] = []
@State private var upcomingExams: [NSManagedObject] = []
var body: some View { var body: some View {
NavigationView {
VStack { VStack {
HStack { HStack {
Text("name".localized(tableName: "General", plural: false) + ": ") Text("name".localized(tableName: "General", plural: false) + ": ")
@ -28,15 +32,78 @@ struct HomeView: View {
Text("director".localized(tableName: "General", plural: false) + ": ") Text("director".localized(tableName: "General", plural: false) + ": ")
Text(self.director) Text(self.director)
} }
// Upcoming events section
HStack {
Spacer()
VStack {
Text("Today's events")
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
.frame(maxWidth: .infinity)
VStack {
Text("Evt 1")
Text("Evt 2")
}
}
.padding()
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.blue, lineWidth: 4)
)
VStack {
Text("Tomorrow's events")
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
.frame(maxWidth: .infinity)
VStack {
Text("Evt 1")
Text("Evt 2")
}
}
.padding()
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.blue, lineWidth: 4)
)
Spacer()
}
// Exams section
HStack {
Spacer()
VStack {
Text("Upcoming exams")
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
.frame(maxWidth: .infinity)
VStack {
ForEach(upcomingExams, id: \.self) { exam in
Text(exam.value(forKey: "summary") as! String)
}
}
}
.padding()
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.red, lineWidth: 4)
)
Spacer()
}
}
.navigationBarTitle(Text("Home"))
}.onAppear{ }.onAppear{
self.readFromCoreData() self.readFromCoreData()
self.upcomingExams = getUpcomingExams()
} }
} }
} }
extension HomeView{ extension HomeView{
func readFromCoreData() { func readFromCoreData() {
let fetchedData = UtilityFunctions.getCoreDataObject(entity: "User", sortDescriptors: []) let fetchedData = UtilityFunctions.getCoreDataObject(entity: "User")
if(!fetchedData.isEmpty) { if(!fetchedData.isEmpty) {
let user = fetchedData[0] let user = fetchedData[0]
@ -45,6 +112,32 @@ extension HomeView{
self.director = user.value(forKey: "director") as! String self.director = user.value(forKey: "director") as! String
} }
} }
func getTodaysEvents() -> [NSManagedObject] {
// let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung') AND (startDate = %@)", Date())
// return Array(UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: searchPredicate)[0...1])
return []
}
func getTomorrowsEvents() -> [NSManagedObject] {
// let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung') AND (startDate = %@)", Date().)
// return Array(UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: searchPredicate)[0...1])
return []
}
func getUpcomingExams() -> [NSManagedObject] {
let searchPredicate = NSPredicate(format: "category == %@", "Prüfung")
let hiddenPredicate = NSPredicate(format: "isHidden == NO")
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [searchPredicate, hiddenPredicate])
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
let sortDescriptors = [sectionSortDescriptor]
let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors, searchPredicate: compoundPredicate)
if(events.count > 0) {
return Array(events[0...min(1, events.count)])
} else {
return []
}
}
} }
struct HomeView_Previews: PreviewProvider { struct HomeView_Previews: PreviewProvider {

View File

@ -0,0 +1,57 @@
//
// LecturePlanItem.swift
// DHBW-Service
//
// Created by Patrick Müller on 01.02.21.
//
import SwiftUI
import CoreData
struct LecturePlanItem: View {
@State var event: NSManagedObject
@State var isHidden = false
var body: some View {
VStack {
Text(event.value(forKey: "summary") as! String)
Button(action: {
event.setValue(!isHidden, forKey: "isHidden")
self.isHidden = !isHidden
PersistenceController.shared.save()
}){
if(self.isHidden){
Text("Show")
} else {
Text("Hide")
}
}
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(15)
}
.onAppear{
self.isHidden = event.value(forKey: "isHidden") as! Bool
}
}
}
struct LecturePlanItem_Previews: PreviewProvider {
static var previews: some View {
LecturePlanItem(event: getPreviewEvent())
.preferredColorScheme(.dark)
.environmentObject(getFirstOpening())
.environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
static func getFirstOpening() -> LocalSettings {
let settings = LocalSettings();
settings.isFirstOpening = false;
return settings
}
static func getPreviewEvent() -> NSManagedObject {
return UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: [])[0]
}
}

View File

@ -13,30 +13,52 @@ struct LecturePlanList: View {
@State private var sortingAscending = true @State private var sortingAscending = true
var body: some View { var body: some View {
VStack { NavigationView() {
Button(action: {
// This is obviously bullshit, but it could be used to sort afer summary or smth like that
self.sortingAscending = !self.sortingAscending
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: sortingAscending)
let sortDescriptors = [sectionSortDescriptor]
self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
}){
Text("Switch order")
}
List { List {
ForEach(events, id: \.self) { event in ForEach(events, id: \.self) { event in
NavigationLink(destination: LecturePlanItem(event: event)){
HStack { HStack {
Text(formatDate(date: event.value(forKeyPath: "startDate") as! Date)) Text(formatDate(date: event.value(forKeyPath: "startDate") as! Date))
.foregroundColor(getEventForegroundColor(for: event)) .foregroundColor(getEventForegroundColor(for: event))
Text(event.value(forKeyPath: "summary") as! String) Text(event.value(forKeyPath: "summary") as! String)
.foregroundColor(getEventForegroundColor(for: event)) .foregroundColor(getEventForegroundColor(for: event))
Spacer()
if(event.value(forKey: "isHidden") as! Bool) {
Image(systemName: "eye.slash")
.foregroundColor(.red)
} else {
Image(systemName: "eye")
} }
} }
} }
// When an event gets updated from child view, reload it here as this will not trigger the onAppear() function
.onReceive(event.objectWillChange, perform: { _ in
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
let sortDescriptors = [sectionSortDescriptor]
self.events = []
self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
})
}
}
.navigationBarTitle(Text("Lectures"))
// .navigationBarItems(trailing: {
// Button(action: {
// // This is obviously bullshit, but it could be used to sort afer summary or smth like that
//
// self.sortingAscending = !self.sortingAscending
// let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: sortingAscending)
// let sortDescriptors = [sectionSortDescriptor]
// self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
// }){
// Text("Switch order")
// }
// })
}.onAppear{ }.onAppear{
let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true) let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
let sortDescriptors = [sectionSortDescriptor] let sortDescriptors = [sectionSortDescriptor]
self.events = []
self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors) self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors)
} }
} }