Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 1773-1774-travel_summary
gitea/salix/1773-1774-travel_summary This commit looks good
Details
gitea/salix/1773-1774-travel_summary This commit looks good
Details
This commit is contained in:
commit
afd7c5684a
|
@ -471,7 +471,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
|
||||||
(11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
|
(11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
|
||||||
(12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
|
(12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
|
||||||
(13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, CURDATE()),
|
(13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, CURDATE()),
|
||||||
(14, 1, 2, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
|
(14, 1, 2, 1, NULL, CURDATE(), CURDATE(), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
|
||||||
(15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()),
|
(15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()),
|
||||||
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||||
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||||
|
|
|
@ -61,7 +61,7 @@ export default {
|
||||||
fiscalDataButton: 'vn-left-menu a[ui-sref="client.card.fiscalData"]',
|
fiscalDataButton: 'vn-left-menu a[ui-sref="client.card.fiscalData"]',
|
||||||
socialNameInput: `vn-textfield input[name="socialName"]`,
|
socialNameInput: `vn-textfield input[name="socialName"]`,
|
||||||
fiscalIdInput: `vn-textfield input[name="fi"]`,
|
fiscalIdInput: `vn-textfield input[name="fi"]`,
|
||||||
equalizationTaxCheckbox: 'vn-check[label="Is equalizated"]',
|
equalizationTaxCheckbox: 'vn-check[ng-model="$ctrl.client.isEqualizated"]',
|
||||||
acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]',
|
acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]',
|
||||||
addressInput: `vn-textfield input[name="street"]`,
|
addressInput: `vn-textfield input[name="street"]`,
|
||||||
postcodeInput: `vn-textfield input[name="postcode"]`,
|
postcodeInput: `vn-textfield input[name="postcode"]`,
|
||||||
|
@ -136,7 +136,7 @@ export default {
|
||||||
addCreditFloatButton: `vn-float-button`,
|
addCreditFloatButton: `vn-float-button`,
|
||||||
creditInput: `vn-input-number input[name="credit"]`,
|
creditInput: `vn-input-number input[name="credit"]`,
|
||||||
saveButton: `button[type=submit]`,
|
saveButton: `button[type=submit]`,
|
||||||
firstCreditText: 'vn-client-credit-index vn-card > div vn-table vn-tbody > vn-tr'
|
firstCreditText: 'vn-client-credit-index vn-card vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
clientGreuge: {
|
clientGreuge: {
|
||||||
addGreugeFloatButton: `vn-float-button`,
|
addGreugeFloatButton: `vn-float-button`,
|
||||||
|
@ -144,13 +144,13 @@ export default {
|
||||||
descriptionInput: `vn-textfield input[name="description"]`,
|
descriptionInput: `vn-textfield input[name="description"]`,
|
||||||
typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.greuge.greugeTypeFk"]',
|
typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.greuge.greugeTypeFk"]',
|
||||||
saveButton: `button[type=submit]`,
|
saveButton: `button[type=submit]`,
|
||||||
firstGreugeText: 'vn-client-greuge-index vn-card > div vn-table vn-tbody > vn-tr'
|
firstGreugeText: 'vn-client-greuge-index vn-card vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
clientMandate: {
|
clientMandate: {
|
||||||
firstMandateText: 'vn-client-mandate vn-card > div vn-table vn-tbody > vn-tr'
|
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
clientInvoices: {
|
clientInvoices: {
|
||||||
firstInvoiceText: 'vn-client-invoice vn-card > div vn-table vn-tbody > vn-tr'
|
firstInvoiceText: 'vn-client-invoice vn-card vn-table vn-tbody > vn-tr'
|
||||||
},
|
},
|
||||||
clientLog: {
|
clientLog: {
|
||||||
logButton: 'vn-left-menu a[ui-sref="client.card.log"]',
|
logButton: 'vn-left-menu a[ui-sref="client.card.log"]',
|
||||||
|
@ -307,7 +307,7 @@ export default {
|
||||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) > vn-td > vn-one:nth-child(3) > div span:nth-child(3)',
|
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) > vn-td > vn-one:nth-child(3) > div span:nth-child(3)',
|
||||||
},
|
},
|
||||||
ticketSummary: {
|
ticketSummary: {
|
||||||
header: 'vn-ticket-summary > vn-card > div > h5',
|
header: 'vn-ticket-summary > vn-card > h5',
|
||||||
state: 'vn-ticket-summary vn-label-value[label="State"] > section > span',
|
state: 'vn-ticket-summary vn-label-value[label="State"] > section > span',
|
||||||
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > a',
|
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > a',
|
||||||
total: 'vn-ticket-summary vn-one.taxes > p:nth-child(3) > strong',
|
total: 'vn-ticket-summary vn-one.taxes > p:nth-child(3) > strong',
|
||||||
|
@ -319,14 +319,14 @@ export default {
|
||||||
popoverDiaryButton: '.vn-popover.shown vn-item-descriptor vn-icon[icon="icon-transaction"]',
|
popoverDiaryButton: '.vn-popover.shown vn-item-descriptor vn-icon[icon="icon-transaction"]',
|
||||||
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3)',
|
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3)',
|
||||||
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6)',
|
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6)',
|
||||||
invoiceOutRef: 'vn-ticket-summary > vn-card > div > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(6) > section > span',
|
invoiceOutRef: 'vn-ticket-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(6) > section > span',
|
||||||
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button'
|
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button'
|
||||||
},
|
},
|
||||||
ticketsIndex: {
|
ticketsIndex: {
|
||||||
openAdvancedSearchButton: 'vn-ticket-index vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-ticket-index vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"] input',
|
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"] input',
|
||||||
newTicketButton: 'vn-ticket-index > a',
|
newTicketButton: 'vn-ticket-index > a',
|
||||||
searchResult: 'vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
||||||
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
|
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
|
||||||
searchTicketInput: `vn-ticket-index vn-textfield input`,
|
searchTicketInput: `vn-ticket-index vn-textfield input`,
|
||||||
|
@ -403,7 +403,7 @@ export default {
|
||||||
saleDescriptorPopoverSummaryButton: '.vn-popover.shown vn-item-descriptor a[ui-sref="item.card.summary({id: $ctrl.item.id})"]',
|
saleDescriptorPopoverSummaryButton: '.vn-popover.shown vn-item-descriptor a[ui-sref="item.card.summary({id: $ctrl.item.id})"]',
|
||||||
descriptorItemDiaryButton: 'vn-item-descriptor .quicklinks.ng-scope > vn-horizontal > a > vn-icon > i',
|
descriptorItemDiaryButton: 'vn-item-descriptor .quicklinks.ng-scope > vn-horizontal > a > vn-icon > i',
|
||||||
newItemFromCatalogButton: 'vn-ticket-sale vn-float-button[icon="add"]',
|
newItemFromCatalogButton: 'vn-ticket-sale vn-float-button[icon="add"]',
|
||||||
newItemButton: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-icon-button > button > vn-icon > i',
|
newItemButton: 'vn-ticket-sale > vn-vertical > vn-card > vn-vertical > vn-one > vn-icon-button > button > vn-icon > i',
|
||||||
moreMenu: 'vn-ticket-sale vn-tool-bar > vn-button-menu[vn-id="more-button"] > div > button',
|
moreMenu: 'vn-ticket-sale vn-tool-bar > vn-button-menu[vn-id="more-button"] > div > button',
|
||||||
moreMenuCreateClaim: '.vn-popover.shown .vn-drop-down li[name="Add claim"]',
|
moreMenuCreateClaim: '.vn-popover.shown .vn-drop-down li[name="Add claim"]',
|
||||||
moreMenuReserve: '.vn-popover.shown .vn-drop-down li[name="Mark as reserved"]',
|
moreMenuReserve: '.vn-popover.shown .vn-drop-down li[name="Mark as reserved"]',
|
||||||
|
@ -443,7 +443,7 @@ export default {
|
||||||
secondSaleQuantity: 'vn-ticket-sale vn-table vn-tr:nth-child(2) vn-input-number input',
|
secondSaleQuantity: 'vn-ticket-sale vn-table vn-tr:nth-child(2) vn-input-number input',
|
||||||
secondSaleConceptCell: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)',
|
secondSaleConceptCell: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)',
|
||||||
secondSaleConceptInput: 'vn-ticket-sale vn-table vn-tr:nth-child(2) > vn-td-editable.ng-isolate-scope.selected vn-textfield input',
|
secondSaleConceptInput: 'vn-ticket-sale vn-table vn-tr:nth-child(2) > vn-td-editable.ng-isolate-scope.selected vn-textfield input',
|
||||||
totalImport: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > vn-one > p:nth-child(3) > strong',
|
totalImport: 'vn-ticket-sale > vn-vertical > vn-card > vn-vertical > vn-horizontal > vn-one > p:nth-child(3) > strong',
|
||||||
selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check',
|
selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check',
|
||||||
secondSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(2) vn-check[ng-model="sale.checked"]',
|
secondSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(2) vn-check[ng-model="sale.checked"]',
|
||||||
thirdSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(3) vn-check[ng-model="sale.checked"]',
|
thirdSaleCheckbox: 'vn-ticket-sale vn-tr:nth-child(3) vn-check[ng-model="sale.checked"]',
|
||||||
|
@ -472,7 +472,7 @@ export default {
|
||||||
zoneAutocomplete: 'vn-autocomplete[ng-model="$ctrl.zoneId"]',
|
zoneAutocomplete: 'vn-autocomplete[ng-model="$ctrl.zoneId"]',
|
||||||
nextStepButton: 'vn-step-control .buttons > section:last-child vn-button',
|
nextStepButton: 'vn-step-control .buttons > section:last-child vn-button',
|
||||||
finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]',
|
finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]',
|
||||||
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > form > vn-card > div > vn-horizontal > table > tfoot > tr > td:nth-child(4)',
|
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > form > vn-card > vn-horizontal > table > tfoot > tr > td:nth-child(4)',
|
||||||
chargesReasonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.option"]',
|
chargesReasonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.option"]',
|
||||||
},
|
},
|
||||||
ticketComponents: {
|
ticketComponents: {
|
||||||
|
@ -481,8 +481,8 @@ export default {
|
||||||
ticketRequests: {
|
ticketRequests: {
|
||||||
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
|
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
|
||||||
request: 'vn-ticket-request-index vn-table vn-tr',
|
request: 'vn-ticket-request-index vn-table vn-tr',
|
||||||
descriptionInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(1) > vn-textfield input',
|
descriptionInput: 'vn-ticket-request-create > form > div > vn-card > vn-horizontal:nth-child(1) > vn-textfield input',
|
||||||
atenderAutocomplete: 'vn-ticket-request-create vn-autocomplete[ng-model="$ctrl.ticketRequest.atenderFk"]',
|
atenderAutocomplete: 'vn-ticket-request-create vn-autocomplete[ng-model="$ctrl.ticketRequest.attenderFk"]',
|
||||||
quantityInput: 'vn-ticket-request-create vn-input-number input[name=quantity]',
|
quantityInput: 'vn-ticket-request-create vn-input-number input[name=quantity]',
|
||||||
priceInput: 'vn-ticket-request-create vn-input-number input[name=price]',
|
priceInput: 'vn-ticket-request-create vn-input-number input[name=price]',
|
||||||
firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)',
|
firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)',
|
||||||
|
@ -505,7 +505,7 @@ export default {
|
||||||
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
||||||
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
||||||
newDescriptionInput: 'vn-ticket-service > vn-dialog vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
|
newDescriptionInput: 'vn-ticket-service > vn-dialog vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
|
||||||
serviceLine: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(2) > vn-horizontal',
|
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
|
||||||
saveServiceButton: `button[type=submit]`,
|
saveServiceButton: `button[type=submit]`,
|
||||||
saveDescriptionButton: 'vn-ticket-service > vn-dialog[vn-id="createServiceTypeDialog"] > div > form > div.buttons > tpl-buttons > button'
|
saveDescriptionButton: 'vn-ticket-service > vn-dialog[vn-id="createServiceTypeDialog"] > div > form > div.buttons > tpl-buttons > button'
|
||||||
},
|
},
|
||||||
|
@ -517,7 +517,7 @@ export default {
|
||||||
},
|
},
|
||||||
claimsIndex: {
|
claimsIndex: {
|
||||||
searchClaimInput: `vn-claim-index vn-textfield input`,
|
searchClaimInput: `vn-claim-index vn-textfield input`,
|
||||||
searchResult: 'vn-claim-index vn-card > div > vn-table > div > vn-tbody > a',
|
searchResult: 'vn-claim-index vn-card > vn-table > div > vn-tbody > a',
|
||||||
searchButton: 'vn-claim-index vn-searchbar vn-icon[icon="search"]'
|
searchButton: 'vn-claim-index vn-searchbar vn-icon[icon="search"]'
|
||||||
},
|
},
|
||||||
claimDescriptor: {
|
claimDescriptor: {
|
||||||
|
@ -526,7 +526,7 @@ export default {
|
||||||
acceptDeleteClaim: 'vn-claim-descriptor > vn-confirm[vn-id="confirm-delete-claim"] button[response="ACCEPT"]'
|
acceptDeleteClaim: 'vn-claim-descriptor > vn-confirm[vn-id="confirm-delete-claim"] button[response="ACCEPT"]'
|
||||||
},
|
},
|
||||||
claimSummary: {
|
claimSummary: {
|
||||||
header: 'vn-claim-summary > vn-card > div > h5',
|
header: 'vn-claim-summary > vn-card > h5',
|
||||||
state: 'vn-claim-summary vn-label-value[label="State"] > section > span',
|
state: 'vn-claim-summary vn-label-value[label="State"] > section > span',
|
||||||
observation: 'vn-claim-summary vn-textarea[ng-model="$ctrl.summary.claim.observation"] textarea',
|
observation: 'vn-claim-summary vn-textarea[ng-model="$ctrl.summary.claim.observation"] textarea',
|
||||||
firstSaleItemId: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(4) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(1) > span',
|
firstSaleItemId: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(4) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(1) > span',
|
||||||
|
@ -534,8 +534,8 @@ export default {
|
||||||
itemDescriptorPopover: '.vn-popover.shown vn-item-descriptor',
|
itemDescriptorPopover: '.vn-popover.shown vn-item-descriptor',
|
||||||
itemDescriptorPopoverItemDiaryButton: '.vn-popover.shown vn-item-descriptor a[href="#!/item/2/diary"]',
|
itemDescriptorPopoverItemDiaryButton: '.vn-popover.shown vn-item-descriptor a[href="#!/item/2/diary"]',
|
||||||
firstDevelopmentWorker: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(5) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > span',
|
firstDevelopmentWorker: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(5) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > span',
|
||||||
firstDevelopmentWorkerGoToClientButton: '.vn-popover.shown vn-worker-descriptor div.quicklinks > a[href="#!/client/21/summary"]',
|
firstDevelopmentWorkerGoToClientButton: '.vn-popover.shown vn-worker-descriptor vn-quick-links > a[href="#!/client/21/summary"]',
|
||||||
firstActionTicketId: 'vn-claim-summary > vn-card > div > vn-horizontal > vn-auto:nth-child(6) vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',
|
firstActionTicketId: 'vn-claim-summary > vn-card > vn-horizontal > vn-auto:nth-child(6) vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',
|
||||||
firstActionTicketDescriptor: '.vn-popover.shown vn-ticket-descriptor'
|
firstActionTicketDescriptor: '.vn-popover.shown vn-ticket-descriptor'
|
||||||
},
|
},
|
||||||
claimBasicData: {
|
claimBasicData: {
|
||||||
|
@ -545,19 +545,19 @@ export default {
|
||||||
saveButton: `button[type=submit]`
|
saveButton: `button[type=submit]`
|
||||||
},
|
},
|
||||||
claimDetail: {
|
claimDetail: {
|
||||||
secondItemDiscount: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(6) > span',
|
secondItemDiscount: 'vn-claim-detail > vn-vertical > vn-card > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(6) > span',
|
||||||
discountInput: '.vn-popover.shown vn-input-number[ng-model="$ctrl.newDiscount"] input',
|
discountInput: '.vn-popover.shown vn-input-number[ng-model="$ctrl.newDiscount"] input',
|
||||||
discoutPopoverMana: '.vn-popover.shown .content > div > vn-horizontal > h5',
|
discoutPopoverMana: '.vn-popover.shown .content > div > vn-horizontal > h5',
|
||||||
addItemButton: 'vn-claim-detail a vn-float-button',
|
addItemButton: 'vn-claim-detail a vn-float-button',
|
||||||
firstClaimableSaleFromTicket: 'vn-claim-detail > vn-dialog vn-tbody > vn-tr',
|
firstClaimableSaleFromTicket: 'vn-claim-detail > vn-dialog vn-tbody > vn-tr',
|
||||||
claimDetailLine: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr',
|
claimDetailLine: 'vn-claim-detail > vn-vertical > vn-card > vn-vertical > vn-table > div > vn-tbody > vn-tr',
|
||||||
firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[ng-model="saleClaimed.quantity"] input',
|
firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[ng-model="saleClaimed.quantity"] input',
|
||||||
totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > div > vn-label-value:nth-child(2) > section > span',
|
totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > vn-vertical > vn-horizontal > div > vn-label-value:nth-child(2) > section > span',
|
||||||
secondItemDeleteButton: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(8) > vn-icon-button > button > vn-icon > i'
|
secondItemDeleteButton: 'vn-claim-detail > vn-vertical > vn-card > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(8) > vn-icon-button > button > vn-icon > i'
|
||||||
},
|
},
|
||||||
claimDevelopment: {
|
claimDevelopment: {
|
||||||
addDevelopmentButton: 'vn-claim-development > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-icon-button > button > vn-icon',
|
addDevelopmentButton: 'vn-claim-development > vn-vertical > vn-card > vn-vertical > vn-one > vn-icon-button > button > vn-icon',
|
||||||
firstDeleteDevelopmentButton: 'vn-claim-development > vn-vertical > vn-card > div > vn-vertical > form > vn-horizontal:nth-child(2) > vn-icon-button > button > vn-icon',
|
firstDeleteDevelopmentButton: 'vn-claim-development > vn-vertical > vn-card > vn-vertical > form > vn-horizontal:nth-child(2) > vn-icon-button > button > vn-icon',
|
||||||
firstClaimReasonAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimReasonFk"]',
|
firstClaimReasonAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimReasonFk"]',
|
||||||
firstClaimResultAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResultFk"]',
|
firstClaimResultAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResultFk"]',
|
||||||
firstClaimResponsibleAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]',
|
firstClaimResponsibleAutocomplete: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]',
|
||||||
|
@ -580,7 +580,7 @@ export default {
|
||||||
isPaidWithManaCheckbox: 'vn-check[ng-model="$ctrl.claim.isChargedToMana"]'
|
isPaidWithManaCheckbox: 'vn-check[ng-model="$ctrl.claim.isChargedToMana"]'
|
||||||
},
|
},
|
||||||
ordersIndex: {
|
ordersIndex: {
|
||||||
searchResult: 'vn-order-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
|
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
|
||||||
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
|
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
|
||||||
searchOrderInput: `vn-order-index vn-textfield input`,
|
searchOrderInput: `vn-order-index vn-textfield input`,
|
||||||
|
@ -641,7 +641,7 @@ export default {
|
||||||
volume: 'vn-route-descriptor vn-label-value[label="Volume"] > section > span'
|
volume: 'vn-route-descriptor vn-label-value[label="Volume"] > section > span'
|
||||||
},
|
},
|
||||||
routeSummary: {
|
routeSummary: {
|
||||||
routeId: 'vn-route-summary > vn-card > div > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(1) > section > span'
|
routeId: 'vn-route-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(1) > section > span'
|
||||||
},
|
},
|
||||||
routeBasicData: {
|
routeBasicData: {
|
||||||
workerAutoComplete: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
workerAutoComplete: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
||||||
|
@ -671,57 +671,58 @@ export default {
|
||||||
},
|
},
|
||||||
workerTimeControl: {
|
workerTimeControl: {
|
||||||
timeDialogInput: '.vn-dialog.shown [ng-model="$ctrl.newTime"]',
|
timeDialogInput: '.vn-dialog.shown [ng-model="$ctrl.newTime"]',
|
||||||
mondayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(1) > vn-icon-button > button > vn-icon',
|
mondayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(1) > vn-icon-button',
|
||||||
tuesdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(2) > vn-icon-button > button > vn-icon',
|
tuesdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(2) > vn-icon-button',
|
||||||
wednesdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(3) > vn-icon-button > button > vn-icon',
|
wednesdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(3) > vn-icon-button',
|
||||||
thursdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-icon-button > button > vn-icon',
|
thursdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-icon-button',
|
||||||
fridayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(5) > vn-icon-button > button > vn-icon',
|
fridayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(5) > vn-icon-button',
|
||||||
saturdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button > button > vn-icon',
|
saturdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button',
|
||||||
sundayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(7) > vn-icon-button > button > vn-icon',
|
sundayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(7) > vn-icon-button',
|
||||||
confirmButton: 'vn-worker-time-control > vn-dialog > div > form > div.buttons > tpl-buttons > button',
|
confirmButton: 'vn-worker-time-control > vn-dialog > div > form > div.buttons > tpl-buttons > button',
|
||||||
firstEntryOfMonday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > span',
|
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > span',
|
||||||
firstEntryOfTuesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > span',
|
firstEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > span',
|
||||||
firstEntryOfWednesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > span',
|
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > span',
|
||||||
firstEntryOfThursday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > span',
|
firstEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > span',
|
||||||
firstEntryOfFriday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > span',
|
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > span',
|
||||||
firstEntryOfSaturday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > span',
|
firstEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > span',
|
||||||
firstEntryOfSunday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > span',
|
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > span',
|
||||||
secondEntryOfMonday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > span',
|
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > span',
|
||||||
secondEntryOfTuesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > span',
|
secondEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > span',
|
||||||
secondEntryOfWednesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > span',
|
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > span',
|
||||||
secondEntryOfThursday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > span',
|
secondEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > span',
|
||||||
secondEntryOfFriday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > span',
|
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > span',
|
||||||
secondEntryOfSaturday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > span',
|
secondEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > span',
|
||||||
secondEntryOfSunday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > span',
|
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > span',
|
||||||
thirdEntryOfMonday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > span',
|
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > span',
|
||||||
thirdEntryOfTuesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > span',
|
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > span',
|
||||||
thirdEntryOfWednesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > span',
|
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > span',
|
||||||
thirdEntryOfThursday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > span',
|
thirdEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > span',
|
||||||
thirdEntryOfFriday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > span',
|
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > span',
|
||||||
thirdEntryOfSaturday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > span',
|
thirdEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > span',
|
||||||
thirdEntryOfSunday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > span',
|
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > span',
|
||||||
fourthEntryOfMonday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > span',
|
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > span',
|
||||||
fourthEntryOfTuesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > span',
|
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > span',
|
||||||
fourthEntryOfWednesday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > span',
|
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > span',
|
||||||
fourthEntryOfThursday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > span',
|
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > span',
|
||||||
fourthEntryOfFriday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > span',
|
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > span',
|
||||||
fourthEntryOfSaturday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > span',
|
fourthEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > span',
|
||||||
fourthEntryOfSunday: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > span',
|
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > span',
|
||||||
mondayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(1)',
|
mondayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(1)',
|
||||||
tuesdayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
|
tuesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
|
||||||
wednesdayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(3)',
|
wednesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(3)',
|
||||||
thursdayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(4)',
|
thursdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(4)',
|
||||||
fridayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(5)',
|
fridayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(5)',
|
||||||
saturdayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(6)',
|
saturdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(6)',
|
||||||
sundayWorkedHours: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(7)',
|
sundayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(7)',
|
||||||
weekWorkedHours: 'vn-worker-time-control > div > vn-side-menu > div > vn-vertical > vn-vertical > vn-label-value > section > span',
|
weekWorkedHours: 'vn-worker-time-control vn-side-menu vn-label-value > section > span',
|
||||||
nextMonthButton: 'vn-worker-time-control > div > vn-side-menu > div > vn-calendar > div > vn-horizontal > vn-auto:nth-child(3) > vn-icon',
|
nextMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_right]',
|
||||||
|
secondWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(8) > .day-number',
|
||||||
navigateBackToIndex: 'vn-worker-descriptor vn-icon[icon="chevron_left"]'
|
navigateBackToIndex: 'vn-worker-descriptor vn-icon[icon="chevron_left"]'
|
||||||
},
|
},
|
||||||
invoiceOutIndex: {
|
invoiceOutIndex: {
|
||||||
searchInvoiceOutInput: `vn-invoice-out-index vn-textfield input`,
|
searchInvoiceOutInput: `vn-invoice-out-index vn-textfield input`,
|
||||||
searchButton: 'vn-invoice-out-index vn-searchbar vn-icon[icon="search"]',
|
searchButton: 'vn-invoice-out-index vn-searchbar vn-icon[icon="search"]',
|
||||||
searchResult: 'vn-invoice-out-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
},
|
},
|
||||||
invoiceOutDescriptor: {
|
invoiceOutDescriptor: {
|
||||||
moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[icon=more_vert]',
|
moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[icon=more_vert]',
|
||||||
|
@ -732,6 +733,6 @@ export default {
|
||||||
acceptBookingButton: 'vn-invoice-out-descriptor > vn-confirm[vn-id="bookConfirmation"] button[response="ACCEPT"]'
|
acceptBookingButton: 'vn-invoice-out-descriptor > vn-confirm[vn-id="bookConfirmation"] button[response="ACCEPT"]'
|
||||||
},
|
},
|
||||||
invoiceOutSummary: {
|
invoiceOutSummary: {
|
||||||
bookedLabel: 'vn-invoice-out-summary > vn-card > div > vn-horizontal > vn-one > vn-label-value:nth-child(4) > section > span'
|
bookedLabel: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-one > vn-label-value:nth-child(4) > section > span'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -286,11 +286,11 @@ describe('Worker time control path', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('as salesBoss', () => {
|
describe('as hr', () => {
|
||||||
describe('on Saturday', () => {
|
describe('on Saturday', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
nightmare
|
nightmare
|
||||||
.loginAndModule('salesBoss', 'worker')
|
.loginAndModule('hr', 'worker')
|
||||||
.accessToSearchResult('HankPym')
|
.accessToSearchResult('HankPym')
|
||||||
.accessToSection('worker.card.timeControl');
|
.accessToSection('worker.card.timeControl');
|
||||||
});
|
});
|
||||||
|
@ -358,10 +358,11 @@ describe('Worker time control path', () => {
|
||||||
it(`should check Hank Pym doesn't have hours set on the next months first week`, async() => {
|
it(`should check Hank Pym doesn't have hours set on the next months first week`, async() => {
|
||||||
const wholeWeekHours = await nightmare
|
const wholeWeekHours = await nightmare
|
||||||
.waitToClick(selectors.workerTimeControl.nextMonthButton)
|
.waitToClick(selectors.workerTimeControl.nextMonthButton)
|
||||||
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 Hours')
|
.waitToClick(selectors.workerTimeControl.secondWeekDay)
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(wholeWeekHours).toEqual('00:00 Hours');
|
expect(wholeWeekHours).toEqual('00:00 h.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should check he didn't scan in this week yet`, async() => {
|
it(`should check he didn't scan in this week yet`, async() => {
|
||||||
|
@ -371,7 +372,7 @@ describe('Worker time control path', () => {
|
||||||
.accessToSection('worker.card.timeControl')
|
.accessToSection('worker.card.timeControl')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(wholeWeekHours).toEqual('00:00 Hours');
|
expect(wholeWeekHours).toEqual('00:00 h.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -386,10 +387,10 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it('should Hank Pym check his hours are alright', async() => {
|
it('should Hank Pym check his hours are alright', async() => {
|
||||||
const wholeWeekHours = await nightmare
|
const wholeWeekHours = await nightmare
|
||||||
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 Hours')
|
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(wholeWeekHours).toEqual('56:00 Hours');
|
expect(wholeWeekHours).toEqual('56:00 h.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('Ticket Summary path', () => {
|
||||||
|
|
||||||
it(`should display details from the ticket and it's client on the top of the header`, async() => {
|
it(`should display details from the ticket and it's client on the top of the header`, async() => {
|
||||||
let result = await nightmare
|
let result = await nightmare
|
||||||
.waitForSpinnerLoad()
|
.waitForTextInElement(selectors.ticketSummary.header, 'Bruce Banner')
|
||||||
.waitToGetProperty(selectors.ticketSummary.header, 'innerText');
|
.waitToGetProperty(selectors.ticketSummary.header, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain(`Ticket #${ticketId}`);
|
expect(result).toContain(`Ticket #${ticketId}`);
|
||||||
|
|
|
@ -48,5 +48,5 @@
|
||||||
vn-id="drop-down"
|
vn-id="drop-down"
|
||||||
on-select="$ctrl.onDropDownSelect(item)"
|
on-select="$ctrl.onDropDownSelect(item)"
|
||||||
on-data-ready="$ctrl.onDataReady()"
|
on-data-ready="$ctrl.onDataReady()"
|
||||||
on-close-start="$ctrl.focus()">
|
on-close-start="$ctrl.onDropDownClose()">
|
||||||
</vn-drop-down>
|
</vn-drop-down>
|
|
@ -209,6 +209,10 @@ export default class Autocomplete extends Field {
|
||||||
this.field = value;
|
this.field = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDropDownClose() {
|
||||||
|
setTimeout(() => this.focus());
|
||||||
|
}
|
||||||
|
|
||||||
onContainerKeyDown(event) {
|
onContainerKeyDown(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
|
|
||||||
|
@ -224,13 +228,10 @@ export default class Autocomplete extends Field {
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onContainerClick(event) {
|
onContainerClick(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
this.showDropDown();
|
this.showDropDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,5 @@
|
||||||
</button>
|
</button>
|
||||||
<vn-drop-down
|
<vn-drop-down
|
||||||
vn-id="drop-down"
|
vn-id="drop-down"
|
||||||
on-select="$ctrl.onDropDownSelect(item)"
|
on-select="$ctrl.onDropDownSelect(item)">
|
||||||
ng-click="$ctrl.onDropDownClick($event)">
|
|
||||||
</vn-drop-down>
|
</vn-drop-down>
|
|
@ -44,15 +44,10 @@ export default class ButtonMenu extends Button {
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (this.disabled) return;
|
if (this.disabled) return;
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
this.emit('open');
|
this.emit('open');
|
||||||
this.showDropDown();
|
this.showDropDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDropDownClick(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
onDropDownSelect(item) {
|
onDropDownSelect(item) {
|
||||||
const value = item[this.valueField];
|
const value = item[this.valueField];
|
||||||
this.field = value;
|
this.field = value;
|
||||||
|
|
|
@ -6,11 +6,8 @@ export default class Button extends FormInput {
|
||||||
constructor($element, $scope) {
|
constructor($element, $scope) {
|
||||||
super($element, $scope);
|
super($element, $scope);
|
||||||
this.design = 'colored';
|
this.design = 'colored';
|
||||||
this.input = this.element.querySelector('button');
|
this.initTabIndex();
|
||||||
|
this.classList.add('vn-button');
|
||||||
let element = this.element;
|
|
||||||
element.tabIndex = 0;
|
|
||||||
element.classList.add('vn-button');
|
|
||||||
this.element.addEventListener('keyup', e => this.onKeyup(e));
|
this.element.addEventListener('keyup', e => this.onKeyup(e));
|
||||||
this.element.addEventListener('click', e => this.onClick(e));
|
this.element.addEventListener('click', e => this.onClick(e));
|
||||||
}
|
}
|
||||||
|
@ -21,16 +18,17 @@ export default class Button extends FormInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyup(event) {
|
onKeyup(event) {
|
||||||
if (event.code == 'Space')
|
if (event.defaultPrevented) return;
|
||||||
this.onClick(event);
|
switch (event.code) {
|
||||||
|
case 'Space':
|
||||||
|
case 'Enter':
|
||||||
|
return this.element.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (this.disabled)
|
||||||
// event.preventDefault();
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
// FIXME: Don't stop event propagation
|
|
||||||
if (this.disabled) event.stopImmediatePropagation();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button.$inject = ['$element', '$scope'];
|
Button.$inject = ['$element', '$scope'];
|
||||||
|
|
|
@ -1,82 +1,46 @@
|
||||||
<div>
|
<div>
|
||||||
<vn-horizontal class="header">
|
<div class="header">
|
||||||
<vn-auto>
|
<vn-button
|
||||||
<vn-icon
|
icon="keyboard_arrow_left"
|
||||||
icon="keyboard_arrow_left"
|
class="flat"
|
||||||
class="pointer"
|
ng-click="$ctrl.movePrevious()"
|
||||||
ng-click="$ctrl.movePrevious($ctrl.skip)"
|
translate-attr="::{title: 'Previous'}"
|
||||||
ng-show="$ctrl.displayControls"/>
|
ng-if="$ctrl.displayControls"/>
|
||||||
</vn-icon>
|
</vn-button>
|
||||||
</vn-auto>
|
<div class="title">
|
||||||
<vn-one>
|
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
|
||||||
<div>
|
<span ng-hide="::$ctrl.hideYear">{{$ctrl.defaultDate | date: 'yyyy'}}</span>
|
||||||
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
|
</div>
|
||||||
<span>{{$ctrl.defaultDate | date: 'yyyy'}}</span>
|
<vn-button
|
||||||
|
icon="keyboard_arrow_right"
|
||||||
|
class="flat"
|
||||||
|
ng-click="$ctrl.moveNext()"
|
||||||
|
translate-attr="::{title: 'Next'}"
|
||||||
|
ng-if="$ctrl.displayControls">
|
||||||
|
</vn-button>
|
||||||
|
</div>
|
||||||
|
<div class="weekdays">
|
||||||
|
<section
|
||||||
|
ng-repeat="day in ::$ctrl.weekDays"
|
||||||
|
translate-attr="::{title: day.name}"
|
||||||
|
ng-click="$ctrl.selectWeekDay(day.index)">
|
||||||
|
<span>{{::day.localeChar}}</span>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="days"
|
||||||
|
ng-class="{'hide-contiguous': $ctrl.hideContiguous}">
|
||||||
|
<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(day)">
|
||||||
|
{{::day | date: 'd'}}
|
||||||
</div>
|
</div>
|
||||||
</vn-one>
|
</section>
|
||||||
<vn-auto>
|
</div>
|
||||||
<vn-icon
|
|
||||||
icon="keyboard_arrow_right"
|
|
||||||
class="pointer"
|
|
||||||
ng-click="$ctrl.moveNext($ctrl.skip)"
|
|
||||||
ng-show="$ctrl.displayControls">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-vertical class="body">
|
|
||||||
<vn-horizontal class="weekdays">
|
|
||||||
<section title="{{'Monday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(1)">
|
|
||||||
<span>L</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Tuesday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(2)">
|
|
||||||
<span>M</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Wednesday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(3)">
|
|
||||||
<span>X</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Thursday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(4)">
|
|
||||||
<span>J</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Friday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(5)">
|
|
||||||
<span>V</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Saturday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(6)">
|
|
||||||
<span>S</span>
|
|
||||||
</section>
|
|
||||||
<section title="{{'Sunday' | translate}}"
|
|
||||||
ng-click="$ctrl.selectAll(0)">
|
|
||||||
<span>D</span>
|
|
||||||
</section>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="days">
|
|
||||||
<section
|
|
||||||
ng-repeat="day in $ctrl.days"
|
|
||||||
class="day {{::$ctrl.getClass({$day: day.dated})}}"
|
|
||||||
ng-class="::{primary: day.events.length > 0 || $ctrl.hasEvents({$day: day.dated})}">
|
|
||||||
<div class="content">
|
|
||||||
<div class="day-number"
|
|
||||||
title="{{(day.eventName) | translate}}"
|
|
||||||
ng-style="$ctrl.renderStyle(day.style)"
|
|
||||||
ng-click="$ctrl.select($index)">
|
|
||||||
{{::day.dated | date: 'd'}}
|
|
||||||
</div>
|
|
||||||
<div ng-if="day.events" class="events">
|
|
||||||
<div ng-repeat="event in day.events" class="event"
|
|
||||||
title="{{(event.description || event.name) | translate}}">
|
|
||||||
<span class="chip ellipsize"
|
|
||||||
ng-style="::$ctrl.renderStyle(event.style)">
|
|
||||||
{{::event.name}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
</div>
|
|
@ -1,43 +1,26 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
import Component from '../../lib/component';
|
import FormInput from '../form-input';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flat calendar.
|
* Flat calendar.
|
||||||
*
|
*
|
||||||
* @property {Array} data Array of events
|
* @property {Array} defaultDate Array of events
|
||||||
* @property {Function} hasEvents Determines if an events exists for a day
|
* @property {Function} hasEvents Determines if an events exists for a day
|
||||||
* @property {Function} getClass Class to apply to specific day
|
* @property {Function} getClass Class to apply to specific day
|
||||||
|
* @event selection Emitted when day or weekday is selected
|
||||||
|
* @event move Emitted when month changes
|
||||||
*/
|
*/
|
||||||
export default class Calendar extends Component {
|
export default class Calendar extends FormInput {
|
||||||
constructor($element, $scope) {
|
constructor($element, $scope, vnWeekDays) {
|
||||||
super($element, $scope);
|
super($element, $scope);
|
||||||
this.events = [];
|
this.weekDays = vnWeekDays.locales;
|
||||||
this.defaultDate = new Date();
|
this.defaultDate = new Date();
|
||||||
this.displayControls = true;
|
this.displayControls = true;
|
||||||
this.disabled = false;
|
|
||||||
this.skip = 1;
|
|
||||||
|
|
||||||
this.window.addEventListener('resize', () => {
|
|
||||||
this.checkSize();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes the calendar
|
* The initial date
|
||||||
* based on component height
|
|
||||||
*/
|
|
||||||
checkSize() {
|
|
||||||
const height = this.$element[0].clientHeight;
|
|
||||||
|
|
||||||
if (height < 530)
|
|
||||||
this.$element.addClass('small');
|
|
||||||
else
|
|
||||||
this.$element.removeClass('small');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the initial date
|
|
||||||
*
|
*
|
||||||
* @return {Date} - Default date
|
* @return {Date} - Default date
|
||||||
*/
|
*/
|
||||||
|
@ -45,11 +28,6 @@ export default class Calendar extends Component {
|
||||||
return this._defaultDate;
|
return this._defaultDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a new initial date
|
|
||||||
*
|
|
||||||
* @param {Date} value - New default date
|
|
||||||
*/
|
|
||||||
set defaultDate(value) {
|
set defaultDate(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
value = new Date(value);
|
value = new Date(value);
|
||||||
|
@ -58,67 +36,10 @@ export default class Calendar extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._defaultDate = value;
|
this._defaultDate = value;
|
||||||
|
this.month = value.getMonth();
|
||||||
this.repaint();
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets events
|
|
||||||
*
|
|
||||||
* @param {Array} value - Array of events
|
|
||||||
* @param {Date} event.dated - Day to add event
|
|
||||||
* @param {String} event.name - Tooltip description
|
|
||||||
* @param {String} event.className - ClassName style
|
|
||||||
* @param {Object} event.style - Style properties
|
|
||||||
*/
|
|
||||||
set data(value) {
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
this.events = [];
|
|
||||||
|
|
||||||
value.forEach(event => {
|
|
||||||
event.dated = new Date(event.dated);
|
|
||||||
event.dated.setHours(0, 0, 0, 0);
|
|
||||||
this.events.push(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.defaultDate) {
|
|
||||||
this.repaint();
|
|
||||||
this.checkSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets current month date
|
|
||||||
*/
|
|
||||||
|
|
||||||
get currentMonth() {
|
|
||||||
return this.defaultDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets next month date
|
|
||||||
*
|
|
||||||
* @return {Date}
|
|
||||||
*/
|
|
||||||
get nextMonth() {
|
|
||||||
const newDate = new Date(this.currentMonth);
|
|
||||||
newDate.setMonth(this.currentMonth.getMonth() + 1);
|
|
||||||
|
|
||||||
return newDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets previous month date
|
|
||||||
*
|
|
||||||
* @return {Date}
|
|
||||||
*/
|
|
||||||
get previousMonth() {
|
|
||||||
const newDate = new Date(this.currentMonth);
|
|
||||||
newDate.setMonth(this.currentMonth.getMonth() - 1);
|
|
||||||
|
|
||||||
return newDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns first day of month from a given date
|
* Returns first day of month from a given date
|
||||||
*
|
*
|
||||||
|
@ -126,185 +47,113 @@ export default class Calendar extends Component {
|
||||||
* @return {Integer}
|
* @return {Integer}
|
||||||
*/
|
*/
|
||||||
firstDay(date) {
|
firstDay(date) {
|
||||||
const newDate = new Date(
|
return new Date(
|
||||||
date.getFullYear(),
|
date.getFullYear(),
|
||||||
date.getMonth(), 1);
|
date.getMonth(),
|
||||||
|
1
|
||||||
return newDate;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns last day of month from a given date
|
* Repaints the calendar.
|
||||||
*
|
|
||||||
* @param {Date} date - Origin date
|
|
||||||
* @return {Integer}
|
|
||||||
*/
|
*/
|
||||||
lastDay(date) {
|
|
||||||
const newDate = new Date(
|
|
||||||
date.getFullYear(),
|
|
||||||
date.getMonth() + 1, 0);
|
|
||||||
|
|
||||||
return newDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
repaint() {
|
repaint() {
|
||||||
const firstWeekday = this.firstDay(this.currentMonth).getDay();
|
const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1;
|
||||||
const previousLastDay = this.lastDay(this.previousMonth).getDate();
|
let weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
|
||||||
const currentLastDay = this.lastDay(this.currentMonth).getDate();
|
|
||||||
const maxFields = 42; // Max field limit
|
|
||||||
|
|
||||||
let weekdayOffset = firstWeekday > 0 ? firstWeekday : 7;
|
let dayIndex = new Date(this.defaultDate.getTime());
|
||||||
let dayPrevious = previousLastDay - (weekdayOffset - 2);
|
dayIndex.setDate(1 - weekdayOffset);
|
||||||
let dayCurrent = 1;
|
|
||||||
let dayNext = 1;
|
|
||||||
|
|
||||||
this.days = [];
|
this.days = [];
|
||||||
|
|
||||||
for (let fieldIndex = 1; fieldIndex < maxFields; fieldIndex++) {
|
for (let i = 1; i <= 42; i++) {
|
||||||
// Insert previous month days
|
this.days.push(new Date(dayIndex.getTime()));
|
||||||
if (fieldIndex < weekdayOffset) {
|
dayIndex.setDate(dayIndex.getDate() + 1);
|
||||||
const dated = new Date(
|
|
||||||
this.previousMonth.getFullYear(),
|
|
||||||
this.previousMonth.getMonth(), dayPrevious);
|
|
||||||
|
|
||||||
this.insertDay(dated, 'gray');
|
|
||||||
dayPrevious++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert current month days
|
|
||||||
if (fieldIndex >= weekdayOffset && dayCurrent <= currentLastDay) {
|
|
||||||
const dated = new Date(
|
|
||||||
this.currentMonth.getFullYear(),
|
|
||||||
this.currentMonth.getMonth(), dayCurrent);
|
|
||||||
|
|
||||||
this.insertDay(dated);
|
|
||||||
dayCurrent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert next month days
|
|
||||||
if (fieldIndex >= weekdayOffset && dayCurrent > currentLastDay) {
|
|
||||||
const dated = new Date(
|
|
||||||
this.nextMonth.getFullYear(),
|
|
||||||
this.nextMonth.getMonth(), dayNext);
|
|
||||||
|
|
||||||
this.insertDay(dated, 'gray');
|
|
||||||
dayNext++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a date on an array of month days
|
* Gets CSS classes to apply to the specified day.
|
||||||
*
|
*
|
||||||
* @param {Date} dated - Date of month
|
* @param {Date} day The day
|
||||||
* @param {String} className - Default class style
|
* @return {Object} The CSS classes to apply
|
||||||
*/
|
*/
|
||||||
insertDay(dated) {
|
getDayClasses(day) {
|
||||||
let events = this.events.filter(event => {
|
let wday = day.getDay();
|
||||||
return event.dated >= dated && event.dated <= dated;
|
let month = day.getMonth();
|
||||||
});
|
|
||||||
|
|
||||||
const params = {dated: dated, events: events /**/, style: {}};
|
let classes = {
|
||||||
const isSaturday = dated.getDay() === 6;
|
weekend: wday === 6 || wday === 0,
|
||||||
const isSunday = dated.getDay() === 0;
|
previous: month < this.month,
|
||||||
const isCurrentMonth = dated.getMonth() === this.currentMonth.getMonth();
|
current: month == this.month,
|
||||||
const hasEvents = events.length > 0;
|
next: month > this.month,
|
||||||
|
event: this.hasEvents({$day: day})
|
||||||
|
};
|
||||||
|
|
||||||
if (isCurrentMonth && isSunday && !hasEvents)
|
let userClass = this.getClass({$day: day});
|
||||||
params.style = {color: '#999'};
|
if (userClass) classes[userClass] = true;
|
||||||
|
|
||||||
if (isCurrentMonth && isSaturday && !hasEvents)
|
return classes;
|
||||||
params.style = {color: '#999'};
|
|
||||||
|
|
||||||
if (!isCurrentMonth)
|
|
||||||
params.style = {opacity: '0.5'};
|
|
||||||
|
|
||||||
if (events.length > 0) {
|
|
||||||
const eventStyle = events[0].style;
|
|
||||||
const eventName = events[0].description || events[0].name;
|
|
||||||
if (eventStyle)
|
|
||||||
Object.assign(params.style, eventStyle);
|
|
||||||
if (eventName)
|
|
||||||
params.eventName = eventName;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.days.push(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves to next month(s)
|
* Moves to next month(s)
|
||||||
*
|
|
||||||
* @param {Integer} skip - Months to skip at once
|
|
||||||
*/
|
*/
|
||||||
moveNext(skip = 1) {
|
moveNext() {
|
||||||
let next = this.defaultDate.getMonth() + skip;
|
this.move(1);
|
||||||
this.defaultDate.setMonth(next);
|
|
||||||
this.repaint();
|
|
||||||
this.emit('moveNext');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves to previous month(s)
|
* Moves to previous month(s)
|
||||||
*
|
|
||||||
* @param {Integer} skip - Months to skip at once
|
|
||||||
*/
|
*/
|
||||||
movePrevious(skip = 1) {
|
movePrevious() {
|
||||||
let previous = this.defaultDate.getMonth() - skip;
|
this.move(-1);
|
||||||
this.defaultDate.setMonth(previous);
|
|
||||||
this.repaint();
|
|
||||||
this.emit('movePrevious');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Day selection event
|
* Moves @direction months backwards/forwards.
|
||||||
*
|
*
|
||||||
* @param {Integer} index - Index from days array
|
* @param {Number} direction Negative to move backwards, positive forwards
|
||||||
*/
|
*/
|
||||||
select(index) {
|
move(direction) {
|
||||||
if (this.disabled) return;
|
let date = new Date(this.defaultDate.getTime());
|
||||||
let day = this.days[index].dated;
|
date.setMonth(date.getMonth() + direction);
|
||||||
|
this.defaultDate = date;
|
||||||
|
|
||||||
|
this.repaint();
|
||||||
|
this.emit('move', {$date: date});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Day selection event
|
||||||
|
*/
|
||||||
|
select(day) {
|
||||||
|
if (!this.editable) return;
|
||||||
|
this.field = day;
|
||||||
this.emit('selection', {
|
this.emit('selection', {
|
||||||
$days: [day],
|
$days: [day],
|
||||||
$type: 'day'
|
$type: 'day'
|
||||||
});
|
});
|
||||||
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* WeekDay selection event
|
* WeekDay selection event
|
||||||
*
|
|
||||||
* @param {Integer} weekday - weekday index
|
|
||||||
*/
|
*/
|
||||||
selectAll(weekday) {
|
selectWeekDay(weekday) {
|
||||||
if (this.disabled) return;
|
if (!this.editable) return;
|
||||||
|
|
||||||
let days = [];
|
let days = [];
|
||||||
for (let i in this.days) {
|
for (let day of this.days) {
|
||||||
const day = this.days[i].dated;
|
if (day.getDay() === weekday && day.getMonth() == this.month)
|
||||||
if (day.getDay() === weekday && day.getMonth() == this.defaultDate.getMonth())
|
|
||||||
days.push(day);
|
days.push(day);
|
||||||
}
|
}
|
||||||
|
this.field = days[0];
|
||||||
this.emit('selection', {
|
this.emit('selection', {
|
||||||
$days: days,
|
$days: days,
|
||||||
$type: 'weekday',
|
$type: 'weekday',
|
||||||
$weekday: weekday
|
$weekday: weekday
|
||||||
});
|
});
|
||||||
}
|
this.repaint();
|
||||||
|
|
||||||
renderStyle(style) {
|
|
||||||
const normalizedStyle = {};
|
|
||||||
|
|
||||||
if (style) {
|
|
||||||
const properties = Object.keys(style);
|
|
||||||
properties.forEach(attribute => {
|
|
||||||
const attrName = attribute.split(/(?=[A-Z])/).
|
|
||||||
join('-').toLowerCase();
|
|
||||||
|
|
||||||
normalizedStyle[attrName] = style[attribute];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return normalizedStyle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEvents() {
|
hasEvents() {
|
||||||
|
@ -314,24 +163,31 @@ export default class Calendar extends Component {
|
||||||
getClass() {
|
getClass() {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repeatLast() {
|
||||||
|
if (!this.formatDay) return;
|
||||||
|
|
||||||
|
let days = this.element.querySelectorAll('.days > .day');
|
||||||
|
for (let i = 0; i < days.length; i++) {
|
||||||
|
this.formatDay({
|
||||||
|
$day: this.days[i],
|
||||||
|
$element: days[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Calendar.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
Calendar.$inject = ['$element', '$scope'];
|
ngModule.vnComponent('vnCalendar', {
|
||||||
|
|
||||||
ngModule.component('vnCalendar', {
|
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Calendar,
|
controller: Calendar,
|
||||||
bindings: {
|
bindings: {
|
||||||
model: '<',
|
|
||||||
data: '<?',
|
|
||||||
defaultDate: '=?',
|
defaultDate: '=?',
|
||||||
onSelection: '&?',
|
|
||||||
onMoveNext: '&?',
|
|
||||||
onMovePrevious: '&?',
|
|
||||||
hasEvents: '&?',
|
hasEvents: '&?',
|
||||||
getClass: '&?',
|
getClass: '&?',
|
||||||
|
formatDay: '&?',
|
||||||
displayControls: '<?',
|
displayControls: '<?',
|
||||||
disabled: '<?',
|
hideYear: '<?',
|
||||||
skip: '<?'
|
hideContiguous: '<?'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,10 @@ describe('Component vnCalendar', () => {
|
||||||
let controller;
|
let controller;
|
||||||
let $element;
|
let $element;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setHours(0, 0, 0, 0);
|
||||||
|
date.setDate(1);
|
||||||
|
|
||||||
beforeEach(angular.mock.module('vnCore', $translateProvider => {
|
beforeEach(angular.mock.module('vnCore', $translateProvider => {
|
||||||
$translateProvider.translations('en', {});
|
$translateProvider.translations('en', {});
|
||||||
}));
|
}));
|
||||||
|
@ -9,79 +13,55 @@ describe('Component vnCalendar', () => {
|
||||||
beforeEach(inject(($compile, $rootScope) => {
|
beforeEach(inject(($compile, $rootScope) => {
|
||||||
$element = $compile(`<vn-calendar></vn-calendar`)($rootScope);
|
$element = $compile(`<vn-calendar></vn-calendar`)($rootScope);
|
||||||
controller = $element.controller('vnCalendar');
|
controller = $element.controller('vnCalendar');
|
||||||
controller.defaultDate = new Date();
|
controller.defaultDate = date;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
$element.remove();
|
$element.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('data() setter', () => {
|
|
||||||
it(`should set an array of events and convert string dates to string object, then call repaint() method`, () => {
|
|
||||||
spyOn(controller, 'repaint');
|
|
||||||
|
|
||||||
let currentDate = new Date().toString();
|
|
||||||
controller.data = [
|
|
||||||
{dated: currentDate, name: 'Event 1'},
|
|
||||||
{dated: currentDate, name: 'Event 2'},
|
|
||||||
];
|
|
||||||
|
|
||||||
expect(controller.events[0].dated instanceof Object).toBeTruthy();
|
|
||||||
expect(controller.repaint).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('moveNext()', () => {
|
describe('moveNext()', () => {
|
||||||
it(`should shift to the next n months, then emit a 'moveNext' event`, () => {
|
it(`should shift to the next month, then emit a 'move' event`, () => {
|
||||||
spyOn(controller, 'emit');
|
spyOn(controller, 'emit');
|
||||||
const currentMonth = controller.defaultDate.getMonth();
|
let nextMonth = new Date(date.getTime());
|
||||||
let nextMonth = currentMonth + 1;
|
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||||||
|
|
||||||
controller.moveNext(1);
|
controller.moveNext();
|
||||||
|
|
||||||
expect(controller.defaultDate.getMonth()).toEqual(nextMonth);
|
expect(controller.month).toEqual(nextMonth.getMonth());
|
||||||
expect(controller.emit).toHaveBeenCalledWith('moveNext');
|
expect(controller.emit).toHaveBeenCalledWith('move', {$date: nextMonth});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('movePrevious()', () => {
|
describe('movePrevious()', () => {
|
||||||
it(`should shift to the previous n months, then emit a 'movePrevious' event`, () => {
|
it(`should shift to the previous month, then emit a 'move' event`, () => {
|
||||||
spyOn(controller, 'emit');
|
spyOn(controller, 'emit');
|
||||||
const currentMonth = controller.defaultDate.getMonth();
|
let previousMonth = new Date(date.getTime());
|
||||||
let previousMonth = currentMonth - 1;
|
previousMonth.setMonth(previousMonth.getMonth() - 1);
|
||||||
|
|
||||||
controller.movePrevious(1);
|
controller.movePrevious();
|
||||||
|
|
||||||
expect(controller.defaultDate.getMonth()).toEqual(previousMonth);
|
expect(controller.month).toEqual(previousMonth.getMonth());
|
||||||
expect(controller.emit).toHaveBeenCalledWith('movePrevious');
|
expect(controller.emit).toHaveBeenCalledWith('move', {$date: previousMonth});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('select()', () => {
|
describe('select()', () => {
|
||||||
it(`should return the selected element, then emit a 'selection' event`, () => {
|
it(`should return the selected element, then emit a 'selection' event`, () => {
|
||||||
spyOn(controller, 'emit');
|
spyOn(controller, 'emit');
|
||||||
const dated = new Date();
|
|
||||||
const days = [{dated}];
|
const day = new Date();
|
||||||
controller.days = days;
|
day.setHours(0, 0, 0, 0);
|
||||||
controller.select(0);
|
controller.select(day);
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
$days: [dated],
|
$days: [day],
|
||||||
$type: 'day'
|
$type: 'day'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
expect(controller.field).toEqual(day);
|
||||||
expect(controller.emit).toHaveBeenCalledWith('selection', res);
|
expect(controller.emit).toHaveBeenCalledWith('selection', res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('renderStyle()', () => {
|
|
||||||
it(`should normalize CSS attributes`, () => {
|
|
||||||
const result = controller.renderStyle({
|
|
||||||
backgroundColor: 'red'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result['background-color']).toEqual('red');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,103 +1,97 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
vn-calendar.small {
|
|
||||||
.events {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vn-calendar {
|
vn-calendar {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
.header vn-one {
|
& > div {
|
||||||
text-align: center;
|
& > .header {
|
||||||
padding: 0.2em 0;
|
display: flex;
|
||||||
height: 1.5em
|
margin-bottom: 0.5em;
|
||||||
}
|
align-items: center;
|
||||||
.weekdays {
|
height: 2.4em;
|
||||||
color: $color-font-secondary;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
.weekdays section {
|
|
||||||
cursor: pointer
|
|
||||||
}
|
|
||||||
.weekdays section, .day {
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 14.28%;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
.days {
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.day {
|
|
||||||
.content {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
top: 0
|
|
||||||
}
|
|
||||||
.day-number {
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
text-align:center;
|
|
||||||
float:inline-end;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 0.85em;
|
|
||||||
width:2.2em;
|
|
||||||
height: 1.2em;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: 0
|
|
||||||
}
|
|
||||||
.day-number:hover {
|
|
||||||
background-color: lighten($color-font-secondary, 20%);
|
|
||||||
opacity: 0.8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.day::after {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
padding-top: 100%;
|
|
||||||
}
|
|
||||||
.day.primary .day-number {
|
|
||||||
background-color: $color-main;
|
|
||||||
color: $color-font-dark;
|
|
||||||
}
|
|
||||||
.events {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
font-size: 0.6em
|
|
||||||
}
|
|
||||||
.events {
|
|
||||||
color: $color-font-secondary;
|
|
||||||
|
|
||||||
.event {
|
& > .title {
|
||||||
margin-bottom: .1em;
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.2em 0;
|
||||||
|
}
|
||||||
|
& > .vn-button {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > .weekdays {
|
||||||
|
display: flex;
|
||||||
|
color: $color-font-secondary;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
& > section {
|
||||||
|
width: 14.28%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > .days {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
& > .day {
|
||||||
|
width: 14.28%;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.weekend {
|
||||||
|
color: $color-font-secondary;
|
||||||
|
}
|
||||||
|
&.previous,
|
||||||
|
&.next {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
&.event .day-number {
|
||||||
|
background-color: $color-main;
|
||||||
|
color: $color-font-dark;
|
||||||
|
}
|
||||||
|
& > .day-number {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 14px;
|
||||||
|
width: 2.2em;
|
||||||
|
height: 2.2em;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: 0;
|
||||||
|
transition: background-color 300ms ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($color-font-secondary, 20%);
|
||||||
|
opacity: .8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.hide-contiguous > .day {
|
||||||
|
&.previous,
|
||||||
|
&.next {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.chip {
|
&.disabled,
|
||||||
background-color: $color-main;
|
&.readonly {
|
||||||
color: $color-font-bg;
|
& > div {
|
||||||
display: inline-block;
|
& > .weekdays > section {
|
||||||
border-radius: .3em;
|
cursor: initial;
|
||||||
padding: 0.3em .8em;
|
}
|
||||||
max-width: 5em;
|
& > .days > .day > .day-number {
|
||||||
}
|
cursor: initial;
|
||||||
.day.gray {
|
}
|
||||||
.day-number {
|
|
||||||
color: $color-font-secondary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.day.sunday {
|
|
||||||
.day-number {
|
|
||||||
color: $color-alert;
|
|
||||||
font-weight: bold
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<div></div>
|
|
|
@ -5,12 +5,11 @@ export default function directive() {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
transclude: true,
|
transclude: true,
|
||||||
template: require('./card.html'),
|
|
||||||
link: function($scope, $element, $attrs, $ctrl, $transclude) {
|
link: function($scope, $element, $attrs, $ctrl, $transclude) {
|
||||||
$element.addClass('demo-card-wide vn-shadow bg-panel');
|
$element[0].classList.add('vn-shadow', 'bg-panel');
|
||||||
|
|
||||||
$transclude($scope, function(clone) {
|
$transclude($scope, function(clone) {
|
||||||
angular.element($element[0].querySelector('div')).append(clone);
|
$element.append(clone);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<h6>Debug info</h6>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{{$ctrl.env}}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span ng-class="{alert: $root.$$watchersCount > 500}">{{$root.$$watchersCount}}</span> watchers
|
||||||
|
</li>
|
||||||
|
</ul>
|
|
@ -0,0 +1,27 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating box displaying debugging information.
|
||||||
|
* Enabled only in development environment.
|
||||||
|
*/
|
||||||
|
export default class Controller {
|
||||||
|
constructor($element, $) {
|
||||||
|
this.env = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
|
if (this.env == 'development')
|
||||||
|
this.interval = setInterval(() => $.$digest(), 2000);
|
||||||
|
else
|
||||||
|
$element[0].style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope'];
|
||||||
|
|
||||||
|
ngModule.component('vnDebugInfo', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -0,0 +1,44 @@
|
||||||
|
@import "variables";
|
||||||
|
|
||||||
|
vn-debug-info {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1em;
|
||||||
|
left: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
min-width: 8em;
|
||||||
|
background-color: #3f51b5;
|
||||||
|
color: $color-font-dark;
|
||||||
|
border-radius: 4px;
|
||||||
|
z-index: 999;
|
||||||
|
box-shadow: $shadow;
|
||||||
|
transition: opacity 400ms ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
& > h6 {
|
||||||
|
font-weight: normal;
|
||||||
|
color: rgba(255, 255, 255, .5);
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
& > li {
|
||||||
|
margin-top: .2em;
|
||||||
|
font-size: .95em;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
padding: .05em .2em;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 200ms ease-in-out;
|
||||||
|
|
||||||
|
&.alert {
|
||||||
|
background-color: $color-alert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
tpl-body {
|
tpl-body {
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 20em;
|
min-width: 16em;
|
||||||
}
|
}
|
||||||
& > button.close {
|
& > button.close {
|
||||||
@extend %clickable;
|
@extend %clickable;
|
||||||
|
|
|
@ -218,17 +218,14 @@ export default class DropDown extends Component {
|
||||||
|
|
||||||
onLoadMoreClick(event) {
|
onLoadMoreClick(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
this.model.loadMore();
|
this.model.loadMore();
|
||||||
}
|
}
|
||||||
|
|
||||||
onContainerClick(event) {
|
onContainerClick(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
let index = getPosition(this.$.ul, event);
|
let index = getPosition(this.$.ul, event);
|
||||||
if (index != -1) {
|
if (index != -1)
|
||||||
event.preventDefault();
|
|
||||||
this.selectOption(index);
|
this.selectOption(index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocKeyDown(event) {
|
onDocKeyDown(event) {
|
||||||
|
|
|
@ -153,13 +153,8 @@ export default class Field extends FormInput {
|
||||||
fix.innerText = text || '';
|
fix.innerText = text || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTabIndex() {
|
|
||||||
this.input.tabIndex = this.disabled ? -1 : this.tabIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick() {
|
onClick() {
|
||||||
// if (event.defaultPrevented) return;
|
// if (event.defaultPrevented) return;
|
||||||
// event.preventDefault();
|
|
||||||
|
|
||||||
if (this.input !== document.activeElement)
|
if (this.input !== document.activeElement)
|
||||||
this.focus();
|
this.focus();
|
||||||
|
@ -177,19 +172,10 @@ export default class Field extends FormInput {
|
||||||
|
|
||||||
onClear(event) {
|
onClear(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
this.field = null;
|
this.field = null;
|
||||||
this.input.dispatchEvent(new Event('change'));
|
this.input.dispatchEvent(new Event('change'));
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
|
||||||
this.input.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
select() {
|
|
||||||
this.input.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
buildInput(type) {
|
buildInput(type) {
|
||||||
let template = `<input type="${type}" ng-model="$ctrl.field"></input>`;
|
let template = `<input type="${type}" ng-model="$ctrl.field"></input>`;
|
||||||
this.input = this.$compile(template)(this.$)[0];
|
this.input = this.$compile(template)(this.$)[0];
|
||||||
|
|
|
@ -49,8 +49,9 @@ export default class FormInput extends Component {
|
||||||
|
|
||||||
set disabled(value) {
|
set disabled(value) {
|
||||||
this._disabled = boolTag(value);
|
this._disabled = boolTag(value);
|
||||||
this.input.disabled = this._disabled;
|
|
||||||
this.classList.toggle('disabled', this._disabled);
|
this.classList.toggle('disabled', this._disabled);
|
||||||
|
if (this.input)
|
||||||
|
this.input.disabled = this._disabled;
|
||||||
this.refreshTabIndex();
|
this.refreshTabIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +61,9 @@ export default class FormInput extends Component {
|
||||||
|
|
||||||
set readonly(value) {
|
set readonly(value) {
|
||||||
this._readonly = boolTag(value);
|
this._readonly = boolTag(value);
|
||||||
this.input.readOnly = this._readonly;
|
|
||||||
this.classList.toggle('readonly', this._readonly);
|
this.classList.toggle('readonly', this._readonly);
|
||||||
|
if (this.input)
|
||||||
|
this.input.readOnly = this._readonly;
|
||||||
}
|
}
|
||||||
|
|
||||||
get readonly() {
|
get readonly() {
|
||||||
|
@ -77,16 +79,30 @@ export default class FormInput extends Component {
|
||||||
return this._tabIndex;
|
return this._tabIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get inputEl() {
|
||||||
|
return this.input || this.element;
|
||||||
|
}
|
||||||
|
|
||||||
|
get editable() {
|
||||||
|
return !(this.readonly || this.disabled);
|
||||||
|
}
|
||||||
|
|
||||||
select() {
|
select() {
|
||||||
this.input.select();
|
if (this.inputEl.select)
|
||||||
|
this.inputEl.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this.input.focus();
|
this.inputEl.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
initTabIndex() {
|
||||||
|
if (!this.element.hasAttribute('tabindex'))
|
||||||
|
this.element.tabIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTabIndex() {
|
refreshTabIndex() {
|
||||||
this.element.tabIndex = this.disabled ? -1 : this.tabIndex;
|
this.inputEl.tabIndex = this.disabled ? -1 : this.tabIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import './check';
|
||||||
import './chip';
|
import './chip';
|
||||||
import './data-viewer';
|
import './data-viewer';
|
||||||
import './date-picker';
|
import './date-picker';
|
||||||
|
import './debug-info';
|
||||||
import './field';
|
import './field';
|
||||||
import './float-button';
|
import './float-button';
|
||||||
import './icon-menu';
|
import './icon-menu';
|
||||||
|
@ -44,3 +45,4 @@ import './td-editable';
|
||||||
import './textarea';
|
import './textarea';
|
||||||
import './th';
|
import './th';
|
||||||
import './treeview';
|
import './treeview';
|
||||||
|
import './wday-picker';
|
||||||
|
|
|
@ -68,7 +68,6 @@ export default class InputNumber extends Field {
|
||||||
|
|
||||||
onStep(event, way) {
|
onStep(event, way) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (way == 'up')
|
if (way == 'up')
|
||||||
this.stepUp();
|
this.stepUp();
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller extends Component {
|
||||||
constructor($element, $translate, $attrs) {
|
constructor($element, $, $attrs) {
|
||||||
this.element = $element[0];
|
super($element, $);
|
||||||
this._ = $translate;
|
|
||||||
this.hasInfo = Boolean($attrs.info);
|
this.hasInfo = Boolean($attrs.info);
|
||||||
this.info = $attrs.info || null;
|
this.info = $attrs.info || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
set label(value) {
|
set label(value) {
|
||||||
let label = this.element.querySelector('vn-label');
|
let label = this.element.querySelector('vn-label');
|
||||||
label.textContent = this._.instant(value);
|
label.textContent = this.$t(value);
|
||||||
this._label = value;
|
this._label = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ export default class Controller {
|
||||||
element.textContent = hasValue ? this.value : '-';
|
element.textContent = hasValue ? this.value : '-';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$element', '$translate', '$attrs'];
|
Controller.$inject = ['$element', '$scope', '$attrs'];
|
||||||
|
|
||||||
ngModule.component('vnLabelValue', {
|
ngModule.component('vnLabelValue', {
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
|
|
|
@ -190,7 +190,6 @@ export default class Popover extends Component {
|
||||||
|
|
||||||
onBgMouseDown(event) {
|
onBgMouseDown(event) {
|
||||||
if (event == this.lastMouseEvent || event.defaultPrevented) return;
|
if (event == this.lastMouseEvent || event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@ export default class Controller extends Component {
|
||||||
|
|
||||||
openPanel(event) {
|
openPanel(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
this.$panelScope = this.$.$new();
|
this.$panelScope = this.$.$new();
|
||||||
this.$panel = this.$compile(`<${this.panel}/>`)(this.$panelScope);
|
this.$panel = this.$compile(`<${this.panel}/>`)(this.$panelScope);
|
||||||
|
|
|
@ -81,18 +81,6 @@ describe('Component vnSearchbar', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('openPanel()', () => {
|
|
||||||
it(`should do nothing if the event is prevented`, () => {
|
|
||||||
let event = {
|
|
||||||
defaultPrevented: true,
|
|
||||||
preventDefault: jasmine.createSpy('preventDefault')
|
|
||||||
};
|
|
||||||
controller.openPanel(event);
|
|
||||||
|
|
||||||
expect(event.preventDefault).not.toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onPopoverClose()', () => {
|
describe('onPopoverClose()', () => {
|
||||||
it(`should get rid of $panel and $panelScope`, () => {
|
it(`should get rid of $panel and $panelScope`, () => {
|
||||||
controller.$panel = {
|
controller.$panel = {
|
||||||
|
|
|
@ -10,43 +10,20 @@ import './style.scss';
|
||||||
export default class Toggle extends FormInput {
|
export default class Toggle extends FormInput {
|
||||||
constructor($element, $) {
|
constructor($element, $) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
|
this.initTabIndex();
|
||||||
let element = this.element;
|
this.classList.add('vn-toggle');
|
||||||
element.tabIndex = 0;
|
this.element.addEventListener('click', e => this.onClick(e));
|
||||||
element.addEventListener('click', e => this.onClick(e));
|
this.element.addEventListener('keydown', e => this.onKeydown(e));
|
||||||
element.addEventListener('keydown', e => this.onKeydown(e));
|
|
||||||
element.classList.add('vn-toggle');
|
|
||||||
}
|
|
||||||
|
|
||||||
set disabled(value) {
|
|
||||||
this._disabled = value;
|
|
||||||
this.classList.toggle('disabled', Boolean(value));
|
|
||||||
this.refreshTabIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
get disabled() {
|
|
||||||
return this._disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
set readonly(value) {
|
|
||||||
this._readonly = value;
|
|
||||||
this.classList.toggle('readonly', Boolean(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
get readonly() {
|
|
||||||
return this._readonly;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeydown(event) {
|
onKeydown(event) {
|
||||||
if (event.code == 'Space')
|
if (!event.defaultPrevented && event.code == 'Space')
|
||||||
this.onClick(event);
|
this.element.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (this.disabled || event.defaultPrevented)
|
if (!this.editable || event.defaultPrevented)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changed() {
|
changed() {
|
||||||
|
|
|
@ -235,7 +235,6 @@ export function directive($document, $compile, $templateRequest) {
|
||||||
$element[0].title = '';
|
$element[0].title = '';
|
||||||
$element.on('mouseover', function(event) {
|
$element.on('mouseover', function(event) {
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
|
||||||
tooltip.show($element[0]);
|
tooltip.show($element[0]);
|
||||||
});
|
});
|
||||||
$element.on('mouseout', function() {
|
$element.on('mouseout', function() {
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
<section class="buttons" ng-if="::!$ctrl.treeview.readOnly">
|
<section class="buttons" ng-if="::!$ctrl.treeview.readOnly">
|
||||||
<vn-icon-button translate-attr="::{title: 'Remove'}"
|
<vn-icon-button translate-attr="::{title: 'Remove'}"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
ng-click="$ctrl.treeview.onRemove($ctrl.item)"
|
ng-click="$ctrl.treeview.onRemove($event, $ctrl.item)"
|
||||||
ng-if="$ctrl.item.parent">
|
ng-if="$ctrl.item.parent">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
<vn-icon-button translate-attr="::{title: 'Create'}"
|
<vn-icon-button translate-attr="::{title: 'Create'}"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.treeview.onCreate($ctrl.item)">
|
ng-click="$ctrl.treeview.onCreate($event, $ctrl.item)">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<ul ng-if="$ctrl.items">
|
<ul ng-if="$ctrl.items">
|
||||||
<li ng-repeat="item in $ctrl.items">
|
<li ng-repeat="item in $ctrl.items">
|
||||||
<vn-treeview-child item="item" ng-class="{expanded: item.active}"
|
<vn-treeview-child item="item" ng-class="{expanded: item.active}"
|
||||||
ng-click="$ctrl.onClick($event, item)">
|
ng-click="$ctrl.treeview.onToggle($event, item)">
|
||||||
</vn-treeview-child>
|
</vn-treeview-child>
|
||||||
<vn-treeview-childs
|
<vn-treeview-childs
|
||||||
items="item.childs">
|
items="item.childs">
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
import Component from '../../lib/component';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
class Controller {}
|
||||||
onClick(event, item) {
|
|
||||||
if (event.defaultPrevented || !item.sons) return;
|
|
||||||
event.preventDefault();
|
|
||||||
this.treeview.onToggle(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnTreeviewChilds', {
|
ngModule.component('vnTreeviewChilds', {
|
||||||
template: require('./childs.html'),
|
template: require('./childs.html'),
|
||||||
|
|
|
@ -141,7 +141,12 @@ export default class Treeview extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggle(item) {
|
onToggle(event, item) {
|
||||||
|
let ignoreEvent = event.defaultPrevented
|
||||||
|
|| event == this.lastActionEvent
|
||||||
|
|| !item.sons;
|
||||||
|
if (ignoreEvent) return;
|
||||||
|
|
||||||
if (item.active)
|
if (item.active)
|
||||||
this.fold(item);
|
this.fold(item);
|
||||||
else
|
else
|
||||||
|
@ -175,7 +180,8 @@ export default class Treeview extends Component {
|
||||||
}).then(() => item.active = true);
|
}).then(() => item.active = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(item) {
|
onRemove(event, item) {
|
||||||
|
this.lastActionEvent = event;
|
||||||
if (this.removeFunc)
|
if (this.removeFunc)
|
||||||
this.removeFunc({$item: item});
|
this.removeFunc({$item: item});
|
||||||
}
|
}
|
||||||
|
@ -191,7 +197,8 @@ export default class Treeview extends Component {
|
||||||
if (parent) parent.sons--;
|
if (parent) parent.sons--;
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreate(parent) {
|
onCreate(event, parent) {
|
||||||
|
this.lastActionEvent = event;
|
||||||
if (this.createFunc)
|
if (this.createFunc)
|
||||||
this.createFunc({$parent: parent});
|
this.createFunc({$parent: parent});
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,11 +102,16 @@ describe('Component vnTreeview', () => {
|
||||||
spyOn(controller, 'fold');
|
spyOn(controller, 'fold');
|
||||||
spyOn(controller, 'unfold');
|
spyOn(controller, 'unfold');
|
||||||
|
|
||||||
const item = {name: 'My item'};
|
let event = new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window
|
||||||
|
});
|
||||||
|
const item = {name: 'My item', sons: 1};
|
||||||
|
|
||||||
controller.onToggle(item);
|
controller.onToggle(event, item);
|
||||||
item.active = true;
|
item.active = true;
|
||||||
controller.onToggle(item);
|
controller.onToggle(event, item);
|
||||||
|
|
||||||
expect(controller.unfold).toHaveBeenCalledWith(item);
|
expect(controller.unfold).toHaveBeenCalledWith(item);
|
||||||
expect(controller.fold).toHaveBeenCalledWith(item);
|
expect(controller.fold).toHaveBeenCalledWith(item);
|
||||||
|
@ -148,9 +153,15 @@ describe('Component vnTreeview', () => {
|
||||||
|
|
||||||
describe('onRemove()', () => {
|
describe('onRemove()', () => {
|
||||||
it(`should call the removeFunc() method`, () => {
|
it(`should call the removeFunc() method`, () => {
|
||||||
|
let event = new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window
|
||||||
|
});
|
||||||
|
|
||||||
spyOn(controller, 'removeFunc');
|
spyOn(controller, 'removeFunc');
|
||||||
const item = {name: 'My item'};
|
const item = {name: 'My item'};
|
||||||
controller.onRemove(item);
|
controller.onRemove(event, item);
|
||||||
|
|
||||||
expect(controller.removeFunc).toHaveBeenCalledWith({$item: item});
|
expect(controller.removeFunc).toHaveBeenCalledWith({$item: item});
|
||||||
});
|
});
|
||||||
|
@ -172,9 +183,15 @@ describe('Component vnTreeview', () => {
|
||||||
|
|
||||||
describe('onCreate()', () => {
|
describe('onCreate()', () => {
|
||||||
it(`should call the createFunc() method`, () => {
|
it(`should call the createFunc() method`, () => {
|
||||||
|
let event = new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window
|
||||||
|
});
|
||||||
|
|
||||||
spyOn(controller, 'createFunc');
|
spyOn(controller, 'createFunc');
|
||||||
const parent = {name: 'My item'};
|
const parent = {name: 'My item'};
|
||||||
controller.onCreate(parent);
|
controller.onCreate(event, parent);
|
||||||
|
|
||||||
expect(controller.createFunc).toHaveBeenCalledWith({$parent: parent});
|
expect(controller.createFunc).toHaveBeenCalledWith({$parent: parent});
|
||||||
});
|
});
|
||||||
|
|
|
@ -181,7 +181,7 @@ export default class Watcher extends Component {
|
||||||
* Notifies the user that the data has been saved.
|
* Notifies the user that the data has been saved.
|
||||||
*/
|
*/
|
||||||
notifySaved() {
|
notifySaved() {
|
||||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
setPristine() {
|
setPristine() {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
<span
|
||||||
|
ng-repeat="day in $ctrl.days"
|
||||||
|
translate-attr="::{title: day.name}"
|
||||||
|
ng-class="{marked: $ctrl.field[day.code]}"
|
||||||
|
ng-click="$ctrl.field[day.code] = !$ctrl.field[day.code]">
|
||||||
|
{{day.localeChar}}
|
||||||
|
</span>
|
|
@ -0,0 +1,17 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import FormInput from '../form-input';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
export default class WdayPicker extends FormInput {
|
||||||
|
constructor($element, $scope, vnWeekDays) {
|
||||||
|
super($element, $scope);
|
||||||
|
this.days = vnWeekDays.locales;
|
||||||
|
this.initTabIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WdayPicker.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnWdayPicker', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: WdayPicker
|
||||||
|
});
|
|
@ -0,0 +1,27 @@
|
||||||
|
@import "effects";
|
||||||
|
|
||||||
|
vn-wday-picker {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: solid 1px rgba(0, 0, 0, .1);
|
||||||
|
}
|
||||||
|
& > span {
|
||||||
|
@extend %clickable;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: .4em;
|
||||||
|
margin: .2em;
|
||||||
|
display: inline-flex;
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
outline: none;
|
||||||
|
background-color: rgba(0, 0, 0, .05);
|
||||||
|
|
||||||
|
&.marked {
|
||||||
|
background: $color-main;
|
||||||
|
color: $color-font-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,15 +2,14 @@ import ngModule from '../module';
|
||||||
|
|
||||||
directive.$inject = ['$document'];
|
directive.$inject = ['$document'];
|
||||||
export function directive($document) {
|
export function directive($document) {
|
||||||
let modifiers = ["alt", "ctrl", "meta", "shift"];
|
let modifiers = ['alt', 'ctrl', 'meta', 'shift'];
|
||||||
|
|
||||||
function checkAttributes($attrs) {
|
function checkAttributes($attrs) {
|
||||||
let shortcut = $attrs.vnBind.split(' ');
|
let shortcut = $attrs.vnBind.split(' ');
|
||||||
let keys = {};
|
let keys = {};
|
||||||
|
|
||||||
if (shortcut[0] == "") {
|
if (shortcut[0] == '')
|
||||||
throw new Error('vnBind: Binding keys not defined');
|
throw new Error('vnBind: Binding keys not defined');
|
||||||
}
|
|
||||||
|
|
||||||
if (shortcut.length == 1) {
|
if (shortcut.length == 1) {
|
||||||
keys.altKey = true;
|
keys.altKey = true;
|
||||||
|
@ -41,7 +40,8 @@ export function directive($document) {
|
||||||
let correctShortcut = true;
|
let correctShortcut = true;
|
||||||
|
|
||||||
for (const key in shortcut) {
|
for (const key in shortcut) {
|
||||||
correctShortcut = correctShortcut && shortcut[key] == event[key];
|
correctShortcut = correctShortcut
|
||||||
|
&& shortcut[key] == event[key];
|
||||||
}
|
}
|
||||||
if (correctShortcut) {
|
if (correctShortcut) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -49,7 +49,7 @@ export function directive($document) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$document.on("keyup", onKeyUp);
|
$document.on('keyup', onKeyUp);
|
||||||
$element.on('$destroy', function() {
|
$element.on('$destroy', function() {
|
||||||
$document.off('keyup', onKeyUp);
|
$document.off('keyup', onKeyUp);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,11 +13,11 @@ export default function directive() {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function($scope, $element, $attrs) {
|
link: function($scope, $element, $attrs) {
|
||||||
$element.on('click', function(event) {
|
$element.on('click', function(event) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
let dialogKey = kebabToCamel($attrs.vnDialog);
|
let dialogKey = kebabToCamel($attrs.vnDialog);
|
||||||
let dialog = $scope[dialogKey];
|
let dialog = $scope[dialogKey];
|
||||||
if (dialog instanceof Dialog)
|
if (dialog instanceof Dialog)
|
||||||
dialog.show();
|
dialog.show();
|
||||||
event.preventDefault();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ import ngModule from '../module';
|
||||||
const regex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i;
|
const regex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i;
|
||||||
export const isMobile = regex.test(navigator.userAgent);
|
export const isMobile = regex.test(navigator.userAgent);
|
||||||
|
|
||||||
export function focus(input) {
|
export function focus($scope, input) {
|
||||||
if (isMobile) return;
|
if (isMobile) return;
|
||||||
|
|
||||||
const element = input;
|
const element = input;
|
||||||
|
@ -23,9 +23,9 @@ export function focus(input) {
|
||||||
}
|
}
|
||||||
|
|
||||||
input.focus();
|
input.focus();
|
||||||
|
$scope.$applyAsync(() => {
|
||||||
if (input.select)
|
|
||||||
input.select();
|
input.select();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,7 @@ export function directive() {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function($scope, $element) {
|
link: function($scope, $element) {
|
||||||
$scope.$watch('', () => focus($element[0]));
|
$scope.$watch('', () => focus($scope, $element[0]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,13 @@ export function directive() {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function($scope, $element, $attrs) {
|
link: function($scope, $element, $attrs) {
|
||||||
$element.on('click', function(event) {
|
$element.on('click', function(event) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
let popoverKey = kebabToCamel($attrs.vnPopover);
|
let popoverKey = kebabToCamel($attrs.vnPopover);
|
||||||
let popover = $scope[popoverKey];
|
let popover = $scope[popoverKey];
|
||||||
if (popover instanceof Popover) {
|
if (popover instanceof Popover) {
|
||||||
popover.parent = $element[0];
|
popover.parent = $element[0];
|
||||||
popover.show();
|
popover.show();
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,6 +40,7 @@ describe('Directive focus', () => {
|
||||||
it('should call select function on the element', () => {
|
it('should call select function on the element', () => {
|
||||||
let html = `<input vn-focus></input>`;
|
let html = `<input vn-focus></input>`;
|
||||||
compile(html);
|
compile(html);
|
||||||
|
$scope.$apply();
|
||||||
|
|
||||||
expect($element[0].select).toHaveBeenCalledWith();
|
expect($element[0].select).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,7 +44,7 @@ export function directive($timeout) {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function($scope, $element, $attrs) {
|
link: function($scope, $element, $attrs) {
|
||||||
$element.on('click', function(event) {
|
$element.on('click', function(event) {
|
||||||
event.preventDefault();
|
if (event.defaultPrevented) return;
|
||||||
|
|
||||||
let src = $attrs.zoomImage || $attrs.src;
|
let src = $attrs.zoomImage || $attrs.src;
|
||||||
if (src)
|
if (src)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import ngModule from '../module';
|
||||||
import EventEmitter from './event-emitter';
|
import EventEmitter from './event-emitter';
|
||||||
import {kebabToCamel} from './string';
|
import {kebabToCamel} from './string';
|
||||||
|
|
||||||
|
@ -44,5 +45,30 @@ export default class Component extends EventEmitter {
|
||||||
get document() {
|
get document() {
|
||||||
return this.element.ownerDocument;
|
return this.element.ownerDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates an string.
|
||||||
|
*
|
||||||
|
* @param {String} string String to translate
|
||||||
|
* @param {Array} params Translate parameters
|
||||||
|
* @return {String} The translated string
|
||||||
|
*/
|
||||||
|
$t(string, params) {
|
||||||
|
return this.$translate.instant(string, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component.$inject = ['$element', '$scope'];
|
Component.$inject = ['$element', '$scope'];
|
||||||
|
|
||||||
|
function runFn($translate, $q, $http, vnApp, $state, $stateParams) {
|
||||||
|
Object.assign(Component.prototype, {
|
||||||
|
$translate,
|
||||||
|
$q,
|
||||||
|
$http,
|
||||||
|
vnApp,
|
||||||
|
$state,
|
||||||
|
$params: $stateParams
|
||||||
|
});
|
||||||
|
}
|
||||||
|
runFn.$inject = ['$translate', '$q', '$http', 'vnApp', '$state', '$stateParams'];
|
||||||
|
|
||||||
|
ngModule.run(runFn);
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import Component from './component';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class with commonly injected services assigned as properties. It also has
|
|
||||||
* abbreviations for commonly used methods like tranlation.
|
|
||||||
*
|
|
||||||
* @property {Object} $translate Angular tranlation service
|
|
||||||
* @property {Object} $http Angular HTTP service
|
|
||||||
* @property {Object} $state Router state service
|
|
||||||
* @property {Object} $stateParams Router state parameters
|
|
||||||
*/
|
|
||||||
export default class Section extends Component {
|
|
||||||
constructor($element, $scope, $translate, $http, $state) {
|
|
||||||
super($element, $scope);
|
|
||||||
Object.assign(this, {
|
|
||||||
$translate,
|
|
||||||
$http,
|
|
||||||
$state,
|
|
||||||
$stateParams: $state.params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates an string.
|
|
||||||
*
|
|
||||||
* @param {String} string String to translate
|
|
||||||
* @param {Array} params Translate parameters
|
|
||||||
* @return {String} The translated string
|
|
||||||
*/
|
|
||||||
_(string, params) {
|
|
||||||
return this.$translate.instant(string, params, );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Section.$inject = ['$element', '$scope', '$translate', '$http', '$state'];
|
|
|
@ -4,10 +4,12 @@ class AclService {
|
||||||
constructor($http) {
|
constructor($http) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.user = null;
|
this.user = null;
|
||||||
this.roles = null;
|
this.roles = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
return this.$http.get('/api/Accounts/acl').then(res => {
|
return this.$http.get('/api/Accounts/acl').then(res => {
|
||||||
this.user = res.data.user;
|
this.user = res.data.user;
|
||||||
|
@ -19,6 +21,7 @@ class AclService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasAny(roles) {
|
hasAny(roles) {
|
||||||
if (this.roles) {
|
if (this.roles) {
|
||||||
for (let role of roles) {
|
for (let role of roles) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ export default class Auth {
|
||||||
loggedIn: false
|
loggedIn: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
let criteria = {
|
let criteria = {
|
||||||
to: state => state.name != 'login'
|
to: state => state.name != 'login'
|
||||||
|
@ -42,6 +43,7 @@ export default class Auth {
|
||||||
return redirectToLogin();
|
return redirectToLogin();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
login(user, password, remember) {
|
login(user, password, remember) {
|
||||||
if (!user)
|
if (!user)
|
||||||
return this.$q.reject(new UserError('Please enter your username'));
|
return this.$q.reject(new UserError('Please enter your username'));
|
||||||
|
@ -54,6 +56,7 @@ export default class Auth {
|
||||||
return this.$http.post('/api/Accounts/login', params).then(
|
return this.$http.post('/api/Accounts/login', params).then(
|
||||||
json => this.onLoginOk(json, remember));
|
json => this.onLoginOk(json, remember));
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoginOk(json, remember) {
|
onLoginOk(json, remember) {
|
||||||
this.vnToken.set(json.data.token, remember);
|
this.vnToken.set(json.data.token, remember);
|
||||||
|
|
||||||
|
@ -65,6 +68,7 @@ export default class Auth {
|
||||||
this.$state.go('home');
|
this.$state.go('home');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
let promise = this.$http.post('/api/Accounts/logout', null, {
|
let promise = this.$http.post('/api/Accounts/logout', null, {
|
||||||
headers: {Authorization: this.vnToken.token}
|
headers: {Authorization: this.vnToken.token}
|
||||||
|
@ -78,6 +82,7 @@ export default class Auth {
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAcls() {
|
loadAcls() {
|
||||||
return this.aclService.load()
|
return this.aclService.load()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
@ -6,3 +6,4 @@ import './token';
|
||||||
import './modules';
|
import './modules';
|
||||||
import './interceptor';
|
import './interceptor';
|
||||||
import './config';
|
import './config';
|
||||||
|
import './week-days';
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
class WeekDays {
|
||||||
|
constructor($translate) {
|
||||||
|
this.$translate = $translate;
|
||||||
|
|
||||||
|
this.days = [
|
||||||
|
{
|
||||||
|
code: 'sun',
|
||||||
|
name: 'Sunday'
|
||||||
|
}, {
|
||||||
|
code: 'mon',
|
||||||
|
name: 'Monday'
|
||||||
|
}, {
|
||||||
|
code: 'tue',
|
||||||
|
name: 'Tuesday'
|
||||||
|
}, {
|
||||||
|
code: 'wed',
|
||||||
|
name: 'Wednesday'
|
||||||
|
}, {
|
||||||
|
code: 'thu',
|
||||||
|
name: 'Thursday'
|
||||||
|
}, {
|
||||||
|
code: 'fri',
|
||||||
|
name: 'Friday'
|
||||||
|
}, {
|
||||||
|
code: 'sat',
|
||||||
|
name: 'Saturday'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.map = {};
|
||||||
|
for (let i = 0; i < this.days.length; i++) {
|
||||||
|
let day = this.days[i];
|
||||||
|
day.index = i;
|
||||||
|
day.char = day.name.substr(0, 1);
|
||||||
|
day.abr = day.name.substr(0, 3);
|
||||||
|
this.map[day.code] = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getLocales();
|
||||||
|
}
|
||||||
|
|
||||||
|
getLocales() {
|
||||||
|
for (let day of this.days) {
|
||||||
|
let locale = this.$translate.instant(day.name);
|
||||||
|
Object.assign(day, {
|
||||||
|
locale,
|
||||||
|
localeChar: locale.substr(0, 1),
|
||||||
|
localeAbr: locale.substr(0, 3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.localeCodes = [
|
||||||
|
'mon',
|
||||||
|
'tue',
|
||||||
|
'wed',
|
||||||
|
'thu',
|
||||||
|
'fri',
|
||||||
|
'sat',
|
||||||
|
'sun'
|
||||||
|
];
|
||||||
|
|
||||||
|
this.locales = [];
|
||||||
|
for (let code of this.localeCodes)
|
||||||
|
this.locales.push(this.map[code]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WeekDays.$inject = ['$translate'];
|
||||||
|
|
||||||
|
ngModule.service('vnWeekDays', WeekDays);
|
|
@ -1,9 +1,12 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
html, body {
|
html {
|
||||||
background-color: $color-bg;
|
background-color: $color-bg;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
font-family: vn-font;
|
font-family: vn-font;
|
||||||
color: $color-font;
|
color: $color-font;
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
|
|
|
@ -42,13 +42,13 @@
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: .2em;
|
margin-bottom: .3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Colors */
|
/* Colors */
|
||||||
|
|
||||||
.text-primary {
|
.text-primary {
|
||||||
color: $color-font;
|
color: $color-main;
|
||||||
}
|
}
|
||||||
.text-secondary {
|
.text-secondary {
|
||||||
color: $color-font-secondary;
|
color: $color-font-secondary;
|
||||||
|
|
|
@ -25,4 +25,5 @@
|
||||||
ng-class="{padding: $ctrl.showTopbar}">
|
ng-class="{padding: $ctrl.showTopbar}">
|
||||||
<vn-home></vn-home>
|
<vn-home></vn-home>
|
||||||
</div>
|
</div>
|
||||||
<vn-snackbar vn-id="snackbar"></vn-snackbar>
|
<vn-snackbar vn-id="snackbar"></vn-snackbar>
|
||||||
|
<vn-debug-info></vn-debug-info>
|
|
@ -1,7 +1,7 @@
|
||||||
<a ng-if="$ctrl.links.btnOne"
|
<a ng-if="$ctrl.links.btnOne"
|
||||||
vn-tooltip="{{::$ctrl.links.btnOne.tooltip}}"
|
vn-tooltip="{{::$ctrl.links.btnOne.tooltip}}"
|
||||||
class="vn-button colored"
|
class="vn-button colored"
|
||||||
ui-sref="{{::$ctrl.links.btnOne.state}}" target="_blank">
|
ui-sref="{{::$ctrl.links.btnOne.state}}">
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="{{::$ctrl.links.btnOne.icon}}">
|
icon="{{::$ctrl.links.btnOne.icon}}">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
<a ng-if="$ctrl.links.btnTwo"
|
<a ng-if="$ctrl.links.btnTwo"
|
||||||
vn-tooltip="{{::$ctrl.links.btnTwo.tooltip}}"
|
vn-tooltip="{{::$ctrl.links.btnTwo.tooltip}}"
|
||||||
class="vn-button colored"
|
class="vn-button colored"
|
||||||
ui-sref="{{::$ctrl.links.btnTwo.state}}" target="_blank">
|
ui-sref="{{::$ctrl.links.btnTwo.state}}">
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="{{::$ctrl.links.btnTwo.icon}}">
|
icon="{{::$ctrl.links.btnTwo.icon}}">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<a ng-if="$ctrl.links.btnThree"
|
<a ng-if="$ctrl.links.btnThree"
|
||||||
vn-tooltip="{{::$ctrl.links.btnThree.tooltip}}"
|
vn-tooltip="{{::$ctrl.links.btnThree.tooltip}}"
|
||||||
class="vn-button colored"
|
class="vn-button colored"
|
||||||
ui-sref="{{::$ctrl.links.btnThree.state}}" target="_blank">
|
ui-sref="{{::$ctrl.links.btnThree.state}}">
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="{{::$ctrl.links.btnThree.icon}}">
|
icon="{{::$ctrl.links.btnThree.icon}}">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller extends Component {
|
||||||
constructor(vnModules, $state, $translate, $sce) {
|
constructor($element, $, vnModules, $sce) {
|
||||||
|
super($element, $);
|
||||||
this.modules = vnModules.get();
|
this.modules = vnModules.get();
|
||||||
this.$state = $state;
|
|
||||||
this._ = $translate;
|
|
||||||
this.$sce = $sce;
|
this.$sce = $sce;
|
||||||
}
|
}
|
||||||
|
|
||||||
getModuleName(mod) {
|
getModuleName(mod) {
|
||||||
let getName = mod => {
|
let getName = mod => {
|
||||||
let name = this._.instant(mod.name);
|
let name = this.$t(mod.name);
|
||||||
let upper = name.toUpperCase();
|
let upper = name.toUpperCase();
|
||||||
if (!mod.keyBind) return name;
|
if (!mod.keyBind) return name;
|
||||||
let index = upper.indexOf(mod.keyBind);
|
let index = upper.indexOf(mod.keyBind);
|
||||||
|
@ -25,8 +26,7 @@ export default class Controller {
|
||||||
return this.$sce.trustAsHtml(getName(mod));
|
return this.$sce.trustAsHtml(getName(mod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnModules', '$sce'];
|
||||||
Controller.$inject = ['vnModules', '$state', '$translate', '$sce'];
|
|
||||||
|
|
||||||
ngModule.component('vnHome', {
|
ngModule.component('vnHome', {
|
||||||
template: require('./home.html'),
|
template: require('./home.html'),
|
||||||
|
|
|
@ -18,6 +18,9 @@ vn-main-menu {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-right: .2em;
|
margin-right: .2em;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
& > .vn-button {
|
& > .vn-button {
|
||||||
|
|
|
@ -39,7 +39,6 @@ export default class SideMenu {
|
||||||
|
|
||||||
onEscape(event) {
|
onEscape(event) {
|
||||||
if (!event.defaultPrevented && event.key == 'Escape') {
|
if (!event.defaultPrevented && event.key == 'Escape') {
|
||||||
event.preventDefault();
|
|
||||||
this.hide();
|
this.hide();
|
||||||
this.$.$digest();
|
this.$.$digest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,50 +4,48 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 950px;
|
max-width: 950px;
|
||||||
|
|
||||||
& > div {
|
& > h5 {
|
||||||
& > h5 {
|
padding: $spacing-sm;
|
||||||
padding: $spacing-sm;
|
border: none;
|
||||||
border: none;
|
background: $color-main;
|
||||||
background: $color-main;
|
color: $color-font-dark;
|
||||||
color: $color-font-dark;
|
margin: 0;
|
||||||
margin: 0;
|
text-align: center;
|
||||||
text-align: center;
|
line-height: 1.3em;
|
||||||
line-height: 1.3em;
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
& > vn-horizontal {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: $spacing-md;
|
||||||
|
overflow: hidden;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-bottom: $spacing-md;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 15pt;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 7px;
|
||||||
|
padding-bottom: 4px; /* Bottom line-height fix */
|
||||||
|
font-weight: lighter;
|
||||||
|
background-color: $color-main-light;
|
||||||
|
border-bottom: .1em solid $color-main;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
& > vn-horizontal {
|
& > * {
|
||||||
flex-wrap: wrap;
|
margin: $spacing-sm;
|
||||||
padding: $spacing-md;
|
min-width: 14em;
|
||||||
overflow: hidden;
|
padding: 0;
|
||||||
align-items: flex-start;
|
}
|
||||||
|
& > vn-auto {
|
||||||
h4 {
|
width: 100%;
|
||||||
margin-bottom: $spacing-md;
|
}
|
||||||
text-transform: uppercase;
|
vn-label-value > section {
|
||||||
font-size: 15pt;
|
margin-bottom: .3em;
|
||||||
line-height: 1;
|
|
||||||
padding: 7px;
|
|
||||||
padding-bottom: 4px; /* Bottom line-height fix */
|
|
||||||
font-weight: lighter;
|
|
||||||
background-color: $color-main-light;
|
|
||||||
border-bottom: .1em solid $color-main;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
& > * {
|
|
||||||
margin: $spacing-sm;
|
|
||||||
min-width: 14em;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
& > vn-auto {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
vn-label-value > section {
|
|
||||||
margin-bottom: .3em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p:after {
|
p:after {
|
||||||
|
|
|
@ -61,11 +61,11 @@ vn-bg-title {
|
||||||
}
|
}
|
||||||
.totalBox {
|
.totalBox {
|
||||||
border: 1px solid #CCC;
|
border: 1px solid #CCC;
|
||||||
text-align: right !important;
|
text-align: right;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 18px;
|
padding: $spacing-md;
|
||||||
max-width: 12em;
|
max-width: 14em;
|
||||||
}
|
}
|
||||||
.form {
|
.form {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
width: 28em;
|
width: 28em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
& > vn-card > div {
|
& > vn-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 12em;
|
height: 12em;
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
<vn-calendar
|
<vn-card>
|
||||||
vn-id="stMonth"
|
<div class="header">
|
||||||
skip="2"
|
<vn-button
|
||||||
has-events="$ctrl.hasEvents($day)"
|
icon="navigate_before"
|
||||||
get-class="$ctrl.getClass($day)"
|
ng-click="$ctrl.step(-1)"
|
||||||
on-selection="$ctrl.onSelection($days, $type, $weekday)"
|
class="flat">
|
||||||
on-move-next="ndMonth.moveNext(2)"
|
</vn-button>
|
||||||
on-move-previous="ndMonth.movePrevious(2)"
|
<span>{{$ctrl.firstDay | date:'MMMM yyyy'}} - {{$ctrl.lastDay | date:'MMMM yyyy'}}</span>
|
||||||
vn-acl="deliveryBoss"
|
<vn-button
|
||||||
class="vn-pa-md">
|
icon="navigate_next"
|
||||||
</vn-calendar>
|
ng-click="$ctrl.step(1)"
|
||||||
<vn-calendar
|
class="flat">
|
||||||
vn-id="ndMonth"
|
</vn-button>
|
||||||
skip="2"
|
</div>
|
||||||
has-events="$ctrl.hasEvents($day)"
|
<div class="calendars vn-pa-md">
|
||||||
get-class="$ctrl.getClass($day)"
|
<vn-calendar
|
||||||
on-selection="$ctrl.onSelection($days, $type, $weekday)"
|
ng-repeat="date in $ctrl.months track by date.getTime()"
|
||||||
default-date="$ctrl.ndMonthDate"
|
default-date="date"
|
||||||
vn-acl="deliveryBoss"
|
display-controls="false"
|
||||||
display-controls="false"
|
hide-contiguous="true"
|
||||||
class="vn-pa-md">
|
has-events="$ctrl.hasEvents($day)"
|
||||||
</vn-calendar>
|
get-class="$ctrl.getClass($day)"
|
||||||
|
on-selection="$ctrl.onSelection($days, $type, $weekday)"
|
||||||
|
class="vn-pa-md"
|
||||||
|
style="min-width: 250px; flex: 1;">
|
||||||
|
</vn-calendar>
|
||||||
|
</div>
|
||||||
|
</vn-card>
|
|
@ -1,100 +1,155 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'core/lib/section';
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Component {
|
||||||
constructor($el, $, $t, $http, $state) {
|
constructor($element, $) {
|
||||||
super($el, $, $t, $http, $state);
|
super($element, $);
|
||||||
|
this.nMonths = 4;
|
||||||
|
|
||||||
this.excls = {};
|
let date = new Date();
|
||||||
this.resetEvents();
|
date.setDate(1);
|
||||||
this.ndMonthDate = new Date();
|
date.setHours(0, 0, 0, 0);
|
||||||
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get date() {
|
||||||
|
return this._date;
|
||||||
|
}
|
||||||
|
|
||||||
|
set date(value) {
|
||||||
|
this._date = value;
|
||||||
|
let stamp = value.getTime();
|
||||||
|
|
||||||
|
let firstDay = new Date(stamp);
|
||||||
|
firstDay.setDate(1);
|
||||||
|
this.firstDay = firstDay;
|
||||||
|
|
||||||
|
let lastDay = new Date(stamp);
|
||||||
|
lastDay.setMonth(lastDay.getMonth() + this.nMonths);
|
||||||
|
lastDay.setDate(0);
|
||||||
|
this.lastDay = lastDay;
|
||||||
|
|
||||||
|
this.months = [];
|
||||||
|
for (let i = 0; i < this.nMonths; i++) {
|
||||||
|
let monthDate = new Date(stamp);
|
||||||
|
monthDate.setMonth(value.getMonth() + i);
|
||||||
|
this.months.push(monthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
step(direction) {
|
||||||
|
let date = new Date(this.date.getTime());
|
||||||
|
date.setMonth(date.getMonth() + (this.nMonths * direction));
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
set data(value) {
|
||||||
|
this._data = value;
|
||||||
|
|
||||||
|
value = value || {};
|
||||||
|
this.events = value.events;
|
||||||
|
this.exclusions = value.exclusions;
|
||||||
|
|
||||||
|
if (this.events) {
|
||||||
|
let codes = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
|
for (event of this.events) {
|
||||||
|
if (!event.weekDays) continue;
|
||||||
|
let weekDays = event.weekDays.split(',');
|
||||||
|
event.wdays = [];
|
||||||
|
for (let wday of weekDays) {
|
||||||
|
let index = codes.indexOf(wday);
|
||||||
|
if (index !== -1) event.wdays[index] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshEvents();
|
||||||
|
|
||||||
|
let calendars = this.element.querySelectorAll('vn-calendar');
|
||||||
|
for (let calendar of calendars)
|
||||||
|
calendar.$ctrl.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshEvents() {
|
||||||
|
function getDate(date) {
|
||||||
|
return date && new Date(date).setHours(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let exclusionsMap = {};
|
||||||
|
if (this.exclusions) {
|
||||||
|
for (let exclusion of this.exclusions)
|
||||||
|
exclusionsMap[getDate(exclusion.day)] = exclusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.days = {};
|
||||||
|
let day = new Date(this.firstDay.getTime());
|
||||||
|
|
||||||
|
while (day < this.lastDay) {
|
||||||
|
let stamp = day.getTime();
|
||||||
|
let wday = day.getDay();
|
||||||
|
let dayEvents = [];
|
||||||
|
|
||||||
|
if (this.events) {
|
||||||
|
for (let event of this.events) {
|
||||||
|
let match;
|
||||||
|
let from = getDate(event.from);
|
||||||
|
let to = getDate(event.to);
|
||||||
|
|
||||||
|
if (event.from && event.to) {
|
||||||
|
match = stamp >= from && stamp <= to
|
||||||
|
&& event.wdays[wday];
|
||||||
|
} else if (event.from)
|
||||||
|
match = from == stamp;
|
||||||
|
else
|
||||||
|
match = event.wdays[wday];
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
dayEvents.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let exclusion = exclusionsMap[stamp];
|
||||||
|
|
||||||
|
if (dayEvents.length || exclusion) {
|
||||||
|
let dayData = {};
|
||||||
|
if (dayEvents.length) dayData.events = dayEvents;
|
||||||
|
if (exclusion) dayData.exclusion = exclusion;
|
||||||
|
this.days[stamp] = dayData;
|
||||||
|
}
|
||||||
|
|
||||||
|
day.setDate(day.getDate() + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelection($days, $type, $weekday) {
|
onSelection($days, $type, $weekday) {
|
||||||
this.emit('selection', {$days, $type, $weekday});
|
let $data = [];
|
||||||
}
|
for (let day of $days) {
|
||||||
|
let dayData = this.days[day.getTime()];
|
||||||
resetEvents() {
|
if (dayData) $data.push(dayData);
|
||||||
this.wdays = [];
|
|
||||||
this.days = {};
|
|
||||||
this.ranges = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
get events() {
|
|
||||||
return this._events;
|
|
||||||
}
|
|
||||||
|
|
||||||
set events(value) {
|
|
||||||
this._events = value;
|
|
||||||
this.resetEvents();
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
function setWdays(wdays, weekDays) {
|
|
||||||
let codes = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
||||||
if (!weekDays) return [];
|
|
||||||
weekDays = weekDays.split(',');
|
|
||||||
for (let wday of weekDays)
|
|
||||||
wdays[codes.indexOf(wday)] = true;
|
|
||||||
return wdays;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let event of value) {
|
this.emit('selection', {
|
||||||
if (event.from && event.to) {
|
$days,
|
||||||
this.ranges.push({
|
$type,
|
||||||
from: new Date(event.from).setHours(0, 0, 0, 0),
|
$weekday,
|
||||||
to: new Date(event.to).setHours(0, 0, 0, 0),
|
$data
|
||||||
wdays: setWdays([], event.weekDays)
|
|
||||||
});
|
|
||||||
} else if (event.from) {
|
|
||||||
let day = new Date(event.from).setHours(0, 0, 0, 0);
|
|
||||||
this.days[day] = true;
|
|
||||||
} else
|
|
||||||
setWdays(this.wdays, event.weekDays);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
get exclusions() {
|
|
||||||
return this._exclusions;
|
|
||||||
}
|
|
||||||
|
|
||||||
set exclusions(value) {
|
|
||||||
this._exclusions = value;
|
|
||||||
this.excls = {};
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
value.forEach(exclusion => {
|
|
||||||
let day = new Date(exclusion.day).setHours(0, 0, 0, 0);
|
|
||||||
this.excls[day] = true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
hasRange(time, wday) {
|
|
||||||
let range = this.ranges.find(e => e.from <= time && e.to >= time);
|
|
||||||
return range && range.wdays[wday];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEvents(day) {
|
hasEvents(day) {
|
||||||
let time = day.getTime();
|
return this.days[day.getTime()] != null;
|
||||||
let wday = day.getDay();
|
|
||||||
return this.wdays[wday]
|
|
||||||
|| this.days[time]
|
|
||||||
|| this.hasRange(time, wday);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getClass(day) {
|
getClass(day) {
|
||||||
if (this.excls[day.getTime()])
|
let dayData = this.days[day.getTime()];
|
||||||
return 'excluded';
|
return dayData && dayData.exclusion ? 'excluded' : '';
|
||||||
}
|
|
||||||
|
|
||||||
repaint() {
|
|
||||||
this.$.stMonth.repaint();
|
|
||||||
this.$.ndMonth.repaint();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +157,6 @@ ngModule.component('vnZoneCalendar', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
events: '<?',
|
data: '<?'
|
||||||
exclusions: '<?'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,40 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
vn-zone-calendar {
|
vn-zone-calendar {
|
||||||
vn-calendar .day {
|
display: block;
|
||||||
&.primary .day-number {
|
|
||||||
background-color: $color-success;
|
& > vn-card {
|
||||||
|
& > .header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: $color-main;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 45px;
|
||||||
|
|
||||||
|
& > .vn-button {
|
||||||
|
color: inherit;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.excluded .day-number {
|
& > .calendars {
|
||||||
background-color: $color-alert;
|
display: flex;
|
||||||
color: $color-font-dark;
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
& > vn-calendar {
|
||||||
|
max-width: 18em;
|
||||||
|
|
||||||
|
.day {
|
||||||
|
&.event .day-number {
|
||||||
|
background-color: $color-success;
|
||||||
|
}
|
||||||
|
&.excluded .day-number {
|
||||||
|
background-color: $color-alert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,47 +1,43 @@
|
||||||
<div style="margin: 0 auto; max-width: 40em;">
|
<div class="vn-w-md">
|
||||||
<form ng-submit="$ctrl.onSubmit()">
|
<form ng-submit="$ctrl.onSubmit()">
|
||||||
<vn-card class="vn-pa-md">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-vertical>
|
<vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-autocomplete
|
||||||
<vn-autocomplete
|
vn-one
|
||||||
vn-one
|
label="Agency"
|
||||||
label="Agency"
|
ng-model="$ctrl.params.agencyModeFk"
|
||||||
ng-model="$ctrl.params.agencyModeFk"
|
url="/api/AgencyModes/isActive">
|
||||||
url="/api/AgencyModes/isActive">
|
</vn-autocomplete>
|
||||||
</vn-autocomplete>
|
</vn-horizontal>
|
||||||
</vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-autocomplete
|
||||||
<vn-autocomplete
|
vn-one
|
||||||
vn-one
|
label="Province"
|
||||||
label="Province"
|
ng-model="$ctrl.params.provinceFk"
|
||||||
ng-model="$ctrl.params.provinceFk"
|
url="/api/Provinces"
|
||||||
url="/api/Provinces"
|
fields="['countryFk']"
|
||||||
fields="['countryFk']"
|
include="'country'"
|
||||||
include="'country'"
|
style="margin-right: .5em;">
|
||||||
style="margin-right: .5em;">
|
<tpl-item>
|
||||||
<tpl-item>
|
<div>{{name}}</div>
|
||||||
<div>{{name}}</div>
|
<div style="font-size: .9em; color: gray; line-height: .8em;">
|
||||||
<div style="font-size: .9em; color: gray; line-height: .8em;">
|
{{country.country}}
|
||||||
{{country.country}}
|
</div>
|
||||||
</div>
|
</tpl-item>
|
||||||
</tpl-item>
|
</vn-autocomplete>
|
||||||
</vn-autocomplete>
|
<vn-textfield
|
||||||
<vn-textfield
|
vn-one
|
||||||
vn-one
|
label="Postcode"
|
||||||
label="Postcode"
|
ng-model="$ctrl.params.postCode">
|
||||||
ng-model="$ctrl.params.postCode">
|
</vn-textfield>
|
||||||
</vn-textfield>
|
</vn-horizontal>
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
<vn-submit label="Query"></vn-submit>
|
<vn-submit label="Query"></vn-submit>
|
||||||
</vn-button-bar>
|
</vn-button-bar>
|
||||||
</form>
|
</form>
|
||||||
<vn-card class="vn-pa-md vn-mt-md">
|
<vn-zone-calendar
|
||||||
<vn-zone-calendar
|
data="data"
|
||||||
events="events.events"
|
class="vn-mt-md">
|
||||||
exclusions="events.exclusions">
|
</vn-zone-calendar>
|
||||||
</vn-zone-calendar>
|
|
||||||
</vn-card>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Controller {
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$http.get(`/api/Zones/getEvents`, {params: this.params})
|
this.$http.get(`/api/Zones/getEvents`, {params: this.params})
|
||||||
.then(res => this.$.events = res.data);
|
.then(res => this.$.data = res.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$scope', '$http'];
|
Controller.$inject = ['$scope', '$http'];
|
||||||
|
|
|
@ -1,27 +1,60 @@
|
||||||
<div class="main-with-right-menu">
|
<div class="main-with-right-menu">
|
||||||
<vn-data-viewer
|
<vn-zone-calendar
|
||||||
|
id="calendar"
|
||||||
data="data"
|
data="data"
|
||||||
is-loading="!data"
|
on-selection="$ctrl.onSelection($days, $type, $weekday, $data)"
|
||||||
|
class="vn-w-md">
|
||||||
|
</vn-zone-calendar>
|
||||||
|
</div>
|
||||||
|
<vn-side-menu side="right">
|
||||||
|
<div class="vn-pa-md">
|
||||||
|
<h6
|
||||||
|
class="text-secondary"
|
||||||
|
style="font-weight: normal;"
|
||||||
|
translate>
|
||||||
|
Edit mode
|
||||||
|
</h6>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-radio
|
||||||
|
label="Include"
|
||||||
|
val="include"
|
||||||
|
ng-model="$ctrl.editMode">
|
||||||
|
</vn-radio>
|
||||||
|
<vn-radio
|
||||||
|
label="Exclude"
|
||||||
|
val="exclude"
|
||||||
|
ng-model="$ctrl.editMode">
|
||||||
|
</vn-radio>
|
||||||
|
</vn-vertical>
|
||||||
|
</div>
|
||||||
|
<h6
|
||||||
|
class="text-secondary vn-px-md"
|
||||||
|
style="font-weight: normal;"
|
||||||
|
translate>
|
||||||
|
Events
|
||||||
|
</h6>
|
||||||
|
<vn-data-viewer
|
||||||
|
data="data.events"
|
||||||
|
is-loading="!data.events"
|
||||||
class="vn-w-sm">
|
class="vn-w-sm">
|
||||||
<vn-card>
|
|
||||||
<div class="vn-list">
|
<div class="vn-list">
|
||||||
<a
|
<a
|
||||||
ng-repeat="row in data"
|
ng-repeat="row in data.events"
|
||||||
translate-attr="{title: 'Edit'}"
|
translate-attr="{title: 'Edit'}"
|
||||||
ng-click="$ctrl.onEdit(row, $event)"
|
ng-click="$ctrl.onEditClick(row, $event)"
|
||||||
class="vn-list-item">
|
class="vn-list-item">
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<div
|
<div
|
||||||
ng-if="::row.from && !row.to"
|
ng-if="::row.from && !row.to"
|
||||||
class="vn-mb-sm">
|
class="vn-mb-sm">
|
||||||
{{::row.from | date:'dd/MM/yyyy'}}
|
{{::row.from | date:'dd/MM/yy'}}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ng-if="::!row.from || row.to"
|
ng-if="::!row.from || row.to"
|
||||||
class="vn-mb-sm">
|
class="vn-mb-sm ellipsize">
|
||||||
<span ng-if="row.to">
|
<span ng-if="row.to">
|
||||||
{{::row.from | date:'dd/MM/yyyy'}} - {{::row.to | date:'dd/MM/yyyy'}}
|
{{::row.from | date:'dd/MM/yy'}} - {{::row.to | date:'dd/MM/yy'}}
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="!row.to" translate>
|
<span ng-if="!row.to" translate>
|
||||||
Indefinitely
|
Indefinitely
|
||||||
|
@ -51,21 +84,13 @@
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
icon="delete"
|
icon="delete"
|
||||||
translate-attr="{title: 'Delete'}"
|
translate-attr="{title: 'Delete'}"
|
||||||
ng-click="$ctrl.onDelete(row.id, $event)">
|
ng-click="$ctrl.onDeleteClick(row.id, $event)">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
</vn-data-viewer>
|
||||||
</div>
|
|
||||||
<vn-side-menu side="right">
|
|
||||||
<vn-zone-calendar
|
|
||||||
events="data"
|
|
||||||
exclusions="exclusions"
|
|
||||||
on-selection="$ctrl.onCreate($days, $type, $weekday)">
|
|
||||||
</vn-zone-calendar>
|
|
||||||
</vn-side-menu>
|
</vn-side-menu>
|
||||||
<vn-dialog
|
<vn-dialog
|
||||||
vn-id="dialog"
|
vn-id="dialog"
|
||||||
|
@ -89,16 +114,11 @@
|
||||||
val="range">
|
val="range">
|
||||||
</vn-radio>
|
</vn-radio>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
<div
|
<vn-wday-picker
|
||||||
ng-if="$ctrl.eventType != 'day'"
|
ng-if="$ctrl.eventType != 'day'"
|
||||||
class="week-days">
|
ng-model="$ctrl.selected.wdays"
|
||||||
<span
|
class="vn-mt-sm vn-mb-md">
|
||||||
ng-repeat="wday in $ctrl.wdays"
|
</vn-wday-picker>
|
||||||
ng-class="{marked: $ctrl.selected.wdays[wday.code]}"
|
|
||||||
ng-click="$ctrl.selected.wdays[wday.code] = !$ctrl.selected.wdays[wday.code]">
|
|
||||||
{{wday.abr}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
ng-if="$ctrl.eventType == 'day'"
|
ng-if="$ctrl.eventType == 'day'"
|
||||||
label="Day"
|
label="Day"
|
||||||
|
@ -140,8 +160,21 @@
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
<tpl-buttons>
|
<tpl-buttons>
|
||||||
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
|
<input
|
||||||
<button response="ACCEPT" translate>Save</button>
|
type="button"
|
||||||
|
response="CANCEL"
|
||||||
|
translate-attr="{value: 'Cancel'}">
|
||||||
|
</input>
|
||||||
|
<button
|
||||||
|
ng-if="!$ctrl.isNew"
|
||||||
|
response="DELETE"
|
||||||
|
translate>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
<button response="ACCEPT">
|
||||||
|
<span ng-if="$ctrl.isNew" translate>Add</span>
|
||||||
|
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
||||||
|
</button>
|
||||||
</tpl-buttons>
|
</tpl-buttons>
|
||||||
</vn-dialog>
|
</vn-dialog>
|
||||||
<vn-confirm
|
<vn-confirm
|
||||||
|
|
|
@ -1,53 +1,27 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'core/lib/section';
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Component {
|
||||||
constructor($el, $, $t, $http, $state) {
|
constructor($element, $, vnWeekDays) {
|
||||||
super($el, $, $t, $http, $state);
|
super($element, $);
|
||||||
|
this.vnWeekDays = vnWeekDays;
|
||||||
|
this.editMode = 'include';
|
||||||
|
|
||||||
this.wdays = [
|
this.path = `api/Zones/${this.$params.id}/events`;
|
||||||
{
|
this.exclusionsPath = `api/Zones/${this.$params.id}/exclusions`;
|
||||||
code: 'mon',
|
|
||||||
name: 'Monday'
|
|
||||||
}, {
|
|
||||||
code: 'tue',
|
|
||||||
name: 'Tuesday'
|
|
||||||
}, {
|
|
||||||
code: 'wed',
|
|
||||||
name: 'Wednesday'
|
|
||||||
}, {
|
|
||||||
code: 'thu',
|
|
||||||
name: 'Thursday'
|
|
||||||
}, {
|
|
||||||
code: 'fri',
|
|
||||||
name: 'Friday'
|
|
||||||
}, {
|
|
||||||
code: 'sat',
|
|
||||||
name: 'Saturday'
|
|
||||||
}, {
|
|
||||||
code: 'sun',
|
|
||||||
name: 'Sunday'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
this.abrWdays = {};
|
|
||||||
for (let wday of this.wdays) {
|
|
||||||
let locale = this._(wday.name);
|
|
||||||
this.abrWdays[wday.code] = locale.substr(0, 3);
|
|
||||||
wday.abr = locale.substr(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$http.get(`/api/Zones/${this.$stateParams.id}/exclusions`)
|
|
||||||
.then(res => this.$.exclusions = res.data);
|
|
||||||
|
|
||||||
this.path = `/api/Zones/${this.$stateParams.id}/events`;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.$http.get(this.path)
|
let data = {};
|
||||||
.then(res => this.$.data = res.data);
|
this.$q.all([
|
||||||
|
this.$http.get(this.path)
|
||||||
|
.then(res => data.events = res.data),
|
||||||
|
this.$http.get(this.exclusionsPath)
|
||||||
|
.then(res => data.exclusions = res.data)
|
||||||
|
]).finally(() => {
|
||||||
|
this.$.data = data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatWdays(weekDays) {
|
formatWdays(weekDays) {
|
||||||
|
@ -55,16 +29,42 @@ class Controller extends Section {
|
||||||
|
|
||||||
let abrWdays = [];
|
let abrWdays = [];
|
||||||
for (let wday of weekDays.split(','))
|
for (let wday of weekDays.split(','))
|
||||||
abrWdays.push(this.abrWdays[wday]);
|
abrWdays.push(this.vnWeekDays.map[wday].localeAbr);
|
||||||
|
|
||||||
return abrWdays.length < 7
|
return abrWdays.length < 7
|
||||||
? abrWdays.join(', ')
|
? abrWdays.join(', ')
|
||||||
: this._('Everyday');
|
: this._('Everyday');
|
||||||
}
|
}
|
||||||
|
|
||||||
onEdit(row, event) {
|
onSelection(days, type, weekday, data) {
|
||||||
if (event.defaultPrevented) return;
|
if (this.editMode == 'include') {
|
||||||
|
let dayData = data[0] || {};
|
||||||
|
let event = dayData.events && dayData.events[0];
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
this.edit(event);
|
||||||
|
else
|
||||||
|
this.create(days, type, weekday);
|
||||||
|
} else {
|
||||||
|
let exclusions = [];
|
||||||
|
for (let dayData of data) {
|
||||||
|
if (dayData.exclusion)
|
||||||
|
exclusions.push(dayData.exclusion.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exclusions.length)
|
||||||
|
this.exclusionDelete(exclusions);
|
||||||
|
else
|
||||||
|
this.exclusionCreate(days);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditClick(row, event) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
|
this.edit(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(row) {
|
||||||
this.isNew = false;
|
this.isNew = false;
|
||||||
|
|
||||||
if (row.from && !row.to)
|
if (row.from && !row.to)
|
||||||
|
@ -86,67 +86,74 @@ class Controller extends Section {
|
||||||
this.$.dialog.show();
|
this.$.dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreate($day, $type, $weekday) {
|
create(days, type, weekday) {
|
||||||
this.isNew = true;
|
this.isNew = true;
|
||||||
this.eventType = $type == 'day' ? 'day' : 'indefinitely';
|
this.eventType = type == 'day' ? 'day' : 'indefinitely';
|
||||||
|
|
||||||
if ($type == 'weekday') {
|
if (type == 'weekday') {
|
||||||
let wdays = [];
|
let wdays = [];
|
||||||
let index = $weekday - 1;
|
let code = this.vnWeekDays.days[weekday].code;
|
||||||
if (index < 0) index = 7 - index;
|
wdays[code] = true;
|
||||||
wdays[this.wdays[index].code] = true;
|
|
||||||
this.selected = {wdays};
|
this.selected = {wdays};
|
||||||
} else
|
} else
|
||||||
this.selected = {from: $day[0]};
|
this.selected = {from: days[0]};
|
||||||
|
|
||||||
this.$.dialog.show();
|
this.$.dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
onSave(response) {
|
onSave(response) {
|
||||||
if (response != 'ACCEPT') return;
|
if (response == 'ACCEPT') {
|
||||||
|
let selected = this.selected;
|
||||||
|
|
||||||
let selected = this.selected;
|
if (this.eventType == 'indefinitely') {
|
||||||
|
selected.from = null;
|
||||||
if (this.eventType == 'indefinitely') {
|
selected.to = null;
|
||||||
selected.from = null;
|
|
||||||
selected.to = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.eventType != 'day') {
|
|
||||||
let weekDays = [];
|
|
||||||
|
|
||||||
for (let wday in selected.wdays) {
|
|
||||||
if (selected.wdays[wday])
|
|
||||||
weekDays.push(wday);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selected.weekDays = weekDays.join(',');
|
if (this.eventType != 'day') {
|
||||||
} else {
|
let weekDays = [];
|
||||||
selected.to = null;
|
|
||||||
selected.weekDays = '';
|
for (let wday in selected.wdays) {
|
||||||
|
if (selected.wdays[wday])
|
||||||
|
weekDays.push(wday);
|
||||||
|
}
|
||||||
|
|
||||||
|
selected.weekDays = weekDays.join(',');
|
||||||
|
} else {
|
||||||
|
selected.to = null;
|
||||||
|
selected.weekDays = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
let req;
|
||||||
|
|
||||||
|
if (this.isNew)
|
||||||
|
req = this.$http.post(this.path, selected);
|
||||||
|
else
|
||||||
|
req = this.$http.put(`${this.path}/${selected.id}`, selected);
|
||||||
|
|
||||||
|
req.then(() => {
|
||||||
|
this.selected = null;
|
||||||
|
this.isNew = null;
|
||||||
|
this.$.dialog.hide();
|
||||||
|
this.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (response == 'DELETE') {
|
||||||
|
this.onDelete(this.selected.id);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let req;
|
|
||||||
|
|
||||||
if (this.isNew)
|
|
||||||
req = this.$http.post(this.path, selected);
|
|
||||||
else
|
|
||||||
req = this.$http.put(`${this.path}/${selected.id}`, selected);
|
|
||||||
|
|
||||||
req.then(() => {
|
|
||||||
this.selected = null;
|
|
||||||
this.isNew = null;
|
|
||||||
this.$.dialog.hide();
|
|
||||||
this.refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onDelete(id, event) {
|
onDeleteClick(id, event) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.$.confirm.show();
|
this.onDelete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDelete(id) {
|
||||||
this.deleteId = id;
|
this.deleteId = id;
|
||||||
|
this.$.confirm.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(response) {
|
delete(response) {
|
||||||
|
@ -156,9 +163,33 @@ class Controller extends Section {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
this.deleteId = null;
|
this.deleteId = null;
|
||||||
|
this.$.dialog.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exclusionCreate(days) {
|
||||||
|
let exclusions = days.map(day => {
|
||||||
|
return {day};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$http.post(this.exclusionsPath, exclusions)
|
||||||
|
.then(() => this.refresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
exclusionDelete(ids) {
|
||||||
|
let promises = [];
|
||||||
|
|
||||||
|
for (let id of ids) {
|
||||||
|
promises.push(
|
||||||
|
this.$http.delete(`${this.exclusionsPath}/${id}`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$q.all(promises)
|
||||||
|
.then(() => this.refresh());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
ngModule.component('vnZoneEvents', {
|
ngModule.component('vnZoneEvents', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Edit mode: Modo de edición
|
||||||
|
Include: Incluir
|
||||||
|
Exclude: Excluir
|
||||||
|
Events: Eventos
|
|
@ -1,28 +0,0 @@
|
||||||
@import "effects";
|
|
||||||
|
|
||||||
vn-zone-events {
|
|
||||||
.week-days {
|
|
||||||
margin-top: $spacing-sm;
|
|
||||||
margin-bottom: $spacing-md;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
& > span {
|
|
||||||
@extend %clickable;
|
|
||||||
border-radius: 50%;
|
|
||||||
padding: .4em;
|
|
||||||
margin: .2em;
|
|
||||||
display: inline-flex;
|
|
||||||
width: 1.5em;
|
|
||||||
height: 1.5em;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
outline: none;
|
|
||||||
background-color: rgba(0, 0, 0, .05);
|
|
||||||
|
|
||||||
&.marked {
|
|
||||||
background: $color-main;
|
|
||||||
color: $color-font-dark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<div class="main-with-right-menu">
|
|
||||||
<vn-data-viewer
|
|
||||||
data="data"
|
|
||||||
is-loading="!data"
|
|
||||||
class="vn-w-xs">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="row in data | orderBy:'day'">
|
|
||||||
<vn-td>{{::row.day | date:'dd/MM/yyyy'}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="delete"
|
|
||||||
translate-attr="{title: 'Delete'}"
|
|
||||||
ng-click="$ctrl.onDelete(row.id)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
</div>
|
|
||||||
<vn-side-menu side="right">
|
|
||||||
<vn-zone-calendar
|
|
||||||
events="events"
|
|
||||||
exclusions="data"
|
|
||||||
on-selection="$ctrl.onCreate($days)">
|
|
||||||
</vn-zone-calendar>
|
|
||||||
</vn-side-menu>
|
|
|
@ -1,35 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'core/lib/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($el, $, $t, $http, $state) {
|
|
||||||
super($el, $, $t, $http, $state);
|
|
||||||
|
|
||||||
this.$http.get(`/api/Zones/${this.$stateParams.id}/events`)
|
|
||||||
.then(res => this.$.events = res.data);
|
|
||||||
|
|
||||||
this.path = `/api/Zones/${this.$stateParams.id}/exclusions`;
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.$http.get(this.path)
|
|
||||||
.then(res => this.$.data = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onCreate($days) {
|
|
||||||
this.$http.post(this.path, {day: $days[0]})
|
|
||||||
.then(() => this.refresh());
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete(id) {
|
|
||||||
if (!id) return;
|
|
||||||
this.$http.delete(`${this.path}/${id}`)
|
|
||||||
.then(() => this.refresh());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnZoneExclusions', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -12,6 +12,5 @@ import './basic-data';
|
||||||
import './warehouses';
|
import './warehouses';
|
||||||
import './events';
|
import './events';
|
||||||
import './calendar';
|
import './calendar';
|
||||||
import './exclusions';
|
|
||||||
import './location';
|
import './location';
|
||||||
import './calendar';
|
import './calendar';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<vn-crud-model
|
<vn-crud-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="/api/Zones/{{$ctrl.$stateParams.id}}/getLeaves"
|
url="/api/Zones/{{$ctrl.$params.id}}/getLeaves"
|
||||||
filter="::$ctrl.filter">
|
filter="::$ctrl.filter">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<div class="vn-w-md">
|
<div class="vn-w-md">
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
ng-model="item.selected"
|
ng-model="item.selected"
|
||||||
on-change="$ctrl.onSelection(value, item)"
|
on-change="$ctrl.onSelection(value, item)"
|
||||||
triple-state="true"
|
triple-state="true"
|
||||||
|
ng-click="$event.preventDefault()"
|
||||||
label="{{::item.name}}">
|
label="{{::item.name}}">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-treeview>
|
</vn-treeview>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'core/lib/section';
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Component {
|
||||||
onSearch(params) {
|
onSearch(params) {
|
||||||
this.$.model.applyFilter({}, params).then(() => {
|
this.$.model.applyFilter({}, params).then(() => {
|
||||||
const data = this.$.model.data;
|
const data = this.$.model.data;
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
{"state": "zone.card.basicData", "icon": "settings"},
|
{"state": "zone.card.basicData", "icon": "settings"},
|
||||||
{"state": "zone.card.location", "icon": "my_location"},
|
{"state": "zone.card.location", "icon": "my_location"},
|
||||||
{"state": "zone.card.warehouses", "icon": "home"},
|
{"state": "zone.card.warehouses", "icon": "home"},
|
||||||
{"state": "zone.card.events", "icon": "today"},
|
{"state": "zone.card.events", "icon": "today"}
|
||||||
{"state": "zone.card.exclusions", "icon": "block"}
|
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
|
@ -65,11 +64,6 @@
|
||||||
"state": "zone.card.events",
|
"state": "zone.card.events",
|
||||||
"component": "vn-zone-events",
|
"component": "vn-zone-events",
|
||||||
"description": "Calendar"
|
"description": "Calendar"
|
||||||
}, {
|
|
||||||
"url": "/exclusions",
|
|
||||||
"state": "zone.card.exclusions",
|
|
||||||
"component": "vn-zone-exclusions",
|
|
||||||
"description": "Exclusions"
|
|
||||||
}, {
|
}, {
|
||||||
"url": "/location?q",
|
"url": "/location?q",
|
||||||
"state": "zone.card.location",
|
"state": "zone.card.location",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'core/lib/section';
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Component {
|
||||||
constructor($el, $, $t, $http, $state) {
|
constructor($element, $) {
|
||||||
super($el, $, $t, $http, $state);
|
super($element, $);
|
||||||
|
|
||||||
this.path = `/api/Zones/${this.$stateParams.id}/warehouses`;
|
this.path = `/api/Zones/${this.$params.id}/warehouses`;
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
<vn-crud-model auto-load="true"
|
<vn-crud-model vn-id="model" auto-load="true" auto-save="true"
|
||||||
vn-id="model"
|
|
||||||
url="claim/api/ClaimEnds"
|
url="claim/api/ClaimEnds"
|
||||||
filter="$ctrl.filter"
|
filter="$ctrl.filter"
|
||||||
data="$ctrl.salesClaimed">
|
data="$ctrl.salesClaimed">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
|
||||||
|
<vn-crud-model auto-load="true"
|
||||||
|
url="/claim/api/ClaimDestinations"
|
||||||
|
data="claimDestinations">
|
||||||
|
</vn-crud-model>
|
||||||
|
|
||||||
<vn-card class="vn-mb-md vn-pa-lg vn-w-lg" style="text-align: right"
|
<vn-card class="vn-mb-md vn-pa-lg vn-w-lg" style="text-align: right"
|
||||||
ng-if="$ctrl.salesClaimed.length > 0">
|
ng-if="$ctrl.salesClaimed.length > 0">
|
||||||
<vn-label-value label="Total claimed"
|
<vn-label-value label="Total claimed"
|
||||||
|
@ -28,7 +32,6 @@
|
||||||
translate-attr="{title: 'Imports ticket lines'}">
|
translate-attr="{title: 'Imports ticket lines'}">
|
||||||
</vn-button>
|
</vn-button>
|
||||||
<vn-range
|
<vn-range
|
||||||
vn-one
|
|
||||||
label="Responsability"
|
label="Responsability"
|
||||||
min-label="Company"
|
min-label="Company"
|
||||||
max-label="Sales/Client"
|
max-label="Sales/Client"
|
||||||
|
@ -82,14 +85,12 @@
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one id="claimDestinationFk"
|
||||||
id="claimDestinationFk"
|
|
||||||
ng-model="saleClaimed.claimDestinationFk"
|
ng-model="saleClaimed.claimDestinationFk"
|
||||||
url="/claim/api/ClaimDestinations"
|
data="claimDestinations"
|
||||||
fields="['id','description']"
|
fields="['id','description']"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
show-field="description"
|
show-field="description">
|
||||||
on-change="$ctrl.setClaimDestination(saleClaimed.id, value)">
|
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>{{::saleClaimed.sale.ticket.landed | date: 'dd/MM/yyyy'}}</vn-td>
|
<vn-td>{{::saleClaimed.sale.ticket.landed | date: 'dd/MM/yyyy'}}</vn-td>
|
||||||
|
|
|
@ -19,7 +19,8 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{relation: 'claimBeggining'}
|
{relation: 'claimBeggining'},
|
||||||
|
{relation: 'claimDestination'}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
this.resolvedState = 3;
|
this.resolvedState = 3;
|
||||||
|
@ -82,16 +83,6 @@ class Controller {
|
||||||
this.calculateTotals();
|
this.calculateTotals();
|
||||||
}
|
}
|
||||||
|
|
||||||
setClaimDestination(id, claimDestinationFk) {
|
|
||||||
if (claimDestinationFk) {
|
|
||||||
let params = {id: id, claimDestinationFk: claimDestinationFk};
|
|
||||||
let query = `claim/api/ClaimEnds/`;
|
|
||||||
this.$http.patch(query, params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateTotals() {
|
calculateTotals() {
|
||||||
this.claimedTotal = 0;
|
this.claimedTotal = 0;
|
||||||
this.salesClaimed.forEach(sale => {
|
this.salesClaimed.forEach(sale => {
|
||||||
|
|
|
@ -82,17 +82,6 @@ describe('claim', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setClaimDestination(id, claimDestinationFk)', () => {
|
|
||||||
it('should make a patch and call refresh and showSuccess', () => {
|
|
||||||
spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
$httpBackend.expectPATCH(`claim/api/ClaimEnds/`).respond({});
|
|
||||||
controller.setClaimDestination(1, 1);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('calculateTotals()', () => {
|
describe('calculateTotals()', () => {
|
||||||
it('should calculate the total price of the items claimed', () => {
|
it('should calculate the total price of the items claimed', () => {
|
||||||
controller.salesClaimed = [
|
controller.salesClaimed = [
|
||||||
|
|
|
@ -29,10 +29,9 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-none>
|
<vn-none>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
pointer
|
|
||||||
class="vn-my-md"
|
|
||||||
vn-tooltip="Remove contact"
|
vn-tooltip="Remove contact"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
tabindex="-1"
|
||||||
ng-click="model.remove($index)">
|
ng-click="model.remove($index)">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-none>
|
</vn-none>
|
||||||
|
|
|
@ -13,6 +13,10 @@ class Controller {
|
||||||
callback.call(this);
|
callback.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get client() {
|
||||||
|
return this._client;
|
||||||
|
}
|
||||||
|
|
||||||
set client(value) {
|
set client(value) {
|
||||||
this._client = value;
|
this._client = value;
|
||||||
|
|
||||||
|
@ -32,10 +36,6 @@ class Controller {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get client() {
|
|
||||||
return this._client;
|
|
||||||
}
|
|
||||||
|
|
||||||
set quicklinks(value = {}) {
|
set quicklinks(value = {}) {
|
||||||
this._quicklinks = Object.assign(value, this._quicklinks);
|
this._quicklinks = Object.assign(value, this._quicklinks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,24 +52,31 @@ class Controller {
|
||||||
|
|
||||||
get freeLineIndex() {
|
get freeLineIndex() {
|
||||||
let lines = this.$scope.model.data;
|
let lines = this.$scope.model.data;
|
||||||
let currentDate = new Date();
|
let minDate = new Date();
|
||||||
currentDate.setHours(0, 0, 0);
|
minDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let maxDate = new Date();
|
||||||
|
maxDate.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
let isFutureDate = new Date(lines[i].date) >= currentDate;
|
const dated = new Date(lines[i].date);
|
||||||
|
|
||||||
if (isFutureDate)
|
let isForFuture = dated > maxDate;
|
||||||
|
let isForToday = (dated >= minDate && dated <= maxDate);
|
||||||
|
|
||||||
|
if (isForFuture || isForToday)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get onPreparationLineIndex() {
|
get onPreparationLineIndex() {
|
||||||
let lines = this.$scope.model.data;
|
let lines = this.$scope.model.data;
|
||||||
|
|
||||||
for (let i = this.freeLineIndex; i >= 0; i--) {
|
for (let i = this.freeLineIndex; i >= 0; i--) {
|
||||||
let line = lines[i];
|
let line = lines[i];
|
||||||
|
|
||||||
let currentDate = new Date();
|
let currentDate = new Date();
|
||||||
currentDate.setHours(0, 0, 0);
|
currentDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
let isPastDate = new Date(lines[i].date) < currentDate;
|
let isPastDate = new Date(lines[i].date) < currentDate;
|
||||||
let isPicked = line.alertLevel == 1 && line.isPicked;
|
let isPicked = line.alertLevel == 1 && line.isPicked;
|
||||||
|
@ -95,6 +102,7 @@ class Controller {
|
||||||
let selectedTicketLineIndex = this.givenTicketIndex;
|
let selectedTicketLineIndex = this.givenTicketIndex;
|
||||||
let lineIndex = this.onPreparationLineIndex;
|
let lineIndex = this.onPreparationLineIndex;
|
||||||
|
|
||||||
|
|
||||||
let lines = body.querySelector('vn-tbody').children;
|
let lines = body.querySelector('vn-tbody').children;
|
||||||
|
|
||||||
if (lineIndex == undefined || !lines.length) return;
|
if (lineIndex == undefined || !lines.length) return;
|
||||||
|
@ -120,7 +128,6 @@ class Controller {
|
||||||
offsetTop = onPreparationLine.offsetTop - headerHeight;
|
offsetTop = onPreparationLine.offsetTop - headerHeight;
|
||||||
|
|
||||||
this.$window.scrollTo(0, offsetTop);
|
this.$window.scrollTo(0, offsetTop);
|
||||||
|
|
||||||
this.ticketFk = null;
|
this.ticketFk = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
<div class="content-block">
|
<div class="content-block">
|
||||||
<vn-card class="vn-pa-md vn-w-sm">
|
<vn-card class="vn-pa-md vn-w-sm">
|
||||||
<vn-horizontal style="align-items: center;">
|
<vn-horizontal style="align-items: center;">
|
||||||
<vn-searchbar
|
<vn-searchbar vn-focus
|
||||||
panel="vn-item-search-panel"
|
panel="vn-item-search-panel"
|
||||||
on-search="$ctrl.onSearch($params)"
|
on-search="$ctrl.onSearch($params)"
|
||||||
info="Search items by id, name or barcode"
|
info="Search items by id, name or barcode"
|
||||||
suggested-filter="{isActive: true}"
|
suggested-filter="{isActive: true}">
|
||||||
vn-focus>
|
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
<vn-icon-menu
|
<vn-icon-menu
|
||||||
vn-id="more-button"
|
vn-id="more-button"
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
ng-model="filter.atenderFk"
|
ng-model="filter.attenderFk"
|
||||||
url="/client/api/Clients/activeWorkersWithRole"
|
url="/client/api/Clients/activeWorkersWithRole"
|
||||||
search-function="{firstName: $search}"
|
search-function="{firstName: $search}"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
|
|
|
@ -1,121 +1,116 @@
|
||||||
<vn-crud-model
|
<vn-crud-model auto-load="true"
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="/ticket/api/TicketRequests/filter"
|
url="/ticket/api/TicketRequests/filter"
|
||||||
limit="20"
|
limit="20"
|
||||||
data="requests"
|
data="requests"
|
||||||
order="isOk ASC"
|
order="shipped DESC, isOk ASC">
|
||||||
auto-load="false">
|
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<form name="form">
|
<form name="form">
|
||||||
<div class="vn-ma-md">
|
<div class="vn-ma-md">
|
||||||
<vn-card class="vn-pa-md vn-list">
|
<vn-card class="vn-pa-md vn-list">
|
||||||
<vn-horizontal>
|
<vn-searchbar vn-one vn-focus
|
||||||
<vn-searchbar
|
auto-load="false"
|
||||||
auto-load="false"
|
panel="vn-request-search-panel"
|
||||||
panel="vn-request-search-panel"
|
on-search="$ctrl.onSearch($params)"
|
||||||
on-search="$ctrl.onSearch($params)"
|
info="Search request by id or alias"
|
||||||
info="Search request by id or alias"
|
suggested-filter="$ctrl.filter.where">
|
||||||
vn-one
|
</vn-searchbar>
|
||||||
vn-focus>
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-card class="vn-my-md">
|
<vn-data-viewer model="model" class="vn-my-md">
|
||||||
<vn-table model="model" auto-load="false">
|
<vn-card>
|
||||||
<vn-thead>
|
<vn-table model="model">
|
||||||
<vn-tr>
|
<vn-thead>
|
||||||
<vn-th field="ticketFk" number>Ticket ID</vn-th>
|
<vn-tr>
|
||||||
<vn-th field="shipped">Shipped</vn-th>
|
<vn-th field="ticketFk" number>Ticket ID</vn-th>
|
||||||
<vn-th field="warehouse">Warehouse</vn-th>
|
<vn-th field="shipped">Shipped</vn-th>
|
||||||
<vn-th field="salesPersonNickname">SalesPerson</vn-th>
|
<vn-th field="warehouse">Warehouse</vn-th>
|
||||||
<vn-th field="description">Description</vn-th>
|
<vn-th field="salesPersonNickname">SalesPerson</vn-th>
|
||||||
<vn-th field="quantity" number editable>Quantity</vn-th>
|
<vn-th field="description">Description</vn-th>
|
||||||
<vn-th field="price" number>Price</vn-th>
|
<vn-th field="quantity" number editable>Requested</vn-th>
|
||||||
<vn-th field="atenderNickname">Atender</vn-th>
|
<vn-th field="price" number>Price</vn-th>
|
||||||
<vn-th field="itemFk">Item</vn-th>
|
<vn-th field="atenderNickname">Atender</vn-th>
|
||||||
<vn-th field="description">Concept</vn-th>
|
<vn-th field="itemFk">Item</vn-th>
|
||||||
<vn-th field="saleQuantity" number>Sale quantity</vn-th>
|
<vn-th field="saleQuantity">Achieved</vn-th>
|
||||||
<vn-th field="isOk">State</vn-th>
|
<vn-th field="description">Concept</vn-th>
|
||||||
</vn-tr>
|
<vn-th field="isOk">State</vn-th>
|
||||||
</vn-thead>
|
</vn-tr>
|
||||||
<vn-tbody>
|
</vn-thead>
|
||||||
<vn-tr ng-repeat="request in requests">
|
<vn-tbody>
|
||||||
<vn-td number>
|
<vn-tr ng-repeat="request in requests">
|
||||||
<span class="link"
|
<vn-td number>
|
||||||
ng-click="$ctrl.showTicketDescriptor($event, request.ticketFk)">
|
<span class="link"
|
||||||
{{request.ticketFk}}
|
ng-click="$ctrl.showTicketDescriptor($event, request.ticketFk)">
|
||||||
</span>
|
{{request.ticketFk}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td>
|
</vn-td>
|
||||||
<span title="{{::request.shipped | date: 'dd/MM/yyyy'}}"
|
<vn-td>
|
||||||
class="chip {{$ctrl.compareDate(request.shipped)}}">
|
<span title="{{::request.shipped | date: 'dd/MM/yyyy'}}"
|
||||||
{{::request.shipped | date: 'dd/MM/yyyy'}}
|
class="chip {{$ctrl.compareDate(request.shipped)}}">
|
||||||
</span>
|
{{::request.shipped | date: 'dd/MM/yyyy'}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td>{{::request.warehouse}}</vn-td>
|
</vn-td>
|
||||||
<vn-td>
|
<vn-td>{{::request.warehouse}}</vn-td>
|
||||||
<span
|
<vn-td>
|
||||||
class="link"
|
<span
|
||||||
ng-click="$ctrl.showWorkerDescriptor($event, request.salesPersonFk)">
|
class="link"
|
||||||
{{::request.salesPersonNickname}}
|
ng-click="$ctrl.showWorkerDescriptor($event, request.salesPersonFk)">
|
||||||
</span>
|
{{::request.salesPersonNickname}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td title="{{::request.description}}">{{::request.description}}</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::request.quantity}}</vn-td>
|
<vn-td title="{{::request.description}}">{{::request.description}}</vn-td>
|
||||||
<vn-td number>{{::request.price | currency: 'EUR':2}}</vn-td>
|
<vn-td number>{{::request.quantity}}</vn-td>
|
||||||
<vn-td>
|
<vn-td number>{{::request.price | currency: 'EUR':2}}</vn-td>
|
||||||
<span
|
<vn-td>
|
||||||
class="link"
|
<span
|
||||||
ng-click="$ctrl.showWorkerDescriptor($event, request.atenderFk)">
|
class="link"
|
||||||
{{::request.atenderNickname}}
|
ng-click="$ctrl.showWorkerDescriptor($event, request.attenderFk)">
|
||||||
</span>
|
{{::request.atenderNickname}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td-editable disabled="request.isOk === 0" number>
|
</vn-td>
|
||||||
<text>{{request.itemFk}}</text>
|
<vn-td-editable disabled="request.isOk != null" number>
|
||||||
<field>
|
<text>{{request.itemFk}}</text>
|
||||||
<vn-input-number
|
<field>
|
||||||
ng-model="request.itemFk"
|
<vn-input-number class="dense" vn-focus
|
||||||
on-change="$ctrl.confirmRequest(request)">
|
ng-model="request.itemFk">
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</field>
|
</field>
|
||||||
</vn-td-editable>
|
</vn-td-editable>
|
||||||
<vn-td>
|
<vn-td-editable disabled="!request.itemFk || request.isOk != null" number>
|
||||||
<span
|
<text number>{{request.saleQuantity}}</text>
|
||||||
class="link"
|
<field>
|
||||||
ng-click="$ctrl.showItemDescriptor($event, request.itemFk)"
|
<vn-input-number class="dense" vn-focus
|
||||||
title="{{::request.itemDescription}}">
|
ng-model="request.saleQuantity"
|
||||||
{{::request.itemDescription}}
|
on-change="$ctrl.changeQuantity(request)">
|
||||||
</span>
|
</vn-input-number>
|
||||||
</vn-td>
|
</field>
|
||||||
<vn-td-editable disabled="request.isOk === 0" number>
|
</vn-td-editable>
|
||||||
<text number>{{request.saleQuantity}}</text>
|
<vn-td>
|
||||||
<field>
|
<span
|
||||||
<vn-input-number
|
class="link"
|
||||||
ng-model="request.saleQuantity"
|
ng-click="$ctrl.showItemDescriptor($event, request.itemFk)"
|
||||||
on-change="$ctrl.changeQuantity(request)">
|
title="{{request.itemDescription}}">
|
||||||
</vn-input-number>
|
{{request.itemDescription}}
|
||||||
</field>
|
</span>
|
||||||
</vn-td-editable>
|
</vn-td>
|
||||||
<vn-td>{{::$ctrl.getState(request.isOk)}}</vn-td>
|
<vn-td>{{$ctrl.getState(request.isOk)}}</vn-td>
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
ng-if="request.response.length"
|
ng-if="request.response.length"
|
||||||
vn-tooltip="{{request.response}}"
|
ranslate-attr="{title: request.response}"
|
||||||
icon="insert_drive_file">
|
icon="insert_drive_file">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
ng-if="request.isOk != 0"
|
ng-if="request.isOk != 0"
|
||||||
number
|
icon="thumb_down"
|
||||||
icon="thumb_down"
|
ng-click="$ctrl.showDenyReason($event, request)"
|
||||||
ng-click="$ctrl.showDenyReason($event, request.id)"
|
translate-attr="{title: 'Discard'}">
|
||||||
vn-tooltip="Discard">
|
</vn-icon-button>
|
||||||
</vn-icon-button>
|
</vn-td>
|
||||||
</vn-td>
|
</vn-tr>
|
||||||
</vn-tr>
|
</vn-tbody>
|
||||||
</vn-tbody>
|
</vn-table>
|
||||||
</vn-table>
|
</vn-card>
|
||||||
</vn-card>
|
</vn-data-viewer>
|
||||||
<vn-pagination model="model"></vn-pagination>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<vn-worker-descriptor-popover
|
<vn-worker-descriptor-popover
|
||||||
|
@ -129,21 +124,17 @@
|
||||||
</vn-item-descriptor-popover>
|
</vn-item-descriptor-popover>
|
||||||
<vn-dialog
|
<vn-dialog
|
||||||
vn-id="denyReason"
|
vn-id="denyReason"
|
||||||
class="modal-form">
|
on-response="$ctrl.denyRequest(response)">
|
||||||
<tpl-body>
|
<tpl-body>
|
||||||
<vn-horizontal class="header">
|
<h5 class="vn-pa-md" translate>Specify the reasons to deny this request</h5>
|
||||||
<h5><span translate>Indicate the reasons to deny this request</span></h5>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
<vn-horizontal class="vn-pa-md">
|
||||||
<vn-textarea
|
<vn-textarea
|
||||||
ng-model="$ctrl.denyObservation">
|
ng-model="$ctrl.denyObservation">
|
||||||
</vn-textarea>
|
</vn-textarea>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-button
|
|
||||||
label="Save"
|
|
||||||
ng-click="$ctrl.denyRequest()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
|
<tpl-buttons>
|
||||||
|
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
|
||||||
|
<button response="ACCEPT" translate>Save</button>
|
||||||
|
</tpl-buttons>
|
||||||
</vn-dialog>
|
</vn-dialog>
|
|
@ -1,16 +1,28 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller extends Component {
|
||||||
constructor($, vnApp, $translate, $http, $state, $stateParams) {
|
constructor($element, $) {
|
||||||
this.$state = $state;
|
super($element, $);
|
||||||
this.$stateParams = $stateParams;
|
|
||||||
this.$http = $http;
|
if (!this.$state.q) {
|
||||||
this.$ = $;
|
const today = new Date();
|
||||||
this.vnApp = vnApp;
|
today.setHours(23, 59, 59, 59);
|
||||||
this._ = $translate;
|
|
||||||
if (!$stateParams.q)
|
const lastWeek = new Date();
|
||||||
this.filter = {isOk: false, mine: true};
|
lastWeek.setHours(0, 0, 0, 0);
|
||||||
|
lastWeek.setDate(lastWeek.getDate() - 7);
|
||||||
|
|
||||||
|
this.filter = {
|
||||||
|
where: {
|
||||||
|
isOk: false,
|
||||||
|
mine: true,
|
||||||
|
from: lastWeek,
|
||||||
|
to: today
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$postLink() {
|
$postLink() {
|
||||||
|
@ -21,7 +33,7 @@ export default class Controller {
|
||||||
getState(isOk) {
|
getState(isOk) {
|
||||||
if (isOk === null)
|
if (isOk === null)
|
||||||
return 'Nueva';
|
return 'Nueva';
|
||||||
else if (isOk === -1 || isOk === 1)
|
else if (isOk === -1 || isOk)
|
||||||
return 'Aceptada';
|
return 'Aceptada';
|
||||||
else
|
else
|
||||||
return 'Denegada';
|
return 'Denegada';
|
||||||
|
@ -34,14 +46,12 @@ export default class Controller {
|
||||||
quantity: request.saleQuantity
|
quantity: request.saleQuantity
|
||||||
};
|
};
|
||||||
|
|
||||||
let endpoint = `/api/TicketRequests/${request.id}/confirm`;
|
let query = `/api/TicketRequests/${request.id}/confirm`;
|
||||||
|
this.$http.post(query, params).then(res => {
|
||||||
|
request.itemDescription = res.data.concept;
|
||||||
|
request.isOk = true;
|
||||||
|
|
||||||
this.$http.post(endpoint, params).then(() => {
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
}).catch( e => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
throw e;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,11 +65,8 @@ export default class Controller {
|
||||||
let endpoint = `/api/Sales/${request.saleFk}/`;
|
let endpoint = `/api/Sales/${request.saleFk}/`;
|
||||||
|
|
||||||
this.$http.patch(endpoint, params).then(() => {
|
this.$http.patch(endpoint, params).then(() => {
|
||||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}).catch( e => {
|
}).then(() => this.confirmRequest(request));
|
||||||
this.$.model.refresh();
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
} else
|
} else
|
||||||
this.confirmRequest(request);
|
this.confirmRequest(request);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +93,7 @@ export default class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
showDenyReason(event, requestId) {
|
showDenyReason(event, requestId) {
|
||||||
this.denyRequestId = requestId;
|
this.selectedRequest = requestId;
|
||||||
this.$.denyReason.parent = event.target;
|
this.$.denyReason.parent = event.target;
|
||||||
this.$.denyReason.show();
|
this.$.denyReason.show();
|
||||||
document.querySelector('vn-item-request vn-textarea textArea').focus();
|
document.querySelector('vn-item-request vn-textarea textArea').focus();
|
||||||
|
@ -96,17 +103,21 @@ export default class Controller {
|
||||||
delete this.denyRequestId;
|
delete this.denyRequestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
denyRequest() {
|
denyRequest(response) {
|
||||||
|
if (response !== 'ACCEPT') return;
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
observation: this.denyObservation
|
observation: this.denyObservation
|
||||||
};
|
};
|
||||||
|
|
||||||
let endpoint = `/api/TicketRequests/${this.denyRequestId}/deny`;
|
let query = `/api/TicketRequests/${this.selectedRequest.id}/deny`;
|
||||||
|
this.$http.post(query, params).then(res => {
|
||||||
|
const request = res.data;
|
||||||
|
this.selectedRequest.isOk = request.isOk;
|
||||||
|
this.selectedRequest.attenderFk = request.attenderFk;
|
||||||
|
this.selectedRequest.response = request.response;
|
||||||
|
|
||||||
this.$http.post(endpoint, params).then(() => {
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.$.denyReason.hide();
|
|
||||||
this.denyObservation = null;
|
this.denyObservation = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -140,8 +151,6 @@ export default class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', 'vnApp', '$translate', '$http', '$state', '$stateParams'];
|
|
||||||
|
|
||||||
ngModule.component('vnItemRequest', {
|
ngModule.component('vnItemRequest', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller
|
controller: Controller
|
||||||
|
|
|
@ -4,6 +4,7 @@ import crudModel from 'core/mocks/crud-model';
|
||||||
describe('Item', () => {
|
describe('Item', () => {
|
||||||
describe('Component vnItemRequest', () => {
|
describe('Component vnItemRequest', () => {
|
||||||
let $scope;
|
let $scope;
|
||||||
|
let $element;
|
||||||
let controller;
|
let controller;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
|
|
||||||
|
@ -16,9 +17,15 @@ describe('Item', () => {
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
$scope.model = crudModel;
|
$scope.model = crudModel;
|
||||||
$scope.denyReason = {hide: () => {}};
|
$scope.denyReason = {hide: () => {}};
|
||||||
controller = $componentController('vnItemRequest', {$scope: $scope});
|
$element = angular.element('<vn-item-request></vn-item-request>');
|
||||||
|
controller = $componentController('vnItemRequest', {$element, $scope});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
$scope.$destroy();
|
||||||
|
$element.remove();
|
||||||
|
});
|
||||||
|
|
||||||
describe('getState()', () => {
|
describe('getState()', () => {
|
||||||
it(`should return an string depending to the isOK value`, () => {
|
it(`should return an string depending to the isOK value`, () => {
|
||||||
let isOk = null;
|
let isOk = null;
|
||||||
|
@ -53,15 +60,15 @@ describe('Item', () => {
|
||||||
let model = controller.$.model;
|
let model = controller.$.model;
|
||||||
spyOn(model, 'refresh');
|
spyOn(model, 'refresh');
|
||||||
|
|
||||||
|
const expectedResult = {concept: 'Melee Weapon'};
|
||||||
let request = {itemFk: 1, saleQuantity: 1, id: 1};
|
let request = {itemFk: 1, saleQuantity: 1, id: 1};
|
||||||
|
|
||||||
$httpBackend.when('POST', `/api/TicketRequests/${request.id}/confirm`).respond();
|
$httpBackend.when('POST', `/api/TicketRequests/${request.id}/confirm`).respond(expectedResult);
|
||||||
$httpBackend.expect('POST', `/api/TicketRequests/${request.id}/confirm`).respond();
|
$httpBackend.expect('POST', `/api/TicketRequests/${request.id}/confirm`).respond(expectedResult);
|
||||||
controller.confirmRequest(request);
|
controller.confirmRequest(request);
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
expect($scope.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -110,20 +117,17 @@ describe('Item', () => {
|
||||||
describe('denyRequest()', () => {
|
describe('denyRequest()', () => {
|
||||||
it(`should perform a query and call vnApp.showSuccess(), refresh(), hide() and set denyObservation to null in the controller`, () => {
|
it(`should perform a query and call vnApp.showSuccess(), refresh(), hide() and set denyObservation to null in the controller`, () => {
|
||||||
spyOn(controller.vnApp, 'showSuccess');
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
let model = controller.$.model;
|
|
||||||
spyOn(model, 'refresh');
|
|
||||||
spyOn(controller.$.denyReason, 'hide');
|
|
||||||
|
|
||||||
controller.denyRequestId = 1;
|
const request = {id: 1};
|
||||||
|
const expectedResult = {isOk: false, attenderFk: 106, response: 'Denied!'};
|
||||||
|
controller.selectedRequest = request;
|
||||||
|
|
||||||
$httpBackend.when('POST', `/api/TicketRequests/${controller.denyRequestId}/deny`).respond();
|
$httpBackend.when('POST', `/api/TicketRequests/${request.id}/deny`).respond(expectedResult);
|
||||||
$httpBackend.expect('POST', `/api/TicketRequests/${controller.denyRequestId}/deny`).respond();
|
$httpBackend.expect('POST', `/api/TicketRequests/${request.id}/deny`).respond(expectedResult);
|
||||||
controller.denyRequest();
|
controller.denyRequest('ACCEPT');
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
expect($scope.model.refresh).toHaveBeenCalledWith();
|
|
||||||
expect($scope.denyReason.hide).toHaveBeenCalledWith();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
Discard: Descartar
|
Discard: Descartar
|
||||||
Indicate the reasons to deny this request: Indique las razones para descartar esta peticion
|
Specify the reasons to deny this request: Especifica las razones para descartar la petición
|
||||||
Buy requests: Peticiones de compra
|
Buy requests: Peticiones de compra
|
||||||
Search request by id or alias: Buscar peticiones por identificador o alias
|
Search request by id or alias: Buscar peticiones por identificador o alias
|
||||||
Sale quantity: C. conseguida
|
Requested: Solicitado
|
||||||
|
Achieved: Conseguido
|
|
@ -28,12 +28,6 @@ module.exports = Self => {
|
||||||
fields: ['id', 'packages', 'warehouseFk', 'nickname', 'clientFk', 'priority', 'addressFk'],
|
fields: ['id', 'packages', 'warehouseFk', 'nickname', 'clientFk', 'priority', 'addressFk'],
|
||||||
order: 'priority',
|
order: 'priority',
|
||||||
include: [
|
include: [
|
||||||
{
|
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'street', 'postcode'],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
relation: 'state',
|
relation: 'state',
|
||||||
scope: {
|
scope: {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Route getSelectedItems() should return the selected items 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"checked": true,
|
||||||
|
"id": 1,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"checked": true,
|
||||||
|
"id": 3,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"checked": true,
|
||||||
|
"id": 5,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
|
@ -1,104 +1,105 @@
|
||||||
<vn-crud-model
|
<vn-crud-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="/api/Routes/{{$ctrl.$stateParams.id}}/getTickets"
|
url="api/Routes/{{$ctrl.$stateParams.id}}/getTickets"
|
||||||
order="priority ASC"
|
order="priority ASC"
|
||||||
data="$ctrl.tickets"
|
data="$ctrl.tickets"
|
||||||
auto-load="true">
|
auto-load="true">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<form name="form">
|
<vn-data-viewer model="model">
|
||||||
<vn-card class="vn-pa-lg">
|
<form name="form">
|
||||||
<vn-tool-bar class="vn-mb-sm">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-button
|
<vn-tool-bar class="vn-mb-sm">
|
||||||
icon="icon-wand"
|
<vn-button
|
||||||
ng-click="$ctrl.guessPriority()"
|
icon="icon-wand"
|
||||||
vn-tooltip="Sort routes">
|
ng-click="$ctrl.guessPriority()"
|
||||||
</vn-button>
|
vn-tooltip="Sort routes">
|
||||||
<vn-button
|
</vn-button>
|
||||||
disabled="!$ctrl.isChecked"
|
<vn-button
|
||||||
ng-click="$ctrl.goToBuscaman()"
|
disabled="!$ctrl.isChecked"
|
||||||
vn-tooltip="Open buscaman"
|
ng-click="$ctrl.goToBuscaman()"
|
||||||
tooltip-position="up"
|
vn-tooltip="Open buscaman"
|
||||||
icon="icon-buscaman">
|
tooltip-position="up"
|
||||||
</vn-button>
|
icon="icon-buscaman">
|
||||||
</vn-tool-bar>
|
</vn-button>
|
||||||
<vn-icon-button
|
</vn-tool-bar>
|
||||||
vn-tooltip="Load more"
|
<vn-icon-button
|
||||||
ng-click="$ctrl.goToBuscaman()">
|
vn-tooltip="Load more"
|
||||||
</vn-icon-button>
|
ng-click="$ctrl.goToBuscaman()">
|
||||||
<vn-table model="model" auto-load="false">
|
</vn-icon-button>
|
||||||
<vn-thead>
|
<vn-table model="model" auto-load="false">
|
||||||
<vn-tr>
|
<vn-thead>
|
||||||
<vn-th shrink>
|
<vn-tr>
|
||||||
<vn-multi-check
|
<vn-th shrink>
|
||||||
model="model">
|
<vn-multi-check
|
||||||
</vn-multi-check>
|
model="model">
|
||||||
</vn-th>
|
</vn-multi-check>
|
||||||
<vn-th>Order</vn-th>
|
</vn-th>
|
||||||
<vn-th number>Ticket</vn-th>
|
<vn-th>Order</vn-th>
|
||||||
<vn-th>Client</vn-th>
|
<vn-th number>Ticket</vn-th>
|
||||||
<vn-th number shrink>Packages</vn-th>
|
<vn-th>Client</vn-th>
|
||||||
<vn-th shrink>m³</vn-th>
|
<vn-th number shrink>Packages</vn-th>
|
||||||
<vn-th shrink>Warehouse</vn-th>
|
<vn-th shrink>m³</vn-th>
|
||||||
<vn-th shrink>PC</vn-th>
|
<vn-th shrink>Warehouse</vn-th>
|
||||||
<vn-th>Street</vn-th>
|
<vn-th expand>Postcode</vn-th>
|
||||||
<vn-th shrink></vn-th>
|
<vn-th>Street</vn-th>
|
||||||
<vn-th shrink></vn-th>
|
<vn-th shrink></vn-th>
|
||||||
</vn-tr>
|
<vn-th shrink></vn-th>
|
||||||
</vn-thead>
|
</vn-tr>
|
||||||
<vn-tbody>
|
</vn-thead>
|
||||||
<vn-tr ng-repeat="ticket in $ctrl.tickets">
|
<vn-tbody>
|
||||||
<vn-td shrink>
|
<vn-tr ng-repeat="ticket in $ctrl.tickets">
|
||||||
<vn-check
|
<vn-td shrink>
|
||||||
ng-model="ticket.checked">
|
<vn-check
|
||||||
</vn-check>
|
ng-model="ticket.checked">
|
||||||
</vn-td>
|
</vn-check>
|
||||||
<vn-td>
|
</vn-td>
|
||||||
<vn-input-number
|
<vn-td>
|
||||||
on-change="$ctrl.setPriority(ticket.id, ticket.priority)"
|
<vn-input-number
|
||||||
ng-model="ticket.priority"
|
on-change="$ctrl.setPriority(ticket.id, ticket.priority)"
|
||||||
rule="Ticket">
|
ng-model="ticket.priority"
|
||||||
</vn-input-number>
|
rule="Ticket">
|
||||||
</vn-td>
|
</vn-input-number>
|
||||||
<vn-td number>
|
</vn-td>
|
||||||
<span
|
<vn-td number>
|
||||||
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)"
|
<span
|
||||||
class="link">
|
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)"
|
||||||
{{ticket.id}}
|
class="link">
|
||||||
</span>
|
{{ticket.id}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td>
|
</vn-td>
|
||||||
<span
|
<vn-td>
|
||||||
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"
|
<span
|
||||||
class="link">
|
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"
|
||||||
{{ticket.nickname}}
|
class="link">
|
||||||
</span>
|
{{ticket.nickname}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td number shrink>{{ticket.packages}}</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>{{ticket.volume}}</vn-td>
|
<vn-td number shrink>{{ticket.packages}}</vn-td>
|
||||||
<vn-td shrink>{{ticket.warehouse.name}}</vn-td>
|
<vn-td shrink>{{ticket.volume}}</vn-td>
|
||||||
<vn-td shrink>{{ticket.client.postcode}}</vn-td>
|
<vn-td shrink>{{ticket.warehouse.name}}</vn-td>
|
||||||
<vn-td expand title="{{ticket.client.street}}">{{ticket.client.street}}</vn-td>
|
<vn-td number shrink>{{ticket.address.postalCode}}</vn-td>
|
||||||
<vn-td shrink>
|
<vn-td expand title="{{ticket.address.street}}">{{ticket.address.street}}</vn-td>
|
||||||
<vn-icon-button
|
<vn-td shrink>
|
||||||
ng-if="ticket.notes.length"
|
<vn-icon-button
|
||||||
title="::{{ticket.notes[0].description}}"
|
ng-if="ticket.notes.length"
|
||||||
icon="insert_drive_file">
|
title="::{{ticket.notes[0].description}}"
|
||||||
</vn-icon-button>
|
icon="insert_drive_file">
|
||||||
</vn-td>
|
</vn-icon-button>
|
||||||
<vn-td>
|
</vn-td>
|
||||||
<vn-icon-button
|
<vn-td>
|
||||||
translate-attr="::{title: 'Remove ticket'}"
|
<vn-icon-button
|
||||||
icon="delete"
|
translate-attr="::{title: 'Remove ticket'}"
|
||||||
ng-click="$ctrl.showDeleteConfirm(ticket.id)"
|
icon="delete"
|
||||||
tabindex="-1">
|
ng-click="$ctrl.showDeleteConfirm(ticket.id)"
|
||||||
</vn-icon-button>
|
tabindex="-1">
|
||||||
</vn-td>
|
</vn-icon-button>
|
||||||
</vn-tr>
|
</vn-td>
|
||||||
</vn-tbody>
|
</vn-tr>
|
||||||
</vn-table>
|
</vn-tbody>
|
||||||
</vn-card>
|
</vn-table>
|
||||||
</form>
|
</vn-card>
|
||||||
|
</form>
|
||||||
|
</vn-data-viewer>
|
||||||
<vn-ticket-descriptor-popover
|
<vn-ticket-descriptor-popover
|
||||||
vn-id="ticketDescriptor">
|
vn-id="ticketDescriptor">
|
||||||
</vn-ticket-descriptor-popover>
|
</vn-ticket-descriptor-popover>
|
||||||
|
@ -109,4 +110,72 @@
|
||||||
vn-id="confirm"
|
vn-id="confirm"
|
||||||
question="Delete ticket from route?"
|
question="Delete ticket from route?"
|
||||||
on-response="$ctrl.removeTicketFromRoute(response)">
|
on-response="$ctrl.removeTicketFromRoute(response)">
|
||||||
</vn-confirm>
|
</vn-confirm>
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="possibleTicketsModel"
|
||||||
|
url="api/Tickets"
|
||||||
|
filter="$ctrl.possibleTicketsFilter"
|
||||||
|
data="$ctrl.possibleTickets">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-dialog
|
||||||
|
vn-id="possibleTicketsDialog"
|
||||||
|
on-response="$ctrl.setTicketsRoute(response)">
|
||||||
|
<tpl-body>
|
||||||
|
<section class="header vn-pa-md">
|
||||||
|
<h5><span translate>Tickets to add</span></h5>
|
||||||
|
</section>
|
||||||
|
<vn-data-viewer class="vn-pa-md" model="possibleTicketsModel">
|
||||||
|
<vn-table model="possibleTicketsModel" auto-load="false">
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th shrink>
|
||||||
|
<vn-multi-check
|
||||||
|
model="possibleTicketsModel">
|
||||||
|
</vn-multi-check>
|
||||||
|
</vn-th>
|
||||||
|
<vn-th number>Ticket</vn-th>
|
||||||
|
<vn-th>Client</vn-th>
|
||||||
|
<vn-th number shrink>Packages</vn-th>
|
||||||
|
<vn-th shrink>Warehouse</vn-th>
|
||||||
|
<vn-th expand>Postcode</vn-th>
|
||||||
|
<vn-th>Address</vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="ticket in $ctrl.possibleTickets">
|
||||||
|
<vn-td shrink>
|
||||||
|
<vn-check
|
||||||
|
ng-model="ticket.checked">
|
||||||
|
</vn-check>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td number>{{ticket.id}}</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
<span
|
||||||
|
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"
|
||||||
|
class="link">
|
||||||
|
{{ticket.nickname}}
|
||||||
|
</span>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td number shrink>{{ticket.packages}}</vn-td>
|
||||||
|
<vn-td expand>{{ticket.warehouse.name}}</vn-td>
|
||||||
|
<vn-td number shrink>{{ticket.address.postalCode}}</vn-td>
|
||||||
|
<vn-td expand title="{{ticket.address.street}}">{{ticket.address.street}}</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
</vn-table>
|
||||||
|
</vn-data-viewer>
|
||||||
|
</tpl-body>
|
||||||
|
<tpl-buttons>
|
||||||
|
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
|
||||||
|
<button response="ACCEPT" translate>Add</button>
|
||||||
|
</tpl-buttons>
|
||||||
|
</vn-dialog>
|
||||||
|
<vn-float-button
|
||||||
|
icon="add"
|
||||||
|
ng-click="$ctrl.openPossibleTicketsDialog()"
|
||||||
|
vn-tooltip="Add ticket"
|
||||||
|
vn-acl="delivery"
|
||||||
|
vn-acl-action="remove"
|
||||||
|
vn-bind="+"
|
||||||
|
fixed-bottom-right>
|
||||||
|
</vn-float-button>
|
|
@ -2,12 +2,23 @@ import ngModule from '../module';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($stateParams, $, $translate, $http, vnApp) {
|
constructor($stateParams, $scope, $translate, $http, vnApp, $filter) {
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
this.$stateParams = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$ = $;
|
this.$ = $scope;
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.vnApp = vnApp;
|
this.vnApp = vnApp;
|
||||||
|
this.$filter = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
set route(value) {
|
||||||
|
this._route = value;
|
||||||
|
if (value)
|
||||||
|
this.buildPossibleTicketsFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
get route() {
|
||||||
|
return this._route;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isChecked() {
|
get isChecked() {
|
||||||
|
@ -19,13 +30,37 @@ class Controller {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildPossibleTicketsFilter() {
|
||||||
|
let minDate = new Date(this.route.finished);
|
||||||
|
minDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let maxDate = new Date(this.route.finished);
|
||||||
|
maxDate.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
|
this.possibleTicketsFilter = {
|
||||||
|
where: {
|
||||||
|
zoneFk: this.route.zoneFk,
|
||||||
|
routeFk: null,
|
||||||
|
landed: {between: [minDate, maxDate]},
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'warehouse',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
relation: 'address'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
getHighestPriority() {
|
getHighestPriority() {
|
||||||
let max = 0;
|
let highestPriority = Math.max(...this.$.model.data.map(tag => {
|
||||||
this.$.model.data.forEach(tag => {
|
return tag.priority;
|
||||||
if (tag.priority > max)
|
}));
|
||||||
max = tag.priority;
|
return highestPriority + 1;
|
||||||
});
|
|
||||||
return max + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPriority(id, priority) {
|
setPriority(id, priority) {
|
||||||
|
@ -37,16 +72,16 @@ class Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getCheckedLines() {
|
getSelectedItems(items) {
|
||||||
let lines = [];
|
const selectedItems = [];
|
||||||
let data = this.tickets;
|
|
||||||
if (data) {
|
if (items) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
if (data[i].checked)
|
if (items[i].checked)
|
||||||
lines.push(data[i]);
|
selectedItems.push(items[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lines;
|
return selectedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
goToBuscaman() {
|
goToBuscaman() {
|
||||||
|
@ -54,7 +89,7 @@ class Controller {
|
||||||
let firstAddress = `46460 Av Espioca 100-46460 Silla`;
|
let firstAddress = `46460 Av Espioca 100-46460 Silla`;
|
||||||
let addresses = firstAddress;
|
let addresses = firstAddress;
|
||||||
|
|
||||||
let lines = this.getCheckedLines();
|
let lines = this.getSelectedItems(this.tickets);
|
||||||
|
|
||||||
let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
|
let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
|
||||||
lines.forEach(line => {
|
lines.forEach(line => {
|
||||||
|
@ -64,8 +99,8 @@ class Controller {
|
||||||
window.open(url + addresses, '_blank');
|
window.open(url + addresses, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
showDeleteConfirm(ticket) {
|
showDeleteConfirm(id) {
|
||||||
this.selectedTicket = ticket;
|
this.selectedTicket = id;
|
||||||
this.$.confirm.show();
|
this.$.confirm.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,14 +144,38 @@ class Controller {
|
||||||
this.$.clientDescriptor.show();
|
this.$.clientDescriptor.show();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openPossibleTicketsDialog() {
|
||||||
|
this.$.possibleTicketsModel.refresh();
|
||||||
|
this.$.possibleTicketsDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
setTicketsRoute(response) {
|
||||||
|
if (response === 'ACCEPT') {
|
||||||
|
let tickets = this.getSelectedItems(this.possibleTickets);
|
||||||
|
|
||||||
|
for (let i = 0; i < tickets.length; i++) {
|
||||||
|
delete tickets[i].checked;
|
||||||
|
tickets[i].routeFk = this.route.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$.possibleTicketsModel.save().then(() => {
|
||||||
|
this.$.model.data = this.$.model.data.concat(tickets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$translate', '$http', 'vnApp'];
|
Controller.$inject = ['$stateParams', '$scope', '$translate', '$http', 'vnApp', '$filter'];
|
||||||
|
|
||||||
ngModule.component('vnRouteTickets', {
|
ngModule.component('vnRouteTickets', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
require: {
|
require: {
|
||||||
card: '^vnRouteCard'
|
card: '^vnRouteCard'
|
||||||
},
|
},
|
||||||
controller: Controller
|
bindings: {
|
||||||
|
route: '<'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Route', () => {
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(angular.mock.module('route', $translateProvider => {
|
||||||
|
$translateProvider.translations('en', {});
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
controller = $componentController('vnRouteTickets');
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('route setter/getter', () => {
|
||||||
|
it('should return the route id', () => {
|
||||||
|
controller.route = 2;
|
||||||
|
|
||||||
|
expect(controller.route).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isChecked getter', () => {
|
||||||
|
it('should return false if none of the tickets is checked or there are no tickets', () => {
|
||||||
|
expect(controller.isChecked).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if any of the tickets is checked', () => {
|
||||||
|
controller.tickets = [{checked: true}];
|
||||||
|
|
||||||
|
expect(controller.isChecked).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('buildPossibleTicketsFilter()', () => {
|
||||||
|
it('should build the possible tickets filter', () => {
|
||||||
|
let expectedFilter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'warehouse',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'address'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
landed: {
|
||||||
|
between: [
|
||||||
|
jasmine.any(Date),
|
||||||
|
jasmine.any(Date)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
routeFk: null,
|
||||||
|
zoneFk: 67
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller.route = {
|
||||||
|
finished: new Date(),
|
||||||
|
routeFk: null,
|
||||||
|
zoneFk: 67
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.buildPossibleTicketsFilter();
|
||||||
|
|
||||||
|
expect(controller.possibleTicketsFilter).toEqual(expectedFilter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getHighestPriority()', () => {
|
||||||
|
it('should return the highest value found in priorities plus 1', () => {
|
||||||
|
controller.$.model = {data: [
|
||||||
|
{priority: 99},
|
||||||
|
{priority: 1},
|
||||||
|
{priority: 2},
|
||||||
|
{priority: 3},
|
||||||
|
{priority: 4},
|
||||||
|
{priority: 5},
|
||||||
|
]};
|
||||||
|
|
||||||
|
let result = controller.getHighestPriority();
|
||||||
|
|
||||||
|
expect(result).toEqual(100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setPriority()', () => {
|
||||||
|
it('should set a ticket priority', () => {
|
||||||
|
controller.$.model = {refresh: () => {}};
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
const ticketId = 1;
|
||||||
|
const priority = 999;
|
||||||
|
|
||||||
|
$httpBackend.expectPATCH(`/api/Tickets/${ticketId}/`).respond('ok');
|
||||||
|
controller.setPriority(ticketId, priority);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getSelectedItems()', () => {
|
||||||
|
it('should return the selected items', () => {
|
||||||
|
let items = [
|
||||||
|
{id: 1, checked: true},
|
||||||
|
{id: 2, checked: false},
|
||||||
|
{id: 3, checked: true},
|
||||||
|
{id: 4, checked: false},
|
||||||
|
{id: 5, checked: true},
|
||||||
|
];
|
||||||
|
|
||||||
|
let selectedItems = controller.getSelectedItems(items);
|
||||||
|
|
||||||
|
expect(selectedItems).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('goToBuscaman()', () => {
|
||||||
|
it('should open buscaman with the given arguments', () => {
|
||||||
|
spyOn(window, 'open');
|
||||||
|
const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460 Av Espioca 100-46460 Silla+to:n19 my street-n19 London';
|
||||||
|
controller.tickets = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
checked: true,
|
||||||
|
address: {
|
||||||
|
street: 'my street',
|
||||||
|
postalCode: 'n19',
|
||||||
|
city: 'London'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
controller.goToBuscaman();
|
||||||
|
|
||||||
|
expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showDeleteConfirm()', () => {
|
||||||
|
it('should open a confirm dialog after setting the selected ticket into the controller', () => {
|
||||||
|
controller.$.confirm = {show: () => {}};
|
||||||
|
spyOn(controller.$.confirm, 'show');
|
||||||
|
let ticketId = 1;
|
||||||
|
|
||||||
|
controller.showDeleteConfirm(ticketId);
|
||||||
|
|
||||||
|
expect(controller.selectedTicket).toEqual(ticketId);
|
||||||
|
expect(controller.$.confirm.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('removeTicketFromRoute()', () => {
|
||||||
|
it('should perform a patch query then call showSuccess and updateVolume methods', () => {
|
||||||
|
spyOn(controller, 'updateVolume');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
let ticketId = 1;
|
||||||
|
controller.selectedTicket = ticketId;
|
||||||
|
|
||||||
|
$httpBackend.expectPATCH(`/api/Tickets/${ticketId}/`).respond('ok');
|
||||||
|
controller.removeTicketFromRoute('ACCEPT');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket removed from route');
|
||||||
|
expect(controller.updateVolume).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updateVolume()', () => {
|
||||||
|
it('should perform a POST query then call both reload and refresh methods', () => {
|
||||||
|
controller.$.model = {refresh: () => {}};
|
||||||
|
controller.card = {reload: () => {}};
|
||||||
|
controller.$stateParamds = {id: 999};
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.card, 'reload');
|
||||||
|
|
||||||
|
let ticketId = 1;
|
||||||
|
controller.selectedTicket = ticketId;
|
||||||
|
|
||||||
|
const url = `/route/api/Routes/${controller.$stateParams.id}/updateVolume`;
|
||||||
|
$httpBackend.expectPOST(url).respond('ok');
|
||||||
|
controller.updateVolume();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
expect(controller.card.reload).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('guessPriority()', () => {
|
||||||
|
it('should perform a GET query then call both refresh and showSuccess methods', () => {
|
||||||
|
controller.$.model = {refresh: () => {}};
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
controller.$stateParams = {id: 99};
|
||||||
|
|
||||||
|
const url = `/api/Routes/${controller.$stateParams.id}/guessPriority/`;
|
||||||
|
$httpBackend.expectGET(url).respond('ok');
|
||||||
|
controller.guessPriority();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Order changed');
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showTicketDescriptor()', () => {
|
||||||
|
it('should call the descriptor show function after setting the parent and the ticket id', () => {
|
||||||
|
controller.$.ticketDescriptor = {show: () => {}};
|
||||||
|
spyOn(controller.$.ticketDescriptor, 'show');
|
||||||
|
const event = {target: {}, preventDefault: () => {}};
|
||||||
|
spyOn(event, 'preventDefault');
|
||||||
|
const ticketId = 999;
|
||||||
|
controller.showTicketDescriptor(event, ticketId);
|
||||||
|
|
||||||
|
expect(controller.$.ticketDescriptor.ticketFk).toEqual(ticketId);
|
||||||
|
expect(controller.$.ticketDescriptor.show).toHaveBeenCalledWith();
|
||||||
|
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showClientDescriptor()', () => {
|
||||||
|
it('should call the descriptor show method after setting the parent and the client id', () => {
|
||||||
|
controller.$.clientDescriptor = {show: () => {}};
|
||||||
|
spyOn(controller.$.clientDescriptor, 'show');
|
||||||
|
const event = {target: {}, preventDefault: () => {}};
|
||||||
|
spyOn(event, 'preventDefault');
|
||||||
|
const clientId = 999;
|
||||||
|
controller.showClientDescriptor(event, clientId);
|
||||||
|
|
||||||
|
expect(controller.$.clientDescriptor.clientFk).toEqual(clientId);
|
||||||
|
expect(controller.$.clientDescriptor.show).toHaveBeenCalledWith();
|
||||||
|
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('openPossibleTicketsDialog()', () => {
|
||||||
|
it('should call both refresh and show methods in posible tickets model and dialog', () => {
|
||||||
|
controller.$.possibleTicketsModel = {refresh: () => {}};
|
||||||
|
spyOn(controller.$.possibleTicketsModel, 'refresh');
|
||||||
|
controller.$.possibleTicketsDialog = {show: () => {}};
|
||||||
|
spyOn(controller.$.possibleTicketsDialog, 'show');
|
||||||
|
|
||||||
|
controller.openPossibleTicketsDialog();
|
||||||
|
|
||||||
|
expect(controller.$.possibleTicketsModel.refresh).toHaveBeenCalledWith();
|
||||||
|
expect(controller.$.possibleTicketsDialog.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setTicketsRoute()', () => {
|
||||||
|
it('should perform a POST query to add tickets to the route', done => {
|
||||||
|
controller.$.possibleTicketsModel = {save: () => {}};
|
||||||
|
spyOn(controller.$.possibleTicketsModel, 'save').and.returnValue(Promise.resolve());
|
||||||
|
controller.$.model = {data: [
|
||||||
|
{id: 1, checked: false}
|
||||||
|
]};
|
||||||
|
|
||||||
|
controller.route = {id: 111};
|
||||||
|
|
||||||
|
controller.possibleTickets = [
|
||||||
|
{id: 2, checked: false},
|
||||||
|
{id: 3, checked: true},
|
||||||
|
{id: 4, checked: false},
|
||||||
|
{id: 5, checked: true},
|
||||||
|
];
|
||||||
|
|
||||||
|
let expectedResult = [
|
||||||
|
{checked: false, id: 1},
|
||||||
|
{id: 3, routeFk: 111},
|
||||||
|
{id: 5, routeFk: 111}
|
||||||
|
];
|
||||||
|
|
||||||
|
controller.setTicketsRoute('ACCEPT').then(() => {
|
||||||
|
expect(controller.$.model.data).toEqual(expectedResult);
|
||||||
|
done();
|
||||||
|
}).catch(done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should just return a promise', () => {
|
||||||
|
expect(controller.setTicketsRoute('CANCEL')).toEqual(jasmine.any(Promise));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,4 +3,6 @@ Open buscaman: Abrir buscaman
|
||||||
Ticket removed from route: Ticket borrado de la ruta
|
Ticket removed from route: Ticket borrado de la ruta
|
||||||
Order changed: Orden cambiado
|
Order changed: Orden cambiado
|
||||||
Delete ticket from route?: ¿Borrar ticket de la ruta?
|
Delete ticket from route?: ¿Borrar ticket de la ruta?
|
||||||
Sort routes: Ordenar rutas
|
Sort routes: Ordenar rutas
|
||||||
|
Add ticket: Añadir ticket
|
||||||
|
Tickets to add: Tickets a añadir
|
|
@ -38,27 +38,27 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
let options = {transaction: tx};
|
let options = {transaction: tx};
|
||||||
|
|
||||||
let item = await models.Item.findById(ctx.args.itemFk);
|
let item = await models.Item.findById(ctx.args.itemFk, null, options);
|
||||||
if (!item)
|
if (!item)
|
||||||
throw new UserError(`That item doesn't exists`);
|
throw new UserError(`That item doesn't exists`);
|
||||||
|
|
||||||
let request = await models.TicketRequest.findById(ctx.args.id, {
|
let request = await models.TicketRequest.findById(ctx.args.id, {
|
||||||
include: {relation: 'ticket'}
|
include: {relation: 'ticket'}
|
||||||
});
|
}, options);
|
||||||
|
|
||||||
let [[stock]] = await Self.rawSql(`CALL vn.getItemVisibleAvailable(?,?,?,?)`, [
|
let [[stock]] = await Self.rawSql(`CALL vn.getItemVisibleAvailable(?,?,?,?)`, [
|
||||||
ctx.args.itemFk,
|
ctx.args.itemFk,
|
||||||
request.ticket().shipped,
|
request.ticket().shipped,
|
||||||
request.ticket().warehouseFk,
|
request.ticket().warehouseFk,
|
||||||
false
|
false
|
||||||
]);
|
], options);
|
||||||
|
|
||||||
if (stock.available < 0)
|
if (stock.available < 0)
|
||||||
throw new UserError(`This item is not available`);
|
throw new UserError(`This item is not available`);
|
||||||
|
|
||||||
|
|
||||||
if (request.saleFk) {
|
if (request.saleFk) {
|
||||||
sale = await models.Sale.findById(request.saleFk);
|
sale = await models.Sale.findById(request.saleFk, null, options);
|
||||||
sale.updateAttributes({
|
sale.updateAttributes({
|
||||||
itemFk: ctx.args.itemFk,
|
itemFk: ctx.args.itemFk,
|
||||||
quantity: ctx.args.quantity,
|
quantity: ctx.args.quantity,
|
||||||
|
@ -71,7 +71,11 @@ module.exports = Self => {
|
||||||
quantity: ctx.args.quantity,
|
quantity: ctx.args.quantity,
|
||||||
concept: item.name
|
concept: item.name
|
||||||
}, options);
|
}, options);
|
||||||
request.updateAttributes({saleFk: sale.id, itemFk: sale.itemFk, isOk: true}, options);
|
request.updateAttributes({
|
||||||
|
saleFk: sale.id,
|
||||||
|
itemFk: sale.itemFk,
|
||||||
|
isOk: true
|
||||||
|
}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
query = `CALL vn.ticketCalculateSale(?)`;
|
query = `CALL vn.ticketCalculateSale(?)`;
|
||||||
|
@ -86,6 +90,8 @@ module.exports = Self => {
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
await tx.commit();
|
await tx.commit();
|
||||||
|
|
||||||
|
return sale;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
@ -29,7 +29,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
isOk: false,
|
isOk: false,
|
||||||
atenderFk: worker.id,
|
attenderFk: worker.id,
|
||||||
response: ctx.args.observation,
|
response: ctx.args.observation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ module.exports = Self => {
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: `Search by warehouse`
|
description: `Search by warehouse`
|
||||||
}, {
|
}, {
|
||||||
arg: 'atenderFk',
|
arg: 'attenderFk',
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: `Search requests atended by the given worker`
|
description: `Search requests atended by the given worker`
|
||||||
}, {
|
}, {
|
||||||
|
@ -65,7 +65,7 @@ module.exports = Self => {
|
||||||
let worker = await Self.app.models.Worker.findOne({where: {userFk: userId}});
|
let worker = await Self.app.models.Worker.findOne({where: {userFk: userId}});
|
||||||
|
|
||||||
if (ctx.args.mine)
|
if (ctx.args.mine)
|
||||||
ctx.args.atenderFk = worker.id;
|
ctx.args.attenderFk = worker.id;
|
||||||
|
|
||||||
let where = buildFilter(ctx.args, (param, value) => {
|
let where = buildFilter(ctx.args, (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
|
@ -75,7 +75,7 @@ module.exports = Self => {
|
||||||
: {'t.nickname': {like: `%${value}%`}};
|
: {'t.nickname': {like: `%${value}%`}};
|
||||||
case 'ticketFk':
|
case 'ticketFk':
|
||||||
return {'t.id': value};
|
return {'t.id': value};
|
||||||
case 'atenderFk':
|
case 'attenderFk':
|
||||||
return {'tr.atenderFk': value};
|
return {'tr.atenderFk': value};
|
||||||
case 'isOk':
|
case 'isOk':
|
||||||
return {'tr.isOk': value};
|
return {'tr.isOk': value};
|
||||||
|
@ -106,13 +106,13 @@ module.exports = Self => {
|
||||||
tr.ticketFk,
|
tr.ticketFk,
|
||||||
tr.quantity,
|
tr.quantity,
|
||||||
tr.price,
|
tr.price,
|
||||||
tr.atenderFk,
|
tr.atenderFk attenderFk,
|
||||||
tr.description,
|
tr.description,
|
||||||
tr.response,
|
tr.response,
|
||||||
tr.saleFk,
|
tr.saleFk,
|
||||||
tr.isOk,
|
tr.isOk,
|
||||||
s.quantity AS saleQuantity,
|
s.quantity AS saleQuantity,
|
||||||
s.itemFK,
|
s.itemFk,
|
||||||
i.name AS itemDescription,
|
i.name AS itemDescription,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
t.nickname,
|
t.nickname,
|
||||||
|
|
|
@ -1,27 +1,14 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('ticket-request confirm()', () => {
|
describe('ticket-request confirm()', () => {
|
||||||
let request;
|
let originalRequest;
|
||||||
let sale;
|
let originalSale;
|
||||||
let createdSaleId;
|
let createdSaleId;
|
||||||
|
|
||||||
afterAll(async done => {
|
afterAll(async done => {
|
||||||
const paramsForRequest = {
|
await originalRequest.updateAttributes(originalRequest);
|
||||||
saleFk: request.saleFk,
|
await originalSale.updateAttributes(originalSale);
|
||||||
isOk: request.isOk,
|
await app.models.Sale.destroyById(createdSaleId);
|
||||||
itemFk: request.itemFk,
|
|
||||||
ticketFk: request.ticketFk
|
|
||||||
};
|
|
||||||
|
|
||||||
const paramsForSale = {
|
|
||||||
itemFk: sale.itemFk,
|
|
||||||
quantity: sale.quantity,
|
|
||||||
concept: sale.concept,
|
|
||||||
};
|
|
||||||
|
|
||||||
await request.updateAttributes(paramsForRequest);
|
|
||||||
await sale.updateAttributes(paramsForSale);
|
|
||||||
app.models.Sale.destroyById(createdSaleId);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,10 +52,11 @@ describe('ticket-request confirm()', () => {
|
||||||
const itemId = 1;
|
const itemId = 1;
|
||||||
const quantity = 10;
|
const quantity = 10;
|
||||||
|
|
||||||
request = await app.models.TicketRequest.findById(requestId);
|
originalRequest = await app.models.TicketRequest.findById(requestId);
|
||||||
sale = await app.models.Sale.findById(saleId);
|
originalSale = await app.models.Sale.findById(saleId);
|
||||||
|
|
||||||
request.updateAttributes({saleFk: saleId});
|
const request = await app.models.TicketRequest.findById(requestId);
|
||||||
|
await request.updateAttributes({saleFk: saleId});
|
||||||
|
|
||||||
let ctx = {req: {accessToken: {userId: 9}}, args: {
|
let ctx = {req: {accessToken: {userId: 9}}, args: {
|
||||||
itemFk: itemId,
|
itemFk: itemId,
|
||||||
|
@ -89,7 +77,8 @@ describe('ticket-request confirm()', () => {
|
||||||
const itemId = 1;
|
const itemId = 1;
|
||||||
const quantity = 10;
|
const quantity = 10;
|
||||||
|
|
||||||
request.updateAttributes({saleFk: null});
|
const request = await app.models.TicketRequest.findById(requestId);
|
||||||
|
await request.updateAttributes({saleFk: null});
|
||||||
|
|
||||||
let ctx = {req: {accessToken: {userId: 9}}, args: {
|
let ctx = {req: {accessToken: {userId: 9}}, args: {
|
||||||
itemFk: itemId,
|
itemFk: itemId,
|
||||||
|
|
|
@ -5,7 +5,7 @@ describe('ticket-request deny()', () => {
|
||||||
afterAll(async done => {
|
afterAll(async done => {
|
||||||
let params = {
|
let params = {
|
||||||
isOk: null,
|
isOk: null,
|
||||||
atenderFk: request.atenderFk,
|
attenderFk: request.attenderFk,
|
||||||
response: null,
|
response: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue