Skip to content

Commit

Permalink
feat: Calendar Sync Feature Analytics Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
shafqat-muneer authored Apr 15, 2024
1 parent 16b17b6 commit a9c562d
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 25 deletions.
14 changes: 11 additions & 3 deletions Core/Core/Analytics/CoreAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public enum AnalyticsEvent: String {
case courseOutlineDiscussionTabClicked = "Course:Discussion Tab"
case courseOutlineHandoutsTabClicked = "Course:Handouts Tab"
case datesComponentClicked = "Dates:Course Component Clicked"
case datesCalendarSyncToggle = "Dates:CalendarSync Toggle"
case datesCalendarSyncDialogAction = "Dates:CalendarSync Dialog Action"
case datesCalendarSyncSnackbar = "Dates:CalendarSync Snackbar"
case plsBannerViewed = "PLS:Banner Viewed"
case plsShiftDatesClicked = "PLS:Shift Button Clicked"
case plsShiftDatesSuccess = "PLS:Shift Dates Success"
Expand Down Expand Up @@ -157,7 +160,10 @@ public enum EventBIValue: String {
case cookiePolicyClicked = "edx.bi.app.profile.cookie_policy.clicked"
case profileDeleteAccountClicked = "edx.bi.app.profile.delete_account.clicked"
case userLogout = "edx.bi.app.user.logout"
case datesComponentClicked = "edx.bi.app.coursedates.component.clicked"
case datesComponentClicked = "edx.bi.app.dates.component.clicked"
case datesCalendarSyncToggle = "edx.bi.app.dates.calendar_sync.toggle"
case datesCalendarSyncDialogAction = "edx.bi.app.dates.calendar_sync.dialog_action"
case datesCalendarSyncSnackbar = "edx.bi.app.dates.calendar_sync.snackbar"
case plsBannerViewed = "edx.bi.app.dates.pls_banner.viewed"
case plsShiftDatesClicked = "edx.bi.app.dates.pls_banner.shift_dates.clicked"
case plsShiftDatesSuccess = "edx.bi.app.dates.pls_banner.shift_dates.success"
Expand Down Expand Up @@ -208,8 +214,6 @@ public struct EventParamKey {
public static let topicName = "topic_name"
public static let blockID = "block_id"
public static let blockName = "block_name"
public static let unitID = "unit_id"
public static let unitName = "unit_name"
public static let method = "method"
public static let label = "label"
public static let coursesCount = "courses_count"
Expand All @@ -233,6 +237,10 @@ public struct EventParamKey {
public static let noOfVideos = "number_of_videos"
public static let supported = "supported"
public static let conversion = "conversion"
public static let enrollmentMode = "enrollment_mode"
public static let pacing = "pacing"
public static let dialog = "dialog"
public static let snackbar = "snackbar"
}

public struct EventCategory {
Expand Down
5 changes: 4 additions & 1 deletion Core/Core/Domain/Model/CourseBlockModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public struct CourseStructure: Equatable {
public var childs: [CourseChapter]
public let media: DataLayer.CourseMedia //FIXME Domain model
public let certificate: Certificate?
public let isSelfPaced: Bool

public init(
id: String,
Expand All @@ -33,7 +34,8 @@ public struct CourseStructure: Equatable {
topicID: String? = nil,
childs: [CourseChapter],
media: DataLayer.CourseMedia,
certificate: Certificate?
certificate: Certificate?,
isSelfPaced: Bool
) {
self.id = id
self.graded = graded
Expand All @@ -45,6 +47,7 @@ public struct CourseStructure: Equatable {
self.childs = childs
self.media = media
self.certificate = certificate
self.isSelfPaced = isSelfPaced
}

public func totalVideosSizeInBytes(downloadQuality: DownloadQuality) -> Int {
Expand Down
12 changes: 10 additions & 2 deletions Course/Course.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
02F0144E28F46474002E513D /* CourseContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseContainerView.swift; sourceTree = "<group>"; };
02F0145628F4A2FF002E513D /* CourseContainerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseContainerViewModel.swift; sourceTree = "<group>"; };
02F066E729DC71750073E13B /* SubtittlesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtittlesView.swift; sourceTree = "<group>"; };
02F175362A4DAFD20019CD70 /* CourseAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseAnalytics.swift; sourceTree = "<group>"; };
02F175362A4DAFD20019CD70 /* CourseAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CourseAnalytics.swift; path = ../Presentation/CourseAnalytics.swift; sourceTree = "<group>"; };
02F3BFDC29252E900051930C /* CourseRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseRouter.swift; sourceTree = "<group>"; };
02F78AEA29E6BCA20038DE30 /* VideoPlayerViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VideoPlayerViewModelTests.swift; path = CourseTests/Presentation/Unit/VideoPlayerViewModelTests.swift; sourceTree = SOURCE_ROOT; };
02F98A8028F8224200DE94C0 /* Discussion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Discussion.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -292,6 +292,7 @@
0289F8F028E1C3510064F8F3 /* Course */ = {
isa = PBXGroup;
children = (
979A6AB92BC3FFF8001B0DE3 /* Analytics */,
02B6B3AD28E1C47100232911 /* SwiftGen */,
02B6B3B828E1D12900232911 /* Data */,
02B6B3B528E1D10700232911 /* Domain */,
Expand Down Expand Up @@ -394,7 +395,6 @@
BAC0E0DC2B32F0EA006B68A9 /* Downloads */,
BAD9CA482B2C88D500DE790A /* Subviews */,
02F3BFDC29252E900051930C /* CourseRouter.swift */,
02F175362A4DAFD20019CD70 /* CourseAnalytics.swift */,
);
path = Presentation;
sourceTree = "<group>";
Expand Down Expand Up @@ -506,6 +506,14 @@
path = Mock;
sourceTree = "<group>";
};
979A6AB92BC3FFF8001B0DE3 /* Analytics */ = {
isa = PBXGroup;
children = (
02F175362A4DAFD20019CD70 /* CourseAnalytics.swift */,
);
path = Analytics;
sourceTree = "<group>";
};
97CA95212B875EA200A9EDEA /* Views */ = {
isa = PBXGroup;
children = (
Expand Down
6 changes: 4 additions & 2 deletions Course/Course/Data/CourseRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ public class CourseRepository: CourseRepositoryProtocol {
topicID: courseBlock.userViewData?.topicID,
childs: childs,
media: course.media,
certificate: course.certificate?.domain
certificate: course.certificate?.domain,
isSelfPaced: course.isSelfPaced
)
}

Expand Down Expand Up @@ -346,7 +347,8 @@ And there are various ways of describing it-- call it oral poetry or
topicID: courseBlock.userViewData?.topicID,
childs: childs,
media: course.media,
certificate: course.certificate?.domain
certificate: course.certificate?.domain,
isSelfPaced: course.isSelfPaced
)
}

Expand Down
13 changes: 12 additions & 1 deletion Course/Course/Data/Model/Data_CourseOutlineResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,31 @@ public extension DataLayer {
public let id: String
public let media: DataLayer.CourseMedia
public let certificate: Certificate?
public let isSelfPaced: Bool

enum CodingKeys: String, CodingKey {
case blocks
case rootItem = "root"
case id
case media
case certificate
case isSelfPaced = "is_self_paced"
}

public init(rootItem: String, dict: Blocks, id: String, media: DataLayer.CourseMedia, certificate: Certificate?) {
public init(
rootItem: String,
dict: Blocks,
id: String,
media: DataLayer.CourseMedia,
certificate: Certificate?,
isSelfPaced: Bool
) {
self.rootItem = rootItem
self.dict = dict
self.id = id
self.media = media
self.certificate = certificate
self.isSelfPaced = isSelfPaced
}

public init(from decoder: Decoder) throws {
Expand All @@ -44,6 +54,7 @@ public extension DataLayer {
id = try values.decode(String.self, forKey: .id)
media = try values.decode(DataLayer.CourseMedia.self, forKey: .media)
certificate = try values.decode(Certificate.self, forKey: .certificate)
isSelfPaced = try values.decode(Bool.self, forKey: .isSelfPaced)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23D60" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23E214" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="CDCourseBlock" representedClassName="CDCourseBlock" syncable="YES" codeGenerationType="class">
<attribute name="allSources" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" customClassName="[String]"/>
<attribute name="blockId" optional="YES" attributeType="String"/>
Expand Down Expand Up @@ -79,6 +79,7 @@
<entity name="CDCourseStructure" representedClassName="CDCourseStructure" syncable="YES" codeGenerationType="class">
<attribute name="certificate" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="String"/>
<attribute name="isSelfPaced" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="mediaLarge" optional="YES" attributeType="String"/>
<attribute name="mediaRaw" optional="YES" attributeType="String"/>
<attribute name="mediaSmall" optional="YES" attributeType="String"/>
Expand Down
3 changes: 2 additions & 1 deletion Course/Course/Domain/CourseInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public class CourseInteractor: CourseInteractorProtocol {
topicID: course.topicID,
childs: newChilds,
media: course.media,
certificate: course.certificate
certificate: course.certificate,
isSelfPaced: course.isSelfPaced
)
}

Expand Down
76 changes: 76 additions & 0 deletions Course/Course/Presentation/CourseAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,44 @@
import Foundation
import Core

public enum EnrollmentMode: String {
case audit
case verified
case none
}

public enum CoursePacing: String {
case `self` = "self"
case instructor = "instructor"
}

public enum CalendarDialogueAction: String {
case on = "on"
case off = "off"
case allow = "allow"
case doNotAllow = "donot_allow"
case add = "add"
case cancel = "cancel"
case remove = "remove"
case update = "update"
case done = "done"
case viewEvent = "view_event"
}

public enum CalendarDialogueType: String {
case devicePermission = "device_permission"
case addCalendar = "add_calendar"
case removeCalendar = "remove_calendar"
case updateCalendar = "update_calendar"
case eventsAdded = "events_added"
}

public enum SnackbarType: String {
case added
case removed
case updated
}

//sourcery: AutoMockable
public protocol CourseAnalytics {
func resumeCourseClicked(courseId: String, courseName: String, blockId: String)
Expand All @@ -29,6 +67,25 @@ public protocol CourseAnalytics {
link: String,
supported: Bool
)
func calendarSyncToggle(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
action: CalendarDialogueAction
)
func calendarSyncDialogAction(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
dialog: CalendarDialogueType,
action: CalendarDialogueAction
)
func calendarSyncSnackbar(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
snackbar: SnackbarType
)
func trackCourseEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String)
func plsEvent(
_ event: AnalyticsEvent,
Expand Down Expand Up @@ -87,6 +144,25 @@ class CourseAnalyticsMock: CourseAnalytics {
link: String,
supported: Bool
) {}
func calendarSyncToggle(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
action: CalendarDialogueAction
) {}
func calendarSyncDialogAction(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
dialog: CalendarDialogueType,
action: CalendarDialogueAction
) {}
func calendarSyncSnackbar(
enrollmentMode: EnrollmentMode,
pacing: CoursePacing,
courseId: String,
snackbar: SnackbarType
) {}
public func trackCourseEvent(_ event: AnalyticsEvent, biValue: EventBIValue, courseID: String) {}
public func plsEvent(
_ event: AnalyticsEvent,
Expand Down
Loading

0 comments on commit a9c562d

Please sign in to comment.