mirror of
https://github.com/moodle/moodle.git
synced 2025-03-18 22:50:19 +01:00
Merge branch 'MDL-66091_master' of git://github.com/dmonllao/moodle
This commit is contained in:
commit
402966c77c
@ -193,18 +193,23 @@ class insights_generator {
|
||||
$insighturl = null;
|
||||
foreach ($predictionactions as $action) {
|
||||
$actionurl = $action->get_url();
|
||||
$opentoblank = false;
|
||||
if (!$actionurl->get_param('forwardurl')) {
|
||||
|
||||
$actiondoneurl = new \moodle_url('/report/insights/done.php');
|
||||
$params = ['actionvisiblename' => $action->get_text(), 'target' => '_blank'];
|
||||
$actiondoneurl = new \moodle_url('/report/insights/done.php', $params);
|
||||
// Set the forward url to the 'done' script.
|
||||
$actionurl->param('forwardurl', $actiondoneurl->out(false));
|
||||
|
||||
$opentoblank = true;
|
||||
}
|
||||
|
||||
if (empty($insighturl)) {
|
||||
// We use the primary action url as insight url so we log that the user followed the provided link.
|
||||
$insighturl = $action->get_url();
|
||||
}
|
||||
$actiondata = (object)['url' => $action->get_url()->out(false), 'text' => $action->get_text()];
|
||||
$actiondata = (object)['url' => $action->get_url()->out(false), 'text' => $action->get_text(),
|
||||
'opentoblank' => $opentoblank];
|
||||
$fullmessageplaintext .= get_string('insightinfomessageaction', 'analytics', $actiondata) . PHP_EOL;
|
||||
$messageactions[] = $actiondata;
|
||||
}
|
||||
|
@ -105,6 +105,15 @@ abstract class base extends \core_analytics\calculable {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the insights of this model be linked from reports?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function link_insights_report(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on facts (processed by machine learning backends) by default.
|
||||
*
|
||||
@ -147,7 +156,7 @@ abstract class base extends \core_analytics\calculable {
|
||||
|
||||
$actions = array();
|
||||
|
||||
if ($includedetailsaction) {
|
||||
if ($this->link_insights_report() && $includedetailsaction) {
|
||||
|
||||
$predictionurl = new \moodle_url('/report/insights/prediction.php', array('id' => $predictionid));
|
||||
$detailstext = $this->get_view_details_text();
|
||||
|
@ -484,6 +484,9 @@ class manager {
|
||||
/**
|
||||
* Returns the models with insights at the provided context.
|
||||
*
|
||||
* Note that this method is used for display purposes. It filters out models whose insights
|
||||
* are not linked from the reports page.
|
||||
*
|
||||
* @param \context $context
|
||||
* @return \core_analytics\model[]
|
||||
*/
|
||||
@ -494,13 +497,52 @@ class manager {
|
||||
$models = self::get_all_models(true, true, $context);
|
||||
foreach ($models as $key => $model) {
|
||||
// Check that it not only have predictions but also generates insights from them.
|
||||
if (!$model->uses_insights()) {
|
||||
if (!$model->uses_insights() || !$model->get_target()->link_insights_report()) {
|
||||
unset($models[$key]);
|
||||
}
|
||||
}
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the models that generated insights in the provided context. It can also be used to add new models to the context.
|
||||
*
|
||||
* Note that if you use this function with $newmodelid is the caller responsibility to ensure that the
|
||||
* provided model id generated insights for the provided context.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @param \context $context
|
||||
* @param int|null $newmodelid A new model to add to the list of models with insights in the provided context.
|
||||
* @return int[]
|
||||
*/
|
||||
public static function cached_models_with_insights(\context $context, int $newmodelid = null) {
|
||||
|
||||
$cache = \cache::make('core', 'contextwithinsights');
|
||||
$modelids = $cache->get($context->id);
|
||||
if ($modelids === false) {
|
||||
// The cache is empty, but we don't know if it is empty because there are no insights
|
||||
// in this context or because cache/s have been purged, we need to be conservative and
|
||||
// "pay" 1 db read to fill up the cache.
|
||||
|
||||
$models = \core_analytics\manager::get_models_with_insights($context);
|
||||
|
||||
if ($newmodelid && empty($models[$newmodelid])) {
|
||||
throw new \coding_exception('The provided modelid ' . $newmodelid . ' did not generate any insights');
|
||||
}
|
||||
|
||||
$modelids = array_keys($models);
|
||||
$cache->set($context->id, $modelids);
|
||||
|
||||
} else if ($newmodelid && !in_array($newmodelid, $modelids)) {
|
||||
// We add the context we got as an argument to the cache.
|
||||
|
||||
array_push($modelids, $newmodelid);
|
||||
$cache->set($context->id, $modelids);
|
||||
}
|
||||
|
||||
return $modelids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a prediction
|
||||
*
|
||||
|
@ -963,19 +963,11 @@ class model {
|
||||
|
||||
$this->get_target()->generate_insight_notifications($this->model->id, $samplecontexts, $predictions);
|
||||
|
||||
// Update cache.
|
||||
$cache = \cache::make('core', 'contextwithinsights');
|
||||
foreach ($samplecontexts as $context) {
|
||||
$modelids = $cache->get($context->id);
|
||||
if (!$modelids) {
|
||||
// The cache is empty, but we don't know if it is empty because there are no insights
|
||||
// in this context or because cache/s have been purged, we need to be conservative and
|
||||
// "pay" 1 db read to fill up the cache.
|
||||
$models = \core_analytics\manager::get_models_with_insights($context);
|
||||
$cache->set($context->id, array_keys($models));
|
||||
} else if (!in_array($this->get_id(), $modelids)) {
|
||||
array_push($modelids, $this->get_id());
|
||||
$cache->set($context->id, $modelids);
|
||||
if ($this->get_target()->link_insights_report()) {
|
||||
|
||||
// Update cache.
|
||||
foreach ($samplecontexts as $context) {
|
||||
\core_analytics\manager::cached_models_with_insights($context, $this->get_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,8 @@
|
||||
"text": "Moodle"
|
||||
}, {
|
||||
"url": "https://en.wikipedia.org/wiki/Noodle",
|
||||
"text": "Noodle"
|
||||
"text": "Noodle",
|
||||
"opentoblank": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -65,5 +66,5 @@ body:not(.dir-ltr):not(.dir-rtl) .btn-insight {
|
||||
|
||||
<br/>
|
||||
{{#actions}}
|
||||
<a class="btn btn-default m-r-1 m-b-1 btn-insight" href="{{url}}">{{text}}</a>
|
||||
<a class="btn btn-default m-r-1 m-b-1 btn-insight" {{#opentoblank}}target="_blank" {{/opentoblank}}href="{{url}}">{{text}}</a>
|
||||
{{/actions}}
|
||||
|
@ -261,6 +261,7 @@ $string['urlforical'] = 'URL for iCalendar export, for subscribing to calendar';
|
||||
$string['user'] = 'User';
|
||||
$string['userevent'] = 'User event';
|
||||
$string['userevents'] = 'User events';
|
||||
$string['viewupcomingactivitiesdue'] = 'View the upcoming activities due';
|
||||
$string['wed'] = 'Wed';
|
||||
$string['wednesday'] = 'Wednesday';
|
||||
$string['weekly'] = 'Weekly';
|
||||
|
@ -3449,3 +3449,20 @@ function get_courses_page($categoryid="all", $sort="c.sortorder ASC", $fields="c
|
||||
$rs->close();
|
||||
return $visiblecourses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the models that generated insights in the provided context.
|
||||
*
|
||||
* @deprecated since Moodle 3.8 MDL-66091 - please do not use this function any more.
|
||||
* @todo MDL-65799 This will be deleted in Moodle 4.2
|
||||
* @see \core_analytics\manager::cached_models_with_insights
|
||||
* @param \context $context
|
||||
* @return int[]
|
||||
*/
|
||||
function report_insights_context_insights(\context $context) {
|
||||
|
||||
debugging('report_insights_context_insights is deprecated. Please use ' .
|
||||
'\core_analytics\manager::cached_models_with_insights instead', DEBUG_DEVELOPER);
|
||||
|
||||
return \core_analytics\manager::cached_models_with_insights($context);
|
||||
}
|
||||
|
@ -26,5 +26,18 @@ require_once(__DIR__ . '/../../config.php');
|
||||
|
||||
require_login();
|
||||
|
||||
$url = new \moodle_url('/');
|
||||
redirect($url, get_string('actionsaved', 'report_insights'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
$actionvisiblename = required_param('actionvisiblename', PARAM_NOTAGS);
|
||||
|
||||
$PAGE->set_pagelayout('popup');
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
$PAGE->set_title(get_site()->fullname);
|
||||
$PAGE->set_url(new \moodle_url('/report/insights/done.php'));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$notification = new \core\output\notification(get_string('actionsaved', 'report_insights', $actionvisiblename),
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
$notification->set_show_closebutton(false);
|
||||
echo $OUTPUT->render($notification);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
@ -40,10 +40,24 @@ if ($context->contextlevel < CONTEXT_COURSE) {
|
||||
// Only for higher levels than course.
|
||||
$PAGE->set_context($context);
|
||||
}
|
||||
|
||||
\core_analytics\manager::check_can_list_insights($context);
|
||||
|
||||
// Get all models that are enabled, trained and have predictions at this context.
|
||||
$othermodels = \core_analytics\manager::get_all_models(true, true, $context);
|
||||
array_filter($othermodels, function($model) use ($context) {
|
||||
|
||||
// Discard insights that are not linked unless you are a manager.
|
||||
if (!$model->get_target()->link_insights_report()) {
|
||||
try {
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
} catch (\required_capability_exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!$modelid && count($othermodels)) {
|
||||
// Autoselect the only available model.
|
||||
$model = reset($othermodels);
|
||||
@ -89,6 +103,12 @@ if (!$modelid) {
|
||||
|
||||
$model = new \core_analytics\model($modelid);
|
||||
|
||||
if (!$model->get_target()->link_insights_report()) {
|
||||
|
||||
// Only manager access if this target does not link the insights report.
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
}
|
||||
|
||||
$insightinfo = new stdClass();
|
||||
$insightinfo->contextname = $context->get_context_name();
|
||||
$insightinfo->insightname = $model->get_target()->get_name();
|
||||
@ -103,8 +123,12 @@ if (!$model->uses_insights()) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($context->id == SYSCONTEXTID) {
|
||||
$PAGE->set_heading(get_site()->shortname);
|
||||
} else {
|
||||
$PAGE->set_heading($insightinfo->contextname);
|
||||
}
|
||||
$PAGE->set_title($insightinfo->insightname);
|
||||
$PAGE->set_heading($insightinfo->contextname);
|
||||
|
||||
// Some models generate one single prediction per context. We can directly show the prediction details in this case.
|
||||
if ($model->get_analyser()::one_sample_per_analysable()) {
|
||||
|
@ -22,11 +22,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['actionsaved'] = 'Your action has been saved.';
|
||||
$string['calculatedvalue'] = 'Calculated value';
|
||||
$string['actionsaved'] = 'Your feedback of \'{$a}\' has been saved.';
|
||||
$string['disabledmodel'] = 'Sorry, this model has been disabled by the administrator';
|
||||
$string['indicator'] = 'Indicator';
|
||||
$string['insightprediction'] = '{$a} prediction';
|
||||
$string['indicators'] = 'Indicators';
|
||||
$string['insight'] = 'Insight';
|
||||
$string['insights'] = 'Insights';
|
||||
$string['justpredictions'] = 'Please note that the following insights are only predictions. It is not possible to predict the future with any certainty. The insights are provided so that action can be taken as necessary to prevent any negative predictions becoming reality.';
|
||||
@ -39,7 +37,6 @@ $string['outcomeverypositive'] = 'Very positive outcome';
|
||||
$string['outcomeverynegative'] = 'Very negative outcome';
|
||||
$string['pluginname'] = 'Insights';
|
||||
$string['prediction'] = 'Prediction';
|
||||
$string['predictioncalculations'] = 'Indicator calculations';
|
||||
$string['predictiondetails'] = 'Prediction details';
|
||||
$string['nodetailsavailable'] = 'No prediction details are relevant.';
|
||||
$string['timecreated'] = 'Time predicted';
|
||||
|
@ -36,7 +36,7 @@ function report_insights_extend_navigation_course($navigation, $course, $context
|
||||
|
||||
if (has_capability('moodle/analytics:listinsights', $context)) {
|
||||
|
||||
$modelids = report_insights_context_insights($context);
|
||||
$modelids = \core_analytics\manager::cached_models_with_insights($context);
|
||||
if (!empty($modelids)) {
|
||||
$url = new moodle_url('/report/insights/insights.php', array('contextid' => $context->id));
|
||||
$node = navigation_node::create(get_string('insights', 'report_insights'), $url, navigation_node::TYPE_SETTING,
|
||||
@ -61,7 +61,7 @@ function report_insights_myprofile_navigation(core_user\output\myprofile\tree $t
|
||||
$context = \context_user::instance($user->id);
|
||||
if (\core_analytics\manager::check_can_list_insights($context, true)) {
|
||||
|
||||
$modelids = report_insights_context_insights($context);
|
||||
$modelids = \core_analytics\manager::cached_models_with_insights($context);
|
||||
if (!empty($modelids)) {
|
||||
$url = new moodle_url('/report/insights/insights.php', array('contextid' => $context->id));
|
||||
$node = new core_user\output\myprofile\node('reports', 'insights', get_string('insights', 'report_insights'),
|
||||
@ -82,7 +82,7 @@ function report_insights_extend_navigation_category_settings($navigation, $conte
|
||||
|
||||
if (has_capability('moodle/analytics:listinsights', $context)) {
|
||||
|
||||
$modelids = report_insights_context_insights($context);
|
||||
$modelids = \core_analytics\manager::cached_models_with_insights($context);
|
||||
if (!empty($modelids)) {
|
||||
$url = new moodle_url('/report/insights/insights.php', array('contextid' => $context->id));
|
||||
|
||||
@ -99,22 +99,3 @@ function report_insights_extend_navigation_category_settings($navigation, $conte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the models that generated insights in the provided context.
|
||||
*
|
||||
* @param \context $context
|
||||
* @return int[]
|
||||
*/
|
||||
function report_insights_context_insights(\context $context) {
|
||||
|
||||
$cache = \cache::make('core', 'contextwithinsights');
|
||||
$modelids = $cache->get($context->id);
|
||||
if ($modelids === false) {
|
||||
// They will be full unless a model has been cleared.
|
||||
$models = \core_analytics\manager::get_models_with_insights($context);
|
||||
$modelids = array_keys($models);
|
||||
$cache->set($context->id, $modelids);
|
||||
}
|
||||
return $modelids;
|
||||
}
|
||||
|
@ -71,8 +71,12 @@ if (!$model->uses_insights()) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($context->id == SYSCONTEXTID) {
|
||||
$PAGE->set_heading(get_site()->shortname);
|
||||
} else {
|
||||
$PAGE->set_heading($insightinfo->contextname);
|
||||
}
|
||||
$PAGE->set_title($insightinfo->insightname);
|
||||
$PAGE->set_heading($insightinfo->contextname);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
|
@ -73,7 +73,7 @@
|
||||
}
|
||||
}}
|
||||
|
||||
<h2 class="mb-2">{{#str}}insightprediction, report_insights, {{insightname}} {{/str}}</h2>
|
||||
<h2 class="mb-2">{{insightname}}</h2>
|
||||
<table class="generaltable insights-list">
|
||||
{{#showpredicionheading}}
|
||||
<caption>
|
||||
@ -101,29 +101,23 @@
|
||||
<caption>{{#str}}predictiondetails, report_insights{{/str}}</caption>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td scope="row">{{#str}}timecreated, report_insights{{/str}}</td>
|
||||
<th scope="row">{{#str}}timecreated, report_insights{{/str}}</td>
|
||||
<td>{{timecreated}}</td>
|
||||
</tr>
|
||||
{{#timerange}}
|
||||
<tr>
|
||||
<td scope="row">{{#str}}timerange, report_insights{{/str}}</td>
|
||||
<th scope="row">{{#str}}timerange, report_insights{{/str}}</td>
|
||||
<td>{{.}}</td>
|
||||
</tr>
|
||||
{{/timerange}}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="generaltable prediction-calculations">
|
||||
<caption class="accesshide">{{#str}}predictioncalculations, report_insights{{/str}}</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{#str}}indicator, report_insights{{/str}}</th>
|
||||
<th scope="col">{{#str}}calculatedvalue, report_insights{{/str}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<caption>{{#str}}indicators, report_insights{{/str}}</caption>
|
||||
<tbody>
|
||||
{{#calculations}}
|
||||
<tr>
|
||||
<td class="{{#style}}table-{{style}}{{/style}}">{{name}}</td>
|
||||
<th scope="row" class="{{#style}}table-{{style}}{{/style}}">{{name}}</td>
|
||||
<td class="{{#style}}table-{{style}}{{/style}}">{{#outcomeicon}}{{> core/pix_icon}}{{/outcomeicon}} {{displayvalue}}</td>
|
||||
</tr>
|
||||
{{/calculations}}
|
||||
|
@ -160,6 +160,15 @@ class upcoming_activities_due extends \core_analytics\local\target\binary {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* No need to link to the insights report in this case.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function link_insights_report(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a view upcoming events action.
|
||||
*
|
||||
@ -180,9 +189,9 @@ class upcoming_activities_due extends \core_analytics\local\target\binary {
|
||||
|
||||
// We force a lookahead of 30 days so we are sure that the upcoming activities due are shown.
|
||||
$url = new \moodle_url('/calendar/view.php', ['view' => 'upcoming', 'lookahead' => '30']);
|
||||
$pix = new \pix_icon('i/calendar', get_string('upcomingevents', 'calendar'));
|
||||
$pix = new \pix_icon('i/calendar', get_string('viewupcomingactivitiesdue', 'calendar'));
|
||||
$action = new \core_analytics\prediction_action('viewupcoming', $prediction,
|
||||
$url, $pix, get_string('upcomingevents', 'calendar'));
|
||||
$url, $pix, get_string('viewupcomingactivitiesdue', 'calendar'));
|
||||
|
||||
return array_merge([$action], $parentactions);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user