mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Fix invoice item drag/drop sorting
This commit is contained in:
parent
b8138288d5
commit
cb09c9d5ae
@ -858,19 +858,14 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (isset($tasks) && $tasks)
|
@if (isset($tasks) && $tasks)
|
||||||
// move the blank invoice line item to the end
|
|
||||||
var blank = model.invoice().invoice_items.pop();
|
|
||||||
var tasks = {!! json_encode($tasks) !!};
|
var tasks = {!! json_encode($tasks) !!};
|
||||||
|
|
||||||
for (var i=0; i<tasks.length; i++) {
|
for (var i=0; i<tasks.length; i++) {
|
||||||
var task = tasks[i];
|
var task = tasks[i];
|
||||||
var item = model.invoice().addItem();
|
var item = model.invoice().addItem(true);
|
||||||
item.notes(task.description);
|
item.notes(task.description);
|
||||||
item.qty(task.duration);
|
item.qty(task.duration);
|
||||||
item.task_public_id(task.publicId);
|
item.task_public_id(task.publicId);
|
||||||
item.invoice_item_type_id({{ INVOICE_ITEM_TYPE_TASK }});
|
|
||||||
}
|
}
|
||||||
model.invoice().invoice_items.push(blank);
|
|
||||||
model.invoice().has_tasks(true);
|
model.invoice().has_tasks(true);
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -878,7 +873,7 @@
|
|||||||
model.expense_currency_id({{ isset($expenseCurrencyId) ? $expenseCurrencyId : 0 }});
|
model.expense_currency_id({{ isset($expenseCurrencyId) ? $expenseCurrencyId : 0 }});
|
||||||
|
|
||||||
// move the blank invoice line item to the end
|
// move the blank invoice line item to the end
|
||||||
var blank = model.invoice().invoice_items.pop();
|
var blank = model.invoice().invoice_items_without_tasks.pop();
|
||||||
var expenses = {!! $expenses !!}
|
var expenses = {!! $expenses !!}
|
||||||
|
|
||||||
for (var i=0; i<expenses.length; i++) {
|
for (var i=0; i<expenses.length; i++) {
|
||||||
@ -894,7 +889,7 @@
|
|||||||
item.tax_rate2(expense.tax_rate2);
|
item.tax_rate2(expense.tax_rate2);
|
||||||
item.tax_name2(expense.tax_name2);
|
item.tax_name2(expense.tax_name2);
|
||||||
}
|
}
|
||||||
model.invoice().invoice_items.push(blank);
|
model.invoice().invoice_items_without_tasks.push(blank);
|
||||||
model.invoice().has_expenses(true);
|
model.invoice().has_expenses(true);
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -1552,23 +1547,25 @@
|
|||||||
{
|
{
|
||||||
var hasEmptyStandard = false;
|
var hasEmptyStandard = false;
|
||||||
var hasEmptyTask = false;
|
var hasEmptyTask = false;
|
||||||
for(var i=0; i<model.invoice().invoice_items().length; i++) {
|
|
||||||
var item = model.invoice().invoice_items()[i];
|
for (var i=0; i<model.invoice().invoice_items_without_tasks().length; i++) {
|
||||||
|
var item = model.invoice().invoice_items_without_tasks()[i];
|
||||||
if (item.isEmpty()) {
|
if (item.isEmpty()) {
|
||||||
if (item.invoice_item_type_id() == {{ INVOICE_ITEM_TYPE_TASK }}) {
|
hasEmptyStandard = true;
|
||||||
hasEmptyTask = true;
|
|
||||||
} else {
|
|
||||||
hasEmptyStandard = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasEmptyStandard) {
|
if (!hasEmptyStandard) {
|
||||||
model.invoice().addItem();
|
model.invoice().addItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var i=0; i<model.invoice().invoice_items_with_tasks().length; i++) {
|
||||||
|
var item = model.invoice().invoice_items_with_tasks()[i];
|
||||||
|
if (item.isEmpty()) {
|
||||||
|
hasEmptyTask = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!hasEmptyTask) {
|
if (!hasEmptyTask) {
|
||||||
item = model.invoice().addItem();
|
model.invoice().addItem(true);
|
||||||
item.invoice_item_type_id({{ INVOICE_ITEM_TYPE_TASK }});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
<th style="min-width:32px;" class="hide-border"></th>
|
<th style="min-width:32px;" class="hide-border"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-bind="sortable: { data: {{ $isTasks ? 'invoice_items_with_tasks' : 'invoice_items_without_tasks' }}, afterMove: onDragged} {{ $isTasks ? ', visible: $root.hasTasks' : '' }}"
|
<tbody data-bind="sortable: { data: invoice_items_{{ $isTasks ? 'with_tasks' : 'without_tasks' }}, allowDrop: false, afterMove: onDragged} {{ $isTasks ? ', visible: $root.hasTasks' : '' }}"
|
||||||
{!! $isTasks ? 'style="display:none;border-spacing: 100px"' : '' !!}>
|
{!! $isTasks ? 'style="display:none;border-spacing: 100px"' : '' !!}>
|
||||||
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
|
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
|
||||||
<td class="hide-border td-icon">
|
<td class="hide-border td-icon">
|
||||||
<i style="display:none" data-bind="visible: actionsVisible() &&
|
<i style="display:none" data-bind="visible: actionsVisible() &&
|
||||||
$parent.invoice_items().length > 1" class="fa fa-sort"></i>
|
$parent.invoice_items_{{ $isTasks ? 'with_tasks' : 'without_tasks' }}().length > 1" class="fa fa-sort"></i>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div id="scrollable-dropdown-menu">
|
<div id="scrollable-dropdown-menu">
|
||||||
|
@ -166,15 +166,15 @@ function ViewModel(data) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.hasTasksCached;
|
self.hasTasksCached = false;
|
||||||
self.hasTasks = ko.computed(function() {
|
self.hasTasks = ko.computed(function() {
|
||||||
if (self.hasTasksCached) {
|
if (self.hasTasksCached) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
invoice = self.invoice();
|
invoice = self.invoice();
|
||||||
for (var i=0; i<invoice.invoice_items().length; ++i) {
|
for (var i=0; i<invoice.invoice_items_with_tasks().length; ++i) {
|
||||||
var item = invoice.invoice_items()[i];
|
var item = invoice.invoice_items()[i];
|
||||||
if (! item.isEmpty() && item.invoice_item_type_id() == {{ INVOICE_ITEM_TYPE_TASK }}) {
|
if (! item.isEmpty()) {
|
||||||
self.hasTasksCached = true;
|
self.hasTasksCached = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -229,7 +229,6 @@ function InvoiceModel(data) {
|
|||||||
self.auto_bill = ko.observable(0);
|
self.auto_bill = ko.observable(0);
|
||||||
self.client_enable_auto_bill = ko.observable(false);
|
self.client_enable_auto_bill = ko.observable(false);
|
||||||
self.invoice_status_id = ko.observable(0);
|
self.invoice_status_id = ko.observable(0);
|
||||||
self.invoice_items = ko.observableArray();
|
|
||||||
self.documents = ko.observableArray();
|
self.documents = ko.observableArray();
|
||||||
self.expenses = ko.observableArray();
|
self.expenses = ko.observableArray();
|
||||||
self.amount = ko.observable(0);
|
self.amount = ko.observable(0);
|
||||||
@ -246,17 +245,33 @@ function InvoiceModel(data) {
|
|||||||
self.custom_text_value1 = ko.observable();
|
self.custom_text_value1 = ko.observable();
|
||||||
self.custom_text_value2 = ko.observable();
|
self.custom_text_value2 = ko.observable();
|
||||||
|
|
||||||
|
self.invoice_items_with_tasks = ko.observableArray();
|
||||||
|
self.invoice_items_without_tasks = ko.observableArray();
|
||||||
|
self.invoice_items = ko.computed({
|
||||||
|
read: function () {
|
||||||
|
return self.invoice_items_with_tasks().concat(self.invoice_items_without_tasks());
|
||||||
|
},
|
||||||
|
write: function(data) {
|
||||||
|
self.invoice_items_with_tasks.removeAll();
|
||||||
|
self.invoice_items_without_tasks.removeAll();
|
||||||
|
for (var i=0; i<data.length; i++) {
|
||||||
|
var item = new ItemModel(data[i]);
|
||||||
|
if (item.isTask()) {
|
||||||
|
self.invoice_items_with_tasks.push(item);
|
||||||
|
} else {
|
||||||
|
self.invoice_items_without_tasks.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
owner: this
|
||||||
|
})
|
||||||
|
|
||||||
self.mapping = {
|
self.mapping = {
|
||||||
'client': {
|
'client': {
|
||||||
create: function(options) {
|
create: function(options) {
|
||||||
return new ClientModel(options.data);
|
return new ClientModel(options.data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'invoice_items': {
|
|
||||||
create: function(options) {
|
|
||||||
return new ItemModel(options.data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'documents': {
|
'documents': {
|
||||||
create: function(options) {
|
create: function(options) {
|
||||||
return new DocumentModel(options.data);
|
return new DocumentModel(options.data);
|
||||||
@ -269,7 +284,7 @@ function InvoiceModel(data) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addItem = function() {
|
self.addItem = function(isTask) {
|
||||||
if (self.invoice_items().length >= {{ MAX_INVOICE_ITEMS }}) {
|
if (self.invoice_items().length >= {{ MAX_INVOICE_ITEMS }}) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -277,7 +292,12 @@ function InvoiceModel(data) {
|
|||||||
@if ($account->hide_quantity)
|
@if ($account->hide_quantity)
|
||||||
itemModel.qty(1);
|
itemModel.qty(1);
|
||||||
@endif
|
@endif
|
||||||
self.invoice_items.push(itemModel);
|
if (isTask) {
|
||||||
|
itemModel.invoice_item_type_id({{ INVOICE_ITEM_TYPE_TASK }});
|
||||||
|
self.invoice_items_with_tasks.push(itemModel);
|
||||||
|
} else {
|
||||||
|
self.invoice_items_without_tasks.push(itemModel);
|
||||||
|
}
|
||||||
applyComboboxListeners();
|
applyComboboxListeners();
|
||||||
return itemModel;
|
return itemModel;
|
||||||
}
|
}
|
||||||
@ -329,7 +349,11 @@ function InvoiceModel(data) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.removeItem = function(item) {
|
self.removeItem = function(item) {
|
||||||
self.invoice_items.remove(item);
|
if (item.isTask()) {
|
||||||
|
self.invoice_items_with_tasks.remove(item);
|
||||||
|
} else {
|
||||||
|
self.invoice_items_without_tasks.remove(item);
|
||||||
|
}
|
||||||
refreshPDF(true);
|
refreshPDF(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,18 +592,6 @@ function InvoiceModel(data) {
|
|||||||
}
|
}
|
||||||
self.applyInclusivTax(taxRate);
|
self.applyInclusivTax(taxRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.invoice_items_with_tasks = ko.computed(function() {
|
|
||||||
return ko.utils.arrayFilter(self.invoice_items(), function(item) {
|
|
||||||
return item.invoice_item_type_id() == {{ INVOICE_ITEM_TYPE_TASK }};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
self.invoice_items_without_tasks = ko.computed(function() {
|
|
||||||
return ko.utils.arrayFilter(self.invoice_items(), function(item) {
|
|
||||||
return item.invoice_item_type_id() != {{ INVOICE_ITEM_TYPE_TASK }};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ClientModel(data) {
|
function ClientModel(data) {
|
||||||
@ -769,6 +781,10 @@ function ItemModel(data) {
|
|||||||
self.invoice_item_type_id = ko.observable({{ INVOICE_ITEM_TYPE_STANDARD }});
|
self.invoice_item_type_id = ko.observable({{ INVOICE_ITEM_TYPE_STANDARD }});
|
||||||
self.actionsVisible = ko.observable(false);
|
self.actionsVisible = ko.observable(false);
|
||||||
|
|
||||||
|
self.isTask = ko.computed(function() {
|
||||||
|
return self.invoice_item_type_id() == {{ INVOICE_ITEM_TYPE_TASK }};
|
||||||
|
});
|
||||||
|
|
||||||
this.tax1 = ko.computed({
|
this.tax1 = ko.computed({
|
||||||
read: function () {
|
read: function () {
|
||||||
return self.tax_rate1IsInclusive() + ' ' + self.tax_rate1() + ' ' + self.tax_name1();
|
return self.tax_rate1IsInclusive() + ' ' + self.tax_rate1() + ' ' + self.tax_name1();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user