Merge branch 'dev' into 2517-clientBalanceCompensaciones
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Javi Gallego 2021-02-01 09:47:00 +01:00
commit 7e95106ff5
34 changed files with 1607 additions and 1356 deletions

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`itemImageQueue`
ADD attempts INT default 0 NULL AFTER error;

View File

@ -3,4 +3,4 @@ host = localhost
port = 3306 port = 3306
user = root user = root
password = root password = root
default-character-set=utf8 default-character-set=utf8

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,25 @@ vn-table {
max-width: 400px; max-width: 400px;
min-width: 0; min-width: 0;
} }
&[vn-fetched-tags] {
width: 235px;
min-width: 155px;
& > vn-one {
overflow: hidden;
text-overflow: ellipsis;
font-size: 0.75rem;
}
& > vn-one:nth-child(2) h3 {
color: $color-font-secondary;
text-transform: uppercase;
line-height: initial;
font-size: 0.75rem
}
}
&[vn-fetched-tags][wide] {
width: 430px;
}
vn-icon.bright, i.bright { vn-icon.bright, i.bright {
color: #f7931e; color: #f7931e;
} }

View File

@ -31,6 +31,9 @@
{"state": "account.alias.card.users", "icon": "groups"} {"state": "account.alias.card.users", "icon": "groups"}
] ]
}, },
"keybindings": [
{"key": "u", "state": "account.index"}
],
"routes": [ "routes": [
{ {
"url": "/account", "url": "/account",

View File

@ -64,12 +64,15 @@
</span> </span>
</vn-td> </vn-td>
<vn-td expand>{{::sale.shipped | date: 'dd/MM/yyyy'}}</vn-td> <vn-td expand>{{::sale.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td expand> <vn-td vn-fetched-tags wide>
<vn-one title="{{::sale.concept}}">{{::sale.concept}}</vn-one>
<vn-one ng-if="::sale.subName">
<h3 title="{{::sale.subName}}">{{::sale.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale" item="::sale"
name="::sale.concept" tabindex="-1">
sub-name="::sale.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.quantity | dashIfEmpty}}</vn-td> <vn-td number>{{::sale.quantity | dashIfEmpty}}</vn-td>

View File

@ -97,12 +97,15 @@
{{::buy.description | dashIfEmpty}} {{::buy.description | dashIfEmpty}}
</vn-td> </vn-td>
<vn-td number>{{::buy.size}}</vn-td> <vn-td number>{{::buy.size}}</vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<vn-one title="{{::buy.name}}">{{::buy.name}}</vn-one>
<vn-one ng-if="::buy.subName">
<h3 title="{{::buy.subName}}">{{::buy.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::buy" item="::buy"
name="::buy.name" tabindex="-1">
sub-name="::buy.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td shrink title="{{::buy.type}}"> <vn-td shrink title="{{::buy.type}}">

View File

@ -16,6 +16,9 @@
{"state": "entry.card.log", "icon": "history"} {"state": "entry.card.log", "icon": "history"}
] ]
}, },
"keybindings": [
{"key": "e", "state": "entry.index"}
],
"routes": [ "routes": [
{ {
"url": "/entry", "url": "/entry",

View File

@ -142,12 +142,12 @@
{{::line.item.minPrice | currency: 'EUR':2}} {{::line.item.minPrice | currency: 'EUR':2}}
</span> </span>
</td> </td>
<td expand colspan="6"> <td vn-fetched-tags colspan="6">
<vn-one title="{{::line.item.name}}">{{::line.item.name}}</vn-one>
<vn-fetched-tags <vn-fetched-tags
expand max-length="6"
item="::line.item" item="::line.item"
name="::line.item.name" tabindex="-1">
sub-name="::line.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</td> </td>
</tr> </tr>

View File

@ -18,39 +18,50 @@ module.exports = Self => {
Self.downloadImages = async() => { Self.downloadImages = async() => {
const models = Self.app.models; const models = Self.app.models;
const container = await models.TempContainer.container('salix-image');
const tempPath = path.join(container.client.root, container.name);
const maxAttempts = 3;
try { const images = await Self.find({
const tempPath = path.join('/tmp/salix-image'); where: {attempts: {eq: maxAttempts}}
});
// Create temporary path for (let image of images) {
await fs.mkdir(tempPath, {recursive: true}); const currentStamp = new Date().getTime();
const updatedStamp = image.updated.getTime();
const graceTime = Math.abs(currentStamp - updatedStamp);
const maxTTL = 3600 * 48 * 1000; // 48 hours in ms;
const timer = setInterval(async() => { if (graceTime >= maxTTL)
const image = await Self.findOne({ await Self.destroyById(image.itemFk);
where: {error: null, url: {neq: null}} }
});
// Exit loop download();
if (!image) return clearInterval(timer);
const srcFile = image.url.split('/').pop(); async function download() {
const fileName = srcFile.split('.')[0]; const image = await Self.findOne({
const file = `${fileName}.png`; where: {url: {neq: null}, attempts: {lt: maxAttempts}},
const filePath = path.join(tempPath, file); order: 'attempts, updated'
});
if (!image) return;
const srcFile = image.url.split('/').pop();
const dotIndex = srcFile.lastIndexOf('.');
const fileName = srcFile.substring(0, dotIndex);
const file = `${fileName}.png`;
const filePath = path.join(tempPath, file);
https.get(image.url, async response => {
if (response.statusCode != 200) {
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
return await errorHandler(image.itemFk, error, filePath);
}
const writeStream = fs.createWriteStream(filePath); const writeStream = fs.createWriteStream(filePath);
writeStream.on('open', () => { writeStream.on('open', () => {
https.get(image.url, async response => { response.pipe(writeStream);
if (response.statusCode != 200) {
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
return await errorHandler(image.itemFk, error, filePath);
}
response.pipe(writeStream);
}).on('error', async error => {
await errorHandler(image.itemFk, error, filePath);
});
}); });
writeStream.on('error', async error => { writeStream.on('error', async error => {
@ -58,31 +69,44 @@ module.exports = Self => {
}); });
writeStream.on('finish', async function() { writeStream.on('finish', async function() {
writeStream.end();
});
writeStream.on('close', async function() {
try { try {
await models.Image.registerImage('catalog', filePath, fileName, image.itemFk); await models.Image.registerImage('catalog', filePath, fileName, image.itemFk);
await image.destroy(); await image.destroy();
download();
} catch (error) { } catch (error) {
await errorHandler(image.itemFk, error, filePath); await errorHandler(image.itemFk, error, filePath);
} }
}); });
}, 1000); }).on('error', async error => {
} catch (error) { await errorHandler(image.itemFk, error, filePath);
throw new Error('Try-catch error: ', error); });
} }
async function errorHandler(rowId, error, filePath) { async function errorHandler(rowId, error, filePath) {
try { try {
const row = await Self.findById(rowId); const row = await Self.findById(rowId);
if (!row) if (!row) return;
throw new Error(`Could not update due error ${error}`);
await row.updateAttribute('error', error); if (row.attempts < maxAttempts) {
await row.updateAttributes({
error: error,
attempts: row.attempts + 1,
updated: new Date()
});
}
if (filePath && fs.existsSync(filePath)) if (filePath && fs.existsSync(filePath))
await fs.unlink(filePath); await fs.unlink(filePath);
download();
} catch (err) { } catch (err) {
throw new Error(`ErrorHandler error: ${err}`); throw new Error(`Image download failed: ${err}`);
} }
} }
}; };

View File

@ -9,17 +9,26 @@
}, },
"properties": { "properties": {
"itemFk": { "itemFk": {
"type": "Number", "type": "number",
"id": true, "id": true,
"description": "Identifier" "description": "Identifier"
}, },
"url": { "url": {
"type": "String", "type": "string",
"required": true "required": true
}, },
"error": { "error": {
"type": "String", "type": "string",
"required": true "required": true
},
"attempts": {
"type": "number"
},
"created": {
"type": "date"
},
"updated": {
"type": "date"
} }
}, },
"relations": { "relations": {

View File

@ -1,8 +1,4 @@
<vn-horizontal> <vn-horizontal>
<vn-one title="{{$ctrl.name}}">{{$ctrl.name}}</vn-one>
<vn-one ng-if="$ctrl.subName">
<h3 title="{{$ctrl.subName}}">{{$ctrl.subName}}</h3>
</vn-one>
<vn-auto> <vn-auto>
<section <section
class="inline-tag ellipsize" class="inline-tag ellipsize"

View File

@ -8,7 +8,5 @@ ngModule.vnComponent('vnFetchedTags', {
bindings: { bindings: {
maxLength: '<', maxLength: '<',
item: '<', item: '<',
name: '<?',
subName: '<?'
} }
}); });

View File

@ -1,42 +1,30 @@
@import "variables"; @import "variables";
vn-fetched-tags { vn-fetched-tags {
&.noTitle vn-one {
display: none !important;
}
& > vn-horizontal { & > vn-horizontal {
align-items: center; align-items: center;
& > vn-one { & > vn-auto {
overflow: hidden; flex-wrap: wrap;
text-overflow: ellipsis;
min-width: 80px;
}
& > vn-one:nth-child(2) h3 { & > .inline-tag {
color: $color-font-secondary; margin: 1px;
text-transform: uppercase; }
line-height: initial;
text-align: center;
font-size: 1rem
} }
& > vn-auto { & > vn-auto {
display: flex; display: flex;
padding-left: 6px;
min-width: 192px;
& > .inline-tag { & > .inline-tag {
display: inline-block;
color: $color-font-secondary; color: $color-font-secondary;
margin-left: 6px;
text-align: center; text-align: center;
font-size: .75rem; font-size: .75rem;
height: 20px; height: 12px;
padding: 1px; padding: 1px;
border-radius: 1px;
width: 64px; width: 64px;
min-width: 64px; min-width: 64px;
max-width: 64px;
flex: 1;
border: 1px solid $color-spacer; border: 1px solid $color-spacer;
&.empty { &.empty {
@ -44,22 +32,5 @@ vn-fetched-tags {
} }
} }
} }
@media screen and (max-width: 1600px) {
flex-direction: column;
& > vn-one {
padding-bottom: 3px
}
& > vn-auto {
white-space: initial;
padding-left: 0;
flex-wrap: wrap;
justify-content: center;
& > .inline-tag {
margin: 1px;
}
}
}
} }
} }

View File

@ -22,13 +22,13 @@
model="model"> model="model">
</vn-searchbar> </vn-searchbar>
</vn-portal> </vn-portal>
<div class="vn-w-xl"> <div class="vn-w-lg">
<vn-card> <vn-card>
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="itemFk">Item ID</vn-th> <vn-th field="itemFk" shrink>Item ID</vn-th>
<vn-th field="itemFk">Item</vn-th> <vn-th field="itemFk">Description</vn-th>
<vn-th field="warehouseFk">Warehouse</vn-th> <vn-th field="warehouseFk">Warehouse</vn-th>
<vn-th field="rate2">P.P.U.</vn-th> <vn-th field="rate2">P.P.U.</vn-th>
<vn-th field="rate3">P.P.P.</vn-th> <vn-th field="rate3">P.P.P.</vn-th>
@ -40,7 +40,7 @@
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="price in prices"> <vn-tr ng-repeat="price in prices">
<vn-td> <vn-td shrink>
<span <span
ng-if="price.itemFk" ng-if="price.itemFk"
ng-click="itemDescriptor.show($event, price.itemFk)" ng-click="itemDescriptor.show($event, price.itemFk)"
@ -64,16 +64,16 @@
</tpl-item> </tpl-item>
</vn-autocomplete> </vn-autocomplete>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<text> <vn-one title="{{price.name}}">{{price.name}}</vn-one>
<vn-fetched-tags <vn-one ng-if="price.subName">
max-length="6" <h3 title="{{price.subName}}">{{price.subName}}</h3>
item="price" </vn-one>
name="price.name" <vn-fetched-tags
sub-name="price.subName" max-length="6"
tabindex="-1"> item="price"
</vn-fetched-tags> tabindex="-1">
</text> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td> <vn-td>
<vn-autocomplete <vn-autocomplete

View File

@ -15,7 +15,7 @@
<vn-th field="id" shrink>Id</vn-th> <vn-th field="id" shrink>Id</vn-th>
<vn-th field="grouping" shrink>Grouping</vn-th> <vn-th field="grouping" shrink>Grouping</vn-th>
<vn-th field="packing" shrink>Packing</vn-th> <vn-th field="packing" shrink>Packing</vn-th>
<vn-th field="description" style="text-align: center">Description</vn-th> <vn-th field="description">Description</vn-th>
<vn-th field="stems" shrink>Stems</vn-th> <vn-th field="stems" shrink>Stems</vn-th>
<vn-th field="size" shrink>Size</vn-th> <vn-th field="size" shrink>Size</vn-th>
<vn-th field="niche" shrink>Niche</vn-th> <vn-th field="niche" shrink>Niche</vn-th>
@ -50,12 +50,15 @@
</vn-td> </vn-td>
<vn-td shrink>{{::item.grouping | dashIfEmpty}}</vn-td> <vn-td shrink>{{::item.grouping | dashIfEmpty}}</vn-td>
<vn-td shrink>{{::item.packing | dashIfEmpty}}</vn-td> <vn-td shrink>{{::item.packing | dashIfEmpty}}</vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<vn-one title="{{::item.name}}">{{::item.name}}</vn-one>
<vn-one ng-if="::item.subName">
<h3 title="{{::item.subName}}">{{::item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::item" item="item"
name="::item.name" tabindex="-1">
sub-name="::item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td shrink>{{::item.stems}}</vn-td> <vn-td shrink>{{::item.stems}}</vn-td>

View File

@ -21,9 +21,6 @@ vn-item-product {
vn-label-value:first-of-type section{ vn-label-value:first-of-type section{
margin-top: 9px; margin-top: 9px;
} }
vn-fetched-tags vn-horizontal{
margin-top: 14px;
}
} }
vn-table { vn-table {

View File

@ -21,7 +21,7 @@
<vn-th number>Id</vn-th> <vn-th number>Id</vn-th>
<vn-th>Description</vn-th> <vn-th>Description</vn-th>
<vn-th>Warehouse</vn-th> <vn-th>Warehouse</vn-th>
<vn-th expand>Shipped</vn-th> <vn-th>Shipped</vn-th>
<vn-th number>Quantity</vn-th> <vn-th number>Quantity</vn-th>
<vn-th number>Price</vn-th> <vn-th number>Price</vn-th>
<vn-th number>Amount</vn-th> <vn-th number>Amount</vn-th>
@ -42,16 +42,19 @@
{{::row.itemFk | zeroFill:6}} {{::row.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
<vn-one ng-if="::row.item.subName">
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::row.item" item="::row.item"
name="::row.item.name" tabindex="-1">
sub-name="::row.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td shrink>{{::row.warehouse.name}}</vn-td> <vn-td>{{::row.warehouse.name}}</vn-td>
<vn-td expand>{{::row.shipped | date: 'dd/MM/yyyy'}}</vn-td> <vn-td>{{::row.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{::row.quantity}}</vn-td> <vn-td number>{{::row.quantity}}</vn-td>
<vn-td number> <vn-td number>
{{::row.price | currency: 'EUR':2}} {{::row.price | currency: 'EUR':2}}

View File

@ -98,12 +98,15 @@
{{::row.itemFk | zeroFill:6}} {{::row.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand vn-fetched-tags>
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
<vn-one ng-if="::row.item.subName">
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::row.item" item="::row.item"
name="::row.item.name" tabindex="-1">
sub-name="::row.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::row.quantity}}</vn-td> <vn-td number>{{::row.quantity}}</vn-td>

View File

@ -24,31 +24,34 @@
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="itemFk" default-order="ASC" number>Item</vn-th> <vn-th shrink field="itemFk" default-order="ASC" number>Item</vn-th>
<vn-th>Description</vn-th> <vn-th>Description</vn-th>
<vn-th field="quantity" number>Quantity</vn-th> <vn-th shrink field="quantity" number>Quantity</vn-th>
<vn-th number>m³ per quantity</vn-th> <vn-th shrink number>m³ per quantity</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="row in rows"> <vn-tr ng-repeat="row in rows">
<vn-td number> <vn-td shrink number>
<span <span
ng-click="descriptor.show($event, row.itemFk)" ng-click="descriptor.show($event, row.itemFk)"
class="link"> class="link">
{{::row.itemFk}} {{::row.itemFk}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td wide vn-fetched-tags>
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
<vn-one ng-if="::row.item.subName">
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::row.item" item="::row.item"
name="::row.item.name" tabindex="-1">
sub-name="::row.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::row.quantity}}</vn-td> <vn-td shrink number>{{::row.quantity}}</vn-td>
<vn-td number>{{::row.volume | number:3}}</vn-td> <vn-td shrink number>{{::row.volume | number:3}}</vn-td>
</vn-tr> </vn-tr>
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>

View File

@ -1,8 +1,7 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
// #2735 route updateVolume() returns inconsistent values describe('route updateVolume()', () => {
xdescribe('route updateVolume()', () => {
const routeId = 1; const routeId = 1;
const userId = 50; const userId = 50;
const activeCtx = { const activeCtx = {
@ -19,7 +18,6 @@ xdescribe('route updateVolume()', () => {
expect(route.m3).toEqual(1.8); expect(route.m3).toEqual(1.8);
const ticket = await app.models.Ticket.findById(14); const ticket = await app.models.Ticket.findById(14);
await ticket.updateAttributes({routeFk: routeId}); await ticket.updateAttributes({routeFk: routeId});
await app.models.Route.updateVolume(ctx, routeId); await app.models.Route.updateVolume(ctx, routeId);
@ -30,7 +28,8 @@ xdescribe('route updateVolume()', () => {
const logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']}); const logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']});
const m3Log = logs.filter(log => { const m3Log = logs.filter(log => {
return log.newInstance.m3 === updatedRoute.m3; if (log.newInstance)
return log.newInstance.m3 === updatedRoute.m3;
}); });
const logIdToDestroy = m3Log[0].id; const logIdToDestroy = m3Log[0].id;

View File

@ -37,7 +37,7 @@
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="entryFk" expand>Entry </vn-th> <vn-th field="entryFk" expand>Entry </vn-th>
<vn-td expand>{{::entry.id}}</vn-td> <vn-td>{{::entry.id}}</vn-td>
<vn-th field="data">Date</vn-th> <vn-th field="data">Date</vn-th>
<vn-td>{{::entry.shipped | date: 'dd/MM/yyyy'}}</vn-td> <vn-td>{{::entry.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-th field="ref">Reference</vn-th> <vn-th field="ref">Reference</vn-th>
@ -51,10 +51,15 @@
{{::buy.itemName}} {{::buy.itemName}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags wide>
<vn-one></vn-one>
<vn-one ng-if="::buy.subName">
<h3 title="{{::buy.subName}}">{{::buy.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::buy"> item="::buy"
tabindex="-1">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::buy.quantity | dashIfEmpty}}</vn-td> <vn-td number>{{::buy.quantity | dashIfEmpty}}</vn-td>

View File

@ -17,6 +17,9 @@
{"state": "supplier.card.consumption", "icon": "show_chart"} {"state": "supplier.card.consumption", "icon": "show_chart"}
] ]
}, },
"keybindings": [
{"key": "p", "state": "supplier.index"}
],
"routes": [ "routes": [
{ {
"url": "/supplier", "url": "/supplier",

View File

@ -18,11 +18,15 @@
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="sale in $ctrl.ticket.sale.items track by sale.id"> <vn-tr ng-repeat="sale in $ctrl.ticket.sale.items track by sale.id">
<vn-td number>{{("000000"+sale.itemFk).slice(-6)}}</vn-td> <vn-td number>{{("000000"+sale.itemFk).slice(-6)}}</vn-td>
<vn-td expand> <vn-td vn-fetched-tags wide>
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
<vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept"> tabindex="-1">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>

View File

@ -29,12 +29,15 @@
{{sale.itemFk | zeroFill:6}} {{sale.itemFk | zeroFill:6}}
</span> </span>
</td> </td>
<td rowspan="{{::sale.components.length + 1}}" expand> <td rowspan="{{::sale.components.length + 1}}" vn-fetched-tags>
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
<vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept" tabindex="-1">
sub-name="::sale.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</td> </td>
<td rowspan="{{::sale.components.length + 1}}" number> <td rowspan="{{::sale.components.length + 1}}" number>

View File

@ -34,12 +34,15 @@
{{::sale.itemFk | zeroFill:6}} {{::sale.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
<vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept" tabindex="-1">
sub-name="::sale.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>

View File

@ -8,7 +8,7 @@
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-data-viewer model="model"> <vn-data-viewer model="model">
<vn-card class="vn-w-xl"> <vn-card class="vn-w-lg">
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
@ -39,12 +39,15 @@
{{sale.itemFk | zeroFill:6}} {{sale.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags wide>
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
<vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept" tabindex="-1">
sub-name="::sale.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>

View File

@ -58,8 +58,8 @@
</vn-th> </vn-th>
<vn-th shrink></vn-th> <vn-th shrink></vn-th>
<vn-th shrink></vn-th> <vn-th shrink></vn-th>
<vn-th number id="ticketId">Id</vn-th> <vn-th shrink id="ticketId">Id</vn-th>
<vn-th>Quantity</vn-th> <vn-th shrink>Quantity</vn-th>
<vn-th>Item</vn-th> <vn-th>Item</vn-th>
<vn-th number>Price</vn-th> <vn-th number>Price</vn-th>
<vn-th number>Disc</vn-th> <vn-th number>Disc</vn-th>
@ -97,7 +97,7 @@
zoom-image="{{::$root.imagePath('catalog', '1600x900', sale.itemFk)}}" zoom-image="{{::$root.imagePath('catalog', '1600x900', sale.itemFk)}}"
on-error-src/> on-error-src/>
</vn-td> </vn-td>
<vn-td number> <vn-td shrink>
<span class="link" ng-if="sale.id" <span class="link" ng-if="sale.id"
ng-click="descriptor.show($event, sale.itemFk, sale.id)"> ng-click="descriptor.show($event, sale.itemFk, sale.id)">
{{sale.itemFk}} {{sale.itemFk}}
@ -117,7 +117,7 @@
</tpl-item> </tpl-item>
</vn-autocomplete> </vn-autocomplete>
</vn-td> </vn-td>
<vn-td-editable disabled="!$ctrl.isEditable" number> <vn-td-editable disabled="!$ctrl.isEditable" shrink>
<text>{{sale.quantity}}</text> <text>{{sale.quantity}}</text>
<field> <field>
<vn-input-number class="dense" <vn-input-number class="dense"
@ -127,13 +127,16 @@
</vn-input-number> </vn-input-number>
</field> </field>
</vn-td-editable> </vn-td-editable>
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand> <vn-td-editable vn-fetched-tags wide disabled="!sale.id || !$ctrl.isEditable">
<text> <text>
<vn-one title="{{sale.concept}}">{{sale.concept}}</vn-one>
<vn-one ng-if="::sale.subName">
<h3 title="{{::sale.subName}}">{{::sale.subName}}</h3>
</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
item="::sale.item" item="::sale.item"
name="sale.concept" tabindex="-1">
sub-name="::sale.subName">
</vn-fetched-tags> </vn-fetched-tags>
</text> </text>
<field> <field>

View File

@ -23,6 +23,25 @@ vn-ticket-sale {
margin: 3px; margin: 3px;
} }
} }
vn-td-editable[vn-fetched-tags] {
& text {
max-width: 430px;
min-width: 150px;
& vn-one {
overflow: hidden;
text-overflow: ellipsis;
font-size: 0.75rem;
}
& vn-one:nth-child(2) h3 {
color: $color-font-secondary;
text-transform: uppercase;
line-height: initial;
font-size: 0.75rem
}
}
}
vn-dialog.edit { vn-dialog.edit {
@extend .edit-popover; @extend .edit-popover;

View File

@ -149,12 +149,15 @@
</span> </span>
</vn-td> </vn-td>
<vn-td number shrink>{{::sale.quantity}}</vn-td> <vn-td number shrink>{{::sale.quantity}}</vn-td>
<vn-td expand> <vn-td vn-fetched-tags wide>
<vn-fetched-tags <vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
max-length="6" <vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags
max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept" tabindex="-1">
sub-name="::sale.item.subName">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.price | currency: 'EUR':2}}</vn-td> <vn-td number>{{::sale.price | currency: 'EUR':2}}</vn-td>

View File

@ -42,12 +42,16 @@
{{sale.itemFk | zeroFill:6}} {{sale.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td vn-fetched-tags>
<vn-fetched-tags <vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
max-length="6" <vn-one ng-if="::sale.item.subName">
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
</vn-one>
<vn-fetched-tags
max-length="6"
item="::sale.item" item="::sale.item"
name="::sale.concept" tabindex="-1">
sub-name="::sale.item.subName"/> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td> <vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>

View File

@ -18,6 +18,9 @@
{"state": "zone.card.events", "icon": "today"} {"state": "zone.card.events", "icon": "today"}
] ]
}, },
"keybindings": [
{"key": "z", "state": "zone.index"}
],
"routes": [ "routes": [
{ {
"url": "/zone", "url": "/zone",