This commit is contained in:
Javi Gallego 2019-10-29 12:58:26 +01:00
commit 700c092b90
725 changed files with 22564 additions and 15821 deletions

View File

@ -9,25 +9,31 @@ module.exports = Self => {
{
arg: 'warehouseId',
type: 'Number',
description: 'The warehouse id'
description: 'The warehouse id',
required: true
}, {
arg: 'companyId',
type: 'Number',
description: 'The company id'
description: 'The company id',
required: true
}, {
arg: 'dmsTypeId',
type: 'Number',
description: 'The dms type id'
description: 'The dms type id',
required: true
}, {
arg: 'reference',
type: 'String'
type: 'String',
required: true
}, {
arg: 'description',
type: 'String'
type: 'String',
required: true
}, {
arg: 'hasFile',
type: 'Boolean',
description: 'True if has an attached file'
description: 'True if has an attached file',
required: true
}],
returns: {
type: 'Object',

View File

@ -52,6 +52,15 @@
},
"Postcode": {
"dataSource": "vn"
},
"UserPhoneType": {
"dataSource": "vn"
},
"UserPhone": {
"dataSource": "vn"
},
"UserLog": {
"dataSource": "vn"
}
}

58
back/models/user-log.json Normal file
View File

@ -0,0 +1,58 @@
{
"name": "UserLog",
"base": "VnModel",
"options": {
"mysql": {
"table": "userLog"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"forceId": false
},
"originFk": {
"type": "Number",
"required": true
},
"userFk": {
"type": "Number"
},
"action": {
"type": "String",
"required": true
},
"changedModel": {
"type": "String"
},
"oldInstance": {
"type": "Object"
},
"newInstance": {
"type": "Object"
},
"creationDate": {
"type": "Date"
},
"changedModelId": {
"type": "Number"
},
"changedModelValue": {
"type": "String"
},
"description": {
"type": "String"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
}
},
"scope": {
"order": ["creationDate DESC", "id DESC"]
}
}

View File

@ -0,0 +1,18 @@
{
"name": "UserPhoneType",
"base": "VnModel",
"options": {
"mysql": {
"table": "userPhoneType"
}
},
"properties": {
"code": {
"id": true,
"type": "String"
},
"description": {
"type": "String"
}
}
}

View File

@ -0,0 +1,9 @@
let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`This phone already exists`);
return err;
});
};

View File

@ -0,0 +1,39 @@
{
"name": "UserPhone",
"base": "Loggable",
"log": {
"model":"UserLog",
"relation": "user"
},
"options": {
"mysql": {
"table": "userPhone"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"phone": {
"type": "Number",
"required": true
},
"typeFk": {
"type": "String",
"required": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
},
"type": {
"type": "belongsTo",
"model": "UserPhoneType",
"foreignKey": "typeFk"
}
}
}

View File

@ -1,23 +0,0 @@
ALTER TABLE `vn2008`.`gestdoc`
ADD COLUMN `contentType` VARCHAR(100) NULL AFTER `file`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`dms` AS
SELECT
`g`.`id` AS `id`,
`g`.`gesttip_id` AS `dmsTypeFk`,
`g`.`file` AS `file`,
`g`.`contentType` AS `contentType`,
`g`.`trabajador_id` AS `workerFk`,
`g`.`warehouse_id` AS `warehouseFk`,
`g`.`emp_id` AS `companyFk`,
`g`.`orden` AS `hardCopyNumber`,
`g`.`original` AS `hasFile`,
`g`.`sref` AS `reference`,
`g`.`brief` AS `description`,
`g`.`odbc_date` AS `created`
FROM
`vn2008`.`gestdoc` `g`;

View File

@ -1,6 +0,0 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Dms', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
('ClaimDms', 'removeFile', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('ClaimDms', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Claim', 'uploadFile', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -1,2 +0,0 @@
ALTER TABLE `vn`.`claimLog`
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT ;

View File

@ -1,14 +0,0 @@
DROP TRIGGER IF EXISTS `vn2008`.`ticket_afterUpdate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`ticket_afterUpdate`
AFTER UPDATE ON `Tickets`
FOR EACH ROW
BEGIN
IF !(NEW.Id_Ticket <=> OLD.Id_Ticket)
OR !(NEW.warehouse_id <=> OLD.warehouse_id)
OR !(NEW.Fecha <=> OLD.Fecha) THEN
CALL stock.log_add('ticket', NEW.Id_Ticket, OLD.Id_Ticket);
END IF;
END$$
DELIMITER ;

View File

@ -1,2 +0,0 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES ('Sale', 'updateConcept', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -1,258 +0,0 @@
DROP procedure IF EXISTS `vn`.`catalog_componentCalculate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`catalog_componentCalculate`(
vZoneFk INT,
vAddressFk INT,
vShipped DATE)
proc: BEGIN
/**
* Calcula los componentes de los articulos de tmp.ticketLot
*
* @param vZoneFk para calcular el transporte
* @param vAgencyModeFk Id del modo de agencia
* @param tmp.ticketLot (warehouseFk,available,itemFk,buyFk)
*
* @return tmp.ticketComponent(itemFk, warehouseFk, available, rate2, rate3, minPrice,
* packing, grouping, groupingMode, buyFk, typeFk)
* @return tmp.ticketComponentPrice (warehouseFk, itemFk, rate, grouping, price)
*/
DECLARE vClientFk INT;
DECLARE vGeneralInflationCoefficient INT DEFAULT 1;
DECLARE vMinimumDensityWeight INT DEFAULT 167;
DECLARE vBoxFreightItem INT DEFAULT 71;
DECLARE vBoxVolume BIGINT; -- DEFAULT 138000;
DECLARE vSpecialPriceComponent INT DEFAULT 10;
DECLARE vDeliveryComponent INT DEFAULT 15;
DECLARE vRecoveryComponent INT DEFAULT 17;
DECLARE vSellByPacketComponent INT DEFAULT 22;
DECLARE vBuyValueComponent INT DEFAULT 28;
DECLARE vMarginComponent INT DEFAULT 29;
DECLARE vDiscountLastItemComponent INT DEFAULT 32;
DECLARE vExtraBaggedComponent INT DEFAULT 38;
DECLARE vManaAutoComponent INT DEFAULT 39;
SELECT volume INTO vBoxVolume
FROM vn.packaging
WHERE id = '94';
SELECT clientFk INTO vClientFK
FROM address
WHERE id = vAddressFk;
SET @rate2 := 0;
SET @rate3 := 0;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentCalculate;
CREATE TEMPORARY TABLE tmp.ticketComponentCalculate
(PRIMARY KEY (itemFk, warehouseFk))
ENGINE = MEMORY
SELECT
tl.itemFk, tl.warehouseFk, tl.available,
IF((@rate2 := IFNULL(pf.rate2, b.price2)) < i.minPrice AND i.hasMinPrice, i.minPrice, @rate2) * 1.0 rate2,
IF((@rate3 := IFNULL(pf.rate3, b.price3)) < i.minPrice AND i.hasMinPrice, i.minPrice, @rate3) * 1.0 rate3,
IFNULL(pf.rate3, 0) AS minPrice,
IFNULL(pf.packing, b.packing) packing,
IFNULL(pf.`grouping`, b.`grouping`) grouping,
ABS(IFNULL(pf.box, b.groupingMode)) groupingMode,
tl.buyFk,
i.typeFk,
IF(i.hasKgPrice,(b.packing * b.weight) / 1000, NULL) weightPacking
FROM tmp.ticketLot tl
JOIN buy b ON b.id = tl.buyFk
JOIN item i ON i.id = tl.itemFk
JOIN itemType it ON it.id = i.typeFk
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
LEFT JOIN specialPrice sp ON sp.itemFk = i.id AND sp.clientFk = vClientFk
LEFT JOIN (
SELECT * FROM (
SELECT pf.itemFk, pf.`grouping`, pf.packing, pf.box, pf.rate2, pf.rate3, z.warehouseFk
FROM priceFixed pf
JOIN zone z ON z.warehouseFk = pf.warehouseFk OR pf.warehouseFk = 0
WHERE vShipped BETWEEN pf.started AND pf.ended ORDER BY pf.itemFk, pf.warehouseFk DESC
) tpf
GROUP BY tpf.itemFk, tpf.warehouseFk
) pf ON pf.itemFk = tl.itemFk AND pf.warehouseFk = tl.warehouseFk
WHERE b.buyingValue + b.freightValue + b.packageValue + b.comissionValue > 0.01 AND ic.display <> 0;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent;
CREATE TEMPORARY TABLE tmp.ticketComponent (
`warehouseFk` INT UNSIGNED NOT NULL,
`itemFk` INT NOT NULL,
`componentFk` INT UNSIGNED NOT NULL,
`cost` DECIMAL(10,4) NOT NULL,
INDEX `itemWarehouse` USING BTREE (`itemFk` ASC, `warehouseFk` ASC),
UNIQUE INDEX `itemWarehouseComponent` (`itemFk` ASC, `warehouseFk` ASC, `componentFk` ASC));
INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
SELECT
tcc.warehouseFk,
tcc.itemFk,
vBuyValueComponent,
b.buyingValue + b.freightValue + b.packageValue + b.comissionValue
FROM tmp.ticketComponentCalculate tcc
JOIN buy b ON b.id = tcc.buyFk;
INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
SELECT
tcc.warehouseFk,
tcc.itemFk,
vMarginComponent,
tcc.rate3 - b.buyingValue - b.freightValue - b.packageValue - b.comissionValue
FROM tmp.ticketComponentCalculate tcc
JOIN buy b ON b.id = tcc.buyFk;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentBase;
CREATE TEMPORARY TABLE tmp.ticketComponentBase ENGINE = MEMORY
SELECT tc.itemFk, ROUND(SUM(tc.cost), 4) AS base, tc.warehouseFk
FROM tmp.ticketComponent tc
GROUP BY tc.itemFk, warehouseFk;
INSERT INTO tmp.ticketComponent
SELECT tcb.warehouseFk, tcb.itemFk, vRecoveryComponent, ROUND(tcb.base * LEAST(cr.recobro, 0.25), 3)
FROM tmp.ticketComponentBase tcb
JOIN bi.claims_ratio cr ON cr.Id_Cliente = vClientFk
WHERE cr.recobro > 0.009;
INSERT INTO tmp.ticketComponent
SELECT tcb.warehouseFk, tcb.itemFk, vManaAutoComponent, ROUND(base * (0.01 + prices_modifier_rate), 3) as manaAuto
FROM tmp.ticketComponentBase tcb
JOIN `client` c on c.id = vClientFk
JOIN bs.mana_spellers ms ON c.salesPersonFk = ms.Id_Trabajador
WHERE ms.prices_modifier_activated
HAVING manaAuto <> 0;
INSERT INTO tmp.ticketComponent
SELECT tcb.warehouseFk,
tcb.itemFk,
cr.id,
GREATEST(IFNULL(ROUND(tcb.base * cr.tax, 4), 0), tcc.minPrice - tcc.rate3)
FROM tmp.ticketComponentBase tcb
JOIN componentRate cr
JOIN tmp.ticketComponentCalculate tcc ON tcc.itemFk = tcb.itemFk AND tcc.warehouseFk = tcb.warehouseFk
LEFT JOIN specialPrice sp ON sp.clientFk = vClientFk AND sp.itemFk = tcc.itemFk
WHERE cr.id = vDiscountLastItemComponent AND cr.tax <> 0 AND tcc.minPrice < tcc.rate3 AND sp.value IS NULL;
INSERT INTO tmp.ticketComponent
SELECT tcc.warehouseFk, tcc.itemFk, vSellByPacketComponent, tcc.rate2 - tcc.rate3
FROM tmp.ticketComponentCalculate tcc
JOIN buy b ON b.id = tcc.buyFk
LEFT JOIN specialPrice sp ON sp.clientFk = vClientFk AND sp.itemFk = tcc.itemFk
WHERE sp.value IS NULL;
INSERT INTO tmp.ticketComponent
SELECT tcc.warehouseFK,
tcc.itemFk,
vDeliveryComponent,
vGeneralInflationCoefficient
* ROUND((
i.compression
* r.cm3
* IF(am.deliveryMethodFk = 1, (GREATEST(i.density, vMinimumDensityWeight) / vMinimumDensityWeight), 1)
* IFNULL((z.price - z.bonus)
* 1/*amz.inflation*/ , 50)) / vBoxVolume, 4
) cost
FROM tmp.ticketComponentCalculate tcc
JOIN item i ON i.id = tcc.itemFk
JOIN zone z ON z.id = vZoneFk
JOIN agencyMode am ON am.id = z.agencyModeFk
LEFT JOIN bi.rotacion r ON r.warehouse_id = tcc.warehouseFk
AND r.Id_Article = tcc.itemFk
HAVING cost <> 0;
IF (SELECT COUNT(*) FROM vn.addressForPackaging WHERE addressFk = vAddressFk) THEN
INSERT INTO tmp.ticketComponent
SELECT tcc.warehouseFk, b.itemFk, vExtraBaggedComponent, ap.packagingValue cost
FROM tmp.ticketComponentCalculate tcc
JOIN vn.addressForPackaging ap
WHERE ap.addressFk = vAddressFk;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentCopy;
CREATE TEMPORARY TABLE tmp.ticketComponentCopy ENGINE = MEMORY
SELECT * FROM tmp.ticketComponent;
INSERT INTO tmp.ticketComponent
SELECT tcc.warehouseFk,
tcc.itemFk,
vSpecialPriceComponent,
sp.value - SUM(tcc.cost) sumCost
FROM tmp.ticketComponentCopy tcc
JOIN componentRate cr ON cr.id = tcc.componentFk
JOIN specialPrice sp ON sp.clientFk = vClientFK AND sp.itemFk = tcc.itemFk
WHERE cr.classRate IS NULL
GROUP BY tcc.itemFk, tcc.warehouseFk
HAVING ABS(sumCost) > 0.001;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentSum;
CREATE TEMPORARY TABLE tmp.ticketComponentSum
(INDEX (itemFk, warehouseFk))
ENGINE = MEMORY
SELECT SUM(cost) sumCost, tc.itemFk, tc.warehouseFk, cr.classRate
FROM tmp.ticketComponent tc
JOIN componentRate cr ON cr.id = tc.componentFk
GROUP BY tc.itemFk, tc.warehouseFk, cr.classRate;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentRate;
CREATE TEMPORARY TABLE tmp.ticketComponentRate ENGINE = MEMORY
SELECT tcc.warehouseFk,
tcc.itemFk,
1 rate,
IF(tcc.groupingMode = 1, tcc.`grouping`, 1) grouping,
CAST(SUM(tcs.sumCost) AS DECIMAL(10,2)) price,
CAST(SUM(tcs.sumCost) AS DECIMAL(10,2)) / weightPacking priceKg
FROM tmp.ticketComponentCalculate tcc
JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk
AND tcs.warehouseFk = tcc.warehouseFk
WHERE IFNULL(tcs.classRate, 1) = 1
AND tcc.groupingMode < 2 AND (tcc.packing > tcc.`grouping` or tcc.groupingMode = 0)
GROUP BY tcs.warehouseFk, tcs.itemFk;
INSERT INTO tmp.ticketComponentRate (warehouseFk, itemFk, rate, grouping, price, priceKg)
SELECT
tcc.warehouseFk,
tcc.itemFk,
2 rate,
tcc.packing grouping,
SUM(tcs.sumCost) price,
SUM(tcs.sumCost) / weightPacking priceKg
FROM tmp.ticketComponentCalculate tcc
JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk
AND tcs.warehouseFk = tcc.warehouseFk
WHERE tcc.available IS NULL OR (IFNULL(tcs.classRate, 2) = 2
AND tcc.packing > 0 AND tcc.available >= tcc.packing)
GROUP BY tcs.warehouseFk, tcs.itemFk;
INSERT INTO tmp.ticketComponentRate (warehouseFk, itemFk, rate, grouping, price, priceKg)
SELECT
tcc.warehouseFk,
tcc.itemFk,
3 rate,
tcc.available grouping,
SUM(tcs.sumCost) price,
SUM(tcs.sumCost) / weightPacking priceKg
FROM tmp.ticketComponentCalculate tcc
JOIN tmp.ticketComponentSum tcs ON tcs.itemFk = tcc.itemFk
AND tcs.warehouseFk = tcc.warehouseFk
WHERE IFNULL(tcs.classRate, 3) = 3
GROUP BY tcs.warehouseFk, tcs.itemFk;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentPrice;
CREATE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY
SELECT * FROM (
SELECT * FROM tmp.ticketComponentRate ORDER BY price
) t
GROUP BY itemFk, warehouseFk, `grouping`;
DROP TEMPORARY TABLE
tmp.ticketComponentCalculate,
tmp.ticketComponentSum,
tmp.ticketComponentBase,
tmp.ticketComponentRate,
tmp.ticketComponentCopy;
END$$
DELIMITER ;

View File

@ -1,2 +0,0 @@
ALTER TABLE `vn2008`.`Movimientos_componentes`
CHANGE COLUMN `Valor` `Valor` DECIMAL(10,4) NOT NULL ;

View File

@ -1,16 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `ticketCalculate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticketCalculate`(
vLanded DATE,
vAddressFk INT,
vAgencyModeFk INT)
proc: BEGIN
-- OBSOLETO utilizar catalog_calculate
CALL vn.catalog_calculate(vLanded, vAddressFk, vAgencyModeFk);
END$$
DELIMITER ;

View File

@ -1,26 +0,0 @@
ALTER TABLE `vn2008`.`warehouse`
ADD COLUMN `hasStowaway` TINYINT(1) NOT NULL DEFAULT 0 AFTER `hasConfectionTeam`;
UPDATE `vn2008`.`warehouse` SET `hasStowaway` = '1' WHERE (`id` = '1');
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`warehouse` AS
SELECT
`t`.`id` AS `id`,
`t`.`name` AS `name`,
`t`.`inventario` AS `isInventory`,
`t`.`fuente` AS `isFeedStock`,
`t`.`is_comparative` AS `isComparative`,
`t`.`comisionantes` AS `hasComission`,
`t`.`reserve` AS `hasAvailable`,
`t`.`isManaged` AS `isManaged`,
`t`.`tpv` AS `isForTicket`,
`t`.`hasStowaway` AS `hasStowaway`
FROM
`vn2008`.`warehouse` `t`;

View File

@ -1,47 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneGetLanded`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneGetLanded`(vShipped DATE, vAddressFk INT, vAgencyModeFk INT, vWarehouseFk INT)
BEGIN
/**
* Devuelve una tabla temporal con el dia de recepcion para vShipped.
*
* @param vShipped Fecha de preparacion de mercancia
* @param vAddressFk Id de consignatario, %NULL para recogida
* @param vAgencyModeFk Id agencia
* @table tmp.zoneGetLanded Datos de recepción
*/
DECLARE vPostalCode varchar(10);
SELECT postalCode INTO vPostalCode
FROM address WHERE id = vAddressFk;
DROP TEMPORARY TABLE IF EXISTS tmp.zoneGetLanded;
CREATE TEMPORARY TABLE tmp.zoneGetLanded
ENGINE = MEMORY
SELECT
id zoneFk,
vShipped shipped,
delivered landed,
vWarehouseFk warehouseFk,
agencyModeFk,
isIncluded
FROM (
SELECT zi.isIncluded, zc.delivered, z.id, z.agencyModeFk
FROM vn.zoneGeo zgSon
JOIN vn.zoneGeo zgFather ON zgSon.lft BETWEEN zgFather.lft AND zgFather.rgt
JOIN zoneIncluded zi ON zi.geoFk = zgFather.id
JOIN zone z ON z.id = zi.zoneFk
JOIN zoneCalendar zc ON zc.zoneFk = z.id
WHERE zgSon.`name` LIKE vPostalCode
AND zc.delivered = TIMESTAMPADD(DAY,z.travelingDays, vShipped)
AND IF(vShipped = CURDATE(), hour(now()) < hour(z.`hour`),TRUE)
AND z.agencyModeFk = vAgencyModeFk
AND z.warehouseFk = vWarehouseFk
ORDER BY zgFather.depth DESC) t
GROUP BY zoneFk
HAVING isIncluded > 0
LIMIT 1;
END$$
DELIMITER ;

View File

@ -1,47 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneGetShipped`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneGetShipped`(vLanded DATE, vAddressFk INT, vAgencyModeFk INT, vWarehouseFk INT)
BEGIN
/**
* Devuelve la mínima fecha de envía para cada warehouse
*
* @param vLanded La fecha de recepcion
* @param vAddressFk Id del consignatario
* @param vAgencyModeFk Id de la agencia
* @return tmp.zoneGetShipped
*/
DECLARE vPostalCode varchar(10);
SELECT postalCode INTO vPostalCode
FROM address WHERE id = vAddressFk;
SELECT * FROM (
SELECT * FROM (
SELECT z.id zoneFk,
TIMESTAMPADD(DAY,-z.travelingDays, vLanded) shipped,
vLanded landed,
vWarehouseFk warehouseFk,
z.agencyModeFk,
zi.isIncluded
FROM zoneGeo zgSon
JOIN zoneGeo zgFather ON zgSon.lft BETWEEN zgFather.lft AND zgFather.rgt
JOIN zoneIncluded zi ON zi.geoFk = zgFather.id
JOIN zone z ON z.id = zi.zoneFk
JOIN zoneCalendar zc ON zc.zoneFk = z.id
WHERE zgSon.`name` LIKE vPostalCode
AND zc.delivered = vLanded
AND z.agencyModeFk = vAgencyModeFk
AND z.warehouseFk = vWarehouseFk
AND IF(TIMESTAMPADD(DAY,-z.travelingDays, vLanded) = CURDATE(), hour(now()) < hour(z.`hour`),TRUE)
ORDER BY z.id, zgFather.depth DESC, isIncluded DESC) t
GROUP BY zoneFk
HAVING isIncluded > 0
ORDER BY shipped)
t
GROUP BY agencyModeFk;
END$$
DELIMITER ;

View File

@ -1,59 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `zoneGetAgency`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zoneGetAgency`(vAddress INT, vLanded DATE)
BEGIN
/**
* OBSOLETO USAR vn.zone_getAvailable
* Devuelve el listado de agencias disponibles para la fecha
* y dirección pasadas.
*
* @param vAddress Id de dirección de envío, %NULL si es recogida
* @param vDate Fecha de recogida
* @select Listado de agencias disponibles
*/
DECLARE vGeoFk INT;
SELECT p.geoFk INTO vGeoFk
FROM address a
JOIN town t ON t.provinceFk = a.provinceFk
JOIN postCode p ON p.townFk = t.id AND p.code = a.postalCode
WHERE a.id = vAddress
ORDER BY (a.city SOUNDS LIKE t.`name`) DESC
LIMIT 1;
DROP TEMPORARY TABLE IF EXISTS tmp.zoneGetAgency;
CREATE TEMPORARY TABLE tmp.zoneGetAgency
(INDEX (agencyModeFk)) ENGINE = MEMORY
SELECT * FROM (
SELECT * FROM (
SELECT am.id agencyModeFk,
am.name agencyMode,
am.description,
am.deliveryMethodFk,
TIMESTAMPADD(DAY,-z.travelingDays, vLanded) shipped,
zi.isIncluded,
z.warehouseFk,
z.id zoneFk
FROM zoneGeo zgSon
JOIN zoneGeo zgFather ON zgSon.lft BETWEEN zgFather.lft AND zgFather.rgt
JOIN zoneIncluded zi ON zi.geoFk = zgFather.id
JOIN zone z ON z.id = zi.zoneFk
JOIN zoneCalendar zc ON zc.zoneFk = z.id
JOIN agencyMode am ON am.id = z.agencyModeFk
WHERE zgSon.`id` = vGeoFk
AND zc.delivered = vLanded
AND TIMESTAMPADD(DAY,-z.travelingDays, vLanded) >= CURDATE()
AND IF(TIMESTAMPADD(DAY,-z.travelingDays, vLanded) = CURDATE(), hour(now()) < hour(z.`hour`),TRUE)
ORDER BY z.id, zgFather.depth DESC, zi.isIncluded DESC) t
GROUP BY zoneFk
HAVING isIncluded > 0
ORDER BY shipped) t
GROUP BY agencyModeFk;
END$$
DELIMITER ;

View File

@ -0,0 +1,10 @@
ALTER TABLE `vn`.`route`
ADD COLUMN `zoneFk` INT NULL AFTER `description`,
ADD INDEX `fk_route_1_idx` (`zoneFk` ASC);
;
ALTER TABLE `vn`.`route`
ADD CONSTRAINT `fk_route_1`
FOREIGN KEY (`zoneFk`)
REFERENCES `vn`.`zone` (`id`)
ON DELETE RESTRICT
ON UPDATE CASCADE;

View File

@ -0,0 +1 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('UserPhone', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,18 @@
CREATE TABLE `vn`.`travelLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`originFk` int(10) unsigned NOT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
`creationDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`description` text CHARACTER SET utf8,
`changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`oldInstance` text COLLATE utf8_unicode_ci,
`newInstance` text COLLATE utf8_unicode_ci,
`changedModelId` int(11) DEFAULT NULL,
`changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `originFk` (`originFk`),
KEY `userFk` (`userFk`),
CONSTRAINT `travelLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -0,0 +1,6 @@
CREATE TABLE `vn`.`packagingConfig` (
`id` INT NOT NULL AUTO_INCREMENT,
`upperGap` INT NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO `vn`.`packagingConfig` (`upperGap`) VALUES ('10');

View File

@ -0,0 +1,18 @@
CREATE TABLE `vn`.`userLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`originFk` int(10) unsigned NOT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
`creationDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`description` text CHARACTER SET utf8,
`changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`oldInstance` text COLLATE utf8_unicode_ci,
`newInstance` text COLLATE utf8_unicode_ci,
`changedModelId` int(11) DEFAULT NULL,
`changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `originFk` (`originFk`),
KEY `userFk` (`userFk`),
CONSTRAINT `userLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `userLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -0,0 +1,9 @@
CREATE TABLE `vn`.`userPhoneType` (
`code` VARCHAR(45) NOT NULL,
`description` VARCHAR(255) NULL,
PRIMARY KEY (`code`));
INSERT INTO `vn`.`userPhoneType` (`code`, `description`) VALUES ('businessPhone', 'Telefono de empresa del usuario');
INSERT INTO `vn`.`userPhoneType` (`code`, `description`) VALUES ('personalPhone', 'Telefono personal del usuario');

View File

@ -0,0 +1,63 @@
CREATE TABLE `vn`.`userPhone` (
`id` INT NOT NULL AUTO_INCREMENT,
`userFk` INT(10) UNSIGNED NOT NULL,
`typeFk` VARCHAR(45) NOT NULL,
`phone` VARCHAR(15) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `UserFK_Phone` (`userFk` ASC, `phone` ASC));
ALTER TABLE `vn`.`userPhone`
ADD CONSTRAINT `fgnTypeFk`
FOREIGN KEY (typeFk)
REFERENCES `vn`.`userPhoneType` (code)
ON DELETE RESTRICT
ON UPDATE CASCADE;
ALTER TABLE `vn`.`userPhone`
ADD CONSTRAINT `fgnUserFk`
FOREIGN KEY (userFk)
REFERENCES `account`.`user` (id)
ON DELETE CASCADE
ON UPDATE CASCADE;
insert into vn.userPhone(userFk,typeFk,phone)
select id,'personalPhone', phone
from vn.client
where phone is not null;
insert into vn.userPhone(userFk,typeFk,phone)
select id,'businessPhone', phone
from vn.worker
where phone is not null AND phone > '';
insert into vn.userPhone(userFk,typeFk,phone)
SELECT
`w`.`userFk`,
'businessPhone',
`m`.`value` AS `mediaValue`
FROM
(((((`postgresql`.`person` `p`
JOIN `postgresql`.`profile` `po` ON ((`po`.`person_id` = `p`.`person_id`)))
JOIN `postgresql`.`profile_media` `pom` ON ((`pom`.`profile_id` = `po`.`profile_id`)))
JOIN `postgresql`.`media` `m` ON ((`m`.`media_id` = `pom`.`media_id`)))
JOIN `postgresql`.`media_type` `mt` ON ((`mt`.`media_type_id` = `m`.`media_type_id`)))
JOIN `vn`.`worker` `w` ON ((`w`.`id` = `p`.`id_trabajador`)))
WHERE
(`mt`.`name` = 'movil empresa');
insert into vn.userPhone(userFk,typeFk,phone)
SELECT
`w`.`userFk`,
'personalPhone',
`m`.`value` AS `mediaValue`
FROM
(((((`postgresql`.`person` `p`
JOIN `postgresql`.`profile` `po` ON ((`po`.`person_id` = `p`.`person_id`)))
JOIN `postgresql`.`profile_media` `pom` ON ((`pom`.`profile_id` = `po`.`profile_id`)))
JOIN `postgresql`.`media` `m` ON ((`m`.`media_id` = `pom`.`media_id`)))
JOIN `postgresql`.`media_type` `mt` ON ((`mt`.`media_type_id` = `m`.`media_type_id`)))
JOIN `vn`.`worker` `w` ON ((`w`.`id` = `p`.`id_trabajador`)))
WHERE
(`mt`.`name` = 'movil personal')

File diff suppressed because one or more lines are too long

View File

@ -57,13 +57,18 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
(19,'Francia', 1, 'FR', 1, 25),
(30,'Canarias', 1, 'IC', 1, 22);
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`)
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`)
VALUES
(1, 'Warehouse One', 1, 1, 1, 1, 1),
(2, 'Warehouse Two', 1, 1, 1, 1, 0),
(3, 'Warehouse Three', 1, 1, 1, 1, 0),
(4, 'Warehouse Four', 1, 1, 1, 1, 0),
(5, 'Warehouse Five', 1, 1, 1, 1, 0);
(1, 'Warehouse One', 1, 1, 1, 1, 1, 1),
(2, 'Warehouse Two', 1, 1, 1, 1, 0, 0),
(3, 'Warehouse Three', 1, 1, 1, 1, 0, 0),
(4, 'Warehouse Four', 1, 1, 1, 1, 0, 0),
(5, 'Warehouse Five', 1, 1, 1, 1, 0, 0);
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`)
VALUES
(1, 'First sector', 1, 1, 'FIRST', 999, 999),
(2, 'Second sector', 2, 0, 'SECOND', 100, 150);
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES
@ -194,8 +199,8 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
(108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1),
(109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1),
(110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1),
(200, 'Missing', NULL, 'Missing man', 'Anton', 'The space', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1),
(400, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1);
(111, 'Missing', NULL, 'Missing man', 'Anton', 'The space', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1),
(112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1);
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `phone`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'SILLA', 46460, 623111111, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, CURDATE(), 1
@ -221,8 +226,8 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1, 1111111111, 222222222, 1, 108, 2, NULL, NULL, 0, 1),
(9, 'Bruce Banner', 'Somewhere in New York', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 1),
(10, 'Jessica Jones', 'NYCC 2015 Poster', 'Silla', 46460, 1, 1111111111, 222222222, 1, 110, 2, NULL, NULL, 0, 1),
(11, 'Missing', 'The space', 'Silla', 46460, 1, 1111111111, 222222222, 1, 200, 10, NULL, NULL, 0, 1),
(12, 'Trash', 'New York city', 'Silla', 46460, 1, 1111111111, 222222222, 1, 400, 10, NULL, NULL, 0, 1),
(11, 'Missing', 'The space', 'Silla', 46460, 1, 1111111111, 222222222, 1, 111, 10, NULL, NULL, 0, 1),
(12, 'Trash', 'New York city', 'Silla', 46460, 1, 1111111111, 222222222, 1, 112, 10, NULL, NULL, 0, 1),
(101, 'address 01', 'Somewhere in Thailand', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(102, 'address 02', 'Somewhere in Poland', 'Silla', 46460, 1, 3333333333, 444444444, 1, 109, 2, NULL, NULL, 0, 0),
(103, 'address 03', 'Somewhere in Japan', 'Silla', 46460, 1, 3333333333, 444444444, 1, 109, 2, NULL, NULL, 0, 0),
@ -252,9 +257,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(127, 'address 27', 'Your pocket', 'Silla', 46460, 1, 1111111111, 222222222, 1, 107, 2, NULL, NULL, 0, 0),
(128, 'address 28', 'Cerebro', 'Silla', 46460, 1, 1111111111, 222222222, 1, 108, 2, NULL, NULL, 0, 0),
(129, 'address 29', 'Luke Cages Bar', 'Silla', 46460, 1, 1111111111, 222222222, 1, 110, 2, NULL, NULL, 0, 0),
(130, 'address 30', 'Non valid address', 'Silla', 46460, 1, 1111111111, 222222222, 0, 101, 2, NULL, NULL, 0, 0),
(131, 'Missing', 'The space', 'Silla', 46460, 1, 1111111111, 222222222, 1, 200, 10, NULL, NULL, 0, 0),
(132, 'Trash', 'New York city', 'Silla', 46460, 1, 1111111111, 222222222, 1, 400, 10, NULL, NULL, 0, 0);
(130, 'address 30', 'Non valid address', 'Silla', 46460, 1, 1111111111, 222222222, 0, 101, 2, NULL, NULL, 0, 0);
INSERT INTO `vn`.`address`( `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `isActive`, `clientFk`, `agencyModeFk`, `isDefaultAddress`)
SELECT name, CONCAT(name, 'Street'), 'SILLA', 46460, 1, 1, id, 2, 1
@ -348,16 +351,6 @@ INSERT INTO `vn`.`creditInsurance`(`id`, `creditClassification`, `credit`, `crea
(2, 2, 6000, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL),
(3, 3, 10000, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL);
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`)
VALUES
(1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 7, 'first route', 2.7, 10, CURDATE(), CURDATE()),
(2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 7, 'second route', 0.9, 20, CURDATE(), CURDATE()),
(3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 7, 'third route', 1.1, 30, CURDATE(), CURDATE()),
(4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 7, 'fourth route', 0.1, 40, CURDATE(), CURDATE()),
(5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 8, 'fifth route', NULL, 50, CURDATE(), CURDATE()),
(6, NULL, 57, CURDATE(), 5, 8, 'sixth route', NULL, 60, CURDATE(), CURDATE()),
(7, NULL, 57, CURDATE(), 6, NULL, 'seventh route', NULL, 70, CURDATE(), CURDATE());
INSERT INTO `vn2008`.`empresa_grupo`(`empresa_grupo_id`, `grupo`)
VALUES
(1, 'Wayne Industries');
@ -453,32 +446,42 @@ INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `warehouseFk`, `agencyModeFk`, `t
(12, 'Zone entanglement', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 4, 4, 0, 0, 0),
(13, 'Zone quantum break', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 5, 5, 0, 0, 0);
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`)
VALUES
(1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 1, 'first route', 1.8, 10, CURDATE(), CURDATE(), 1),
(2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 2, 'second route', 0.2, 20, CURDATE(), CURDATE(), 9),
(3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 3, 'third route', 0.5, 30, CURDATE(), CURDATE(), 10),
(4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 4, 'fourth route', 0, 40, CURDATE(), CURDATE(), 12),
(5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 5, 'fifth route', 0.1, 50, CURDATE(), CURDATE(), 13),
(6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), CURDATE(), 3),
(7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), CURDATE(), 5);
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `created`)
VALUES
(1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3 , 1, 7, 1, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(4 , 3, 2, 1, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(5 , 3, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(6 , 1, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(7 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()),
(8 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()),
(9 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()),
(10, 1, 1, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 11, CURDATE()),
(11, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
(12, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
(13, 1, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
(14, 1, 2, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
(15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()),
(16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
(17, 1, 7, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
(18, 1, 4, 4, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
(19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(21, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(22, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(23, NULL, 10, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 8, CURDATE()),
(24 ,NULL, 10, 1, NULL, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 8, CURDATE());
(1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3 , 1, 7, 1, 6, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(4 , 3, 2, 1, 2, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(5 , 3, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(6 , 1, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(7 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()),
(8 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()),
(9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()),
(10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 1, 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()),
(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(), 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()),
(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()),
(18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
(19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 5, CURDATE()),
(24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 5, CURDATE());
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES
@ -646,7 +649,9 @@ INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `d
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, NULL),
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, NULL, 2, NULL);
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, NULL);
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`)
VALUES
@ -663,12 +668,14 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `create
INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`)
VALUES
(1, 0.00, 10, 10, 0, 0, CURDATE(), 6, 1.50),
(2, 100.00, 20, 20, 0, 0, CURDATE(), 7, 1.00),
(3, 14000.00, 0, 0, 0, 0, CURDATE(), NULL, 0),
(4, 218000.00, 0, 0, 0, 0, CURDATE(), NULL, 0),
(5, 292000.00, 0, 0, 0, 0, CURDATE(), NULL, 0),
(94, 140875.00, 49.00, 115.00, 25.00, 0, CURDATE(), 71, 0.00);
(1, 0.00, 10, 10, 0, 1, CURDATE(), 6, 1.50),
(2, 100.00, 20, 20, 0, 1, CURDATE(), 7, 1.00),
(3, 14000.00, 0, 0, 0, 1, CURDATE(), NULL, 0),
(4, 218000.00, 0, 0, 0, 0, CURDATE(), NULL, 0),
(5, 292000.00, 0, 0, 0, 0, CURDATE(), NULL, 0),
(94, 140875.00, 49.00, 115.00, 25.00, 0, CURDATE(), 71, 0.00),
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00),
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00);
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
VALUES
@ -1044,50 +1051,50 @@ INSERT INTO `vn`.`ticketWeekly`(`ticketFk`, `weekDay`)
(4, 4),
(5, 6);
INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `m3`, `kg`)
INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `m3`, `kg`,`ref`, `totalEntries`)
VALUES
(1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000),
(2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000),
(3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00),
(4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500),
(5, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 2, 1, 50.00, 500),
(6, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 2, 1, 50.00, 500),
(7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 2, 1, 50.00, 500);
(1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000, 'first travel', 1),
(2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000, 'second travel', 2),
(3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00, 'third travel', 1),
(4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500, 'fourth travel', 0),
(5, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 2, 1, 50.00, 500, 'fifth travel', 1),
(6, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 2, 1, 50.00, 500, 'sixth travel', 1),
(7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 2, 1, 50.00, 500, 'seventh travel', 1);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`,`ref`)
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`, `ref`, `notes`, `evaNotes`)
VALUES
(1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 442, 'Movimiento 1'),
(2, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 442, 'Movimiento 2'),
(3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 442, 'Movimiento 3'),
(4, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 69, 'Movimiento 4'),
(5, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 442, 'Movimiento 5'),
(6, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 6, 442, 'Movimiento 6'),
(7, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 7, 442, 'Movimiento 7');
(1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 442, 'Movement 1', 'this is the note one', 'observation one'),
(2, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 442, 'Movement 2', 'this is the note two', 'observation two'),
(3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 442, 'Movement 3', 'this is the note three', 'observation three'),
(4, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 69, 'Movement 4', 'this is the note four', 'observation four'),
(5, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 442, 'Movement 5', 'this is the note five', 'observation five'),
(6, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 6, 442, 'Movement 6', 'this is the note six', 'observation six'),
(7, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 7, 442, 'Movement 7', 'this is the note seven', 'observation seven');
INSERT INTO `bi`.`claims_ratio`(`id_Cliente`, `Consumo`, `Reclamaciones`, `Ratio`, `recobro`, `inflacion`)
VALUES
(101, 500, NULL, 0.00, 0.00, 1.00),
(102, 1000, 2.00, 0.01, 0.05, 1.00),
(102, 1000, 2.00, 0.01, 0.05, 1.00),
(103, 2000, 0.00, 0.00, 0.02, 1.00),
(104, 2500, 150.00, 0.02, 0.10, 1.00);
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`minPrice`,`producer`,`printedStickers`,`isChecked`,`isIgnored`, `created`)
VALUES
(1, 1, 1, 50, 5000, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(2, 2, 1, 50, 100, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3, 3, 1, 50, 100, 4, 1, 0.000, 0.000, 0.000, 1, 1, 0, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(4, 2, 2, 5, 450, 3, 1, 0.000, 0.000, 0.000, 10, 10, 0, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(5, 3, 3, 55, 500, 5, 1, 0.000, 0.000, 0.000, 1, 1, 0, NULL, 0.00, 78.3, 75.6, 0.00, NULL, 0, 1, 0, CURDATE()),
(6, 4, 8, 50, 1000, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(7, 4, 9, 20, 1000, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 30.50, 29.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(8, 4, 4, 1.25, 1000, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(9, 4, 4, 1.25, 1000, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(10, 5, 1, 50, 10, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(11, 5, 4, 1.25, 10, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(12, 6, 4, 1.25, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(13, 7, 1, 50, 0, 3, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(14, 7, 2, 5, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(15, 7, 4, 1.25, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE());
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3, 3, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 0, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(4, 2, 2, 5, 450, 3, 1, 1.000, 1.000, 0.000, 10, 10, 0, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(5, 3, 3, 55, 500, 5, 1, 1.000, 1.000, 0.000, 1, 1, 0, NULL, 0.00, 78.3, 75.6, 0.00, NULL, 0, 1, 0, CURDATE()),
(6, 4, 8, 50, 1000, 4, 1, 1.000, 1.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(7, 4, 9, 20, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 30.50, 29.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(8, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(9, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(10, 5, 1, 50, 10, 4, 1, 2.500, 2.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(11, 5, 4, 1.25, 10, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE());
INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`)
VALUES
@ -1859,4 +1866,67 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`)
VALUES
(1, 'Alta'),
(2, 'Normal'),
(3, 'Baja');
(3, 'Baja');
INSERT INTO `vn`.`userPhone`(`id`, `userFk`, `typeFk`, `phone`)
VALUES
(1, 101, 'personalPhone', 1111111111),
(2, 102, 'personalPhone', 1111111111),
(3, 103, 'personalPhone', 1111111111),
(4, 104, 'personalPhone', 1111111111),
(5, 105, 'personalPhone', 1111111111),
(6, 106, 'personalPhone', 1111111111),
(7, 107, 'personalPhone', 1111111111),
(8, 108, 'personalPhone', 1111111111),
(9, 109, 'personalPhone', 1111111111),
(10, 110, 'personalPhone', 1111111111),
(11, 111, 'personalPhone', 1111111111),
(12, 112, 'personalPhone', 1111111111),
(13, 1, 'personalPhone', 623111111),
(14, 2, 'personalPhone', 623111111),
(15, 3, 'personalPhone', 623111111),
(16, 5, 'personalPhone', 623111111),
(17, 6, 'personalPhone', 623111111),
(18, 9, 'personalPhone', 623111111),
(19, 13, 'personalPhone', 623111111),
(20, 15, 'personalPhone', 623111111),
(21, 16, 'personalPhone', 623111111),
(22, 17, 'personalPhone', 623111111),
(23, 18, 'personalPhone', 623111111),
(24, 19, 'personalPhone', 623111111),
(25, 20, 'personalPhone', 623111111),
(26, 21, 'personalPhone', 623111111),
(27, 22, 'personalPhone', 623111111),
(28, 30, 'personalPhone', 623111111),
(29, 31, 'personalPhone', 623111111),
(30, 32, 'personalPhone', 623111111),
(31, 34, 'personalPhone', 623111111),
(32, 35, 'personalPhone', 623111111),
(33, 36, 'personalPhone', 623111111),
(34, 37, 'personalPhone', 623111111),
(35, 38, 'personalPhone', 623111111),
(36, 39, 'personalPhone', 623111111),
(37, 40, 'personalPhone', 623111111),
(38, 41, 'personalPhone', 623111111),
(39, 42, 'personalPhone', 623111111),
(40, 43, 'personalPhone', 623111111),
(41, 44, 'personalPhone', 623111111),
(42, 45, 'personalPhone', 623111111),
(43, 47, 'personalPhone', 623111111),
(44, 48, 'personalPhone', 623111111),
(45, 50, 'personalPhone', 623111111),
(46, 51, 'personalPhone', 623111111),
(47, 52, 'personalPhone', 623111111),
(48, 54, 'personalPhone', 623111111),
(49, 55, 'personalPhone', 623111111),
(50, 56, 'personalPhone', 623111111),
(51, 57, 'personalPhone', 623111111),
(52, 58, 'personalPhone', 623111111),
(53, 59, 'personalPhone', 623111111),
(54, 60, 'personalPhone', 623111111),
(55, 61, 'personalPhone', 623111111),
(56, 65, 'personalPhone', 623111111),
(57, 66, 'personalPhone', 623111111),
(65, 107, 'businessPhone', 700987987),
(67, 106, 'businessPhone', 1111111112),
(68, 106, 'personalPhone', 1111111113);

File diff suppressed because it is too large Load Diff

View File

@ -45,20 +45,20 @@ TABLES=(
claimReason
claimRedelivery
claimResult
ticketUpdateAction
state
)
dump_tables ${TABLES[@]}
TABLES=(
vn2008
accion_dits
bionic_updating_options
businessReasonEnd
container
department
escritos
Grupos
iva_group_codigo
state
tarifa_componentes
tarifa_componentes_series
)

View File

@ -1,6 +0,0 @@
export default {
vnTextfield: 'vn-textfield input',
vnInputNumber: 'vn-input-number input',
vnSubmit: 'vn-submit > input',
vnFloatButton: 'vn-float-button > button'
};

View File

@ -7,181 +7,184 @@ import config from './config.js';
let currentUser;
let actions = {
clearTextarea: function(selector, done) {
this.wait(selector)
.evaluate(inputSelector => {
return document.querySelector(inputSelector).value = '';
}, selector)
.then(done)
.catch(done);
// Generic extensions
clickIfExists: async function(selector) {
let exists = await this.exists(selector);
if (exists) await this.click(selector);
return exists;
},
clearInput: function(selector, done) {
this.wait(selector)
parsedUrl: async function() {
return new URL(await this.url());
},
waitUntilNotPresent: async function(selector) {
await this.wait(selector => {
return document.querySelector(selector) == null;
}, selector);
},
// Salix specific extensions
changeLanguageToEnglish: async function() {
let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]';
let lang = await this.waitToClick('#user')
.wait(langSelector)
.waitToGetProperty(`${langSelector} input`, 'value');
if (lang !== 'English')
await this.autocompleteSearch(langSelector, 'English');
},
doLogin: async function(userName, password) {
if (password == null) password = 'nightmare';
await this.wait(`vn-login [name=user]`)
.clearInput(`vn-login [name=user]`)
.write(`vn-login [name=user]`, userName)
.write(`vn-login [name=password]`, password)
.click(`vn-login button[type=submit]`);
},
login: async function(userName) {
if (currentUser !== userName) {
let logoutClicked = await this.clickIfExists('#logout');
if (logoutClicked) {
let buttonSelector = '.vn-dialog.shown button[response=ACCEPT]';
await this.wait(buttonSelector => {
return document.querySelector(buttonSelector) != null
|| location.hash == '#!/login';
}, buttonSelector);
await this.clickIfExists(buttonSelector);
}
try {
await this.waitForURL('#!/login');
} catch (e) {
await this.goto(`${config.url}/#!/login`);
}
await this.doLogin(userName, null)
.waitForURL('#!/')
.changeLanguageToEnglish();
currentUser = userName;
} else
await this.waitToClick('vn-topbar a[ui-sref="home"]');
},
waitForLogin: async function(userName) {
await this.login(userName);
},
selectModule: async function(moduleName) {
let snakeName = moduleName.replace(/[\w]([A-Z])/g, m => {
return m[0] + '-' + m[1];
}).toLowerCase();
await this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`)
.waitForURL(snakeName);
},
loginAndModule: async function(userName, moduleName) {
await this.login(userName)
.selectModule(moduleName);
},
datePicker: async function(selector, changeMonth, day) {
let date = new Date();
if (changeMonth) date.setMonth(date.getMonth() + changeMonth);
date.setDate(day ? day : 16);
date = date.toISOString().substr(0, 10);
await this.wait(selector)
.evaluate((selector, date) => {
let input = document.querySelector(selector).$ctrl.input;
input.value = date;
input.dispatchEvent(new Event('change'));
}, selector, date);
},
pickTime: async function(selector, time) {
await this.wait(selector)
.evaluate((selector, time) => {
let input = document.querySelector(selector).$ctrl.input;
input.value = time;
input.dispatchEvent(new Event('change'));
}, selector, time);
},
clearTextarea: function(selector) {
return this.wait(selector)
.evaluate(inputSelector => {
return document.querySelector(inputSelector).value = '';
}, selector);
},
clearInput: function(selector) {
return this.wait(selector)
.evaluate(selector => {
let $ctrl = document.querySelector(selector).closest('.vn-field').$ctrl;
$ctrl.field = null;
$ctrl.$.$apply();
$ctrl.input.dispatchEvent(new Event('change'));
}, selector)
.then(done)
.catch(done);
}, selector);
},
login: function(userName, done) {
if (currentUser)
this.waitToClick('#logout');
let doLogin = () => {
this.wait(`vn-login input[name=user]`)
.clearInput(`vn-login input[name=user]`)
.write(`vn-login input[name=user]`, userName)
.write(`vn-login input[name=password]`, 'nightmare')
.click(`vn-login input[type=submit]`)
.then(() => {
currentUser = userName;
done();
})
.catch(done);
};
this.waitForURL('#!/login')
.then(doLogin)
.catch(() => {
this.goto(`${config.url}/#!/login`)
.then(doLogin)
.catch(done);
});
},
waitForLogin: function(userName, done) {
if (currentUser === userName) {
return this.waitToClick('vn-topbar a[ui-sref="home"]')
.waitForURL('#!/')
.changeLanguageToEnglish()
.then(done)
.catch(done);
}
return this.login(userName)
.waitForURL('#!/')
.url()
.changeLanguageToEnglish()
.then(done)
.catch(done);
},
resetLogin: function(done) {
this.then(() => {
currentUser = undefined;
done();
})
.catch(done);
},
changeLanguageToEnglish: function(done) {
let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]';
this.waitToClick('#user')
.wait(langSelector)
.waitToGetProperty(`${langSelector} input`, 'value')
.then(lang => {
if (lang === 'English') {
this.then(done)
.catch(done);
} else {
this.autocompleteSearch(langSelector, 'English')
.then(done)
.catch(done);
}
});
},
selectModule: function(moduleName, done) {
let snakeName = moduleName.replace(/[\w]([A-Z])/g, m => {
return m[0] + '-' + m[1];
}).toLowerCase();
this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`)
.waitForURL(snakeName)
.then(done)
.catch(done);
},
loginAndModule: function(userName, moduleName, done) {
this.waitForLogin(userName)
.selectModule(moduleName)
.then(done)
.catch(done);
},
parsedUrl: function(done) {
this.url()
.then(url => {
done(null, new URL(url));
}).catch(done);
},
getProperty: function(selector, property, done) {
this.evaluate_now((selector, property) => {
getProperty: function(selector, property) {
return this.evaluate((selector, property) => {
return document.querySelector(selector)[property].replace(/\s+/g, ' ').trim();
}, done, selector, property);
}, selector, property);
},
waitPropertyLength: function(selector, property, minLength, done) {
this.wait((selector, property, minLength) => {
waitPropertyLength: function(selector, property, minLength) {
return this.wait((selector, property, minLength) => {
const element = document.querySelector(selector);
return element && element[property] != null && element[property] !== '' && element[property].length >= minLength;
}, selector, property, minLength)
.getProperty(selector, property)
.then(result => done(null, result), done);
.getProperty(selector, property);
},
waitPropertyValue: function(selector, property, status, done) {
this.wait(selector)
waitPropertyValue: function(selector, property, status) {
return this.wait(selector)
.wait((selector, property, status) => {
const element = document.querySelector(selector);
return element[property] === status;
}, selector, property, status)
.then(done)
.catch(done);
}, selector, property, status);
},
waitToGetProperty: function(selector, property, done) {
this.wait((selector, property) => {
waitToGetProperty: function(selector, property) {
return this.wait((selector, property) => {
const element = document.querySelector(selector);
return element && element[property] != null && element[property] !== '';
}, selector, property)
.getProperty(selector, property)
.then(result => done(null, result), done);
.getProperty(selector, property);
},
write: function(selector, text, done) {
this.wait(selector)
.type(selector, text)
.then(done)
.catch(done);
write: function(selector, text) {
return this.wait(selector)
.type(selector, text);
},
waitToClick: function(selector, done) {
this.wait(selector)
.click(selector)
.then(done)
.catch(done);
waitToClick: function(selector) {
return this.wait(selector)
.click(selector);
},
focusElement: function(selector, done) {
this.wait(selector)
.evaluate_now(selector => {
focusElement: function(selector) {
return this.wait(selector)
.evaluate(selector => {
let element = document.querySelector(selector);
element.focus();
}, done, selector)
.then(done)
.catch(done);
}, selector);
},
isVisible: function(selector, done) {
this.wait(selector)
.evaluate_now(elementSelector => {
isVisible: function(selector) {
return this.wait(selector)
.evaluate(elementSelector => {
const selectorMatches = document.querySelectorAll(elementSelector);
const element = selectorMatches[0];
@ -219,122 +222,96 @@ let actions = {
element.removeEventListener('mouseover', eventHandler);
}
return isVisible;
}, done, selector);
}, selector);
},
waitImgLoad: function(selector, done) {
this.wait(selector)
waitImgLoad: function(selector) {
return this.wait(selector)
.wait(selector => {
const imageReady = document.querySelector(selector).complete;
return imageReady;
}, selector)
.then(done)
.catch(() => {
done(new Error(`image ${selector}, load timed out`));
});
}, selector);
},
clickIfVisible: function(selector, done) {
this.wait(selector)
clickIfVisible: function(selector) {
return this.wait(selector)
.isVisible(selector)
.then(visible => {
if (visible)
return this.click(selector);
throw new Error(`invisible selector: ${selector}`);
})
.then(done)
.catch(done);
},
countElement: function(selector, done) {
this.evaluate_now(selector => {
return document.querySelectorAll(selector).length;
}, done, selector);
},
waitForNumberOfElements: function(selector, count, done) {
this.wait((selector, count) => {
return document.querySelectorAll(selector).length === count;
}, selector, count)
.then(done)
.catch(() => {
done(new Error(`.waitForNumberOfElements() for ${selector}, count ${count} timed out`));
});
},
waitForClassNotPresent: function(selector, className, done) {
this.wait(selector)
countElement: function(selector) {
return this.evaluate(selector => {
return document.querySelectorAll(selector).length;
}, selector);
},
waitForNumberOfElements: function(selector, count) {
return this.wait((selector, count) => {
return document.querySelectorAll(selector).length === count;
}, selector, count);
},
waitForClassNotPresent: function(selector, className) {
return this.wait(selector)
.wait((selector, className) => {
if (!document.querySelector(selector).classList.contains(className))
return true;
}, selector, className)
.then(done)
.catch(() => {
done(new Error(`.waitForClassNotPresent() for ${selector}, class ${className} timed out`));
});
}, selector, className);
},
waitForClassPresent: function(selector, className, done) {
this.wait(selector)
waitForClassPresent: function(selector, className) {
return this.wait(selector)
.wait((elementSelector, targetClass) => {
if (document.querySelector(elementSelector).classList.contains(targetClass))
return true;
}, selector, className)
.then(done)
.catch(() => {
done(new Error(`.waitForClassPresent() for ${selector}, class ${className} timed out`));
});
}, selector, className);
},
waitForTextInElement: function(selector, text, done) {
this.wait(selector)
waitForTextInElement: function(selector, text) {
return this.wait(selector)
.wait((selector, text) => {
return document.querySelector(selector).innerText.toLowerCase().includes(text.toLowerCase());
}, selector, text)
.then(done)
.catch(done);
}, selector, text);
},
waitForTextInInput: function(selector, text, done) {
this.wait(selector)
waitForTextInInput: function(selector, text) {
return this.wait(selector)
.wait((selector, text) => {
return document.querySelector(selector).value.toLowerCase().includes(text.toLowerCase());
}, selector, text)
.then(done)
.catch(done);
}, selector, text);
},
waitForInnerText: function(selector, done) {
this.wait(selector)
waitForInnerText: function(selector) {
return this.wait(selector)
.wait(selector => {
const innerText = document.querySelector(selector).innerText;
return innerText != null && innerText != '';
}, selector)
.evaluate_now(selector => {
.evaluate(selector => {
return document.querySelector(selector).innerText;
}, done, selector);
}, selector);
},
waitForEmptyInnerText: function(selector, done) {
this.wait(selector => {
waitForEmptyInnerText: function(selector) {
return this.wait(selector => {
return document.querySelector(selector).innerText == '';
}, selector)
.then(done)
.catch(done);
}, selector);
},
waitForURL: function(hashURL, done) {
this.wait(hash => {
waitForURL: function(hashURL) {
return this.wait(hash => {
return document.location.hash.includes(hash);
}, hashURL)
.then(done)
.catch(done);
}, hashURL);
},
waitForShapes: function(selector, done) {
this.wait(selector)
.evaluate_now(selector => {
waitForShapes: function(selector) {
return this.wait(selector)
.evaluate(selector => {
const shapes = document.querySelectorAll(selector);
const shapesList = [];
@ -343,33 +320,29 @@ let actions = {
return shapesList;
}, done, selector);
}, selector);
},
waitForSnackbar: function(done) {
this.wait(500).waitForShapes('vn-snackbar .shape .text')
.then(shapes => {
done(null, shapes);
}).catch(done);
waitForSnackbar: function() {
return this.wait(500)
.waitForShapes('vn-snackbar .shape .text');
},
waitForLastShape: function(selector, done) {
this.wait(selector)
.evaluate_now(selector => {
waitForLastShape: function(selector) {
return this.wait(selector)
.evaluate(selector => {
const shape = document.querySelector(selector);
return shape.innerText;
}, done, selector);
}, selector);
},
waitForLastSnackbar: function(done) {
this.wait(500).waitForLastShape('vn-snackbar .shape .text')
.then(shapes => {
done(null, shapes);
}).catch(done);
waitForLastSnackbar: function() {
return this.wait(500)
.waitForLastShape('vn-snackbar .shape .text');
},
accessToSearchResult: function(searchValue, done) {
this.clearInput('vn-searchbar input')
accessToSearchResult: function(searchValue) {
return this.clearInput('vn-searchbar input')
.write('vn-searchbar input', searchValue)
.click('vn-searchbar vn-icon[icon="search"]')
.wait(100)
@ -382,13 +355,11 @@ let actions = {
return this.waitToClick('ui-view vn-card vn-td');
return this.waitToClick('ui-view vn-card a');
})
.then(done)
.catch(done);
});
},
accessToSection: function(sectionRoute, done) {
this.wait(`vn-left-menu`)
accessToSection: function(sectionRoute) {
return this.wait(`vn-left-menu`)
.evaluate(sectionRoute => {
return document.querySelector(`vn-left-menu ul li ul li > a[ui-sref="${sectionRoute}"]`) != null;
}, sectionRoute)
@ -399,90 +370,35 @@ let actions = {
return this.waitToClick('vn-left-menu .collapsed')
.wait('vn-left-menu .expanded')
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`);
})
.then(done)
.catch(done);
});
},
autocompleteSearch: function(autocompleteSelector, searchValue, done) {
this.waitToClick(`${autocompleteSelector} input`)
.write(`.vn-popover.shown .vn-drop-down input`, searchValue)
.waitToClick(`.vn-popover.shown .vn-drop-down li.active`)
autocompleteSearch: function(autocompleteSelector, searchValue) {
return this.waitToClick(`${autocompleteSelector} input`)
.write(`.vn-drop-down.shown input`, searchValue)
.waitToClick(`.vn-drop-down.shown li.active`)
.wait((autocompleteSelector, searchValue) => {
return document.querySelector(`${autocompleteSelector} input`).value
.toLowerCase()
.includes(searchValue.toLowerCase());
}, autocompleteSelector, searchValue)
.then(done)
.catch(() => {
done(new Error(`.autocompleteSearch() for value ${searchValue} in ${autocompleteSelector} timed out`));
});
}, autocompleteSelector, searchValue);
},
pickTime: function(selector, time, done) {
this.wait(selector)
.evaluate((selector, time) => {
let input = document.querySelector(selector);
input.value = time;
input.dispatchEvent(new Event('change'));
}, selector, time)
.then(done)
.catch(done);
},
datePicker: function(selector, changeMonth, day, done) {
this.wait(selector)
.mousedown(`${selector} input`)
.wait('.flatpickr-calendar.open');
if (changeMonth > 0)
this.mousedown(`.flatpickr-calendar.open .flatpickr-next-month`);
if (changeMonth < 0)
this.mousedown(`.flatpickr-calendar.open .flatpickr-prev-month`);
let daySelector;
if (!day)
daySelector = `.flatpickr-calendar.open .flatpickr-day:nth-child(16)`;
if (day)
daySelector = `.flatpickr-calendar.open .flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`;
this.wait(selector => {
return document.querySelector(selector);
}, daySelector)
.evaluate(selector => {
let event = new MouseEvent('mousedown', {
bubbles: true,
cancelable: true,
view: window
});
document.querySelector(selector).dispatchEvent(event);
}, daySelector)
.then(done)
.catch(() => {
done(new Error(`.datePicker(), for ${daySelector} timed out`));
});
},
reloadSection: function(sectionRoute, done) {
this.waitToClick('vn-icon[icon="desktop_windows"]')
reloadSection: function(sectionRoute) {
return this.waitToClick('vn-icon[icon="desktop_windows"]')
.wait('vn-card.summary')
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`)
.then(done)
.catch(done);
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`);
},
forceReloadSection: function(sectionRoute, done) {
this.waitToClick('vn-icon[icon="desktop_windows"]')
forceReloadSection: function(sectionRoute) {
return this.waitToClick('vn-icon[icon="desktop_windows"]')
.waitToClick('button[response="ACCEPT"]')
.wait('vn-card.summary')
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`)
.then(done)
.catch(done);
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`);
},
checkboxState: function(selector, done) {
this.wait(selector)
checkboxState: function(selector) {
return this.wait(selector)
.evaluate(selector => {
let checkbox = document.querySelector(selector);
switch (checkbox.$ctrl.field) {
@ -493,30 +409,39 @@ let actions = {
default:
return 'unchecked';
}
}, selector)
.then(res => done(null, res))
.catch(done);
}, selector);
},
isDisabled: function(selector, done) {
this.wait(selector)
isDisabled: function(selector) {
return this.wait(selector)
.evaluate(selector => {
let element = document.querySelector(selector);
return element.$ctrl.disabled;
}, selector)
.then(res => done(null, res))
.catch(done);
}, selector);
},
waitForSpinnerLoad: function(done) {
let spinnerSelector = 'vn-spinner > div';
this.waitForClassNotPresent(spinnerSelector, 'is-active')
.then(done)
.catch(done);
waitForSpinnerLoad: function() {
return this.waitForClassNotPresent('vn-spinner > div', 'is-active');
},
};
Object.keys(actions).forEach(function(name) {
let fn = actions[name];
Nightmare.action(name, fn);
});
for (let name in actions) {
Nightmare.action(name, function(...args) {
let fnArgs = args.slice(0, args.length - 1);
let done = args[args.length - 1];
actions[name].apply(this, fnArgs)
.then(res => done(null, res))
.catch(err => {
let stringArgs = fnArgs
.map(i => typeof i == 'function' ? 'Function' : i)
.join(', ');
let orgMessage = err.message.startsWith('.wait()')
? '.wait() timed out'
: err.message;
done(new Error(`.${name}(${stringArgs}) failed: ${orgMessage}`));
});
});
}

View File

@ -1,4 +1,6 @@
const Nightmare = require('nightmare');
const config = require('./config.js');
let nightmare;
module.exports = function createNightmare(width = 1280, height = 720) {
@ -25,5 +27,5 @@ module.exports = function createNightmare(width = 1280, height = 720) {
});
nightmare.header('Accept-Language', 'en');
return nightmare;
return nightmare.goto(config.url);
};

View File

@ -1,4 +1,3 @@
import components from './components_selectors.js';
export default {
globalItems: {
@ -19,33 +18,33 @@ export default {
userConfigFirstAutocompleteClear: '#localWarehouse .icons > vn-icon[icon=clear]',
userConfigSecondAutocompleteClear: '#localBank .icons > vn-icon[icon=clear]',
userConfigThirdAutocompleteClear: '#localCompany .icons > vn-icon[icon=clear]',
acceptButton: 'vn-confirm button[response=ACCEPT]'
acceptButton: '.vn-confirm.shown button[response=ACCEPT]'
},
clientsIndex: {
searchClientInput: `${components.vnTextfield}`,
searchClientInput: `vn-textfield input`,
searchButton: 'vn-searchbar vn-icon[icon="search"]',
searchResult: 'vn-client-index .vn-list-item',
createClientButton: `${components.vnFloatButton}`,
createClientButton: `vn-float-button`,
othersButton: 'vn-left-menu li[name="Others"] > a'
},
createClientView: {
name: `${components.vnTextfield}[name="name"]`,
taxNumber: `${components.vnTextfield}[name="fi"]`,
socialName: `${components.vnTextfield}[name="socialName"]`,
street: `${components.vnTextfield}[name="street"]`,
postcode: `${components.vnTextfield}[name="postcode"]`,
city: `${components.vnTextfield}[name="city"]`,
name: `vn-textfield input[name="name"]`,
taxNumber: `vn-textfield input[name="fi"]`,
socialName: `vn-textfield input[name="socialName"]`,
street: `vn-textfield input[name="street"]`,
postcode: `vn-textfield input[name="postcode"]`,
city: `vn-textfield input[name="city"]`,
province: `vn-autocomplete[ng-model="$ctrl.client.provinceFk"]`,
country: `vn-autocomplete[ng-model="$ctrl.client.countryFk"]`,
userName: `${components.vnTextfield}[name="userName"]`,
email: `${components.vnTextfield}[name="email"]`,
userName: `vn-textfield input[name="userName"]`,
email: `vn-textfield input[name="email"]`,
salesPersonAutocomplete: `vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]`,
createButton: `${components.vnSubmit}`,
createButton: `button[type=submit]`,
cancelButton: 'vn-button[href="#!/client/index"]'
},
clientDescriptor: {
moreMenu: 'vn-client-descriptor vn-icon-menu > div > vn-icon',
simpleTicketButton: '.vn-popover.shown .vn-drop-down li'
moreMenu: 'vn-client-descriptor vn-icon-menu[icon=more_vert]',
simpleTicketButton: '.vn-drop-down.shown li'
},
clientBasicData: {
basicDataButton: 'vn-left-menu a[ui-sref="client.card.basicData"]',
@ -56,17 +55,17 @@ export default {
emailInput: 'vn-textfield[ng-model="$ctrl.client.email"] input',
salesPersonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]',
channelAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.contactChannelFk"]',
saveButton: `${components.vnSubmit}`
saveButton: `button[type=submit]`
},
clientFiscalData: {
fiscalDataButton: 'vn-left-menu a[ui-sref="client.card.fiscalData"]',
socialNameInput: `${components.vnTextfield}[name="socialName"]`,
fiscalIdInput: `${components.vnTextfield}[name="fi"]`,
equalizationTaxCheckbox: 'vn-check[label="Is equalizated"]',
acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]',
addressInput: `${components.vnTextfield}[name="street"]`,
postcodeInput: `${components.vnTextfield}[name="postcode"]`,
cityInput: `${components.vnTextfield}[name="city"]`,
socialNameInput: `vn-textfield input[name="socialName"]`,
fiscalIdInput: `vn-textfield input[name="fi"]`,
equalizationTaxCheckbox: 'vn-check[ng-model="$ctrl.client.isEqualizated"]',
acceptPropagationButton: '.vn-confirm.shown button[response=ACCEPT]',
addressInput: `vn-textfield input[name="street"]`,
postcodeInput: `vn-textfield input[name="postcode"]`,
cityInput: `vn-textfield input[name="city"]`,
provinceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
countryAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
activeCheckbox: 'vn-check[label="Active"]',
@ -76,36 +75,36 @@ export default {
hasToInvoiceCheckbox: 'vn-check[label="Has to invoice"]',
invoiceByMailCheckbox: 'vn-check[label="Invoice by mail"]',
viesCheckbox: 'vn-check[label="Vies"]',
saveButton: `${components.vnSubmit}`
saveButton: `button[type=submit]`
},
clientBillingData: {
payMethodAutocomplete: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]',
IBANInput: `vn-client-billing-data ${components.vnTextfield}[name="iban"]`,
dueDayInput: `vn-client-billing-data ${components.vnInputNumber}[name="dueDay"]`,
IBANInput: `vn-client-billing-data vn-textfield input[name="iban"]`,
dueDayInput: `vn-client-billing-data vn-input-number input[name="dueDay"]`,
receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]',
receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]',
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
swiftBicAutocomplete: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"] .icons > vn-icon[icon=clear]',
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: 'vn-client-billing-data > vn-dialog vn-textfield[label="Name"] input',
newBankEntityBIC: 'vn-client-billing-data > vn-dialog vn-textfield[label="Swift / BIC"] input',
newBankEntityCode: 'vn-client-billing-data > vn-dialog vn-textfield[label="Entity Code"] input',
acceptBankEntityButton: 'vn-client-billing-data > vn-dialog button[response="ACCEPT"]',
saveButton: `${components.vnSubmit}`
newBankEntityName: '.vn-dialog.shown vn-textfield[label="Name"] input',
newBankEntityBIC: '.vn-dialog.shown vn-textfield[label="Swift / BIC"] input',
newBankEntityCode: '.vn-dialog.shown vn-textfield[label="Entity Code"] input',
acceptBankEntityButton: '.vn-dialog.shown button[response="ACCEPT"]',
saveButton: `button[type=submit]`
},
clientAddresses: {
addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]',
createAddress: `vn-client-address-index ${components.vnFloatButton}`,
createAddress: `vn-client-address-index vn-float-button`,
defaultCheckboxInput: 'vn-check[label="Default"]',
consigneeInput: `${components.vnTextfield}[name="nickname"]`,
streetAddressInput: `${components.vnTextfield}[name="street"]`,
postcodeInput: `${components.vnTextfield}[name="postalCode"]`,
cityInput: `${components.vnTextfield}[name="city"]`,
consigneeInput: `vn-textfield input[name="nickname"]`,
streetAddressInput: `vn-textfield input[name="street"]`,
postcodeInput: `vn-textfield input[name="postalCode"]`,
cityInput: `vn-textfield input[name="city"]`,
provinceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.address.provinceFk"]',
agencyAutocomplete: 'vn-autocomplete[ng-model="$ctrl.address.agencyModeFk"]',
phoneInput: `${components.vnTextfield}[name="phone"]`,
mobileInput: `${components.vnTextfield}[name="mobile"]`,
phoneInput: `vn-textfield input[name="phone"]`,
mobileInput: `vn-textfield input[name="mobile"]`,
defaultAddress: 'vn-client-address-index div:nth-child(1) div[name="street"]',
secondMakeDefaultStar: 'vn-client-address-index vn-card div:nth-child(2) vn-icon-button[icon="star_border"]',
firstEditAddress: 'vn-client-address-index div:nth-child(1) > a',
@ -117,41 +116,41 @@ export default {
secondObservationTypeAutocomplete: 'vn-client-address-edit [name=observations] :nth-child(2) [ng-model="observation.observationTypeFk"]',
secondObservationDescriptionInput: 'vn-client-address-edit [name=observations] :nth-child(2) [ng-model="observation.description"] input',
addObservationButton: 'vn-client-address-edit div[name="observations"] vn-icon-button[icon="add_circle"]',
saveButton: `${components.vnSubmit}`,
saveButton: `button[type=submit]`,
cancelCreateAddressButton: 'button[ui-sref="client.card.address.index"]',
cancelEditAddressButton: 'vn-client-address-edit > form > vn-button-bar > vn-button > button'
},
clientWebAccess: {
webAccessButton: 'vn-left-menu a[ui-sref="client.card.webAccess"]',
enableWebAccessCheckbox: 'vn-check[label="Enable web access"]',
userNameInput: `${components.vnTextfield}[name="name"]`,
saveButton: `${components.vnSubmit}`
userNameInput: `vn-textfield input[name="name"]`,
saveButton: `button[type=submit]`
},
clientNotes: {
addNoteFloatButton: `${components.vnFloatButton}`,
addNoteFloatButton: `vn-float-button`,
noteInput: 'vn-textarea[label="Note"]',
saveButton: `${components.vnSubmit}`,
saveButton: `button[type=submit]`,
firstNoteText: 'vn-client-note .text'
},
clientCredit: {
addCreditFloatButton: `${components.vnFloatButton}`,
creditInput: `${components.vnInputNumber}[name="credit"]`,
saveButton: `${components.vnSubmit}`,
firstCreditText: 'vn-client-credit-index vn-card > div vn-table vn-tbody > vn-tr'
addCreditFloatButton: `vn-float-button`,
creditInput: `vn-input-number input[name="credit"]`,
saveButton: `button[type=submit]`,
firstCreditText: 'vn-client-credit-index vn-card vn-table vn-tbody > vn-tr'
},
clientGreuge: {
addGreugeFloatButton: `${components.vnFloatButton}`,
amountInput: `${components.vnInputNumber}[name="amount"]`,
descriptionInput: `${components.vnTextfield}[name="description"]`,
addGreugeFloatButton: `vn-float-button`,
amountInput: `vn-input-number input[name="amount"]`,
descriptionInput: `vn-textfield input[name="description"]`,
typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.greuge.greugeTypeFk"]',
saveButton: `${components.vnSubmit}`,
firstGreugeText: 'vn-client-greuge-index vn-card > div vn-table vn-tbody > vn-tr'
saveButton: `button[type=submit]`,
firstGreugeText: 'vn-client-greuge-index vn-card vn-table vn-tbody > vn-tr'
},
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: {
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: {
logButton: 'vn-left-menu a[ui-sref="client.card.log"]',
@ -163,10 +162,10 @@ export default {
clientBalance: {
balanceButton: 'vn-left-menu a[ui-sref="client.card.balance.index"]',
companyAutocomplete: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyFk"]',
newPaymentButton: `${components.vnFloatButton}`,
newPaymentBank: 'vn-client-balance-create vn-autocomplete[ng-model="$ctrl.receipt.bankFk"]',
newPaymentAmountInput: 'vn-client-balance-create vn-input-number[ng-model="$ctrl.receipt.amountPaid"] input',
saveButton: 'vn-client-balance-create vn-button[label="Save"]',
newPaymentButton: `vn-float-button`,
newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.receipt.bankFk"]',
newPaymentAmountInput: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.receipt.amountPaid"] input',
saveButton: '.vn-dialog.shown vn-button[label="Save"]',
firstBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)'
},
@ -178,51 +177,51 @@ export default {
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
acceptDeleteButton: 'vn-client-dms-index > vn-confirm button[response="ACCEPT"]'
acceptDeleteButton: '.vn-confirm.shown button[response="ACCEPT"]'
},
itemsIndex: {
searchIcon: 'vn-item-index vn-searchbar vn-icon[icon="search"]',
createItemButton: `${components.vnFloatButton}`,
createItemButton: `vn-float-button`,
searchResult: 'vn-item-index a.vn-tr',
searchResultPreviewButton: 'vn-item-index .buttons > [icon="desktop_windows"]',
searchResultCloneButton: 'vn-item-index .buttons > [icon="icon-clone"]',
acceptClonationAlertButton: 'vn-item-index [vn-id="clone"] [response="ACCEPT"]',
acceptClonationAlertButton: '.vn-confirm.shown [response="ACCEPT"]',
searchItemInput: 'vn-searchbar vn-textfield input',
searchButton: 'vn-searchbar vn-icon[icon="search"]',
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close',
closeItemSummaryPreview: '.vn-popup.shown',
fieldsToShowButton: 'vn-item-index vn-table > div > div > vn-icon-button[icon="menu"]',
fieldsToShowForm: 'vn-item-index vn-table > div > div > vn-dialog > div > form',
fieldsToShowForm: '.vn-dialog.shown form',
firstItemImage: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(1)',
firstItemId: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(2)',
idCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(2) > vn-check',
stemsCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(3) > vn-check',
sizeCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(4) > vn-check',
nicheCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(5) > vn-check',
typeCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(6) > vn-check',
categoryCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(7) > vn-check',
intrastadCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(8) > vn-check',
originCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(9) > vn-check',
buyerCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(10) > vn-check',
destinyCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(11) > vn-check',
taxClassCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(12) > vn-check',
saveFieldsButton: 'vn-item-index vn-dialog vn-horizontal:nth-child(16) > vn-button > button'
idCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(2) > vn-check',
stemsCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(3) > vn-check',
sizeCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(4) > vn-check',
nicheCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(5) > vn-check',
typeCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(6) > vn-check',
categoryCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(7) > vn-check',
intrastadCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(8) > vn-check',
originCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(9) > vn-check',
buyerCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(10) > vn-check',
destinyCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(11) > vn-check',
taxClassCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(12) > vn-check',
saveFieldsButton: '.vn-dialog.shown vn-horizontal:nth-child(16) > vn-button > button'
},
itemCreateView: {
temporalName: `${components.vnTextfield}[name="provisionalName"]`,
temporalName: `vn-textfield input[name="provisionalName"]`,
typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.typeFk"]',
intrastatAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.intrastatFk"]',
originAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
createButton: `${components.vnSubmit}`,
cancelButton: 'button[ui-sref="item.index"]'
createButton: `button[type=submit]`,
cancelButton: 'vn-button[ui-sref="item.index"]'
},
itemDescriptor: {
goBackToModuleIndexButton: 'vn-item-descriptor a[href="#!/item/index"]',
moreMenu: 'vn-item-descriptor vn-icon-menu > div > vn-icon',
moreMenuRegularizeButton: '.vn-popover.shown .vn-drop-down li[name="Regularize stock"]',
regularizeQuantityInput: 'vn-item-descriptor vn-dialog tpl-body > div > vn-textfield input',
regularizeWarehouseAutocomplete: 'vn-item-descriptor vn-dialog vn-autocomplete[ng-model="$ctrl.warehouseFk"]',
moreMenu: 'vn-item-descriptor vn-icon-menu[icon=more_vert]',
moreMenuRegularizeButton: '.vn-drop-down.shown li[name="Regularize stock"]',
regularizeQuantityInput: '.vn-dialog.shown tpl-body > div > vn-textfield input',
regularizeWarehouseAutocomplete: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.warehouseFk"]',
editButton: 'vn-item-card vn-item-descriptor vn-float-button[icon="edit"]',
regularizeSaveButton: 'vn-item-descriptor > vn-dialog > div > form > div.buttons > tpl-buttons > button',
regularizeSaveButton: '.vn-dialog.shown tpl-buttons > button',
inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]',
navigateBackToIndex: 'vn-item-descriptor vn-icon[icon="chevron_left"]'
},
@ -238,7 +237,7 @@ export default {
longNameInput: 'vn-textfield[ng-model="$ctrl.item.longName"] input',
isActiveCheckbox: 'vn-check[label="Active"]',
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
submitBasicDataButton: `${components.vnSubmit}`
submitBasicDataButton: `button[type=submit]`
},
itemTags: {
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
@ -257,19 +256,19 @@ export default {
seventhValueInput: 'vn-item-tags vn-horizontal:nth-child(7) > vn-textfield[label="Value"] input',
seventhRelevancyInput: 'vn-item-tags vn-horizontal:nth-child(7) > vn-textfield[label="Relevancy"] input',
addItemTagButton: 'vn-item-tags vn-icon-button[icon="add_circle"]',
submitItemTagsButton: `vn-item-tags ${components.vnSubmit}`
submitItemTagsButton: `vn-item-tags button[type=submit]`
},
itemTax: {
undoChangesButton: 'vn-item-tax vn-button-bar > vn-button[label="Undo changes"]',
firstClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(1) > vn-autocomplete[ng-model="tax.taxClassFk"]',
secondClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(2) > vn-autocomplete[ng-model="tax.taxClassFk"]',
thirdClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="tax.taxClassFk"]',
submitTaxButton: `vn-item-tax ${components.vnSubmit}`
submitTaxButton: `vn-item-tax button[type=submit]`
},
itemBarcodes: {
addBarcodeButton: 'vn-item-barcode vn-icon[icon="add_circle"]',
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
submitBarcodesButton: `vn-item-barcode ${components.vnSubmit}`,
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(3) > vn-textfield input`,
submitBarcodesButton: `vn-item-barcode button[type=submit]`,
firstCodeRemoveButton: 'vn-item-barcode vn-horizontal vn-none vn-icon[icon="delete"]'
},
itemNiches: {
@ -281,13 +280,13 @@ export default {
secondNicheRemoveButton: 'vn-item-niche vn-horizontal:nth-child(2) > vn-none > vn-icon-button[icon="delete"]',
thirdWarehouseAutocomplete: 'vn-item-niche vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="niche.warehouseFk"]',
thirdCodeInput: 'vn-item-niche vn-horizontal:nth-child(3) > vn-textfield[label="Code"] input',
submitNichesButton: `vn-item-niche ${components.vnSubmit}`
submitNichesButton: `vn-item-niche button[type=submit]`
},
itemBotanical: {
botanicalInput: `vn-item-botanical vn-horizontal:nth-child(1) > ${components.vnTextfield}`,
botanicalInput: `vn-item-botanical vn-horizontal:nth-child(1) > vn-textfield input`,
genusAutocomplete: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]',
speciesAutocomplete: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]',
submitBotanicalButton: `vn-item-botanical ${components.vnSubmit}`
submitBotanicalButton: `vn-item-botanical button[type=submit]`
},
itemSummary: {
basicData: 'vn-item-summary [name="basicData"]',
@ -308,9 +307,9 @@ 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)',
},
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',
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > a',
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > span > a',
total: 'vn-ticket-summary vn-one.taxes > p:nth-child(3) > strong',
sale: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr',
firstSaleItemId: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',
@ -320,28 +319,28 @@ export default {
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)',
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'
},
ticketsIndex: {
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',
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',
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
searchTicketInput: `vn-ticket-index ${components.vnTextfield}`,
searchWeeklyTicketInput: `vn-ticket-weekly-index ${components.vnTextfield}`,
searchTicketInput: `vn-ticket-index vn-textfield input`,
searchWeeklyTicketInput: `vn-ticket-weekly-index vn-textfield input`,
searchWeeklyClearInput: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon=clear]',
advancedSearchButton: 'vn-ticket-search-panel vn-submit[label="Search"] input',
advancedSearchButton: 'vn-ticket-search-panel button[type=submit]',
searchButton: 'vn-ticket-index vn-searchbar vn-icon[icon="search"]',
searchWeeklyButton: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon="search"]',
moreMenu: 'vn-ticket-index vn-icon-menu[vn-id="more-button"] > div > vn-icon',
moreMenuWeeklyTickets: '.vn-popover.shown .vn-drop-down li:nth-child(2)',
moreMenu: 'vn-ticket-index vn-icon-menu[icon=more_vert]',
moreMenuWeeklyTickets: '.vn-drop-down.shown li:nth-child(2)',
sixthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tr:nth-child(6) vn-autocomplete[ng-model="weekly.weekDay"] input',
weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr',
firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
acceptDeleteTurn: 'vn-ticket-weekly-index > vn-confirm[vn-id="deleteWeekly"] button[response="ACCEPT"]'
acceptDeleteTurn: '.vn-confirm.shown button[response="ACCEPT"]'
},
createTicketView: {
clientAutocomplete: 'vn-ticket-create vn-autocomplete[ng-model="$ctrl.clientFk"]',
@ -349,42 +348,43 @@ export default {
deliveryDateInput: 'vn-ticket-create vn-date-picker[ng-model="$ctrl.landed"]',
warehouseAutocomplete: 'vn-ticket-create vn-autocomplete[ng-model="$ctrl.warehouseFk"]',
agencyAutocomplete: 'vn-ticket-create vn-autocomplete[ng-model="$ctrl.ticket.agencyModeFk"]',
createButton: `${components.vnSubmit}`
createButton: `button[type=submit]`
},
ticketDescriptor: {
idLabelValue: 'vn-ticket-descriptor vn-label-value[label="Id"]',
stateLabelValue: 'vn-ticket-descriptor vn-label-value[label="State"]',
goBackToModuleIndexButton: 'vn-ticket-descriptor a[ui-sref="ticket.index"]',
moreMenu: 'vn-ticket-descriptor vn-icon-menu > div > vn-icon',
moreMenuAddStowaway: '.vn-popover.shown .vn-drop-down li[name="Add stowaway"]',
moreMenuDeleteStowawayButton: '.vn-popover.shown .vn-drop-down li[name="Remove stowaway"]',
moreMenuAddToTurn: '.vn-popover.shown .vn-drop-down li[name="Add turn"]',
moreMenuDeleteTicket: '.vn-popover.shown .vn-drop-down li[name="Delete ticket"]',
moreMenuMakeInvoice: '.vn-popover.shown .vn-drop-down li[name="Make invoice"]',
moreMenuChangeShippedHour: '.vn-popover.shown .vn-drop-down li[name="Change shipped hour"]',
changeShippedHourInput: 'vn-ticket-descriptor .vn-dialog.shown vn-input-time input',
addStowawayDialogFirstTicket: 'vn-ticket-descriptor > vn-add-stowaway > vn-dialog vn-table vn-tbody vn-tr',
shipButton: 'vn-ticket-descriptor > div > div.body > div.quicklinks vn-icon[icon="icon-stowaway"]',
thursdayButton: 'vn-ticket-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-tool-bar > vn-button:nth-child(4)',
saturdayButton: 'vn-ticket-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-tool-bar > vn-button:nth-child(6)',
closeStowawayDialog: 'vn-ticket-descriptor > vn-add-stowaway > vn-dialog > div > button[class="close"]',
acceptDeleteButton: 'vn-ticket-descriptor button[response="ACCEPT"]',
acceptChangeHourButton: 'vn-ticket-descriptor vn-dialog[vn-id="changeShippedDialog"] button[response="ACCEPT"]',
moreMenu: 'vn-ticket-descriptor vn-icon-menu[icon=more_vert]',
moreMenuAddStowaway: '.vn-drop-down.shown li[name="Add stowaway"]',
moreMenuDeleteStowawayButton: '.vn-drop-down.shown li[name="Remove stowaway"]',
moreMenuAddToTurn: '.vn-drop-down.shown li[name="Add turn"]',
moreMenuDeleteTicket: '.vn-drop-down.shown li[name="Delete ticket"]',
moreMenuMakeInvoice: '.vn-drop-down.shown li[name="Make invoice"]',
moreMenuChangeShippedHour: '.vn-drop-down.shown li[name="Change shipped hour"]',
changeShippedHourDialog: '.vn-dialog.shown',
changeShippedHourInput: '.vn-dialog.shown [ng-model="$ctrl.newShipped"]',
addStowawayDialogFirstTicket: '.vn-dialog.shown vn-table vn-tbody vn-tr',
shipButton: 'vn-ticket-descriptor vn-icon[icon="icon-stowaway"]',
thursdayButton: '.vn-popup.shown vn-tool-bar > vn-button:nth-child(4)',
saturdayButton: '.vn-popup.shown vn-tool-bar > vn-button:nth-child(6)',
closeStowawayDialog: '.vn-dialog.shown button[class="close"]',
acceptDeleteButton: '.vn-dialog.shown button[response="ACCEPT"]',
acceptChangeHourButton: '.vn-dialog.shown button[response="ACCEPT"]',
descriptorDeliveryDate: 'vn-ticket-descriptor > div > div.body > div.attributes > vn-label-value:nth-child(6) > section > span',
acceptInvoiceOutButton: 'vn-ticket-descriptor vn-confirm[vn-id="makeInvoiceConfirmation"] button[response="ACCEPT"]',
acceptDeleteStowawayButton: 'vn-ticket-descriptor > vn-remove-stowaway button[response="ACCEPT"]'
acceptInvoiceOutButton: '.vn-confirm.shown button[response="ACCEPT"]',
acceptDeleteStowawayButton: '.vn-dialog.shown button[response="ACCEPT"]'
},
ticketNotes: {
firstNoteRemoveButton: 'vn-icon[icon="delete"]',
addNoteButton: 'vn-icon[icon="add_circle"]',
firstNoteTypeAutocomplete: 'vn-autocomplete[ng-model="observation.observationTypeFk"]',
firstDescriptionInput: 'vn-textfield[label="Description"] input',
submitNotesButton: `${components.vnSubmit}`
submitNotesButton: `button[type=submit]`
},
ticketExpedition: {
expeditionButton: 'vn-left-menu a[ui-sref="ticket.card.expedition"]',
secondExpeditionRemoveButton: 'vn-ticket-expedition vn-table div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(1) > vn-icon-button[icon="delete"]',
acceptDeleteRowButton: 'vn-ticket-expedition > vn-confirm[vn-id="delete-expedition"] button[response=ACCEPT]',
acceptDeleteRowButton: '.vn-confirm.shown button[response=ACCEPT]',
expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr'
},
ticketPackages: {
@ -394,7 +394,7 @@ export default {
firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]',
addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]',
clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] .icons > vn-icon[icon=clear]',
savePackagesButton: `${components.vnSubmit}`
savePackagesButton: `button[type=submit]`
},
ticketSales: {
saleButton: 'vn-left-menu a[ui-sref="ticket.card.sale"]',
@ -403,13 +403,13 @@ export default {
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',
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',
moreMenuCreateClaim: '.vn-popover.shown .vn-drop-down li[name="Add claim"]',
moreMenuReserve: '.vn-popover.shown .vn-drop-down li[name="Mark as reserved"]',
moreMenuUnmarkReseved: '.vn-popover.shown .vn-drop-down li[name="Unmark as reserved"]',
moreMenuUpdateDiscount: '.vn-popover.shown .vn-drop-down li[name="Update discount"]',
moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog form vn-ticket-sale-edit-discount vn-input-number[ng-model="$ctrl.newDiscount"] input',
moreMenuCreateClaim: '.vn-drop-down.shown li[name="Add claim"]',
moreMenuReserve: '.vn-drop-down.shown li[name="Mark as reserved"]',
moreMenuUnmarkReseved: '.vn-drop-down.shown li[name="Unmark as reserved"]',
moreMenuUpdateDiscount: '.vn-drop-down.shown li[name="Update discount"]',
moreMenuUpdateDiscountInput: '.vn-dialog.shown form vn-ticket-sale-edit-discount vn-input-number[ng-model="$ctrl.newDiscount"] input',
transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text',
transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable',
firstSaleClaimIcon: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) vn-icon[icon="icon-claims"]',
@ -420,9 +420,8 @@ export default {
firstSaleQuantity: 'vn-input-number[ng-model="sale.quantity"]:nth-child(1) input',
firstSaleQuantityCell: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable:nth-child(5)',
firstSaleQuantityClearInput: 'vn-textfield[ng-model="sale.quantity"] div.suffix > i',
firstSaleIdInput: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete input',
firstSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete',
idAutocompleteFirstResult: '.vn-popover.shown .vn-drop-down li',
idAutocompleteFirstResult: '.vn-drop-down.shown li',
firstSalePrice: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(7) > span',
firstSalePriceInput: '.vn-popover.shown vn-input-number input',
firstSaleDiscount: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(8) > span',
@ -444,7 +443,7 @@ export default {
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)',
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',
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"]',
@ -454,15 +453,15 @@ export default {
moveToTicketInputClearButton: '.vn-popover.shown i[title="Clear"]',
moveToTicketButton: '.vn-popover.shown vn-icon[icon="arrow_forward_ios"]',
moveToNewTicketButton: '.vn-popover.shown vn-button[label="New ticket"]',
acceptDeleteLineButton: 'vn-ticket-sale > vn-confirm[vn-id="delete-lines"] button[response=ACCEPT]',
acceptDeleteTicketButton: 'vn-ticket-sale > vn-confirm[vn-id="delete-ticket"] button[response=ACCEPT]',
acceptDeleteLineButton: '.vn-confirm.shown button[response=ACCEPT]',
acceptDeleteTicketButton: '.vn-confirm.shown button[response=ACCEPT]',
stateMenuButton: 'vn-ticket-sale vn-tool-bar > vn-button-menu[label="State"]'
},
ticketTracking: {
trackingButton: 'vn-left-menu a[ui-sref="ticket.card.tracking.index"]',
createStateButton: `${components.vnFloatButton}`,
createStateButton: `vn-float-button`,
stateAutocomplete: 'vn-ticket-tracking-edit vn-autocomplete[ng-model="$ctrl.stateFk"]',
saveButton: `${components.vnSubmit}`,
saveButton: `button[type=submit]`,
cancelButton: 'vn-ticket-tracking-edit vn-button[ui-sref="ticket.card.tracking.index"]'
},
ticketBasicData: {
@ -471,9 +470,9 @@ export default {
addressAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.addressFk"]',
agencyAutocomplete: 'vn-autocomplete[ng-model="$ctrl.agencyModeId"]',
zoneAutocomplete: 'vn-autocomplete[ng-model="$ctrl.zoneId"]',
nextStepButton: 'vn-step-control > section > section.buttons > section:nth-child(2) > vn-button',
finalizeButton: 'vn-step-control > section > section.buttons > section:nth-child(2) > vn-submit',
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > form > vn-card > div > vn-horizontal > table > tfoot > tr > td:nth-child(4)',
nextStepButton: 'vn-step-control .buttons > section:last-child vn-button',
finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]',
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"]',
},
ticketComponents: {
@ -482,12 +481,12 @@ export default {
ticketRequests: {
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
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',
atenderAutocomplete: 'vn-ticket-request-create vn-autocomplete[ng-model="$ctrl.ticketRequest.atenderFk"]',
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.attenderFk"]',
quantityInput: 'vn-ticket-request-create vn-input-number input[name=quantity]',
priceInput: 'vn-ticket-request-create vn-input-number input[name=price]',
firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)',
saveButton: 'vn-ticket-request-create > form > div > vn-button-bar > vn-submit[label="Create"] input',
saveButton: 'vn-ticket-request-create button[type=submit]',
firstDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(2)',
},
@ -499,66 +498,66 @@ export default {
},
ticketService: {
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"] > button',
firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]',
firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.description"]',
firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input',
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
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',
serviceLine: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(2) > vn-horizontal',
saveServiceButton: `${components.vnSubmit}`,
saveDescriptionButton: 'vn-ticket-service > vn-dialog[vn-id="createServiceTypeDialog"] > div > form > div.buttons > tpl-buttons > button'
newDescriptionInput: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
saveServiceButton: `button[type=submit]`,
saveDescriptionButton: '.vn-dialog.shown tpl-buttons > button'
},
createStateView: {
stateAutocomplete: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',
workerAutocomplete: 'vn-autocomplete[ng-model="$ctrl.workerFk"]',
clearStateInputButton: 'vn-autocomplete[ng-model="$ctrl.stateFk"] .icons > vn-icon[icon=clear]',
saveStateButton: `${components.vnSubmit}`
saveStateButton: `button[type=submit]`
},
claimsIndex: {
searchClaimInput: `vn-claim-index ${components.vnTextfield}`,
searchResult: 'vn-claim-index vn-card > div > vn-table > div > vn-tbody > a',
searchClaimInput: `vn-claim-index vn-textfield input`,
searchResult: 'vn-claim-index vn-card > vn-table > div > vn-tbody > a',
searchButton: 'vn-claim-index vn-searchbar vn-icon[icon="search"]'
},
claimDescriptor: {
moreMenu: 'vn-claim-descriptor vn-icon-menu[vn-id="more-button"]',
moreMenuDeleteClaim: '.vn-popover.shown .vn-drop-down li[name="Delete claim"]',
acceptDeleteClaim: 'vn-claim-descriptor > vn-confirm[vn-id="confirm-delete-claim"] button[response="ACCEPT"]'
moreMenu: 'vn-claim-descriptor vn-icon-menu[icon=more_vert]',
moreMenuDeleteClaim: '.vn-drop-down.shown li[name="Delete claim"]',
acceptDeleteClaim: '.vn-confirm.shown button[response="ACCEPT"]'
},
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',
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',
firstSaleDescriptorImage: '.vn-popover.shown vn-item-descriptor img',
itemDescriptorPopover: '.vn-popover.shown vn-item-descriptor',
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',
firstDevelopmentWorkerGoToClientButton: '.vn-popover.shown vn-worker-descriptor div.quicklinks > 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',
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 vn-quick-links > a[href="#!/client/21/summary"]',
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'
},
claimBasicData: {
claimStateAutocomplete: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]',
responsabilityInputRange: 'vn-input-range',
responsabilityInputRange: 'vn-range',
observationInput: 'vn-textarea[ng-model="$ctrl.claim.observation"] textarea',
saveButton: `${components.vnSubmit}`
saveButton: `button[type=submit]`
},
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',
discoutPopoverMana: '.vn-popover.shown .content > div > vn-horizontal > h5',
addItemButton: 'vn-claim-detail a vn-float-button',
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',
firstClaimableSaleFromTicket: '.vn-dialog.shown 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',
totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > div > 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'
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 > 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: {
addDevelopmentButton: 'vn-claim-development > vn-vertical > vn-card > div > 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',
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 > 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"]',
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"]',
@ -569,7 +568,7 @@ export default {
secondClaimResponsibleAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]',
secondClaimWorkerAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.workerFk"]',
secondClaimRedeliveryAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimRedeliveryFk"]',
saveDevelopmentButton: `${components.vnSubmit}`
saveDevelopmentButton: `button[type=submit]`
},
claimAction: {
importClaimButton: 'vn-claim-action vn-button[label="Import claim"]',
@ -581,23 +580,23 @@ export default {
isPaidWithManaCheckbox: 'vn-check[ng-model="$ctrl.claim.isChargedToMana"]'
},
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)',
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
searchOrderInput: `vn-order-index ${components.vnTextfield}`,
searchOrderInput: `vn-order-index vn-textfield input`,
searchButton: 'vn-order-index vn-searchbar vn-icon[icon="search"]',
createOrderButton: `${components.vnFloatButton}`,
createOrderButton: `vn-float-button`,
},
orderDescriptor: {
returnToModuleIndexButton: 'vn-order-descriptor a[ui-sref="order.index"]',
acceptNavigationButton: 'vn-order-basic-data vn-confirm button[response=ACCEPT]'
acceptNavigationButton: '.vn-confirm.shown button[response=ACCEPT]'
},
createOrderView: {
clientAutocomplete: 'vn-autocomplete[label="Client"]',
addressAutocomplete: 'vn-autocomplete[label="Address"]',
agencyAutocomplete: 'vn-autocomplete[label="Agency"]',
landedDatePicker: 'vn-date-picker[label="Landed"]',
createButton: `${components.vnSubmit}`,
createButton: `button[type=submit]`,
cancelButton: 'vn-button[href="#!/client/index"]'
},
orderCatalog: {
@ -609,23 +608,23 @@ export default {
openTagSearch: 'vn-catalog-filter > div > vn-vertical > vn-textfield[ng-model="$ctrl.value"] .append i',
tagAutocomplete: 'vn-order-catalog-search-panel vn-autocomplete[ng-model="filter.tagFk"]',
tagValueInput: 'vn-order-catalog-search-panel vn-textfield[ng-model="filter.value"] input',
searchTagButton: 'vn-order-catalog-search-panel > div > form > vn-horizontal:nth-child(3) > vn-submit > input',
thirdFilterRemoveButton: 'vn-catalog-filter > div > vn-horizontal.chips > vn-chip:nth-child(3) button',
fourthFilterRemoveButton: 'vn-catalog-filter > div > vn-horizontal.chips > vn-chip:nth-child(4) button',
searchTagButton: 'vn-order-catalog-search-panel button[type=submit]',
thirdFilterRemoveButton: 'vn-catalog-filter .chips > vn-chip:nth-child(3) vn-icon[icon=cancel]',
fourthFilterRemoveButton: 'vn-catalog-filter .chips > vn-chip:nth-child(4) vn-icon[icon=cancel]',
},
orderBasicData: {
clientAutocomplete: 'vn-autocomplete[label="Client"]',
addressAutocomplete: 'vn-autocomplete[label="Address"]',
agencyAutocomplete: 'vn-autocomplete[label="Agency"]',
observationInput: 'vn-textarea[label="Observation"] textarea',
saveButton: `${components.vnSubmit}`,
acceptButton: 'vn-order-basic-data vn-confirm[vn-id="confirm"] button[response="ACCEPT"]'
saveButton: `button[type=submit]`,
acceptButton: '.vn-confirm.shown button[response="ACCEPT"]'
},
orderLine: {
orderSubtotal: 'vn-order-line vn-horizontal.header p:nth-child(1)',
orderSubtotal: 'vn-order-line .header :first-child',
firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]',
confirmOrder: 'vn-order-line > vn-vertical > vn-button-bar > vn-button > button',
confirmButton: 'vn-order-line > vn-confirm button[response="ACCEPT"]',
confirmOrder: 'vn-order-line vn-float-button',
confirmButton: '.vn-confirm.shown button[response="ACCEPT"]',
},
routeIndex: {
addNewRouteButton: 'vn-route-index > a[ui-sref="route.create"]'
@ -636,13 +635,13 @@ export default {
vehicleAutoComplete: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]',
agencyAutoComplete: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.agencyModeFk"]',
descriptionInput: 'vn-route-create vn-textfield[ng-model="$ctrl.route.description"] input',
submitButton: 'vn-route-create vn-submit > input[type="submit"]'
submitButton: 'vn-route-create button[type=submit]'
},
routeDescriptor: {
volume: 'vn-route-descriptor vn-label-value[label="Volume"] > section > span'
},
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: {
workerAutoComplete: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
@ -653,7 +652,7 @@ export default {
createdDateInput: 'vn-route-basic-data vn-date-picker[ng-model="$ctrl.route.created"]',
startedHourInput: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.started"] input',
finishedHourInput: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.finished"] input',
saveButton: 'vn-route-basic-data vn-submit[label="Save"] input'
saveButton: 'vn-route-basic-data button[type=submit]'
},
routeTickets: {
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-textfield[ng-model="ticket.priority"] input',
@ -664,75 +663,76 @@ export default {
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check',
buscamanButton: 'vn-route-tickets vn-button[icon="icon-buscaman"]',
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',
confirmButton: 'vn-route-tickets > vn-confirm button[response="ACCEPT"]'
confirmButton: '.vn-confirm.shown button[response="ACCEPT"]'
},
workerPbx: {
extensionInput: 'vn-worker-pbx vn-textfield[ng-model="$ctrl.worker.sip.extension"] input',
saveButton: 'vn-worker-pbx vn-submit[label="Save"] input'
saveButton: 'vn-worker-pbx button[type=submit]'
},
workerTimeControl: {
timeDialogInput: 'vn-worker-time-control > vn-dialog input',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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',
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)',
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)',
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)',
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)',
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)',
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)',
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)',
weekWorkedHours: 'vn-worker-time-control > div > vn-side-menu > div > vn-vertical > vn-vertical > 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',
timeDialogInput: '.vn-dialog.shown [ng-model="$ctrl.newTime"]',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(2) > vn-icon-button',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-icon-button',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button',
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-dialog.shown tpl-buttons > button',
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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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 vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > span',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(4)',
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 vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(6)',
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 vn-side-menu vn-label-value > section > span',
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"]'
},
invoiceOutIndex: {
searchInvoiceOutInput: `vn-invoice-out-index ${components.vnTextfield}`,
searchInvoiceOutInput: `vn-invoice-out-index vn-textfield input`,
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: {
moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[vn-id="more-button"]',
moreMenuDeleteInvoiceOut: '.vn-popover.shown .vn-drop-down li[name="Delete Invoice"]',
moreMenuBookInvoiceOut: '.vn-popover.shown .vn-drop-down li[name="Book invoice"]',
moreMenuShowInvoiceOutPdf: '.vn-popover.shown .vn-drop-down li[name="Show invoice PDF"]',
acceptDeleteButton: 'vn-invoice-out-descriptor > vn-confirm[vn-id="deleteConfirmation"] button[response="ACCEPT"]',
acceptBookingButton: 'vn-invoice-out-descriptor > vn-confirm[vn-id="bookConfirmation"] button[response="ACCEPT"]'
moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[icon=more_vert]',
moreMenuDeleteInvoiceOut: '.vn-drop-down.shown li[name="Delete Invoice"]',
moreMenuBookInvoiceOut: '.vn-drop-down.shown li[name="Book invoice"]',
moreMenuShowInvoiceOutPdf: '.vn-drop-down.shown li[name="Show invoice PDF"]',
acceptDeleteButton: '.vn-confirm.shown button[response="ACCEPT"]',
acceptBookingButton: '.vn-confirm.shown button[response="ACCEPT"]'
},
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'
}
};

View File

@ -1,58 +1,35 @@
import createNightmare from '../../helpers/nightmare';
import config from '../../helpers/config.js';
describe('Login path', () => {
const nightmare = createNightmare();
it('should receive an error when the username is incorrect', async() => {
const username = 'nobody';
const password = 'nightmare';
const result = await nightmare
.goto(`${config.url}/#!/login`)
.wait(`vn-login input[name=user]`)
.write(`vn-login input[name=user]`, username)
.write(`vn-login input[name=password]`, password)
.click(`vn-login input[type=submit]`)
.doLogin('badUser', null)
.waitForLastSnackbar();
expect(result.length).toBeGreaterThan(0);
});
it('should receive an error when the username is blank', async() => {
const password = 'nightmare';
const result = await nightmare
.clearInput(`vn-login input[name=user]`)
.write(`vn-login input[name=password]`, password)
.click(`vn-login input[type=submit]`)
.doLogin('', null)
.waitForLastSnackbar();
expect(result.length).toBeGreaterThan(0);
});
it('should receive an error when the password is incorrect', async() => {
const username = 'employee';
const password = 'badpassword';
const result = await nightmare
.write(`vn-login input[name=user]`, username)
.write(`vn-login input[name=password]`, password)
.click(`vn-login input[type=submit]`)
.doLogin('employee', 'badPassword')
.waitForLastSnackbar();
expect(result.length).toBeGreaterThan(0);
});
it('should log in', async() => {
const username = 'employee';
const password = 'nightmare';
const url = await nightmare
.write(`vn-login input[name=user]`, username)
.write(`vn-login input[name=password]`, password)
.click(`vn-login input[type=submit]`)
.doLogin('employee', null)
.wait('#logout')
.parsedUrl();

View File

@ -42,9 +42,7 @@ describe('Client Edit fiscalData path', () => {
it('should not be able to edit the verified data checkbox', async() => {
const result = await nightmare
.wait(selectors.clientFiscalData.verifiedDataCheckbox)
.evaluate(selector => {
return document.querySelector(selector).getAttribute('disabled');
}, selectors.clientFiscalData.verifiedDataCheckbox);
.isDisabled(selectors.clientFiscalData.verifiedDataCheckbox);
expect(result).toBeTruthy();
});

View File

@ -110,7 +110,7 @@ describe('Client Add address path', () => {
it(`should go back to the addreses section by clicking the cancel button`, async() => {
const url = await nightmare
.waitToClick(selectors.clientAddresses.cancelEditAddressButton)
.waitToClick('vn-confirm button[response="ACCEPT"]')
.waitToClick('.vn-confirm.shown button[response="ACCEPT"]')
.waitForURL('address/index')
.parsedUrl();

View File

@ -16,9 +16,7 @@ describe('Client lock verified data path', () => {
const result = await nightmare
.wait(200)
.wait(selectors.clientFiscalData.verifiedDataCheckbox)
.evaluate(selector => {
return document.querySelector(selector).getAttribute('disabled');
}, selectors.clientFiscalData.verifiedDataCheckbox);
.isDisabled(selectors.clientFiscalData.verifiedDataCheckbox);
expect(result).toBeTruthy();
});

View File

@ -286,11 +286,11 @@ describe('Worker time control path', () => {
});
});
describe('as salesBoss', () => {
describe('as hr', () => {
describe('on Saturday', () => {
beforeAll(() => {
nightmare
.loginAndModule('salesBoss', 'worker')
.loginAndModule('hr', 'worker')
.accessToSearchResult('HankPym')
.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() => {
const wholeWeekHours = await nightmare
.waitToClick(selectors.workerTimeControl.nextMonthButton)
.waitToClick(selectors.workerTimeControl.nextMonthButton)
.waitToClick(selectors.workerTimeControl.secondWeekDay)
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 h.')
.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() => {
@ -371,7 +372,7 @@ describe('Worker time control path', () => {
.accessToSection('worker.card.timeControl')
.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() => {
const wholeWeekHours = await nightmare
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 Hours')
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 h.')
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
expect(wholeWeekHours).toEqual('56:00 Hours');
expect(wholeWeekHours).toEqual('56:00 h.');
});
});
});

View File

@ -21,16 +21,12 @@ describe('Item summary path', () => {
});
it(`should click on the search result summary button to open the item summary popup`, async() => {
const isVisibleBefore = await nightmare
const isVisible = await nightmare
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Ranged weapon longbow 2m')
.isVisible(selectors.itemSummary.basicData);
const isVisibleAfter = await nightmare
.waitToClick(selectors.itemsIndex.searchResultPreviewButton)
.isVisible(selectors.itemSummary.basicData);
expect(isVisibleBefore).toBeFalsy();
expect(isVisibleAfter).toBeTruthy();
expect(isVisible).toBeTruthy();
});
it(`should check the item summary preview shows fields from basic data`, async() => {
@ -75,8 +71,9 @@ describe('Item summary path', () => {
it(`should close the summary popup`, async() => {
const result = await nightmare
.waitToClick(selectors.itemsIndex.closeItemSummaryPreview)
.isVisible(selectors.itemSummary.basicData);
.mousedown(selectors.itemsIndex.closeItemSummaryPreview)
.waitUntilNotPresent(selectors.itemSummary.basicData)
.visible(selectors.itemSummary.basicData);
expect(result).toBeFalsy();
});
@ -94,17 +91,13 @@ describe('Item summary path', () => {
});
it(`should now click on the search result summary button to open the item summary popup`, async() => {
const isVisibleBefore = await nightmare
const isVisible = await nightmare
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Melee weapon combat fist 15cm')
.isVisible(selectors.itemSummary.basicData);
const isVisibleAfter = await nightmare
.waitToClick(selectors.itemsIndex.searchResultPreviewButton)
.isVisible(selectors.itemSummary.basicData);
expect(isVisibleBefore).toBeFalsy();
expect(isVisibleAfter).toBeTruthy();
expect(isVisible).toBeTruthy();
});
it(`should now check the item summary preview shows fields from basic data`, async() => {
@ -149,8 +142,9 @@ describe('Item summary path', () => {
it(`should now close the summary popup`, async() => {
const result = await nightmare
.waitToClick(selectors.itemsIndex.closeItemSummaryPreview)
.isVisible(selectors.itemSummary.basicData);
.mousedown(selectors.itemsIndex.closeItemSummaryPreview)
.waitUntilNotPresent(selectors.itemSummary.basicData)
.visible(selectors.itemSummary.basicData);
expect(result).toBeFalsy();
});

View File

@ -30,6 +30,7 @@ describe('Ticket Edit basic data path', () => {
it(`should confirm the zone autocomplete is enabled for the role productionBoss`, async() => {
const disabled = await nightmare
.waitForSpinnerLoad()
.wait(selectors.ticketBasicData.zoneAutocomplete)
.evaluate(selector => {
return document.querySelector(selector).disabled;

View File

@ -30,18 +30,10 @@ describe('Ticket descriptor path', () => {
expect(url.hash).toContain('/summary');
});
it('should open the change shipped hours dialog by using the more menu option', async() => {
const visible = await nightmare
it(`should update the shipped hour using the descriptor menu`, async() => {
const result = await nightmare
.waitToClick(selectors.ticketDescriptor.moreMenu)
.waitToClick(selectors.ticketDescriptor.moreMenuChangeShippedHour)
.wait(selectors.ticketDescriptor.changeShippedHourInput)
.isVisible(selectors.ticketDescriptor.changeShippedHourInput);
expect(visible).toBeTruthy();
});
it(`should update the shipped hour`, async() => {
const result = await nightmare
.pickTime(selectors.ticketDescriptor.changeShippedHourInput, '08:15')
.waitToClick(selectors.ticketDescriptor.acceptChangeHourButton)
.waitForLastSnackbar();

View File

@ -17,9 +17,7 @@ describe('Ticket services path', () => {
const result = await nightmare
.waitToClick(selectors.ticketService.addServiceButton)
.wait(selectors.ticketService.firstAddDescriptionButton)
.evaluate(selector => {
return document.querySelector(selector).disabled;
}, selectors.ticketService.firstAddDescriptionButton);
.isDisabled(selectors.ticketService.firstAddDescriptionButton);
expect(result).toBeTruthy();
});
@ -67,7 +65,7 @@ describe('Ticket services path', () => {
it('should click on the add new description to open the dialog', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.firstAddDescriptionButton)
.waitForClassPresent('vn-ticket-service > vn-dialog', 'shown')
.wait('.vn-dialog.shown')
.isVisible(selectors.ticketService.newDescriptionInput);
expect(result).toBeTruthy();

View File

@ -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() => {
let result = await nightmare
.waitForSpinnerLoad()
.waitForTextInElement(selectors.ticketSummary.header, 'Bruce Banner')
.waitToGetProperty(selectors.ticketSummary.header, 'innerText');
expect(result).toContain(`Ticket #${ticketId}`);

View File

@ -66,7 +66,7 @@ describe('Order catalog', () => {
const result = await nightmare
.waitToClick(selectors.orderCatalog.fourthFilterRemoveButton)
.waitToClick(selectors.orderCatalog.thirdFilterRemoveButton)
.waitForNumberOfElements('section.product', 4)
.waitForNumberOfElements('.product', 4)
.countElement('section.product');
expect(result).toEqual(4);

View File

@ -3,7 +3,6 @@ import createNightmare from '../../helpers/nightmare';
describe('InvoiceOut descriptor path', () => {
const nightmare = createNightmare();
let bookedDate;
describe('as Administrative', () => {
beforeAll(() => {
@ -123,10 +122,9 @@ describe('InvoiceOut descriptor path', () => {
it(`should check the invoiceOut is booked in the summary data`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.invoiceOutSummary.bookedLabel, '/')
.waitToGetProperty(selectors.invoiceOutSummary.bookedLabel, 'innerText');
bookedDate = result;
expect(result.length).toBeGreaterThan(1);
});
@ -141,10 +139,13 @@ describe('InvoiceOut descriptor path', () => {
});
it(`should check the invoiceOut booked in the summary data`, async() => {
let today = new Date();
let expectedDate = `${today.getDate()}/${(today.getMonth() + 1)}/${today.getFullYear()}`;
const result = await nightmare
.waitToGetProperty(selectors.invoiceOutSummary.bookedLabel, 'innerText');
expect(result).not.toEqual(bookedDate);
expect(result).toEqual(expectedDate);
});
});

View File

@ -100,7 +100,7 @@ export default class ArrayModel extends ModelProxy {
addFilter(user, params) {
this.userFilter = this.mergeFilters(user, this.userFilter);
Object.assign(this.userParams, params);
this.userParams = Object.assign({}, this.userParams, params);
return this.refresh();
}

View File

@ -1,6 +1,6 @@
<div
class="container"
ng-click="$ctrl.onContainerMouseDown($event)"
ng-click="$ctrl.onContainerClick($event)"
ng-keydown="$ctrl.onContainerKeyDown($event)">
<div
ng-transclude="prepend"
@ -26,7 +26,7 @@
ng-click="$ctrl.onClear($event)">
</vn-icon>
<vn-icon
ng-if="::$ctrl.info"
ng-if="::$ctrl.info != null"
icon="info_outline"
vn-tooltip="{{::$ctrl.info}}">
</vn-icon>
@ -48,5 +48,5 @@
vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(item)"
on-data-ready="$ctrl.onDataReady()"
on-close="$ctrl.focus()">
on-close-start="$ctrl.onDropDownClose()">
</vn-drop-down>

View File

@ -17,14 +17,9 @@ import './style.scss';
* @event change Thrown when value is changed
*/
export default class Autocomplete extends Field {
constructor($element, $scope, $compile, $http, $transclude, $translate, $interpolate) {
super($element, $scope, $compile);
Object.assign(this, {
$http,
$interpolate,
$transclude,
$translate
});
constructor($element, $, $compile, $transclude) {
super($element, $, $compile);
this.$transclude = $transclude;
this._selection = null;
this.input = this.element.querySelector('input');
@ -48,7 +43,6 @@ export default class Autocomplete extends Field {
set field(value) {
super.field = value;
this.refreshSelection();
this.emit('change', {value});
}
get model() {
@ -121,7 +115,6 @@ export default class Autocomplete extends Field {
return;
const selection = this.fetchSelection();
this.selection = selection;
}
@ -206,13 +199,17 @@ export default class Autocomplete extends Field {
onDropDownSelect(item) {
const value = item[this.valueField];
this.selection = item;
this.field = value;
this.change(value);
}
onDropDownClose() {
setTimeout(() => this.focus());
}
onContainerKeyDown(event) {
if (event.defaultPrevented) return;
switch (event.code) {
switch (event.key) {
case 'ArrowUp':
case 'ArrowDown':
case 'Enter':
@ -224,13 +221,10 @@ export default class Autocomplete extends Field {
else
return;
}
event.preventDefault();
}
onContainerMouseDown(event) {
onContainerClick(event) {
if (event.defaultPrevented) return;
event.preventDefault();
this.showDropDown();
}
@ -240,12 +234,13 @@ export default class Autocomplete extends Field {
assignDropdownProps() {
if (!this.$.dropDown) return;
this.$.dropDown.copySlot('tplItem', this.$transclude);
assignProps(this, this.$.dropDown, [
'valueField',
'showField',
'showFilter',
'multiple',
'$transclude',
'translateFields',
'model',
'data',
@ -260,6 +255,7 @@ export default class Autocomplete extends Field {
}
showDropDown(search) {
if (this.readonly) return;
this.assignDropdownProps();
this.$.dropDown.show(this.container, search);
}
@ -275,7 +271,7 @@ export default class Autocomplete extends Field {
this.refreshSelection();
}
}
Autocomplete.$inject = ['$element', '$scope', '$compile', '$http', '$transclude', '$translate', '$interpolate'];
Autocomplete.$inject = ['$element', '$scope', '$compile', '$transclude'];
ngModule.vnComponent('vnAutocomplete', {
template: require('./index.html'),

View File

@ -3,9 +3,7 @@ describe('Component vnAutocomplete', () => {
let controller;
let data = {id: 1, name: 'Bruce Wayne'};
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-autocomplete></vn-autocomplete>`)($rootScope);

View File

@ -1,6 +1,6 @@
@import "effects";
vn-autocomplete.vn-field {
.vn-autocomplete {
overflow: hidden;
& > .container {
@ -20,4 +20,7 @@ vn-autocomplete.vn-field {
}
}
}
&.readonly > .container > .icons.post {
display: none;
}
}

View File

@ -1,13 +0,0 @@
<div class="button-menu">
<button
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored button-menu__button">
<vn-label vn-none translate>{{::$ctrl.label}}</vn-label>
<vn-icon vn-none icon="{{::$ctrl.icon}}"></vn-icon>
<vn-icon vn-none class="button-menu__arrow_down" icon="keyboard_arrow_down"></vn-icon>
</button>
<vn-drop-down
vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(item)"
ng-click="$ctrl.onDropDownClick($event)">
</vn-drop-down>
</div>

View File

@ -0,0 +1,19 @@
<button>
<span
ng-if="::$ctrl.label"
translate>
{{::$ctrl.label}}
</span>
<vn-icon
ng-if="::$ctrl.icon"
icon="{{::$ctrl.icon}}">
</vn-icon>
<vn-icon
class="button-menu__arrow_down"
icon="keyboard_arrow_down">
</vn-icon>
</button>
<vn-drop-down
vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(item)">
</vn-drop-down>

View File

@ -1,17 +1,13 @@
import ngModule from '../../module';
import Input from '../../lib/input';
import Button from '../button';
import assignProps from '../../lib/assign-props';
import './style.scss';
export default class ButtonMenu extends Input {
export default class ButtonMenu extends Button {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.$transclude = $transclude;
this.input = this.element.querySelector('.mdl-button');
$element.on('click', e => {
if (!this.disabled)
this.onClick(e);
});
$element.on('click', e => this.onClick(e));
}
get model() {
@ -46,16 +42,12 @@ export default class ButtonMenu extends Input {
}
onClick(event) {
if (this.disabled) return;
if (event.defaultPrevented) return;
event.preventDefault();
this.emit('open');
this.showDropDown();
}
onDropDownClick(event) {
event.preventDefault();
}
onDropDownSelect(item) {
const value = item[this.valueField];
this.field = value;
@ -63,12 +55,13 @@ export default class ButtonMenu extends Input {
}
showDropDown() {
this.$.dropDown.copySlot('tplItem', this.$transclude);
assignProps(this, this.$.dropDown, [
'valueField',
'showField',
'showFilter',
'multiple',
'$transclude',
'translateFields',
'model',
'data',
@ -85,15 +78,14 @@ export default class ButtonMenu extends Input {
}
ButtonMenu.$inject = ['$element', '$scope', '$transclude'];
ngModule.component('vnButtonMenu', {
template: require('./button-menu.html'),
ngModule.vnComponent('vnButtonMenu', {
template: require('./index.html'),
controller: ButtonMenu,
bindings: {
label: '@',
showField: '@?',
selection: '<?',
valueField: '@?',
selectFields: '<?',
disabled: '<?',
initialData: '<?',
showFilter: '<?',
field: '=?',
@ -104,12 +96,10 @@ ngModule.component('vnButtonMenu', {
limit: '<?',
multiple: '<?',
onChange: '&?',
icon: '@?',
translateFields: '<?',
onOpen: '&?'
},
transclude: {
tplItem: '?tplItem'
},
controller: ButtonMenu
}
});

View File

@ -2,9 +2,7 @@ describe('Component vnButtonMenu', () => {
let controller;
let $element;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-icon-menu></vn-icon-menu>`)($rootScope);

View File

@ -1,19 +1,3 @@
vn-button-menu {
.vn-button-menu {
position: relative;
cursor: pointer;
.button-menu__button {
padding: 0 10px;
}
vn-label {
float: left;
margin-top: 1px;
}
vn-icon {
float: left;
margin-top: 3px;
}
vn-icon.button-menu__arrow_down {
margin: 6px 0 0 5px;
}
}

View File

@ -1,6 +0,0 @@
<button type="{{::$ctrl.type}}" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
<span translate>{{$ctrl.label}}</span>
<vn-icon
icon="{{::$ctrl.icon}}">
</vn-icon>
</button>

View File

@ -1,34 +0,0 @@
import ngModule from '../../module';
import Input from '../../lib/input';
import './style.scss';
export default class Button extends Input {
constructor($element) {
super($element);
this.$element = $element;
this.input = this.element.querySelector('.mdl-button');
$element[0].addEventListener('click', event => {
if (this.disabled)
event.stopImmediatePropagation();
});
}
$onInit() {
if (!this.type)
this.type = 'button';
}
}
Button.$inject = ['$element'];
ngModule.component('vnButton', {
controller: Button,
template: require('./button.html'),
bindings: {
label: '@?',
disabled: '<?',
icon: '@?',
type: '@?'
}
});

View File

@ -0,0 +1,11 @@
<button type="{{::$ctrl.type}}" tabindex="-1">
<span
ng-if="::$ctrl.label"
translate>
{{::$ctrl.label}}
</span>
<vn-icon
ng-if="::$ctrl.icon"
icon="{{::$ctrl.icon}}">
</vn-icon>
</button>

View File

@ -0,0 +1,43 @@
import ngModule from '../../module';
import FormInput from '../form-input';
import './style.scss';
export default class Button extends FormInput {
constructor($element, $scope) {
super($element, $scope);
this.design = 'colored';
this.initTabIndex();
this.element.addEventListener('keyup', e => this.onKeyup(e));
this.element.addEventListener('click', e => this.onClick(e));
}
$onInit() {
this.element.classList.add(this.design);
if (!this.type) this.type = 'button';
}
onKeyup(event) {
if (event.defaultPrevented) return;
switch (event.key) {
case ' ':
case 'Enter':
return this.element.click();
}
}
onClick(event) {
if (this.disabled)
event.stopImmediatePropagation();
}
}
Button.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnButton', {
controller: Button,
template: require('./index.html'),
bindings: {
icon: '@?',
type: '@?'
}
});

View File

@ -1,5 +1,83 @@
vn-button {
& > button > vn-icon {
vertical-align: middle;
@import "variables";
.vn-button {
display: inline-flex;
align-items: center;
justify-content: center;
height: 36px;
border: none;
border-radius: .1em;
font-family: vn-font-bold;
text-transform: uppercase;
font-size: 14px;
cursor: pointer;
box-sizing: border-box;
outline: none;
& > button {
width: 100%;
padding: 0 12px;
box-sizing: border-box;
background-color: transparent;
border: none;
height: inherit;
color: inherit;
font: inherit;
display: block;
text-transform: inherit;
cursor: inherit;
outline: none;
display: flex;
align-items: center;
justify-content: center;
& > vn-icon {
vertical-align: middle;
color: inherit;
font-size: 1.7em;
}
}
}
&.colored {
color: white;
background-color: $color-main;
box-shadow: 0 .15em .15em 0 rgba(0, 0, 0, .3);
transition: background 200ms ease-in-out;
&:not(.disabled) {
&:hover,
&:focus {
background-color: lighten($color-main, 10%);
}
}
}
&.flat {
color: $color-main;
background-color: transparent;
box-shadow: none;
transition: background 200ms ease-in-out;
&:not(.disabled) {
&:hover,
&:focus {
background-color: $color-hover-cd;
}
}
}
&:hover,
&:focus {
outline: none;
}
&.round {
border-radius: 50%;
height: 3.8em;
width: 3.8em;
& > button > span {
display: none;
}
}
&.disabled {
opacity: .7;
cursor: initial;
}
}

View File

@ -1,82 +1,46 @@
<div>
<vn-horizontal class="header">
<vn-auto>
<vn-icon
icon="keyboard_arrow_left"
class="pointer"
ng-click="$ctrl.movePrevious($ctrl.skip)"
ng-show="$ctrl.displayControls"/>
</vn-icon>
</vn-auto>
<vn-one>
<div>
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
<span>{{$ctrl.defaultDate | date: 'yyyy'}}</span>
<div class="header">
<vn-button
icon="keyboard_arrow_left"
class="flat"
ng-click="$ctrl.movePrevious()"
translate-attr="::{title: 'Previous'}"
ng-if="$ctrl.displayControls"/>
</vn-button>
<div class="title">
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
<span ng-hide="::$ctrl.hideYear">{{$ctrl.defaultDate | date: 'yyyy'}}</span>
</div>
<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>
</vn-one>
<vn-auto>
<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>
</section>
</div>
</div>

View File

@ -1,43 +1,26 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import FormInput from '../form-input';
import './style.scss';
/**
* 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} 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 {
constructor($element, $scope) {
export default class Calendar extends FormInput {
constructor($element, $scope, vnWeekDays) {
super($element, $scope);
this.events = [];
this.weekDays = vnWeekDays.locales;
this.defaultDate = new Date();
this.displayControls = true;
this.disabled = false;
this.skip = 1;
this.window.addEventListener('resize', () => {
this.checkSize();
});
}
/**
* Resizes the calendar
* 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
* The initial date
*
* @return {Date} - Default date
*/
@ -45,11 +28,6 @@ export default class Calendar extends Component {
return this._defaultDate;
}
/**
* Sets a new initial date
*
* @param {Date} value - New default date
*/
set defaultDate(value) {
if (value) {
value = new Date(value);
@ -58,67 +36,10 @@ export default class Calendar extends Component {
}
this._defaultDate = value;
this.month = value.getMonth();
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
*
@ -126,185 +47,113 @@ export default class Calendar extends Component {
* @return {Integer}
*/
firstDay(date) {
const newDate = new Date(
return new Date(
date.getFullYear(),
date.getMonth(), 1);
return newDate;
date.getMonth(),
1
);
}
/**
* Returns last day of month from a given date
*
* @param {Date} date - Origin date
* @return {Integer}
* Repaints the calendar.
*/
lastDay(date) {
const newDate = new Date(
date.getFullYear(),
date.getMonth() + 1, 0);
return newDate;
}
repaint() {
const firstWeekday = this.firstDay(this.currentMonth).getDay();
const previousLastDay = this.lastDay(this.previousMonth).getDate();
const currentLastDay = this.lastDay(this.currentMonth).getDate();
const maxFields = 42; // Max field limit
const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1;
let weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
let weekdayOffset = firstWeekday > 0 ? firstWeekday : 7;
let dayPrevious = previousLastDay - (weekdayOffset - 2);
let dayCurrent = 1;
let dayNext = 1;
let dayIndex = new Date(this.defaultDate.getTime());
dayIndex.setDate(1 - weekdayOffset);
this.days = [];
for (let fieldIndex = 1; fieldIndex < maxFields; fieldIndex++) {
// Insert previous month days
if (fieldIndex < weekdayOffset) {
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++;
}
for (let i = 1; i <= 42; i++) {
this.days.push(new Date(dayIndex.getTime()));
dayIndex.setDate(dayIndex.getDate() + 1);
}
}
/**
* 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 {String} className - Default class style
* @param {Date} day The day
* @return {Object} The CSS classes to apply
*/
insertDay(dated) {
let events = this.events.filter(event => {
return event.dated >= dated && event.dated <= dated;
});
getDayClasses(day) {
let wday = day.getDay();
let month = day.getMonth();
const params = {dated: dated, events: events /**/, style: {}};
const isSaturday = dated.getDay() === 6;
const isSunday = dated.getDay() === 0;
const isCurrentMonth = dated.getMonth() === this.currentMonth.getMonth();
const hasEvents = events.length > 0;
let classes = {
weekend: wday === 6 || wday === 0,
previous: month < this.month,
current: month == this.month,
next: month > this.month,
event: this.hasEvents({$day: day})
};
if (isCurrentMonth && isSunday && !hasEvents)
params.style = {color: '#999'};
let userClass = this.getClass({$day: day});
if (userClass) classes[userClass] = true;
if (isCurrentMonth && isSaturday && !hasEvents)
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);
return classes;
}
/**
* Moves to next month(s)
*
* @param {Integer} skip - Months to skip at once
*/
moveNext(skip = 1) {
let next = this.defaultDate.getMonth() + skip;
this.defaultDate.setMonth(next);
this.repaint();
this.emit('moveNext');
moveNext() {
this.move(1);
}
/**
* Moves to previous month(s)
*
* @param {Integer} skip - Months to skip at once
*/
movePrevious(skip = 1) {
let previous = this.defaultDate.getMonth() - skip;
this.defaultDate.setMonth(previous);
this.repaint();
this.emit('movePrevious');
movePrevious() {
this.move(-1);
}
/**
* 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) {
if (this.disabled) return;
let day = this.days[index].dated;
move(direction) {
let date = new Date(this.defaultDate.getTime());
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.change(day);
this.emit('selection', {
$days: [day],
$type: 'day'
});
this.repaint();
}
/**
/*
* WeekDay selection event
*
* @param {Integer} weekday - weekday index
*/
selectAll(weekday) {
if (this.disabled) return;
selectWeekDay(weekday) {
if (!this.editable) return;
let days = [];
for (let i in this.days) {
const day = this.days[i].dated;
if (day.getDay() === weekday && day.getMonth() == this.defaultDate.getMonth())
for (let day of this.days) {
if (day.getDay() === weekday && day.getMonth() == this.month)
days.push(day);
}
this.field = days[0];
this.emit('selection', {
$days: days,
$type: 'weekday',
$weekday: weekday
});
}
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;
this.repaint();
}
hasEvents() {
@ -314,24 +163,31 @@ export default class Calendar extends Component {
getClass() {
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.component('vnCalendar', {
ngModule.vnComponent('vnCalendar', {
template: require('./index.html'),
controller: Calendar,
bindings: {
model: '<',
data: '<?',
defaultDate: '=?',
onSelection: '&?',
onMoveNext: '&?',
onMovePrevious: '&?',
hasEvents: '&?',
getClass: '&?',
formatDay: '&?',
displayControls: '<?',
disabled: '<?',
skip: '<?'
hideYear: '<?',
hideContiguous: '<?'
}
});

View File

@ -2,86 +2,64 @@ describe('Component vnCalendar', () => {
let controller;
let $element;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
let date = new Date();
date.setHours(0, 0, 0, 0);
date.setDate(1);
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-calendar></vn-calendar`)($rootScope);
controller = $element.controller('vnCalendar');
controller.defaultDate = new Date();
controller.defaultDate = date;
}));
afterEach(() => {
$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()', () => {
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');
const currentMonth = controller.defaultDate.getMonth();
let nextMonth = currentMonth + 1;
let nextMonth = new Date(date.getTime());
nextMonth.setMonth(nextMonth.getMonth() + 1);
controller.moveNext(1);
controller.moveNext();
expect(controller.defaultDate.getMonth()).toEqual(nextMonth);
expect(controller.emit).toHaveBeenCalledWith('moveNext');
expect(controller.month).toEqual(nextMonth.getMonth());
expect(controller.emit).toHaveBeenCalledWith('move', {$date: nextMonth});
});
});
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');
const currentMonth = controller.defaultDate.getMonth();
let previousMonth = currentMonth - 1;
let previousMonth = new Date(date.getTime());
previousMonth.setMonth(previousMonth.getMonth() - 1);
controller.movePrevious(1);
controller.movePrevious();
expect(controller.defaultDate.getMonth()).toEqual(previousMonth);
expect(controller.emit).toHaveBeenCalledWith('movePrevious');
expect(controller.month).toEqual(previousMonth.getMonth());
expect(controller.emit).toHaveBeenCalledWith('move', {$date: previousMonth});
});
});
describe('select()', () => {
it(`should return the selected element, then emit a 'selection' event`, () => {
spyOn(controller, 'emit');
const dated = new Date();
const days = [{dated}];
controller.days = days;
controller.select(0);
const day = new Date();
day.setHours(0, 0, 0, 0);
controller.select(day);
let res = {
$days: [dated],
$days: [day],
$type: 'day'
};
expect(controller.field).toEqual(day);
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');
});
});
});

View File

@ -1,103 +1,97 @@
@import "variables";
vn-calendar.small {
.events {
display: none
}
}
vn-calendar {
.vn-calendar {
display: block;
.header vn-one {
text-align: center;
padding: 0.2em 0;
height: 1.5em
}
.weekdays {
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;
& > div {
& > .header {
display: flex;
margin-bottom: 0.5em;
align-items: center;
height: 2.4em;
.event {
margin-bottom: .1em;
& > .title {
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 {
background-color: $color-main;
color: $color-font-bg;
display: inline-block;
border-radius: .3em;
padding: 0.3em .8em;
max-width: 5em;
}
.day.gray {
.day-number {
color: $color-font-secondary
}
}
.day.sunday {
.day-number {
color: $color-alert;
font-weight: bold
&.disabled,
&.readonly {
& > div {
& > .weekdays > section {
cursor: initial;
}
& > .days > .day > .day-number {
cursor: initial;
}
}
}
}

View File

@ -1 +0,0 @@
<div></div>

View File

@ -5,12 +5,11 @@ export default function directive() {
return {
restrict: 'E',
transclude: true,
template: require('./card.html'),
link: function($scope, $element, $attrs, $ctrl, $transclude) {
$element.addClass('demo-card-wide mdl-shadow--2dp bg-panel');
$element[0].classList.add('vn-shadow', 'bg-panel');
$transclude($scope, function(clone) {
angular.element($element[0].querySelector('div')).append(clone);
$element.append(clone);
});
}
};

View File

@ -1,3 +1,4 @@
vn-card {
display: block;
box-sizing: border-box;
}

View File

@ -49,18 +49,19 @@ export default class Check extends Toggle {
onClick(event) {
if (super.onClick(event)) return;
let value;
if (this.tripleState) {
if (this.field == null)
this.field = true;
value = true;
else if (this.field)
this.field = false;
value = false;
else
this.field = null;
value = null;
} else
this.field = !this.field;
value = !this.field;
this.changed();
this.change(value);
}
}

View File

@ -1,15 +1,13 @@
describe('Component vnCheck', () => {
let $element;
let $ctrl;
let controller;
let element;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-check></vn-check>`)($rootScope);
$ctrl = $element.controller('vnCheck');
controller = $element.controller('vnCheck');
element = $element[0];
}));
@ -19,46 +17,46 @@ describe('Component vnCheck', () => {
describe('field() setter', () => {
it(`should set model value`, () => {
$ctrl.field = true;
controller.field = true;
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should uncheck value and change to true when clicked`, () => {
$ctrl.field = false;
controller.field = false;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
controller.field = true;
element.click();
expect($ctrl.field).toEqual(false);
expect(controller.field).toEqual(false);
});
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
$ctrl.tripleState = true;
controller.field = true;
controller.tripleState = true;
element.click();
expect($ctrl.field).toEqual(false);
expect(controller.field).toEqual(false);
});
it(`should set value to null and change to true when clicked`, () => {
$ctrl.field = null;
$ctrl.tripleState = true;
controller.field = null;
controller.tripleState = true;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should cast value to boolean when clicked`, () => {
$ctrl.field = 0;
controller.field = 0;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
});
});

View File

@ -1,6 +1,6 @@
@import "variables";
vn-check {
.vn-check {
& > .btn {
border-radius: 2px;
transition: background 250ms;
@ -12,8 +12,13 @@ vn-check {
border-width: 0;
}
}
& > vn-icon {
margin-left: 5px;
color: $color-font-secondary;
vertical-align: middle;
}
&.checked > .btn {
border-color: $color-main;
border-color: transparent;
background-color: $color-main;
& > .mark {
@ -35,9 +40,7 @@ vn-check {
height: 2px;
border-bottom: 2px solid #666;
}
& > vn-icon {
margin-left: 5px;
color: $color-font-secondary;
vertical-align: middle;
&.disabled.checked > .btn {
background-color: $color-font-secondary;
}
}

View File

@ -1,8 +1,7 @@
<vn-one>
<span ng-class="{'mdl-chip--deletable': !$ctrl.disabled}" class="mdl-chip">
<span class="mdl-chip__text ellipsize" ng-transclude></span>
<button ng-click="$ctrl.remove()" ng-show="!$ctrl.disabled" type="button" class="mdl-chip__action">
<i class="material-icons">cancel</i>
</button>
</span>
</vn-one>
<div ng-transclude></div>
<vn-icon
ng-click="$ctrl.onRemove()"
ng-if="$ctrl.removable"
icon="cancel"
tabindex="0">
</vn-icon>

View File

@ -1,25 +1,20 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
export default class Chip {
/**
* Remove chip event
*/
remove() {
if (this.onRemove)
this.onRemove();
export default class Chip extends Component {
onRemove() {
if (!this.disabled) this.emit('remove');
}
}
Chip.$inject = ['$element', '$scope', '$transclude'];
ngModule.component('vnChip', {
ngModule.vnComponent('vnChip', {
template: require('./index.html'),
controller: Chip,
transclude: true,
bindings: {
disabled: '<?',
onRemove: '&?'
removable: '<?'
}
});

View File

@ -6,9 +6,7 @@ describe('Component vnChip', () => {
let $scope;
let controller;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($componentController, $rootScope) => {
$scope = $rootScope.$new();
@ -16,13 +14,13 @@ describe('Component vnChip', () => {
controller = $componentController('vnChip', {$element, $scope, $transclude: () => {}});
}));
describe('remove()', () => {
it(`should call onRemove()`, () => {
controller.onRemove = () => {};
spyOn(controller, 'onRemove');
controller.remove();
describe('onRemove()', () => {
it(`should emit remove event`, () => {
controller.emit = () => {};
spyOn(controller, 'emit');
controller.onRemove();
expect(controller.onRemove).toHaveBeenCalledWith();
expect(controller.emit).toHaveBeenCalledWith('remove');
});
});
});

View File

@ -1,18 +1,53 @@
@import "variables";
vn-chip {
border-radius: 16px;
background-color: $color-bg;
margin: 0 0.5em 0.5em 0;
color: $color-font;
font-size: 14px;
margin: .25em;
display: inline-flex;
align-items: center;
text-overflow: ellipsis;
white-space: nowrap;
height: 28px;
padding: 0 .7em;
overflow: hidden;
.mdl-chip {
background-color: rgba($color-main, 0.9);
color: #FFF
&.colored {
background-color: $color-main;
color: $color-font-dark;
}
.mdl-chip:active {
background-color: $color-main
}
& > vn-one > span > span {
& > div {
display: flex;
align-items: center;
max-width: 100%;
height: 100%;
& > vn-avatar {
margin-left: -0.7em;
margin-right: .4em;
}
}
& > vn-icon {
margin-left: .2em;
margin-right: -0.3em;
vertical-align: middle;
opacity: .6;
cursor: pointer;
transition: opacity 250ms ease-out;
&:hover,
&:focus {
opacity: 1;
}
}
}
vn-avatar {
display: inline-block;
height: 28px;
width: 28px;
border-radius: 50%;
}

View File

@ -1,8 +0,0 @@
<span
ng-class="{'pointer': $ctrl.$attrs['onClick']}"
class="mdl-chip mdl-chip--contact"
ng-repeat="legend in $ctrl.data track by $index"
ng-click="$ctrl.onClick(legend)">
<span class="mdl-chip__contact" ng-style="{backgroundColor: legend.color}"></span>
<span class="mdl-chip__text">{{legend.name}}</span>
</span>

View File

@ -1,24 +0,0 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
export default class Controller extends Component {
constructor($element, $scope, $attrs) {
super($element, $scope);
this.$attrs = $attrs;
}
onClick(legend) {
this.emit('click', {legend});
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnColorLegend', {
template: require('./index.html'),
controller: Controller,
bindings: {
data: '<?'
}
});

View File

@ -1,13 +0,0 @@
@import "variables";
.mdl-chip--contact {
margin-left: 5px;
height: 20px;
line-height: 5px;
float: left
}
.mdl-chip--contact .mdl-chip__contact {
height: 20px;
width: 20px
}

View File

@ -1,4 +1,4 @@
<root>
<div>
<tpl-body>
<h6 translate>{{::$ctrl.message}}</h6>
<span translate>{{::$ctrl.question}}</span>
@ -7,4 +7,4 @@
<button response="CANCEL" translate>Cancel</button>
<button response="ACCEPT" translate>Accept</button>
</tpl-buttons>
</root>
</div>

View File

@ -1,24 +1,22 @@
import ngModule from '../../module';
import Dialog from '../dialog/dialog';
import Dialog from '../dialog';
import template from './confirm.html';
export default class Confirm extends Dialog {
constructor($element, $scope, $compile) {
super($element);
let cTemplate = $compile(template)($scope)[0];
this.body = cTemplate.querySelector('tpl-body');
this.buttons = cTemplate.querySelector('tpl-buttons');
constructor($element, $, $transclude) {
super($element, $, $transclude);
let $template = angular.element(template);
this.fillSlot('body', $template.find('tpl-body'));
this.fillSlot('buttons', $template.find('tpl-buttons'));
}
}
Confirm.$inject = ['$element', '$scope', '$compile'];
ngModule.component('vnConfirm', {
template: require('../dialog/dialog.html'),
ngModule.vnComponent('vnConfirm', {
controller: Confirm,
transclude: true,
bindings: {
onOpen: '&?',
onResponse: '&',
question: '@',
message: '@?'
},
controller: Confirm
}
});

View File

@ -95,7 +95,7 @@ export default class CrudModel extends ModelProxy {
*/
addFilter(filter, params) {
this.userFilter = mergeFilters(filter, this.userFilter);
Object.assign(this.userParams, params);
this.userParams = Object.assign({}, this.userParams, params);
return this.refresh();
}

View File

@ -1,15 +1,37 @@
import ngModule from '../../module';
import Field from '../field';
import {Flatpickr} from '../../vendor';
import './style.scss';
class DatePicker extends Field {
constructor($element, $scope, $compile, $translate) {
constructor($element, $scope, $compile) {
super($element, $scope, $compile);
this.$translate = $translate;
this.input = $compile(`<input type="text"></input>`)($scope)[0];
this.initPicker();
this.input = $compile(`<input type="date"></input>`)($scope)[0];
this.input.addEventListener('change', () => this.onValueUpdate());
}
onValueUpdate() {
let date = null;
let value = this.input.value;
if (value) {
date = new Date(value);
if (this.field) {
let orgDate = this.field instanceof Date
? this.field
: new Date(this.field);
date.setHours(
orgDate.getHours(),
orgDate.getMinutes(),
orgDate.getSeconds(),
orgDate.getMilliseconds()
);
}
}
super.field = date;
this.$.$applyAsync();
}
get field() {
@ -18,69 +40,10 @@ class DatePicker extends Field {
set field(value) {
super.field = value;
let date = value;
if (date && !(date instanceof Date))
date = new Date(date);
this.picker.setDate(fixDate(date));
}
set options(value) {
let selectedDates = this.picker.selectedDates || [];
this._options = value;
this.initPicker();
this.picker.setDate(selectedDates[0]);
}
get options() {
return this._options;
}
initPicker() {
let locale = this.$translate.use();
let format = locale == 'es' ? 'd-m-Y' : 'Y-m-d';
let options = this.options || {};
let defaultOptions = {
locale: locale,
dateFormat: format,
enableTime: false,
disableMobile: true,
onValueUpdate: () => this.onValueUpdate()
};
if (options.enableTime) {
Object.assign(defaultOptions, {
dateFormat: `${format} h:i`,
time_24hr: true
});
}
let mergedOptions = Object.assign({},
defaultOptions,
options
);
if (this.picker) this.picker.destroy();
this.picker = new Flatpickr(this.input, mergedOptions);
}
onValueUpdate() {
let date = null;
if (this.picker.selectedDates.length)
date = this.picker.selectedDates[0];
super.field = fixDate(date, -1);
this.$.$applyAsync();
}
$onDestroy() {
this.picker.destroy();
this.input.value = this.$filter('date')(value, 'yyyy-MM-dd');
}
}
DatePicker.$inject = ['$element', '$scope', '$compile', '$translate'];
DatePicker.$inject = ['$element', '$scope', '$compile'];
ngModule.vnComponent('vnDatePicker', {
controller: DatePicker,
@ -88,12 +51,3 @@ ngModule.vnComponent('vnDatePicker', {
options: '<?'
}
});
function fixDate(date, mult = 1) {
if (date) {
let offset = date.getTimezoneOffset() * 60000;
date.setTime(date.getTime() + (offset * mult));
}
return date;
}

View File

@ -2,20 +2,14 @@ describe('Component vnDatePicker', () => {
let $filter;
let $element;
let $ctrl;
let today;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($compile, $rootScope, _$filter_) => {
$filter = _$filter_;
$element = $compile(`<vn-date-picker></vn-date-picker>`)($rootScope);
$ctrl = $element.controller('vnDatePicker');
today = new Date();
today.setUTCHours(0, 0, 0, 0);
}));
afterEach(() => {
@ -24,20 +18,12 @@ describe('Component vnDatePicker', () => {
describe('field() setter', () => {
it(`should display the formated the date`, () => {
let today;
today = new Date();
today.setHours(0, 0, 0, 0);
$ctrl.field = today;
let displayed = $filter('dateTime')(today, 'yyyy-MM-dd');
expect($ctrl.value).toEqual(displayed);
});
});
describe('options() setter', () => {
it(`should display the date with the new format`, () => {
$ctrl.options = {dateFormat: 'Y-m'};
$ctrl.field = today;
let displayed = $filter('dateTime')(today, 'yyyy-MM');
let displayed = $filter('date')(today, 'yyyy-MM-dd');
expect($ctrl.value).toEqual(displayed);
});

View File

@ -1,7 +0,0 @@
@import "variables";
.flatpickr-months .flatpickr-month,
.flatpickr-weekdays,
span.flatpickr-weekday {
background-color: $color-main;
}

View File

@ -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>

View File

@ -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
});

View File

@ -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;
}
}
}
}
}

View File

@ -1,17 +0,0 @@
<div ng-mousedown="$ctrl.onDialogMouseDown($event)">
<button
class="close"
ng-click="$ctrl.hide()"
translate-attr="{title: 'Close'}">
<vn-icon icon="clear"></vn-icon>
</button>
<form>
<div
class="body">
</div>
<div
class="buttons"
ng-click="$ctrl.onButtonClick($event)">
</div>
</form>
</div>

View File

@ -1,126 +0,0 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
/**
* Dialog component.
*
* @property {HTMLElement} body The dialog HTML body
* @property {HTMLElement} buttons The dialog HTML buttons
*/
export default class Dialog extends Component {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.shown = false;
this.$element.addClass('vn-dialog');
this.element.addEventListener('mousedown',
e => this.onBackgroundMouseDown(e));
if ($transclude) {
$transclude($scope.$parent, tClone => {
this.body = tClone[0];
}, null, 'body');
$transclude($scope.$parent, tClone => {
this.buttons = tClone[0];
}, null, 'buttons');
}
}
set body(value) {
this.element.querySelector('.body').appendChild(value);
}
set buttons(value) {
this.element.querySelector('.buttons').appendChild(value);
}
/**
* Displays the dialog to the user.
*/
show() {
if (this.shown) return;
this.shown = true;
this.keyDownHandler = e => this.onkeyDown(e);
this.document.addEventListener('keydown', this.keyDownHandler);
this.element.style.display = 'flex';
this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
this.emit('open');
}
/**
* Hides the dialog calling the response handler.
*/
hide() {
this.fireResponse();
this.realHide();
this.emit('close');
}
/**
* Calls the response handler.
*
* @param {String} response The response code
* @return {Boolean} %true if response was canceled, %false otherwise
*/
fireResponse(response) {
let cancel = false;
if (this.onResponse)
cancel = this.onResponse({response: response});
return cancel;
}
realHide() {
if (!this.shown) return;
this.element.style.display = 'none';
this.document.removeEventListener('keydown', this.keyDownHandler);
this.lastEvent = null;
this.shown = false;
this.transitionTimeout = setTimeout(() => this.$element.removeClass('shown'), 30);
}
onButtonClick(event) {
let buttons = this.element.querySelector('.buttons');
let tplButtons = buttons.querySelector('tpl-buttons');
let node = event.target;
while (node.parentNode != tplButtons) {
if (node == buttons) return;
node = node.parentNode;
}
let response = node.getAttribute('response');
let cancel = this.fireResponse(response);
if (cancel !== false) this.realHide();
}
onDialogMouseDown(event) {
this.lastEvent = event;
}
onBackgroundMouseDown(event) {
if (event != this.lastEvent)
this.hide();
}
onkeyDown(event) {
if (event.keyCode == 27) // Esc
this.hide();
}
$onDestroy() {
clearTimeout(this.transitionTimeout);
}
}
Dialog.$inject = ['$element', '$scope', '$transclude'];
ngModule.component('vnDialog', {
template: require('./dialog.html'),
transclude: {
body: 'tplBody',
buttons: '?tplButtons'
},
bindings: {
onResponse: '&?'
},
controller: Dialog
});

View File

@ -1,75 +0,0 @@
describe('Component vnDialog', () => {
let $element;
let controller;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(angular.mock.inject($componentController => {
$element = angular.element('<vn-dialog></vn-dialog>');
controller = $componentController('vnDialog', {$element, $transclude: null});
controller.emit = jasmine.createSpy('emit');
}));
describe('show()', () => {
it(`should do nothing if controller.shown is defined`, () => {
controller.element = {style: {display: 'none'}};
controller.shown = true;
controller.show();
expect(controller.element.style.display).toEqual('none');
expect(controller.emit).not.toHaveBeenCalledWith('open');
});
it(`should set shown on the controller, set style.display on the element and emit onOpen() event`, () => {
controller.show();
expect(controller.element.style.display).toEqual('flex');
expect(controller.shown).toBeTruthy();
expect(controller.emit).toHaveBeenCalledWith('open');
});
});
describe('hide()', () => {
describe('fireResponse()', () => {
it(`should call onResponse() if it's defined in the controller`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
controller.hide();
expect(controller.onResponse).toHaveBeenCalledWith(jasmine.any(Object));
});
it(`should call onResponse() with a response`, () => {
let responseRes;
controller.onResponse = response => {
responseRes = response;
return false;
};
let responseRet = controller.fireResponse('answer');
expect(responseRes).toEqual({response: 'answer'});
expect(responseRet).toEqual(false);
});
});
describe('realHide()', () => {
it(`should do nothing if controller.shown is not defined`, () => {
controller.element = {style: {display: 'not none'}};
controller.hide();
expect(controller.element.style.display).toEqual('not none');
});
it(`should set lastEvent, shown and element.style.display to their expected values`, () => {
controller.shown = true;
controller.hide();
expect(controller.lastEvent).toBeFalsy();
expect(controller.shown).toBeFalsy();
expect(controller.element.style.display).toEqual('none');
});
});
});
});

View File

@ -0,0 +1,17 @@
<vn-button
ng-click="$ctrl.hide()"
translate-attr="{title: 'Close'}"
icon="clear"
class="flat close">
</vn-button>
<form>
<div
class="body"
ng-transclude="body">
</div>
<div
class="buttons"
ng-click="$ctrl.onButtonClick($event)"
ng-transclude="buttons">
</div>
</form>

View File

@ -0,0 +1,71 @@
import ngModule from '../../module';
import Popup from '../popup';
import template from './index.html';
import './style.scss';
/**
* Dialog component.
*
* @property {HTMLElement} body The dialog HTML body
* @property {HTMLElement} buttons The dialog HTML buttons
*/
export default class Dialog extends Popup {
constructor($element, $, $transclude) {
super($element, $, $transclude);
this.fillDefaultSlot(template);
}
/**
* Hides the dialog calling the response handler.
*/
hide() {
this.fireResponse();
super.hide();
}
/**
* Calls the response handler.
*
* @param {String} response The response code
* @return {Boolean} %true if response was canceled, %false otherwise
*/
fireResponse(response) {
let cancel;
if (this.onResponse)
cancel = this.onResponse({response: response});
return cancel;
}
onButtonClick(event) {
let buttons = this.popup.querySelector('.buttons');
let tplButtons = buttons.querySelector('tpl-buttons');
let node = event.target;
while (node.parentNode != tplButtons) {
if (node == buttons) return;
node = node.parentNode;
}
let response = node.getAttribute('response');
let cancel = this.fireResponse(response);
let close = res => {
if (res !== false) super.hide();
};
if (cancel instanceof Object && cancel.then)
cancel.then(close);
else
close(cancel);
}
}
ngModule.vnComponent('vnDialog', {
controller: Dialog,
transclude: {
body: 'tplBody',
buttons: '?tplButtons'
},
bindings: {
onResponse: '&?'
}
});

View File

@ -0,0 +1,36 @@
describe('Component vnDialog', () => {
let $element;
let controller;
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($rootScope, $compile) => {
$element = $compile('<vn-dialog><tpl-body>Body</tpl-body></vn-dialog>')($rootScope);
controller = $element.controller('vnDialog');
controller.emit = jasmine.createSpy('emit');
}));
describe('hide()', () => {
describe('fireResponse()', () => {
it(`should call onResponse() if it's defined in the controller`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
controller.hide();
expect(controller.onResponse).toHaveBeenCalledWith(jasmine.any(Object));
});
it(`should call onResponse() with a response`, () => {
let responseRes;
controller.onResponse = response => {
responseRes = response;
return false;
};
let responseRet = controller.fireResponse('answer');
expect(responseRes).toEqual({response: 'answer'});
expect(responseRet).toEqual(false);
});
});
});
});

View File

@ -1,55 +1,27 @@
@import "effects";
.vn-dialog {
display: none;
justify-content: center;
align-items: center;
z-index: 20;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, .6);
opacity: 0;
transition: opacity 300ms ease-in-out;
padding: 3em;
box-sizing: border-box;
.vn-dialog > .window {
padding: $spacing-lg;
&.shown {
opacity: 1;
& > .close {
@extend %clickable;
text-transform: uppercase;
background-color: transparent;
border: none;
border-radius: .1em;
position: absolute;
top: 0;
right: 0;
padding: .3em;
color: #666;
}
& > div {
position: relative;
box-shadow: 0 0 .4em $color-shadow;
background-color: $color-bg-panel;
border-radius: .2em;
overflow: auto;
padding: 2em;
box-sizing: border-box;
max-height: 100%;
tpl-body {
& > form {
& > .body > tpl-body {
display: block;
min-width: 20em;
min-width: 16em;
}
& > button.close {
@extend %clickable;
text-transform: uppercase;
background-color: transparent;
border: none;
border-radius: .1em;
position: absolute;
top: 0;
right: 0;
padding: .3em;
& > vn-icon {
display: block;
color: #666;
}
}
& > form > .buttons {
& > .buttons > tpl-buttons {
display: block;
margin-top: 1.5em;
text-align: right;

View File

@ -1,30 +0,0 @@
<vn-popover
vn-id="popover"
on-open="$ctrl.onOpen()"
on-close="$ctrl.onClose()">
<div class="vn-drop-down">
<div ng-show="$ctrl.showFilter" class="filter">
<vn-textfield
vn-id="input"
ng-model="$ctrl.search"
class="dense search"
ng-blur="$ctrl.onFocusOut()"
placeholder="{{::'Search' | translate}}">
</vn-textfield>
</div>
<div vn-id="list" class="list" tabindex="-1">
<ul
vn-id="ul"
class="dropdown"
ng-click="$ctrl.onContainerClick($event)">
</ul>
<div
ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div>
</div>
</div>
</vn-popover>

View File

@ -0,0 +1,21 @@
<div ng-show="$ctrl.showFilter" class="filter">
<vn-textfield
ng-model="$ctrl.search"
class="dense search"
ng-blur="$ctrl.onFocusOut()"
placeholder="{{::'Search' | translate}}">
</vn-textfield>
</div>
<div class="list" tabindex="-1">
<ul
class="dropdown"
ng-click="$ctrl.onContainerClick($event)">
</ul>
<div
ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div>
</div>

View File

@ -1,6 +1,7 @@
import './style.scss';
import ngModule from '../../module';
import Component from '../../lib/component';
import Popover from '../popover';
import template from './index.html';
import ArrayModel from '../array-model/array-model';
import CrudModel from '../crud-model/crud-model';
import {mergeWhere} from 'vn-loopback/util/filter';
@ -9,37 +10,17 @@ import {mergeWhere} from 'vn-loopback/util/filter';
* @event select Thrown when model item is selected
* @event change Thrown when model data is ready
*/
export default class DropDown extends Component {
constructor($element, $scope, $transclude, $timeout, $translate, $http, $q, $filter) {
super($element, $scope);
this.$transclude = $transclude;
this.$timeout = $timeout;
this.$translate = $translate;
this.$http = $http;
this.$q = $q;
this.$filter = $filter;
export default class DropDown extends Popover {
constructor($element, $, $transclude) {
super($element, $, $transclude);
this.valueField = 'id';
this.showField = 'name';
this._search = undefined;
this._activeOption = -1;
this.showLoadMore = true;
this.showFilter = true;
this.docKeyDownHandler = e => this.onDocKeyDown(e);
}
$postLink() {
super.$postLink();
this.$.list.addEventListener('scroll', e => this.onScroll(e));
}
get shown() {
return this.$.popover && this.$.popover.shown;
}
set shown(value) {
this.$.popover.shown = value;
this.searchDelay = 300;
this.fillDefaultSlot(template);
}
get search() {
@ -67,7 +48,7 @@ export default class DropDown extends Component {
this.searchTimeout = this.$timeout(() => {
this.refreshModel();
this.searchTimeout = null;
}, 350);
}, value != null ? this.searchDelay : 0);
} else
this.refreshModel();
}
@ -106,16 +87,37 @@ export default class DropDown extends Component {
*/
show(parent, search) {
this._activeOption = -1;
this.$.popover.show(parent || this.parent);
super.show(parent);
this.list = this.popup.querySelector('.list');
this.ul = this.popup.querySelector('ul');
this.docKeyDownHandler = e => this.onDocKeyDown(e);
this.document.addEventListener('keydown', this.docKeyDownHandler);
this.listScrollHandler = e => this.onScroll(e);
this.list.addEventListener('scroll', this.listScrollHandler);
this.list.scrollTop = 0;
this.search = search;
this.buildList();
let input = this.popup.querySelector('input');
setTimeout(() => input.focus());
}
/**
* Hides the drop-down.
*/
hide() {
this.$.popover.hide();
onClose() {
this.document.removeEventListener('keydown', this.docKeyDownHandler);
this.docKeyDownHandler = null;
this.list.removeEventListener('scroll', this.listScrollHandler);
this.listScrollHandler = null;
this.list = null;
this.ul = null;
this.destroyList();
super.onClose();
}
/**
@ -126,7 +128,7 @@ export default class DropDown extends Component {
moveToOption(option) {
this.activateOption(option);
let list = this.$.list;
let list = this.list;
let li = this.activeLi;
if (!li) return;
@ -153,7 +155,7 @@ export default class DropDown extends Component {
let data = this.modelData;
if (option >= 0 && data && option < data.length) {
this.activeLi = this.$.ul.children[option];
this.activeLi = this.ul.children[option];
this.activeLi.className = 'active';
}
}
@ -187,19 +189,7 @@ export default class DropDown extends Component {
}
if (!this.multiple)
this.$.popover.hide();
}
onOpen() {
this.document.addEventListener('keydown', this.docKeyDownHandler);
this.$.list.scrollTop = 0;
this.$.input.focus();
this.emit('open');
}
onClose() {
this.document.removeEventListener('keydown', this.docKeyDownHandler);
this.emit('close');
this.hide();
}
onClearClick() {
@ -207,7 +197,7 @@ export default class DropDown extends Component {
}
onScroll() {
let list = this.$.list;
let list = this.list;
let shouldLoad =
list.scrollTop + list.clientHeight >= (list.scrollHeight - 40)
&& !this.model.isLoading;
@ -218,17 +208,13 @@ export default class DropDown extends Component {
onLoadMoreClick(event) {
if (event.defaultPrevented) return;
event.preventDefault();
this.model.loadMore();
}
onContainerClick(event) {
if (event.defaultPrevented) return;
let index = getPosition(this.$.ul, event);
if (index != -1) {
event.preventDefault();
this.selectOption(index);
}
let index = getPosition(this.ul, event);
if (index != -1) this.selectOption(index);
}
onDocKeyDown(event) {
@ -238,23 +224,23 @@ export default class DropDown extends Component {
let option = this.activeOption;
let nOpts = data ? data.length - 1 : 0;
switch (event.keyCode) {
case 9: // Tab
switch (event.key) {
case 'Tab':
this.selectOption(option);
return;
case 13: // Enter
case 'Enter':
this.selectOption(option);
break;
case 38: // Up
case 'ArrowUp':
this.moveToOption(option <= 0 ? nOpts : option - 1);
break;
case 40: // Down
case 'ArrowDown':
this.moveToOption(option >= nOpts ? 0 : option + 1);
break;
case 35: // End
case 'End':
this.moveToOption(nOpts);
break;
case 36: // Start
case 'Home':
this.moveToOption(0);
break;
default:
@ -311,13 +297,14 @@ export default class DropDown extends Component {
}
}
this.$.ul.appendChild(fragment);
this.ul.appendChild(fragment);
this.activateOption(this._activeOption);
this.$.$applyAsync(() => this.$.popover.relocate());
this.$.$applyAsync(() => this.relocate());
}
destroyList() {
this.$.ul.innerHTML = '';
if (this.ul)
this.ul.innerHTML = '';
if (this.scopes) {
for (let scope of this.scopes)
@ -340,10 +327,6 @@ export default class DropDown extends Component {
return fields;
}
$onDestroy() {
this.destroyList();
}
// Model related code
onDataChange() {
@ -432,7 +415,6 @@ export default class DropDown extends Component {
return {[this.showField]: scope.$search};
}
}
DropDown.$inject = ['$element', '$scope', '$transclude', '$timeout', '$translate', '$http', '$q', '$filter'];
/**
* Gets the position of an event element relative to a parent.
@ -459,9 +441,11 @@ function getPosition(parent, event) {
return -1;
}
ngModule.component('vnDropDown', {
template: require('./drop-down.html'),
ngModule.vnComponent('vnDropDown', {
controller: DropDown,
transclude: {
tplItem: '?tplItem'
},
bindings: {
field: '=?',
selection: '=?',
@ -478,9 +462,7 @@ ngModule.component('vnDropDown', {
where: '<?',
order: '@?',
limit: '<?',
searchFunction: '&?'
},
transclude: {
tplItem: '?tplItem'
searchFunction: '&?',
searchDelay: '<?'
}
});

View File

@ -2,9 +2,7 @@ describe('Component vnDropDown', () => {
let $element;
let controller;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope, $document) => {
$element = $compile(`<vn-drop-down></vn-drop-down>`)($rootScope);

View File

@ -1,7 +1,7 @@
@import "effects";
@import "variables";
.vn-drop-down {
.vn-drop-down > .window > .content {
display: flex;
flex-direction: column;
height: inherit;

View File

@ -19,7 +19,7 @@
ng-click="$ctrl.onClear($event)">
</vn-icon>
<vn-icon
ng-if="::$ctrl.info"
ng-if="::$ctrl.info != null"
icon="info_outline"
vn-tooltip="{{::$ctrl.info}}">
</vn-icon>

View File

@ -3,16 +3,13 @@ import FormInput from '../form-input';
import './style.scss';
export default class Field extends FormInput {
constructor($element, $scope, $compile) {
constructor($element, $scope) {
super($element, $scope);
this.$compile = $compile;
this.prefix = null;
this.suffix = null;
this.control = this.element.querySelector('.control');
this.classList = this.element.classList;
this.classList.add('vn-field');
this.element.addEventListener('click', e => this.onClick(e));
this.container = this.element.querySelector('.container');
@ -26,9 +23,7 @@ export default class Field extends FormInput {
this.input.addEventListener('focus', () => this.onFocus(true));
this.input.addEventListener('blur', () => this.onFocus(false));
this.input.addEventListener('change', e => {
this.emit('change', {event: e});
});
this.input.addEventListener('change', () => this.onChange());
}
set field(value) {
@ -43,9 +38,11 @@ export default class Field extends FormInput {
}
set input(value) {
if (this.input) this.control.removeChild(this.input);
if (this.input)
this.control.removeChild(this.input);
this._input = value;
this.control.appendChild(value);
if (value)
this.control.appendChild(value);
}
get input() {
@ -84,36 +81,8 @@ export default class Field extends FormInput {
return this.input.placeholder;
}
set tabIndex(value) {
this.input.tabIndex = value;
}
get tabIndex() {
return this.input.tabIndex;
}
set disabled(value) {
this._disabled = boolTag(value);
this.input.disabled = this._disabled;
this.classList.toggle('disabled', this._disabled);
}
get disabled() {
return this._disabled;
}
set readonly(value) {
this._readonly = boolTag(value);
this.input.readOnly = this._readonly;
this.classList.toggle('readonly', this._readonly);
}
get readonly() {
return this._readonly;
}
set required(value) {
this._required = boolTag(value);
this._required = value;
let required = this.element.querySelector('.required');
display(required, this._required);
}
@ -181,8 +150,7 @@ export default class Field extends FormInput {
}
onClick() {
if (event.defaultPrevented) return;
event.preventDefault();
// if (event.defaultPrevented) return;
if (this.input !== document.activeElement)
this.focus();
@ -205,14 +173,6 @@ export default class Field extends FormInput {
this.input.dispatchEvent(new Event('change'));
}
focus() {
this.input.focus();
}
select() {
this.input.select();
}
buildInput(type) {
let template = `<input type="${type}" ng-model="$ctrl.field"></input>`;
this.input = this.$compile(template)(this.$)[0];
@ -230,8 +190,12 @@ export default class Field extends FormInput {
this.inputError = error;
this.refreshHint();
}
onChange() {
this.emit('change', {value: this.field});
}
}
Field.$inject = ['$element', '$scope', '$compile'];
Field.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnField', {
template: require('./index.html'),
@ -250,15 +214,10 @@ ngModule.vnComponent('vnField', {
suffix: '@?',
hint: '@?',
error: '<?',
tabIndex: '<?',
rule: '@?'
}
});
function boolTag(value) {
return Boolean(value || value === '');
}
function display(element, display) {
element.style.display = display ? 'initial' : 'none';
}

Some files were not shown because too many files have changed in this diff Show More