UNPKG

cmsmon

Version:
417 lines (374 loc) 18.1 kB
'use strict'; module.exports = (cms) => { const {mongoose, utils:{makeSelect, makeMultiSelect, makeTypeSelect, makeStyles, makeCustomSelect}} = cms; cms.registerWrapper('EmployeeForm', { formatter: ` <h4>Form</h4> `, mTemplate: ` <GridLayout columns="*" rows="auto,auto,auto,auto" [init]="fn.init()"> <TextField row="1" [(ngModel)]="model.name" hint="Name"></TextField> <TextField row="2" [(ngModel)]="model.maxHour" hint="maxHour"></TextField> <TextField row="3" [(ngModel)]="model.position" hint="Position"></TextField> </GridLayout> <Button text="Submit" (tap)="fn.submit()" horizontalAlignment="left" ></Button> `, fn: { init: function () { this.position = 'Waiter'; this.positions = ['Waiter', 'Manager', 'Chef']; }, submit: function () { cms.createModel('Employee', null, {name: this.name, maxHour: this.maxHour, position: this.position}); }, link: function () { try { this.router.navigate(['Cat']); } catch (e) { } } }, serverFn: {} }); /* <div ng-repeat="employee in model.employees" ng-init="shifts = employee.subMenge"> <h4>Name: {{employee.name}}</h4> <div ng-repeat="shift in shifts"> Date: {{shift.day}}.{{shift.month}},weekDay:{{shift.weekDay}}, beginHour: {{shift.beginHour}}, endHour: {{shift.endHour}} </div> </div> */ cms.registerWrapper('Info', { formatter: ` <div ng-init="fn.onInit()"> <div class="hidden-print"> <div class="form-group"> <label>Choose company:</label> <ui-select data-ng-model="model.company" on-select="model.chooseCompany($item)" theme="bootstrap"> <ui-select-match placeholder="Choose company">{{$select.selected.name}}</ui-select-match> <ui-select-choices data-repeat="item.name as item in model.companies | filterBy: ['name']: $select.search"> <div ng-bind-html="item.name | highlight: $select.search"></div> </ui-select-choices> </ui-select> </div> <div class="form-group"> <label>Choose Employees:</label> <ui-select multiple data-ng-model="model._employees" theme="bootstrap"> <ui-select-match placeholder="Choose Employees">{{$item.name}}</ui-select-match> <ui-select-choices data-repeat="item in model.employeeList | filterBy: ['name']: $select.search"> <div ng-bind-html="item.name | highlight: $select.search"></div> </ui-select-choices> </ui-select> </div> <div class="form-group"> <label>Choose month:</label> <input type="month" class="form-control" ng-model="model.month"> </div> <button class="btn btn-white btn-sm" ng-click="model.calculateRange(model.month)">Calculate</button> </div> <div ng-if="model._calculated"> <div ng-repeat="week in model.weeks" style="page-break-after:always;page-break-inside: avoid;"> <h4>Week {{$index}}</h4> <table border="1"> <tr> <th ng-repeat="_day in model.weekday2" style="padding-left: 20px;padding-right: 20px;vertical-align: top" ng-init="_index = $index"> <p>{{model.weekday[_day]}}</p> <div ng-repeat="day in week"> <div ng-if="day.day.getDay() === _day"> {{day.day.getDate()}}/{{day.day.getMonth() +1}} </div> </div> </th> </tr> <tr style="padding-top: 10px;padding-bottom: 10px;"> <td ng-repeat="_day in model.weekday2" style="padding-left: 20px;padding-right: 20px;vertical-align: top"> <div ng-repeat="day in week"> <div ng-if="day.day.getDay() === _day"> <div ng-repeat="shift in day.shifts" ng-init="employee = shift.employee"> <div ng-if="employee !== null"> <p style="margin-bottom: 0px;">{{shift.beginHour}} - {{shift.endHour}}</p> <p>{{employee.name}}</p> </div> </div> </div> </div> </td> </tr> </table> </div> </div> </div> `, mTemplate: ` <StackLayout [init]="fn.onInit()"> <Button text="Refresh" (tap)="fn.onInit()"></Button> <StackLayout *ngFor="#employee of model.employees"> <Label text="Name: {{employee.name}}"></Label> <StackLayout *ngFor="#shift of employee.subMenge"> <Label text="Date: {{shift.day}}.{{shift.month}},beginHour: {{shift.beginHour}}, endHour: {{shift.endHour}}"> </Label> </StackLayout> </StackLayout> </StackLayout> `, ID: String, fn: { getShifts: function () { return Types.Shift.list.map(shift => { shift.$workingTime = Types.Shift.fn.getWorkingTime.bind(shift)(); return shift; }); }, onInit: function () { const model = this; const weekday = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]; function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; // While there remain elements to shuffle... while (0 !== currentIndex) { // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; // And swap it with the current element. temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } function createNextMenge(menge) { return menge.map(shift => { return {workingTime: shift.workingTime, name: `S${parseInt(shift.name.substring(1)) + length}`}; }); } function sum(menge) { let s = 0; menge.forEach(item => s += item ? item.workingTime : 0); return s ? s : 0; } function getDaysInMonth(d1, m1, y1, d2, m2, y2) { var date1 = new Date(y1, m1 - 1, d1); var date2 = new Date(y2, m2 - 1, d2); var days = []; while (date1 <= date2) { days.push(new Date(date1)); date1.setDate(date1.getDate() + 1); } return days; } function genShifts(d1, m1, y1, d2, m2, y2) { const days = getDaysInMonth(d1, m1, y1, d2, m2, y2); let shifts = Types.Shift.list.filter(shift => shift.company.name === model.company).map(shift => { return { beginHour: shift.beginHour, endHour: shift.endHour < shift.beginHour ? shift.endHour + 24 : shift.endHour, workingTime: Types.Shift.fn.getWorkingTime.bind(shift)(), weekDay: shift.weekDay, _id: shift._id }; }); const result = []; const _days = days.map(day => { const shiftsInDay = JsonFn.clone(_.filter(shifts, shift => shift.weekDay === weekday[day.getDay()])); shiftsInDay.forEach(s => { s.day = day.getDate(), s.month = day.getMonth() }); Array.prototype.push.apply(result, shiftsInDay); return {day, shifts: shiftsInDay} }) return {shifts: result, days: _days}; } function isConflict(shift1, shift2) { if (shift1.day === shift2.day) { if (shift1.endHour > shift2.beginHour) return true; } return false; } function softByBeginHour(shifts) { return shifts.sort((shift1, shift2) => { if (shift1.month < shift2.month) return -1; if (shift1.month > shift2.month) return 1; if (shift1.day < shift2.day) return -1; if (shift1.day > shift2.day) return 1; return shift1.beginHour - shift2.beginHour; }); } function isConflictWithList(shifts, shift) { let conflict = false; shifts.forEach(s => { if (s.beginHour <= shift.beginHour && isConflict(s, shift)) conflict = true if (s.beginHour >= shift.beginHour && isConflict(shift, s)) conflict = true }); return conflict; } function assignShiftToPersons(shifts, employees, days) { shifts = shuffle(shifts); for (let employee of employees) { let subMenge = []; const conflictArray = []; while (shifts.length > 0 && sum(subMenge) + shifts[0].workingTime < employee.maxHour && conflictArray.length < shifts.length) { subMenge = softByBeginHour(subMenge); const shift = shifts.shift(); if (isConflictWithList(subMenge, shift)) { shifts.push(shift); conflictArray.push(shift); } else { subMenge.push(shift); } } employee.sum = sum(subMenge); employee.subMenge = softByBeginHour(subMenge); } function smartPush() { const _shift = shifts.shift(); if (!_shift) return false; const last = employees[employees.length - 1]; for (let employee of employees.filter((e, i) => i !== employees.length - 1)) { const subMenge = employee.subMenge; const maxHour = employee.maxHour; for (let shift of subMenge) { if (shift.workingTime + (maxHour - sum(subMenge)) >= _shift.workingTime) { if (!isConflictWithList(last.subMenge, shift) && sum(last.subMenge.concat(shift)) < last.maxHour) { // swap _.remove(subMenge, shift); last.subMenge.push(shift); subMenge.push(_shift); return shifts.length === 0 ? false : true; } } } } return shifts.length === 0 ? false : true; } while (smartPush()) { } for (let employee of employees) { for (let shift of employee.subMenge) { // assign to days const day = _.find(days, day => { return _.contains(day.shifts, shift); }); for (let _shift of day.shifts) { if (_shift === shift) { _shift.employee = employee; } } } } } try { cms.loadElements('Company', () => { this.companies = Types.Company.list; }) cms.loadElements('Shift'); cms.loadElements('Employee', () => { this.employeeList = Types.Employee.list; }); this.chooseCompany = $item => { this._employees = this.employeeList = _.filter(Types.Employee.list, employee => _.find(employee.company, {name: $item.name})); } this.calculate = function (d1, m1, y1, d2, m2, y2) { const employees = JsonFn.clone(model._employees).sort((e1, e2) => e1.maxHour - e2.maxHour); const {shifts, days} = genShifts(d1, m1, y1, d2, m2, y2); assignShiftToPersons(shifts, employees, days); model.employees = employees; model.days = days; const weeks = []; let week = []; days.forEach(day => { week.push(day); if (day.day.getDay() === 0) { weeks.push(week); week = []; } }) if (week.length > 0) weeks.push(week); model.weeks = weeks; } this.calculateRange = function (date1) { this._calculated = true; const date2 = new Date(date1); date2.setMonth(date2.getMonth() + 1); date2.setDate(date2.getDate() - 1); this.calculate(date1.getDate(), date1.getMonth() + 1, date1.getFullYear(), date2.getDate(), date2.getMonth() + 1, date2.getFullYear()) } this.weekday = weekday; this.weekday2 = [1, 2, 3, 4, 5, 6, 0]; } catch (e) { // console.warn(e); } } } }); const Company = cms.registerSchema({ name: {type: String, default: 'Name'} }, { name: 'Company', formatter: ` <h4>{{model.name}}</h4> `, title: 'name', isViewElement: false, mTemplate: ` <StackLayout> <Label text="{{model.name}}"></Label> </StackLayout> `, alwaysLoad: true }); const Employee = cms.registerSchema({ name: {type: String, default: 'Employee', index: true}, position: {type: String, form: makeSelect('waiter', 'chef', 'manager')}, maxHour: Number, company: [{type: mongoose.Schema.Types.ObjectId, ref: 'Company', autopopulate: true}] }, { name: 'Employee', formatter: ` <h4>{{model.name}} - {{model.position}} - {{model.maxHour}}</h4> `, title: 'name', isViewElement: false, mTemplate: ` <StackLayout> <Label text="{{model.name}} - {{model.position}} - {{model.maxHour}}"></Label> </StackLayout> `, fn: { order: function () { } }, autopopulate: true, info: { adminTemplate: ` <h4>{{model.name}} - {{model.position}} - {{model.maxHour}}</h4> ` } }); const Shift = cms.registerSchema({ weekDay: { type: String, form: makeSelect('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday') }, beginHour: Number, endHour: Number, company: {type: mongoose.Schema.Types.ObjectId, ref: 'Company', autopopulate: true} }, { name: 'Shift', formatter: ` <h4>{{model.weekDay}} - {{model.beginHour}}-{{model.endHour}}</h4> `, title: 'name', isViewElement: false, mTemplate: ` <StackLayout> <Label [text]="model.name+' - '+model.weekDay+' - '+ model.beginHour+' - '+model.endHour"></Label> </StackLayout> `, fn: { getWorkingTime: function () { return this.endHour < this.beginHour ? 24 + this.endHour - this.beginHour : this.endHour - this.beginHour; } }, autopopulate: true }); }