├── LICENSE.md
├── README.md
├── assign.php
├── block_analytics_graphs.php
├── classes
├── event
│ ├── block_analytics_graphs_event_send_email.php
│ └── block_analytics_graphs_event_view_graph.php
└── privacy
│ └── provider.php
├── composer.json
├── db
├── access.php
├── install.xml
└── upgrade.php
├── edit_form.php
├── email.php
├── externalref
├── export-csv-master
│ ├── LICENSE
│ ├── README.md
│ ├── bower.json
│ ├── export-csv.js
│ ├── manifest.json
│ └── package.json
├── exporting.js
├── highcharts-3d.js
├── highcharts-more.js
├── highcharts.js
├── highstock.js
├── jquery-1.12.2.js
├── jquery-3.1.1.js
├── jquery-3.1.1.min.js
├── jquery-ui-1.12.1
│ ├── AUTHORS.txt
│ ├── LICENSE.txt
│ ├── external
│ │ └── jquery
│ │ │ └── jquery.js
│ ├── images
│ │ ├── ui-icons_444444_256x240.png
│ │ ├── ui-icons_555555_256x240.png
│ │ ├── ui-icons_777620_256x240.png
│ │ ├── ui-icons_777777_256x240.png
│ │ ├── ui-icons_cc0000_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── index.html
│ ├── jquery-ui.css
│ ├── jquery-ui.js
│ ├── jquery-ui.min.css
│ ├── jquery-ui.min.js
│ ├── jquery-ui.structure.css
│ ├── jquery-ui.structure.min.css
│ ├── jquery-ui.theme.css
│ ├── jquery-ui.theme.min.css
│ └── package.json
└── no-data-to-display.js
├── grades_chart.php
├── graph_submission.php
├── graphresourcestartup.php
├── graphresourceurl.php
├── groupjavascript.php
├── highslide
├── graphics
│ ├── close.png
│ ├── closeX.png
│ ├── controlbar-black-border.gif
│ ├── controlbar-text-buttons.png
│ ├── controlbar-white-small.gif
│ ├── controlbar-white.gif
│ ├── controlbar2.gif
│ ├── controlbar3.gif
│ ├── controlbar4-hover.gif
│ ├── controlbar4.gif
│ ├── fullexpand.gif
│ ├── geckodimmer.png
│ ├── icon.gif
│ ├── loader.gif
│ ├── loader.white.gif
│ ├── outlines
│ │ ├── Outlines.psd
│ │ ├── beveled.png
│ │ ├── drop-shadow.png
│ │ ├── glossy-dark.png
│ │ ├── outer-glow.png
│ │ ├── rounded-black.png
│ │ └── rounded-white.png
│ ├── resize.gif
│ ├── scrollarrows.png
│ ├── zoomin.cur
│ └── zoomout.cur
├── highslide-full.js
├── highslide-full.min.js
├── highslide-full.packed.js
├── highslide-ie6.css
├── highslide-with-gallery.js
├── highslide-with-gallery.min.js
├── highslide-with-gallery.packed.js
├── highslide-with-html.js
├── highslide-with-html.min.js
├── highslide-with-html.packed.js
├── highslide.css
├── highslide.js
├── highslide.min.js
└── highslide.packed.js
├── hits.php
├── hotpot.php
├── images
├── exclamation_sign.png
└── warning-attention-road-sign-exclamation-mark.png
├── javascriptfunctions.php
├── lang
├── en
│ └── block_analytics_graphs.php
├── pt_br
│ └── block_analytics_graphs.php
└── zh_cn
│ └── block_analytics_graphs.php
├── lib.php
├── query_grades.php
├── query_messages.php
├── query_resources_access.php
├── quiz.php
├── settings.php
├── thirdpartylibs.xml
├── timeaccesseschart.php
├── turnitin.php
└── version.php
/README.md:
--------------------------------------------------------------------------------
1 | AnalyticsGraphs
2 | ===============
3 |
4 | Learning analytics Moodle plugin - graphs to help teachers.
5 |
--------------------------------------------------------------------------------
/assign.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 |
18 | require('../../config.php');
19 | require('graph_submission.php');
20 | require('javascriptfunctions.php');
21 | require_once('lib.php');
22 |
23 | $course = required_param('id', PARAM_INT);
24 |
25 | /* Access control */
26 | require_login($course);
27 | $context = context_course::instance($course);
28 | require_capability('block/analytics_graphs:viewpages', $context);
29 | require_capability('block/analytics_graphs:viewassignmentsubmissions', $context);
30 |
31 | $title = get_string('submissions_assign', 'block_analytics_graphs');
32 | $submissionsgraph = new graph_submission($course, $title);
33 |
34 |
35 | $students = block_analytics_graphs_get_students($COURSE);
36 | $numberofstudents = count($students);
37 | if ($numberofstudents == 0) {
38 | echo(get_string('no_students', 'block_analytics_graphs'));
39 | exit;
40 | }
41 | $result = block_analytics_graphs_get_assign_submission($course, $students);
42 | $numberoftasks = count($result);
43 | if ($numberoftasks == 0) {
44 | echo(get_string('no_graph', 'block_analytics_graphs'));
45 | exit;
46 | }
47 | $submissionsgraphoptions = $submissionsgraph->create_graph($result, $students);
48 |
49 | /* Discover groups/groupings and members */
50 | $groupmembers = block_analytics_graphs_get_course_group_members($COURSE);
51 | $groupingmembers = block_analytics_graphs_get_course_grouping_members($COURSE);
52 | $groupmembers = array_merge($groupmembers, $groupingmembers);
53 | $groupmembersjson = json_encode($groupmembers);
54 |
55 | $studentsjson = json_encode($students);
56 | $resultjson = json_encode($result);
57 | $statisticsjson = $submissionsgraph->get_statistics();
58 |
59 | $codename = "assign.php";
60 | require('groupjavascript.php');
61 |
--------------------------------------------------------------------------------
/block_analytics_graphs.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | require_once($CFG->dirroot . '/blocks/analytics_graphs/lib.php');
20 |
21 | class block_analytics_graphs extends block_base {
22 | public function init() {
23 | $this->title = get_string('analytics_graphs', 'block_analytics_graphs');
24 | }
25 | // The PHP tag and the curly bracket for the class definition
26 | // will only be closed after there is another function added in the next section.
27 | public function get_content() {
28 | global $CFG;
29 | global $DB;
30 |
31 | $course = $this->page->course;
32 | $context = context_course::instance($course->id);
33 | // Capability is course level, not block level, as graphs are for course level.
34 | $canview = has_capability('block/analytics_graphs:viewpages', $context);
35 | if (!$canview) {
36 | return;
37 | }
38 | if ($this->content !== null) {
39 | return $this->content;
40 | }
41 |
42 | $sql = "SELECT cm.module, md.name
43 | FROM {course_modules} cm
44 | LEFT JOIN {modules} md ON cm.module = md.id
45 | WHERE cm.course = ?
46 | GROUP BY cm.module, md.name";
47 | $params = array($course->id);
48 | $availablemodulestotal = $DB->get_records_sql($sql, $params);
49 | $availablemodules = array();
50 | foreach ($availablemodulestotal as $result) {
51 | array_push($availablemodules, $result->name);
52 | }
53 |
54 | $this->content = new stdClass;
55 | $this->content->text = "";
56 | if (has_capability('block/analytics_graphs:viewgradeschart', $context)) {
57 | $this->content->text .= "
wwwroot}/blocks/analytics_graphs/grades_chart.php?id={$course->id}
58 | target=_blank>" . get_string('grades_chart', 'block_analytics_graphs') . "";
59 | }
60 | if (has_capability('block/analytics_graphs:viewcontentaccesses', $context)) {
61 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/graphresourcestartup.php?id={$course->id}
62 | target=_blank>" . get_string('access_to_contents', 'block_analytics_graphs') . "";
63 | }
64 | if (has_capability('block/analytics_graphs:viewnumberofactivestudents', $context)) {
65 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/timeaccesseschart.php?id={$course->id}&days=7
66 | target=_blank>" . get_string('timeaccesschart_title', 'block_analytics_graphs') . "";
67 | }
68 | if (has_capability('block/analytics_graphs:viewassignmentsubmissions', $context) && in_array("assign", $availablemodules)) {
69 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/assign.php?id={$course->id}
70 | target=_blank>" . get_string('submissions_assign', 'block_analytics_graphs') . "";
71 | }
72 | if (has_capability('block/analytics_graphs:viewquizsubmissions', $context) && in_array("quiz", $availablemodules)) {
73 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/quiz.php?id={$course->id}
74 | target=_blank>" . get_string('submissions_quiz', 'block_analytics_graphs') . "";
75 | }
76 | if (in_array("hotpot", $availablemodules)) {
77 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/hotpot.php?id={$course->id}
78 | target=_blank>" . get_string('submissions_hotpot', 'block_analytics_graphs') . "";
79 | }
80 | if (in_array("turnitintooltwo", $availablemodules)) {
81 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/turnitin.php?id={$course->id}
82 | target=_blank>" . get_string('submissions_turnitin', 'block_analytics_graphs') . "";
83 | }
84 | if (has_capability('block/analytics_graphs:viewhitsdistribution', $context)) {
85 | $this->content->text .= " wwwroot}/blocks/analytics_graphs/hits.php?id={$course->id}
86 | target=_blank>" . get_string('hits_distribution', 'block_analytics_graphs') . "";
87 | }
88 |
89 | $this->content->footer = '
';
90 | return $this->content;
91 | }
92 |
93 | /**
94 | * Enables global configuration of the block in settings.php.
95 | *
96 | * @return bool True if the global configuration is enabled.
97 | */
98 | public function has_config() {
99 | return true;
100 | }
101 |
102 | /**
103 | * Enabled config per block.
104 | *
105 | * @return true
106 | */
107 | public function instance_allow_config() {
108 | return (bool) get_config('block_analytics_graphs', 'overrideonlyactive');;
109 | }
110 |
111 | /**
112 | * Process deletion of a block instance.
113 | */
114 | public function instance_delete() {
115 | $needupdate = false;
116 | $onlyactivecourses = block_analytics_graphs_get_onlyactivecourses();
117 |
118 | // If related course has "onlyactive" setting enabled, we would like to clean it up on the block deletion.
119 | if (($key = array_search($this->page->course->id, $onlyactivecourses)) !== false) {
120 | unset($onlyactivecourses[$key]);
121 | $needupdate = true;
122 | }
123 |
124 | if ($needupdate) {
125 | set_config('onlyactivecourses', implode(',', $onlyactivecourses), 'block_analytics_graphs');
126 | }
127 | }
128 | } // Here's the closing bracket for the class definition.
129 |
--------------------------------------------------------------------------------
/classes/event/block_analytics_graphs_event_send_email.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The EVENTNAME event.
19 | *
20 | * @package analytics_graphs
21 | * @copyright 2014 Marcelo Augusto Rauh Schmitt
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 |
26 | namespace block_analytics_graphs\event;
27 | defined('MOODLE_INTERNAL') || die();
28 | /**
29 | * The block_analytics_graphs_event_send_email event class.
30 | *
31 | * @property-read array $other {
32 | * Extra information about event.
33 | *
34 | * - Whenever a teacher views a graph
35 | * }
36 | *
37 | * @since Moodle MOODLEVERSION
38 | * @copyright 2014 YOUR NAME
39 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 | **/
41 | class block_analytics_graphs_event_send_email extends \core\event\base {
42 | protected function init() {
43 | $this->data['crud'] = 'c';
44 | $this->data['edulevel'] = self::LEVEL_TEACHING;
45 | $this->data['objecttable'] = 'course';
46 |
47 | }
48 |
49 | public static function get_name() {
50 | return get_string('event_send_email', 'block_analytics_graphs');
51 | }
52 |
53 | public function get_description() {
54 | return "User: {$this->userid} - Course: {$this->objectid} - Graph: {$this->other}";
55 | }
56 |
57 | public function get_url() {
58 | return new \moodle_url('/blocks/analytics_graphs/' . $this->other, array('id' => $this->objectid, 'legacy' => '0'));
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/classes/event/block_analytics_graphs_event_view_graph.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The EVENTNAME event.
19 | *
20 | * @package analytics_graphs
21 | * @copyright 2014 Marcelo Augusto Rauh Schmitt
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 |
26 | namespace block_analytics_graphs\event;
27 | defined('MOODLE_INTERNAL') || die();
28 | /**
29 | * The block_analytics_graphs_event_view_graph event class.
30 | *
31 | * @property-read array $other {
32 | * Extra information about event.
33 | *
34 | * - Whenever a teacher views a graph
35 | * }
36 | *
37 | * @since Moodle MOODLEVERSION
38 | * @copyright 2014 YOUR NAME
39 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 | **/
41 | class block_analytics_graphs_event_view_graph extends \core\event\base {
42 | protected function init() {
43 | $this->data['crud'] = 'r';
44 | $this->data['edulevel'] = self::LEVEL_TEACHING;
45 | $this->data['objecttable'] = 'course';
46 | }
47 |
48 | public static function get_name() {
49 | return get_string('event_view_graph', 'block_analytics_graphs');
50 | }
51 |
52 | public function get_description() {
53 | return "User: {$this->userid} - Course: {$this->objectid} - Graph: {$this->other}";
54 | }
55 |
56 | public function get_url() {
57 | return new \moodle_url('/blocks/analytics_graphs/' . $this->other, array('id' => $this->objectid, 'legacy' => '0'));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/classes/privacy/provider.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace block_analytics_graphs\privacy;
18 |
19 | use core_privacy\local\metadata\collection;
20 | use core_privacy\local\request\approved_contextlist;
21 | use core_privacy\local\request\approved_userlist;
22 | use core_privacy\local\request\writer;
23 | use core_privacy\local\request\contextlist;
24 | use core_privacy\local\request\userlist;
25 |
26 | /**
27 | * Privacy Subsystem implementation for block_analytics_graphs.
28 | *
29 | * @package block_analytics_graphs
30 | * @author Dmitrii Metelkin
31 | * @copyright 2022 Catalyst IT
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | */
34 | class provider implements \core_privacy\local\metadata\provider,
35 | \core_privacy\local\request\core_userlist_provider,
36 | \core_privacy\local\request\plugin\provider {
37 |
38 |
39 | /**
40 | * Returns metadata.
41 | *
42 | * @param \core_privacy\local\metadata\collection $collection
43 | * @return \core_privacy\local\metadata\collection
44 | */
45 | public static function get_metadata(collection $collection): collection {
46 | $collection->add_database_table(
47 | 'block_analytics_graphs_msg',
48 | [
49 | 'fromid' => 'privacy:metadata:block_analytics_graphs_msg:fromid',
50 | 'subject' => 'privacy:metadata:block_analytics_graphs_msg:subject',
51 | ],
52 | 'privacy:metadata:block_analytics_graphs_msg'
53 | );
54 |
55 | $collection->add_database_table(
56 | 'block_analytics_graphs_dest',
57 | [
58 | 'toid' => 'privacy:metadata:block_analytics_graphs_dest:toid',
59 | 'messageid' => 'privacy:metadata:block_analytics_graphs_dest:messageid',
60 | ],
61 | 'privacy:metadata:block_analytics_graphs_dest'
62 | );
63 |
64 | return $collection;
65 | }
66 |
67 | /**
68 | * Gets context for provided user ID.
69 | *
70 | * @param int $userid User ID.
71 | * @return \core_privacy\local\request\contextlist
72 | */
73 | public static function get_contexts_for_userid(int $userid): contextlist {
74 | $contextlist = new contextlist();
75 |
76 | $sql = "SELECT c.id
77 | FROM {context} ctx
78 | INNER JOIN {course} c ON c.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
79 | INNER JOIN {block_analytics_graphs_msg} agm ON agm.courseid = c.id
80 | WHERE agm.fromid = :userid
81 | ";
82 |
83 | $contextlist->add_from_sql($sql, [
84 | 'contextlevel' => CONTEXT_COURSE,
85 | 'userid' => $userid,
86 | ]);
87 |
88 | $sql = "SELECT c.id
89 | FROM {context} ctx
90 | INNER JOIN {course} c ON c.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
91 | INNER JOIN {block_analytics_graphs_msg} agm ON agm.courseid = c.id
92 | INNER JOIN {block_analytics_graphs_dest} agd ON agd.messageid = agm.id
93 | WHERE agd.toid = :userid
94 | ";
95 |
96 | $contextlist->add_from_sql($sql, [
97 | 'contextlevel' => CONTEXT_COURSE,
98 | 'userid' => $userid,
99 | ]);
100 |
101 | return $contextlist;
102 | }
103 |
104 | /**
105 | * Get users in the provided context.
106 | *
107 | * @param \core_privacy\local\request\userlist $userlist
108 | */
109 | public static function get_users_in_context(userlist $userlist) {
110 | $context = $userlist->get_context();
111 |
112 | if (!$context instanceof \context_course) {
113 | return;
114 | }
115 |
116 | $params = ['courseid' => $context->instanceid];
117 |
118 | $sql = "SELECT fromid FROM {block_analytics_graphs_msg} WHERE courseid = :courseid";
119 | $userlist->add_from_sql('fromid', $sql, $params);
120 |
121 | $sql = "SELECT agd.toid
122 | FROM {block_analytics_graphs_dest} agd
123 | INNER JOIN {block_analytics_graphs_msg} agm ON agd.messageid = agm.id
124 | WHERE agm.courseid = :courseid";
125 | $userlist->add_from_sql('toid', $sql, $params);
126 | }
127 |
128 | /**
129 | * Export user data in the provided context.
130 | *
131 | * @param \core_privacy\local\request\approved_contextlist $contextlist
132 | */
133 | public static function export_user_data(approved_contextlist $contextlist) {
134 | global $DB;
135 |
136 | $user = $contextlist->get_user();
137 |
138 | foreach ($contextlist->get_contexts() as $context) {
139 | if ($context->contextlevel === CONTEXT_COURSE) {
140 | // Data export is organised in: {Context}/{Plugin Name}/{Table name}/{index}/data.json.
141 | $courseids[] = $context->instanceid;
142 |
143 | // Messages.
144 | $messages = $DB->get_records('block_analytics_graphs_msg', [
145 | 'courseid' => $context->instanceid,
146 | 'fromid' => $user->id,
147 | ]);
148 | $index = 0;
149 | foreach ($messages as $message) {
150 | // Data export is organised in: {Context}/{Plugin Name}/{Table name}/{index}/data.json.
151 | $index++;
152 | $subcontext = [
153 | get_string('pluginname', 'block_analytics_graphs'),
154 | 'block_analytics_graphs_msg',
155 | $index
156 | ];
157 |
158 | $data = (object) [
159 | 'fromid' => $message->fromid,
160 | 'subject' => $message->subject,
161 | ];
162 |
163 | writer::with_context($context)->export_data($subcontext, $data);
164 | }
165 |
166 | // Destinations.
167 | $sql = "SELECT agd.toid, agd.messageid
168 | FROM {block_analytics_graphs_dest} agd
169 | INNER JOIN {block_analytics_graphs_msg} agm ON agd.messageid = agm.id
170 | WHERE agm.courseid = :courseid AND agd.toid = :userid";
171 |
172 | $messages = $DB->get_records_sql($sql, [
173 | 'courseid' => $context->instanceid,
174 | 'userid' => $user->id,
175 | ]);
176 | $index = 0;
177 | foreach ($messages as $message) {
178 | // Data export is organised in: {Context}/{Plugin Name}/{Table name}/{index}/data.json.
179 | $index++;
180 | $subcontext = [
181 | get_string('pluginname', 'block_analytics_graphs'),
182 | 'block_analytics_graphs_dest',
183 | $index
184 | ];
185 |
186 | $data = (object) [
187 | 'toid' => $message->toid,
188 | 'messageid' => $message->messageid,
189 | ];
190 |
191 | writer::with_context($context)->export_data($subcontext, $data);
192 | }
193 | }
194 | }
195 | }
196 |
197 | /**
198 | * Delete data for all users in the provided context.
199 | *
200 | * @param \context $context
201 | */
202 | public static function delete_data_for_all_users_in_context(\context $context) {
203 | global $DB;
204 |
205 | if ($context->contextlevel !== CONTEXT_COURSE) {
206 | return;
207 | }
208 |
209 | $messageids = $DB->get_field('block_analytics_graphs_msg', 'id', ['courseid' => $context->instanceid]);
210 | list($insql, $inparams) = $DB->get_in_or_equal($messageids);
211 |
212 | $DB->delete_records_select('block_analytics_graphs_dest', " messageid $insql", $inparams);
213 | $DB->delete_records('block_analytics_graphs_msg', ['courseid' => $context->instanceid]);
214 | }
215 |
216 | /**
217 | * Delete data for user.
218 | *
219 | * @param \core_privacy\local\request\approved_contextlist $contextlist
220 | */
221 | public static function delete_data_for_user(approved_contextlist $contextlist) {
222 | global $DB;
223 |
224 | // If the user has data, then only the User context should be present so get the first context.
225 | $contexts = $contextlist->get_contexts();
226 | if (count($contexts) == 0) {
227 | return;
228 | }
229 |
230 | $userid = $contextlist->get_user()->id;
231 |
232 | $DB->set_field_select('block_analytics_graphs_dest', 'toid', 0, "toid = :toid", ['toid' => $userid]);
233 | $DB->set_field_select('block_analytics_graphs_msg', 'fromid', 0, "fromid = :fromid", ['fromid' => $userid]);
234 | }
235 |
236 | /**
237 | * Delete data for users.
238 | *
239 | * @param \core_privacy\local\request\approved_userlist $userlist
240 | */
241 | public static function delete_data_for_users(approved_userlist $userlist) {
242 | global $DB;
243 |
244 | $context = $userlist->get_context();
245 |
246 | if ($context->contextlevel !== CONTEXT_COURSE) {
247 | return;
248 | }
249 |
250 | $userids = $userlist->get_userids();
251 | list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
252 |
253 | $DB->set_field_select('block_analytics_graphs_dest', 'toid', 0, "toid {$insql}", $inparams);
254 | $DB->set_field_select('block_analytics_graphs_msg', 'fromid', 0, "fromid {$insql}", $inparams);
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "marceloschmitt/moodle-block_analytics_graphs",
3 | "type": "moodle-block",
4 | "require": {
5 | "composer/installers": "~1.0"
6 | },
7 | "extra": {
8 | "installer-name": "analytics_graphs"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/db/access.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | $capabilities = array(
20 | 'block/analytics_graphs:bemonitored' => array(
21 | 'captype' => 'read',
22 | 'contextlevel' => CONTEXT_BLOCK,
23 | 'archetypes' => array(
24 | 'student' => CAP_ALLOW,
25 | )
26 | ),
27 |
28 | 'block/analytics_graphs:viewpages' => array(
29 | 'riskbitmask' => RISK_SPAM,
30 | 'captype' => 'read',
31 | 'contextlevel' => CONTEXT_BLOCK,
32 | 'archetypes' => array(
33 | 'guest' => CAP_PREVENT,
34 | 'student' => CAP_PREVENT,
35 | 'teacher' => CAP_ALLOW,
36 | 'editingteacher' => CAP_ALLOW,
37 | 'manager' => CAP_ALLOW
38 | )
39 | ),
40 | 'block/analytics_graphs:myaddinstance' => array(
41 | 'riskbitmask' => RISK_SPAM | RISK_XSS,
42 | 'captype' => 'write',
43 | 'contextlevel' => CONTEXT_SYSTEM,
44 | 'archetypes' => array(
45 | 'editingteacher' => CAP_ALLOW,
46 | 'manager' => CAP_ALLOW
47 | ),
48 | ),
49 | 'block/analytics_graphs:addinstance' => array(
50 | 'riskbitmask' => RISK_SPAM | RISK_XSS,
51 | 'captype' => 'write',
52 | 'contextlevel' => CONTEXT_BLOCK,
53 | 'archetypes' => array(
54 | 'editingteacher' => CAP_ALLOW,
55 | 'manager' => CAP_ALLOW
56 | )
57 | ),
58 | 'block/analytics_graphs:viewgradeschart' => array(
59 | 'riskbitmask' => RISK_SPAM,
60 | 'captype' => 'read',
61 | 'contextlevel' => CONTEXT_BLOCK,
62 | 'archetypes' => array(
63 | 'guest' => CAP_PREVENT,
64 | 'student' => CAP_PREVENT,
65 | 'teacher' => CAP_ALLOW,
66 | 'editingteacher' => CAP_ALLOW,
67 | 'manager' => CAP_ALLOW
68 | )
69 | ),
70 | 'block/analytics_graphs:viewcontentaccesses' => array(
71 | 'riskbitmask' => RISK_SPAM,
72 | 'captype' => 'read',
73 | 'contextlevel' => CONTEXT_BLOCK,
74 | 'archetypes' => array(
75 | 'guest' => CAP_PREVENT,
76 | 'student' => CAP_PREVENT,
77 | 'teacher' => CAP_ALLOW,
78 | 'editingteacher' => CAP_ALLOW,
79 | 'manager' => CAP_ALLOW
80 | )
81 | ),
82 | 'block/analytics_graphs:viewnumberofactivestudents' => array(
83 | 'riskbitmask' => RISK_SPAM,
84 | 'captype' => 'read',
85 | 'contextlevel' => CONTEXT_BLOCK,
86 | 'archetypes' => array(
87 | 'guest' => CAP_PREVENT,
88 | 'student' => CAP_PREVENT,
89 | 'teacher' => CAP_ALLOW,
90 | 'editingteacher' => CAP_ALLOW,
91 | 'manager' => CAP_ALLOW
92 | )
93 | ),
94 | 'block/analytics_graphs:viewassignmentsubmissions' => array(
95 | 'riskbitmask' => RISK_SPAM,
96 | 'captype' => 'read',
97 | 'contextlevel' => CONTEXT_BLOCK,
98 | 'archetypes' => array(
99 | 'guest' => CAP_PREVENT,
100 | 'student' => CAP_PREVENT,
101 | 'teacher' => CAP_ALLOW,
102 | 'editingteacher' => CAP_ALLOW,
103 | 'manager' => CAP_ALLOW
104 | )
105 | ),
106 | 'block/analytics_graphs:viewquizsubmissions' => array(
107 | 'riskbitmask' => RISK_SPAM,
108 | 'captype' => 'read',
109 | 'contextlevel' => CONTEXT_BLOCK,
110 | 'archetypes' => array(
111 | 'guest' => CAP_PREVENT,
112 | 'student' => CAP_PREVENT,
113 | 'teacher' => CAP_ALLOW,
114 | 'editingteacher' => CAP_ALLOW,
115 | 'manager' => CAP_ALLOW
116 | )
117 | ),
118 | 'block/analytics_graphs:viewhitsdistribution' => array(
119 | 'riskbitmask' => RISK_SPAM,
120 | 'captype' => 'read',
121 | 'contextlevel' => CONTEXT_BLOCK,
122 | 'archetypes' => array(
123 | 'guest' => CAP_PREVENT,
124 | 'student' => CAP_PREVENT,
125 | 'teacher' => CAP_ALLOW,
126 | 'editingteacher' => CAP_ALLOW,
127 | 'manager' => CAP_ALLOW
128 | )
129 | ),
130 | );
131 |
--------------------------------------------------------------------------------
/db/install.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/db/upgrade.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | function xmldb_block_analytics_graphs_upgrade($oldversion, $block) {
20 | global $CFG, $DB;
21 |
22 | $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
23 |
24 | if ($oldversion < 2015042003) {
25 | // Define table block_analytics_graphs_msg to be created.
26 | $table = new xmldb_table('block_analytics_graphs_msg');
27 |
28 | // Adding fields to table block_analytics_graphs_msg.
29 | $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
30 | $table->add_field('fromid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
31 | $table->add_field('subject', XMLDB_TYPE_TEXT, null, null, null, null, null);
32 | $table->add_field('message', XMLDB_TYPE_TEXT, null, null, null, null, null);
33 | $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '1');
34 | $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
35 |
36 | // Adding keys to table block_analytics_graphs_msg.
37 | $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
38 | $table->add_key('fromid', XMLDB_KEY_FOREIGN, array('fromid'), 'user', array('id'));
39 | $table->add_key('courseid', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id'));
40 |
41 | // Conditionally launch create table for block_analytics_graphs_msg.
42 | if (!$dbman->table_exists($table)) {
43 | $dbman->create_table($table);
44 | }
45 |
46 | // Define table block_analytics_graphs_dest to be created.
47 | $table = new xmldb_table('block_analytics_graphs_dest');
48 |
49 | // Adding fields to table block_analytics_graphs_dest.
50 | $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
51 | $table->add_field('messageid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
52 | $table->add_field('toid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
53 |
54 | // Adding keys to table block_analytics_graphs_dest.
55 | $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
56 | $table->add_key('messageid', XMLDB_KEY_FOREIGN, array('messageid'), 'block_analytics_graphs_msg', array('id'));
57 | $table->add_key('toid', XMLDB_KEY_FOREIGN, array('toid'), 'user', array('id'));
58 |
59 | // Conditionally launch create table for block_analytics_graphs_dest.
60 | if (!$dbman->table_exists($table)) {
61 | $dbman->create_table($table);
62 | }
63 |
64 | // Analytics_graphs savepoint reached.
65 | upgrade_block_savepoint(true, 2015042003, 'analytics_graphs');
66 | }
67 |
68 | if ($oldversion < 2015051302) {
69 | $table = new xmldb_table('block_analytics_graphs_msg');
70 |
71 | // Define field courseid to be added to block_analytics_graphs_msg.
72 | $field = new xmldb_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '1', 'message');
73 | // Conditionally launch add field courseid.
74 | if (!$dbman->field_exists($table, $field)) {
75 | $dbman->add_field($table, $field);
76 | $key = new xmldb_key('courseid', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id'));
77 | $dbman->add_key($table, $key);
78 | }
79 |
80 | // Define field timecreated to be added to block_analytics_graphs_msg.
81 | $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, '0', 'courseid');
82 | // Conditionally launch add field timecreated.
83 | if (!$dbman->field_exists($table, $field)) {
84 | $dbman->add_field($table, $field);
85 | $index = new xmldb_index('timecreated', XMLDB_INDEX_NOTUNIQUE, array('timecreated'));
86 | if (!$dbman->index_exists($table, $index)) {
87 | $dbman->add_index($table, $index);
88 | }
89 | }
90 |
91 | // Analytics_graphs savepoint reached.
92 | upgrade_block_savepoint(true, 2015051302, 'analytics_graphs');
93 | }
94 |
95 | return true;
96 | }
97 |
--------------------------------------------------------------------------------
/edit_form.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | require_once($CFG->dirroot . '/blocks/analytics_graphs/lib.php');
20 |
21 | /**
22 | * Form for editing lock instances.
23 | *
24 | * @package block_analytics_graphs
25 | * @copyright 2024 Catalyst IT
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 | class block_analytics_graphs_edit_form extends block_edit_form {
29 |
30 | /**
31 | * Block config form definition.
32 | *
33 | * @param \MoodleQuickForm $mform Block form.
34 | *
35 | * @return void
36 | */
37 | protected function specific_definition($mform) {
38 | // Adding a new "only active" setting only of allowed for individual blocks.
39 | if (get_config('block_analytics_graphs', 'overrideonlyactive')) {
40 | $mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
41 | $mform->addElement('advcheckbox', 'config_onlyactive', get_string('settings:onlyactive', 'block_analytics_graphs'));
42 | $mform->addHelpButton('config_onlyactive', 'settings:onlyactive', 'block_analytics_graphs');
43 | $mform->setDefault('config_onlyactive', (bool) get_config('block_analytics_graphs', 'onlyactive'));
44 | }
45 | }
46 |
47 | /**
48 | * Display the configuration form when block is being added to the page
49 | *
50 | * @return bool
51 | */
52 | public static function display_form_when_adding(): bool {
53 | // Makes sense to display block's setting when adding a block only if allowed extra setting.
54 | return (bool) get_config('block_analytics_graphs', 'overrideonlyactive');
55 | }
56 |
57 | /**
58 | * Process the form submission, used if form was submitted via AJAX
59 | */
60 | public function process_dynamic_submission() {
61 | parent::process_dynamic_submission();
62 |
63 | // If allowed to have 'only active' setting per block,
64 | // then we would like to update it based on the curren block data.
65 | if (get_config('block_analytics_graphs', 'overrideonlyactive')) {
66 | $needupdate = false;
67 | $onlyactivecourses = block_analytics_graphs_get_onlyactivecourses();
68 | $courseid = $this->page->course->id;
69 | $data = $this->get_data();
70 |
71 | if(!empty($data->config_onlyactive)) {
72 | if (!in_array($courseid, $onlyactivecourses)) {
73 | $onlyactivecourses[] = $courseid;
74 | $needupdate = true;
75 | }
76 | } else {
77 | if (($key = array_search($courseid, $onlyactivecourses)) !== false) {
78 | unset($onlyactivecourses[$key]);
79 | $needupdate = true;
80 | }
81 | }
82 |
83 | // Conditionally save the settings only if updated.
84 | if ($needupdate) {
85 | set_config('onlyactivecourses', implode(',', $onlyactivecourses), 'block_analytics_graphs');
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/email.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | require_once("../../config.php");
18 | require_once('lib.php');
19 | global $USER;
20 | global $DB;
21 | require_once($CFG->dirroot.'/lib/moodlelib.php');
22 | $course = required_param('id', PARAM_INT);
23 | $ids = required_param('ids', PARAM_TEXT);
24 | $other = required_param('other', PARAM_INT);
25 | $subject = required_param('subject', PARAM_TEXT);
26 | $messagetext = required_param('texto', PARAM_TEXT);
27 | $ccteachers = required_param('ccteachers', PARAM_BOOL);
28 | $messagehtml = $messagetext;
29 |
30 | /* Access control */
31 | require_login($course);
32 | $context = context_course::instance($course);
33 | require_capability('block/analytics_graphs:viewpages', $context);
34 |
35 | $destination = explode(',', $ids);
36 |
37 | $touser = new stdClass();
38 | $fromuser = new stdClass();
39 | $touser->mailformat = 0;
40 | $fromuser->email = $USER->email;
41 | $fromuser->firstname = $USER->firstname;
42 | $fromuser->maildisplay = core_user::MAILDISPLAY_COURSE_MEMBERS_ONLY;
43 | $fromuser->lastname = $USER->lastname;
44 | $fromuser->id = $USER->id;
45 |
46 | $recordmsg = new stdClass();
47 | $recordmsg->fromid = $fromuser->id;
48 | $recordmsg->subject = $subject;
49 | $recordmsg->message = $messagetext;
50 | $recordmsg->courseid = $course;
51 | $recordmsg->timecreated = time();
52 | $messageid = $DB->insert_record('block_analytics_graphs_msg', $recordmsg, true);
53 | $recorddest = new stdClass();
54 | $recorddest->messageid = $messageid;
55 |
56 |
57 | foreach ($destination as $i => $x) {
58 | $touser->id = $destination[$i];
59 | $recorddest->toid = $touser->id;
60 | $touser->email = $DB->get_field('user', 'email', array('id' => $destination[$i]));
61 | email_to_user($touser, $fromuser, $subject, $messagetext, $messagehtml, '', '', true);
62 | $DB->insert_record('block_analytics_graphs_dest', $recorddest, false);
63 | }
64 |
65 | $messagetext = get_string('mailcopyalert', 'block_analytics_graphs') . $messagetext;
66 | $messagehtml = get_string('mailcopyalert', 'block_analytics_graphs') . $messagehtml;
67 |
68 | if ($ccteachers) {
69 | $userstocopyemail = block_analytics_graphs_get_teachers($course);
70 |
71 | foreach ($userstocopyemail as $i) {
72 | $touser->id = $i->id;
73 | $touser->email = $DB->get_field('user', 'email', array('id' => $i->id));
74 | email_to_user($touser, $fromuser, $subject, $messagetext, $messagehtml, '', '', true);
75 | }
76 | }
77 | $mensagem = "ok";
78 | echo json_encode($mensagem);
79 | $event = \block_analytics_graphs\event\block_analytics_graphs_event_send_email::create(array(
80 | 'objectid' => $course,
81 | 'context' => $context,
82 | 'other' => $other,
83 | ));
84 | $event->trigger();
--------------------------------------------------------------------------------
/externalref/export-csv-master/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 highslide-software
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/externalref/export-csv-master/README.md:
--------------------------------------------------------------------------------
1 | export-csv
2 | ==========
3 | This plugin allows the user to export the chart data to various formats and views.
4 |
5 | The contents of the plugin is located in the JavaScript file "export-csv.js".
6 | This plugin is published under the MIT license, and the license document is included in the repository.
7 |
8 | ### Demos
9 | * [Categorized chart](http://jsfiddle.net/highcharts/cqjvD/)
10 | * [View data table from menu](http://jsfiddle.net/highcharts/j4w4s0mw/)
11 | * [Highstock with time axis](http://jsfiddle.net/highcharts/2Jyn5/)
12 | * [Unit tests](http://jsfiddle.net/highcharts/pspdp2de/)
13 |
14 | ### Options
15 | * `exporting.csv.columnHeaderFormatter`
16 | Formatter callback for the column headers. Parameters are `item` (the series or axis object), `key` (the point key, for example `y` or `z`), and `keyLength`. By default it returns the series name, followed by the key if there is more than one key. For the axis it returns the axis title or "Category" or "DateTime" by default.
17 |
18 | * `exporting.csv.dateFormat`
19 | Which date format to use for exported dates on a datetime X axis. See [Highcharts.dateFormat](http://api.highcharts.com/highcharts#Highcharts.dateFormat\(\)).
20 |
21 | * `exporting.csv.itemDelimiter`
22 | The item delimiter, defaults to `,`. Use `;` for direct import to Excel.
23 |
24 | * `exporting.csv.lineDelimiter`
25 | The line delimiter, defaults to `\\n`.
26 |
27 | * `series.includeInCSVExport`
28 | Set this to false to prevent an individual series from being exported. To prevent the navigator in a stock chart, set `navigator.series.includeInCSVExport` to false.
29 |
30 | ### Methods
31 | * `Chart.getCSV()`
32 | Returns the current chart data as a CSV string
33 |
34 | * `Chart.getTable()`
35 | Returns the current chart data as a HTML table string, ready to be inserted into the DOM using `innerHTML`.
36 |
37 | * `Chart.getDataRows()`
38 | Returns the current chart data as a two dimensional array.
39 |
40 | * `Chart.viewData()`
41 | Inserts a data table below the chart container.
--------------------------------------------------------------------------------
/externalref/export-csv-master/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "highcharts-export-csv",
3 | "version": "1.4.5",
4 | "description": "Highcharts plugin to export the chart data to CSV, XLS or HTML table",
5 | "keywords": [
6 | "export",
7 | "csv",
8 | "xls"
9 | ],
10 | "authors": [
11 | { "name": "Torstein Hønsi", "homepage": "https://github.com/highslide-software" }
12 | ],
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/highcharts/export-csv"
16 | },
17 | "main": "export-csv.js",
18 | "license": "MIT",
19 | "ignore": [
20 | "**/.*",
21 | "README.md"
22 | ],
23 | "homepage": "http://www.highcharts.com/plugin-registry/single/7/Export-CSV"
24 | }
25 |
--------------------------------------------------------------------------------
/externalref/export-csv-master/export-csv.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A Highcharts plugin for exporting data from a rendered chart as CSV, XLS or HTML table
3 | *
4 | * Author: Torstein Honsi
5 | * Licence: MIT
6 | * Version: 1.4.5
7 | */
8 | /*global Highcharts, window, document, Blob */
9 | (function (factory) {
10 | if (typeof module === 'object' && module.exports) {
11 | module.exports = factory;
12 | } else {
13 | factory(Highcharts);
14 | }
15 | })(function (Highcharts) {
16 |
17 | 'use strict';
18 |
19 | var each = Highcharts.each,
20 | pick = Highcharts.pick,
21 | seriesTypes = Highcharts.seriesTypes,
22 | downloadAttrSupported = document.createElement('a').download !== undefined;
23 |
24 | Highcharts.setOptions({
25 | lang: {
26 | downloadCSV: 'Download CSV',
27 | downloadXLS: 'Download XLS',
28 | viewData: 'View data table'
29 | }
30 | });
31 |
32 |
33 | /**
34 | * Get the data rows as a two dimensional array
35 | */
36 | Highcharts.Chart.prototype.getDataRows = function () {
37 | var options = (this.options.exporting || {}).csv || {},
38 | xAxis = this.xAxis[0],
39 | rows = {},
40 | rowArr = [],
41 | dataRows,
42 | names = [],
43 | i,
44 | x,
45 | xTitle,
46 | // Options
47 | dateFormat = options.dateFormat || '%Y-%m-%d %H:%M:%S',
48 | columnHeaderFormatter = options.columnHeaderFormatter || function (item, key, keyLength) {
49 | if (item instanceof Highcharts.Axis) {
50 | return (item.options.title && item.options.title.text) ||
51 | (item.isDatetimeAxis ? 'DateTime' : 'Category');
52 | }
53 | return item.name + (keyLength > 1 ? ' ('+ key + ')' : '');
54 | };
55 |
56 | // Loop the series and index values
57 | i = 0;
58 | each(this.series, function (series) {
59 | var keys = series.options.keys,
60 | pointArrayMap = keys || series.pointArrayMap || ['y'],
61 | valueCount = pointArrayMap.length,
62 | requireSorting = series.requireSorting,
63 | categoryMap = {},
64 | j;
65 |
66 | // Map the categories for value axes
67 | each(pointArrayMap, function (prop) {
68 | categoryMap[prop] = (series[prop + 'Axis'] && series[prop + 'Axis'].categories) || [];
69 | });
70 |
71 | if (series.options.includeInCSVExport !== false && series.visible !== false) { // #55
72 | j = 0;
73 | while (j < valueCount) {
74 | names.push(columnHeaderFormatter(series, pointArrayMap[j], pointArrayMap.length));
75 | j = j + 1;
76 | }
77 |
78 | each(series.points, function (point, pIdx) {
79 | var key = requireSorting ? point.x : pIdx,
80 | prop,
81 | val;
82 |
83 | j = 0;
84 |
85 | if (!rows[key]) {
86 | rows[key] = [];
87 | }
88 | rows[key].x = point.x;
89 |
90 | // Pies, funnels, geo maps etc. use point name in X row
91 | if (!series.xAxis || series.exportKey === 'name') {
92 | rows[key].name = point.name;
93 | }
94 |
95 | while (j < valueCount) {
96 | prop = pointArrayMap[j]; // y, z etc
97 | val = point[prop];
98 | rows[key][i + j] = pick(categoryMap[prop][val], val); // Pick a Y axis category if present
99 | j = j + 1;
100 | }
101 |
102 | });
103 | i = i + j;
104 | }
105 | });
106 |
107 | // Make a sortable array
108 | for (x in rows) {
109 | if (rows.hasOwnProperty(x)) {
110 | rowArr.push(rows[x]);
111 | }
112 | }
113 | // Sort it by X values
114 | rowArr.sort(function (a, b) {
115 | return a.x - b.x;
116 | });
117 |
118 | // Add header row
119 | xTitle = columnHeaderFormatter(xAxis);
120 | dataRows = [[xTitle].concat(names)];
121 |
122 | // Add the category column
123 | each(rowArr, function (row) {
124 |
125 | var category = row.name;
126 | if (!category) {
127 | if (xAxis.isDatetimeAxis) {
128 | if (row.x instanceof Date) {
129 | row.x = row.x.getTime();
130 | }
131 | category = Highcharts.dateFormat(dateFormat, row.x);
132 | } else if (xAxis.categories) {
133 | category = pick(xAxis.names[row.x], xAxis.categories[row.x], row.x)
134 | } else {
135 | category = row.x;
136 | }
137 | }
138 |
139 | // Add the X/date/category
140 | row.unshift(category);
141 | dataRows.push(row);
142 | });
143 |
144 | return dataRows;
145 | };
146 |
147 | /**
148 | * Get a CSV string
149 | */
150 | Highcharts.Chart.prototype.getCSV = function (useLocalDecimalPoint) {
151 | var csv = '',
152 | rows = this.getDataRows(),
153 | options = (this.options.exporting || {}).csv || {},
154 | itemDelimiter = options.itemDelimiter || ',', // use ';' for direct import to Excel
155 | lineDelimiter = options.lineDelimiter || '\n'; // '\n' isn't working with the js csv data extraction
156 |
157 | // Transform the rows to CSV
158 | each(rows, function (row, i) {
159 | var val = '',
160 | j = row.length,
161 | n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.';
162 | while (j--) {
163 | val = row[j];
164 | if (typeof val === "string") {
165 | val = '"' + val + '"';
166 | }
167 | if (typeof val === 'number') {
168 | if (n === ',') {
169 | val = val.toString().replace(".", ",");
170 | }
171 | }
172 | row[j] = val;
173 | }
174 | // Add the values
175 | csv += row.join(itemDelimiter);
176 |
177 | // Add the line delimiter
178 | if (i < rows.length - 1) {
179 | csv += lineDelimiter;
180 | }
181 | });
182 | return csv;
183 | };
184 |
185 | /**
186 | * Build a HTML table with the data
187 | */
188 | Highcharts.Chart.prototype.getTable = function (useLocalDecimalPoint) {
189 | var html = '',
190 | rows = this.getDataRows();
191 |
192 | // Transform the rows to HTML
193 | each(rows, function (row, i) {
194 | var tag = i ? 'td' : 'th',
195 | val,
196 | j,
197 | n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.';
198 |
199 | html += '';
200 | for (j = 0; j < row.length; j = j + 1) {
201 | val = row[j];
202 | // Add the cell
203 | if (typeof val === 'number') {
204 | val = val.toString();
205 | if (n === ',') {
206 | val = val.replace('.', n);
207 | }
208 | html += '<' + tag + ' class="number">' + val + '' + tag + '>';
209 |
210 | } else {
211 | html += '<' + tag + '>' + (val === undefined ? '' : val) + '' + tag + '>';
212 | }
213 | }
214 |
215 | html += '
';
216 |
217 | // After the first row, end head and start body
218 | if (!i) {
219 | html += '';
220 | }
221 |
222 | });
223 | html += '
';
224 |
225 | console.log(html);
226 | return html;
227 | };
228 |
229 | function getContent(chart, href, extension, content, MIME) {
230 | var a,
231 | blobObject,
232 | name,
233 | options = (chart.options.exporting || {}).csv || {},
234 | url = options.url || 'http://www.highcharts.com/studies/csv-export/download.php';
235 |
236 | if (chart.options.exporting.filename) {
237 | name = chart.options.exporting.filename;
238 | } else if (chart.title) {
239 | name = chart.title.textStr.replace(/ /g, '-').toLowerCase();
240 | } else {
241 | name = 'chart';
242 | }
243 |
244 | // MS specific. Check this first because of bug with Edge (#76)
245 | if (window.Blob && window.navigator.msSaveOrOpenBlob) {
246 | // Falls to msSaveOrOpenBlob if download attribute is not supported
247 | blobObject = new Blob([content]);
248 | window.navigator.msSaveOrOpenBlob(blobObject, name + '.' + extension);
249 |
250 | // Download attribute supported
251 | } else if (downloadAttrSupported) {
252 | a = document.createElement('a');
253 | a.href = href;
254 | a.target = '_blank';
255 | a.download = name + '.' + extension;
256 | chart.container.append(a); // #111
257 | a.click();
258 | a.remove();
259 |
260 | } else {
261 | // Fall back to server side handling
262 | Highcharts.post(url, {
263 | data: content,
264 | type: MIME,
265 | extension: extension
266 | });
267 | }
268 | }
269 |
270 | /**
271 | * Call this on click of 'Download CSV' button
272 | */
273 | Highcharts.Chart.prototype.downloadCSV = function () {
274 | var csv = this.getCSV(true);
275 | getContent(
276 | this,
277 | 'data:text/csv,\uFEFF' + encodeURIComponent(csv),
278 | 'csv',
279 | csv,
280 | 'text/csv'
281 | );
282 | };
283 |
284 | /**
285 | * Call this on click of 'Download XLS' button
286 | */
287 | Highcharts.Chart.prototype.downloadXLS = function () {
288 | var uri = 'data:application/vnd.ms-excel;base64,',
289 | template = '' +
290 | '' +
293 | '' +
294 | '' +
295 | '' +
296 | '' +
297 | this.getTable(true) +
298 | '',
299 | base64 = function (s) {
300 | return window.btoa(unescape(encodeURIComponent(s))); // #50
301 | };
302 | getContent(
303 | this,
304 | uri + base64(template),
305 | 'xls',
306 | template,
307 | 'application/vnd.ms-excel'
308 | );
309 | };
310 |
311 | /**
312 | * View the data in a table below the chart
313 | */
314 | Highcharts.Chart.prototype.viewData = function () {
315 | if (!this.dataTableDiv) {
316 | this.dataTableDiv = document.createElement('div');
317 | this.dataTableDiv.className = 'highcharts-data-table';
318 |
319 | // Insert after the chart container
320 | this.renderTo.parentNode.insertBefore(
321 | this.dataTableDiv,
322 | this.renderTo.nextSibling
323 | );
324 | }
325 |
326 | this.dataTableDiv.innerHTML = this.getTable();
327 | };
328 |
329 |
330 | // Add "Download CSV" to the exporting menu. Use download attribute if supported, else
331 | // run a simple PHP script that returns a file. The source code for the PHP script can be viewed at
332 | // https://raw.github.com/highslide-software/highcharts.com/master/studies/csv-export/csv.php
333 | if (Highcharts.getOptions().exporting) {
334 | Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
335 | textKey: 'downloadCSV',
336 | onclick: function () { this.downloadCSV(); }
337 | }, {
338 | textKey: 'downloadXLS',
339 | onclick: function () { this.downloadXLS(); }
340 | }/*, {
341 | textKey: 'viewData',
342 | onclick: function () { this.viewData(); }
343 | }*/ );
344 | }
345 |
346 | // Series specific
347 | if (seriesTypes.map) {
348 | seriesTypes.map.prototype.exportKey = 'name';
349 | }
350 | if (seriesTypes.mapbubble) {
351 | seriesTypes.mapbubble.prototype.exportKey = 'name';
352 | }
353 |
354 | });
355 |
--------------------------------------------------------------------------------
/externalref/export-csv-master/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Export Data",
3 | "version": "1.4.5",
4 | "title": "Export chart data to CSV, XLS, HTML or JS array",
5 | "demo": [
6 | "http://jsfiddle.net/highcharts/cqjvD/",
7 | "http://jsfiddle.net/highcharts/2Jyn5/"
8 | ],
9 | "author": {
10 | "name": "Torstein Hønsi",
11 | "url": "https://github.com/highslide-software"
12 | },
13 | "maintainers": [
14 | {
15 | "name": "Torgrim Thorsen",
16 | "url": "https://github.com/SirAlexiner",
17 | "email": "Sir_Alexiner@hotmail.com"
18 | }
19 | ],
20 | "licenses": [
21 | {
22 | "type": "MIT",
23 | "url": "https://github.com/highslide-software/export-csv/blob/master/LICENSE"
24 | }
25 | ],
26 | "description": "Highcharts plugin to export the chart data to CSV, XLS or HTML table.",
27 | "keywords": [
28 | "export",
29 | "csv",
30 | "xls"
31 | ],
32 | "dependencies": {
33 | "Highcharts": ">=3.0.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/externalref/export-csv-master/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "highcharts-export-csv",
3 | "version": "1.4.5",
4 | "description": "Highcharts plugin to export the chart data to CSV, XLS or HTML table",
5 | "keywords": [
6 | "export",
7 | "csv",
8 | "xls"
9 | ],
10 | "main": "export-csv.js",
11 | "author": {
12 | "name": "Torstein Hønsi",
13 | "url": "https://github.com/highslide-software"
14 | },
15 | "contributors": [
16 | {
17 | "name": "Torgrim Thorsen",
18 | "url": "https://github.com/SirAlexiner",
19 | "email": "Sir_Alexiner@hotmail.com"
20 | }
21 | ],
22 | "repository": {
23 | "type": "git",
24 | "url": "https://github.com/highcharts/export-csv"
25 | },
26 | "peerDependencies": {
27 | "highcharts": ">=3.0.0"
28 | },
29 | "license": "MIT",
30 | "bugs": {
31 | "url": "https://github.com/highcharts/export-csv/issues"
32 | },
33 | "homepage": "http://www.highcharts.com/plugin-registry/single/7/Export-CSV"
34 | }
35 |
--------------------------------------------------------------------------------
/externalref/exporting.js:
--------------------------------------------------------------------------------
1 | /*
2 | Highcharts JS v5.0.2 (2016-10-26)
3 | Exporting module
4 |
5 | (c) 2010-2016 Torstein Honsi
6 |
7 | License: www.highcharts.com/license
8 | */
9 | (function(m){"object"===typeof module&&module.exports?module.exports=m:m(Highcharts)})(function(m){(function(f){var m=f.defaultOptions,n=f.doc,u=f.Chart,v=f.addEvent,D=f.removeEvent,E=f.fireEvent,r=f.createElement,B=f.discardElement,w=f.css,q=f.merge,C=f.pick,h=f.each,t=f.extend,G=f.splat,H=f.isTouchDevice,F=f.win,I=f.Renderer.prototype.symbols;t(m.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",
10 | contextButtonTitle:"Chart context menu"});m.navigation={buttonOptions:{theme:{},symbolSize:14,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,verticalAlign:"top",width:24}};q(!0,m.navigation,{menuStyle:{border:"1px solid #999999",background:"#ffffff",padding:"5px 0"},menuItemStyle:{padding:"0.5em 1em",background:"none",color:"#333333",fontSize:H?"14px":"11px",transition:"background 250ms, color 250ms"},menuItemHoverStyle:{background:"#335cad",color:"#ffffff"},buttonOptions:{symbolFill:"#666666",
11 | symbolStroke:"#666666",symbolStrokeWidth:3,theme:{fill:"#ffffff",stroke:"none",padding:5}}});m.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{className:"highcharts-contextbutton",menuClassName:"highcharts-contextmenu",symbol:"menu",_titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},
12 | {textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};f.post=function(a,b,e){var c;a=r("form",q({method:"post",action:a,enctype:"multipart/form-data"},e),{display:"none"},n.body);for(c in b)r("input",{type:"hidden",name:c,value:b[c]},null,a);a.submit();B(a)};t(u.prototype,{sanitizeSVG:function(a){a=a.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,
13 | "").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\(("|")(\S+)("|")\)/g,"url($2)").replace(/url\([^#]+#/g,"url(#").replace(/