Component shows now the year week numbers #738

Merged
carlosjr merged 4 commits from 2389-calendar_weeks into dev 2021-09-20 08:50:12 +00:00
9 changed files with 193 additions and 41 deletions

View File

@ -19,28 +19,42 @@
ng-if="$ctrl.displayControls"> ng-if="$ctrl.displayControls">
</vn-button> </vn-button>
</div> </div>
<div class="weekdays"> <div id="days-header" ng-class="{'hide-weeks': $ctrl.hideWeeks}">
<section <div class="week-numbers" ng-if="!$ctrl.hideWeeks"></div>
ng-repeat="day in ::$ctrl.weekDays" <div class="weekdays">
translate-attr="::{title: day.name}" <section
ng-click="$ctrl.selectWeekDay($event, day.index)"> ng-repeat="day in ::$ctrl.weekDays"
<span>{{::day.localeChar}}</span> translate-attr="::{title: day.name}"
</section> ng-click="$ctrl.selectWeekDay($event, day.index)">
<span>{{::day.localeChar}}</span>
</section>
</div>
</div> </div>
<div
class="days" <div id="days-container" ng-class="{'hide-weeks': $ctrl.hideWeeks}">
ng-class="{'hide-contiguous': $ctrl.hideContiguous}"> <div class="weeks" ng-if="!$ctrl.hideWeeks">
<section <section ng-repeat="week in $ctrl.weekNumbers"
ng-repeat="day in $ctrl.days" class="day">
class="day" <div class="day-number">
ng-class="::$ctrl.getDayClasses(day)" {{::week}}
vn-repeat-last </div>
on-last="$ctrl.repeatLast()"> </section>
<div </div>
class="day-number" <div
ng-click="$ctrl.select($event, day)"> class="days"
{{::day | date: 'd'}} ng-class="{'hide-contiguous': $ctrl.hideContiguous}">
</div> <section
</section> ng-repeat="day in $ctrl.days"
class="day"
ng-class="::$ctrl.getDayClasses(day)"
vn-repeat-last
on-last="$ctrl.repeatLast()">
<div
class="day-number"
ng-click="$ctrl.select($event, day)">
{{::day | date: 'd'}}
</div>
</section>
</div>
</div> </div>
</div> </div>

View File

@ -12,11 +12,12 @@ import './style.scss';
* @event move Emitted when month changes * @event move Emitted when month changes
*/ */
export default class Calendar extends FormInput { export default class Calendar extends FormInput {
constructor($element, $scope, vnWeekDays) { constructor($element, $scope, vnWeekDays, moment) {
super($element, $scope); super($element, $scope);
this.weekDays = vnWeekDays.locales; this.weekDays = vnWeekDays.locales;
this.defaultDate = new Date(); this.defaultDate = new Date();
this.displayControls = true; this.displayControls = true;
this.moment = moment;
} }
/** /**
@ -54,15 +55,23 @@ export default class Calendar extends FormInput {
); );
} }
lastDay() {
return new Date(
this.defaultDate.getFullYear(),
this.defaultDate.getMonth() + 1,
0
).getDate();
}
/** /**
* Repaints the calendar. * Repaints the calendar.
*/ */
repaint() { repaint() {
const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1; const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1;
let weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6; this.weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
let dayIndex = new Date(this.defaultDate.getTime()); let dayIndex = new Date(this.defaultDate.getTime());
dayIndex.setDate(1 - weekdayOffset); dayIndex.setDate(1 - this.weekdayOffset);
this.days = []; this.days = [];
@ -70,27 +79,55 @@ export default class Calendar extends FormInput {
this.days.push(new Date(dayIndex.getTime())); this.days.push(new Date(dayIndex.getTime()));
dayIndex.setDate(dayIndex.getDate() + 1); dayIndex.setDate(dayIndex.getDate() + 1);
} }
this.getWeekdays();
}
getWeekdays() {
if (!this.moment) return;
const totalSlots = this.lastDay() + this.weekdayOffset;
const weeks = Math.ceil(totalSlots / 7);
const dated = this.moment(this.defaultDate);
const firstWeekNumber = dated.set('date', 1).isoWeek();
const weekNumbers = [];
for (let w = 0; w < weeks; w++) {
let weekNumber = firstWeekNumber;
if (dated.get('month') == 0 && firstWeekNumber > 1 && w > 0)
weekNumber = 0;
weekNumbers.push(weekNumber + w);
}
this.weekNumbers = weekNumbers;
} }
/** /**
* Gets CSS classes to apply to the specified day. * Gets CSS classes to apply to the specified day.
* *
* @param {Date} day The day * @param {Date} date The date
* @return {Object} The CSS classes to apply * @return {Object} The CSS classes to apply
*/ */
getDayClasses(day) { getDayClasses(date) {
let wday = day.getDay(); let day = date.getDate();
let month = day.getMonth(); let wday = date.getDay();
let month = date.getMonth();
const currentDay = new Date().getDate();
const currentMonth = new Date().getMonth();
let classes = { let classes = {
today: day === currentDay && month === currentMonth,
weekend: wday === 6 || wday === 0, weekend: wday === 6 || wday === 0,
previous: month < this.month, previous: month < this.month,
current: month == this.month, current: month == this.month,
next: month > this.month, next: month > this.month,
event: this.hasEvents({$day: day}) event: this.hasEvents({$day: date})
}; };
let userClass = this.getClass({$day: day}); let userClass = this.getClass({$day: date});
if (userClass) classes[userClass] = true; if (userClass) classes[userClass] = true;
return classes; return classes;
@ -181,7 +218,7 @@ export default class Calendar extends FormInput {
} }
} }
} }
Calendar.$inject = ['$element', '$scope', 'vnWeekDays']; Calendar.$inject = ['$element', '$scope', 'vnWeekDays', 'moment'];
ngModule.vnComponent('vnCalendar', { ngModule.vnComponent('vnCalendar', {
template: require('./index.html'), template: require('./index.html'),
@ -193,6 +230,7 @@ ngModule.vnComponent('vnCalendar', {
formatDay: '&?', formatDay: '&?',
displayControls: '<?', displayControls: '<?',
hideYear: '<?', hideYear: '<?',
hideContiguous: '<?' hideContiguous: '<?',
hideWeeks: '<?'
} }
}); });

View File

@ -19,7 +19,14 @@
color: inherit; color: inherit;
} }
} }
& > .weekdays { & #days-header {
flex-direction: row;
display: flex
}
& #days-header > .week-numbers {
width: 10%
}
& #days-header > .weekdays {
display: flex; display: flex;
color: $color-font-secondary; color: $color-font-secondary;
margin-bottom: 8px; margin-bottom: 8px;
@ -27,17 +34,49 @@
font-weight: bold; font-weight: bold;
font-size: .8rem; font-size: .8rem;
text-align: center; text-align: center;
width: 90%;
& > section { & > section {
width: 14.28%; width: 14.28%;
cursor: pointer; cursor: pointer;
} }
} }
& > .days { & #days-header.hide-weeks {
& > .weekdays {
width: 100%
}
}
& > #days-container {
flex-direction: row;
display: flex
}
& > #days-container > .weeks {
display: flex; display: flex;
flex-direction: column;
color: $color-font-secondary;
font-weight: bold;
font-size: .8rem;
width: 10%;
& > .day {
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
}
& #days-container.hide-weeks {
& > .days {
width: 100%
}
}
#days-container > .days {
display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
width: 90%;
& > .day { & > .day {
width: 14.28%; width: 14.28%;
@ -46,6 +85,17 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
&.today {
color: $color-font-bg;
& > .day-number {
border: 2px solid $color-font-link;
&:hover {
background-color: lighten($color-font-link, 20%);
opacity: .8
}
}
}
&.weekend { &.weekend {
color: $color-font-secondary; color: $color-font-secondary;
} }

View File

@ -9,13 +9,15 @@ import 'angular-translate-loader-partial';
import '@uirouter/angularjs'; import '@uirouter/angularjs';
import 'mg-crud'; import 'mg-crud';
import 'oclazyload'; import 'oclazyload';
import 'angular-moment';
export const ngDeps = [ export const ngDeps = [
'ngAnimate', 'ngAnimate',
'pascalprecht.translate', 'pascalprecht.translate',
'ui.router', 'ui.router',
'mgCrud', 'mgCrud',
'oc.lazyLoad' 'oc.lazyLoad',
'angularMoment'
]; ];
import * as validator from 'validator'; import * as validator from 'validator';

View File

@ -12,6 +12,7 @@
"@uirouter/angularjs": "^1.0.20", "@uirouter/angularjs": "^1.0.20",
"angular": "^1.7.5", "angular": "^1.7.5",
"angular-animate": "^1.7.8", "angular-animate": "^1.7.8",
"angular-moment": "^1.3.0",
"angular-translate": "^2.18.1", "angular-translate": "^2.18.1",
"angular-translate-loader-partial": "^2.18.1", "angular-translate-loader-partial": "^2.18.1",
"croppie": "^2.6.5", "croppie": "^2.6.5",
@ -51,6 +52,17 @@
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz", "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA==" "integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
}, },
"node_modules/angular-moment": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
"dependencies": {
"moment": ">=2.8.0 <3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/angular-translate": { "node_modules/angular-translate": {
"version": "2.18.4", "version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz", "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz",
@ -115,6 +127,14 @@
"angular": "^1.6.1" "angular": "^1.6.1"
} }
}, },
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/oclazyload": { "node_modules/oclazyload": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz", "resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
@ -182,6 +202,14 @@
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz", "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA==" "integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
}, },
"angular-moment": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
"requires": {
"moment": ">=2.8.0 <3.0.0"
}
},
"angular-translate": { "angular-translate": {
"version": "2.18.4", "version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz", "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz",
@ -233,6 +261,11 @@
"angular": "^1.6.1" "angular": "^1.6.1"
} }
}, },
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"oclazyload": { "oclazyload": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz", "resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",

View File

@ -12,6 +12,7 @@
"@uirouter/angularjs": "^1.0.20", "@uirouter/angularjs": "^1.0.20",
"angular": "^1.7.5", "angular": "^1.7.5",
"angular-animate": "^1.7.8", "angular-animate": "^1.7.8",
"angular-moment": "^1.3.0",
"angular-translate": "^2.18.1", "angular-translate": "^2.18.1",
"angular-translate-loader-partial": "^2.18.1", "angular-translate-loader-partial": "^2.18.1",
"croppie": "^2.6.5", "croppie": "^2.6.5",

View File

@ -78,6 +78,11 @@
</vn-avatar> </vn-avatar>
<span translate>Festive</span> <span translate>Festive</span>
</vn-chip> </vn-chip>
<vn-chip>
<vn-avatar class="today">
</vn-avatar>
<span translate>Current day</span>
</vn-chip>
</div> </div>
</div> </div>
</vn-side-menu> </vn-side-menu>

View File

@ -8,3 +8,4 @@ days: días
Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha
To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia
You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual
Current day: Día actual

View File

@ -42,11 +42,19 @@ vn-worker-calendar {
border-bottom: 1px solid rgba(0, 0, 0, 0.3); border-bottom: 1px solid rgba(0, 0, 0, 0.3);
} }
.festive { vn-avatar.festive,
background-color:white; vn-avatar.today {
border: 2px solid $color-alert; background-color: $color-font-dark;
width: 24px; width: 24px;
min-width: 24px; min-width: 24px;
height: 24px height: 24px
} }
vn-avatar.festive {
border: 2px solid $color-alert
}
vn-avatar.today {
border: 2px solid $color-font-link
}
} }