d2l_sdk 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,213 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+ require 'zip'
4
+ require 'csv'
5
+ ##########################
6
+ # DATA HUB Import/Export##
7
+ ##########################
8
+
9
+ # Requirements to work properly:
10
+ # !!! 1. Custom Reporting Framework must be on
11
+ # --- Organization Tools > Custom Reporting Framework > Click "Availability" Slider
12
+ # --- This should have enabled it, otherwise you may need further permissions
13
+ # !!! 2. Next, the API user must have the permissions
14
+ # --- Roles and Permissions > ROLE > Filter by 'Custom Reporting Framework' >
15
+ # --- Enable all reports you need.
16
+ # !!! 3. EACH data set has its own permissions. These must be enabled.
17
+ # --- The Insights tool must be on, this can be checked at:
18
+ # ----- "Config variable browser" > tools > insights > ETL > isEnabled
19
+ # ----- If the value is 0, then you must contact support to enable it
20
+ # ----- If the value is 1, then move onto the next sub-step
21
+ # --- Roles and Permissions > ROLES> Filter by 'Insights' > Enable "Can Export
22
+ # --- Data Warehouse Reports" permission
23
+
24
+ # Lists all available data sets
25
+ def get_all_data_sets
26
+ _get("/d2l/api/lp/#{$lp_ver}/dataExport/list")
27
+ # returns a JSON array of DataSetData blocks
28
+ end
29
+
30
+ # Retrieve a data set
31
+ def get_data_set(data_set_id)
32
+ _get("/d2l/api/lp/#{$lp_ver}/dataExport/list/#{data_set_id}")
33
+ # returns a DataSetData JSON block
34
+ end
35
+
36
+ # assures that the CreateExportJobData JSON block is valid based off of a
37
+ # specified JSON schema.
38
+ # filter names: startDate, endDate, roles, and parentOrgUnitId
39
+ # --- startDate and EndDate must be UTC dates
40
+ # --- parentOrgUnitId and roles are integers corresponding to an ou_id & role_id
41
+ def validate_create_export_job_data(create_export_job_data)
42
+ schema = {
43
+ 'type' => 'object',
44
+ # 'title'=>'the CreateExportJobData JSON block',
45
+ 'required' => %w(DataSetId Filters),
46
+ 'properties' => {
47
+ 'DataSetId' => { 'type' => 'string' },
48
+ 'Filters' => { # define the filter array
49
+ # 'description' => 'The array of filters for CreateExportJobData',
50
+ 'type' => 'array',
51
+ 'items' =>
52
+ {
53
+ 'type' => "object",
54
+ "properties" => {
55
+ "Name" => {'type'=>"string"},
56
+ "Value" => {'type'=>"string"}
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ #ap schema
63
+ JSON::Validator.validate!(schema, create_export_job_data, validate_schema: true)
64
+ # returns true if the CreateExportJobData JSON block is valid
65
+ end
66
+
67
+ # Create an export job for the requested data set
68
+ def create_export_job(create_export_job_data)
69
+ # init payload and merge with export job data
70
+ payload = {
71
+ 'DataSetId' => '',
72
+ 'Filters' => [] # {"Name"=> "startDate", "Value" => UTCDATETIME STRING}
73
+ }.merge!(create_export_job_data)
74
+ validate_create_export_job_data(payload)
75
+ # Requires: CreateExportJobData JSON parameter
76
+ path = "/d2l/api/lp/#{$lp_ver}/dataExport/create"
77
+ _post(path, payload)
78
+ # returns ExportJobData JSON block
79
+ end
80
+
81
+ # List all available export jobs that you have previously submitted
82
+ def get_all_export_jobs(bookmark = '') # optional parameter page -- integer
83
+ path = "/d2l/api/lp/#{$lp_ver}/dataExport/jobs"
84
+ path += "?bookmark=#{bookmark}" if bookmark != ''
85
+ _get(path)
86
+ # returns: JSON array of paged ExportJobData blocks, sorted by SubmitDate
87
+ end
88
+
89
+ # Retrieves information about a data export job that you have previously submitted.
90
+ def get_data_export_job(export_job_id)
91
+ _get("/d2l/api/lp/#{$lp_ver}/dataExport/jobs/#{export_job_id}")
92
+ # returns: ExportJobData JSON block
93
+ end
94
+
95
+ def get_job_status_code(export_job_id)
96
+ get_data_export_job(export_job_id)["Status"] #if 2 is OKAY/COMPLETED
97
+ end
98
+
99
+ # Downloads the identified job and stores the zip within the working directory
100
+ # Extracts zipped job contents in "export_jobs" folder of working directory
101
+ def download_job_csv(export_job_id)
102
+ attempt = 0
103
+ puts "Attempting to download job: #{export_job_id}"
104
+ while attempt < 20 # Attempts 20 times (~3 mins) unless job failed.
105
+ status = get_job_status_code(export_job_id)
106
+ case status
107
+ when 2 # If the status was okay, break loop + return download of job
108
+ zip_fname = 'export1.zip'
109
+ puts "Job complete, writing to zip: #{zip_fname}"
110
+ File.write(zip_fname,_get_raw("/d2l/api/lp/#{$lp_ver}/dataExport/download/#{export_job_id}"))
111
+ unzip(zip_fname, /sec_|off_/) # unzip file; filter if Enrollments + CSV
112
+ puts "file downloaded and unzipped"
113
+ break
114
+ when /3|4/
115
+ puts "Job download failed due to status: #{status}"
116
+ if status == 3
117
+ puts "Status description: Error - An error occurred when processing the export"
118
+ else
119
+ puts "Status description: Deleted - File was deleted from file system"
120
+ end
121
+ break
122
+ else # else, print out the status and wait 10 seconds before next attempt
123
+ puts "The job is not currently ready to download\n Status Code: #{status}"
124
+ if status == 0
125
+ puts "Status description: Queued - Export job has been received for processing."
126
+ else
127
+ puts "Status description: Processing - Currently in process of exporting data set."
128
+ end
129
+ puts "Sleeping for 10 seconds.."
130
+ sleep 10
131
+ attempt = attempt + 1
132
+ end
133
+ # returns: ZIP file containing a CSV file of data from the export job
134
+ end
135
+ end
136
+
137
+ # Unzip the file, applying a regex filter to the CSV if
138
+ # the file is Enrollments data.
139
+ def unzip(file_path, csv_filter = //)
140
+ puts "Unzipping file: #{file_path}"
141
+ # Unzip the file
142
+ Zip::File.open(file_path) { |zip_file|
143
+ # for each file in the zip file
144
+ zip_file.each { |f|
145
+ # create file path of export_jobs/#{f.name}
146
+ f_path=File.join("export_jobs", f.name)
147
+ # make the directory if not already made
148
+ FileUtils.mkdir_p(File.dirname(f_path))
149
+ # extract the file unless the file already exists
150
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
151
+ # if the file is CSV and Enrollments, apply filters and proper
152
+ # CSV formatting to the file, writing it as base f.name + filtered.csv
153
+ if (f.name.include? ".csv") && (f.name.include? "Enrollments")
154
+ filter_formatted_enrollments("export_jobs/#{f.name}", csv_filter, "export_jobs/instr.csv")
155
+ end
156
+ }
157
+ }
158
+ end
159
+
160
+ # Get all 'current' courses, assuming all instr courses are current
161
+ # and add their sec/off course_term_star_num codes to a set.
162
+ # return: set of current classes formatted as "#{course_term}_#{star_number}"
163
+ def get_current_courses(csv_fname)
164
+ puts "Retrieving current courses from #{csv_fname}"
165
+ instr_courses = Set.new
166
+ CSV.foreach(csv_fname, :headers => true) do |row|
167
+ star_number = row[0]
168
+ course_term = row[10]
169
+ instr_courses.add("#{course_term}_#{star_number}")
170
+ end
171
+ instr_courses
172
+ end
173
+
174
+ # Filter all enrollments and withdrawals in a csv file, excluding data
175
+ # that is not properly formatted (based on ou code), not a current or
176
+ # future course, or nil for their ou code.
177
+ def filter_formatted_enrollments(csv_fname, regex_filter = //, instr_fname)
178
+ # Create csv with 'filtered' pre-appended to '.csv' substring
179
+ filtered_csv = csv_fname.gsub(/\.csv/,"filtered.csv")
180
+ File.open(filtered_csv, 'w') do |file|
181
+ # set row num to 0 to keep track of headers
182
+ row_num = 0
183
+ current = get_current_courses(instr_fname)
184
+ # for each row
185
+ puts "Filtering #{csv_fname}"
186
+ CSV.foreach(csv_fname) do |row|
187
+ # the line is initialized as an empty string
188
+ line = ""
189
+ # Skip the row if not a valid
190
+ # or skip in-filter OU_code,
191
+ # or skip if the header
192
+ # or skip if not within the INSTR SET of current/future courses
193
+ if row[3] == nil || row_num > 0 && !(row[3] =~ regex_filter) || (!current.include? row[3][4..-1])
194
+ row_num += 1
195
+ next
196
+ end
197
+ # for values not filtered from above ^
198
+ # for all of these values
199
+ row[0..-1].each do |value|
200
+ # If it a UTC date time value, then parse as Time.
201
+ if value =~ /\b[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]*Z\b/ # if the value is UTC formatted
202
+ line << "\"#{Time.parse(value)}\""
203
+ elsif value == row[-1]# if its the last value in the row
204
+ line <<"\"#{value}\"" # then dont put a comma at the end.
205
+ else # not the last value in the row,
206
+ line << "\"#{value}\"," # throw a comma after the value
207
+ end
208
+ end
209
+ file.write(line + "\n") # append this line to the csv
210
+ row_num += 1 # increment the row number
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,89 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+
4
+ ########################
5
+ # DEMOGRPAHICS:#########
6
+ ########################
7
+
8
+ ###### Actions
9
+
10
+ # Delete one or more of a particular user's associated demographics entries.
11
+ # if no entries specified, it DELETES ALL.
12
+ # entry_ids are added as additional variables
13
+ # entry_ids is a CSV formatted string
14
+ def delete_user_demographics(user_id, entry_ids = '')
15
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/users/#{user_id}"
16
+ path += "?entryIds=" + entry_ids if entry_ids != ''
17
+ _delete(path)
18
+ end
19
+
20
+ # optional params: fieldIds, roleIds, and userIds are CSV formatted Strings
21
+ # search and bookmark are Strings
22
+ # retrieve all the demographics entries for all users enrolled in an OU
23
+ def get_all_demographics_by_org_unit(org_unit_id, field_ids = '', role_ids = '',
24
+ user_ids = '', search = '', bookmark = '')
25
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/orgUnits/#{org_unit_id}/users/"
26
+ path += "?fieldIds=" + field_ids if field_ids != ''
27
+ path += "?roleIds=" + role_ids if role_ids != ''
28
+ path += "?userIds=" + user_ids if user_ids != ''
29
+ path += "?search=" + search if search != ''
30
+ path += "?bookmark=" + bookmark if bookmark != ''
31
+ _get(path)
32
+ # returns paged result set of DemographicsUserEntryData JSON blocks
33
+ end
34
+
35
+ # retrieve all the demographics entries for a specific user within an OU
36
+ def get_all_demographics_by_org_unit_by_user(org_unit_id, user_id, field_ids = '')
37
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/orgUnits/#{org_unit_id}/users/(#{user_id})"
38
+ path += "#{field_ids}" if field_ids != ''
39
+ _get(path)
40
+ # returns DemographicsUserEntryData JSON block
41
+ end
42
+
43
+ # retrieve all demographics entries for all users with specified filters
44
+ def get_all_demographics(field_ids = '', role_ids = '', user_ids = '',
45
+ search = '', bookmark = '')
46
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/users/"
47
+ path += "#{field_ids}" if field_ids != ''
48
+ path += "#{role_ids}" if role_ids != ''
49
+ path += "#{user_ids}" if user_ids != ''
50
+ path += "#{search}" if search != ''
51
+ path += "#{bookmark}" if bookmark != ''
52
+ _get(path)
53
+ # returns paged result set of DemographicsUserEntryData JSON blocks
54
+ end
55
+
56
+
57
+ ###### FIELDS
58
+ # retrieve list of all demographics fields
59
+ def get_all_demographic_fields(bookmark = '')
60
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/fields/"
61
+ path += "#{bookmark}" if bookmark != ''
62
+ _get(path)
63
+ # returns paged result set of DemographicsField JSON blocks
64
+ end
65
+
66
+ # retrieve a single demographic field
67
+ def get_demographic_field(field_id)
68
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/fields/#{field_id}"
69
+ _get(path)
70
+ # returns fetch form of DemographicsField JSON block
71
+ end
72
+
73
+ ###### DATA TYPES
74
+
75
+ # retrieve the list of all demographics data types
76
+ # uses DataTypeId's as a paging control value
77
+ def get_all_demographic_types(bookmark = '')
78
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/dataTypes/"
79
+ path += "#{bookmark}" if bookmark != ''
80
+ _get(path)
81
+ # returns paged result set of DemographicsDataType JSON blocks
82
+ end
83
+
84
+ # retrieve a single demographic data type
85
+ def get_demographic_type(data_type_id)
86
+ path = "/d2l/api/lp/#{$lp_ver}/demographics/dataTypes/#{data_type_id}"
87
+ _get(path)
88
+ # returns DemographicsDataType JSON block
89
+ end
@@ -0,0 +1,133 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+ ########################
4
+ # Enrollments:##########
5
+ ########################
6
+
7
+ # Check the validity of the CreateEnrollmentData that is passed as a payload
8
+ def check_create_enrollment_data_validity(enrollment_data)
9
+ schema = {
10
+ 'type' => 'object',
11
+ 'required' => %w(OrgUnitId UserId RoleId),
12
+ 'properties' => {
13
+ 'OrgUnitId' => { 'type' => 'integer' },
14
+ 'UserId' => { 'type' => 'integer' },
15
+ 'RoleId' => { 'type' => 'integer' },
16
+ }
17
+ }
18
+ JSON::Validator.validate!(schema, enrollment_data, validate_schema: true)
19
+ end
20
+
21
+ # Create a new enrollment for a user.
22
+ def create_user_enrollment(course_enrollment_data)
23
+ payload = { 'OrgUnitId' => '', # String
24
+ 'UserId' => '', # String
25
+ 'RoleId' => '', # String
26
+ }.merge!(course_enrollment_data)
27
+ # ap payload
28
+ # requires: CreateEnrollmentData JSON block
29
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/"
30
+ _post(path, payload)
31
+ puts '[+] User successfully enrolled'.green
32
+ # Returns: EnrollmentData JSON block for the newly enrolled user.
33
+ end
34
+
35
+ # Retrieve enrollment details in an org unit for the provided user.
36
+ # Same as +get_org_unit_enrollment_data_by_user+
37
+ def get_user_enrollment_data_by_org_unit(user_id, org_unit_id)
38
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/users/#{user_id}/orgUnits/#{org_unit_id}"
39
+ _get(path)
40
+ # Returns: EnrollmentData JSON block.
41
+ end
42
+
43
+ # Retrieve a list of all enrollments for the provided user.
44
+ # Optional params:
45
+ # --orgUnitTypeId (CSV of D2LIDs)
46
+ # --roleId: D2LIDs
47
+ # --bookmark: string
48
+ def get_all_enrollments_of_user(user_id, org_unit_type_id = 0, role_id = 0,
49
+ bookmark = '')
50
+ path = "/d2l/api/lp/1.3/enrollments/users/#{user_id}/orgUnits/"
51
+ path += "?orgUnitTypeId=#{org_unit_type_id}" if org_unit_type_id != 0
52
+ path += "?roleId=#{role_id}" if role_id != 0
53
+ path += "?bookmark=#{bookmark}" if bookmark != ''
54
+ _get(path)
55
+ # Returns: paged result set w/ the resulting UserOrgUnit data blocks
56
+ end
57
+
58
+ # Retrieve enrollment details for a user in the provided org unit.
59
+ # Note:
60
+ # Same as +get_user_enrollment_data_by_org_unit+
61
+ # This call is equivalent to the route that fetches by specifying the user first,
62
+ # and then the org unit.
63
+ def get_org_unit_enrollment_data_by_user(org_unit_id, user_id)
64
+ path = "/d2l/api/lp/#{$lp_ver}/orgUnits/#{org_unit_id}/users/#{user_id}"
65
+ _get(path)
66
+ # Returns: EnrollmentData JSON block.
67
+ end
68
+
69
+ # Retrieve the collection of users enrolled in the identified org unit.
70
+ # Optional params:
71
+ # --roleId: D2LID
72
+ # --bookmark: String
73
+ def get_org_unit_enrollments(org_unit_id, role_id = 0, bookmark = '')
74
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/orgUnits/#{org_unit_id}/users/"
75
+ path += "?roleId=#{role_id}" if role_id != 0
76
+ path += "?bookmark=#{bookmark}" if bookmark != ''
77
+ _get(path)
78
+ # Returns: paged result set containing the resulting OrgUnitUser data blocks
79
+ end
80
+
81
+ # Retrieve the enrollment details for the current user in the provided org unit.
82
+ def get_enrollments_details_of_current_user
83
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/myenrollments/org_unit_id/"
84
+ _get(path)
85
+ # Returns: MyOrgUnitInfo JSON block.
86
+ end
87
+
88
+ # Retrieve the list of all enrollments for the current user
89
+ # Optional params:
90
+ # --orgUnitTypeId: CSV of D2LIDs
91
+ # --bookmark: String
92
+ # --sortBy: string
93
+ # --isActive: bool
94
+ # --startDateTime: UTCDateTime
95
+ # --endDateTime: UTCDateTime
96
+ # --canAccess: bool
97
+ def get_all_enrollments_of_current_user(bookmark = '', sort_by = '', is_active = nil,
98
+ start_date_time = '', end_date_time = '',
99
+ can_access = nil)
100
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/myenrollments/"
101
+ path += "?bookmark=#{bookmark}" if bookmark != ''
102
+ path += "?sortBy=#{sort_by}" if sort_by != ''
103
+ path += "?isActive=#{is_active}" if is_active != nil
104
+ path += "?startDateTime=#{start_date_time}" if start_date_time != ''
105
+ path += "?endDateTime=#{end_date_time}" if end_date_time != ''
106
+ path += "?canAccess=#{can_access}" if can_access != nil
107
+ _get(path)
108
+ # Returns: paged result set containing the resulting MyOrgUnitInfo data blocks
109
+ end
110
+
111
+ # Retrieve the enrolled users in the classlist for an org unit
112
+ def get_enrolled_users_in_classlist(org_unit_id)
113
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/classlist/"
114
+ _get(path)
115
+ # Returns: JSON array of ClasslistUser data blocks.
116
+ end
117
+
118
+ # Delete a user’s enrollment in a provided org unit.
119
+ def delete_user_enrollment(user_id, org_unit_id)
120
+ path = "/d2l/api/lp/#{$lp_ver}/users/#{user_id}/orgUnits/#{org_unit_id}"
121
+ _delete(path)
122
+ # Returns: EnrollmentData JSON block showing the enrollment status
123
+ # just before this action deleted the enrollment of the user
124
+ end
125
+
126
+
127
+ # Delete a user’s enrollment in a provided org unit.
128
+ def delete_user_enrollment_alternative(user_id, org_unit_id)
129
+ path = "/d2l/api/lp/#{$lp_ver}/enrollments/orgUnits/#{org_unit_id}/users/#{user_id}"
130
+ _delete(path)
131
+ # Returns: EnrollmentData JSON block showing the enrollment status
132
+ # just before this action deleted the enrollment of the user
133
+ end
@@ -0,0 +1,232 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+ ####################################
4
+ # Groups/Group Categories:##########
5
+ ####################################
6
+ # Delete a particular group category from an org unit.
7
+ def delete_group_category(org_unit_id, group_category_id)
8
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}"
9
+ _delete(path)
10
+ end
11
+
12
+ # Delete a particular group from an org unit.
13
+ def delete_group(org_unit_id, group_category_id, group_id)
14
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/(groupId)"
15
+ _delete(path)
16
+ end
17
+
18
+ # Remove a particular user from a group.
19
+ def remove_user_from_group(org_unit_id, group_category_id, group_id, user_id)
20
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/#{group_id}/enrollments/#{user_id}"
21
+ _delete(path)
22
+ end
23
+
24
+ # Retrieve a list of all the group categories for the provided org unit.
25
+ def get_all_org_unit_group_categories(org_unit_id)
26
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/"
27
+ _get(path)
28
+ end
29
+
30
+ # Retrieve a particular group category for an org unit.
31
+ def get_org_unit_group_category(org_unit_id, group_category_id)
32
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}"
33
+ _get(path)
34
+ end
35
+
36
+ # Retrieve a list of all the groups in a specific group category for an OrgUnit
37
+ def get_all_group_category_groups(org_unit_id, group_category_id)
38
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/"
39
+ _get(path)
40
+ end
41
+
42
+ # Retrieve a particular group in an org unit.
43
+ def get_org_unit_group(org_unit_id, group_category_id, group_id)
44
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/#{group_id}"
45
+ _get(path)
46
+ end
47
+
48
+ ######
49
+ ######
50
+
51
+ def validate_create_group_category_data(group_category_data)
52
+ schema = {
53
+ 'type' => 'object',
54
+ 'required' => %w(Name Description EnrollmentStyle
55
+ EnrollmentQuality AutoEnroll RandomizeEnrollments
56
+ NumberOfGroups MaxUsersPerGroup AllocateAfterExpiry
57
+ SelfEnrollmentExpiryDate GroupPrefix),
58
+ 'properties' => {
59
+ 'Name' => { 'type' => 'string' },
60
+ 'Description' =>
61
+ {
62
+ 'type' => 'object',
63
+ 'properties'=>{
64
+ "Content" => "string",
65
+ "Type" => "string" #"Text|HTML"
66
+ }
67
+ }, #RichTextInput
68
+ # if set to SingleUserMemberSpecificGroup, values set for NumberOfGroups
69
+ # and MaxUsersPerGroup are IGNORED
70
+ # ----------------------------------
71
+ # GPRENROLL_T integer value meanings
72
+ # 0 = NumberOfGrupsNoEnrollment ^
73
+ # 1 = PeoplePerGroupAutoEnrollment
74
+ # 2 = NumerOfGroupsAutoEnrollment
75
+ # 3 = PeoplePerGroupSelfEnrollment
76
+ # 4 = SelfEnrollmentNumberOfGroups
77
+ # 5 = PeoplePerNumberOfGroupsSelfEnrollment
78
+ # ----------------------------------
79
+ 'EnrollmentStyle' => { 'type' => 'integer' }, #num GRPENROLL_T
80
+ # if non-nil, values for NumberOfGroups and MaxUsersPerGroup are IGNORED
81
+ 'EnrollmentQuantity' => { 'type' => %w(integer null) },
82
+ 'AutoEnroll' => { 'type' => 'boolean'},
83
+ 'RandomizeEnrollments' => { 'type' => 'boolean' },
84
+ 'NumberOfGroups' => { 'type' => %w(integer null) }, #nil, 0, 1, 3, 5
85
+ 'MaxUsersPerGroup' => { 'type' => %w(integer null) }, #1, 3, 5
86
+ # if MaxUsersPerGroup has a value, then set this to true.
87
+ 'AllocateAfterExpiry' => { 'type' => 'boolean' },
88
+ 'SelfEnrollmentExpiryDate' => { 'type' => %w(string null) }, #UTCDATETIME
89
+ # Prepends group prefix to GroupName and GroupCode
90
+ 'GroupPrefix' => { 'type' => %w(string null) }
91
+ }
92
+ }
93
+ JSON::Validator.validate!(schema, group_category_data, validate_schema: true)
94
+ end
95
+
96
+ ####
97
+ #### See +validate_create_group_category_data+ for details on schema formal
98
+ #### requirements of values
99
+ # Create a new group category for an org unit.
100
+ def create_org_unit_group_category(org_unit_id, group_category_data)
101
+ payload = { 'Name' => '', # String
102
+ 'Description' => {}, # RichTextInput
103
+ 'EnrollmentStyle' => 0, # number : group_enroll
104
+ 'EnrollmentQuantity' => nil, # number | null
105
+ 'AutoEnroll' => false, # bool
106
+ 'RandomizeEnrollments' => false, # bool
107
+ 'NumberOfGroups' => nil, # number | nil
108
+ 'MaxUsersPerGroup' => nil, # number | nil
109
+ 'AllocateAfterExpiry' => false, # bool
110
+ 'SelfEnrollmentExpiryDate' => nil, # string: UTCDateTime | nil
111
+ 'GroupPrefix' => nil, # String | nil
112
+ }.merge!(group_category_data)
113
+ # Requires: JSON block of GroupCategoryData
114
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/"
115
+ _post(path, payload)
116
+ # returns a GroupCategoryData JSON block, in the Fetch form, of the new categ.
117
+ end
118
+
119
+ def validate_group_data(group_data)
120
+ schema =
121
+ {
122
+ 'type' => 'object',
123
+ 'required' => %w(Name Code Description),
124
+ 'properties' =>
125
+ {
126
+ 'Name' => { 'type' => 'string' },
127
+ "Code" => {'type' => 'string'},
128
+ 'Description' =>
129
+ {
130
+ 'type' => 'object',
131
+ 'properties'=>
132
+ {
133
+ "Content" => "string",
134
+ "Type" => "string" #"Text|HTML"
135
+ }
136
+ }
137
+ }
138
+ }
139
+ JSON::Validator.validate!(schema, group_data, validate_schema: true)
140
+ end
141
+
142
+ # Create a new group for an org unit.
143
+ def create_org_unit_group(org_unit_id, group_category_id, group_data)
144
+ payload =
145
+ {
146
+ "Name" => "string",
147
+ "Code" => "string",
148
+ "Description" => {}
149
+ }.merge!(group_data)
150
+ # Requires: JSON block of GroupData
151
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/"
152
+ _post(path, payload)
153
+ # returns a GroupData JSON block, in the Fetch form, of the new group
154
+ end
155
+
156
+ # Update a particular group for an org unit
157
+ def update_org_unit_group(org_unit_id, group_category_id, group_id, group_data)
158
+ payload = {
159
+ "Name" => "string",
160
+ "Code" => "string",
161
+ "Description" => {}
162
+ }.merge!(group_data)
163
+ # Requires: JSON block of GroupData
164
+ validate_group_data(payload)
165
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/#{group_id}"
166
+ # returns a GroupData JSON block, in the Fetch form, of the updated group.
167
+ _put(path, payload)
168
+ end
169
+
170
+ def validate_group_enrollment_data(group_enrollment_data)
171
+ schema = {
172
+ 'type' => 'object',
173
+ 'required' => %w(UserId),
174
+ 'properties' => {
175
+ 'UserId' => { 'type' => 'integer' }
176
+ }
177
+ }
178
+ JSON::Validator.validate!(schema, course_data, validate_schema: true)
179
+ end
180
+
181
+ # Enroll a user in a group
182
+ def enroll_user_in_group(org_unit_id, group_category_id, group_id, user_id)
183
+ payload = {
184
+ "UserId" => user_id
185
+ }
186
+ # Requires: JSON block of GroupEnrollment
187
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/groups/#{group_id}/enrollments/"
188
+ validate_group_enrollment_data(payload)
189
+ _post(path, payload)
190
+ end
191
+
192
+ def validate_update_group_category_data(group_category_data)
193
+ schema = {
194
+ 'type' => 'object',
195
+ 'required' => %w(Name Description AutoEnroll RandomizeEnrollments),
196
+ 'properties' => {
197
+ 'Name' => { 'type' => 'string' },
198
+ 'Description' =>
199
+ {
200
+ 'type' => 'object',
201
+ 'properties'=>{
202
+ "Content" => "string",
203
+ "Type" => "string" #"Text|HTML"
204
+ }
205
+ },
206
+ 'AutoEnroll' => { 'type' => 'boolean'},
207
+ 'RandomizeEnrollments' => { 'type' => 'boolean' }
208
+ }
209
+ }
210
+ JSON::Validator.validate!(schema, group_category_data, validate_schema: true)
211
+ end
212
+
213
+ # update a particular group category for an org unit
214
+ def update_org_unit_group_category(org_unit_id, group_category_id, group_category_data)
215
+
216
+ payload = { 'Name' => '', # String
217
+ 'Description' => {}, # RichTextInput
218
+ 'AutoEnroll' => false, # bool
219
+ 'RandomizeEnrollments' => false, # bool
220
+ }.merge!(group_category_data)
221
+ # Requires: JSON block of GroupCategoryData
222
+ validate_update_group_category_data(payload)
223
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_data}"
224
+ _put(path, payload)
225
+ # Returns a GroupCategoryData JSON block, in the Fetch form, of updated grp. cat.
226
+ end
227
+
228
+ def is_group_category_locker_set_up(org_unit_id, group_category_id)
229
+ path = "/d2l/api/lp/#{$lp_ver}/#{org_unit_id}/groupcategories/#{group_category_id}/locker"
230
+ _get(path)["HasLocker"]
231
+ #returns true if the group cat. locker has been setup already
232
+ end