ode-ngjs-front 1.4.12-develop-integration.202506191529 → 1.4.12-develop-integration.202507011402

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.
@@ -1,19 +1,62 @@
1
- interface ScreenTimeData {
2
- weekly: {
3
- [key: string]: number[];
4
- };
5
- daily: {
6
- [key: string]: {
7
- [hour: string]: number;
8
- };
9
- };
10
- }
1
+ import { Moment } from "moment";
2
+ import 'moment/locale/fr';
11
3
  export declare class Controller {
12
4
  selectedUser: string;
13
5
  viewMode: "weekly" | "daily";
14
- screenTimeData: ScreenTimeData;
6
+ userData: {
7
+ [key: string]: {
8
+ weekly: any;
9
+ daily: any;
10
+ };
11
+ };
12
+ selectedDailyDate: string;
13
+ weekStart: Moment;
14
+ weekEnd: Moment;
15
15
  updateChart: () => void;
16
+ todayOnCampus: number;
17
+ todayOffCampus: number;
18
+ todayTotal: number;
19
+ todaySchoolUsePercentage: number;
20
+ todayOutOfSchoolPercentage: number;
21
+ weeklyAvgOnCampus: number;
22
+ weeklyAvgOffCampus: number;
23
+ weeklyTotalAverage: number;
24
+ weeklyAvgSchoolUsePercentage: number;
25
+ weeklyAvgOutOfSchoolPercentage: number;
26
+ fixedTodayOnCampus: number;
27
+ fixedTodayOffCampus: number;
28
+ fixedTodayTotal: number;
29
+ fixedTodaySchoolUsePercentage: number;
30
+ fixedTodayOutOfSchoolPercentage: number;
31
+ fixedWeeklyAvgOnCampus: number;
32
+ fixedWeeklyAvgOffCampus: number;
33
+ fixedWeeklyTotalAverage: number;
34
+ fixedWeeklyAvgSchoolUsePercentage: number;
35
+ fixedWeeklyAvgOutOfSchoolPercentage: number;
36
+ customWeekMode: boolean;
37
+ customStartDate: string;
38
+ customEndDate: string;
39
+ isParent: boolean;
40
+ hasError: boolean;
41
+ errorMessage: string;
42
+ fetchDataForCurrentUser: () => void;
43
+ fetchLightboxData: () => void;
44
+ showLightbox: boolean;
45
+ showDatePicker: boolean;
46
+ children: {
47
+ id: string;
48
+ name: string;
49
+ userId: string;
50
+ }[];
51
+ selectedChild: null;
52
+ selectedChildHistogram: string;
53
+ toggleDatePicker(show: boolean): void;
54
+ setDateFromPicker(date: string): void;
55
+ toggleLightbox(show: boolean): void;
56
+ changeDay(offset: number): void;
57
+ changeWeek(offset: number): void;
58
+ get selectedDailyDateObj(): Date;
59
+ get weekLabel(): string;
16
60
  }
17
61
  export declare const odeModuleName = "odeCantineWidgetModule";
18
- export {};
19
62
  //# sourceMappingURL=screen-time-widget.widget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"screen-time-widget.widget.d.ts","sourceRoot":"","sources":["../../../../src/ts/widgets/screen-time-widget/screen-time-widget.widget.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACpB,MAAM,EAAE;QACJ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;KAC7C,CAAC;CACL;AAsCD,qBAAa,UAAU;IACZ,YAAY,EAAE,MAAM,CAAa;IACjC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAY;IACxC,cAAc,EAAE,cAAc,CAA6B;IAC3D,WAAW,EAAE,MAAM,IAAI,CAAa;CAC9C;AAyHD,eAAO,MAAM,aAAa,2BAA2B,CAAC"}
1
+ {"version":3,"file":"screen-time-widget.widget.d.ts","sourceRoot":"","sources":["../../../../src/ts/widgets/screen-time-widget/screen-time-widget.widget.ts"],"names":[],"mappings":"AAGA,OAAe,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,kBAAkB,CAAC;AAM1B,qBAAa,UAAU;IACZ,YAAY,EAAE,MAAM,CAAM;IAC1B,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAY;IAExC,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,MAAM,EAAE,GAAG,CAAC;YAAC,KAAK,EAAE,GAAG,CAAA;SAAE,CAAA;KAAE,CAAM;IAC9D,iBAAiB,EAAE,MAAM,CAAiC;IAC1D,SAAS,EAAE,MAAM,CAA+B;IAChD,OAAO,EAAE,MAAM,CAA6B;IAE5C,WAAW,EAAE,MAAM,IAAI,CAAa;IAEpC,aAAa,SAAK;IAClB,cAAc,SAAK;IACnB,UAAU,SAAK;IACf,wBAAwB,EAAE,MAAM,CAAK;IACrC,0BAA0B,EAAE,MAAM,CAAK;IAEvC,iBAAiB,SAAK;IACtB,kBAAkB,SAAK;IACvB,kBAAkB,SAAK;IACvB,4BAA4B,EAAE,MAAM,CAAK;IACzC,8BAA8B,EAAE,MAAM,CAAK;IAG3C,kBAAkB,SAAK;IACvB,mBAAmB,SAAK;IACxB,eAAe,SAAK;IACpB,6BAA6B,EAAE,MAAM,CAAK;IAC1C,+BAA+B,EAAE,MAAM,CAAK;IAE5C,sBAAsB,SAAK;IAC3B,uBAAuB,SAAK;IAC5B,uBAAuB,SAAK;IAC5B,iCAAiC,EAAE,MAAM,CAAK;IAC9C,mCAAmC,EAAE,MAAM,CAAK;IAKhD,cAAc,EAAE,OAAO,CAAS;IAChC,eAAe,EAAE,MAAM,CAAM;IAC7B,aAAa,EAAE,MAAM,CAAM;IAE3B,QAAQ,EAAE,OAAO,CAAS;IAE1B,QAAQ,EAAE,OAAO,CAAS;IAC1B,YAAY,EAAE,MAAM,CAAM;IAE1B,uBAAuB,EAAE,MAAM,IAAI,CAAa;IAChD,iBAAiB,EAAE,MAAM,IAAI,CAAa;IAE1C,YAAY,EAAE,OAAO,CAAS;IAC9B,cAAc,EAAE,OAAO,CAAS;IAEhC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAC9D,aAAa,OAAQ;IACrB,sBAAsB,SAAM;IAE5B,gBAAgB,CAAC,IAAI,EAAE,OAAO;IAI9B,iBAAiB,CAAC,IAAI,EAAE,MAAM;IAM9B,cAAc,CAAC,IAAI,EAAE,OAAO;IAwB5B,SAAS,CAAC,MAAM,EAAE,MAAM;IAKxB,UAAU,CAAC,MAAM,EAAE,MAAM;IAMhC,IAAW,oBAAoB,IAAI,IAAI,CAEtC;IAED,IAAW,SAAS,IAAI,MAAM,CAI7B;CACJ;AA2WD,eAAO,MAAM,aAAa,2BAA2B,CAAC"}
package/dist/version.txt CHANGED
@@ -1 +1 @@
1
- ode-ngjs-front 19/06/2025 15:30:15
1
+ ode-ngjs-front 01/07/2025 14:03:24
@@ -1,2 +1,2 @@
1
- "use strict";(self.webpackChunkode_ngjs_front=self.webpackChunkode_ngjs_front||[]).push([[202],{5688:(e,t,n)=>{n.d(t,{Z:()=>i});const i='<div> <label for="userSelect">Choisir un utilisateur :</label> <select id="userSelect" ng-model="ctrl.selectedUser" ng-change="ctrl.updateChart()"> <option value="Mathieu">Mathieu</option> <option value="Jean">Jean</option> </select> <label for="viewMode">Mode :</label> <select id="viewMode" ng-model="ctrl.viewMode" ng-change="ctrl.updateChart()"> <option value="weekly">Hebdomadaire</option> <option value="daily">Quotidien</option> </select> </div> <canvas id="myChart" width="400" height="200"></canvas>'},58:function(e,t,n){var i=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(a,r){function o(e){try{u(i.next(e))}catch(e){r(e)}}function l(e){try{u(i.throw(e))}catch(e){r(e)}}function u(e){var t;e.done?a(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(o,l)}u((i=i.apply(e,t||[])).next())})},a=this&&this.__generator||function(e,t){var n,i,a,r,o={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return r={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(r[Symbol.iterator]=function(){return this}),r;function l(r){return function(l){return function(r){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,i&&(a=2&r[0]?i.return:r[0]?i.throw||((a=i.return)&&a.call(i),0):i.next)&&!(a=a.call(i,r[1])).done)return a;switch(i=0,a&&(r=[2&r[0],a.value]),r[0]){case 0:case 1:a=r;break;case 4:return o.label++,{value:r[1],done:!1};case 5:o.label++,i=r[1],r=[0];continue;case 7:r=o.ops.pop(),o.trys.pop();continue;default:if(!(a=o.trys,(a=a.length>0&&a[a.length-1])||6!==r[0]&&2!==r[0])){o=0;continue}if(3===r[0]&&(!a||r[1]>a[0]&&r[1]<a[3])){o.label=r[1];break}if(6===r[0]&&o.label<a[1]){o.label=a[1],a=r;break}if(a&&o.label<a[2]){o.label=a[2],o.ops.push(r);break}a[2]&&o.ops.pop(),o.trys.pop();continue}r=t.call(e,o)}catch(e){r=[6,e],i=0}finally{n=a=0}if(5&r[0])throw r[1];return{value:r[0]?r[1]:void 0,done:!0}}([r,l])}}},r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.odeModuleName=t.Controller=void 0;var o=r(n(4202)),l=n(9419),u=n(5668);u.Chart.register.apply(u.Chart,u.registerables);var s=function(){this.selectedUser="Mathieu",this.viewMode="weekly",this.screenTimeData={weekly:{},daily:{}},this.updateChart=function(){}};t.Controller=s;var c=function(){function e(){this.restrict="E",this.template=n(5688).Z,this.scope={},this.bindToController=!0,this.controller=[s],this.controllerAs="ctrl",this.require=["odeScreenTimeWidget"]}return e.prototype.link=function(e,t,n,r){return i(this,void 0,void 0,function(){var n,i;return a(this,function(a){return(n=r?r[0]:null)?(i=null,e.$evalAsync(function(){var a=t[0].querySelector("#myChart");if(a){var r=a.getContext("2d");r&&(i=new u.Chart(r,{type:"bar",data:{labels:[],datasets:[{label:"",data:[],borderWidth:1,backgroundColor:"#4e79a7"}]},options:{animation:!1,responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!0},tooltip:{enabled:!1}},scales:{x:{ticks:{autoSkip:!0,maxTicksLimit:10}},y:{beginAtZero:!0}}}}),new Promise(function(e){setTimeout(function(){e({weekly:{Mathieu:[12,19,3,5,2,3,1],Jean:[5,8,6,7,4,2,3]},daily:{Mathieu:{"08:00":15,"09:00":10,"10:00":30,"11:00":20,"12:00":25,"13: 00":17,"16:00":5,"18:00":10,"20:00":8,"22:00":12,"23:00":4},Jean:{"07:00":5,"09:00":25,"10:00":10,"18:00":15}}})},100)}).then(function(e){n.screenTimeData=e,n.updateChart()}),n.updateChart=function(){i&&requestAnimationFrame(function(){var e=[],t=[];if("weekly"===n.viewMode)e=["Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"],t=n.screenTimeData.weekly[n.selectedUser]||[];else{var a=n.screenTimeData.daily[n.selectedUser]||{};t=(e=Object.keys(a)).map(function(e){return a[e]})}i&&(i.data.labels=e,i.data.datasets[0].data=t,i.data.datasets[0].label="weekly"===n.viewMode?"Temps d'écran hebdo (heures)":"Temps d'écran aujourd'hui (minutes)",i.update())})},e.$watch(function(){return n.selectedUser},function(){return n.updateChart()}),e.$watch(function(){return n.viewMode},function(){return n.updateChart()}))}}),[2]):[2]})})},e}();(0,l.notif)().onLangReady().promise.then(function(e){(0,l.conf)().Platform.idiom.addKeys(n(1245))}),t.odeModuleName="odeCantineWidgetModule",o.default.module(t.odeModuleName,[]).directive("odeScreenTimeWidget",function(){return new c})},1245:e=>{e.exports={}}}]);
1
+ "use strict";(self.webpackChunkode_ngjs_front=self.webpackChunkode_ngjs_front||[]).push([[202],{5688:(e,t,o)=>{o.d(t,{Z:()=>a});const a='<style>.screen-time-summary{padding:16px;font-family:Roboto,sans-serif;display:flex;flex-direction:column;gap:12px}.title{padding-bottom:6px;font-size:16px;color:#4a4a4a;font-weight:700;border-bottom:1px solid #e0e0e0}.summary-row{display:flex;gap:12px}.summary-row:nth-of-type(2){margin-top:10px}.summary-block{flex:1;background:#e5f5ff;border-radius:12px;padding:12px;box-shadow:0 1px 3px rgba(0,0,0,.1)}.summary-block .label{font-size:16px;color:#4a4a4a;font-weight:700;margin-bottom:4px}.summary-block .value{font-size:32px;color:#333}.percentage-bar-container{width:100%;height:10px;background-color:#e0e0e0;border-radius:5px;margin-top:5px;display:flex;overflow:hidden}.percentage-bar{height:100%;transition:width .5s ease-in-out;border-radius:5px}.au-college{background-color:#2a9cc8}.hors-college{background-color:#ecbe30}.legend{display:flex;gap:16px;align-items:center;margin-top:10px;font-size:10px;color:#333}.legend-item{display:flex;align-items:center;gap:6px}.legend-square{width:16px;height:16px;border-radius:4px}.legend-au-college{background-color:#2a9cc8}.legend-hors-college{background-color:#ecbe30}.custom-select{appearance:none;border:none;padding:8px 32px 8px 12px;border-radius:6px;font-size:16px;color:#333;font-family:Roboto,sans-serif;background:#fff url("data:image/svg+xml,%3Csvg fill=\'none\' stroke=\'%23666\' stroke-width=\'2\' viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath stroke-linecap=\'round\' stroke-linejoin=\'round\' d=\'M19 9l-7 7-7-7\'%3E%3C/path%3E%3C/svg%3E") no-repeat right 10px center;background-size:16px;cursor:pointer;min-width:150px}.custom-select:focus{outline:0;box-shadow:0 0 0 2px rgba(42,156,200,.3)}.see-more{display:flex;justify-content:flex-end;margin-top:8px;padding-left:4px}.see-more button{background-color:transparent;border:none;font-family:Roboto,sans-serif;font-weight:600;font-size:16px;line-height:24px;padding:6px 12px;cursor:pointer;color:#2a9cc8;border-radius:4px;transition:background-color .2s ease}.see-more button:hover{background-color:#f0f8fc}.centered-controls{margin:0 auto 20px auto;width:fit-content;text-align:center}.close-button-container{display:flex;justify-content:flex-end;margin-top:20px}.close-button{width:84px;height:40px;padding:8px 16px;background:#ff8d2e;color:#fff;font-size:16px;font-weight:700;border:none;border-radius:8px;cursor:pointer;transition:background .3s ease}.close-button:hover{background:#e67c24}.date-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.nav-button{background:0 0;border:none;font-size:24px;cursor:pointer}.date-navigation{display:flex;align-items:center;justify-content:center;gap:1rem}.date-navigation button{background:0 0;border:none;font-size:1.5rem;cursor:pointer}.selected-date{cursor:pointer;font-weight:700}.error-message{background-color:#ffe5e5;color:#c00;border:1px solid #c00;padding:12px;border-radius:6px;font-size:14px;font-weight:500}</style> <div class="screen-time-widget-container"> <div class="screen-time-summary"> <div class="title"> <div class="label">TEMPS D\'ÉCRAN</div> </div> <div ng-if="ctrl.isParent"> <select id="userSelect" class="custom-select" ng-model="ctrl.selectedUser" ng-options="child.userId as child.name for child in ctrl.children" ng-change="ctrl.fetchDataForCurrentUser()"> </select> </div> <div class="error-message" ng-if="ctrl.errorMessage"> {{ ctrl.errorMessage }} </div> <div ng-if="!ctrl.errorMessage"> <div class="summary-row"> <div class="summary-block"> <div class="label">Aujourd\'hui</div> <div class="value">{{ ctrl.todayTotal | duration }}</div> <div class="percentage-bar-container"> <div class="percentage-bar au-college" ng-style="{ width: ctrl.todaySchoolUsePercentage + \'%\' }" title="{{ ctrl.todaySchoolUsePercentage | duration }} au collège"> </div> <div class="percentage-bar hors-college" ng-style="{ width: ctrl.todayOutOfSchoolPercentage + \'%\' }" title="{{ ctrl.todayOutOfSchoolPercentage | duration }} hors collège"></div> </div> </div> </div> <div class="summary-row"> <div class="summary-block"> <div class="label">Moyenne de la semaine</div> <div class="value">{{ ctrl.weeklyTotalAverage | duration }}</div> <div class="percentage-bar-container"> <div class="percentage-bar au-college" ng-style="{ width: ctrl.weeklyAvgSchoolUsePercentage + \'%\' }" title="{{ ctrl.weeklyAvgSchoolUsePercentage | duration }} au Collège"> </div> <div class="percentage-bar hors-college" ng-style="{ width: ctrl.weeklyAvgOutOfSchoolPercentage + \'%\' }" title="{{ ctrl.weeklyAvgOutOfSchoolPercentage | duration}} hors collège"></div> </div> </div> </div> <div class="legend"> <div class="legend-item"> <div class="legend-square legend-au-college"></div> <span>Au collège</span> </div> <div class="legend-item"> <div class="legend-square legend-hors-college"></div> <span>Hors collège</span> </div> <div class="see-more"> <button ng-click="ctrl.toggleLightbox(true)">Voir le détail</button> </div> </div> </div> </div> <ode-modal visible="ctrl.showLightbox" on-close="ctrl.toggleLightbox(false)" size="lg" dnd-nodrag> <ode-modal-title> <h2>Temps d\'écran</h2> </ode-modal-title> <ode-modal-body> <div class="centered-controls"> <label style="font-size:14px" for="userSelect">Utilisateur :</label> <div ng-if="ctrl.isParent"> <select id="userSelect" class="custom-select" ng-model="ctrl.selectedChildHistogram" ng-options="child.userId as child.name for child in ctrl.children" ng-change="ctrl.fetchLightboxData()"> </select> </div> <label for="viewMode">Affichage :</label> <select id="viewMode" class="custom-select" ng-model="ctrl.viewMode" ng-change="ctrl.updateChart()"> <option value="weekly">Hebdomadaire</option> <option value="daily">Quotidien</option> </select> </div> <canvas id="myChart" style="width:100%;height:200px"></canvas> <div class="date-selectors centered-controls" ng-if="ctrl.showLightbox"> <div class="date-navigation" ng-if="ctrl.viewMode === \'daily\'"> <button ng-click="ctrl.changeDay(-1)">←</button> <div ng-if="!ctrl.showDatePicker" class="selected-date" ng-click="ctrl.toggleDatePicker(true)"> {{ ctrl.selectedDailyDateObj | date:\'fullDate\' }} </div> <input type="date" ng-if="ctrl.showDatePicker" ng-model="ctrl.selectedDailyDate" ng-change="ctrl.setDateFromPicker(ctrl.selectedDailyDate)" ng-blur="ctrl.toggleDatePicker(false)" max="{{ ctrl.selectedDailyDate }}"/> <button ng-click="ctrl.changeDay(1)">→</button> </div> <div class="date-navigation" ng-if="ctrl.viewMode === \'weekly\'"> <button ng-click="ctrl.changeWeek(-1)">←</button> <div class="selected-date">{{ ctrl.weekLabel }}</div> <button ng-click="ctrl.changeWeek(1)">→</button> </div> </div> <div class="close-button-container"> <button class="close-button" ng-click="ctrl.toggleLightbox(false)">Fermer</button> </div> </ode-modal-body> </ode-modal> </div>'},58:function(e,t,o){var a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.odeModuleName=t.Controller=void 0;var r=a(o(4202)),i=o(9419),s=o(5668),l=a(o(381));o(4470),s.Chart.register.apply(s.Chart,s.registerables),l.default.locale("fr");var n=function(){function e(){this.selectedUser="",this.viewMode="weekly",this.userData={},this.selectedDailyDate=(0,l.default)().format("YYYY-MM-DD"),this.weekStart=(0,l.default)().startOf("isoWeek"),this.weekEnd=(0,l.default)().endOf("isoWeek"),this.updateChart=function(){},this.todayOnCampus=0,this.todayOffCampus=0,this.todayTotal=0,this.todaySchoolUsePercentage=0,this.todayOutOfSchoolPercentage=0,this.weeklyAvgOnCampus=0,this.weeklyAvgOffCampus=0,this.weeklyTotalAverage=0,this.weeklyAvgSchoolUsePercentage=0,this.weeklyAvgOutOfSchoolPercentage=0,this.fixedTodayOnCampus=0,this.fixedTodayOffCampus=0,this.fixedTodayTotal=0,this.fixedTodaySchoolUsePercentage=0,this.fixedTodayOutOfSchoolPercentage=0,this.fixedWeeklyAvgOnCampus=0,this.fixedWeeklyAvgOffCampus=0,this.fixedWeeklyTotalAverage=0,this.fixedWeeklyAvgSchoolUsePercentage=0,this.fixedWeeklyAvgOutOfSchoolPercentage=0,this.customWeekMode=!1,this.customStartDate="",this.customEndDate="",this.isParent=!1,this.hasError=!1,this.errorMessage="",this.fetchDataForCurrentUser=function(){},this.fetchLightboxData=function(){},this.showLightbox=!1,this.showDatePicker=!1,this.children=[],this.selectedChild=null,this.selectedChildHistogram=""}return e.prototype.toggleDatePicker=function(e){this.showDatePicker=e},e.prototype.setDateFromPicker=function(e){this.selectedDailyDate=(0,l.default)(e).format("YYYY-MM-DD"),this.showDatePicker=!1,this.fetchLightboxData()},e.prototype.toggleLightbox=function(e){this.showLightbox=e,e&&(this.fixedTodayOnCampus=this.todayOnCampus,this.fixedTodayOffCampus=this.todayOffCampus,this.fixedTodayTotal=this.todayTotal,this.fixedTodaySchoolUsePercentage=this.todaySchoolUsePercentage,this.fixedTodayOutOfSchoolPercentage=this.todayOutOfSchoolPercentage,this.fixedWeeklyAvgOnCampus=this.weeklyAvgOnCampus,this.fixedWeeklyAvgOffCampus=this.weeklyAvgOffCampus,this.fixedWeeklyTotalAverage=this.weeklyTotalAverage,this.fixedWeeklyAvgSchoolUsePercentage=this.weeklyAvgSchoolUsePercentage,this.fixedWeeklyAvgOutOfSchoolPercentage=this.weeklyAvgOutOfSchoolPercentage,this.selectedDailyDate=(0,l.default)().format("YYYY-MM-DD"),this.weekStart=(0,l.default)().startOf("isoWeek"),this.weekEnd=(0,l.default)().endOf("isoWeek"),this.selectedChildHistogram=this.selectedUser,this.fetchLightboxData())},e.prototype.changeDay=function(e){this.selectedDailyDate=(0,l.default)(this.selectedDailyDate).add(e,"days").format("YYYY-MM-DD"),this.fetchLightboxData()},e.prototype.changeWeek=function(e){this.weekStart=this.weekStart.clone().add(e,"weeks"),this.weekEnd=this.weekStart.clone().endOf("isoWeek"),this.fetchLightboxData()},Object.defineProperty(e.prototype,"selectedDailyDateObj",{get:function(){return new Date(this.selectedDailyDate)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"weekLabel",{get:function(){var e=this.weekStart.format("dddd D MMMM"),t=this.weekEnd.format("dddd D MMMM");return"du ".concat(e," au ").concat(t)},enumerable:!1,configurable:!0}),e}();function c(e,t,o,a,r,i){t.children=d(t);var s="/appregistry/screen-time/".concat(o,"/weekly?startDate=").concat(r,"&endDate=").concat(i,"&mock=false"),l="/appregistry/screen-time/".concat(o,"/daily?date=").concat(a,"&mock=false");return Promise.all([e.get(s),e.get(l)]).then(function(e){var o=e[0],a=e[1];return console.log("weekly: ",o.data),console.log("daily: ",a.data),t.hasError=!1,t.errorMessage="",{weekly:o.data.dailySummaries.reduce(function(e,t){return e[t.date]={duration:t.durationMinutes,schoolUsePercentage:t.schoolUsePercentage/100},e},{}),daily:a.data.durations.map(function(e){return{hour:e.hour,duration:e.durationMinutes,schoolUsePercentage:e.schoolUsePercentage/100}})}}).catch(function(e){return t.hasError=!0,404===(null==e?void 0:e.status)?t.errorMessage="Erreur lors de l’identification de l’utilisateur. Contactez l’administrateur de votre établissement.":t.errorMessage="Un problème technique est survenu. Si le problème persiste contactez l’administrateur de votre établissement.",console.error("Error fetching data for current user and dates:",e),Promise.reject(e)})}function d(e){var t=(0,i.session)().user.children;e.isParent=!1;if(t&&Object.keys(t).length>0){e.isParent=!0;var o=100;return Object.entries(t).map(function(e){var t=e[0],a=e[1],r=(o++).toString();return{id:t,name:"".concat(a.firstName," ").concat(a.lastName),userId:r}})}return[]}t.Controller=n;var u=function(){function e(){this.restrict="E",this.template=o(5688).Z,this.scope={},this.bindToController=!0,this.controller=[n],this.controllerAs="ctrl",this.require=["odeScreenTimeWidget"]}return e.prototype.link=function(e,t,o,a){var n=a?a[0]:null;if(n){var u=r.default.injector(["ng"]).get("$http"),h=(0,i.session)().user.userId;n.fetchDataForCurrentUser();var g=null,f=function(e,t,o,a){return console.log("3"),"".concat(e,"_daily_").concat(t,"_weekly_").concat(o,"_").concat(a)};n.fetchDataForCurrentUser=function(){n.errorMessage="",n.hasError=!1;var t=f(n.selectedUser,(0,l.default)().format("YYYY-MM-DD"),(0,l.default)().startOf("isoWeek").format("YYYY-MM-DD"),(0,l.default)().endOf("isoWeek").format("YYYY-MM-DD"));c(u,n,n.selectedUser,(0,l.default)().format("YYYY-MM-DD"),(0,l.default)().startOf("isoWeek").format("YYYY-MM-DD"),(0,l.default)().endOf("isoWeek").format("YYYY-MM-DD")).then(function(o){var a,r,i,s,c,d,u,h,g,f;n.userData[t]={weekly:o.weekly,daily:o.daily},a=o.weekly,r=0,i=0,s=0,c=(0,l.default)().format("YYYY-MM-DD"),d=0,u=0,h=0,g=0,f=0,Object.keys(a).forEach(function(e){var t=a[e],o=t.duration||0,p=t.schoolUsePercentage||0,y=o*p,m=o*(1-p);r+=y,i+=m,s++,h+=y,g+=m,f+=o,(0,l.default)(e).format("YYYY-MM-DD")===c&&(d=y,u=m,n.todaySchoolUsePercentage=100*t.schoolUsePercentage,n.todayOutOfSchoolPercentage=100-100*t.schoolUsePercentage)}),n.todayOnCampus=d,n.todayOffCampus=u,n.todayTotal=d+u,n.weeklyAvgOnCampus=s>0?r/s:0,n.weeklyAvgOffCampus=s>0?i/s:0,n.weeklyTotalAverage=n.weeklyAvgOnCampus+n.weeklyAvgOffCampus,f>0?(n.weeklyAvgSchoolUsePercentage=h/f*100,n.weeklyAvgOutOfSchoolPercentage=g/f*100):(n.weeklyAvgSchoolUsePercentage=0,n.weeklyAvgOutOfSchoolPercentage=0),e.$applyAsync()}).catch(function(t){e.$applyAsync(),console.error("Error fetching initial data for current user:",t)})},n.fetchLightboxData=function(){var t=n.selectedChildHistogram||n.selectedUser;if(t){var o=f(t,n.selectedDailyDate,n.weekStart.format("YYYY-MM-DD"),n.weekEnd.format("YYYY-MM-DD"));n.userData[o]?n.showLightbox&&setTimeout(function(){return n.updateChart()},50):c(u,n,t,n.selectedDailyDate,n.weekStart.format("YYYY-MM-DD"),n.weekEnd.format("YYYY-MM-DD")).then(function(t){n.userData[o]={weekly:t.weekly,daily:t.daily},n.showLightbox&&setTimeout(function(){return n.updateChart()},50),e.$applyAsync()}).catch(function(e){console.error("Error fetching data for lightbox:",e)})}},n.updateChart=function(){var e=t[0].querySelector("#myChart");if(e){var o=e.getContext("2d");if(o){g&&g.destroy();var a=[],r=[],i=[],c=n.selectedChildHistogram||n.selectedUser,d=f(c,n.selectedDailyDate,n.weekStart.format("YYYY-MM-DD"),n.weekEnd.format("YYYY-MM-DD")),u=n.userData[d];if(u){var h="weekly"===n.viewMode?u.weekly:u.daily;if(h){if("weekly"===n.viewMode)Object.keys(h).sort().forEach(function(e){var t=h[e];a.push((0,l.default)(e).format("ddd D")),r.push(t.duration*t.schoolUsePercentage),i.push(t.duration*(1-t.schoolUsePercentage))});else h.forEach(function(e){a.push("".concat(e.hour,"h")),r.push(e.duration*e.schoolUsePercentage),i.push(e.duration*(1-e.schoolUsePercentage))});g=new s.Chart(o,{type:"bar",data:{labels:a,datasets:[{label:"Usage scolaire",data:r,backgroundColor:"#2A9CC8"},{label:"Usage hors scolaire",data:i,backgroundColor:"#ECBE30"}]},options:{plugins:{tooltip:{callbacks:{label:function(e){var t=e.raw;return"".concat(e.dataset.label,": ").concat(t," minutes")}}}},responsive:!0,scales:{x:{stacked:!0},y:{stacked:!0,beginAtZero:!0,title:{display:!0,text:"Minutes"}}}}})}}}}},n.children=d(n),n.isParent&&n.children.length>0?(n.selectedUser||(n.selectedUser=n.children[0].userId),n.fetchDataForCurrentUser()):!n.isParent&&h?(n.selectedUser=h,n.fetchDataForCurrentUser()):(n.hasError=!0,n.errorMessage="Aucun utilisateur disponible pour afficher les données de temps d'écran.",e.$applyAsync()),e.$watch(function(){return n.viewMode},function(e,t){e!==t&&n.showLightbox&&setTimeout(function(){return n.updateChart()},50)}),e.$watch(function(){return n.selectedChildHistogram},function(e,t){e!==t&&n.showLightbox&&n.fetchLightboxData()}),e.$watch(function(){return n.showLightbox},function(e){e?setTimeout(function(){n.updateChart()},100):g&&(g.destroy(),g=null)})}},e}();t.odeModuleName="odeCantineWidgetModule",r.default.module(t.odeModuleName,[]).filter("duration",function(){return function(e){if(isNaN(e)||null===e||e<0)return"0m";var t=Math.floor(e),o=Math.floor(t/60),a=t%60,r="";return o>0&&(r+="".concat(o,"h")),(a>0||0===o&&0===t)&&(r+="".concat(a,"m")),r.trim()||"0m"}}).directive("odeScreenTimeWidget",function(){return new u}),(0,i.notif)().onLangReady().promise.then(function(e){(0,i.conf)().Platform.idiom.addKeys(o(1245))})},1245:e=>{e.exports={}}}]);
2
2
  //# sourceMappingURL=screen-time-widget.widget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"widgets/screen-time-widget/screen-time-widget.widget.js","mappings":"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","sources":["webpack://ode-ngjs-front/./src/ts/widgets/screen-time-widget/screen-time-widget.widget.html","webpack://ode-ngjs-front/./src/ts/widgets/screen-time-widget/screen-time-widget.widget.ts"],"sourcesContent":["// Module\nvar code = \"<div> <label for=\\\"userSelect\\\">Choisir un utilisateur :</label> <select id=\\\"userSelect\\\" ng-model=\\\"ctrl.selectedUser\\\" ng-change=\\\"ctrl.updateChart()\\\"> <option value=\\\"Mathieu\\\">Mathieu</option> <option value=\\\"Jean\\\">Jean</option> </select> <label for=\\\"viewMode\\\">Mode :</label> <select id=\\\"viewMode\\\" ng-model=\\\"ctrl.viewMode\\\" ng-change=\\\"ctrl.updateChart()\\\"> <option value=\\\"weekly\\\">Hebdomadaire</option> <option value=\\\"daily\\\">Quotidien</option> </select> </div> <canvas id=\\\"myChart\\\" width=\\\"400\\\" height=\\\"200\\\"></canvas>\";\n// Exports\nexport default code;","import angular, { IAttributes, IController, IDirective, IScope } from \"angular\";\nimport { conf, notif } from \"../../utils\";\nimport { Chart, registerables } from \"chart.js\";\n\n// Register Chart.js components\nChart.register(...registerables);\n\n// Screen time data structure\ninterface ScreenTimeData {\n weekly: {\n [key: string]: number[]; // per user, 7-day weekly data\n };\n daily: {\n [key: string]: { [hour: string]: number }; // per user, hourly screen time (e.g., \"09:00\": 30)\n };\n}\n// Mocked API function\nfunction fetchScreenTimeData(): Promise<ScreenTimeData> {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n weekly: {\n Mathieu: [12, 19, 3, 5, 2, 3, 1],\n Jean: [5, 8, 6, 7, 4, 2, 3]\n },\n daily: {\n Mathieu: {\n \"08:00\": 15,\n \"09:00\": 10,\n \"10:00\": 30,\n \"11:00\": 20,\n \"12:00\": 25,\n \"13: 00\": 17,\n \"16:00\": 5,\n \"18:00\": 10,\n \"20:00\": 8,\n \"22:00\": 12,\n \"23:00\": 4\n },\n Jean: {\n \"07:00\": 5,\n \"09:00\": 25,\n \"10:00\": 10,\n \"18:00\": 15\n }\n }\n });\n }, 100);\n });\n}\n\n\n// Controller\nexport class Controller {\n public selectedUser: string = \"Mathieu\";\n public viewMode: \"weekly\" | \"daily\" = \"weekly\";\n public screenTimeData: ScreenTimeData = { weekly: {}, daily: {} };\n public updateChart: () => void = () => { };\n}\n\n\nclass Directive implements IDirective<IScope, JQLite, IAttributes, IController[]> {\n restrict = \"E\";\n template = require(\"./screen-time-widget.widget.html\").default;\n scope = {};\n bindToController = true;\n controller = [Controller];\n controllerAs = \"ctrl\";\n require = [\"odeScreenTimeWidget\"];\n\n async link(scope: IScope, elem: angular.IAugmentedJQuery, attrs: IAttributes, controllers?: IController[]) {\n const ctrl: Controller | null = controllers ? (controllers[0] as Controller) : null;\n if (!ctrl) return;\n\n let chartInstance: Chart | null = null;\n let debounceTimeout: any;\n\n // Wait for DOM render\n scope.$evalAsync(() => {\n const canvas = elem[0].querySelector<HTMLCanvasElement>(\"#myChart\");\n if (!canvas) return;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n // Init blank chart first\n chartInstance = new Chart(ctx, {\n type: \"bar\",\n data: {\n labels: [],\n datasets: [{\n label: \"\",\n data: [],\n borderWidth: 1,\n backgroundColor: \"#4e79a7\"\n }]\n },\n options: {\n animation: false,\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: {\n display: true\n },\n tooltip: {\n enabled: false\n }\n },\n scales: {\n x: {\n ticks: {\n autoSkip: true,\n maxTicksLimit: 10\n }\n },\n y: {\n beginAtZero: true\n }\n }\n }\n });\n\n // Fetch and update chart\n fetchScreenTimeData().then((data) => {\n ctrl.screenTimeData = data;\n ctrl.updateChart();\n });\n\n ctrl.updateChart = () => {\n if (!chartInstance) return;\n\n requestAnimationFrame(() => {\n let labels: string[] = [];\n let values: number[] = [];\n\n if (ctrl.viewMode === \"weekly\") {\n labels = [\"Lundi\", \"Mardi\", \"Mercredi\", \"Jeudi\", \"Vendredi\", \"Samedi\", \"Dimanche\"];\n values = ctrl.screenTimeData.weekly[ctrl.selectedUser] || [];\n } else {\n const daily = ctrl.screenTimeData.daily[ctrl.selectedUser] || {};\n labels = Object.keys(daily);\n values = labels.map(hour => daily[hour]);\n }\n\n if (chartInstance) {\n chartInstance.data.labels = labels;\n chartInstance.data.datasets[0].data = values;\n chartInstance.data.datasets[0].label =\n ctrl.viewMode === \"weekly\"\n ? \"Temps d'écran hebdo (heures)\"\n : \"Temps d'écran aujourd'hui (minutes)\";\n chartInstance.update();\n }\n\n });\n };\n\n\n // Watcher for view mode or user change (if you bind to select/input in HTML)\n scope.$watch(() => ctrl.selectedUser, () => ctrl.updateChart());\n scope.$watch(() => ctrl.viewMode, () => ctrl.updateChart());\n });\n }\n}\n\nfunction DirectiveFactory() {\n return new Directive();\n}\n\nnotif()\n .onLangReady()\n .promise.then((lang) => {\n switch (lang) {\n default:\n conf().Platform.idiom.addKeys(require(\"./i18n/fr.json\"));\n break;\n }\n });\n\nexport const odeModuleName = \"odeCantineWidgetModule\";\n\nangular\n .module(odeModuleName, [])\n .directive(\"odeScreenTimeWidget\", DirectiveFactory);\n"],"names":["Chart","register","registerables","selectedUser","viewMode","screenTimeData","weekly","daily","updateChart","Controller","restrict","template","scope","bindToController","controller","controllerAs","require","link","elem","attrs","controllers","ctrl","chartInstance","$evalAsync","canvas","querySelector","ctx","getContext","type","data","labels","datasets","label","borderWidth","backgroundColor","options","animation","responsive","maintainAspectRatio","plugins","legend","display","tooltip","enabled","scales","x","ticks","autoSkip","maxTicksLimit","y","beginAtZero","Promise","resolve","setTimeout","Mathieu","Jean","then","requestAnimationFrame","values","Object","keys","map","hour","update","$watch","notif","onLangReady","promise","lang","conf","Platform","idiom","addKeys","odeModuleName","module","directive","Directive"],"sourceRoot":""}
1
+ {"version":3,"file":"widgets/screen-time-widget/screen-time-widget.widget.js","mappings":"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","sources":["webpack://ode-ngjs-front/./src/ts/widgets/screen-time-widget/screen-time-widget.widget.html","webpack://ode-ngjs-front/./src/ts/widgets/screen-time-widget/screen-time-widget.widget.ts"],"sourcesContent":["// Module\nvar code = \"<style>.screen-time-summary{padding:16px;font-family:Roboto,sans-serif;display:flex;flex-direction:column;gap:12px}.title{padding-bottom:6px;font-size:16px;color:#4a4a4a;font-weight:700;border-bottom:1px solid #e0e0e0}.summary-row{display:flex;gap:12px}.summary-row:nth-of-type(2){margin-top:10px}.summary-block{flex:1;background:#e5f5ff;border-radius:12px;padding:12px;box-shadow:0 1px 3px rgba(0,0,0,.1)}.summary-block .label{font-size:16px;color:#4a4a4a;font-weight:700;margin-bottom:4px}.summary-block .value{font-size:32px;color:#333}.percentage-bar-container{width:100%;height:10px;background-color:#e0e0e0;border-radius:5px;margin-top:5px;display:flex;overflow:hidden}.percentage-bar{height:100%;transition:width .5s ease-in-out;border-radius:5px}.au-college{background-color:#2a9cc8}.hors-college{background-color:#ecbe30}.legend{display:flex;gap:16px;align-items:center;margin-top:10px;font-size:10px;color:#333}.legend-item{display:flex;align-items:center;gap:6px}.legend-square{width:16px;height:16px;border-radius:4px}.legend-au-college{background-color:#2a9cc8}.legend-hors-college{background-color:#ecbe30}.custom-select{appearance:none;border:none;padding:8px 32px 8px 12px;border-radius:6px;font-size:16px;color:#333;font-family:Roboto,sans-serif;background:#fff url(\\\"data:image/svg+xml,%3Csvg fill='none' stroke='%23666' stroke-width='2' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E\\\") no-repeat right 10px center;background-size:16px;cursor:pointer;min-width:150px}.custom-select:focus{outline:0;box-shadow:0 0 0 2px rgba(42,156,200,.3)}.see-more{display:flex;justify-content:flex-end;margin-top:8px;padding-left:4px}.see-more button{background-color:transparent;border:none;font-family:Roboto,sans-serif;font-weight:600;font-size:16px;line-height:24px;padding:6px 12px;cursor:pointer;color:#2a9cc8;border-radius:4px;transition:background-color .2s ease}.see-more button:hover{background-color:#f0f8fc}.centered-controls{margin:0 auto 20px auto;width:fit-content;text-align:center}.close-button-container{display:flex;justify-content:flex-end;margin-top:20px}.close-button{width:84px;height:40px;padding:8px 16px;background:#ff8d2e;color:#fff;font-size:16px;font-weight:700;border:none;border-radius:8px;cursor:pointer;transition:background .3s ease}.close-button:hover{background:#e67c24}.date-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.nav-button{background:0 0;border:none;font-size:24px;cursor:pointer}.date-navigation{display:flex;align-items:center;justify-content:center;gap:1rem}.date-navigation button{background:0 0;border:none;font-size:1.5rem;cursor:pointer}.selected-date{cursor:pointer;font-weight:700}.error-message{background-color:#ffe5e5;color:#c00;border:1px solid #c00;padding:12px;border-radius:6px;font-size:14px;font-weight:500}</style> <div class=\\\"screen-time-widget-container\\\"> <div class=\\\"screen-time-summary\\\"> <div class=\\\"title\\\"> <div class=\\\"label\\\">TEMPS D'ÉCRAN</div> </div> <div ng-if=\\\"ctrl.isParent\\\"> <select id=\\\"userSelect\\\" class=\\\"custom-select\\\" ng-model=\\\"ctrl.selectedUser\\\" ng-options=\\\"child.userId as child.name for child in ctrl.children\\\" ng-change=\\\"ctrl.fetchDataForCurrentUser()\\\"> </select> </div> <div class=\\\"error-message\\\" ng-if=\\\"ctrl.errorMessage\\\"> {{ ctrl.errorMessage }} </div> <div ng-if=\\\"!ctrl.errorMessage\\\"> <div class=\\\"summary-row\\\"> <div class=\\\"summary-block\\\"> <div class=\\\"label\\\">Aujourd'hui</div> <div class=\\\"value\\\">{{ ctrl.todayTotal | duration }}</div> <div class=\\\"percentage-bar-container\\\"> <div class=\\\"percentage-bar au-college\\\" ng-style=\\\"{ width: ctrl.todaySchoolUsePercentage + '%' }\\\" title=\\\"{{ ctrl.todaySchoolUsePercentage | duration }} au collège\\\"> </div> <div class=\\\"percentage-bar hors-college\\\" ng-style=\\\"{ width: ctrl.todayOutOfSchoolPercentage + '%' }\\\" title=\\\"{{ ctrl.todayOutOfSchoolPercentage | duration }} hors collège\\\"></div> </div> </div> </div> <div class=\\\"summary-row\\\"> <div class=\\\"summary-block\\\"> <div class=\\\"label\\\">Moyenne de la semaine</div> <div class=\\\"value\\\">{{ ctrl.weeklyTotalAverage | duration }}</div> <div class=\\\"percentage-bar-container\\\"> <div class=\\\"percentage-bar au-college\\\" ng-style=\\\"{ width: ctrl.weeklyAvgSchoolUsePercentage + '%' }\\\" title=\\\"{{ ctrl.weeklyAvgSchoolUsePercentage | duration }} au Collège\\\"> </div> <div class=\\\"percentage-bar hors-college\\\" ng-style=\\\"{ width: ctrl.weeklyAvgOutOfSchoolPercentage + '%' }\\\" title=\\\"{{ ctrl.weeklyAvgOutOfSchoolPercentage | duration}} hors collège\\\"></div> </div> </div> </div> <div class=\\\"legend\\\"> <div class=\\\"legend-item\\\"> <div class=\\\"legend-square legend-au-college\\\"></div> <span>Au collège</span> </div> <div class=\\\"legend-item\\\"> <div class=\\\"legend-square legend-hors-college\\\"></div> <span>Hors collège</span> </div> <div class=\\\"see-more\\\"> <button ng-click=\\\"ctrl.toggleLightbox(true)\\\">Voir le détail</button> </div> </div> </div> </div> <ode-modal visible=\\\"ctrl.showLightbox\\\" on-close=\\\"ctrl.toggleLightbox(false)\\\" size=\\\"lg\\\" dnd-nodrag> <ode-modal-title> <h2>Temps d'écran</h2> </ode-modal-title> <ode-modal-body> <div class=\\\"centered-controls\\\"> <label style=\\\"font-size:14px\\\" for=\\\"userSelect\\\">Utilisateur :</label> <div ng-if=\\\"ctrl.isParent\\\"> <select id=\\\"userSelect\\\" class=\\\"custom-select\\\" ng-model=\\\"ctrl.selectedChildHistogram\\\" ng-options=\\\"child.userId as child.name for child in ctrl.children\\\" ng-change=\\\"ctrl.fetchLightboxData()\\\"> </select> </div> <label for=\\\"viewMode\\\">Affichage :</label> <select id=\\\"viewMode\\\" class=\\\"custom-select\\\" ng-model=\\\"ctrl.viewMode\\\" ng-change=\\\"ctrl.updateChart()\\\"> <option value=\\\"weekly\\\">Hebdomadaire</option> <option value=\\\"daily\\\">Quotidien</option> </select> </div> <canvas id=\\\"myChart\\\" style=\\\"width:100%;height:200px\\\"></canvas> <div class=\\\"date-selectors centered-controls\\\" ng-if=\\\"ctrl.showLightbox\\\"> <div class=\\\"date-navigation\\\" ng-if=\\\"ctrl.viewMode === 'daily'\\\"> <button ng-click=\\\"ctrl.changeDay(-1)\\\">←</button> <div ng-if=\\\"!ctrl.showDatePicker\\\" class=\\\"selected-date\\\" ng-click=\\\"ctrl.toggleDatePicker(true)\\\"> {{ ctrl.selectedDailyDateObj | date:'fullDate' }} </div> <input type=\\\"date\\\" ng-if=\\\"ctrl.showDatePicker\\\" ng-model=\\\"ctrl.selectedDailyDate\\\" ng-change=\\\"ctrl.setDateFromPicker(ctrl.selectedDailyDate)\\\" ng-blur=\\\"ctrl.toggleDatePicker(false)\\\" max=\\\"{{ ctrl.selectedDailyDate }}\\\"/> <button ng-click=\\\"ctrl.changeDay(1)\\\">→</button> </div> <div class=\\\"date-navigation\\\" ng-if=\\\"ctrl.viewMode === 'weekly'\\\"> <button ng-click=\\\"ctrl.changeWeek(-1)\\\">←</button> <div class=\\\"selected-date\\\">{{ ctrl.weekLabel }}</div> <button ng-click=\\\"ctrl.changeWeek(1)\\\">→</button> </div> </div> <div class=\\\"close-button-container\\\"> <button class=\\\"close-button\\\" ng-click=\\\"ctrl.toggleLightbox(false)\\\">Fermer</button> </div> </ode-modal-body> </ode-modal> </div>\";\n// Exports\nexport default code;","import angular, { IAttributes, IController, IDirective, IScope, IHttpService } from \"angular\";\nimport { conf, notif, session } from \"../../utils\";\nimport { Chart, registerables } from \"chart.js\";\nimport moment, { Moment } from \"moment\";\nimport 'moment/locale/fr';\n\nChart.register(...registerables);\nmoment.locale('fr');\n\n// Controller\nexport class Controller {\n public selectedUser: string = \"\";\n public viewMode: \"weekly\" | \"daily\" = \"weekly\";\n\n public userData: { [key: string]: { weekly: any, daily: any } } = {};\n public selectedDailyDate: string = moment().format('YYYY-MM-DD');\n public weekStart: Moment = moment().startOf('isoWeek'); // Monday\n public weekEnd: Moment = moment().endOf('isoWeek'); // Sunday\n\n public updateChart: () => void = () => { };\n\n public todayOnCampus = 0;\n public todayOffCampus = 0;\n public todayTotal = 0;\n public todaySchoolUsePercentage: number = 0;\n public todayOutOfSchoolPercentage: number = 0;\n\n public weeklyAvgOnCampus = 0;\n public weeklyAvgOffCampus = 0;\n public weeklyTotalAverage = 0;\n public weeklyAvgSchoolUsePercentage: number = 0;\n public weeklyAvgOutOfSchoolPercentage: number = 0;\n\n // new props\n public fixedTodayOnCampus = 0;\n public fixedTodayOffCampus = 0;\n public fixedTodayTotal = 0;\n public fixedTodaySchoolUsePercentage: number = 0;\n public fixedTodayOutOfSchoolPercentage: number = 0;\n\n public fixedWeeklyAvgOnCampus = 0;\n public fixedWeeklyAvgOffCampus = 0;\n public fixedWeeklyTotalAverage = 0;\n public fixedWeeklyAvgSchoolUsePercentage: number = 0;\n public fixedWeeklyAvgOutOfSchoolPercentage: number = 0;\n\n\n // end of new \n\n public customWeekMode: boolean = false;\n public customStartDate: string = \"\";\n public customEndDate: string = \"\";\n\n public isParent: boolean = false;\n\n public hasError: boolean = false;\n public errorMessage: string = \"\";\n\n public fetchDataForCurrentUser: () => void = () => { };\n public fetchLightboxData: () => void = () => { };\n\n public showLightbox: boolean = false;\n public showDatePicker: boolean = false;\n\n public children: { id: string; name: string; userId: string }[] = [];\n public selectedChild = null;\n public selectedChildHistogram = \"\";\n\n public toggleDatePicker(show: boolean) {\n this.showDatePicker = show;\n }\n\n public setDateFromPicker(date: string) {\n this.selectedDailyDate = moment(date).format('YYYY-MM-DD');\n this.showDatePicker = false;\n this.fetchLightboxData();\n }\n\n public toggleLightbox(show: boolean) {\n this.showLightbox = show;\n if (show) {\n // Store the current summary values when lightbox opens\n this.fixedTodayOnCampus = this.todayOnCampus;\n this.fixedTodayOffCampus = this.todayOffCampus;\n this.fixedTodayTotal = this.todayTotal;\n this.fixedTodaySchoolUsePercentage = this.todaySchoolUsePercentage;\n this.fixedTodayOutOfSchoolPercentage = this.todayOutOfSchoolPercentage;\n this.fixedWeeklyAvgOnCampus = this.weeklyAvgOnCampus;\n this.fixedWeeklyAvgOffCampus = this.weeklyAvgOffCampus;\n this.fixedWeeklyTotalAverage = this.weeklyTotalAverage;\n this.fixedWeeklyAvgSchoolUsePercentage = this.weeklyAvgSchoolUsePercentage;\n this.fixedWeeklyAvgOutOfSchoolPercentage = this.weeklyAvgOutOfSchoolPercentage;\n\n // Initialize lightbox dates to current date/week\n this.selectedDailyDate = moment().format('YYYY-MM-DD');\n this.weekStart = moment().startOf('isoWeek');\n this.weekEnd = moment().endOf('isoWeek');\n this.selectedChildHistogram = this.selectedUser;\n this.fetchLightboxData();\n }\n }\n\n public changeDay(offset: number) {\n this.selectedDailyDate = moment(this.selectedDailyDate).add(offset, 'days').format('YYYY-MM-DD');\n this.fetchLightboxData();\n }\n\n public changeWeek(offset: number) {\n this.weekStart = this.weekStart.clone().add(offset, 'weeks');\n this.weekEnd = this.weekStart.clone().endOf('isoWeek');\n this.fetchLightboxData();\n }\n\n public get selectedDailyDateObj(): Date {\n return new Date(this.selectedDailyDate);\n }\n\n public get weekLabel(): string {\n const start = this.weekStart.format('dddd D MMMM');\n const end = this.weekEnd.format('dddd D MMMM');\n return `du ${start} au ${end}`;\n }\n}\n\nfunction fetchAllScreenTimeDataForUserAndDates($http: IHttpService, ctrl: Controller, userId: string, dailyDate: string, startDate: string, endDate: string): Promise<{ weekly: any, daily: any }> {\n ctrl.children = fetchChildren(ctrl);\n\n const weeklyEndpoint = `/appregistry/screen-time/${userId}/weekly?startDate=${startDate}&endDate=${endDate}&mock=false`;\n const dailyEndpoint = `/appregistry/screen-time/${userId}/daily?date=${dailyDate}&mock=false`;\n\n return Promise.all([\n $http.get(weeklyEndpoint),\n $http.get(dailyEndpoint)\n ]).then(([weeklyResponse, dailyResponse]: [any, any]) => {\n console.log(\"weekly: \", weeklyResponse.data);\n console.log(\"daily: \", dailyResponse.data);\n ctrl.hasError = false;\n ctrl.errorMessage = \"\";\n return {\n weekly: weeklyResponse.data.dailySummaries.reduce((acc: any, day: any) => {\n acc[day.date] = {\n duration: day.durationMinutes,\n schoolUsePercentage: day.schoolUsePercentage / 100 // convert to ratio\n };\n return acc;\n }, {}),\n daily: dailyResponse.data.durations.map((hour: any) => ({\n hour: hour.hour,\n duration: hour.durationMinutes,\n schoolUsePercentage: hour.schoolUsePercentage / 100 // convert to ratio\n }))\n };\n }).catch(error => {\n ctrl.hasError = true;\n\n if (error?.status === 404) {\n ctrl.errorMessage = \"Erreur lors de l’identification de l’utilisateur. Contactez l’administrateur de votre établissement.\";\n } else {\n ctrl.errorMessage = \"Un problème technique est survenu. Si le problème persiste contactez l’administrateur de votre établissement.\";\n }\n\n console.error(\"Error fetching data for current user and dates:\", error);\n return Promise.reject(error);\n });\n}\n\nfunction fetchChildren(ctrl: Controller) {\n const childrenObj = session().user.children;\n ctrl.isParent = false;\n\n const USE_MOCK_IDS = true;\n\n if (childrenObj && Object.keys(childrenObj).length > 0) {\n ctrl.isParent = true;\n\n // Replace userIds with mocked values: 100, 101, 102, ...\n let mockIdCounter = 100;\n\n return Object.entries(childrenObj).map(([userId, childData]) => {\n const child = childData as { firstName: string; lastName: string };\n const mockedId = (mockIdCounter++).toString(); // To remove and use real Id\n return {\n id: userId,\n name: `${child.firstName} ${child.lastName}`,\n userId: USE_MOCK_IDS ? mockedId : userId\n };\n });\n } else {\n return [];\n }\n}\n\nclass Directive implements IDirective<IScope, JQLite, IAttributes, IController[]> {\n restrict = \"E\";\n template = require(\"./screen-time-widget.widget.html\").default;\n scope = {};\n bindToController = true;\n controller = [Controller];\n controllerAs = \"ctrl\";\n require = [\"odeScreenTimeWidget\"];\n\n link(scope: IScope, elem: angular.IAugmentedJQuery, attrs: IAttributes, controllers?: IController[]) {\n const ctrl: Controller | null = controllers ? (controllers[0] as Controller) : null;\n if (!ctrl) return;\n\n const $http = angular.injector([\"ng\"]).get<IHttpService>(\"$http\");\n const currentUserId = session().user.userId;\n\n ctrl.fetchDataForCurrentUser();\n\n let chartInstance: Chart | null = null;\n\n // Function to update the summary values from the pre-fetched weekly data\n const updateSummary = (weeklyData: any) => {\n let totalOnCampus = 0;\n let totalOffCampus = 0;\n let daysCount = 0;\n const today = moment().format(\"YYYY-MM-DD\");\n let todayOnCampusTemp = 0;\n let todayOffCampusTemp = 0;\n\n let weeklyTotalSchoolUseDuration = 0;\n let weeklyTotalOutOfSchoolDuration = 0;\n let weeklyTotalOverallDuration = 0;\n\n Object.keys(weeklyData).forEach(dateStr => {\n const entry = weeklyData[dateStr];\n const duration = entry.duration || 0;\n const schoolUsePct = entry.schoolUsePercentage || 0;\n\n const onCampus = duration * schoolUsePct;\n const offCampus = duration * (1 - schoolUsePct);\n\n totalOnCampus += onCampus;\n totalOffCampus += offCampus;\n daysCount++;\n\n weeklyTotalSchoolUseDuration += onCampus;\n weeklyTotalOutOfSchoolDuration += offCampus;\n weeklyTotalOverallDuration += duration;\n\n if (moment(dateStr).format(\"YYYY-MM-DD\") === today) {\n todayOnCampusTemp = onCampus;\n todayOffCampusTemp = offCampus;\n ctrl.todaySchoolUsePercentage = entry.schoolUsePercentage * 100;\n ctrl.todayOutOfSchoolPercentage = 100 - (entry.schoolUsePercentage * 100);\n }\n });\n\n ctrl.todayOnCampus = todayOnCampusTemp;\n ctrl.todayOffCampus = todayOffCampusTemp;\n ctrl.todayTotal = todayOnCampusTemp + todayOffCampusTemp;\n ctrl.weeklyAvgOnCampus = daysCount > 0 ? totalOnCampus / daysCount : 0;\n ctrl.weeklyAvgOffCampus = daysCount > 0 ? totalOffCampus / daysCount : 0;\n ctrl.weeklyTotalAverage = ctrl.weeklyAvgOnCampus + ctrl.weeklyAvgOffCampus;\n\n if (weeklyTotalOverallDuration > 0) {\n ctrl.weeklyAvgSchoolUsePercentage = (weeklyTotalSchoolUseDuration / weeklyTotalOverallDuration) * 100;\n ctrl.weeklyAvgOutOfSchoolPercentage = (weeklyTotalOutOfSchoolDuration / weeklyTotalOverallDuration) * 100;\n } else {\n ctrl.weeklyAvgSchoolUsePercentage = 0;\n ctrl.weeklyAvgOutOfSchoolPercentage = 0;\n }\n };\n\n // Helper to generate a unique key for caching data based on user and date range\n const generateDataKey = (userId: string, dailyDate: string, startDate: string, endDate: string) => {\n console.log(\"3\");\n return `${userId}_daily_${dailyDate}_weekly_${startDate}_${endDate}`;\n };\n\n // New function assigned to ctrl.fetchDataForCurrentUser to be called from HTML\n ctrl.fetchDataForCurrentUser = () => {\n ctrl.errorMessage = \"\";\n ctrl.hasError = false;\n const currentKey = generateDataKey(\n ctrl.selectedUser,\n moment().format('YYYY-MM-DD'), // Always use today's date for initial load\n moment().startOf('isoWeek').format('YYYY-MM-DD'),\n moment().endOf('isoWeek').format('YYYY-MM-DD')\n );\n\n // Fetch initial summary data (today and current week)\n fetchAllScreenTimeDataForUserAndDates(\n $http,\n ctrl,\n ctrl.selectedUser,\n moment().format('YYYY-MM-DD'),\n moment().startOf('isoWeek').format('YYYY-MM-DD'),\n moment().endOf('isoWeek').format('YYYY-MM-DD')\n ).then((data) => {\n ctrl.userData[currentKey] = { weekly: data.weekly, daily: data.daily };\n updateSummary(data.weekly); // Update the main summary values\n scope.$applyAsync();\n }).catch(error => {\n scope.$applyAsync();\n console.error(\"Error fetching initial data for current user:\", error);\n });\n };\n\n ctrl.fetchLightboxData = () => {\n\n const userIdForLightbox = ctrl.selectedChildHistogram || ctrl.selectedUser;\n\n if (!userIdForLightbox) return;\n\n const currentKey = generateDataKey(\n userIdForLightbox,\n ctrl.selectedDailyDate,\n ctrl.weekStart.format('YYYY-MM-DD'),\n ctrl.weekEnd.format('YYYY-MM-DD')\n );\n\n // Check if data is already cached\n if (ctrl.userData[currentKey]) {\n if (ctrl.showLightbox) {\n setTimeout(() => ctrl.updateChart(), 50);\n }\n } else {\n fetchAllScreenTimeDataForUserAndDates(\n $http,\n ctrl,\n userIdForLightbox,\n ctrl.selectedDailyDate,\n ctrl.weekStart.format('YYYY-MM-DD'),\n ctrl.weekEnd.format('YYYY-MM-DD')\n ).then((data) => {\n ctrl.userData[currentKey] = { weekly: data.weekly, daily: data.daily };\n if (ctrl.showLightbox) {\n setTimeout(() => ctrl.updateChart(), 50);\n }\n scope.$applyAsync();\n }).catch(error => {\n console.error(\"Error fetching data for lightbox:\", error);\n });\n }\n };\n\n ctrl.updateChart = () => {\n const canvas = elem[0].querySelector<HTMLCanvasElement>(\"#myChart\");\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n if (chartInstance) chartInstance.destroy();\n\n let labels: string[] = [];\n let appTimes: number[] = [];\n let otherTimes: number[] = [];\n\n const userIdForChart = ctrl.selectedChildHistogram || ctrl.selectedUser;\n\n // Use the dates from the lightbox controls for the chart data key\n const currentDataKey = generateDataKey(\n userIdForChart,\n ctrl.selectedDailyDate,\n ctrl.weekStart.format('YYYY-MM-DD'),\n ctrl.weekEnd.format('YYYY-MM-DD')\n );\n const currentUserAndDateData = ctrl.userData[currentDataKey];\n\n if (!currentUserAndDateData) return;\n\n const dataToUse: any = ctrl.viewMode === \"weekly\" ? currentUserAndDateData.weekly : currentUserAndDateData.daily;\n if (!dataToUse) return;\n\n if (ctrl.viewMode === \"weekly\") {\n const sortedDates = Object.keys(dataToUse).sort();\n\n sortedDates.forEach(dateStr => {\n const entry = dataToUse[dateStr];\n labels.push(moment(dateStr).format(\"ddd D\"));\n appTimes.push(entry.duration * entry.schoolUsePercentage);\n otherTimes.push(entry.duration * (1 - entry.schoolUsePercentage));\n });\n } else {\n dataToUse.forEach((hourData: any) => {\n labels.push(`${hourData.hour}h`);\n appTimes.push(hourData.duration * hourData.schoolUsePercentage);\n otherTimes.push(hourData.duration * (1 - hourData.schoolUsePercentage));\n });\n }\n\n chartInstance = new Chart(ctx, {\n type: \"bar\",\n data: {\n labels,\n datasets: [\n {\n label: \"Usage scolaire\",\n data: appTimes,\n backgroundColor: \"#2A9CC8\"\n },\n {\n label: \"Usage hors scolaire\",\n data: otherTimes,\n backgroundColor: \"#ECBE30\"\n }\n ]\n },\n options: {\n plugins: {\n tooltip: {\n callbacks: {\n label: function (context) {\n const value = context.raw;\n return `${context.dataset.label}: ${value} minutes`;\n }\n }\n }\n },\n responsive: true,\n scales: {\n x: {\n stacked: true\n },\n y: {\n stacked: true,\n beginAtZero: true,\n title: {\n display: true,\n text: \"Minutes\"\n }\n }\n }\n }\n });\n };\n\n ctrl.children = fetchChildren(ctrl);\n\n // Determine the user whose data should be fetched on load\n if (ctrl.isParent && ctrl.children.length > 0) {\n // If a parent, and has children, default to the first child if no child is selected yet\n if (!ctrl.selectedUser) {\n ctrl.selectedUser = ctrl.children[0].userId;\n }\n ctrl.fetchDataForCurrentUser();\n } else if (!ctrl.isParent && currentUserId) {\n // If not a parent, and current user ID is available, fetch data for themselves\n ctrl.selectedUser = currentUserId; // Set selectedUser to the current logged-in user's ID\n ctrl.fetchDataForCurrentUser();\n } else {\n // No children AND no current user ID (or other error condition)\n ctrl.hasError = true;\n ctrl.errorMessage = \"Aucun utilisateur disponible pour afficher les données de temps d'écran.\";\n scope.$applyAsync(); // Ensure the error message is displayed\n }\n\n // Watch for changes in view mode (within lightbox): only updates the chart\n scope.$watch(() => ctrl.viewMode, (newVal, oldVal) => {\n if (newVal !== oldVal && ctrl.showLightbox) {\n setTimeout(() => ctrl.updateChart(), 50);\n }\n });\n // Watch for selectedUser changes within the lightbox to update chart data\n scope.$watch(() => ctrl.selectedChildHistogram, (newVal, oldVal) => { // Changed from ctrl.selectedUser\n if (newVal !== oldVal && ctrl.showLightbox) {\n ctrl.fetchLightboxData();\n }\n });\n\n // Watch for lightbox visibility changes\n scope.$watch(() => ctrl.showLightbox, (isVisible: boolean) => {\n if (isVisible) {\n setTimeout(() => {\n ctrl.updateChart();\n }, 100);\n } else {\n if (chartInstance) {\n chartInstance.destroy();\n chartInstance = null;\n }\n }\n });\n }\n}\n\n// Factory function for the directive\nfunction DirectiveFactory() {\n return new Directive();\n}\n\n// Define the module name\nexport const odeModuleName = \"odeCantineWidgetModule\";\n\n// Angular module definition\nangular\n .module(odeModuleName, [])\n // Define the custom 'duration' filter\n .filter('duration', function () {\n return function (input: number) {\n if (isNaN(input) || input === null || input < 0) {\n return '0m';\n }\n\n const totalMinutes = Math.floor(input);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n\n let result = '';\n\n if (hours > 0) {\n result += `${hours}h`;\n }\n if (minutes > 0 || (hours === 0 && totalMinutes === 0)) {\n result += `${minutes}m`;\n }\n\n return result.trim() || '0m';\n };\n })\n\n // Register the directive\n .directive(\"odeScreenTimeWidget\", DirectiveFactory);\n\n// Internationalization setup\nnotif()\n .onLangReady()\n .promise.then((lang) => {\n switch (lang) {\n default:\n conf().Platform.idiom.addKeys(require(\"./i18n/fr.json\"));\n break;\n }\n });\n"],"names":["Chart","register","registerables","locale","selectedUser","viewMode","userData","selectedDailyDate","format","weekStart","startOf","weekEnd","endOf","updateChart","todayOnCampus","todayOffCampus","todayTotal","todaySchoolUsePercentage","todayOutOfSchoolPercentage","weeklyAvgOnCampus","weeklyAvgOffCampus","weeklyTotalAverage","weeklyAvgSchoolUsePercentage","weeklyAvgOutOfSchoolPercentage","fixedTodayOnCampus","fixedTodayOffCampus","fixedTodayTotal","fixedTodaySchoolUsePercentage","fixedTodayOutOfSchoolPercentage","fixedWeeklyAvgOnCampus","fixedWeeklyAvgOffCampus","fixedWeeklyTotalAverage","fixedWeeklyAvgSchoolUsePercentage","fixedWeeklyAvgOutOfSchoolPercentage","customWeekMode","customStartDate","customEndDate","isParent","hasError","errorMessage","fetchDataForCurrentUser","fetchLightboxData","showLightbox","showDatePicker","children","selectedChild","selectedChildHistogram","toggleDatePicker","show","this","setDateFromPicker","date","toggleLightbox","changeDay","offset","add","changeWeek","clone","Date","start","end","fetchAllScreenTimeDataForUserAndDates","$http","ctrl","userId","dailyDate","startDate","endDate","fetchChildren","weeklyEndpoint","dailyEndpoint","Promise","all","get","then","weeklyResponse","dailyResponse","console","log","data","weekly","dailySummaries","reduce","acc","day","duration","durationMinutes","schoolUsePercentage","daily","durations","map","hour","catch","error","status","reject","childrenObj","session","user","Object","keys","length","entries","child","mockedId","toString","id","name","firstName","lastName","Controller","restrict","template","scope","bindToController","controller","controllerAs","require","link","elem","attrs","controllers","injector","currentUserId","chartInstance","generateDataKey","currentKey","weeklyData","totalOnCampus","totalOffCampus","daysCount","today","todayOnCampusTemp","todayOffCampusTemp","weeklyTotalSchoolUseDuration","weeklyTotalOutOfSchoolDuration","weeklyTotalOverallDuration","forEach","dateStr","entry","schoolUsePct","onCampus","offCampus","$applyAsync","userIdForLightbox","setTimeout","canvas","querySelector","ctx","getContext","destroy","labels","appTimes","otherTimes","userIdForChart","currentDataKey","currentUserAndDateData","dataToUse","sort","push","hourData","type","datasets","label","backgroundColor","options","plugins","tooltip","callbacks","context","value","raw","dataset","responsive","scales","x","stacked","y","beginAtZero","title","display","text","$watch","newVal","oldVal","isVisible","odeModuleName","module","filter","input","isNaN","totalMinutes","Math","floor","hours","minutes","result","trim","directive","Directive","notif","onLangReady","promise","lang","conf","Platform","idiom","addKeys"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ode-ngjs-front",
3
- "version": "1.4.12-develop-integration.202506191529",
3
+ "version": "1.4.12-develop-integration.202507011402",
4
4
  "description": "Open Digital Education Frontend Framework",
5
5
  "homepage": "https://github.com/opendigitaleducation/ode-ngjs-front#readme",
6
6
  "bugs": {