Added delete handles on all items in context modals

This commit is contained in:
PMKuipers 2023-09-02 23:25:21 +02:00
parent 207c638a66
commit d432f77494
14 changed files with 198 additions and 40 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){function format_date(d,short){d instanceof Date||(d=new Date(d));var monthformat="short";return short&&(monthformat="numeric"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);var dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date,_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings}}));
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){function format_date(d,short){d instanceof Date||(d=new Date(d));var monthformat="short";return short&&(monthformat="numeric"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);var dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date,_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,(function(m,m1){return m1&&values.hasOwnProperty(m1)?values[m1]:m}))}}));
//# sourceMappingURL=string-helper.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@ import {SimpleLine} from "./simpleline/simpleline";
import {call} from 'core/ajax';
import notification from 'core/notification';
import {get_strings} from 'core/str';
import {load_stringkeys, load_strings, format_date, datespaninfo} from './util/string-helper';
import {load_stringkeys, load_strings, format_date, datespaninfo, strformat } from './util/string-helper';
import {objCopy,transportItem} from './studyplan-processor';
import Debugger from './util/debugger';
import {download,upload} from './downloader';
@ -61,10 +61,7 @@ export default {
let string_keys = load_stringkeys({
conditions: [
{ value: null, textkey: 'condition_default'},
{ value: 'ALL', textkey: 'condition_all'},
{ value: '67', textkey: 'condition_67'},
{ value: '50', textkey: 'condition_50'},
{ value: 'ANY', textkey: 'condition_any'},
],
});
@ -174,7 +171,7 @@ export default {
warning: 'course_timing_warning',
timing_ok: 'course_timing_ok',
timing_off: 'course_timing_off',
course: 'course$core',
course: 'course@core',
period: 'period',
yes: 'yes$core',
no: 'no$core',
@ -210,6 +207,15 @@ export default {
item_text: {
select_conditions: "select_conditions",
item_configuration: "item_configuration",
ok: "ok@core",
delete: "delete@core",
item_delete_message: "item_delete_message",
type_course: "course@core",
type_junction: "tool-junction",
type_start: "tool-start",
type_finish: "tool-finish",
type_badge: "tool-badge",
type_invalid: "course-invalid",
},
item_course_text: {
select_conditions: "select_conditions",
@ -219,7 +225,9 @@ export default {
coursetiming_future: "coursetiming_future",
grade_include: "grade_include",
grade_require: "grade_require",
ok: "ok$core",
ok: "ok@core",
cancel: "cancel@core",
delete: "delete@core",
},
invalid: {
error: 'error',
@ -2187,7 +2195,15 @@ export default {
:data="item"
:type="makeType(item)"
@cut="onCut"
><t-item v-model="value[itemidx]" :plan="plan" :page='page' :period='period' :maxspan='maxSpan()'></t-item
><t-item
@deleted="onCut"
v-model="value[itemidx]"
:plan="plan"
:line='line'
:page='page'
:period='period'
:maxspan='maxSpan()'
></t-item
></drag
><drop v-else
:class="'t-slot-drop '+type + (layer > 0?' secondary':' primary')"
@ -2487,6 +2503,10 @@ export default {
type: Object, // Studyplan page
default() { return null;},
},
line: {
type: Object, // Studyplan page
default() { return null;},
},
page: {
type: Object, // Studyplan page
default() { return null;},
@ -2705,6 +2725,36 @@ export default {
delete this.lines[conn.to_id];
}
},
deleteItem(){
const self = this;
const msgparams = {
item: this.text['type_' + this.value.type].toLocaleLowerCase(),
name: (this.value.type=='course')?this.value.course.displayname:"",
line: (this.line) ? this.line.name : "",
period: (this.period) ? this.period.fullname : this.plan.name,
};
this.$bvModal.msgBoxConfirm(strformat(this.text.item_delete_message, msgparams), {
okVariant : 'danger',
okTitle : this.text.ok,
cancelTitle: this.text.cancel,
}).then(value => {
if ( value ) {
// Confirmed to delete.
call([{
methodname: 'local_treestudyplan_delete_studyitem',
args: { 'id': self.value.id, }
}])[0].done(function(response){
if(response.success == true){
self.$emit("deleted",{ data: self.value });
}
}).fail(notification.exception);
}
}).catch(err => {
debug.console.error(err);
});
}
},
computed: {
@ -2715,7 +2765,7 @@ export default {
return !(["start",].includes(this.value.type));
},
hasContext() {
return ['junction','finish'].includes(this.value.type);
return ['start','junction','finish'].includes(this.value.type);
}
},
created(){
@ -2782,13 +2832,40 @@ export default {
},
template: `
<div class="t-item-base" :id="'studyitem-'+value.id">
<t-item-course v-model="value" v-if="value.type == 'course'"
:plan='plan' :page='page' :period='period' :maxspan='maxspan'></t-item-course>
<t-item-junction v-model="value" v-if="value.type == 'junction'" ></t-item-junction>
<t-item-start v-model="value" v-if="value.type == 'start'" ></t-item-start>
<t-item-finish v-model="value" v-if="value.type == 'finish'" ></t-item-finish>
<t-item-badge v-model="value" v-if="value.type == 'badge'" ></t-item-badge>
<t-item-invalid v-model="value" v-if="value.type == 'invalid'" ></t-item-invalid>
<t-item-course
v-if="value.type == 'course'"
@deleterq="deleteItem"
v-model="value"
:plan='plan'
:page='page'
:period='period'
:maxspan='maxspan'
></t-item-course>
<t-item-junction
v-if="value.type == 'junction'"
@deleterq="deleteItem"
v-model="value"
></t-item-junction>
<t-item-start
v-if="value.type == 'start'"
@deleterq="deleteItem"
v-model="value"
></t-item-start>
<t-item-finish
v-if="value.type == 'finish'"
@deleterq="deleteItem"
v-model="value"
></t-item-finish>
<t-item-badge
v-if="value.type == 'badge'"
@deleterq="deleteItem"
v-model="value"
></t-item-badge>
<t-item-invalid
v-if="value.type == 'invalid'"
@deleterq="deleteItem"
v-model="value"
></t-item-invalid>
<drop v-if='!dummy && hasConnectionsIn' accepts-type="linestart"
:id="'t-item-cend-'+value.id"
class="t-item-connector-end"
@ -2820,13 +2897,15 @@ export default {
</div>
<a v-if="hasContext" class="t-item-config"
v-b-modal="'t-item-config-'+value.id" href="#" @click.prevent=""><i class="fa fa-gear"></i></a>
<b-modal no-body class='t-item-contextview'
<b-modal no-body class=""
:id="'t-item-config-'+value.id"
:title="text['item_configuration']"
scrollable
ok-only
class="t-item-contextview b-modal-justify-footer-between"
>
<b-form-group
v-if="value.type != 'start'"
:label="text.select_conditions"
>
<b-form-select size="sm"
@ -2835,6 +2914,17 @@ export default {
:options="condition_options"
></b-form-select>
</b-form-group>
<template #modal-footer="{ ok, cancel, hide }" >
<a href='#' @click='deleteItem()' class="text-danger"
><i class="fa fa-trash"></i>
{{ text.delete }}
</a>
<b-button size="sm" variant="primary" @click="ok()">
{{ text.ok }}
</b-button>
</template>
</b-modal>
</div>
`,
@ -2864,6 +2954,8 @@ export default {
<b-col md="11">
<b-card-body class="align-items-center">
<i class="fa fa-exclamation"></i> {{text.error}}
<a href='#' @click='$emit("deleterq")' class="text-danger"
><i class="fa fa-trash"></i></a>
</b-card-body>
</b-col>
</b-row>
@ -3015,12 +3107,13 @@ export default {
</b-card-body>
</div>
</div>
<b-modal
<b-modal class=""
:id="'t-item-course-config-'+value.id"
:title="value.course.displayname + ' - ' + value.course.fullname"
ok-only
size="lg"
scrollable
class="b-modal-justify-footer-between"
>
<template #modal-header>
<div>
@ -3056,6 +3149,16 @@ export default {
v-model='value.course.completion'
:course='value.course'
></t-item-course-completion>
<template #modal-footer="{ ok, cancel, hide }" >
<a href='#' @click='$emit("deleterq")' class="text-danger"
><i class="fa fa-trash"></i>
{{ text.delete }}
</a>
<b-button size="sm" variant="primary" @click="ok()">
{{ text.ok }}
</b-button>
</template>
</b-modal>
</b-card></div>
`,
@ -3333,6 +3436,7 @@ export default {
data() {
return {
txt: strings,
text: strings.item_text,
};
},
methods: {
@ -3348,13 +3452,14 @@ export default {
</svg>
<a class="t-item-config badge"
v-b-modal="'t-item-badge-details-'+value.id" href="#" @click.prevent=""><i class="fa fa-gear"></i></a>
<b-modal
<b-modal class=""
:id="'t-item-badge-details-'+value.id"
:title="value.badge.name"
size="lg"
ok-only
centered
scrollable
class="b-modal-justify-footer-between"
>
<template #modal-header>
<div>
@ -3376,6 +3481,15 @@ export default {
<a :href="value.badge.infolink">{{ txt.badge.badgeinfo }}</a></strong></p>
</b-col></b-row>
</b-container>
<template #modal-footer="{ ok, cancel, hide }" >
<a href='#' @click='$emit("deleterq")' class="text-danger"
><i class="fa fa-trash"></i>
{{ text.delete }}
</a>
<b-button size="sm" variant="primary" @click="ok()">
{{ text.ok }}
</b-button>
</template>
</b-modal>
</div>

View File

@ -117,3 +117,18 @@ export function datespaninfo(first,last){
}
/**
* String formatting function - replaces {name} in string by value of same key in values parameter
* @param {string} str String t
* @param {object} values Object containing keys to replace {key} strings with
* @returns Formatted string
*/
export function strformat(str,values) {
return str.replace(/\{(\w+)\}/g, (m, m1) => {
if (m1 && values.hasOwnProperty(m1)) {
return values[m1];
} else {
return m;
}
});
}

View File

@ -14,17 +14,21 @@
--incomplete: var(--gray);
}
.path-local-treestudyplan div.tab-pane:target {
.path-local-treestudyplan div.tab-pane:target,
.features-treestudyplan div.tab-pane:target {
margin-top: 0;
}
.path-local-treestudyplan [v-cloak] {
.path-local-treestudyplan [v-cloak],
.features-treestudyplan [v-cloak] {
visibility: hidden;
}
.path-local-treestudyplan .vue-loader {
.path-local-treestudyplan .vue-loader,
.features-treestudyplan .vue-loader {
width: 32px;
margin: auto;
}
.path-local-treestudyplan .special {
.path-local-treestudyplan .special,
.features-treestudyplan .special {
color: gold;
}
@ -640,7 +644,7 @@
.path-local-treestudyplan a.t-item-config,
.features-treestudyplan a.t-item-config {
position: absolute;
top: -5px;
top: -10px;
right: -5px;
}
.path-local-treestudyplan a.t-item-config.badge,
@ -1327,3 +1331,8 @@
.features-treestudyplan .border-grey {
border-color: #aaa;
}
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
justify-content: space-between;
}

View File

@ -143,6 +143,7 @@ $string["tool-junction"] = 'Junction';
$string["tool-start"] = 'Start/continue';
$string["tool-finish"] = 'Finish';
$string["tool-badge"] = 'Badge';
$string["course-invalid"] = "Error";
$string["badges"] = 'Badges';
@ -330,7 +331,7 @@ $string["course_timing_off"] = 'Course timing does not match period timing. Clic
$string["course_period_span"] = 'Spans';
$string["course_period_span_desc"] = 'If the space directly after this course is free, the course can be expanded to span multiple periods.';
$string["view_completion_report"] = 'View detailed course completion report';
$string["item_delete_message"] = 'Are you sure you want to delete {$a->item} {$a->name} from studyline {$a->line} in period {$a->period}?';
$string["item_delete_message"] = 'Are you sure you want to delete the {item} {name} from studyline {line} in {period}?';
$string["student_not_tracked"] = 'Not enrolled in this course';
$string["completion_not_enabled"] = 'Completion is not enabled in this course';

View File

@ -143,6 +143,7 @@ $string["tool-junction"] = 'Kruispunt';
$string["tool-start"] = 'Start/Vervolgpunt';
$string["tool-finish"] = 'Eindpunt';
$string["tool-badge"] = 'Badge';
$string["course-invalid"] = "Storing";
$string["badges"] = 'Badges';
@ -331,7 +332,7 @@ $string["course_timing_off"] = 'Cursustiming en periodetiming komen niet overeen
$string["course_period_span"] = 'Duurt';
$string["course_period_span_desc"] = 'Als de ruimte na deze cursus leeg is, kan de cursus worden uitgespreid over meerdere perioden.';
$string["view_completion_report"] = 'Bekijk gedetailleerd voltooiingsoverzicht';
$string["item_delete_message"] = 'Weet je zeker dat je {$a->item} {$a->name} wilt verwijderen uit leerlijn {$a->line} in periode {$a->period}?';
$string["item_delete_message"] = 'Weet je zeker dat je {item} {name} wilt verwijderen uit leerlijn {line} in {period}?';
$string["student_not_tracked"] = 'Niet ingeschreven in deze cursus';
$string["completion_not_enabled"] = 'Cursusvoltooiing is niet ingeschakeld';

8
scss/bootstraptweaking.scss vendored Normal file
View File

@ -0,0 +1,8 @@
.path-local-treestudyplan, .features-treestudyplan {
.b-modal-justify-footer-between .modal-footer {
justify-content: space-between;
}
}

View File

@ -1,4 +1,4 @@
.path-local-treestudyplan {
.path-local-treestudyplan, .features-treestudyplan {
div.tab-pane:target {
margin-top: 0;
}

View File

@ -539,7 +539,7 @@
a.t-item-config {
position: absolute;
top: -5px;
top: -10px;
right: -5px;
}

View File

@ -1,4 +1,5 @@
@import "colors.scss";
@import "generic.scss";
@import "invitemanager.scss";
@import "studyplan.scss"
@import "studyplan.scss";
@import "bootstraptweaking.scss";

View File

@ -14,17 +14,21 @@
--incomplete: var(--gray);
}
.path-local-treestudyplan div.tab-pane:target {
.path-local-treestudyplan div.tab-pane:target,
.features-treestudyplan div.tab-pane:target {
margin-top: 0;
}
.path-local-treestudyplan [v-cloak] {
.path-local-treestudyplan [v-cloak],
.features-treestudyplan [v-cloak] {
visibility: hidden;
}
.path-local-treestudyplan .vue-loader {
.path-local-treestudyplan .vue-loader,
.features-treestudyplan .vue-loader {
width: 32px;
margin: auto;
}
.path-local-treestudyplan .special {
.path-local-treestudyplan .special,
.features-treestudyplan .special {
color: gold;
}
@ -640,7 +644,7 @@
.path-local-treestudyplan a.t-item-config,
.features-treestudyplan a.t-item-config {
position: absolute;
top: -5px;
top: -10px;
right: -5px;
}
.path-local-treestudyplan a.t-item-config.badge,
@ -1327,3 +1331,8 @@
.features-treestudyplan .border-grey {
border-color: #aaa;
}
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
justify-content: space-between;
}