Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4077-login_recover-password
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
cc57742766
|
@ -1,6 +1,6 @@
|
|||
FROM mariadb:10.7.5
|
||||
FROM mariadb:10.7.3
|
||||
|
||||
ENV MARIADB_ROOT_PASSWORD root
|
||||
ENV MYSQL_ROOT_PASSWORD root
|
||||
ENV TZ Europe/Madrid
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
@ -22,7 +22,6 @@ COPY \
|
|||
docker/docker-start.sh \
|
||||
/usr/local/bin/
|
||||
|
||||
RUN chmod 775 /etc/mysql/conf.d/docker.cnf
|
||||
RUN mkdir /mysql-data \
|
||||
&& chown -R mysql:mysql /mysql-data
|
||||
|
||||
|
@ -36,8 +35,6 @@ COPY \
|
|||
dump/structure.sql \
|
||||
dump/dumpedFixtures.sql \
|
||||
./
|
||||
|
||||
RUN chmod 775 config.ini
|
||||
RUN gosu mysql docker-init.sh \
|
||||
&& docker-dump.sh mysqlPlugins \
|
||||
&& docker-dump.sh mockDate \
|
||||
|
|
|
@ -1014,9 +1014,9 @@ export default {
|
|||
save: 'vn-travel-create vn-submit > button'
|
||||
},
|
||||
travelExtraCommunity: {
|
||||
anySearchResult: 'vn-travel-extra-community > vn-data-viewer div > vn-tbody > vn-tr',
|
||||
firstTravelReference: 'vn-travel-extra-community vn-tbody:nth-child(2) vn-td-editable[name="reference"]',
|
||||
firstTravelLockedKg: 'vn-travel-extra-community vn-tbody:nth-child(2) vn-td-editable[name="lockedKg"]',
|
||||
anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]',
|
||||
firstTravelReference: 'vn-travel-extra-community tbody:nth-child(2) vn-textfield[ng-model="travel.ref"]',
|
||||
firstTravelLockedKg: 'vn-travel-extra-community tbody:nth-child(2) vn-input-number[ng-model="travel.kg"]',
|
||||
removeContinentFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(3) > vn-icon > i'
|
||||
},
|
||||
travelBasicData: {
|
||||
|
|
|
@ -19,18 +19,22 @@ describe('Travel extra community path', () => {
|
|||
it('should edit the travel reference and the locked kilograms', async() => {
|
||||
await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter);
|
||||
await page.waitForSpinnerLoad();
|
||||
await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelReference, 'edited reference');
|
||||
await page.waitForSpinnerLoad();
|
||||
await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelLockedKg, '1500');
|
||||
await page.clearInput(selectors.travelExtraCommunity.firstTravelReference);
|
||||
await page.write(selectors.travelExtraCommunity.firstTravelReference, 'edited reference');
|
||||
await page.clearInput(selectors.travelExtraCommunity.firstTravelLockedKg);
|
||||
await page.write(selectors.travelExtraCommunity.firstTravelLockedKg, '1500');
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
});
|
||||
|
||||
it('should reload the index and confirm the reference and locked kg were edited', async() => {
|
||||
await page.accessToSection('travel.index');
|
||||
await page.accessToSection('travel.extraCommunity');
|
||||
await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter);
|
||||
await page.waitForTextInElement(selectors.travelExtraCommunity.firstTravelReference, 'edited reference');
|
||||
const reference = await page.getProperty(selectors.travelExtraCommunity.firstTravelReference, 'innerText');
|
||||
const lockedKg = await page.getProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'innerText');
|
||||
|
||||
const reference = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelReference, 'value');
|
||||
const lockedKg = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'value');
|
||||
|
||||
expect(reference).toContain('edited reference');
|
||||
expect(lockedKg).toContain(1500);
|
||||
|
|
|
@ -30,11 +30,24 @@ module.exports = Self => {
|
|||
sum(ws.saleWaste) AS dwindle
|
||||
FROM bs.waste ws
|
||||
WHERE year = YEAR(TIMESTAMPADD(WEEK,-1, ?))
|
||||
AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1)
|
||||
AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1)
|
||||
GROUP BY buyer, family
|
||||
) sub
|
||||
ORDER BY percentage DESC`, [date, date], myOptions);
|
||||
|
||||
const wastesTotal = await Self.rawSql(`
|
||||
SELECT *, 100 * dwindle / total AS percentage
|
||||
FROM (
|
||||
SELECT buyer,
|
||||
sum(ws.saleTotal) AS total,
|
||||
sum(ws.saleWaste) AS dwindle
|
||||
FROM bs.waste ws
|
||||
WHERE year = YEAR(TIMESTAMPADD(WEEK,-1, ?))
|
||||
AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1)
|
||||
GROUP BY buyer
|
||||
) sub
|
||||
ORDER BY percentage DESC`, [date, date], myOptions);
|
||||
|
||||
const details = [];
|
||||
|
||||
for (let waste of wastes) {
|
||||
|
@ -55,6 +68,14 @@ module.exports = Self => {
|
|||
buyerDetail.lines.push(waste);
|
||||
}
|
||||
|
||||
for (let waste of details) {
|
||||
let buyerTotal = wastesTotal.find(totals => {
|
||||
return waste.buyer == totals.buyer;
|
||||
});
|
||||
|
||||
Object.assign(waste, buyerTotal);
|
||||
}
|
||||
|
||||
return details;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ describe('Item getWasteByWorker()', () => {
|
|||
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
|
||||
|
||||
expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/);
|
||||
expect(anyResult.total).toBeGreaterThanOrEqual(1000);
|
||||
expect(anyResult.lines.length).toBeGreaterThanOrEqual(3);
|
||||
|
||||
await tx.rollback();
|
||||
|
|
|
@ -4,39 +4,46 @@
|
|||
data="details">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer model="model">
|
||||
<section ng-repeat="detail in details" class="vn-pa-md">
|
||||
<vn-horizontal class="header">
|
||||
<h5><span translate>{{detail.buyer}}</span></h5>
|
||||
<vn-none>
|
||||
<vn-icon
|
||||
ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}"
|
||||
class="arrow pointer"
|
||||
icon="keyboard_arrow_up"
|
||||
vn-tooltip="Minimize/Maximize"
|
||||
ng-click="$ctrl.toggleHidePanel(detail)">
|
||||
</vn-icon>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<vn-card ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}">
|
||||
<vn-table>
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th class="waste-family">Family</vn-th>
|
||||
<vn-th number>Percentage</vn-th>
|
||||
<vn-th number>Dwindle</vn-th>
|
||||
<vn-th number>Total</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a ng-repeat="waste in detail.lines" class="clickable vn-tr"
|
||||
ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})">
|
||||
<vn-td class="waste-family">{{::waste.family}}</vn-td>
|
||||
<vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
|
||||
<vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
|
||||
<vn-td number>{{::waste.total | currency: 'EUR'}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</section>
|
||||
</vn-data-viewer>
|
||||
<vn-card>
|
||||
<vn-table>
|
||||
<vn-thead>
|
||||
<vn-tr class="header">
|
||||
<vn-th class="waste-family">Buyer</vn-th>
|
||||
<vn-th class="waste-family">Family</vn-th>
|
||||
<vn-th number>Percentage</vn-th>
|
||||
<vn-th number>Dwindle</vn-th>
|
||||
<vn-th number>Total</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody ng-repeat="detail in details" class="vn-mb-md">
|
||||
<vn-tr class="header">
|
||||
<vn-td>{{::detail.buyer}}</vn-td>
|
||||
<vn-td>{{::detail.family}}</vn-td>
|
||||
<vn-td number>{{::(detail.percentage / 100) | percentage: 2}}</vn-td>
|
||||
<vn-td number>{{::detail.dwindle | currency: 'EUR'}}</vn-td>
|
||||
<vn-td number>{{::detail.total | currency: 'EUR'}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}"
|
||||
class="arrow pointer"
|
||||
icon="keyboard_arrow_up"
|
||||
vn-tooltip="Minimize/Maximize"
|
||||
ng-click="$ctrl.toggleHidePanel(detail)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
<vn-tr ng-repeat="waste in detail.lines" class="clickable vn-tr"
|
||||
ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})"
|
||||
ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}">
|
||||
<vn-td></vn-td>
|
||||
<vn-td>{{::waste.family}}</vn-td>
|
||||
<vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
|
||||
<vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
|
||||
<vn-td number>{{::waste.total | currency: 'EUR'}}</vn-td>
|
||||
<vn-td shrink></vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
|
|
|
@ -5,20 +5,9 @@ vn-item-waste-index,
|
|||
vn-item-waste-detail {
|
||||
.header {
|
||||
padding: 12px 0 5px 0;
|
||||
color: gray;
|
||||
background-color: $color-bg;
|
||||
font-size: 1.2rem;
|
||||
border-bottom: $border;
|
||||
margin-bottom: 10px;
|
||||
|
||||
& > vn-none > vn-icon {
|
||||
@extend %clickable-light;
|
||||
color: $color-button;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
vn-none > .arrow {
|
||||
transition: transform 200ms;
|
||||
}
|
||||
}
|
||||
|
||||
vn-table vn-th.waste-family,
|
||||
|
@ -26,12 +15,13 @@ vn-item-waste-detail {
|
|||
max-width: 64px;
|
||||
width: 64px
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
|
||||
}
|
||||
.header > vn-none > .arrow.hidden {
|
||||
|
||||
.arrow.hidden {
|
||||
display: block;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,10 @@
|
|||
},
|
||||
"scope": {
|
||||
"where": {
|
||||
"isActive": true
|
||||
}
|
||||
"isActive": {
|
||||
"neq": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
|
|
|
@ -128,7 +128,7 @@ module.exports = Self => {
|
|||
w.name AS warehouseInFk,
|
||||
w.name AS warehouseInName,
|
||||
SUM(b.stickers) AS stickers,
|
||||
s.id AS supplierFk,
|
||||
s.id AS cargoSupplierFk,
|
||||
s.nickname AS cargoSupplierNickname,
|
||||
CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg,
|
||||
CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg
|
||||
|
@ -160,13 +160,14 @@ module.exports = Self => {
|
|||
e.travelFk,
|
||||
e.ref,
|
||||
e.loadPriority,
|
||||
s.id AS supplierFk,
|
||||
s.name AS supplierName,
|
||||
SUM(b.stickers) AS stickers,
|
||||
e.evaNotes,
|
||||
e.notes,
|
||||
CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedkg,
|
||||
CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg
|
||||
FROM tmp.travel tr
|
||||
FROM tmp.travel tr
|
||||
JOIN entry e ON e.travelFk = tr.id
|
||||
JOIN buy b ON b.entryFk = e.id
|
||||
JOIN packaging pkg ON pkg.id = b.packageFk
|
||||
|
|
|
@ -50,15 +50,15 @@
|
|||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
label="Warehouse In"
|
||||
ng-model="filter.warehouseInFk"
|
||||
label="Warehouse Out"
|
||||
ng-model="filter.warehouseOutFk"
|
||||
url="Warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
label="Warehouse Out"
|
||||
ng-model="filter.warehouseOutFk"
|
||||
label="Warehouse In"
|
||||
ng-model="filter.warehouseInFk"
|
||||
url="Warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
|
@ -84,4 +84,4 @@
|
|||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Travels/extraCommunityFilter"
|
||||
filter="::$ctrl.filter"
|
||||
data="travels"
|
||||
order="shipped ASC, landed ASC, travelFk, loadPriority, agencyModeFk, evaNotes"
|
||||
limit="20"
|
||||
|
@ -18,112 +19,174 @@
|
|||
model="model">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-data-viewer model="model" class="travel-list">
|
||||
<vn-card>
|
||||
<section class="vn-pa-md">
|
||||
<vn-tool-bar class="vn-mb-md">
|
||||
<vn-button disabled="!$ctrl.hasDateRange"
|
||||
icon="picture_as_pdf"
|
||||
ng-click="$ctrl.showReport()"
|
||||
vn-tooltip="Open as PDF">
|
||||
</vn-button>
|
||||
</vn-tool-bar>
|
||||
<vn-table>
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th shrink>Id</vn-th>
|
||||
<vn-th expand>Supplier</vn-th>
|
||||
<vn-th expand>Freighter</vn-th>
|
||||
<vn-th>Reference</vn-th>
|
||||
<vn-th number>Packages</vn-th>
|
||||
<vn-th number>Bl. KG</vn-th>
|
||||
<vn-th number>Phy. KG</vn-th>
|
||||
<vn-th number>Vol. KG</vn-th>
|
||||
<vn-th expand translate-attr="{title: 'Warehouse Out'}">
|
||||
Wh. Out
|
||||
</vn-th>
|
||||
<vn-th expand>W. Shipped</vn-th>
|
||||
<vn-th expand translate-attr="{title: 'Warehouse In'}">
|
||||
Wh. In
|
||||
</vn-th>
|
||||
<vn-th expand>W. Landed</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody ng-repeat="travel in travels" class="vn-mb-md" vn-droppable="$ctrl.onDrop($event)" ng-attr-id="{{::travel.id}}">
|
||||
<vn-tr class="header">
|
||||
<vn-td>
|
||||
<span class="link"
|
||||
<vn-card class="travel-list scrollable">
|
||||
<smart-table
|
||||
model="model"
|
||||
options="$ctrl.smartTableOptions">
|
||||
<slot-actions>
|
||||
<section>
|
||||
<vn-tool-bar class="vn-mb-md">
|
||||
<vn-button
|
||||
disabled="!$ctrl.hasDateRange"
|
||||
icon="picture_as_pdf"
|
||||
ng-click="$ctrl.showReport()"
|
||||
vn-tooltip="Open as PDF">
|
||||
</vn-button>
|
||||
</vn-tool-bar>
|
||||
</section>
|
||||
</slot-actions>
|
||||
<slot-table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th field="id" shrink>
|
||||
<span translate>Id</span>
|
||||
</th>
|
||||
<th field="cargoSupplierFk" expand>
|
||||
<span translate>Supplier</span>
|
||||
</th>
|
||||
<th field="agencyModeFk" expand>
|
||||
<span translate>Agency</span>
|
||||
</th>
|
||||
<th field="ref">
|
||||
<span translate>Reference</span>
|
||||
</th>
|
||||
<th field="stickers" number>
|
||||
<span translate>Packages</span>
|
||||
</th>
|
||||
<th field="kg" number>
|
||||
<span translate>Bl. KG</span>
|
||||
</th>
|
||||
<th field="loadedKg" number>
|
||||
<span translate>Phy. KG</span>
|
||||
</th>
|
||||
<th field="volumeKg" number>
|
||||
<span translate>Vol. KG</span>
|
||||
</th>
|
||||
<th
|
||||
field="warehouseOutFk"
|
||||
translate-attr="{title: 'Warehouse Out'}">
|
||||
<span translate>Wh. Out</span>
|
||||
</th>
|
||||
<th field="shipped">
|
||||
<span translate>W. Shipped</span>
|
||||
</th>
|
||||
<th
|
||||
field="warehouseInFk"
|
||||
translate-attr="{title: 'Warehouse In'}">
|
||||
<span translate>Wh. In</span>
|
||||
</th>
|
||||
<th field="landed">
|
||||
<span translate>W. Landed</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
ng-repeat="travel in travels"
|
||||
class="vn-mb-md"
|
||||
vn-droppable="$ctrl.onDrop($event)"
|
||||
ng-attr-id="{{::travel.id}}"
|
||||
vn-stop-click>
|
||||
<tr
|
||||
class="header"
|
||||
vn-anchor="::{
|
||||
state: 'travel.card.basicData',
|
||||
params: {id: travel.id}
|
||||
}">
|
||||
<td vn-click-stop>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="travelDescriptor.show($event, travel.id)">
|
||||
{{::travel.id}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>{{::travel.agencyModeName}}</vn-td>
|
||||
<vn-td expand>{{::travel.cargoSupplierNickname}}</vn-td>
|
||||
<vn-td-editable name="reference" expand>
|
||||
<text>{{travel.ref}}</text>
|
||||
<field>
|
||||
<vn-textfield class="dense" vn-focus
|
||||
ng-model="travel.ref"
|
||||
on-change="$ctrl.save(travel.id, {ref: value})">
|
||||
</vn-textfield>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td number>{{::travel.stickers}}</vn-td>
|
||||
<vn-td-editable name="lockedKg" expand style="text-align: right">
|
||||
<text number>{{travel.kg}}</text>
|
||||
<field>
|
||||
<vn-input-number class="dense" vn-focus
|
||||
ng-model="travel.kg"
|
||||
on-change="$ctrl.save(travel.id, {kg: value})"
|
||||
min="0">
|
||||
</vn-input-number>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td number>{{::travel.loadedKg}}</vn-td>
|
||||
<vn-td number>{{::travel.volumeKg}}</vn-td>
|
||||
<vn-td expand>{{::travel.warehouseOutName}}</vn-td>
|
||||
<vn-td expand>{{::travel.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td expand>{{::travel.warehouseInName}}</vn-td>
|
||||
<vn-td expand>{{::travel.landed | date: 'dd/MM/yyyy'}}</vn-td>
|
||||
</vn-tr>
|
||||
<a href="#" ng-repeat="entry in travel.entries" class="vn-tr" draggable
|
||||
</td>
|
||||
<td expand vn-click-stop>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="supplierDescriptor.show($event, travel.cargoSupplierFk)">
|
||||
{{::travel.cargoSupplierNickname}}
|
||||
</span>
|
||||
</td>
|
||||
<td expand>{{::travel.agencyModeName}}</td>
|
||||
<td
|
||||
name="reference"
|
||||
expand
|
||||
vn-click-stop>
|
||||
<vn-textfield
|
||||
class="dense td-editable"
|
||||
ng-model="travel.ref"
|
||||
on-change="$ctrl.save(travel.id, {ref: value})">
|
||||
</vn-textfield>
|
||||
</vn-icon>
|
||||
</td>
|
||||
<td number>{{::travel.stickers}}</td>
|
||||
<td
|
||||
name="lockedKg"
|
||||
expand
|
||||
vn-click-stop>
|
||||
<vn-input-number
|
||||
number
|
||||
class="td-editable number"
|
||||
ng-model="travel.kg"
|
||||
on-change="$ctrl.save(travel.id, {kg: value})"
|
||||
min="0">
|
||||
</vn-input-number>
|
||||
</td>
|
||||
<td number>{{::travel.loadedKg}}</td>
|
||||
<td number>{{::travel.volumeKg}}</td>
|
||||
<td expand>{{::travel.warehouseOutName}}</td>
|
||||
<td expand>{{::travel.shipped | date: 'dd/MM/yyyy'}}</td>
|
||||
<td expand>{{::travel.warehouseInName}}</td>
|
||||
<td expand>{{::travel.landed | date: 'dd/MM/yyyy'}}</td>
|
||||
</tr>
|
||||
<tr
|
||||
ng-repeat="entry in travel.entries"
|
||||
draggable
|
||||
ng-attr-id="{{::entry.id}}"
|
||||
ng-click="$event.preventDefault()">
|
||||
<vn-td>
|
||||
<td>
|
||||
<span class="link"
|
||||
ng-click="entryDescriptor.show($event, entry.id)">
|
||||
{{::entry.id}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::entry.supplierName}}</vn-td>
|
||||
<vn-td></vn-td>
|
||||
<vn-td expand>{{::entry.ref}}</vn-td>
|
||||
<vn-td number>{{::entry.stickers}}</vn-td>
|
||||
<vn-td number></vn-td>
|
||||
<vn-td number>{{::entry.loadedkg}}</vn-td>
|
||||
<vn-td number>{{::entry.volumeKg}}</vn-td>
|
||||
<vn-td>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="supplierDescriptor.show($event, entry.supplierFk)">
|
||||
{{::entry.supplierName}}
|
||||
</span>
|
||||
</td>
|
||||
<td></td>
|
||||
<td expand>{{::entry.ref}}</td>
|
||||
<td number>{{::entry.stickers}}</td>
|
||||
<td number></td>
|
||||
<td number>{{::entry.loadedkg}}</td>
|
||||
<td number>{{::entry.volumeKg}}</td>
|
||||
<td>
|
||||
<span ng-if="::entry.notes" vn-tooltip="{{::entry.notes}}">
|
||||
{{::entry.notes}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="::entry.evaNotes" vn-tooltip="{{::entry.evaNotes}}">
|
||||
{{::entry.evaNotes}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td></vn-td>
|
||||
<vn-td></vn-td>
|
||||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</section>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</slot-table>
|
||||
</smart-table>
|
||||
</vn-card>
|
||||
<vn-travel-descriptor-popover
|
||||
vn-id="travelDescriptor">
|
||||
</vn-travel-descriptor-popover>
|
||||
<vn-entry-descriptor-popover
|
||||
vn-id="entryDescriptor">
|
||||
</vn-entry-descriptor-popover>
|
||||
|
||||
<vn-supplier-descriptor-popover
|
||||
vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
||||
|
|
|
@ -14,8 +14,15 @@ class Controller extends Section {
|
|||
draggable.addEventListener('dragend',
|
||||
event => this.dragEnd(event));
|
||||
|
||||
this.draggableElement = 'a[draggable]';
|
||||
this.droppableElement = 'vn-tbody[vn-droppable]';
|
||||
draggable.addEventListener('dragover',
|
||||
event => this.dragOver(event));
|
||||
draggable.addEventListener('dragenter',
|
||||
event => this.dragEnter(event));
|
||||
draggable.addEventListener('dragleave',
|
||||
event => this.dragLeave(event));
|
||||
|
||||
this.draggableElement = 'tr[draggable]';
|
||||
this.droppableElement = 'tbody[vn-droppable]';
|
||||
|
||||
const twoDays = 2;
|
||||
const shippedFrom = new Date();
|
||||
|
@ -32,6 +39,8 @@ class Controller extends Section {
|
|||
landedTo: landedTo,
|
||||
continent: 'AM'
|
||||
};
|
||||
|
||||
this.smartTableOptions = {};
|
||||
}
|
||||
|
||||
get hasDateRange() {
|
||||
|
@ -44,6 +53,15 @@ class Controller extends Section {
|
|||
return hasLanded || hasShipped || hasContinent || hasWarehouseOut;
|
||||
}
|
||||
|
||||
onDragInterval() {
|
||||
if (this.dragClientY > 0 && this.dragClientY < 75)
|
||||
this.$window.scrollTo(0, this.$window.scrollY - 10);
|
||||
|
||||
const maxHeight = window.screen.availHeight - (window.outerHeight - window.innerHeight);
|
||||
if (this.dragClientY > maxHeight - 75 && this.dragClientY < maxHeight)
|
||||
this.$window.scrollTo(0, this.$window.scrollY + 10);
|
||||
}
|
||||
|
||||
findDraggable($event) {
|
||||
const target = $event.target;
|
||||
const draggable = target.closest(this.draggableElement);
|
||||
|
@ -65,6 +83,7 @@ class Controller extends Section {
|
|||
const id = parseInt(draggable.id);
|
||||
this.entryId = id;
|
||||
this.entry = draggable;
|
||||
this.interval = setInterval(() => this.onDragInterval(), 50);
|
||||
}
|
||||
|
||||
dragEnd($event) {
|
||||
|
@ -72,6 +91,8 @@ class Controller extends Section {
|
|||
draggable.classList.remove('dragging');
|
||||
this.entryId = null;
|
||||
this.entry = null;
|
||||
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
onDrop($event) {
|
||||
|
@ -91,6 +112,37 @@ class Controller extends Section {
|
|||
}
|
||||
}
|
||||
|
||||
undrop() {
|
||||
if (!this.dropping) return;
|
||||
this.dropping.classList.remove('dropping');
|
||||
this.dropping = null;
|
||||
}
|
||||
|
||||
dragOver($event) {
|
||||
this.dragClientY = $event.clientY;
|
||||
$event.preventDefault();
|
||||
}
|
||||
|
||||
dragEnter($event) {
|
||||
let element = this.findDroppable($event);
|
||||
if (element) this.dropCount++;
|
||||
|
||||
if (element != this.dropping) {
|
||||
this.undrop();
|
||||
if (element) element.classList.add('dropping');
|
||||
this.dropping = element;
|
||||
}
|
||||
}
|
||||
|
||||
dragLeave($event) {
|
||||
let element = this.findDroppable($event);
|
||||
|
||||
if (element) {
|
||||
this.dropCount--;
|
||||
if (this.dropCount == 0) this.undrop();
|
||||
}
|
||||
}
|
||||
|
||||
save(id, data) {
|
||||
const endpoint = `Travels/${id}`;
|
||||
this.$http.patch(endpoint, data)
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('Travel Component vnTravelExtraCommunity', () => {
|
|||
|
||||
describe('findDraggable()', () => {
|
||||
it('should find the draggable element', () => {
|
||||
const draggable = document.createElement('a');
|
||||
const draggable = document.createElement('tr');
|
||||
draggable.setAttribute('draggable', true);
|
||||
|
||||
const $event = new Event('dragstart');
|
||||
|
@ -43,7 +43,7 @@ describe('Travel Component vnTravelExtraCommunity', () => {
|
|||
|
||||
describe('findDroppable()', () => {
|
||||
it('should find the droppable element', () => {
|
||||
const droppable = document.createElement('vn-tbody');
|
||||
const droppable = document.createElement('tbody');
|
||||
droppable.setAttribute('vn-droppable', true);
|
||||
|
||||
const $event = new Event('drop');
|
||||
|
@ -58,9 +58,9 @@ describe('Travel Component vnTravelExtraCommunity', () => {
|
|||
});
|
||||
|
||||
describe('dragStart()', () => {
|
||||
it(`should add the class "dragging" to the draggable element
|
||||
it(`should add the class "dragging" to the draggable element
|
||||
and then set the entryId controller property`, () => {
|
||||
const draggable = document.createElement('a');
|
||||
const draggable = document.createElement('tr');
|
||||
draggable.setAttribute('draggable', true);
|
||||
draggable.setAttribute('id', 3);
|
||||
|
||||
|
@ -78,9 +78,9 @@ describe('Travel Component vnTravelExtraCommunity', () => {
|
|||
});
|
||||
|
||||
describe('dragEnd()', () => {
|
||||
it(`should remove the class "dragging" from the draggable element
|
||||
it(`should remove the class "dragging" from the draggable element
|
||||
and then set the entryId controller property to null`, () => {
|
||||
const draggable = document.createElement('a');
|
||||
const draggable = document.createElement('tr');
|
||||
draggable.setAttribute('draggable', true);
|
||||
draggable.setAttribute('id', 3);
|
||||
draggable.classList.add('dragging');
|
||||
|
@ -100,13 +100,13 @@ describe('Travel Component vnTravelExtraCommunity', () => {
|
|||
|
||||
describe('onDrop()', () => {
|
||||
it('should make an HTTP patch query', () => {
|
||||
const droppable = document.createElement('vn-tbody');
|
||||
const droppable = document.createElement('tbody');
|
||||
droppable.setAttribute('vn-droppable', true);
|
||||
droppable.setAttribute('id', 1);
|
||||
|
||||
jest.spyOn(controller, 'findDroppable').mockReturnValue(droppable);
|
||||
|
||||
const oldDroppable = document.createElement('vn-tbody');
|
||||
const oldDroppable = document.createElement('tbody');
|
||||
oldDroppable.setAttribute('vn-droppable', true);
|
||||
const entry = document.createElement('div');
|
||||
oldDroppable.appendChild(entry);
|
||||
|
|
|
@ -15,41 +15,44 @@ vn-travel-extra-community {
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
vn-td-editable text {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-bottom: 1px dashed $color-active;
|
||||
border-radius: 0;
|
||||
color: $color-active
|
||||
}
|
||||
|
||||
vn-td-editable:hover text:after {
|
||||
font-family: 'Material Icons';
|
||||
content: 'edit';
|
||||
position: absolute;
|
||||
right: -15px;
|
||||
color: $color-spacer
|
||||
}
|
||||
|
||||
vn-table[vn-droppable] {
|
||||
table[vn-droppable] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
a[draggable] {
|
||||
tr[draggable] {
|
||||
transition: all .5s;
|
||||
cursor: move;
|
||||
overflow: auto;
|
||||
outline: 0;
|
||||
height: 65px;
|
||||
pointer-events: fill;
|
||||
user-select:all;
|
||||
}
|
||||
|
||||
a[draggable]:hover {
|
||||
background-color: $color-hover-cd
|
||||
tr[draggable] *::selection{
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a[draggable].dragging {
|
||||
background-color: $color-success-light;
|
||||
font-weight:bold
|
||||
tr[draggable]:hover {
|
||||
background-color: $color-hover-cd;
|
||||
}
|
||||
}
|
||||
|
||||
tr[draggable].dragging {
|
||||
background-color: $color-primary-light;
|
||||
color: $color-font-light;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.td-editable{
|
||||
input{
|
||||
font-size: 1.25rem!important;
|
||||
}
|
||||
}
|
||||
|
||||
.number *{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"name": "ZoneExclusion",
|
||||
"base": "VnModel",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model":"ZoneLog",
|
||||
"relation": "zone"
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "zoneExclusion"
|
||||
|
|
Loading…
Reference in New Issue