Compare commits

...

2901 Commits

Author SHA1 Message Date
Oliver
52ab8b8064 Update docker_publish.yaml
Add $
2021-05-29 18:28:07 +10:00
Oliver
b94c0b6d9b Merge pull request #1619 from SchrodingersGat/docker-publish
Tag with release tag
2021-05-29 18:24:57 +10:00
Oliver Walters
8d33dc5795 Tag with release tag 2021-05-29 17:48:40 +10:00
Oliver
878e9c1e8a Update version.py
Bump to v2.2
2021-05-29 17:35:05 +10:00
Oliver
0995ccee67 L10 merge master (#1617)
* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Adds a commit message

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* New Crowdin updates (#1551)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* New Crowdin updates (#1552)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* New Crowdin updates (#1568)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* New Crowdin updates (#1570)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* Trans merge fix (#1599)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* New Crowdin updates (#1597)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Update github actions

* L10 merge fix (#1614)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Update github actions

(cherry picked from commit d9bbebddb0)

* New Crowdin updates (#1603)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Update github actions

(cherry picked from commit d9bbebddb0)

* updated translation base

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2021-05-29 17:33:07 +10:00
Oliver
7f58d95254 Merge pull request #1482 from matmair/price-history
Stock price history
2021-05-29 17:27:51 +10:00
Matthias Mair
9cc81df276 Merge branch 'inventree:master' into price-history 2021-05-28 12:14:03 +02:00
Oliver
723a900388 Merge pull request #1613 from SchrodingersGat/actions
Ignore actions for l10 branches
2021-05-28 14:34:08 +10:00
Oliver
4c78f88aa3 Merge pull request #1612 from SchrodingersGat/exchange-fixes
Remove debug message
2021-05-28 13:26:14 +10:00
Oliver Walters
b716312438 Ignore actions for l10 branches 2021-05-28 13:24:18 +10:00
Oliver Walters
be6e2aa276 Better exception handling 2021-05-28 13:02:34 +10:00
Oliver Walters
7832ccccc2 Check if database tables are ready 2021-05-28 12:54:55 +10:00
Oliver
70e13e4cae Merge pull request #1581 from eeintech/bom_items_purchase_price
Added purchase price range and average to BOM items/view
2021-05-28 12:50:31 +10:00
Oliver Walters
0978235370 Fix? 2021-05-28 12:49:50 +10:00
Oliver Walters
4ddeab3330 Update exchange rates when launching the server
- Ensures that the exchange rates don't get messed up if the base currency is changed!
2021-05-28 12:44:39 +10:00
Oliver Walters
52fc698b51 Remove debug message 2021-05-28 12:07:53 +10:00
eeintech
cdb453b09c Merge branch 'master' of github.com:inventree/InvenTree into bom_items_purchase_price 2021-05-27 10:20:40 -04:00
Oliver
59aca2791a Merge pull request #1611 from SchrodingersGat/exchange-simplification
Exchange simplification
2021-05-27 17:10:30 +10:00
Oliver Walters
c71f4ed045 Add currency exchange unit tests 2021-05-27 16:48:13 +10:00
Oliver Walters
4520bb7447 PEP style fixes 2021-05-27 16:36:26 +10:00
Oliver Walters
6085478672 Simplify settings view
- Show various currency exchange rates
- Button to "refresh now"
2021-05-27 16:34:37 +10:00
Oliver Walters
af1904b6e4 Simplify exhange rate backend 2021-05-27 15:45:38 +10:00
Oliver
62320e46d5 Merge pull request #1610 from SchrodingersGat/template-fix
Bug fix for template
2021-05-27 13:24:08 +10:00
Oliver Walters
2a64e4a309 Bug fix for template 2021-05-27 13:23:20 +10:00
Oliver
8501aba368 Merge pull request #1609 from SchrodingersGat/variant-convert
Expand possibilities for variant conversion
2021-05-27 13:18:48 +10:00
Oliver Walters
4abd3524b4 Looks like py-moneyed has been updated 2021-05-27 12:59:30 +10:00
Oliver Walters
4df7e53bb8 Add DEFAULT_CURRENCY option 2021-05-27 12:55:30 +10:00
Oliver Walters
c2fe5e08b4 Expand possibilities for variant conversion
- Ref get_conversion_options
2021-05-27 12:35:55 +10:00
eeintech
bf83cfb04c Merge branch 'master' of github.com:inventree/InvenTree into bom_items_purchase_price 2021-05-26 09:28:55 -04:00
Oliver
3a36e800c0 Merge pull request #1600 from eeintech/update_rates_manual
Currencies settings and exchange rates list/refresh
2021-05-26 19:10:43 +10:00
eeintech
b04ad48178 Fixed test using manual exchange backend, template update 2021-05-25 11:39:04 -04:00
eeintech
93bfe4c5f1 Added 'Custom Exchange Rate' boolea setting
Removed Fixer.io exchange rate backend
2021-05-25 11:19:07 -04:00
eeintech
654d4ecf46 Merged @SchrodingersGat ExchangeRateHost integration work 2021-05-25 10:34:20 -04:00
Francois
949920865b Merge pull request #3 from matmair/pr1600
proposed changes for translation and safer backend loading
2021-05-25 08:56:59 -05:00
Oliver
500770d1bf Merge pull request #1608 from SchrodingersGat/rate-update-fix
Rate update fix
2021-05-25 14:33:38 +10:00
Oliver Walters
0a26a06909 Use INVENTREE_DEFAULT_CURRENCY as specified base currency 2021-05-25 10:46:30 +10:00
Oliver Walters
619cba6007 Currency: Use ExchangeRateHost backend by default, rather than fixer.io
- No longer support fixer.io as it requires an API key and does not support "base" currency
2021-05-25 10:37:53 +10:00
Oliver
817287a26c Merge pull request #1607 from SchrodingersGat/docker-paths
Docker: Add parent directories if they do not exist
2021-05-25 09:48:11 +10:00
Oliver Walters
ff80c722fb Docker: Add parent directories if they do not exist 2021-05-25 09:32:21 +10:00
Matthias
b15c20611d style 2021-05-24 22:45:00 +02:00
Matthias
b4c9edcd27 bom-price ranges as pie-chart 2021-05-24 22:31:33 +02:00
Matthias
3363969c17 added in randomColor for dynamic color gen 2021-05-24 19:14:38 +02:00
Matthias
206bab137b refactor 2021-05-24 17:39:32 +02:00
Matthias
fe8e03c666 additional information for graph 2021-05-24 15:46:11 +02:00
Matthias
d5b2bfedbc re-layouting tables 2021-05-24 02:18:34 +02:00
Matthias
25681fb805 style 2021-05-24 01:30:37 +02:00
Matthias
84d71d928f removing new stuff in pricing modal 2021-05-24 01:14:15 +02:00
Matthias
7c18ebbbe4 creating new tab 2021-05-24 01:13:46 +02:00
Matthias
b803fbae72 remofing setting 2021-05-24 00:18:04 +02:00
Oliver
2d61e6fc5d Merge pull request #1605 from SchrodingersGat/exchange-rates
Add backend for exchangerate.host
2021-05-23 21:35:15 +10:00
Oliver Walters
65aa468168 Add backend for exchangerate.host 2021-05-23 21:14:43 +10:00
Matthias
1da1753b23 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-05-23 02:31:07 +02:00
Matthias
b1b974a1f6 safer check if fixer-backend is used 2021-05-22 14:55:41 +02:00
Matthias
4503f23ae4 beeing safe with wrong / unknown setttings 2021-05-22 14:55:05 +02:00
Matthias
53ce848145 better translation 2021-05-22 14:48:56 +02:00
Oliver
098b9b7597 Merge pull request #1602 from SchrodingersGat/api-increment
Bump API version to 3
2021-05-22 21:14:18 +10:00
Oliver Walters
240ff59b30 Bump API version to 3
- New stock item history tracking is incompatible
- Adds API info to the "about" dialog
2021-05-22 20:56:56 +10:00
eeintech
be3f37f28f Updated default currency backend 2021-05-20 15:22:18 -04:00
eeintech
bbd95f2c70 Fixed exchange rate backend test 2021-05-20 14:52:56 -04:00
eeintech
27799b43b2 Template fix/improvement 2021-05-20 13:51:54 -04:00
eeintech
747b0554e1 Ready for review 2021-05-20 13:45:26 -04:00
eeintech
bed6a7e49c Added exchange rates form 2021-05-20 09:49:56 -04:00
eeintech
6d5b2d3227 Added 'Currencies' settings view in global settings 2021-05-19 17:06:41 -04:00
eeintech
34ded08ee7 Added InvenTreeFixerExchangeBackend class 2021-05-19 16:17:03 -04:00
eeintech
7a175f13a1 Merge branch 'master' of github.com:inventree/InvenTree into bom_items_purchase_price 2021-05-19 13:25:13 -04:00
Oliver
6c91d067d7 Merge pull request #1598 from SchrodingersGat/fixer-currency-integration
Fixer currency integration
2021-05-18 22:59:14 +10:00
Oliver Walters
4101e25680 Style fixes 2021-05-18 22:41:57 +10:00
Oliver Walters
663f5562e8 Schedule a daily task to update currency information 2021-05-18 22:41:26 +10:00
Oliver Walters
01d444279c Add setting for fixer.io API key 2021-05-18 22:11:24 +10:00
Oliver
efe888056f Merge pull request #1596 from SchrodingersGat/banner-reworks
Banner reworks
2021-05-18 19:34:18 +10:00
Oliver
013d42de7a L10 merge (#1595)
* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Adds a commit message

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* updated translation base

* New Crowdin updates (#1551)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* New Crowdin updates (#1552)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* updated translation base

* New Crowdin updates (#1568)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* New Crowdin updates (#1570)

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* updated translation base

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

* Fix: New translations django.po from Crowdin

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2021-05-18 19:20:24 +10:00
Oliver Walters
7cd345aeb5 Change location of 'banner' messages
- Place them inside the main panel
- Generally underneath the thumbnail
2021-05-18 19:19:43 +10:00
Oliver Walters
a1c4662e91 Move status messages for stock item 2021-05-18 19:11:37 +10:00
Oliver Walters
5204567628 Bug fix for stock item tracking API 2021-05-18 19:06:41 +10:00
Oliver
56fd8132c7 Merge pull request #1593 from SchrodingersGat/hide-purchase-price
Disable "purchase price" field for non-purchaseable parts
2021-05-17 20:45:06 +10:00
Oliver Walters
64c1503fe4 Disable "purchase price" field for non-purchaseable parts 2021-05-17 20:15:53 +10:00
Oliver
b3206f729e Merge pull request #1591 from matmair/more-copy-info
More copy info
2021-05-17 08:52:27 +10:00
Matthias
cfa6994302 docker-mode in stats 2021-05-16 18:20:32 +02:00
Matthias
ff9970f1cc docker in version copy 2021-05-16 18:20:06 +02:00
Matthias
b2a912c770 docker-mode switch in settings and tags 2021-05-16 18:19:35 +02:00
Matthias
16b7d6c34d database and debug info in version copy 2021-05-16 18:18:58 +02:00
Matthias
6c30d128a1 removing duplicate information 2021-05-16 17:33:24 +02:00
Oliver
980befe0fa Merge pull request #1586 from nwns/feature/show_poline_items_in_admin
feat(admin): Show the line items on the PO on the Admin Site
2021-05-15 07:50:53 +10:00
Oliver
6f10195f8c Merge pull request #1465 from nwns/feature/po_on_sales_order
Show PO for Stock Items on Sales Order Detail and stock
2021-05-15 07:49:59 +10:00
eeintech
5ce262172d Fixed bom_item unit test 2021-05-14 16:59:59 -04:00
eeintech
e9f41a8357 Currency finding fix 2021-05-14 16:38:30 -04:00
eeintech
274eb51e48 Added read_only args 2021-05-14 16:29:55 -04:00
eeintech
1940fd5199 Now processing currencies 2021-05-14 16:16:23 -04:00
Nigel
30a2194fe1 feat(admin): Show the line items on the PO on the Admin Site 2021-05-14 13:24:13 -06:00
Oliver
310728ead4 Merge pull request #1583 from SchrodingersGat/server-info
Add debug mode and database backend as info to the "stats" dialog
2021-05-14 12:56:12 +10:00
Oliver Walters
7deea1ec00 Style fixes 2021-05-14 12:40:42 +10:00
Oliver Walters
f76bc5a7b8 Add debug mode and database backend as info to the "stats" dialog 2021-05-14 12:38:38 +10:00
Oliver
033aa29531 Merge pull request #1580 from matmair/BUG-copy
fixing bug from refactor
2021-05-14 07:50:33 +10:00
Oliver
4e6764f952 Merge pull request #1582 from eeintech/po_upload_duplicate_fix
Fixed duplicate check for PO file upload
2021-05-14 07:50:02 +10:00
eeintech
68f5ec8b6a Added currency conversion 2021-05-13 17:09:52 -04:00
Matthias
be92efe7b9 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-05-13 22:58:01 +02:00
Nigel
bca2f4a07b feat(sales_order): Stock Items show the PO number
Stock items show the PO number that they were purchased on when being
viewed in the sales order allocation modal and when viewing the sales
order details.
2021-05-13 14:18:25 -06:00
eeintech
32d0f3039d Obviously new float fields should be read-only... 2021-05-13 16:17:45 -04:00
eeintech
a64ab5956b Removed leftover print 2021-05-13 16:07:57 -04:00
eeintech
22249206d2 Fixed duplicate check 2021-05-13 16:06:57 -04:00
eeintech
f2e9f58f1b Added purchase price range and average to BOM items/view 2021-05-13 15:47:42 -04:00
Matthias
e382f2a57e fixing bug from refactor 2021-05-13 15:46:27 +02:00
Oliver
a1fa3315b1 Merge pull request #1579 from SchrodingersGat/report-naming
Adds a "filename_template" field to reports
2021-05-13 14:03:30 +10:00
Oliver Walters
82a3d9ca96 Implements custom naming for generated labels 2021-05-13 13:40:40 +10:00
Oliver Walters
6de44a5921 Adds a "filename_template" field to reports
- Allows users to define the naming scheme for generated reports
- Templated, can use any context variable already available to the report instance
- Adds some more context variables to various reports
2021-05-13 13:23:51 +10:00
Oliver
8f6e14193a Merge pull request #1576 from matmair/matmair/issue1574
copy-btn in all the places
2021-05-13 10:45:51 +10:00
Matthias
ba3f3108d7 missing translation 2021-05-13 00:21:42 +02:00
Matthias
5077419b68 fewer js-functions 2021-05-13 00:20:51 +02:00
Matthias Mair
b1410c7c2b Merge branch 'inventree:master' into price-history 2021-05-12 23:39:57 +02:00
Matthias
8a8f61c568 functionality for #725 2021-05-12 23:25:39 +02:00
Matthias
0ff7ee21d0 usage of new templates 2021-05-12 15:41:48 +02:00
Matthias
3d574f6a18 templates for mailto and tel - links 2021-05-12 15:41:15 +02:00
Matthias
cdcb6504f9 fixing wrong position 2021-05-12 15:33:49 +02:00
Matthias
f9f191b5e3 Inclusion in all tamplates
#1574
2021-05-12 15:31:35 +02:00
Oliver
07c7af1f2e Merge pull request #1569 from SchrodingersGat/docker-dev
Development docker image
2021-05-12 22:27:50 +10:00
Oliver
9d98ecca92 Merge pull request #1561 from eeintech/multi_part_forms
Multi-step form framework + Purchase order upload file view
2021-05-12 22:18:35 +10:00
Oliver Walters
719b1775f2 Add entrypoint for running development worker 2021-05-12 22:12:26 +10:00
Oliver Walters
530f28ba95 Fix for running webserver 2021-05-12 21:35:54 +10:00
Oliver Walters
00c5a88383 Split environment variables out into a .env file
- No need to collect "static" file when we are running in DEBUG mode
2021-05-12 21:15:53 +10:00
Oliver Walters
3381c5e257 Improvements to development docker-compose script
- Python packages are installed in a virtual environment within the src dir
- This prevents a LONG installation process each time the docker image is rebuilt
2021-05-12 20:53:50 +10:00
Oliver Walters
914db9e913 Development docker image
- Uses multistage build
- Adds a docker compose file for dev
2021-05-12 19:28:04 +10:00
Oliver
d301794516 Merge pull request #1572 from SchrodingersGat/stock-item-history
Stock item history
2021-05-12 10:57:56 +10:00
Oliver Walters
3b252b8409 Record the user when updating stock items 2021-05-12 10:42:09 +10:00
Oliver Walters
30ff48d803 Fixes 2021-05-12 10:09:02 +10:00
Oliver Walters
68b53acbf1 remove old fields from the StockItemTracking model 2021-05-12 08:07:03 +10:00
eeintech
e9c4ce8c5f Added support for reference and notes fields 2021-05-11 17:11:09 -04:00
eeintech
7e6ac54015 YAML does not get installed during django-import-export package? 2021-05-11 14:13:21 -04:00
eeintech
ba561d6d19 Fixed import for excel formats 2021-05-11 14:06:38 -04:00
eeintech
a093118856 Few more fixes 2021-05-11 11:02:54 -04:00
Matthias
169745c11f style fix 2021-05-11 16:23:26 +02:00
eeintech
10eb69caf9 Merge branch 'master' of github.com:inventree/InvenTree into multi_part_forms 2021-05-11 10:22:34 -04:00
Matthias
71c3ff4b9f prefetching related information 2021-05-11 16:15:10 +02:00
Oliver Walters
03a231bffb Updates
- Add StockHistoryCode to custom context
- Add simple form for editing stock item history
- Add tracking entry when stock status is changed
2021-05-11 23:38:26 +10:00
Oliver Walters
84bfffd5a7 Override 'add_note' when new StockItem is created
- This allows us to prevent the issue of duplicate notes being created
2021-05-11 22:51:29 +10:00
Oliver Walters
0c19a94f5c Add run-time addition of extra data to the API 2021-05-11 22:50:58 +10:00
Oliver Walters
93e6eb6dc7 Unit test fixes 2021-05-11 22:26:03 +10:00
Matthias
4156b71c4b Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-05-11 13:32:14 +02:00
Oliver Walters
a1203aa1e5 Fixes for unit testing 2021-05-11 21:22:54 +10:00
Oliver Walters
0020e85397 Refactor add_tracking_entry 2021-05-11 20:56:20 +10:00
Oliver Walters
385131137f Extract stock location from legacy stocktracking entry
- Not 100% accurate - e.g. if the stock location has been altered!
2021-05-11 20:55:14 +10:00
Oliver Walters
ed4da4d338 Improve introspection in migration file 2021-05-11 18:23:29 +10:00
Oliver Walters
725a64c29d Extract more information from legacy tracking data 2021-05-11 18:11:27 +10:00
Oliver Walters
1126e2e110 "Guess" stock history code from recorded title string 2021-05-11 17:41:37 +10:00
Oliver Walters
70ad0ba0de Improve reporting in stock history API 2021-05-11 17:41:17 +10:00
Oliver Walters
af53b341f0 Replace "addTrasactionNote" function with "add_tracking_entry"
- Does not add translated strings to the database
2021-05-11 17:17:48 +10:00
Oliver Walters
82c6d10c33 Add translateable status codes for StockHistory 2021-05-11 17:12:31 +10:00
Oliver
efec09e9a7 Merge pull request #1571 from SchrodingersGat/clipboard-tweaks
Trim content when copying to clipboard
2021-05-11 08:39:14 +10:00
eeintech
c9e77edf04 Almost there? 2021-05-10 17:31:29 -04:00
eeintech
6d8f94619b Improved template render, raised bar for automatic field matching 2021-05-10 12:52:34 -04:00
eeintech
f0932040ee Fixed form validation for previous step, hide tab depending on order status, added purchase_price field 2021-05-10 11:42:22 -04:00
Francois
6857964c17 Merge pull request #1 from matmair/fix-eeintech
Looks good, thanks @matmair !
2021-05-10 07:55:29 -05:00
Oliver Walters
6aab704144 Trim content when copying to clipboard 2021-05-10 19:40:54 +10:00
Oliver
c7d625f23e Merge pull request #1565 from matmair/clipboard-ui
Clipboard UI
2021-05-10 17:24:31 +10:00
Matthias
fc83458bdb changes as suggested by @SchrodingersGat 2021-05-10 07:53:58 +02:00
Oliver
fb1dce1357 Merge pull request #1567 from SchrodingersGat/login-redirect
Login redirect
2021-05-10 12:56:30 +10:00
Oliver Walters
7e55e343e2 PEP fix 2021-05-10 12:35:19 +10:00
Oliver
6a08191595 Merge pull request #1564 from matmair/fix-css
inventree.css cleanup
2021-05-10 12:34:25 +10:00
Oliver Walters
be31154a44 Cleaner implementation 2021-05-10 12:33:49 +10:00
Oliver Walters
d9f621c922 Login redirect fix 2021-05-10 12:29:51 +10:00
Matthias
b0a8477a54 removes unallowed char 2021-05-09 14:35:33 +02:00
Matthias
c148ab9f8e fixed css-comments 2021-05-09 14:34:52 +02:00
Matthias
d38c1f6c0b sample implementation 2021-05-09 14:30:39 +02:00
Matthias
9f6f69a815 rename for shorter inclusion str 2021-05-09 14:29:35 +02:00
Matthias
783b039eb1 initial functionality for #997 2021-05-09 14:28:46 +02:00
Oliver
1f1b0547b0 Merge pull request #1563 from matmair/smal-trans
just a small translation
2021-05-09 10:16:57 +10:00
Matthias
a210b331ce just a small translation 2021-05-09 00:27:00 +02:00
Matthias
f931ba405b style fixes 2021-05-08 21:08:12 +02:00
Matthias
89e0856824 fix for deleting items
in step 2 not working in step 3
2021-05-08 21:05:02 +02:00
Matthias
5622468209 better readable structure 2021-05-08 20:55:01 +02:00
Matthias
e6372fd600 added translations 2021-05-08 20:54:23 +02:00
Matthias
a0d9bf692e simpler code - same function 2021-05-08 20:53:26 +02:00
Oliver
e683912561 Merge pull request #1556 from matmair/spaces!
removes all lines consisting only of spaces
2021-05-08 20:54:36 +10:00
Matthias
5eb1a1f426 fixed styling 2021-05-08 12:32:19 +02:00
Matthias Mair
e59f467c79 Merge branch 'master' into spaces! 2021-05-08 12:27:19 +02:00
eeintech
9b69980a6c Oopsy forgot to merge PurchaseOrderUpload view 2021-05-07 18:08:11 -04:00
eeintech
88000200b3 Merged master and resolved conflicts 2021-05-07 18:02:40 -04:00
eeintech
ceccdf3909 Now creating PurchaseOrderLineItem instances! 2021-05-07 18:00:30 -04:00
eeintech
fbf24621f3 Getting there... 2021-05-07 16:46:10 -04:00
eeintech
6e269ae41a Now displaying item match table 2021-05-07 13:23:10 -04:00
Oliver
e47a8d6d5e Merge pull request #1545 from matmair/issue1425
adds sales order line item price
2021-05-07 23:54:45 +10:00
Matthias
63cf75eefc styling again 2021-05-07 15:37:15 +02:00
Matthias
b6043af7c0 auto-set price if sales-order line is added 2021-05-07 15:35:35 +02:00
Matthias Mair
bdd61fdb2c enable live-serving of i18n_static tag in debug (#1560)
* enable live-serving of i18n_static tag in debug

* style repair
2021-05-07 23:18:06 +10:00
Matthias
9e59d41f12 style improvments 2021-05-07 07:46:35 +02:00
Matthias
ae01503a9e handeling data in an inheritable way 2021-05-07 07:20:43 +02:00
Matthias
c775c4611f adding custom action button
save the changes to the db and return success-json
2021-05-07 07:19:43 +02:00
Matthias
f73863ea51 adding in cstm action buttons function 2021-05-07 07:18:13 +02:00
Matthias
09fe9ccf11 sales order item tracking 2021-05-07 07:15:33 +02:00
Matthias
985967fccb save return of part.id 2021-05-07 07:13:23 +02:00
Francois
5ed17022f2 Fixed stock import as it was not validating the serial properly (#1559) 2021-05-07 07:57:16 +10:00
eeintech
4f942fd9f7 Working towards item match form 2021-05-06 17:07:22 -04:00
eeintech
e31452a6ad Match field step is now managed through form 2021-05-06 16:05:58 -04:00
eeintech
f79382d96f Handling part match form but still not creating purchase order items 2021-05-06 12:35:52 -04:00
Matthias
053793288b same spacing for tables
thanks @eeintech
2021-05-06 18:05:43 +02:00
eeintech
005063aad6 Merge branch 'master' of github.com:inventree/InvenTree into multi_part_forms 2021-05-06 11:30:08 -04:00
Matthias
aac05db6bf style fixing 2021-05-06 17:15:10 +02:00
Matthias
792b2d11c0 cleanup 2021-05-06 16:46:52 +02:00
Matthias
660a3f9410 cleaner get function 2021-05-06 16:46:29 +02:00
Matthias
90c207b935 keeping part id in inherited form 2021-05-06 16:45:39 +02:00
Matthias
4830ff28bf new function for initials 2021-05-06 16:34:37 +02:00
Matthias
c2a5e1fd23 moved the special stuff into the inherited view 2021-05-06 16:29:03 +02:00
Matthias Mair
3a1c233bff Bug/calender (#1558)
* fixes calendar not rendering when toggling view

* same for po

* and builds
2021-05-07 00:11:08 +10:00
Matthias
b09f49aaa5 Merge branch 'master' of https://github.com/inventree/InvenTree into issue1425 2021-05-06 14:54:26 +02:00
Matthias
d8769748f5 config 2021-05-06 14:46:32 +02:00
Matthias
c1bcc60f0a forgot a py 2021-05-06 14:41:26 +02:00
Matthias
d5b65e6e41 yaml! 2021-05-06 14:38:13 +02:00
Matthias
8c63b53c16 here we go js 2021-05-06 14:35:23 +02:00
Matthias
a77d9d9de7 same treatment for html 2021-05-06 14:33:03 +02:00
Matthias Mair
39d4129157 chery picked all fixed trans str from #1438 (#1554) 2021-05-06 20:29:58 +10:00
Matthias
f2b0717d10 removes all lines consisting only of spaces
this really bothers me for some reason - nothing technical
2021-05-06 12:11:38 +02:00
Oliver
3511b4adda Merge pull request #1550 from matmair/layout-fix
Layout fix
2021-05-06 08:58:08 +10:00
Matthias
1259374822 removes layout-shift due to typo in menubar 2021-05-06 00:37:45 +02:00
Matthias
f9463fa277 fixes navbar-layout shift with narrow dollar-sign 2021-05-06 00:33:34 +02:00
Matthias
66f198baa9 removing duplicate information in pricing table 2021-05-06 00:17:46 +02:00
Matthias
c4d0865f06 Merge branch 'master' of https://github.com/inventree/InvenTree into issue1425 2021-05-06 00:14:33 +02:00
Matthias
efa9da2ce1 removed unused imports 2021-05-06 00:00:13 +02:00
Matthias
030865f8dd sale price in pricing table 2021-05-05 23:49:04 +02:00
Matthias
1b7ade9405 adding in missing parts for full saleprice 2021-05-05 23:47:46 +02:00
Matthias
1a227faec4 abstracting get_price 2021-05-05 23:42:52 +02:00
Matthias
287a05ddc5 clearer spacing in html 2021-05-05 21:48:58 +02:00
eeintech
40e8ed9e5b Match parts view is now populated correctly 2021-05-05 15:28:04 -04:00
Matthias
2cfb9c60a3 space cleanup 2021-05-05 20:57:00 +02:00
Matthias
b392586a08 quantity also for modal 2021-05-05 20:55:37 +02:00
Matthias
dc4fb64987 add in price modal in table 2021-05-05 20:53:53 +02:00
Matthias
ee028ef925 space cleanup 2021-05-05 20:38:27 +02:00
eeintech
2cd1df691b Working towards part matching 2021-05-05 13:16:40 -04:00
eeintech
9773fee50b Validation of matching fields is working 2021-05-05 12:40:48 -04:00
Oliver
ecc9eec084 Merge pull request #1547 from SchrodingersGat/no-wrap
Disable wrapping for translation files
2021-05-05 17:54:01 +10:00
Oliver Walters
7a19145be1 Disable wrapping for translation files
This ensures that the updates pushed back from crowding don't have unnecessary file deltas

Ref: https://docs.djangoproject.com/en/3.2/ref/django-admin/#django-admin-makemessages
2021-05-05 17:34:35 +10:00
Oliver
54fb96f239 Merge pull request #1542 from matmair/matmair/issue1513
adds auto price-update from price-brake to purchase order lines
2021-05-05 09:22:59 +10:00
Oliver
6bf4887284 Merge pull request #1544 from matmair/matmair/issue1543
[BUG] invoke: too many arguments
2021-05-05 09:18:56 +10:00
Matthias
251603b69b removing temp fix for invoke error 2021-05-04 23:47:21 +02:00
eeintech
b4342d6203 Fixed templates, not sure why can't keep FileManager across forms... and also need to save form data 2021-05-04 17:35:27 -04:00
Matthias
7fa235282b sale price in ui 2021-05-04 22:50:04 +02:00
Matthias
28a67828e3 [BUG] invoke: too many arguments
Fixes #1543
2021-05-04 22:04:05 +02:00
Matthias
a6fc5d2ebe Merge branch 'issue1425' of https://github.com/matmair/InvenTree into issue1425 2021-05-04 21:57:44 +02:00
Matthias
294e86cc38 Add in sale price model 2021-05-04 21:56:25 +02:00
Matthias
1614c6e08a Add in sale price model 2021-05-04 21:51:42 +02:00
Matthias
55cdeef30e adds price-calc to purchase order Fixes #1513 2021-05-04 21:33:00 +02:00
eeintech
64fb492b97 Added match parts step, need to process fields data 2021-05-04 14:45:52 -04:00
eeintech
7cdf0af04a Added upload file step 2021-05-04 12:20:57 -04:00
eeintech
373898d43e Added step description and crispy form tag 2021-05-04 10:28:00 -04:00
Matthias
75f487aee9 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-05-04 00:02:15 +02:00
eeintech
b847604f15 Started implementation of multi-step form for purchase order file uplod 2021-05-03 17:30:33 -04:00
Oliver
5d214fc869 Merge pull request #1535 from eeintech/get_price
Added support for fractional price and lower price break
2021-05-01 09:52:21 +10:00
Oliver
706f3a913d Update README.md 2021-05-01 09:12:36 +10:00
Oliver
94ff8829f7 Merge pull request #1536 from eeintech/manufacturer_part_api_fix
API fixes related to ManufacturerPart
2021-05-01 08:26:32 +10:00
Oliver
ecbea8ca30 Merge pull request #1537 from matmair/credits
Link for credits in UI and README Closes #1533
2021-05-01 08:25:17 +10:00
Matthias
036c5661ec Link for credits in UI and README Closes #1533 2021-04-30 23:40:52 +02:00
eeintech
4972440dda Fixed API test 2021-04-30 15:27:36 -04:00
eeintech
41962ca23a API fixes related to ManufacturerPart 2021-04-30 13:54:56 -04:00
Oliver
c60f4c4f2f Merge pull request #1529 from matmair/matmair/issue1527
per session user-language settings
2021-04-30 11:53:39 +10:00
eeintech
ad8d95f2f0 Added two more tests with fractional quantities 2021-04-29 14:35:23 -04:00
eeintech
87b38ec992 Added support for fractional part/bom quantity and price 2021-04-29 14:22:07 -04:00
Oliver
2eafdd53b8 Merge pull request #1530 from eeintech/complete_build_output_fix
Fixes to create build output form
2021-04-29 14:56:29 +10:00
Oliver
dd03efe5f2 Merge pull request #1532 from eeintech/purchase_order_fixes
Purchase order fixes
2021-04-29 09:48:11 +10:00
eeintech
d072187bf8 Fixed exception for quantity check 2021-04-28 16:46:42 -04:00
eeintech
a63d5012f0 Purchase order fixes 2021-04-28 13:16:40 -04:00
eeintech
b1ff686395 Fixes to create build output form, added validation on quantity field 2021-04-28 11:18:47 -04:00
Matthias
15eb835ffc explicit redirection url Fixes #1527 2021-04-28 14:38:07 +02:00
Matthias
c5640fe6c6 renamed theme to appearance 2021-04-28 14:37:11 +02:00
Matthias
660f2673ac added in language-change form 2021-04-28 14:26:55 +02:00
Oliver
28b4e12d8c Merge pull request #1528 from matmair/BUG/polish
fixed wrong i18n-code for polish
2021-04-28 22:21:57 +10:00
Matthias
292944179e fixed wrong i18n-code for polish 2021-04-28 13:57:39 +02:00
Oliver
9feed0dcdc Merge pull request #1522 from eeintech/import_records_fix
Add owner model to imports ignore list
2021-04-28 09:01:48 +10:00
Oliver
e6c2252887 Merge pull request #1523 from eeintech/required_parts_build_order
Updated "Required for Build Orders" API queryset
2021-04-28 08:57:30 +10:00
Oliver
2e5be35517 Merge pull request #1525 from matmair/matmair/issue1524
[BUG] no attribute MPN
2021-04-28 07:52:17 +10:00
Matthias
fc429708f1 [BUG] no attribute MPN
Fixes #1524
2021-04-27 21:38:06 +02:00
eeintech
f0b44450fb Updated 'Required for Build Orders' API queryset 2021-04-27 12:48:36 -04:00
eeintech
c5ce5c533b Add owner model to imports ignore list 2021-04-27 11:10:46 -04:00
Matthias
8f40b57121 improvements after code-review by @eeintech 2021-04-27 16:32:43 +02:00
Oliver
4d2e23f701 Merge pull request #1521 from matmair/matmair/issue1519
More syntax for adding serial numbers #1519
2021-04-27 20:43:46 +10:00
Matthias
f4502aecca Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-26 21:48:42 +02:00
Matthias
2de3b892a5 More syntax for adding serial numbers #1519 2021-04-26 21:33:39 +02:00
Oliver
90d12a7406 Merge pull request #1517 from SchrodingersGat/import-export-fixes
Import export fixes
2021-04-25 12:44:46 +10:00
Oliver Walters
80f11290c9 Remove old command 2021-04-25 12:30:59 +10:00
Oliver Walters
5dbebf37b7 Duplicate import of the same data should *NOT* error out 2021-04-25 12:30:14 +10:00
Oliver Walters
f8ec32c3f5 Remove unused include 2021-04-25 12:24:05 +10:00
Oliver Walters
b08cd8da20 Remove dbbackup integration
- Data dumping and restoring is now very complex!
- We should use the invoke export-records function now, rather than relying on dbbackup / dbrestore
- Documentation will be updated to match
2021-04-25 12:14:36 +10:00
Oliver Walters
2f2354afdc Pre-process json data before importing
- Removes any unwanted "permissions" entries from data imported from an *older* version of InvenTree
2021-04-25 12:07:58 +10:00
Oliver Walters
b6cfa50e12 Allow data operations to run for 'test' 2021-04-25 11:59:35 +10:00
Oliver Walters
f766711838 Add fixture for users / groups 2021-04-25 11:41:48 +10:00
Oliver Walters
e13850515d PEP fixes 2021-04-25 11:30:17 +10:00
Oliver Walters
d9d6a2392d Custom post-processing step as part of export-records command:
- We must delete the permission objects associated with a user or group, as auth.permissions are *NOT* included in the exported data file
- The permissions will be automatically created on first run of the server
2021-04-25 11:29:07 +10:00
Oliver Walters
8ad16ceb9c Refactorin' 2021-04-25 11:07:57 +10:00
Oliver Walters
368a5c3f63 Gotsta create tables first ... 2021-04-25 11:07:43 +10:00
Oliver Walters
dd8c0276c7 Ignore session data when exporting records 2021-04-25 10:52:47 +10:00
Oliver Walters
06afd4d726 Refactor "ready" state into a function 2021-04-25 10:52:31 +10:00
Oliver Walters
6e5fc43105 Prevent copying of labels and templates during data import phase 2021-04-25 10:33:11 +10:00
Oliver Walters
2d7bff0773 Prevent auto-update of group permissions during loaddata stage 2021-04-25 10:30:56 +10:00
Oliver Walters
4f9898fba5 Test import / export for MySQL and PostgreSQL 2021-04-25 10:30:31 +10:00
Oliver Walters
792ff16127 Ignore data file 2021-04-25 10:14:13 +10:00
Oliver Walters
de720afd0e Exclude unwanted modules from import / export 2021-04-25 10:13:31 +10:00
Oliver
525a49f001 Merge pull request #1514 from 42CrMo4/multi-platform-docker
docker image armv7
2021-04-23 18:08:32 +10:00
42CrMo4
d97816e5c9 Docker multi-platform publish amv7 2021-04-23 09:30:23 +02:00
42CrMo4
d9cd94f13a Docker multi-platform build amv7 2021-04-23 09:29:24 +02:00
Oliver
43a36754dc Update README.md
Added more translation badges
2021-04-23 09:53:38 +10:00
Oliver
bdd5219019 Merge pull request #1511 from 42CrMo4/multi-platform-docker
Multi platform docker image
2021-04-23 09:07:26 +10:00
Matthias
a11fff0269 man those tests take long 2021-04-22 23:17:27 +02:00
Matthias
83764d5e6c added PO in the fixtures so that should be higher 2021-04-22 22:57:48 +02:00
Matthias
a1237b4a49 always adjust pruchase price if one exists 2021-04-22 22:17:54 +02:00
Matthias
7cb858546e tests for new methods in #1509 2021-04-22 22:16:56 +02:00
Matthias
c14478ed1f automato fill purchase price #1509 2021-04-22 19:31:04 +02:00
42CrMo4
2f13e5a027 Docker multi-platform publish 2021-04-22 19:28:21 +02:00
42CrMo4
654f3ac91b Docker multi-platform build 2021-04-22 18:43:36 +02:00
Oliver
2b66eed7fb Merge pull request #1510 from SchrodingersGat/new-translation
Adds some more translatable strings
2021-04-22 23:37:50 +10:00
Oliver Walters
50d6007afa Cleanup 2021-04-22 23:25:00 +10:00
Oliver
eb55fb3e6b Update translations.yml
Fix the context in which this actions runs

(cherry picked from commit a09e852ecb)
2021-04-22 23:24:13 +10:00
Oliver
a09e852ecb Update translations.yml
Fix the context in which this actions runs
2021-04-22 23:23:32 +10:00
Oliver Walters
d6ef9ee212 Adds some more translatable strings
- Mostly just to check the workflow integration
2021-04-22 23:19:11 +10:00
Oliver
92f6c13fcd Merge pull request #1500 from matmair/feature/translation-action
translations action
2021-04-22 22:50:47 +10:00
Oliver
2f4e78fe51 Merge pull request #1508 from matmair/use-spaces
use spaces instead of tabs
2021-04-22 21:16:45 +10:00
Matthias
294dd0525f use spaces instead of tabs 2021-04-22 12:53:49 +02:00
Matthias
126c5ca3bf typo 2021-04-22 12:48:42 +02:00
Matthias
f7635fb1c0 reording form 2021-04-22 12:39:48 +02:00
Matthias
80d46fb3ab cleanup; using one currency 2021-04-22 12:30:38 +02:00
Matthias
a0154067d2 added setting -> default false 2021-04-22 12:05:48 +02:00
Oliver
12954f885c Merge pull request #1507 from SchrodingersGat/report-permissions
Allow 'admin' account access to the report models
2021-04-22 17:20:54 +10:00
Oliver Walters
4a522bb05a Allow 'admin' account access to the report models 2021-04-22 14:53:42 +10:00
Oliver
022219e3cf Merge pull request #1506 from SchrodingersGat/docker-compose-fixes
docker-compose improvements
2021-04-22 13:34:51 +10:00
Oliver Walters
0c572486ba Revert volume path 2021-04-22 12:49:11 +10:00
Oliver Walters
52deb20e85 docker-compose improvements
- Prepend "inventree" to the name of each container
- Explicitly expose more env variables required for InvenTree db lookup
- Adjust server name in nginx-conf file
2021-04-22 12:15:25 +10:00
Oliver
99060159e3 Merge pull request #1495 from matmair/feature/performance-op
performance improvments docker
2021-04-22 08:53:00 +10:00
Oliver
c5b6e22a58 Merge pull request #1505 from eeintech/email_reset
Enabled default email sender setting
2021-04-22 08:50:05 +10:00
Oliver
34341c31f2 Merge pull request #1504 from SchrodingersGat/turkish
Added skeleton for Turkish translation
2021-04-22 08:46:31 +10:00
Oliver
6259d73583 Merge pull request #1503 from matmair/l10n_trans
added german translations
2021-04-22 08:46:15 +10:00
Matthias
c6b0bdf0fb Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-21 15:36:47 +02:00
eeintech
ee3f3c7960 Updated default backend setting and enabled default sender setting 2021-04-21 09:28:30 -04:00
Matthias
ee64f1086f removing manifest-storage for now, has issues 2021-04-21 15:04:04 +02:00
Oliver Walters
d9cf721589 Added skeleton for Turkish translation 2021-04-21 22:36:57 +10:00
Matthias Mair
decb56e353 updated reference for InvenTree/InvenTree
won't work if there isn't a origin/l10 in the repo
2021-04-21 14:27:25 +02:00
Oliver
8d8ef22b8d Update README.md
Typo fix
2021-04-21 22:19:05 +10:00
Matthias Mair
37953f9926 Merge branch 'master' into l10n_trans 2021-04-21 14:17:19 +02:00
Oliver
2583ab12ae Update README.md 2021-04-21 22:04:46 +10:00
Matthias Mair
41e5a503ac New translations django.po (German)
[ci skip]
2021-04-21 12:42:23 +02:00
Oliver
ae51b1d9ee Update Crowdin configuration file 2021-04-21 20:41:39 +10:00
Oliver
4b069f83bf Update Crowdin configuration file 2021-04-21 20:39:51 +10:00
Oliver
53f2060c40 Update Crowdin configuration file 2021-04-21 20:27:44 +10:00
Matthias Mair
78bf6237d0 New translations django.po (Chinese Simplified)
[ci skip]
2021-04-21 11:33:38 +02:00
Matthias Mair
6600879ed1 New translations django.po (Russian)
[ci skip]
2021-04-21 11:33:37 +02:00
Matthias Mair
0131340bdf New translations django.po (Polish)
[ci skip]
2021-04-21 11:33:35 +02:00
Matthias Mair
08887d2e78 New translations django.po (Japanese)
[ci skip]
2021-04-21 11:33:34 +02:00
Matthias Mair
c5e5dea904 New translations django.po (Italian)
[ci skip]
2021-04-21 11:33:32 +02:00
Matthias Mair
2019dc1f78 New translations django.po (Spanish)
[ci skip]
2021-04-21 11:33:31 +02:00
Matthias Mair
eccd4762b3 New translations django.po (French)
[ci skip]
2021-04-21 11:33:29 +02:00
Matthias Mair
78cbfcfda7 New translations django.po (German)
[ci skip]
2021-04-21 11:33:28 +02:00
Matthias Mair
227327a687 New translations django.po (Chinese Simplified) 2021-04-21 11:17:46 +02:00
Matthias Mair
39af8d8a94 New translations django.po (Russian) 2021-04-21 11:17:45 +02:00
Matthias Mair
3a23c78202 New translations django.po (Polish) 2021-04-21 11:17:43 +02:00
Matthias Mair
97049a90f5 New translations django.po (Japanese) 2021-04-21 11:17:42 +02:00
Matthias Mair
c8a28c4bfb New translations django.po (Italian) 2021-04-21 11:17:40 +02:00
Matthias Mair
8fbbe4ab8e New translations django.po (Spanish) 2021-04-21 11:17:39 +02:00
Matthias Mair
51994b210d New translations django.po (French) 2021-04-21 11:17:37 +02:00
Matthias Mair
cdea39def0 use invoke for trans
instead of commandline
2021-04-21 11:16:05 +02:00
Matthias
07d68f7fde Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-21 11:12:48 +02:00
Matthias
018b845415 Merge branch 'master' of https://github.com/inventree/InvenTree into feature/translation-action 2021-04-21 11:03:45 +02:00
Matthias
a36b22692e Merge branch 'master' of https://github.com/inventree/InvenTree into feature/performance-op 2021-04-21 10:47:25 +02:00
Oliver
2d59c0a119 Merge pull request #1499 from SchrodingersGat/ci-fixes
Change file just to re-run CI
2021-04-21 17:51:22 +10:00
Oliver Walters
3e63334125 Change file just to re-run CI 2021-04-21 17:34:56 +10:00
Oliver
cfddaadccf Merge pull request #1492 from SchrodingersGat/build-order-simplification
Build order simplification
2021-04-21 17:29:24 +10:00
Oliver Walters
c0ab2d1da9 Unit test fixes 2021-04-21 17:16:07 +10:00
Oliver Walters
59341397ba Fixes 2021-04-21 16:44:18 +10:00
Oliver Walters
9b763ca715 Adds ability to specify "status" of a build output at time of completion 2021-04-21 16:44:18 +10:00
Oliver Walters
0722aea58a Further fixes for unit tests 2021-04-21 16:44:18 +10:00
Oliver Walters
debc086f89 Unit test improvements 2021-04-21 16:44:17 +10:00
Oliver Walters
715d912137 Bug fixes 2021-04-21 16:44:17 +10:00
Oliver Walters
5a44a50f3b Fix date in build table 2021-04-21 16:44:17 +10:00
Oliver Walters
76e2b67f36 Fix logic for completing builds
- Display better messages to the user, too
2021-04-21 16:44:17 +10:00
Oliver Walters
4420557863 Refactor various functions for assessing build allocation 2021-04-21 16:44:17 +10:00
Oliver Walters
05e2b62305 Bug fix - calculate button PK at run time!! 2021-04-21 16:44:17 +10:00
Oliver Walters
16b01ed772 significant rework of the build allocation tables / views 2021-04-21 16:44:16 +10:00
Oliver Walters
f0595cc052 Fix for display of "outstanding" allocations 2021-04-21 16:44:16 +10:00
Oliver Walters
9e470d4064 Add separate section for "untracked" part allocation 2021-04-21 16:44:16 +10:00
Oliver
852cc9c4fa Merge pull request #1498 from SchrodingersGat/new-locales
Add some new (empty) locale translation entries
2021-04-21 13:27:52 +10:00
Oliver Walters
64c29d73cc gettext required for translation 2021-04-21 13:11:57 +10:00
Oliver Walters
043d929dbb Fix proper good 2021-04-21 12:57:54 +10:00
Oliver Walters
096403b429 CI file fixes 2021-04-21 12:37:20 +10:00
Oliver Walters
a1e835e01b Add some new (empty) locale translation entries
- fr
- it
- ja
- pl
- ru
- zh

Also fixes the `invoke translate` command (maybe it was changed with the recent update to Django 3.2?)

The CI pipeline now runs the translation and static collection steps, to check those for errors.
2021-04-21 12:33:56 +10:00
Oliver
45d23bd606 Merge pull request #1497 from SchrodingersGat/docker-push
Changes to docker workflow
2021-04-21 11:27:45 +10:00
Oliver Walters
b20c832702 Changes to docker workflow 2021-04-21 11:13:37 +10:00
Matthias Mair
6c296e1384 added collection-step to coverage 2021-04-20 19:28:12 +02:00
Matthias
5a7f83798e docker-start - collect static js #1485 2021-04-20 18:46:35 +02:00
Matthias
fdf3e3a333 added expiry headers to nginx-docker #1485 2021-04-20 18:45:59 +02:00
Matthias
a88d9c7986 Manifeststorage as suggested in #1485 2021-04-20 18:36:51 +02:00
Oliver
4903826be1 Merge pull request #1494 from matmair/feature/js_translation
Translating JS-Files once
2021-04-20 22:58:43 +10:00
Matthias
99dc02e2cb cleaning up names / comments 2021-04-20 14:39:28 +02:00
Matthias
4d439db322 fixing styling issues 2021-04-20 13:48:05 +02:00
Matthias
2943dc6083 initial implementation as in #1485 2021-04-20 13:37:19 +02:00
Oliver
9addad9b46 Merge pull request #1493 from SchrodingersGat/multi-location-print
Split "part category" view into separate pages
2021-04-20 21:10:46 +10:00
Oliver Walters
4d1eb51bc4 Fixes 2021-04-20 20:42:55 +10:00
Oliver Walters
2bb86ff22b Adds missing template file 2021-04-20 20:20:00 +10:00
Oliver Walters
fd3e59650a Style fixes 2021-04-20 20:15:51 +10:00
Oliver Walters
c5fa0bb459 Improved API filtering for PartCategory 2021-04-20 20:15:06 +10:00
Oliver Walters
38eea21f4f Enable printing of multiple stock location labels 2021-04-20 20:06:13 +10:00
Oliver Walters
412b05d76c Allow API filtering by "cascading" stock locations 2021-04-20 20:00:15 +10:00
Oliver Walters
6986709fb8 Reorganized stock location view 2021-04-20 19:49:07 +10:00
Oliver Walters
f578f68001 Split "part category" view into separate pages 2021-04-20 19:30:43 +10:00
Oliver
21708dabaf Merge pull request #1490 from SchrodingersGat/django-3.2
Update to django 3.2
2021-04-20 11:25:25 +10:00
Oliver Walters
0fbf39f1bc More fixes 2021-04-20 10:59:28 +10:00
Oliver Walters
6b9145ae56 Fixes required for v3.2 compatibility
- Specify DEFAULT_AUTO_FIELD
- Specify output_field for annotations
2021-04-20 09:14:08 +10:00
Oliver Walters
12f1fb9526 Update to django 3.2 2021-04-20 08:15:43 +10:00
Oliver
6c159e91cc Merge pull request #1489 from eeintech/stock_fixes
Stock return to customer fix
2021-04-20 07:38:32 +10:00
eeintech
2dbd61c611 Stock return to customer fix, stock children item table fix 2021-04-19 11:25:39 -04:00
Oliver
5f04802ead Merge pull request #1487 from inventree/dependabot/pip/django-3.1.8
Bump django from 3.1.7 to 3.1.8
2021-04-19 21:11:08 +10:00
Oliver
ebf3f6f542 Merge pull request #1488 from SchrodingersGat/suppress-warning
Do not print EMAIL warning if in TEST mode
2021-04-19 21:10:49 +10:00
Oliver Walters
252abb920f Do not print EMAIL warning if in TEST mode 2021-04-19 20:49:24 +10:00
dependabot[bot]
716ab4872a Bump django from 3.1.7 to 3.1.8
Bumps [django](https://github.com/django/django) from 3.1.7 to 3.1.8.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.1.7...3.1.8)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-19 10:48:19 +00:00
Oliver
afca4f244d Merge pull request #1422 from SchrodingersGat/django-latest-version
Update requirements
2021-04-19 20:47:57 +10:00
Oliver Walters
98be42846c Update requirements 2021-04-19 12:21:43 +10:00
Oliver
157d58b157 Merge pull request #1481 from matmair/instance-name-in-title
Instance name in title
2021-04-18 21:48:37 +10:00
Matthias Mair
26e12f299d New translations django.po (German) 2021-04-18 13:31:52 +02:00
Matthias Mair
00ddffa59e New translations django.po (German) 2021-04-18 13:04:25 +02:00
Matthias
6c3a66f7d6 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-18 12:58:19 +02:00
Matthias
e668577d97 fix as noted in #1481 2021-04-18 12:31:17 +02:00
Oliver
3bb0f7dde0 Merge pull request #1480 from SchrodingersGat/docker-build-fix
Fix directory
2021-04-18 20:24:16 +10:00
Oliver
26c19dc77d Merge pull request #1479 from matmair/feature/translations
Feature/translations
2021-04-18 20:23:51 +10:00
Oliver Walters
e057d6d161 Fix directory 2021-04-18 20:00:03 +10:00
Matthias
337f680c89 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-18 11:58:46 +02:00
Oliver
724ecebb4c Update version.py 2021-04-18 19:54:16 +10:00
Oliver
0b5557395b Update version.py 2021-04-18 19:53:15 +10:00
Oliver
6c410521a1 Merge pull request #1476 from SchrodingersGat/docker-improvements
Cleanup docker files
2021-04-18 19:52:42 +10:00
Oliver Walters
9d88d38bf8 Enforce line-endings for more file types 2021-04-18 19:39:03 +10:00
Oliver Walters
4531030551 Fix line endings 2021-04-18 19:37:11 +10:00
Oliver Walters
aced0e73c7 compose file cleanup 2021-04-18 18:58:00 +10:00
Oliver Walters
61eba2f7fc Typo fix 2021-04-18 18:54:21 +10:00
Oliver Walters
0926992b4f Updated nginx conf 2021-04-18 18:53:30 +10:00
Oliver Walters
d8e1e18f4d change web -> inventree 2021-04-18 17:21:06 +10:00
Oliver
b7247284a6 Merge pull request #1478 from SchrodingersGat/log-fix
Remove log output which was leaking password into the logs
2021-04-18 17:20:43 +10:00
Oliver Walters
1502a07b81 Remove log output which was leaking password into the logs 2021-04-18 16:54:35 +10:00
Oliver Walters
eb108edb60 Adds entrypoint for starting a development server 2021-04-18 16:26:32 +10:00
Oliver Walters
270c0ea85d Cleanup docker files 2021-04-18 15:24:33 +10:00
Oliver
83002a5d51 Merge pull request #1475 from SchrodingersGat/docker-fixes
Add binaries for database dumping
2021-04-18 15:23:55 +10:00
Oliver Walters
9eb559bec5 More install fixes 2021-04-18 15:09:01 +10:00
Oliver Walters
69473b9bff Fix install
Also make the web port configurable
2021-04-18 15:05:52 +10:00
Oliver Walters
c07aef7f75 Remove commented line 2021-04-18 14:58:02 +10:00
Oliver Walters
cbb94d2ff7 sqlite3 -> sqlite 2021-04-18 14:57:25 +10:00
Oliver Walters
75054f870e Fix 2021-04-18 14:50:22 +10:00
Oliver Walters
124db01b63 Add binaries for database dumping 2021-04-18 14:45:41 +10:00
Matthias Mair
43422ca169 squashing dev-branch (#14)
* added action to auto-gen the translation base-file
2021-04-18 01:42:52 +02:00
Matthias
0c4d22623d added german translations 2021-04-18 01:33:35 +02:00
Matthias
c99850abf3 po files for new chnaged translation strings 2021-04-18 01:27:04 +02:00
Matthias
c3319e88f4 typo fix 2021-04-18 01:21:44 +02:00
Matthias
5b9c4dc225 sipler translation strings 2021-04-18 01:21:11 +02:00
Matthias
c233e82919 added translatable strings 2021-04-17 23:54:23 +02:00
Matthias
46822017c6 FIX: multiline trans not possible 2021-04-17 23:52:55 +02:00
Matthias
59063bee6b extending translations to the whole sentence 2021-04-17 23:52:21 +02:00
Matthias
20af4c9ba0 template tag for translatable alerts with links 2021-04-17 23:48:47 +02:00
Matthias
7a0a901c2b translations fo true/false yes /no 2021-04-17 23:28:10 +02:00
Matthias Mair
410d6195a8 New translations django.po (German) 2021-04-17 19:00:32 +02:00
Matthias Mair
37b3ac07ff New translations django.po (German) 2021-04-17 17:46:27 +02:00
Matthias
b1e08dae78 Merge branch 'master' of https://github.com/inventree/InvenTree into instance-name-in-title 2021-04-17 12:19:38 +02:00
Matthias Mair
d8d015925b New translations django.po (German) 2021-04-17 11:03:13 +02:00
Matthias Mair
d561186313 New translations django.po (German) 2021-04-17 10:01:03 +02:00
Matthias
3598c36043 Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-17 09:59:05 +02:00
Oliver
2be78f5d4c Merge pull request #1469 from eeintech/stock_item_template_fix
Fixed stock item template for items without manufacturer part
2021-04-17 08:05:21 +10:00
Oliver
d3da262687 Merge pull request #1470 from eeintech/hide_system_alert_nostaff
Hide system alert for non-staff users
2021-04-17 08:04:45 +10:00
eeintech
2b4723cc32 Hide system alert for non-staff users, introduced orange icon for less severe alert than background workers not running (like missing email config) 2021-04-16 12:22:13 -04:00
eeintech
09ef85ce9d Fixed stock item template for items without manufacturer part 2021-04-16 11:43:21 -04:00
Oliver
d4529ec1c4 Merge pull request #1464 from matmair/translation_improv
Translation improvments
2021-04-16 21:46:07 +10:00
Oliver
f8edcf8a0d Merge pull request #1466 from nwns/fix/handle_null_manufacturer_part
fix: don't link manufacturer part if it doesn't have one
2021-04-16 11:09:04 +10:00
Nigel
6f00c662a1 fix: don't link manufacturer part if it doesn't have one 2021-04-15 16:28:50 -06:00
Matthias
098ac0c461 using feature in views 2021-04-15 14:52:08 +02:00
Matthias
d49977bed3 initial implementation as described in #1463 2021-04-15 14:51:11 +02:00
Matthias
cfae92e22b more translated strings for api-titles and filters 2021-04-15 12:15:02 +02:00
Matthias Mair
ecbab57b3b New translations django.po (German) 2021-04-15 12:14:14 +02:00
Matthias Mair
bc140be0ca New translations django.po (German) 2021-04-15 11:18:25 +02:00
Oliver
3e6429cb13 Merge pull request #1462 from eeintech/stock_label
Added revision and stock item QR code URL for label creation
2021-04-15 13:00:09 +10:00
Oliver
3a8cce9af3 Merge pull request #1417 from eeintech/manufacturer_part
Manufacturer Parts
2021-04-15 11:13:02 +10:00
Matthias Mair
ddf14a8f3b New translations django.po (German) 2021-04-14 22:58:16 +02:00
eeintech
aa41e3e17d Fixed default url barcode setting 2021-04-14 16:24:24 -04:00
Matthias Mair
7cc77e70f6 Delete crowdin.yml 2021-04-14 22:04:33 +02:00
eeintech
1bf72ee335 Added revision and stock item URL for label creation 2021-04-14 16:00:28 -04:00
Matthias Mair
50922b1ed4 New translations django.po (German) 2021-04-14 21:59:11 +02:00
Matthias Mair
35c764036c New translations django.po (German) 2021-04-14 21:33:17 +02:00
Matthias
75381cbb7b Merge branch 'master' of https://github.com/inventree/InvenTree into price-history 2021-04-14 21:18:21 +02:00
Matthias Mair
b4003cc3e0 New translations django.po (German) 2021-04-14 16:19:06 +02:00
Matthias Mair
5ff624bf82 New translations django.po (German) 2021-04-14 13:56:23 +02:00
Matthias Mair
a4dfaa9528 New translations django.po (Spanish) 2021-04-14 13:56:22 +02:00
Matthias Mair
7e1bd7b0f7 Update Crowdin configuration file 2021-04-14 13:53:15 +02:00
Matthias Mair
27f5c41359 Update Crowdin configuration file 2021-04-14 13:20:43 +02:00
matmair
c8b234362f updated translation-string 2021-04-14 11:13:13 +00:00
Matthias Mair
91c56d6605 Update Crowdin configuration file 2021-04-14 12:40:58 +02:00
Matthias
73bcacc2d8 added tranlation strings 2021-04-14 12:23:51 +02:00
Matthias
79a643ccf5 Merge branch 'master' of https://github.com/inventree/InvenTree into translation_improv 2021-04-14 10:46:41 +02:00
Oliver
623d0366fc Update README.md
Fixed docker link
2021-04-14 07:55:12 +10:00
eeintech
1e6c6c678f Split supplier part update migration and added reverse method for manufacturer data 2021-04-13 10:25:53 -04:00
eeintech
42a73576da Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part 2021-04-13 09:48:55 -04:00
Oliver
a8d22dac62 Merge pull request #1458 from matmair/translation_improv
updated translation references
2021-04-13 21:20:32 +10:00
Matthias
75a249da95 Merge branch 'master' of https://github.com/inventree/InvenTree into translation_improv 2021-04-13 13:03:58 +02:00
Matthias
71425d3bc5 updated translation references 2021-04-13 12:56:18 +02:00
Oliver
79dc66e840 Merge pull request #1304 from SchrodingersGat/email-support
Support for email settings
2021-04-13 20:42:23 +10:00
Oliver Walters
d5034ece51 typo fix 2021-04-13 20:21:33 +10:00
Oliver Walters
04318c6d70 Adjust default email settings 2021-04-13 20:15:09 +10:00
Oliver Walters
96efb0eb28 Remove "forgot password" link if the email backend is not configured 2021-04-13 20:02:20 +10:00
eeintech
3eae70e745 Merged master and company migrations 2021-04-12 11:10:35 -04:00
Oliver Walters
f902b79d79 And more templates 2021-04-12 20:07:38 +10:00
Oliver Walters
12a4c22a9b Password reset templates 2021-04-12 20:02:05 +10:00
Oliver Walters
a9d490b716 PEP fixes 2021-04-12 19:20:41 +10:00
Oliver Walters
d243ff6b37 Offload email task to background worker 2021-04-12 19:18:47 +10:00
Oliver Walters
fb5a94a778 Support for email settings 2021-04-12 18:50:37 +10:00
Oliver
72f83771f1 Merge pull request #1453 from SchrodingersGat/part-parameter-api
Part parameter api
2021-04-11 19:41:02 +10:00
Oliver Walters
8a06eaa40d Unit testing 2021-04-11 19:28:39 +10:00
Oliver Walters
85c9bc1b81 Adds detail endpoint for PartParameter model 2021-04-11 18:56:35 +10:00
Oliver
471d009e84 Merge pull request #1452 from SchrodingersGat/workflow-fox
Fix workflow for publishing docker files
2021-04-11 15:45:40 +10:00
Oliver Walters
029808a986 Fix workflow for publishing docker files 2021-04-11 15:45:17 +10:00
Oliver
effd547260 Update version.py 2021-04-11 15:39:53 +10:00
Oliver
7c9ad3f406 Update version.py 2021-04-11 15:39:16 +10:00
Oliver
4cf0339393 Update README.md 2021-04-11 15:38:52 +10:00
Oliver
a2ff3e3474 Merge pull request #1398 from SchrodingersGat/django-q
Django q
2021-04-11 15:38:20 +10:00
Oliver Walters
c2f85b0447 docker-compose tweaks 2021-04-11 15:25:32 +10:00
Oliver Walters
8f07efa4e3 Add dockerhub badge 2021-04-11 15:15:11 +10:00
Oliver Walters
b490c5d035 Add new docker workflow for publising docker images on release 2021-04-11 15:08:13 +10:00
Oliver Walters
f9449da576 Merge remote-tracking branch 'upstream/master' into django-q
# Conflicts:
#	InvenTree/InvenTree/version.py
2021-04-11 15:03:33 +10:00
Oliver
34e95ab70c Update version.py 2021-04-11 14:49:41 +10:00
Oliver Walters
5f9236d280 Updates to docker files 2021-04-11 14:46:40 +10:00
Oliver Walters
44fe5721e0 Disgusting hack for tasks.py 2021-04-11 14:05:55 +10:00
Oliver Walters
f6f3815f31 Include worker status in main API call 2021-04-11 13:58:59 +10:00
Oliver Walters
78bcbe271a Update supervisor conf file 2021-04-11 13:45:56 +10:00
Oliver Walters
2e8d3b6424 Fix for tasks.py (??) 2021-04-11 13:22:16 +10:00
Oliver Walters
c9021fe991 Simplify docker build workflow 2021-04-10 22:48:23 +10:00
Oliver Walters
0e1b647e7b Remove mariadb test (uses the same backend as mysql!) 2021-04-10 22:47:30 +10:00
Oliver Walters
b74d365529 Merge remote-tracking branch 'upstream/master' into django-q 2021-04-10 22:46:20 +10:00
Oliver Walters
3da5505b58 Fix build workflow 2021-04-10 22:44:37 +10:00
Oliver Walters
5a168abbfe Separated docker file into separate directory 2021-04-10 22:42:08 +10:00
Oliver Walters
8f626d305e Fix location of entrypoint scripts 2021-04-10 22:35:10 +10:00
Oliver Walters
5d9e273559 Adds nxinx service 2021-04-10 22:25:07 +10:00
Oliver Walters
91b6f98f95 Update directory structure to match docker config 2021-04-10 22:08:36 +10:00
Oliver Walters
2f1db486a0 Do not use python virtual environment inside container 2021-04-10 21:40:27 +10:00
Oliver Walters
823f84e46a Simplified volume management in docker-compose 2021-04-10 20:58:51 +10:00
Oliver Walters
178715ce61 Auto create config file in specified location if it does not exist 2021-04-10 20:57:56 +10:00
Oliver Walters
e787c853e5 Update logger context 2021-04-10 20:08:13 +10:00
Oliver Walters
5e54b0f5cf Auto-generate key file if it does not exist! 2021-04-10 19:01:02 +10:00
Oliver Walters
9086c8a3bf Simplify external directory structure
- All InvenTree data now in a single subdir
- Copy default config file (if it does not exist)
- Config file is accessible from outside world
- Update start_server and start_worker scripts
2021-04-10 17:36:19 +10:00
Oliver
e011faa9b7 Merge pull request #1450 from SchrodingersGat/company-description-optional
Company description is no longer a required field
2021-04-10 16:19:30 +10:00
Oliver Walters
e6bd91c9e2 Company description is no longer a required field 2021-04-10 15:29:44 +10:00
Oliver Walters
1372343bd5 Updates to docker-compose file
- Note: not ready yet!
2021-04-10 15:27:50 +10:00
Oliver Walters
8eb571bddf Update dockerfile 2021-04-10 15:08:10 +10:00
Oliver
c7e1ac5648 Merge pull request #1449 from eeintech/fix_stock_ops
Fixed transfer stock action in template
2021-04-10 09:19:43 +10:00
Oliver
6bf3cc9e01 Merge pull request #1446 from eeintech/bom_yaml_export
Replace normalize with integer wrapper for quantity field
2021-04-10 09:17:23 +10:00
eeintech
6bf4140e5a Fixed transfer stock action in template 2021-04-09 16:55:05 -04:00
eeintech
afddf12339 Changed int to float 2021-04-08 22:04:26 -04:00
Oliver
6a1bb0a806 Merge pull request #1445 from eeintech/simple_stock_table_view
Simplified stock table view in Part and SupplierPart detail pages
2021-04-09 11:58:33 +10:00
eeintech
97e1bc0a67 Added missing part_detail reference 2021-04-08 21:46:11 -04:00
eeintech
cbddda6640 Remove normalize import 2021-04-08 14:41:06 -04:00
eeintech
7491cda313 Replace normalize with integer wrapper for quantity field 2021-04-08 14:35:47 -04:00
eeintech
b5a5f5b409 Simplified stock table view in Part and SupplierPart detail pages 2021-04-08 13:42:35 -04:00
eeintech
f8d1ee8805 Made company description optional 2021-04-08 13:24:17 -04:00
Oliver Walters
47a93bc4cb More environment variables for config.yaml 2021-04-08 21:01:52 +10:00
Oliver Walters
3381945e14 Add newline 2021-04-08 17:10:48 +10:00
eeintech
0bb2507dd6 Added manufacturer part deletion warning when deleting a part 2021-04-07 14:02:50 -04:00
eeintech
1074300ba0 Improved BOM export of combined manufacturer and supplier data 2021-04-07 12:24:32 -04:00
eeintech
ccd35fc4b4 Fixed supplier part list bug and hide manufacturer fields in supplier part edit form 2021-04-07 11:50:11 -04:00
eeintech
c0691c3e9b Decoupled manufacturer and supplier data in BOM export, aggregate data needs more work 2021-04-07 11:43:05 -04:00
eeintech
63ade51c6c Updated migrations after merge with master 2021-04-07 10:49:19 -04:00
Oliver Walters
3926276fd1 Greatly simplified "wait_for_db" command 2021-04-08 00:37:34 +10:00
eeintech
f39928368e Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part 2021-04-07 10:33:55 -04:00
eeintech
2db6af2af6 PO table and stock item template improvements 2021-04-07 10:33:31 -04:00
Oliver Walters
71cac6e269 Simplify waiting for db 2021-04-08 00:09:51 +10:00
Oliver Walters
ed304f571a Better configuration of github repo 2021-04-08 00:05:37 +10:00
eeintech
b2264940a3 Dynamic control of information to make cleaner supplier and manufacturer tables 2021-04-07 09:54:20 -04:00
Oliver Walters
14aead038e Adds docker_compose file 2021-04-07 23:46:30 +10:00
Oliver Walters
d4d9263131 Add option to specify config file via environment variable 2021-04-07 23:46:03 +10:00
Oliver Walters
9c38d67b52 Merge remote-tracking branch 'upstream/master' into django-q
# Conflicts:
#	InvenTree/InvenTree/status.py
#	InvenTree/templates/about.html
2021-04-07 22:29:47 +10:00
Oliver Walters
4a3ca4638c Dockerfile updates 2021-04-07 22:27:55 +10:00
Oliver Walters
d91531720b Unit testing for task scheduling 2021-04-07 22:17:24 +10:00
Oliver
5e0e364b6c Merge pull request #1441 from SchrodingersGat/missing-git
Hide git information if there is an error
2021-04-07 22:09:38 +10:00
Oliver
da63ec5351 Merge pull request #1437 from matmair/translation_improv
Translation improvements
2021-04-07 20:57:47 +10:00
Oliver Walters
6412cf1c87 Hide git information if there is an error 2021-04-07 20:55:44 +10:00
eeintech
734985faa9 Made manufacturer part ID dynamic for API supplier part create test 2021-04-06 14:53:35 -04:00
eeintech
52b2b9582d More tests and improved coverage (hopefully) 2021-04-06 14:30:03 -04:00
eeintech
7b4d3a3c07 Added test units for migration and API 2021-04-06 13:16:01 -04:00
Matthias
32eaf48c12 fixed styling 2021-04-06 18:33:57 +02:00
Matthias
f647120cd1 initial showcase implementation 2021-04-06 18:17:09 +02:00
eeintech
76fe535ef9 Improved delete form to show supplier parts deletion 2021-04-06 09:32:59 -04:00
eeintech
bd65a42410 Removed global setting for manufacturer parts (enabled for all users) 2021-04-06 08:49:45 -04:00
eeintech
fd66e8b136 Added MPN link to supplier part list 2021-04-05 15:41:18 -04:00
eeintech
547dcc6e80 Deleted manufacturers tab from supplier detail page 2021-04-05 15:19:34 -04:00
eeintech
58ddc47065 Updated migration files to handle duplicate manufacturer data 2021-04-05 11:21:34 -04:00
Matthias
530b90042a added german(de) translations 2021-04-04 22:51:16 +02:00
Matthias
2c053eae4c added translations 2021-04-04 22:49:47 +02:00
Matthias
ef64d1e61d added label to DatePickerFormField 2021-04-04 22:49:17 +02:00
Matthias
adcb211572 set language in the used js scripts 2021-04-04 22:48:36 +02:00
Matthias
efd14fca64 made translation lazy 2021-04-04 22:47:01 +02:00
Matthias
20c455384e added more translation-strings 2021-04-04 22:44:14 +02:00
Matthias
c68220a597 migrations for all the translated models, totally forgot that 2021-04-03 14:11:28 +02:00
Matthias
cd7724d490 added german(de) translations for the new stuff 2021-04-03 13:48:02 +02:00
Matthias
f67210b20f added translation files for changes 2021-04-03 04:11:40 +02:00
Matthias
1854da380b made filters.js dynamic for translation 2021-04-03 04:07:27 +02:00
Matthias
0547e1c03b added more translations in html / js 2021-04-03 04:05:59 +02:00
Matthias
446bc06c1b switched translation methode to lazy 2021-04-03 04:01:40 +02:00
Matthias
2de6fcbfa4 added missing translation fields #753 2021-04-03 03:59:09 +02:00
Matthias
698b946403 activated translations for settings 2021-04-02 23:03:24 +02:00
eeintech
45ca8d0e93 Fixes to the way ManufacturerPart is saved, manufacturer table filtering and test units 2021-04-02 11:13:57 -04:00
eeintech
bb69e38c1a Simple and View test units 2021-04-01 16:30:06 -04:00
eeintech
94574b37ae Added Manufacturer parts to search, fixed icons, added manufacturer view in supplier part detail page 2021-04-01 10:00:15 -04:00
Oliver Walters
00c4519d28 Simplify dockerfile 2021-04-02 00:54:29 +11:00
Oliver Walters
2436b1f2c9 Entrypoint script - start.sh 2021-04-02 00:40:47 +11:00
eeintech
a8b858c824 Fixed serializer 2021-04-01 09:11:47 -04:00
Oliver Walters
8d3b9e2ca4 Updates to settings.py
- Create secret_key.txt if it does not exist
- Copy default settings file if it does not exist
2021-04-02 00:06:17 +11:00
Oliver Walters
be41be3981 Add "wait_for_db" management command 2021-04-02 00:03:56 +11:00
Oliver Walters
8e7e36089b Fix venv 2021-04-01 21:11:59 +11:00
Oliver Walters
47ba0599eb Reference environment variables in supervisor conf file 2021-04-01 20:44:27 +11:00
Oliver Walters
db858b3cfc Install packages inside venv 2021-04-01 20:44:13 +11:00
Oliver Walters
148600a9c4 Copy gunicorn.conf.py 2021-04-01 20:38:18 +11:00
Oliver Walters
839c29117d Dockerfile updates
- Pipe supervisor logs to stdout (so they are passed to the docker instance)
- Fix supervisor service
- Expose home dir and port as env vars
2021-04-01 20:30:51 +11:00
Oliver Walters
d446f8ddd1 Add supervisor conf file specific to docker 2021-04-01 20:14:31 +11:00
Oliver Walters
08a1a6cf43 Add configuration options for the Dockerfile 2021-04-01 20:14:17 +11:00
Oliver Walters
76ab38a06b Add docker info 2021-04-01 11:35:03 +11:00
eeintech
8c8b25a0d2 Validating API for SupplierPart, not able to spin-off ManufacturerPart from serialized data 2021-03-31 18:04:28 -04:00
Oliver Walters
38b9655ad9 Remove unused workflow 2021-04-01 08:43:58 +11:00
eeintech
9e56bf90c5 More web testing, looks ready 2021-03-31 13:53:55 -04:00
eeintech
2f2e5862a9 Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part 2021-03-31 13:10:33 -04:00
Oliver Walters
b9e81c3c0e Start supervisord
Ref: https://advancedweb.hu/supervisor-with-docker-lessons-learned/
2021-03-31 23:39:16 +11:00
Oliver Walters
b9f9b26ca5 Sudo not required, I guess? 2021-03-31 23:32:03 +11:00
Oliver Walters
7683cc1aaa APK not APT 2021-03-31 23:27:01 +11:00
Oliver Walters
ff6b127f1b Typo fixin' 2021-03-31 23:22:17 +11:00
Oliver Walters
8b227ce297 More required packages, I guess... 2021-03-31 23:20:32 +11:00
Oliver Walters
286cf9b102 gcc required 2021-03-31 23:12:27 +11:00
Oliver Walters
24d36e0b66 Getting there... 2021-03-31 23:09:24 +11:00
Oliver Walters
251ec7a02f Fix lib names 2021-03-31 23:06:54 +11:00
Oliver Walters
61f8b982ce lib name fix 2021-03-31 23:03:13 +11:00
Oliver Walters
1f881dd041 Run as root 2021-03-31 23:00:22 +11:00
Oliver Walters
42b400e619 typo fix 2021-03-31 22:58:32 +11:00
Oliver Walters
601aff8283 Install git 2021-03-31 22:55:44 +11:00
Oliver Walters
58bfc80f79 Alpine uses different commands 2021-03-31 22:54:17 +11:00
Oliver Walters
2746396d11 Fix tag name 2021-03-31 22:50:41 +11:00
Oliver Walters
6017cad6b3 So apparently I cannot spell... 2021-03-31 22:48:58 +11:00
Oliver Walters
1a7b6e2613 Fix 2021-03-31 22:47:41 +11:00
Oliver Walters
ab57fd3b76 Build docker image 2021-03-31 22:45:42 +11:00
Oliver Walters
c0a0ca4588 PEP fix 2021-03-31 22:35:48 +11:00
Oliver Walters
3f257279ee Specify directories for CI 2021-03-31 22:31:50 +11:00
Oliver Walters
731ec25b24 Merge remote-tracking branch 'inventree/master' into django-q
# Conflicts:
#	.github/workflows/style.yaml
#	.travis.yml
#	InvenTree/InvenTree/settings.py
2021-03-31 22:17:38 +11:00
Oliver
53c9475e6d Update README.md 2021-03-31 22:11:01 +11:00
Oliver
9ccff64679 Update README.md 2021-03-31 22:10:12 +11:00
Oliver
de3395ed26 Update README.md 2021-03-31 22:09:39 +11:00
Oliver
16433f49c6 Merge pull request #1433 from SchrodingersGat/coverage-workflow
Add workflow for code coverage
2021-03-31 22:08:08 +11:00
Oliver Walters
73e032e1d0 Specify database name 2021-03-31 21:54:13 +11:00
Oliver Walters
82b6c48946 Specify database name 2021-03-31 21:48:54 +11:00
Oliver Walters
566c3af39e Environment variables take preference! 2021-03-31 21:40:19 +11:00
Oliver Walters
5d141e3568 Always print database config 2021-03-31 21:24:14 +11:00
Oliver Walters
83cd24961d INFO level debug 2021-03-31 21:18:17 +11:00
Oliver Walters
737a378515 Extra debug output for tests 2021-03-31 21:17:17 +11:00
Oliver Walters
f71ebc20ec Remove travis script 2021-03-31 21:07:16 +11:00
Oliver Walters
ac9753e72c Add data import/export step 2021-03-31 20:58:30 +11:00
Oliver Walters
dc94376f6d Fix workflows 2021-03-31 20:46:26 +11:00
Oliver Walters
c846e2e65a Use env variables rather than custom ci scripts 2021-03-31 20:39:22 +11:00
Oliver Walters
608f47837f Update README.md with badges 2021-03-31 20:26:47 +11:00
Oliver Walters
2f6ee330de Add CI check against MariaDB 2021-03-31 20:20:10 +11:00
Oliver Walters
c66dddc03f Force TCP for postgres 2021-03-31 20:14:57 +11:00
Oliver Walters
48cbd3be97 Remove (old) docs 2021-03-31 20:13:12 +11:00
Oliver Walters
6b99808c52 Run as root 2021-03-31 20:12:45 +11:00
Oliver Walters
61d14a0eda Database naming fix 2021-03-31 20:07:42 +11:00
Oliver Walters
5aea35f8fa Force TCP 2021-03-31 20:04:18 +11:00
Oliver Walters
3cc0530419 Root password 2021-03-31 20:01:02 +11:00
Oliver Walters
cef75aabc5 Update 2021-03-31 19:59:23 +11:00
Oliver Walters
09693d0d09 Start service 2021-03-31 19:54:37 +11:00
Oliver Walters
70703f8588 Try localhost 2021-03-31 19:48:20 +11:00
Oliver Walters
67a4c5a9a2 Try pointing to different host 2021-03-31 19:45:58 +11:00
Oliver Walters
db8d93e2e9 Create mysql database manually 2021-03-31 17:54:42 +11:00
Oliver Walters
af52f0eace Typo fix 2021-03-31 17:45:57 +11:00
Oliver Walters
631e41e22a Fix postgres workflow 2021-03-31 17:40:37 +11:00
Oliver Walters
f8d29b7b3b Typo 2021-03-31 17:36:33 +11:00
Oliver Walters
9e4218d02f Mysql fixes 2021-03-31 17:34:12 +11:00
Oliver Walters
d09483f30c Workflow fixes 2021-03-31 17:28:30 +11:00
Oliver Walters
d1a42f55a2 Fix flake issues 2021-03-31 17:20:12 +11:00
Oliver Walters
bdd5fa96e7 Add tests for mysql and postgresql 2021-03-31 17:18:04 +11:00
Oliver Walters
4f87c848a5 Ensure flake8 fails 2021-03-31 17:17:40 +11:00
Oliver Walters
d20c3bb733 GITHUB_TOKEN 2021-03-31 17:08:24 +11:00
Oliver Walters
ae72224ece Fix coveralls 2021-03-31 16:57:44 +11:00
Oliver Walters
fd43f8dc64 Merge remote-tracking branch 'inventree/master' into coverage-workflow
# Conflicts:
#	.github/workflows/style.yaml
2021-03-31 16:26:02 +11:00
Oliver Walters
6b32142725 run on pull request 2021-03-31 16:24:33 +11:00
Oliver Walters
01e6635032 Add workflow for code coverage 2021-03-31 13:06:22 +11:00
Oliver
88a021f165 Merge pull request #1432 from SchrodingersGat/style-checks
Update style worfdlow
2021-03-31 13:05:59 +11:00
Oliver Walters
b16f85de65 Update style worfdlow 2021-03-31 12:41:39 +11:00
eeintech
0b1f22c7fd Almost there, needs some interface testing and tweaking 2021-03-30 18:08:33 -04:00
eeintech
9c8817d73b Fixed serializers and started update of templates 2021-03-30 16:48:16 -04:00
eeintech
811f9333e8 SupplierPart manufacturer data is not serializing 2021-03-30 13:55:20 -04:00
eeintech
a4d098194b New SupplierPart manufacturer_part field
New migration file with database update to manufacturer parts
Removed SourceItem model
2021-03-30 13:14:30 -04:00
eeintech
e78455085f Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part 2021-03-30 11:30:47 -04:00
Oliver
865436c42a Merge pull request #1431 from SchrodingersGat/workflows
Add code style workflow
2021-03-30 22:41:27 +11:00
Oliver Walters
db994fd908 Add code style workflow 2021-03-30 21:56:17 +11:00
Oliver Walters
83f8afe113 Add github actions 2021-03-30 21:33:49 +11:00
Oliver Walters
e7ed4c4eab Travis fixes 2021-03-30 21:24:06 +11:00
Oliver Walters
39b2c5f943 Reintroduce default database config 2021-03-30 21:18:09 +11:00
Oliver Walters
3ddbb6a6cd Check for empty values 2021-03-30 20:53:26 +11:00
Oliver
fd01e23245 Merge pull request #1430 from SchrodingersGat/missing-permission-fix
Emit warning rather than raise error
2021-03-30 10:28:54 +11:00
Oliver Walters
1a288168b7 PEP fixes 2021-03-30 10:00:43 +11:00
Oliver
f288b906ad Merge pull request #1426 from SchrodingersGat/assign-by-sn
Assign by sn
2021-03-30 09:29:49 +11:00
Oliver Walters
58c30f48d5 Remove extra whitespace 2021-03-30 09:28:02 +11:00
Oliver Walters
bfbdd72306 Remove unused import 2021-03-30 08:43:09 +11:00
Oliver Walters
0b78f3d931 Add unit testing for migrations 2021-03-30 08:42:44 +11:00
Oliver Walters
32cfe1b954 Emit warning rather than raise error
- All calling functions check for None anyway
2021-03-30 08:25:51 +11:00
Oliver
67f06d6e5d Merge pull request #1428 from inventree/dependabot/pip/pygments-2.7.4
Bump pygments from 2.2.0 to 2.7.4
2021-03-30 08:16:21 +11:00
Oliver Walters
408b9d5e5b Fix for unit testing 2021-03-30 08:08:55 +11:00
eeintech
50adb2ac61 SourceItem only for SupplierPart, added logic to templates 2021-03-29 15:39:25 -04:00
dependabot[bot]
49bb5634da Bump pygments from 2.2.0 to 2.7.4
Bumps [pygments](https://github.com/pygments/pygments) from 2.2.0 to 2.7.4.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.2.0...2.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-29 19:20:11 +00:00
eeintech
e6dfb7da52 Added global setting to enable manufacturer parts
Created SourceItem model
Updated templates
2021-03-29 13:22:15 -04:00
eeintech
cbb887ae79 Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part 2021-03-29 10:12:20 -04:00
Oliver Walters
709bfb1bd2 Remove "unique" constraint for part / order relationship 2021-03-30 00:14:47 +11:00
Oliver Walters
217097c9d3 Add custom form template 2021-03-30 00:10:28 +11:00
Oliver Walters
19059ea4cf Tweaks 2021-03-29 23:38:38 +11:00
Oliver Walters
d64dd68403 Agk, working out forms is hard 2021-03-29 23:32:41 +11:00
Oliver Walters
bd87f4c733 Adds form to assign stock item by serial numbers 2021-03-29 23:10:36 +11:00
Oliver
19c03e1472 Merge pull request #1424 from SchrodingersGat/notes-css
HTML / CSS fixes
2021-03-29 17:01:23 +11:00
Oliver Walters
cffe2ba84b Add a separate form for creating a sales order allocation 2021-03-29 16:44:01 +11:00
Oliver Walters
7a4b90649a HTML / CSS fixes 2021-03-29 16:36:27 +11:00
Oliver
88c1bc79d7 Merge pull request #1423 from matmair/translation-de
german translations
2021-03-29 09:12:45 +11:00
Matthias
a3ab70b05d finished german translation, small corrections 2021-03-28 18:09:35 +02:00
Matthias
c558a04162 updated translation reference 2021-03-28 18:08:07 +02:00
Oliver
1ffd3a0070 Merge pull request #1409 from eeintech/fix_stock_ops
Template fix for stock actions
2021-03-28 20:42:14 +11:00
eeintech
e0a0bfdadb Fix style 2021-03-25 15:39:16 -04:00
eeintech
c85d737446 Fix CI 2021-03-25 15:04:48 -04:00
Oliver
5a5e76e0a6 Merge pull request #1414 from inventree/dependabot/pip/djangorestframework-3.11.2
Bump djangorestframework from 3.10.3 to 3.11.2
2021-03-25 17:29:43 +11:00
eeintech
fd4f33d45b More templates updates 2021-03-24 12:39:26 -04:00
eeintech
4abd8587ab Updated company templates 2021-03-24 12:08:45 -04:00
eeintech
afd2dacfc7 Can now create, view list of parts and view detail page 2021-03-24 11:44:51 -04:00
Oliver Walters
3a0c68bf5c Add invoke task to start background worker 2021-03-24 22:42:04 +11:00
Oliver Walters
df0ab2359f Remove invoke tasks which perform system commands
- tasks.py is now for InvenTree specific tasks only
2021-03-24 22:24:47 +11:00
eeintech
e28dde7f7b Fixed navbar, added missing template and urls 2021-03-23 17:45:03 -04:00
eeintech
08ffbee8ed Fixed model name and added to part navbar 2021-03-23 17:33:29 -04:00
Oliver Walters
ce64feb79d Update supervisor conf file 2021-03-24 08:32:00 +11:00
Oliver Walters
e3f49b8996 Install invoke and gunicorn as part of requirements.txt 2021-03-24 08:31:53 +11:00
eeintech
8f610d826f Added URLs and templates 2021-03-23 17:16:29 -04:00
eeintech
e897864396 Added ManufacturerPart model, form and views 2021-03-23 17:01:54 -04:00
Oliver Walters
edbbfff1af Reduce frequency of heartbeat 2021-03-23 19:58:29 +11:00
Oliver Walters
8fd666e662 Improvements for "check for updates" task
- Let it throw an error if something fails
- Errors are caught as "unsuccessful tasks"
2021-03-22 11:20:09 +11:00
dependabot[bot]
f25c83226f Bump djangorestframework from 3.10.3 to 3.11.2
Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.10.3 to 3.11.2.
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.10.3...3.11.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-19 22:23:09 +00:00
Oliver Walters
b7718d9c6c Specify user and logfile 2021-03-19 22:08:11 +11:00
Oliver Walters
283663633a First pass at a supervisor.conf file 2021-03-19 21:52:36 +11:00
Oliver
c9464fd393 Merge pull request #1412 from SchrodingersGat/pillow-version
Bump pillow version
2021-03-19 11:25:10 +11:00
Oliver Walters
84aea1d587 Bump pillow version 2021-03-19 10:59:28 +11:00
Oliver
57289fe141 Merge pull request #1410 from SchrodingersGat/image-downloader
Image downloader
2021-03-18 11:10:07 +11:00
Oliver Walters
9c91ba4692 Add image download functionality for company 2021-03-18 09:20:24 +11:00
Oliver Walters
4e7243b999 Add modal image overlay for company 2021-03-17 23:55:21 +11:00
Oliver Walters
e3a5a56371 Add "modal image" display for part thumbnails 2021-03-17 23:44:47 +11:00
Oliver Walters
db47629867 Cleanup 2021-03-17 23:15:48 +11:00
Oliver Walters
8b310d8e47 Check length of response 2021-03-17 23:11:38 +11:00
Oliver Walters
be30933bfa Add custom form template 2021-03-17 23:06:56 +11:00
Oliver Walters
9a710ca28f Fix image download code 2021-03-17 23:02:32 +11:00
Oliver Walters
47a1143570 Catch error when generating company thumbnail images 2021-03-17 11:55:51 +11:00
Oliver Walters
5f19f534fc Catch error if invalid image is uploaded 2021-03-17 09:47:57 +11:00
Oliver
e2e870858d Merge pull request #1400 from eeintech/ipn_edit_setting
Add setting to disable IPN editing after part is created (web only)
2021-03-17 09:47:39 +11:00
Oliver Walters
15678f789c Add global setting to enable download of files / images from remote URL 2021-03-17 08:40:30 +11:00
Oliver Walters
45edb7e802 Add button 2021-03-17 08:28:38 +11:00
Oliver Walters
5b7d35e6f7 add View 2021-03-17 08:28:28 +11:00
Oliver Walters
3900f9b1b6 Add form for submitting image URL 2021-03-17 08:28:12 +11:00
eeintech
8619af9f09 Template fix for stock actions 2021-03-16 12:32:56 -04:00
eeintech
85474516a3 Merge branch 'master' of github.com:inventree/InvenTree into ipn_edit_setting 2021-03-16 10:23:27 -04:00
Oliver Walters
6946abae13 CSS fix for modal error info dialog 2021-03-16 16:42:33 +11:00
Oliver
5e48009241 Merge pull request #1407 from eeintech/bom_match_headers
Split required and part match headers for BOM import
2021-03-16 08:19:32 +11:00
eeintech
64a57128bc Return True for BOM valid flag if part does not have BOM items 2021-03-15 10:37:30 -04:00
eeintech
d39bd88440 Split required and part match headers for BOM import 2021-03-15 09:41:04 -04:00
eeintech
7b81a470b9 Merge branch 'master' of github.com:inventree/InvenTree into ipn_edit_setting 2021-03-15 08:50:31 -04:00
Oliver
247cbe0154 Merge pull request #1406 from SchrodingersGat/part-pricing-form-error
Add option to hide form error message
2021-03-15 21:01:19 +11:00
Oliver Walters
2de879d2ba Add option to hide form error message 2021-03-15 20:30:18 +11:00
Oliver
b17a50bd51 Merge pull request #1405 from SchrodingersGat/css-tweak
Small tweak for breadcrumb div css
2021-03-15 17:52:14 +11:00
Oliver Walters
9918860820 Small tweak for breadcrumb div css 2021-03-15 17:00:14 +11:00
Oliver Walters
c6e154f996 PEP style fixes 2021-03-15 10:15:48 +11:00
Oliver Walters
c1aed51de1 Fix import error 2021-03-15 09:34:32 +11:00
Oliver Walters
24823adc6d Adds unit tests for version number comparison 2021-03-15 08:51:50 +11:00
Oliver Walters
6ea846ce45 Add a #TODO 2021-03-15 08:36:27 +11:00
Oliver Walters
f6dd710d6e Automatically delete old heartbeat messages 2021-03-15 08:35:06 +11:00
Oliver Walters
de85d61451 Directly compare version tuples, rather than converting to primitive 2021-03-15 08:31:19 +11:00
Oliver
5ff18a0a3a Merge pull request #1403 from matmair/translations-de
unified translation scheme
2021-03-15 08:27:24 +11:00
Oliver
82faccc62f Merge pull request #1401 from eeintech/stock_filter_assembly
Stock filter for parts assemblies
2021-03-13 07:48:15 +11:00
Oliver
59e98bc22d Merge pull request #1402 from eeintech/fix_typo
Fixed build typo
2021-03-13 07:46:11 +11:00
eeintech
acb0b2c10a Fixed build typo 2021-03-12 11:46:56 -05:00
eeintech
429f9d0a13 Removed test print 2021-03-12 11:19:20 -05:00
eeintech
89c7c87f1e Add stock filter for parts assemblies 2021-03-12 11:18:19 -05:00
eeintech
b152f7041b Add setting to disable IPN editing after part is created (web only) 2021-03-12 10:30:31 -05:00
Oliver Walters
700effcee7 Remove celery reference 2021-03-12 16:57:27 +11:00
Oliver Walters
18b559fee7 Fix for unit test 2021-03-12 16:28:54 +11:00
Oliver Walters
9d404afec0 Add 'ignore' rules for the django-q tables 2021-03-12 16:00:25 +11:00
Oliver Walters
51616c8aca Merge remote-tracking branch 'upstream/master' into django-q 2021-03-12 15:47:03 +11:00
Oliver Walters
ef4dbda223 Catch errors if the DB is not up 2021-03-12 15:35:55 +11:00
Oliver Walters
006dd10a79 Delete successful tasks more than a month old 2021-03-12 15:35:33 +11:00
Oliver Walters
5b8eb1c530 Newline 2021-03-12 15:27:53 +11:00
Oliver Walters
bfb0cb3b47 Add a "heartbeat" task which runs every 5 minutes
- Allows us to track if the worker is running
- Due to Stat.get_all() not always working
2021-03-12 15:27:28 +11:00
Oliver
ed028aed62 Merge pull request #1397 from SchrodingersGat/order-report
Order report
2021-03-12 14:44:10 +11:00
Oliver Walters
c07f217416 Add "ignore" rules for new report models 2021-03-12 14:01:20 +11:00
Matthias
47c98db8a1 unified translation scheme 2021-03-11 12:44:28 +01:00
Oliver Walters
4925f24ca9 Add "up to date" info to the "about" window 2021-03-11 20:07:59 +11:00
Oliver Walters
18defcff16 Read version number from GitHub 2021-03-11 19:56:22 +11:00
Oliver Walters
3cf5aec289 Refactor 2021-03-11 19:21:28 +11:00
Oliver Walters
1532a0c3a1 Add InvenTree/apps.py 2021-03-11 17:18:57 +11:00
Oliver Walters
5949ccd74f Bug fix 2021-03-11 17:11:57 +11:00
Oliver Walters
f1ba20c3da Basic PO and SO reports 2021-03-11 15:01:25 +11:00
Oliver Walters
eb6310c774 Render company image to report 2021-03-11 15:01:15 +11:00
Oliver Walters
9d321f4833 Removed 2021-03-11 14:47:45 +11:00
Oliver Walters
e1ba0a9a99 Bug fix for tables 2021-03-11 14:24:28 +11:00
Oliver Walters
8e2a2c59bf Add more context data to reports 2021-03-11 14:19:25 +11:00
Oliver Walters
7ccd339b5c Print reports for multiple selected sales orders / purchase orders 2021-03-11 14:15:31 +11:00
Oliver Walters
fa95759a00 Enable printing for PO and SO 2021-03-11 14:09:57 +11:00
Oliver
23e19614a5 Merge pull request #1394 from mosenturm/translation_de
further translation de
2021-03-10 20:35:50 +11:00
Andreas Kaiser
3897166185 fix typo 2021-03-10 09:48:54 +01:00
Oliver Walters
7800664f4b Add printing endpoints 2021-03-10 18:29:22 +11:00
Oliver
448c3cc6f5 Merge pull request #1395 from SchrodingersGat/responsible-user
Responsible user
2021-03-10 18:27:46 +11:00
Oliver Walters
5a6a12604e Add detail endpoints 2021-03-10 17:13:19 +11:00
Oliver Walters
33e176e4e7 Add list view API endpoints 2021-03-10 17:09:37 +11:00
Oliver Walters
9b0595d232 Add serializers 2021-03-10 16:53:02 +11:00
Oliver Walters
7f05485954 Add new reports to the admin interface 2021-03-10 16:50:55 +11:00
Oliver Walters
727fd38978 Add new report models 2021-03-10 16:48:20 +11:00
Oliver Walters
d559d92f58 Display responsible owner for salesorder and purchaseorder 2021-03-10 16:26:20 +11:00
Oliver Walters
39d44ce32f Add "responsible" field to PO and SO models 2021-03-10 16:19:44 +11:00
Oliver Walters
5b68d82fa3 Skeleton for background tasks 2021-03-10 14:03:19 +11:00
Oliver Walters
660fed9196 Remove unused code from settings.py 2021-03-10 14:03:09 +11:00
Andreas Kaiser
6f63b43c1c Merge branch 'master' into translation_de 2021-03-09 11:14:07 +01:00
Andreas Kaiser
ca626ead6c german translation 2021-03-09 00:45:37 +01:00
Oliver
fb096bd65b Merge pull request #1393 from matmair/german-translations
updated german translations
2021-03-09 10:39:39 +11:00
Matthias
a00756ec3a added all obvious translations 2021-03-08 23:50:24 +01:00
Andreas Kaiser
af0c72d338 german translation 2021-03-08 17:45:22 +01:00
Andreas Kaiser
5ae5b9c0d4 german translation 2021-03-08 16:09:36 +01:00
Andreas Kaiser
48cd227f06 german translation, HTML tags refactored 2021-03-06 21:52:57 +01:00
Andreas Kaiser
ae3a0133eb Merge branch 'master' into translation_de 2021-03-06 13:50:39 +01:00
Oliver Walters
45b3c68930 New status info 2021-03-06 21:41:19 +11:00
Oliver Walters
7bec3ff5dd django-q 2021-03-06 20:58:57 +11:00
Oliver
9ea3193ffb Merge pull request #1391 from SchrodingersGat/order-parts-fix
Hacky fix for ordering parts form
2021-03-06 20:20:30 +11:00
Oliver Walters
8061669c70 Hacky fix for ordering parts form 2021-03-06 19:49:49 +11:00
Andreas Kaiser
ade1d36397 updated german translation, change tags bold italics 2021-03-05 01:03:08 +01:00
Oliver
a4257ad9df Update version.py 2021-03-04 22:52:40 +11:00
Oliver
15ca35ca94 Update version.py 2021-03-04 22:51:32 +11:00
Oliver
c46fe354c2 Merge pull request #1390 from SchrodingersGat/CI-fixes
Hide fields rather than pop, to reduce warnings in CI logs
2021-03-04 22:42:17 +11:00
Oliver Walters
d43cfccfc1 Typo fix 2021-03-04 22:11:38 +11:00
Oliver Walters
5ad915a845 More fields 2021-03-04 22:09:46 +11:00
Oliver Walters
d111e7bff0 Hide fields rather than pop, to reduce warnings in CI logs 2021-03-04 21:42:49 +11:00
Oliver
249860fa76 Merge pull request #1387 from SchrodingersGat/null-fix
Bug fix
2021-03-03 22:16:12 +11:00
Oliver Walters
a9e3e46b8a Bug fix
check if self.object.owner is None
2021-03-03 21:52:02 +11:00
Oliver
fb5d7c415b Merge pull request #1385 from SchrodingersGat/order-filtering
Order filtering
2021-03-03 09:27:40 +11:00
Oliver Walters
979f543c3f Add build orders to search results list 2021-03-03 08:44:13 +11:00
Oliver Walters
14000517ce Fixes for build order table 2021-03-03 08:39:14 +11:00
Oliver Walters
4a28fa7fa8 Fixes for company table 2021-03-03 08:36:16 +11:00
Oliver Walters
339a02a6b2 Bug fix for sorting of sales orders 2021-03-03 08:32:57 +11:00
Oliver Walters
558ea98fa1 Add purchase order and sales order to search results 2021-03-03 08:30:20 +11:00
Oliver Walters
0b15b77140 Fix server-side ordering for purchase order table 2021-03-03 08:13:55 +11:00
Oliver
a53aadd466 Merge pull request #1384 from mosenturm/translation_ak
updated german translation (de)
2021-03-03 08:02:40 +11:00
Andreas Kaiser
3a6f13f259 updated german translation (de) 2021-03-02 17:44:53 +01:00
Oliver
3d4cfcf1b6 Merge pull request #1381 from SchrodingersGat/table-name-fix
Fixes incorrect table name
2021-03-02 22:03:51 +11:00
Oliver Walters
e7e2abf3fc Remove debug prints 2021-03-02 21:34:26 +11:00
Oliver Walters
cd01bb0ad7 Refactor HTML view permission
- Introspect database model from View
- Automatically get the permission from the View class
2021-03-02 21:32:32 +11:00
Oliver Walters
753483e6c2 Use app label rather than table name for permission lookup
- For legacy reasons there are some tables that are not named according to their app_label
- Simply use the app_label instead
2021-03-02 19:34:56 +11:00
Oliver
7f6f489463 Merge pull request #1379 from SchrodingersGat/po-bug-fix
Pagination Bug Fix
2021-03-02 17:15:12 +11:00
Oliver
33f195533e Merge pull request #1380 from SchrodingersGat/label-base
Adds body styling to label base
2021-03-02 16:53:05 +11:00
Oliver Walters
42dfda6d07 Merge remote-tracking branch 'inventree/master' into po-bug-fix 2021-03-02 16:29:12 +11:00
Oliver Walters
7cb712f422 Merge remote-tracking branch 'inventree/master' into label-base
# Conflicts:
#	.travis.yml
2021-03-02 16:28:58 +11:00
Oliver
a2f849d663 Merge pull request #1382 from SchrodingersGat/linter-fix
Remove django-migration-linter which was causing strange errors
2021-03-02 16:28:10 +11:00
Oliver Walters
9478da2ad2 Remove django-migration-linter which was causing strange errors 2021-03-02 15:53:56 +11:00
Oliver Walters
f6e982ce81 Fixes incorrect table name 2021-03-02 15:34:45 +11:00
Oliver Walters
bc25e795dd Shorten git hash 2021-03-02 14:34:20 +11:00
Oliver Walters
2cf87c1c30 Adds body styling to label base 2021-03-02 14:05:52 +11:00
Oliver Walters
628e87cb28 search field fixes 2021-03-02 13:08:12 +11:00
Oliver Walters
6f4178acdb Improve server-side pagination for POLineItem 2021-03-02 12:38:37 +11:00
Oliver Walters
1c3b017283 Improve server-side pagination of SalesOrderLineItem 2021-03-02 12:33:41 +11:00
Oliver Walters
4ff1c690cc Bug fix for paginated tables 2021-03-02 12:33:01 +11:00
Oliver
7cf1715e2b Merge pull request #1374 from eeintech/dark-reader
Dark Reader color theme update
2021-03-02 10:45:56 +11:00
Oliver
197682635e Merge pull request #1377 from SchrodingersGat/nav-tree-fix
Fix incorrect javascript call
2021-03-02 10:45:31 +11:00
eeintech
a85ac6161e Removed binary SVG images from CSS 2021-03-01 16:19:16 -05:00
Oliver Walters
478dce449d Fix incorrect javascript call 2021-03-02 08:07:18 +11:00
eeintech
36c7528aeb Removed absolute static URLs 2021-03-01 11:00:42 -05:00
eeintech
374860c914 Updated Dark Reader color theme 2021-03-01 10:48:37 -05:00
Oliver
278466e830 Update README.md 2021-03-01 14:49:13 +11:00
Oliver
7aed696451 Merge pull request #1373 from SchrodingersGat/server-pagination
Server pagination
2021-03-01 13:31:50 +11:00
Oliver Walters
b7cf57c875 PEP fix 2021-03-01 11:38:52 +11:00
Oliver Walters
9f9629edb3 Fix for unit test 2021-03-01 11:21:18 +11:00
Oliver Walters
b157690ae0 Add API version to server info endpoint 2021-03-01 11:15:53 +11:00
Oliver Walters
34def10765 Delete un-needed code 2021-02-28 21:44:10 +11:00
Oliver Walters
04dbfbd892 Fix for stock item tracking table 2021-02-28 20:50:19 +11:00
Oliver Walters
3dad86f004 Actually just enable (optional) pagination for every list endpoint 2021-02-28 20:45:41 +11:00
Oliver Walters
44635d2499 Use server-side pagination for more list endpoints 2021-02-28 20:35:32 +11:00
Oliver Walters
90feb6d210 Server-side paginatino for build orders 2021-02-28 20:31:01 +11:00
Oliver Walters
1239d4af16 Fixes result limiting
- Required for index page
2021-02-28 20:16:05 +11:00
Oliver Walters
487794a938 Server side pagination for the part list 2021-02-28 16:29:25 +11:00
Oliver Walters
8ce7b572cc Optionally paginate the StockList table on the server
- This makes the bootstrap table interface SO FREAKING MUCH FASTER
- Search is now performed on the server too!
2021-02-28 16:18:45 +11:00
Oliver
45791c0257 Merge pull request #1372 from SchrodingersGat/sidenav-fix
Refactor side navigation tree
2021-02-28 13:29:50 +11:00
Oliver Walters
6f2ba71339 Refactor side navigation tree 2021-02-28 11:48:20 +11:00
Oliver
5cdae04c62 Merge pull request #1371 from SchrodingersGat/api-404
Adds "404" response when asking for an API endpoint that does not exist
2021-02-28 07:34:34 +11:00
Oliver Walters
19c76f7842 Include 404 URL in response 2021-02-27 22:44:38 +11:00
Oliver Walters
5069882a7f URL tweaks 2021-02-27 22:41:36 +11:00
Oliver Walters
0b9cb507c7 Redirect invalid API urls to a 404 page 2021-02-27 22:38:08 +11:00
Oliver
732388c7d3 Merge pull request #1370 from SchrodingersGat/stock-adjust-permissions
Fix API permissions for stock adjustment
2021-02-27 22:25:55 +11:00
Oliver Walters
f1c8c48d35 Fix API permissions for stock adjustment 2021-02-27 20:17:52 +11:00
Oliver
d5597a3dca Merge pull request #1363 from SchrodingersGat/api-permissions
Api permissions
2021-02-27 08:39:47 +11:00
Oliver
4b147e86ce Merge pull request #1368 from SchrodingersGat/hide-stock-buttons
Hide stock buttons on top-level stock location display
2021-02-27 08:39:25 +11:00
Oliver Walters
b6d87850dc Hide stock buttons on top-level stock location display 2021-02-27 08:00:00 +11:00
Oliver Walters
b315b958b0 PEP fixes 2021-02-27 07:56:38 +11:00
Oliver Walters
5a536be22d More test refactoring 2021-02-26 22:08:06 +11:00
Oliver Walters
d76b873c00 Refactor build API unit tests 2021-02-26 22:00:22 +11:00
Oliver Walters
9d099c81a7 Refactor API tests for stock 2021-02-26 21:53:54 +11:00
Oliver Walters
ee744be5fe Refactor API unit tests for part 2021-02-26 21:45:37 +11:00
Oliver Walters
6e3cb326fb Use better introspection, no longer required "role_required" 2021-02-26 21:36:40 +11:00
Oliver Walters
0f6cdd0037 Improve unit testing for new role endpoint 2021-02-26 21:04:09 +11:00
Oliver Walters
aad92902f2 Unit tests for new role view 2021-02-26 20:37:12 +11:00
Oliver Walters
2460965fef Add some more context data 2021-02-26 17:55:56 +11:00
Oliver Walters
5c61c18dc4 Add API endpoint which provides list of role permissions available to current user 2021-02-26 17:52:06 +11:00
Oliver Walters
cd5bc395f2 PEP fixes 2021-02-26 16:03:38 +11:00
Oliver Walters
20740035e8 Add role to API endpoints in 'part' app 2021-02-26 14:37:50 +11:00
Oliver Walters
81e9fd7a44 Escape hatch if role not required 2021-02-26 14:26:37 +11:00
Oliver Walters
0e971c468b Remove test code 2021-02-26 14:07:18 +11:00
Oliver Walters
36359fc547 RolePermission is now default for API endpoints 2021-02-26 14:05:26 +11:00
Oliver Walters
cd8c6fa81a Add RolePermission for API endpoints 2021-02-26 13:53:23 +11:00
Oliver Walters
1dfda5b0ed Fix display for top-level category 2021-02-26 13:03:03 +11:00
Oliver
414a981858 Merge pull request #1361 from SchrodingersGat/multi-bom-delete
Refactor multi-bom deletion
2021-02-26 11:15:51 +11:00
Oliver Walters
12c2ea3b37 Refactor multi-bom deletion 2021-02-26 10:54:54 +11:00
Oliver
44f5e0907e Merge pull request #1359 from SchrodingersGat/api-star
Simplify process for marking a part as "starred"
2021-02-25 23:51:45 +11:00
Oliver Walters
f2da1c990b Simplify process for marking a part as "starred" 2021-02-25 23:27:27 +11:00
Oliver
35b9b17167 Merge pull request #1354 from SchrodingersGat/tree-fix
Sidenav Fixes
2021-02-25 09:45:56 +11:00
Oliver Walters
bb03f2bd58 CSS fixes 2021-02-25 09:22:02 +11:00
Oliver Walters
26e80fa0ab Fancify all the menubars 2021-02-25 09:10:20 +11:00
Oliver Walters
fe42d5c54d Cleanup display for part 2021-02-24 21:58:40 +11:00
Oliver Walters
a451de3735 Update translations 2021-02-24 21:53:23 +11:00
Oliver Walters
ef84b98a89 Build view now uses menubar 2021-02-24 21:52:26 +11:00
Oliver Walters
48d2a395de Part Category now uses menubar display 2021-02-24 21:39:45 +11:00
Oliver Walters
a0eec930bb Cleanup 2021-02-24 21:30:55 +11:00
Oliver Walters
89bdfd1c62 StockItem display now uses menubar 2021-02-24 21:27:44 +11:00
Oliver Walters
888fd4116c SupplierPart display now uses menubar display style 2021-02-24 21:12:41 +11:00
Oliver Walters
5525b23b9f Company view now uses menubar 2021-02-24 20:31:48 +11:00
Oliver Walters
3210af31b4 Sales order now uses menubar 2021-02-24 20:17:25 +11:00
Oliver Walters
213851e8aa Purchase Order now uses menu bar 2021-02-24 20:01:05 +11:00
Oliver Walters
bedfaa582c Update "part" display to use new menubar 2021-02-24 17:58:43 +11:00
Oliver Walters
2a7b32d4f4 Part display tweaks 2021-02-24 16:37:32 +11:00
Oliver
3b03d45f1f Merge pull request #1355 from SchrodingersGat/search-fields
Allow searching part by revision field
2021-02-24 13:04:06 +11:00
Oliver Walters
546a1c91cc Allow searching part by revision field 2021-02-24 11:05:52 +11:00
Oliver Walters
a660578262 Move part menu to the left 2021-02-24 11:02:11 +11:00
Oliver Walters
15a59d54ca Abstract template context data for part 2021-02-24 09:05:31 +11:00
Oliver Walters
edb803bf67 Make part menu 'sticky' 2021-02-23 21:58:28 +11:00
Oliver Walters
2e87499fa5 Basic right-side menu for part 2021-02-23 21:51:41 +11:00
Oliver Walters
68f24e97ac Make tree sidenav resizable 2021-02-23 21:09:55 +11:00
Oliver Walters
0016628b41 Keep tree items constrained to a single line 2021-02-23 19:38:28 +11:00
Oliver
8cc904fe8a Merge pull request #1352 from SchrodingersGat/bug-fix
Bug fix for trackable parts
2021-02-23 18:01:56 +11:00
Oliver
2c85d630f7 Merge pull request #1353 from SchrodingersGat/regex-search-fix
Remove regex search functionality from part api
2021-02-23 18:01:48 +11:00
Oliver Walters
15275d24b4 Better CSS for side nav bars 2021-02-23 18:01:42 +11:00
Oliver Walters
a48be3bea9 Remove regex search functionality from part api 2021-02-23 16:57:17 +11:00
Oliver Walters
b64d48544d Bug fix for trackable parts 2021-02-23 16:49:09 +11:00
Oliver
ad7a70f033 Merge pull request #1351 from SchrodingersGat/report-filter-fix
Bug fix for label / report filtering
2021-02-23 16:02:29 +11:00
Oliver Walters
8c9202de21 Bug fix for label / report filtering 2021-02-23 15:40:31 +11:00
Oliver
94c8bb6805 Merge pull request #1350 from SchrodingersGat/recently-updated
Adds "Recently Updated Stock" to index page
2021-02-23 14:47:24 +11:00
Oliver Walters
648d322f54 Style fixes 2021-02-23 14:24:09 +11:00
Oliver Walters
8717be66fc Configure number of "recent items" shown on index page 2021-02-23 14:15:12 +11:00
Oliver Walters
8972a51bd6 Fixes for integer validator for inventree setting 2021-02-23 14:12:16 +11:00
Oliver
333d6dd1b8 Merge pull request #1348 from SchrodingersGat/supplier-part-admin
Adds "admin" button to supplier part page
2021-02-23 13:43:51 +11:00
Oliver
615e2f8271 Merge pull request #1349 from SchrodingersGat/used-in-filter
Enable filtering for "used in" table
2021-02-23 13:43:45 +11:00
Oliver Walters
571a03043e Show recently updated stock items on the index page 2021-02-23 13:43:41 +11:00
Oliver Walters
949a541ee0 Add more options to StockList api
- Limit query results
- Order by various fields
2021-02-23 13:43:26 +11:00
Oliver Walters
66e1b180e4 Add option to stock table to disable grouping at run-time 2021-02-23 13:42:59 +11:00
Oliver Walters
39d4ddd845 Enable filtering for "used in" table 2021-02-23 13:23:23 +11:00
Oliver Walters
5a58e0a298 Adds "admin" button to supplier part page 2021-02-23 13:16:03 +11:00
Oliver
791b14920a Merge pull request #1347 from SchrodingersGat/variant-stock-tab
Display stock tab for virtual parts
2021-02-23 12:23:01 +11:00
Oliver Walters
041f056116 Display stock tab for virtual parts 2021-02-23 10:40:52 +11:00
Oliver
4dc093662d Merge pull request #1344 from SchrodingersGat/sub-build-table
Build: Filter by parent or ancestor in API
2021-02-23 09:46:51 +11:00
Oliver Walters
832a6ef9a2 PEP fixes 2021-02-23 09:01:03 +11:00
Oliver Walters
58863b1924 Show child builds 2021-02-22 22:35:54 +11:00
Oliver Walters
c1dd5b1ca1 Add "child build" page 2021-02-22 22:21:46 +11:00
Oliver Walters
2186a66465 Build: Filter by parent or ancestor in API
- Add unit testing
2021-02-22 22:05:20 +11:00
Oliver
b8327a5531 Merge pull request #1342 from SchrodingersGat/label-improvements
Label improvements
2021-02-22 19:45:11 +11:00
Oliver
613776fbe5 Merge pull request #1343 from SchrodingersGat/part-annotate
Adds 'suppliers' field to Part serializer
2021-02-22 19:45:02 +11:00
Oliver Walters
199ba27031 PEP!!! 2021-02-22 18:44:59 +11:00
Oliver Walters
cf6a03456f Adds 'suppliers' field to Part serializer
- Number of supplier parts associated with the Part object
2021-02-22 18:44:31 +11:00
Oliver Walters
28e9aa4afa More unit fixes 2021-02-22 18:11:40 +11:00
Oliver Walters
9159afe9ce Unit test fix 2021-02-22 17:27:48 +11:00
Oliver
5d1e6981d8 Merge pull request #1341 from SchrodingersGat/variant-table-fix
Fixes weird variant display
2021-02-22 17:21:34 +11:00
Oliver Walters
7582b9ccf4 PEP fixes 2021-02-22 17:02:33 +11:00
Oliver Walters
9fe9cbc795 Fixes weird variant display
- Seems like the double import was at fault (somehow??)
2021-02-22 16:57:33 +11:00
Oliver Walters
7d54997cb8 Tweaks 2021-02-22 16:48:00 +11:00
Oliver Walters
bf51e1bfb1 Update label templates
- New ones are automatically copied across now
2021-02-22 16:39:38 +11:00
Oliver Walters
da715d7381 Refactoring label printing 2021-02-22 16:12:13 +11:00
Oliver Walters
caf4c293d9 Rename "barcode" module to "barcodes" to prevent import shadowing
- Add 'barcode' support
2021-02-22 15:15:25 +11:00
Oliver Walters
23da591c22 Remove old dependency on django_qr_code 2021-02-22 15:00:12 +11:00
Oliver Walters
828b3adc49 Update requirements.txt
- Remove blabel
- Remove django-qr-code
- Add python-barcode
- Add qrcode
2021-02-22 14:40:40 +11:00
Oliver Walters
a742df2c12 Adds 'length' and 'width' fields to label models 2021-02-22 10:10:58 +11:00
Oliver
ad6c69ecc7 Merge pull request #1336 from SchrodingersGat/app-info
Add app info to about dialog
2021-02-22 08:59:23 +11:00
Oliver Walters
89cdcda614 Add app info to about dialog 2021-02-22 01:10:11 +11:00
Oliver
beb155133a Update version.py 2021-02-21 21:50:52 +11:00
Oliver
2ac9eadd13 Update version.py 2021-02-21 21:49:38 +11:00
Oliver
d426e376c4 Merge pull request #1333 from SchrodingersGat/cleaner-homepage
Cleaner homepage
2021-02-21 21:36:28 +11:00
Oliver Walters
2b1101e165 remove unused files 2021-02-21 21:09:55 +11:00
Oliver Walters
afd7199a69 Cleanup search page too 2021-02-21 21:06:52 +11:00
Oliver Walters
745188082b Add more searchable fields to SupplierPart model 2021-02-21 21:06:44 +11:00
Oliver Walters
e53c6e9975 Fancy 2021-02-21 20:29:48 +11:00
Oliver
cc2b672117 Merge pull request #1335 from SchrodingersGat/stock-filter
Add option to filter out variants in stock table
2021-02-21 20:28:30 +11:00
Oliver Walters
d11adf3b34 fade in 2021-02-21 20:18:14 +11:00
Oliver Walters
dffff89e9d Add option to filter out variants in stock table 2021-02-21 20:08:23 +11:00
Oliver Walters
9d12d43574 Cleanup / refactor 2021-02-19 18:10:10 +11:00
Oliver Walters
116ea65160 Show / hide panels 2021-02-19 17:57:38 +11:00
Oliver Walters
6df6a460e4 Add items using javascript 2021-02-19 17:48:32 +11:00
Oliver
b95d6a4ab2 Merge pull request #1327 from SchrodingersGat/installed-test-results
Read test results from installed items
2021-02-19 16:49:51 +11:00
Oliver Walters
6037f1452a Unit testing for new feature 2021-02-19 15:50:32 +11:00
Oliver Walters
beeb94785d Add option for TestReport to include tests for installed items 2021-02-19 15:50:25 +11:00
Oliver
e02fb8c8fa Merge pull request #1332 from SchrodingersGat/destroyed-stock-adjust
Allow adjustment for destroyed (or lost) stock
2021-02-19 15:40:10 +11:00
Oliver Walters
ea4b713eed Allow adjustment for destroyed (or lost) stock 2021-02-19 15:13:56 +11:00
Oliver
ca16e4f35d Merge pull request #1330 from SchrodingersGat/supplier-part-packaging
Display supplier part packaging
2021-02-19 15:02:34 +11:00
Oliver Walters
ba71ce941f Display supplier part packaging 2021-02-19 14:34:21 +11:00
Oliver
5b549b8dea Merge pull request #1329 from SchrodingersGat/stock-packaging
Stock packaging
2021-02-19 12:52:38 +11:00
Oliver Walters
098b494047 Add option to disable stock item grouping 2021-02-19 11:31:38 +11:00
Oliver Walters
e8bacbe45f Edit packaging field 2021-02-19 11:11:22 +11:00
Oliver Walters
644583f636 Display packaging info in stock table 2021-02-19 11:09:24 +11:00
Oliver Walters
556d6455e8 Add "packaging" field for StockItem 2021-02-19 11:08:58 +11:00
Oliver Walters
a9f255be85 Prevent stock item being added as an installed item inside itself 2021-02-18 18:01:41 +11:00
Oliver Walters
ef23ab1abc Adds functionality for traversing "through" installed items to extract test results 2021-02-18 17:59:04 +11:00
Oliver
cdb3dd2aa5 Merge pull request #1325 from SchrodingersGat/build-bom-view
Adds "required parts" tab to build view
2021-02-18 17:58:20 +11:00
Oliver Walters
0c053c6339 Add action buttons to order or build stock 2021-02-18 17:25:39 +11:00
Oliver Walters
bfbcbe252b Adds "required parts" tab to build view 2021-02-18 17:14:57 +11:00
Oliver
8cb3d6ab0a Merge pull request #1321 from SchrodingersGat/next-build-order
Logic fix for "guessing" next build order number
2021-02-18 16:08:58 +11:00
Oliver Walters
43a7359501 Logic fix for "guessing" next build order number 2021-02-18 15:44:43 +11:00
Oliver
d2d842163d Merge pull request #1320 from SchrodingersGat/inherited-bom-used-in
Implement filtering which accommodates new inheritable BOM feature
2021-02-18 15:19:15 +11:00
Oliver Walters
0f60482e09 Add secondary dialog for creating new supplier 2021-02-18 14:59:13 +11:00
Oliver Walters
1b73f56937 modal content wrapper for secondary modal 2021-02-18 14:56:35 +11:00
Oliver Walters
e75b9d04fe PEP fix 2021-02-18 14:38:25 +11:00
Oliver Walters
7a51e6cf78 Implement filtering which accommodates new inheritable BOM feature
- Can no longer filter bom_items by sub_part
- Adds get_used_in_filter() and get_used_in() for part model (returns a query of other part objects)
2021-02-18 14:35:21 +11:00
Oliver
25ada20a19 Merge pull request #1315 from SchrodingersGat/copy-bom-fix
Fix for duplicating BOM
2021-02-18 08:22:05 +11:00
Oliver Walters
07ee27ad9b Another CSS tweak 2021-02-18 00:49:36 +11:00
Oliver Walters
3822b60bb0 CSS tweaks 2021-02-18 00:49:16 +11:00
Oliver Walters
abe1018abe Add new fields to BOM item hash 2021-02-18 00:40:30 +11:00
Oliver Walters
8caf6bad10 Fix for duplicating BOM
- Do not duplicate bom items which are "inherited"
2021-02-18 00:38:40 +11:00
Oliver
bf63005731 Merge pull request #1313 from SchrodingersGat/inherited-bom-items
Inherited bom items
2021-02-18 00:30:52 +11:00
Oliver Walters
3f30421ba9 bug fix 2021-02-17 23:57:45 +11:00
Oliver Walters
ef902fc313 Add bom_items to build order report context 2021-02-17 23:27:09 +11:00
Oliver Walters
bb3440a8a4 Refactor bom item filter
- Also updates a number of part functions to make use of inherited BOM items
2021-02-17 22:53:56 +11:00
Oliver Walters
1eb2456e3d Display inherited rows a bit differenter 2021-02-17 22:25:43 +11:00
Oliver Walters
5b402b6bc0 BOM table formatting
- Display link to external BOM
- Prevent item from being edited to selected
2021-02-17 22:18:32 +11:00
Oliver Walters
43eba3f7ec Add ability to include bom items inherited from parent parts in the API list 2021-02-17 22:05:17 +11:00
Oliver Walters
40d75090a7 Add 'inherited' flag to API 2021-02-17 21:53:26 +11:00
Oliver Walters
d692c18274 Add 'inherited' field to BomItem 2021-02-17 21:53:15 +11:00
Oliver
69708b842c Merge pull request #1309 from SchrodingersGat/order-requirement
Order requirement
2021-02-17 14:42:17 +11:00
Oliver Walters
afc33c59ea bug fix 2021-02-17 14:13:56 +11:00
Oliver Walters
08cc866e74 Add function to make barcode for build order 2021-02-17 13:47:14 +11:00
Oliver Walters
98bd7dfa9a Style fixes 2021-02-17 13:16:15 +11:00
Oliver Walters
fcc35f2260 Fix display of parts currently being built 2021-02-17 13:14:27 +11:00
Oliver Walters
ba542dcbdb Auto-fill build quantity 2021-02-17 13:06:18 +11:00
Oliver Walters
c8650ce34c Bug fix for tables 2021-02-17 13:05:58 +11:00
Oliver Walters
8780b8435a style fix 2021-02-17 12:46:05 +11:00
Oliver Walters
34df19242c Adds more context data 2021-02-17 11:08:11 +11:00
Oliver Walters
28c9c80f54 Calculate quantity required for sales orders
- Cache data going to part detail view
2021-02-17 10:57:17 +11:00
Oliver Walters
cda97829ab Add function for required build order quantity 2021-02-17 10:27:36 +11:00
Oliver
d2c9f759b1 Merge pull request #1305 from SchrodingersGat/incorrect-login-fix
Add message if username / password combo is rejected
2021-02-17 07:37:08 +11:00
Oliver Walters
baa352ca98 Add message if username / password combo is rejected 2021-02-16 22:34:24 +11:00
Oliver
a444f21e64 Merge pull request #1292 from SchrodingersGat/bom-report
BOM report
2021-02-16 21:32:28 +11:00
Oliver Walters
6b48f0db43 Unit test fixes 2021-02-16 20:56:18 +11:00
Oliver Walters
7071ef5a5c Fixes for build report template 2021-02-16 20:53:28 +11:00
Oliver Walters
7d30e75bc6 Display images in report debug mode 2021-02-16 20:40:09 +11:00
Oliver Walters
46f20593c5 Add default build order report
Toot toot refactor tractor
2021-02-16 20:39:07 +11:00
Oliver Walters
f87b15e4ea Refactoring 2021-02-16 20:14:13 +11:00
Oliver Walters
b09e9c0781 Fixes for URL generation 2021-02-16 17:16:36 +11:00
Oliver Walters
fdca3d842d Add report function for generating an internal link 2021-02-16 16:45:13 +11:00
Oliver Walters
81cac0927d Layout tweask 2021-02-16 16:04:24 +11:00
Oliver Walters
a416c56e5a pre-fill 'issued_by' user 2021-02-16 15:55:09 +11:00
Oliver Walters
a722057dab Display responsible and issuing users for build orders 2021-02-16 15:46:18 +11:00
Oliver Walters
31a8c94d2f Adds 'issued_by' and 'responsible' field to BuildOrder
- issued_by is a user
- responsible is a user or a group
2021-02-16 15:40:27 +11:00
Oliver Walters
6cc0880b4a Add INVENTREE_BASE_URL setting
- Also adds callable validator!
2021-02-16 15:31:04 +11:00
Oliver Walters
247c4bdb4b Print multiple build reports 2021-02-16 08:45:28 +11:00
Oliver Walters
b222119653 Add option to print build report 2021-02-16 08:36:04 +11:00
Oliver Walters
e72aaf2e07 PEP fixes 2021-02-16 08:25:52 +11:00
Oliver Walters
a349e77866 Adds model for BuildReport
- List / Detail / Print
2021-02-16 08:25:04 +11:00
Oliver
4431082440 Merge pull request #1294 from SchrodingersGat/login-static-files
Allow access to static files without being logged in
2021-02-13 19:48:27 +11:00
Oliver Walters
e0db833038 Rotated splash image for better handling of portrait view 2021-02-13 16:50:51 +11:00
Oliver Walters
39d9ecffec Add image attribution (need to work out how to make it more obvious) 2021-02-13 13:52:35 +11:00
Oliver Walters
99578e6986 Getting a little bit fancy 2021-02-13 13:49:21 +11:00
Oliver Walters
10e50cf5e4 Allow access to static files without being logged in 2021-02-13 12:19:10 +11:00
Oliver
998620b5f3 Merge pull request #1290 from SchrodingersGat/modal-css-fixes
Modal form CSS fixes
2021-02-12 21:32:46 +11:00
Oliver
16692a2905 Merge pull request #1288 from SchrodingersGat/part-table-fix
Remove code which was causing issue
2021-02-12 21:32:40 +11:00
Oliver
67b6123b70 Merge pull request #1289 from SchrodingersGat/null-units
Hide units when empty
2021-02-12 21:32:33 +11:00
Oliver Walters
e8fd336612 Fix getSubdir function 2021-02-12 21:32:26 +11:00
Oliver Walters
11099676ef Dialog for printing BOM reports 2021-02-12 21:23:56 +11:00
Oliver Walters
4e9b9ee6fd Detail and print view for the BOM report 2021-02-12 21:15:03 +11:00
Oliver Walters
9be2989971 Refactor printing code into ReportPrintMixin 2021-02-12 21:08:33 +11:00
Oliver Walters
a1cf893eb2 List API endpint for BOM reports 2021-02-12 20:55:13 +11:00
Oliver Walters
ba85ff63bf Refactor selectTestReport into selectReport 2021-02-12 20:38:30 +11:00
Oliver Walters
12821b80fb Add BOMReport model 2021-02-12 20:28:12 +11:00
Oliver Walters
19143ed082 Modal form CSS fixes 2021-02-12 20:13:17 +11:00
Oliver Walters
b22b82877d Hide units when empty 2021-02-12 20:01:09 +11:00
Oliver Walters
efc2290613 Remove code which was causing issue 2021-02-12 19:57:44 +11:00
Oliver
b43d6a2ad4 Merge pull request #1284 from eeintech/backup_restore
Added inv restore command
2021-02-11 09:25:49 +11:00
eeintech
d6eae83809 Added inv restore command 2021-02-10 10:55:04 -05:00
Oliver
89adac49f9 Merge pull request #1283 from SchrodingersGat/filter-validation
Wrap custom filter validation in try/except blocks
2021-02-10 21:20:03 +11:00
Oliver Walters
2fa7c8706b Wrap custom filter validation in try/except blocks 2021-02-10 20:40:15 +11:00
Oliver
9385447761 Merge pull request #1279 from SchrodingersGat/default-page-size
Default page size
2021-02-06 18:42:38 +11:00
Oliver Walters
a5c36e2ca8 Update scheme for inventree test report
- Copy across a simpler report which extends the "base" report
- This way the InvenTree report version is always up to date!
2021-02-06 18:07:27 +11:00
Oliver Walters
ef31727ec9 Would you like some PEPper with that? 2021-02-06 17:58:21 +11:00
Oliver Walters
30d95e1511 Add 'REPORT_DEBUG_MODE' setting
- If set, reports are printed in raw HTML
- Not pretty, but useful for debugging output of rendered template
2021-02-06 17:36:22 +11:00
Oliver Walters
dbaa0fc300 Add default page size for reports
- A4 / Legal / Letter
- Use this for the default page size for InvenTree reports
2021-02-06 17:11:20 +11:00
Oliver
2aa2f08658 Merge pull request #1275 from SchrodingersGat/report-revision
Report revision
2021-02-05 14:58:19 +11:00
Oliver Walters
b5e993872f Keep asset and snippet filenames the same (if possible) 2021-02-05 13:51:25 +11:00
Oliver Walters
d686fb5057 Fix typo in js file 2021-02-05 12:31:13 +11:00
Oliver Walters
f458342e5f Add report revision information to the template context 2021-02-05 12:02:16 +11:00
Oliver Walters
33d66182df Add "revision" number to report model
- Auto-increments whenever the model is saved
2021-02-05 12:01:44 +11:00
Oliver
af7a627230 Merge pull request #1271 from SchrodingersGat/migration-unit-test
Migration unit test
2021-02-04 23:56:12 +11:00
Oliver Walters
978ea7cc0b Typo fix 2021-02-04 23:11:19 +11:00
Oliver Walters
3c5169c793 So I learned something today...
In migration files you can access the "historical" pythonic model, and use that, with *all* the helpers,
rather than writing clunky old SQL!!!!

:'(
2021-02-04 23:10:10 +11:00
Oliver Walters
74704a7c1e Mark migrations with data operations "non atomic"
Ref: https://docs.djangoproject.com/en/dev/howto/writing-migrations/#non-atomic-migrations
2021-02-04 22:19:15 +11:00
Oliver
4d91a34136 Merge pull request #1270 from SchrodingersGat/report-templates
Adds "report snippet" class allowing re-usable report snippets
2021-02-04 22:14:38 +11:00
Oliver Walters
140c8b5395 Use integer field instead of boolean literal (not correct SQL) 2021-02-04 21:33:10 +11:00
Oliver Walters
62a7964dda PEP fixes 2021-02-04 21:17:20 +11:00
Oliver Walters
a0e7d37a19 Add setting for enabling / disabling test reports 2021-02-04 21:15:19 +11:00
Oliver Walters
5aec487c12 TestReport name no longer needs to be unique 2021-02-04 21:15:07 +11:00
Oliver Walters
bc36775270 Copy default test report across 2021-02-04 20:25:01 +11:00
Oliver Walters
98d291c2f8 Add model rule for ReportSnippet 2021-02-04 19:26:43 +11:00
Oliver Walters
59904ace1d Revoke support for LaTex reporting 2021-02-04 16:18:28 +11:00
Oliver Walters
264bd625d3 Remove debug string 2021-02-04 16:13:03 +11:00
Oliver Walters
0de284f1aa Unit fixes 2021-02-04 16:06:01 +11:00
Oliver Walters
6ebebe03d4 Simplify report snippet class definition 2021-02-04 15:38:41 +11:00
Oliver Walters
a025b7239d Adds simple test-report template 2021-02-04 15:29:46 +11:00
Oliver Walters
ddbf2a6313 Add margin callouts for report template base 2021-02-04 14:49:11 +11:00
Oliver Walters
cf0c43d899 Add report base template 2021-02-04 13:54:26 +11:00
Oliver Walters
6230fb3614 Add custom report template tags 2021-02-04 13:41:47 +11:00
Oliver Walters
801b945438 Add current date to report context 2021-02-04 13:33:14 +11:00
Oliver Walters
3ccc500e8e Add more context data to report 2021-02-04 12:58:19 +11:00
Oliver Walters
b107c54eb2 PEP fix 2021-02-04 09:13:45 +11:00
Oliver Walters
cabac6614c Add unit test for currency migration 2021-02-04 09:13:23 +11:00
Oliver Walters
e407b99d0d Add initial migration unit test for the 'part' app 2021-02-04 09:13:11 +11:00
Oliver Walters
d811f3c48a Typo fix
(cherry picked from commit c58399206c)
2021-02-04 08:39:27 +11:00
Oliver Walters
93f0dbd4ee Bug fix: add missing line
(cherry picked from commit 2303e03580)
2021-02-04 08:39:20 +11:00
Oliver Walters
ad0b59bf11 Bug fxi
(cherry picked from commit 0e11b722be)
2021-02-04 08:39:14 +11:00
Oliver Walters
b284fe7f2b Remove quotes around column names
(cherry picked from commit 386cb2dd3a)
2021-02-04 08:39:05 +11:00
Oliver Walters
75431f0ee4 Flake errors 2021-02-04 00:51:00 +11:00
Oliver Walters
e417ff2b4d Test migrations for build app 2021-02-04 00:44:37 +11:00
Oliver Walters
29bb735dc4 Helper functions to automatically extract migration file info 2021-02-04 00:25:00 +11:00
Oliver Walters
5c8e65c285 Only run linter checks for *new* migration files 2021-02-04 00:01:16 +11:00
Oliver Walters
f135f11564 Run lint checks on migration files 2021-02-03 23:56:59 +11:00
Oliver Walters
c2b5d96186 Ensure migration files are covered in coverage tests 2021-02-03 23:39:43 +11:00
Oliver Walters
bd9447d9aa Add django-migration-linter to ensure django migrations are tippy-top 2021-02-03 23:29:14 +11:00
Oliver Walters
34dbfe6d28 Test troublesome migration 0019 2021-02-03 23:16:23 +11:00
Oliver Walters
1d317b1ecb Add django-test-migrations package 2021-02-03 23:16:00 +11:00
Oliver Walters
cbadb2a888 Small refactor, and allow editing of ReportAsset in the admin interface 2021-02-03 21:54:11 +11:00
Oliver Walters
90bef69a59 Adds "report snippet" class allowing re-usable report snippets to be uploaded 2021-02-03 16:58:06 +11:00
Oliver
79ddea50f5 Merge pull request #1267 from SchrodingersGat/migration-fixes
Migration fixes
2021-02-03 14:48:21 +11:00
Oliver Walters
5e9097b5e0 PSQL: Upper-case column names *must* be qualified with double-quotes
Ref: https://www.xspdf.com/resolution/53039249.html
2021-02-03 13:16:32 +11:00
Oliver Walters
0e246a7fdf Migration fix (response is different for postgresql) 2021-02-03 13:02:28 +11:00
Oliver Walters
793e5b820e Remove all model references from migration file 2021-02-03 11:56:48 +11:00
Oliver Walters
bc43d14ebf Change model functions to raw SQL 2021-02-03 11:28:43 +11:00
Oliver Walters
f798537c73 Reverse migration company.0024 2021-02-03 09:52:59 +11:00
Oliver
65791a2b9b Merge pull request #1255 from SchrodingersGat/simple-qr-codes
Default to using "simple" QR codes
2021-02-01 13:37:42 +11:00
Oliver Walters
43e03ed023 Update unit tests 2021-02-01 12:26:58 +11:00
Oliver Walters
7d38507785 Merge remote-tracking branch 'inventree/master' into simple-qr-codes 2021-02-01 12:24:16 +11:00
Oliver
3449848682 Merge pull request #1266 from SchrodingersGat/barcode-data-fix
Limit barcode hash to printable characters.
2021-01-31 22:29:19 +11:00
Oliver Walters
97140b19ba Limit barcode hash to printable characters.
This is a dirty filthy hack, as the web-input strips non printable chars when they are typed in (but will accept them if they are copy-pasted)
2021-01-31 21:45:34 +11:00
Oliver
27b8928a10 Merge pull request #1263 from SchrodingersGat/table-translations
Table translations
2021-01-30 09:48:47 +11:00
Oliver
cb81d8b66a Merge pull request #1262 from SchrodingersGat/hide-barcode-button
Hide main QR button if setting is disabled
2021-01-29 13:06:48 +11:00
Oliver Walters
8fda2cf745 Fixes for unit tests 2021-01-29 12:47:46 +11:00
Oliver Walters
4ef6a6dc62 Translations for stock transaction notes 2021-01-29 12:23:22 +11:00
Oliver Walters
282ed0c637 Recompile translations 2021-01-29 12:05:47 +11:00
Oliver Walters
c1a54ddffd Expose bootstrap table strings to translation layer 2021-01-29 12:04:36 +11:00
Oliver Walters
62501ecb93 Hide main QR button if setting is disabled 2021-01-29 09:48:16 +11:00
Oliver
8c7621d4bc Merge pull request #1260 from SchrodingersGat/barcode-scanner
Barcode scanner
2021-01-29 00:42:50 +11:00
Oliver Walters
fc193c26d0 Delete unused function 2021-01-28 22:43:41 +11:00
Oliver Walters
489a15704c Refactoring 2021-01-28 22:41:20 +11:00
Oliver Walters
ae15ce9d0a Update translations 2021-01-28 22:38:47 +11:00
Oliver Walters
e8d73c78eb Fixes for unit tests 2021-01-28 22:37:28 +11:00
Oliver Walters
c61631a380 Refactor tractor 2021-01-28 22:24:06 +11:00
Oliver Walters
5e5bced0c7 Optionally include javascript code based on barcode feature 2021-01-28 21:51:34 +11:00
Oliver Walters
4641123cd8 Allow multiple stock items to be checked into a location using table selection 2021-01-28 21:47:39 +11:00
Oliver Walters
d61ae8532a Dialog for checking multiple items into a stock location 2021-01-28 21:36:57 +11:00
Oliver Walters
7e8def15ed Hide barcode actions if barcode support is disabled 2021-01-28 20:45:42 +11:00
Oliver Walters
51a33e5dca Add setting to enable / disable barcode support
(Default = True)
2021-01-28 20:18:03 +11:00
Oliver
14d24ebe07 Merge pull request #1258 from SchrodingersGat/part-image-fix
Prevent part images from auto deleting
2021-01-28 00:18:44 +11:00
Oliver Walters
220777611a Prevent part images from auto deleting
- Part images can be used for multiple parts
2021-01-27 22:31:21 +11:00
Oliver Walters
5c9dd93ff1 More unit test fix 2021-01-22 12:22:29 +11:00
Oliver Walters
03f7baf87f Unit test fixes 2021-01-22 09:50:30 +11:00
Oliver Walters
2d412e2be1 Default to using "simple" QR codes 2021-01-21 20:55:13 +11:00
Oliver
b90311acea Merge pull request #1250 from SchrodingersGat/url-col
Display link column in part table
2021-01-20 19:30:36 +11:00
Oliver Walters
69362ab960 Display link column in part table 2021-01-20 18:04:08 +11:00
Oliver
71522fa608 Merge pull request #1248 from SchrodingersGat/overdue-unit-test
Adds unit testing for order overdue status
2021-01-20 08:38:44 +11:00
Oliver Walters
82e6b87e1c Adds unit testing for order overdue status 2021-01-20 07:49:14 +11:00
Oliver
914fe15921 Merge pull request #1247 from Pervanovo/pr-fix-misspelled-query-filter
Fix misspelled query filter method name
2021-01-20 07:27:15 +11:00
Daniel Pervan
0d462389b9 Fix misspelled query filter method name 2021-01-19 12:00:30 +01:00
Oliver
d17cb47e3c Update version.py 2021-01-19 11:06:08 +11:00
Oliver
5c2012f873 Update version.py 2021-01-19 11:05:50 +11:00
Oliver
0517fe5073 Merge pull request #1243 from SchrodingersGat/report-filter-validation
Improve filter validation for test report
2021-01-19 11:05:24 +11:00
Oliver Walters
59e37b2526 Improve filter validation for test report 2021-01-19 08:15:50 +11:00
Oliver
ce28b84f34 Merge pull request #1242 from SchrodingersGat/batch-reports
Batch reports
2021-01-18 23:48:19 +11:00
Oliver Walters
f81c154578 Update translation files 2021-01-18 23:25:11 +11:00
Oliver Walters
436207b315 Merge remote-tracking branch 'inventree/master' into batch-reports
# Conflicts:
#	InvenTree/templates/stock_table.html
2021-01-18 23:23:58 +11:00
Oliver
a5aa90cdf2 Merge pull request #1155 from eeintech/stock_owner
Stock Locations and Items Ownership
2021-01-18 22:55:26 +11:00
Oliver Walters
833ba8c472 Template fixes 2021-01-18 22:45:07 +11:00
Oliver Walters
526d81481b Cleanup 2021-01-18 22:25:53 +11:00
Oliver Walters
697a338700 Add a smattering of unit tests 2021-01-18 22:14:38 +11:00
Oliver Walters
6a7c722efc Stock table button cleanup 2021-01-18 21:52:20 +11:00
Oliver Walters
952da19600 Print test report for multiple stock items at once 2021-01-18 21:42:55 +11:00
Oliver Walters
0a566c062d Add click callback on item test tab 2021-01-18 21:36:37 +11:00
Oliver Walters
ef7cc3f78d Replace existing django form views with API request 2021-01-18 21:33:15 +11:00
Oliver Walters
1b835a71df Print one (or more!) report templates via API 2021-01-18 21:17:19 +11:00
Oliver Walters
cbb286e46d Add API for stock item test report 2021-01-18 20:55:30 +11:00
Oliver
873ac9accb Merge pull request #1241 from SchrodingersGat/settings.py
Allow more settings to be specified via environment variables
2021-01-18 20:52:50 +11:00
Oliver Walters
f7079c3bc2 Style fixes 2021-01-18 20:21:19 +11:00
Oliver Walters
3ae4125df3 Allow more settings to be specified via environment variables 2021-01-18 20:17:36 +11:00
Oliver
1d6bd2c6ca Merge pull request #1240 from SchrodingersGat/translation-stats
Translation stats
2021-01-18 20:08:20 +11:00
Oliver Walters
c392bba196 Add script to calculate translation stats 2021-01-18 19:13:52 +11:00
Oliver Walters
c517801c5f Update doc strings for translation scripts 2021-01-18 18:51:10 +11:00
Oliver
2277d225eb Merge pull request #1239 from SchrodingersGat/stock-serial-fix
Stock serial fix
2021-01-18 16:50:54 +11:00
Oliver Walters
2b30df1a70 Fix 2021-01-18 14:41:31 +11:00
Oliver Walters
a7baad33ba Fix form error for creating a new stock item 2021-01-18 14:41:31 +11:00
eeintech
72c7ceb553 Merged master and updated stock_table.html 2021-01-17 13:11:59 -05:00
Oliver
2991ce9317 Merge pull request #1236 from SchrodingersGat/js-fix
Bug fix
2021-01-17 19:58:35 +11:00
Oliver Walters
0dee4df8fb Bug fix 2021-01-15 17:11:46 +11:00
Oliver
69e6006436 Merge pull request #1235 from SchrodingersGat/stock-updated-filter
Stock updated filter
2021-01-15 17:08:21 +11:00
Oliver Walters
4952c95c33 Extra check to prevent JS crash 2021-01-15 16:51:34 +11:00
Oliver Walters
fc32d99327 Add "updated_before" and "updated_after" filter for stock API 2021-01-15 16:39:50 +11:00
Oliver Walters
ef3ac43c4a Add "last updated" date to stock table 2021-01-15 15:27:40 +11:00
Oliver
8f4ae14f2d Merge pull request #1233 from SchrodingersGat/limit-matches
Limit matches to the 5 "most matchy" ones
2021-01-15 12:55:39 +11:00
Oliver Walters
85bce24e30 Limit matches to the 5 "most matchy" ones 2021-01-15 12:32:27 +11:00
Oliver
aada0ca5af Merge pull request #1212 from SchrodingersGat/label-api
Label API
2021-01-15 09:47:34 +11:00
eeintech
7d5571ba5b Merged changes from master 2021-01-14 08:52:56 -05:00
Oliver Walters
a70416abac Update translations 2021-01-15 00:04:31 +11:00
Oliver Walters
0134597747 Merge remote-tracking branch 'inventree/master' into label-api
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
2021-01-14 23:56:23 +11:00
Oliver
449b462bf2 Merge pull request #1232 from SchrodingersGat/purchase-order-target-date
Purchase order target date
2021-01-14 23:26:58 +11:00
Oliver Walters
4fd0d7d8b5 Unit test fix 2021-01-14 23:06:49 +11:00
Oliver Walters
959914c78c Display overdue purchase orders in the calendar view 2021-01-14 22:19:32 +11:00
Oliver Walters
fef5b7548e Increase unit testing for order API 2021-01-14 22:06:53 +11:00
Oliver
af7af395f8 Merge pull request #1219 from rcludwick/secret_key
Fixes #1215.  Allow secret key to come from file.
2021-01-14 21:11:30 +11:00
Rob Ludwick
3cfe358102 Fixes #1215. Allow secret key to come from file. 2021-01-14 01:02:34 -07:00
Oliver Walters
02132fa495 Updated translation files 2021-01-14 17:55:00 +11:00
Oliver Walters
75e1442fce Display overdue purchase orders on the index page 2021-01-14 17:48:16 +11:00
Oliver Walters
e8fd597f29 Adds ability to edit target_date in purchaseorder form 2021-01-14 17:44:21 +11:00
Oliver Walters
21e8ddd1e6 Display overdue status on PurcahseOrder page 2021-01-14 17:42:38 +11:00
Oliver Walters
a8e6d0a89f Display overdue status in purchase order table
- Allow table to be filtered by "overdue" status
2021-01-14 17:37:10 +11:00
Oliver Walters
4d73aab090 Add "overdue" flag to serializer
- Also allow filtering by overdue status in the API
2021-01-14 17:33:24 +11:00
Oliver Walters
834d9ec9a1 Add "target_date" field to PurchaseOrder 2021-01-14 17:28:57 +11:00
Oliver
9efde9de29 Merge pull request #1231 from SchrodingersGat/slow-bom-fix
Add option to show part quantity in various forms
2021-01-14 15:35:39 +11:00
Oliver Walters
1dc2636e45 Add option to show part quantity in various forms
Enabling this option can make BOM item forms *very* slow!
2021-01-14 15:20:42 +11:00
Oliver
8d6b4a2fd3 Merge pull request #1229 from SchrodingersGat/cancel-order-fix
Bug fix for cancelling purchase orders
2021-01-14 15:03:36 +11:00
Oliver Walters
be41741b1e Bug fix for cancelling purchase orders 2021-01-14 14:37:49 +11:00
Oliver
76c938762c Merge pull request #1228 from SchrodingersGat/stock-status-ste
Stock status ste
2021-01-14 14:24:47 +11:00
Oliver
3ec57a7259 Merge pull request #1226 from SchrodingersGat/can-build
Add "Can Build" column in BOM view
2021-01-14 14:04:43 +11:00
Oliver Walters
bb9fe98a7e Set status for multiple stock items at once 2021-01-14 14:04:24 +11:00
Oliver Walters
aac835f634 Add menu item to set stock status for multiple items 2021-01-14 13:41:38 +11:00
Oliver Walters
d459947949 Add "Can Build" column in BOM view 2021-01-14 13:34:51 +11:00
Oliver
a2f9d721f3 Merge pull request #1222 from SchrodingersGat/bom-upload-fix
Fix IPN comparison against null value
2021-01-14 13:17:23 +11:00
Oliver Walters
1cb951bd0b Fix for font-awesome icon 2021-01-14 12:08:54 +11:00
Oliver Walters
df327d4e64 Add stocktake_date field to stock API, and to stock table 2021-01-14 11:29:35 +11:00
Oliver Walters
1316e6bf5b Properly save user data when creating a new StockItem 2021-01-14 11:24:52 +11:00
Oliver Walters
890ce9ef95 Fix IPN comparison against null value 2021-01-14 10:58:29 +11:00
Oliver Walters
df335b683c Add #TODO 2021-01-14 10:54:34 +11:00
eeintech
c5778b6fb6 Added missing migration file (how did it escape?) 2021-01-13 17:33:55 -05:00
eeintech
e92e5dfe8f Merged master 2021-01-13 17:08:01 -05:00
Oliver
e4b202edd8 Merge pull request #1221 from eeintech/new_rule_sets
Separated category from part permissions and location from stock item permissions
2021-01-14 08:38:44 +11:00
Oliver Walters
b7bbc97218 Add unit test 2021-01-14 08:32:37 +11:00
Oliver Walters
9884fe5c5e Improve validators for 'filters' field 2021-01-14 08:15:05 +11:00
Oliver Walters
88a7b3251d Remove unused import 2021-01-14 08:14:32 +11:00
eeintech
af1abb7129 Added missing migration file 2021-01-13 14:57:16 -05:00
eeintech
59c0a50289 Separated category from part permissions and location from stock item permissions 2021-01-13 13:35:49 -05:00
eeintech
28fb1b5fab Added owner model to admin page and added test cases 2021-01-13 11:38:37 -05:00
Oliver Walters
6e4cf7c092 Catch db integrity errors 2021-01-13 22:07:30 +11:00
Oliver Walters
80c88b4fcc Update translations 2021-01-13 21:53:11 +11:00
Oliver Walters
4e2d3b7da2 Improvement for existing StockItemLabel template 2021-01-13 21:52:16 +11:00
Oliver Walters
e561b3a4fc Add StockItemLabel templates 2021-01-13 21:51:55 +11:00
Oliver
eedd8059d8 Merge pull request #1217 from eeintech/bom_item_delete
Allow user with part.change permission to delete BOM items, part attachments and parameters
2021-01-13 10:16:25 +11:00
eeintech
a1b2347784 Also allow part attachements and parameters to be deleted 2021-01-12 17:43:12 -05:00
eeintech
ba1862478c Allow user with part.change permission to delete BOM items 2021-01-12 17:34:11 -05:00
eeintech
0a0a47a5e4 Added location owner change test case to verify stock item owner in that location is also updated 2021-01-12 17:11:46 -05:00
eeintech
3054c637dd Removed f-string debug 2021-01-12 16:42:09 -05:00
eeintech
5ca03af3e2 Improved Owner.get_owner method and fixed tests (try#2) 2021-01-12 16:36:29 -05:00
eeintech
49c954aa68 Fixed test cases? 2021-01-12 15:02:44 -05:00
eeintech
452d22579a Removed f-string causing build failure 2021-01-12 13:23:14 -05:00
eeintech
b6135fda74 Updated templates and a lot of manual testing 2021-01-12 13:16:04 -05:00
eeintech
9eace09e0e Added owner create method and fixed post_save receiver 2021-01-12 10:53:17 -05:00
eeintech
6f3cbb4e14 Switched to global owner model, need to validate use-cases table and fix tests 2021-01-11 17:41:29 -05:00
eeintech
6a88bdb37d StockLocation owner is now a GenericForeignKey that can be set to user or group models 2021-01-11 12:56:40 -05:00
Oliver Walters
01e27a0d59 Add simplified 'barcode' function for StockItem 2021-01-12 00:22:58 +11:00
Oliver Walters
663a0a6165 Create simple label templates for stocklocation labels 2021-01-11 23:45:25 +11:00
Oliver Walters
d1d243fb14 Update label models 2021-01-11 23:44:11 +11:00
Oliver Walters
b6cd2c215a Adds function to provide simplified barcode for stock location 2021-01-11 21:32:31 +11:00
Oliver Walters
1368b06afa PEP fix 2021-01-11 19:46:17 +11:00
Oliver Walters
d91700fd39 StockLocation labels are now printable 2021-01-11 18:41:57 +11:00
Oliver Walters
af47b211fd Add dialog for selection of stock location labels 2021-01-11 17:22:04 +11:00
Oliver Walters
79b63e6d30 Update translation 2021-01-09 22:23:51 +11:00
Oliver Walters
a3c5ea1f2b Typo fix 2021-01-09 22:02:33 +11:00
Oliver Walters
21d5440f98 Remove unused views 2021-01-09 21:55:05 +11:00
Oliver Walters
e133fff03e Download PDF for labels 2021-01-09 21:50:42 +11:00
Oliver Walters
bdc7367e29 Add endpoint for printing labels 2021-01-09 20:43:48 +11:00
Oliver Walters
44e60a705e Add detail endpoints for the StockItemLabel and StockLocationLabel models 2021-01-09 08:20:29 +11:00
Oliver Walters
a0d1f95171 Add exception for new database table 2021-01-09 08:10:04 +11:00
eeintech
587bf26d94 Fixed style 2021-01-08 14:23:35 -05:00
eeintech
2f78c7c036 Updated stock tests quantities 2021-01-08 14:05:53 -05:00
eeintech
d25a719724 Merge branch 'stock_owner' of github.com:eeintech/InvenTree into stock_owner 2021-01-08 13:51:49 -05:00
Oliver Walters
7c7a67fcc6 Add filterable API for StockLocation labels 2021-01-08 23:08:30 +11:00
Oliver Walters
f0fa092c66 Add model for StockLocation label 2021-01-08 23:08:00 +11:00
Oliver Walters
80c7ee6dab Add ability to filter label by StockItem 2021-01-08 22:47:47 +11:00
Oliver Walters
446c744462 Expose stock items labels to the API 2021-01-08 22:19:52 +11:00
Oliver
ab9a6bd3c4 Merge pull request #1211 from SchrodingersGat/attachment-api
Filter PartAttachment API list by Part reference
2021-01-08 12:22:59 +11:00
Oliver Walters
59bb5d15c8 Filter PartAttachment API list by Part reference 2021-01-08 08:43:00 +11:00
eeintech
67bc86c159 Updated stock owners migration file 2021-01-07 14:05:43 -05:00
eeintech
f26f1c38a2 Merged master 2021-01-07 13:50:29 -05:00
Oliver
5666db6b7a Merge pull request #1208 from SchrodingersGat/calendar
Add fullcalendar javascript library
2021-01-08 00:04:16 +11:00
Oliver Walters
75f31ecc63 Update translations 2021-01-07 23:50:34 +11:00
Oliver Walters
47b0f40e97 Calendar view for build orders 2021-01-07 23:41:54 +11:00
Oliver Walters
76c86e7b2f Calendar view for purchase orders 2021-01-07 23:04:00 +11:00
Oliver Walters
38b6367453 PEP fixes 2021-01-07 22:34:17 +11:00
Oliver Walters
b7203f0ebb Switch between calendar and list view for sales orders 2021-01-07 22:32:17 +11:00
Oliver Walters
5f6442ba6b Render sales orders to a calendar view 2021-01-07 18:47:29 +11:00
Oliver Walters
b4277e09e8 Add fullcalendar javascript library 2021-01-07 14:21:32 +11:00
Oliver
c377fb7b0c Merge pull request #1205 from SchrodingersGat/hide-report-button
Rearrange button options for StockItem
2021-01-07 00:34:23 +11:00
Oliver Walters
bb72658e76 Rearrange button options for StockItem 2021-01-07 00:18:18 +11:00
Oliver
735a3d2eb2 Merge pull request #1202 from SchrodingersGat/stock-expiry
StockItem expiry date
2021-01-06 23:51:18 +11:00
Oliver Walters
7ac7e8f969 Fixed unit test 2021-01-06 23:38:01 +11:00
Oliver Walters
a8e3e6c8db Update translation 2021-01-06 23:12:52 +11:00
Oliver Walters
e5b346e7fa PEP fixes 2021-01-06 23:09:26 +11:00
Oliver Walters
1d6a049c5a Annotate stock queryset with stale status 2021-01-06 23:06:49 +11:00
Oliver Walters
a5b18640af Display stale stock on index page 2021-01-06 22:30:12 +11:00
Oliver Walters
e62873a650 Display "stale" status on StockItem info page 2021-01-06 22:21:18 +11:00
Oliver Walters
ba915da22b Filter StockItem API by staleness 2021-01-06 22:20:54 +11:00
Oliver Walters
33d6396a4e Exclude expired stock from builds 2021-01-06 21:00:45 +11:00
Oliver Walters
580e7599a0 Prevent expired stock from being added to a sales order 2021-01-06 20:22:56 +11:00
Oliver Walters
9b086560cb Hide "expiry_date" column in Stock table if feature not enabled 2021-01-06 12:09:48 +11:00
Oliver Walters
d0fb69e67d Add option to enable / disable stock expiry feature
- Simply hides fields in form views
2021-01-05 08:50:07 +11:00
Oliver Walters
1335c85de1 Edit new stock settings on settings page 2021-01-05 00:59:10 +11:00
Oliver Walters
855098e30b Merge conflicting migration files 2021-01-05 00:58:48 +11:00
Oliver Walters
e715ea5d79 Merge remote-tracking branch 'inventree/master' into stock-expiry
# Conflicts:
#	InvenTree/common/models.py
2021-01-05 00:58:32 +11:00
Oliver Walters
213d6550d3 Add new setock settings 2021-01-05 00:54:05 +11:00
Oliver Walters
9a30108b75 Auto-update the expiry date in the StockItem form when switching Part selection 2021-01-05 00:37:42 +11:00
Oliver Walters
9dc9c0fcb7 Auto-populate expiry date for stockitem when created via the API
(Now with unit testing!)
2021-01-05 00:21:26 +11:00
Oliver Walters
da02ab3eac Add unit testing for view 2021-01-05 00:01:44 +11:00
Oliver Walters
7d7d5d24cc Pre-fill stockitem expiry date in CreateStockItem form 2021-01-04 23:40:51 +11:00
Oliver Walters
37dcf1c1cf Add "default_expiry" field to Part model 2021-01-04 23:36:11 +11:00
Oliver Walters
692cee113c Display "expiry date" column in stock table 2021-01-04 23:11:35 +11:00
Oliver Walters
4d7c60a130 Add "expired stock" table to index page 2021-01-04 09:46:14 +11:00
Oliver Walters
d1ce0f062e Improve unit testing for StockItem API 2021-01-04 01:22:43 +11:00
Oliver Walters
a0c95579b4 Display expiry status on StockItem page
- Also adds ability to filter Stock table by expired status
2021-01-04 00:21:47 +11:00
Oliver Walters
39b9dcfec9 Add 'expired' flag to StockItem serializer 2021-01-04 00:21:21 +11:00
Oliver Walters
1a930f7f80 Add ability to edit expiry_date for StockItem 2021-01-04 00:20:02 +11:00
Oliver Walters
6d4c81e68b Add ability to filter by 'expired' status in API 2021-01-04 00:19:48 +11:00
Oliver Walters
07cda765f0 Add "expiry_date" field to StockItem model
- Also adds "is_expired" function
2021-01-03 23:56:35 +11:00
Oliver
bc72cd612e Merge pull request #1201 from SchrodingersGat/settings
Settings Improvements
2021-01-03 23:47:35 +11:00
Oliver Walters
0f9c4703cf Update unit testing 2021-01-03 23:33:47 +11:00
Oliver Walters
b05504e1c4 Add PART_VIRTUAL setting 2021-01-03 23:13:58 +11:00
Oliver
fe3d4a9867 Merge pull request #1200 from SchrodingersGat/supplier-part-import
SupplierPart import/export fixes
2021-01-03 23:08:05 +11:00
Oliver Walters
0aeeba808c PEP fixes 2021-01-03 23:07:21 +11:00
Oliver Walters
6c7b648133 Implement global settings for assembly and template values of Part model 2021-01-03 23:06:51 +11:00
Oliver Walters
9fa37a9156 Improve visualisation of global settings 2021-01-03 22:57:39 +11:00
Oliver Walters
8e9c976e99 Update translations 2021-01-03 22:18:08 +11:00
Oliver Walters
2a91bb0c87 Update SupplierPart model to allow data importing
- django-import-export plugin seems to require null=True for char fields
- yes, this goes against django "best practice"
- Hopefully a better solution can be found
2021-01-03 22:16:32 +11:00
Oliver
bdc3a9ef02 Merge pull request #1198 from SchrodingersGat/stock-item-form-fix
Fix for StockItem create / edit forms
2021-01-03 14:15:56 +11:00
Oliver Walters
2ad090c224 pop purchase_price field for StockItemEdit form 2021-01-03 13:15:42 +11:00
Oliver Walters
fe0d356675 pops the purchase_price field instead of using a HiddenInput
Using a HiddenInput on a MoneyFormField causes a validation error, for some reason...
2021-01-03 13:13:14 +11:00
Oliver
11c6248b06 Merge pull request #1197 from SchrodingersGat/bom-fix
Fix variable scope issue
2021-01-03 10:30:47 +11:00
Oliver Walters
298e9cae65 Fix variable scope issue 2021-01-03 10:07:38 +11:00
Oliver
2dfa4d1acd Merge pull request #1196 from SchrodingersGat/target-date-optional
Target date optional
2021-01-03 09:00:46 +11:00
Oliver Walters
725a70327a Add some unit testing 2021-01-02 22:21:37 +11:00
Oliver Walters
b2a732197b Fix target date form field for SalesOrder 2021-01-02 21:54:07 +11:00
Oliver Walters
2b57ffeb08 Custom date picker field
- Prevents picker from being "required" by the form
2021-01-02 21:50:10 +11:00
Oliver Walters
03276629c2 CSS tweaks 2021-01-02 21:41:47 +11:00
eeintech
3ff76fbdab Merging master and resolved conflict 2020-12-18 17:08:37 -05:00
Oliver
7560b7e167 Merge pull request #1177 from SchrodingersGat/sales-order-overdue
Sales order overdue
2020-12-18 20:06:48 +11:00
Oliver Walters
08a8556fe7 Fix unit testing 2020-12-18 19:46:02 +11:00
Oliver Walters
13e924cc05 Fix default value for PO and SO codes 2020-12-18 16:10:55 +11:00
Oliver Walters
8e13a7b470 Add "overdue sales orders" to index page 2020-12-18 12:45:42 +11:00
Oliver Walters
c34196538b Filter API by overdue status 2020-12-18 12:40:47 +11:00
Oliver Walters
b21c6f0b99 Add overdue filter for salesorder table 2020-12-18 12:27:08 +11:00
Oliver Walters
c6134b54ab Add "overdue" status to SalesOrder serializer 2020-12-18 12:26:58 +11:00
Oliver Walters
000348f70f Add 'target_date' field to SalesOrder model 2020-12-18 12:19:16 +11:00
Oliver
8bb4683bbe Merge pull request #1175 from eeintech/fix_stock_template
Keep 'stock actions' button enabled when on children tab
2020-12-18 12:02:39 +11:00
Oliver
d38d9b21a9 Merge pull request #1174 from eeintech/fix_category_parameter_url
Fixed category parameter templates settings view
2020-12-18 12:00:51 +11:00
eeintech
1a48405491 Keep 'stock actions' button enabled when on children tab 2020-12-17 17:37:54 -05:00
eeintech
bcae1d09a8 Fixed category parameter templates settings view 2020-12-17 17:25:10 -05:00
Oliver
a8c6e79bc0 Merge pull request #1172 from SchrodingersGat/duplicate-ipn-fix
Bugfix for duplicate IPN checks when blank IPN is used
2020-12-16 21:53:14 +11:00
Oliver Walters
06d9f4f982 Bugfix for duplicate IPN checks when blank IPN is used 2020-12-16 21:02:53 +11:00
Oliver
7df25df2af Merge pull request #1168 from SchrodingersGat/order-date
Build Order Target Date
2020-12-16 19:36:10 +11:00
Oliver Walters
464d76a819 Update form title strings 2020-12-16 19:09:53 +11:00
Oliver Walters
447f0b0ed7 Update translations 2020-12-16 19:03:04 +11:00
Oliver Walters
0500036d0a settings.py - typo fix 2020-12-16 16:58:40 +11:00
Oliver Walters
261a9af4f5 Typo fix 2020-12-16 16:32:20 +11:00
Oliver
04336dd039 Merge pull request #1169 from SchrodingersGat/parent-test-link
Render link rather than just text
2020-12-16 16:29:54 +11:00
Oliver Walters
a9310d4a39 Add a #TODO in code 2020-12-16 16:16:07 +11:00
Oliver Walters
a8704a05d6 PEP style fixes 2020-12-16 16:15:39 +11:00
Oliver Walters
597bf8be73 Add date input to build target_date 2020-12-16 16:13:38 +11:00
Oliver Walters
6ef4325eac Javascript formatting 2020-12-16 15:55:42 +11:00
Oliver Walters
1a07ae0936 Render link rather than just text 2020-12-16 15:48:41 +11:00
Oliver
bf3b5bdd7f Merge pull request #1167 from SchrodingersGat/login-page
Improve rendering for login page
2020-12-15 23:34:32 +11:00
Oliver Walters
17d23fa47c Add overdue builds to the index page 2020-12-15 23:34:28 +11:00
Oliver Walters
c8c50af54b Filter builds by "overdue" status 2020-12-15 23:31:19 +11:00
Oliver Walters
51da26d21d Filter builds by "overdue" status 2020-12-15 23:27:59 +11:00
Oliver Walters
802dd5174c Add "target_date" for Build model
- Add "overdue" status to Build serializer
2020-12-15 23:24:37 +11:00
Oliver Walters
f11348c965 Improve rendering for login page 2020-12-15 22:39:57 +11:00
Oliver
a7d825158c Merge pull request #1164 from SchrodingersGat/stock-report-filter
Stock report filter
2020-12-15 13:32:13 +11:00
Oliver Walters
297bfd776c Pre-select a template if only one matching one exists 2020-12-15 12:31:02 +11:00
Oliver Walters
ef032d406f Bugfix for stock report filter 2020-12-15 11:57:52 +11:00
Oliver
980cb9522b Merge pull request #1162 from SchrodingersGat/gunicorn-conf
Update default gunicorn conf file
2020-12-14 11:00:57 +11:00
Oliver Walters
55b7cd3d6a PEP fix 2020-12-14 10:44:38 +11:00
Oliver
70cac17138 Merge pull request #1163 from SchrodingersGat/hide-purchase-price
Hide purchase price field for non-purchaseable parts
2020-12-14 10:43:21 +11:00
Oliver Walters
648595cf18 Hide purchase price field for non-purchaseable parts 2020-12-14 09:55:39 +11:00
Oliver Walters
d609e881c2 Update default gunicorn conf file 2020-12-14 09:43:07 +11:00
Oliver
1c168452a4 Merge pull request #1159 from eeintech/roles_overview
Display permission levels for each ruleset in Group admin list view
2020-12-11 10:03:56 +11:00
eeintech
1ef5a2b481 Display permission levels for each ruleset in Group admin list view 2020-12-10 15:38:48 -05:00
eeintech
33dfecfdef Added create view test cases for stock ownership 2020-12-03 13:29:59 -05:00
eeintech
3aad5111b5 Stock ownership: test case for edit stock location and item 2020-12-03 11:56:45 -05:00
eeintech
f99c83f69d Added test case for stock location ownership 2020-12-03 07:32:01 -05:00
eeintech
5c6939429a Improved handling of stock location owner 2020-12-02 17:19:41 -05:00
eeintech
1a7a460ba8 Hidden owner field when ownership control is disabled 2020-12-02 14:05:45 -05:00
eeintech
de1dfdcc38 Improved naming of new setting and variables 2020-12-02 13:38:53 -05:00
eeintech
2bdd1305ed Fix style 2020-12-02 13:26:26 -05:00
eeintech
c66ac2579e Updated StockItem create/edit view with ownership control 2020-12-02 13:25:33 -05:00
eeintech
2d7461f609 Updated StockLocation create/edit view with ownership control 2020-12-02 12:05:00 -05:00
eeintech
c9b3c16c6f Added help text on owner fields 2020-12-01 17:46:11 -05:00
eeintech
8dac6bb982 Updated template stock item logic and added to stock locations 2020-12-01 17:41:03 -05:00
eeintech
4104e7df8e Fixed template logic 2020-12-01 16:08:27 -05:00
eeintech
2c38be2d13 Added global setting and updated stock item templates 2020-12-01 15:54:05 -05:00
eeintech
e1fb7e5d98 Added owner field to both stock item and location tables and forms 2020-12-01 13:45:01 -05:00
Oliver
9dae7c1566 Merge pull request #1154 from SchrodingersGat/build-delete-fix
Change delete behaviour for parent build item
2020-12-01 12:36:24 +11:00
Oliver Walters
47d38e1cca Change delete behaviour for parent build item
- was causing database integrity errors when a parent build existed
2020-12-01 10:24:51 +11:00
Oliver
28a5ee32c4 Merge pull request #1152 from elmo2k3/fix-stocklist-sidebar
Fix sidenav in stocklist
2020-12-01 08:56:41 +11:00
Bjoern Biesenbach
95f62d529f Fix sidenav in stocklist 2020-11-30 18:30:51 +01:00
Oliver
a8f605c2e6 Merge pull request #1149 from SchrodingersGat/bom-upload-speed
Vastly improved speed of BOM upload
2020-11-27 15:25:46 +11:00
Oliver Walters
ea2f5009c8 Vastly improved speed of BOM upload
- Was calculating the stock levels for *every* part, for *every* drop down
- Many many many calls were being made
- Just remove stock count entirely from the drop-down menus
2020-11-27 14:40:30 +11:00
Oliver
a5e6ac2300 Merge pull request #1148 from SchrodingersGat/order-parts
Order parts
2020-11-27 12:28:04 +11:00
Oliver
b150c9c6bc Merge pull request #1147 from SchrodingersGat/form-fixes
Fixes for 'non field' errors in forms
2020-11-27 12:27:53 +11:00
Oliver Walters
50a88e4826 Revert "Add extra context to SupplierPartCreate form"
This reverts commit 5f8f0232a9.
2020-11-27 11:19:16 +11:00
Oliver Walters
6c68197e61 Allow part ordering from build view 2020-11-27 11:18:58 +11:00
Oliver Walters
7068f70811 Fixes for 'order parts' form
- Sometimes the part pk was not being retrieved properly
2020-11-27 11:18:45 +11:00
Oliver Walters
607cc90ce0 Add extra context to SupplierPartCreate form
(cherry picked from commit 5f8f0232a9)
2020-11-27 11:18:23 +11:00
Oliver Walters
5f8f0232a9 Add extra context to SupplierPartCreate form 2020-11-27 11:17:55 +11:00
Oliver Walters
56f05e2604 Fixes for 'non field' errors in forms
- Fixes issue where non-model fields would not show error text
2020-11-27 10:42:01 +11:00
Oliver
aacc7119bd Merge pull request #1144 from SchrodingersGat/bom-fixes
Bom fixes
2020-11-24 22:28:20 +11:00
Oliver Walters
083d7671d0 Bug fix for BOM table
If the BOM for part included a BomItem with the same PK as the top-level part,
the bootstrap-tree-grid library borked

Probably for good reason, too!

So we now ensure that the top-level key is unique
2020-11-24 21:19:19 +11:00
Oliver Walters
28333c1a21 Add a simple "shell" task 2020-11-24 21:18:00 +11:00
Oliver Walters
e3231bbedb Hide "pricing" information in the BOM table 2020-11-24 20:58:18 +11:00
Oliver
3ff0759bb9 Merge pull request #1142 from SchrodingersGat/bom-form-fixes
Bom form fixes
2020-11-24 14:23:04 +11:00
Oliver Walters
b5d75d6e6a PEP fixes 2020-11-24 11:56:51 +11:00
Oliver Walters
ce82579930 Cleanup getRequiredParts function 2020-11-24 10:18:07 +11:00
Oliver Walters
371ec582e1 Cleanup queryset for BomItemEdit view 2020-11-24 09:43:49 +11:00
Oliver Walters
3391db506a Cleanup queryset for BomItemCreate view 2020-11-24 09:43:32 +11:00
Oliver Walters
af9b88de11 Fix for BomItem clean function
Handle the case where the sub_part does not exist
2020-11-24 09:33:26 +11:00
Oliver
73259c0bcb Merge pull request #1140 from SchrodingersGat/request-frequency
Reduce duplicate function calls in custom context parser
2020-11-20 11:40:10 +11:00
Oliver
a0168515c3 Merge pull request #1139 from eeintech/fix_supplierpart_edit_form
Fix for SupplierPart edit form validation
2020-11-20 09:40:00 +11:00
Oliver Walters
20e8161038 Reduce duplicate function calls in custom context parser 2020-11-20 08:29:06 +11:00
eeintech
11745ebd6c Removed one too many indent 2020-11-19 15:32:42 -05:00
eeintech
4768c9cbb3 Fixed validation of SupplierPart edit form by forcing the value of single_pricing field 2020-11-19 15:31:39 -05:00
Oliver
6b104fbb8b Merge pull request #1136 from SchrodingersGat/warning-icon
Add framework for "health checks"
2020-11-19 13:30:17 +11:00
Oliver Walters
4049c8e915 Adds framework for "server health" display
- Adds global context object "system_healthy" (boolean)
- Framework for running system health checks
- Updated system info forms
- Displays warning next to user menu if system health errors exist

(cherry picked from commit ce6d626ab39147fc389de90815ca8baae2385d82)
2020-11-19 12:36:54 +11:00
Oliver
e55f4a2798 Merge pull request #1135 from SchrodingersGat/quoth-the-raven
Fixes for custom SQL queries
2020-11-19 10:34:53 +11:00
Oliver Walters
599220a931 Fixes for custom SQL queries
- Don't use double quotes!
- NO NO NO!
- Single quotes only
2020-11-19 09:15:16 +11:00
Oliver
0594ebaef7 Merge pull request #1133 from SchrodingersGat/stock-table-fix
Smallt tweaks for the Stock table
2020-11-18 15:24:06 +11:00
Oliver Walters
24fd520ec3 Smallt tweaks for the Stock table 2020-11-18 15:03:51 +11:00
Oliver
4daf291619 Merge pull request #1131 from SchrodingersGat/purchase-price-fix
Fix for StockItem creation form
2020-11-17 16:07:31 +11:00
Oliver Walters
6144d7e209 Fix for StockItem creation form
- purchase_price field was required (should not be!)
- Fixed some validation issues
- Cleaned up form implementation
2020-11-17 15:29:44 +11:00
Oliver
9fa718e58d Merge pull request #1130 from eeintech/api_category_parameters
Improved API endpoint for category parameter templates
2020-11-17 09:36:34 +11:00
eeintech
ac2797c7a1 Improved API endpoint for category parameter templates 2020-11-16 16:10:00 -05:00
Oliver
d8e7c2a932 Update version.py 2020-11-15 16:53:27 +11:00
Oliver
20f6964b1f Update version.py 2020-11-15 16:51:50 +11:00
Oliver
771efecaa2 Merge pull request #1127 from SchrodingersGat/settings-view-unit-test
Extra unit testing for settings forms / views
2020-11-14 09:19:31 +11:00
Oliver Walters
2e842503e6 Fix try statement 2020-11-14 07:39:51 +11:00
Oliver Walters
b738f8b143 Try transaction.atomic 2020-11-13 22:22:02 +11:00
Oliver Walters
aae1400929 Mayyyyyyyyyyyyybe? 2020-11-13 21:37:39 +11:00
Oliver Walters
5f9758e85f More fixes 2020-11-13 21:01:30 +11:00
Oliver Walters
03e852f957 Remove custom save method 2020-11-13 20:22:28 +11:00
Oliver
0bb8c0a1e3 Merge pull request #1128 from SchrodingersGat/settings-improvements
Improve settings.py
2020-11-13 15:32:48 +11:00
Oliver Walters
f0777ead92 Removed eprint statements 2020-11-13 14:39:28 +11:00
Oliver Walters
0f42916521 Improve settings.py
- Load database config from either config.yaml or environment variables
- Mix and match, if you want!
- Move to use logging module rather than just printing stuff
- Error if required database parameters are not required
2020-11-13 13:38:01 +11:00
Oliver Walters
ee70e27f7d Change function name 2020-11-13 13:21:43 +11:00
Oliver Walters
01ff562dcd Extra unit testing for settings forms / views 2020-11-13 11:50:58 +11:00
Oliver
1d4b826d03 Merge pull request #1124 from eeintech/fix_nocategory_templates_error
Check that category was selected before fetching templates
2020-11-13 10:41:51 +11:00
Oliver
d777549a1a Merge pull request #1123 from eeintech/fix_form_errors
Fixed disabling of form errors messing-up with global settings validation
2020-11-13 09:59:57 +11:00
Oliver
3130b672b4 Merge pull request #1117 from SchrodingersGat/currency-support
Currency support
2020-11-13 09:13:55 +11:00
eeintech
d4ac35b9aa Check that category was selected before fetching templates 2020-11-12 16:52:22 -05:00
eeintech
80b70fd2df Fixed disabling of form errors messing-up with global settings 2020-11-12 16:38:35 -05:00
Oliver Walters
362437e75e PEP fixes 2020-11-13 07:28:21 +11:00
Oliver Walters
f239c8f8c8 Add missing migration file 2020-11-12 22:04:50 +11:00
Oliver Walters
ae7fbd6112 Add PEP8-naming extension for flake
- Enforcing python naming checks
2020-11-12 21:53:04 +11:00
Oliver Walters
47cbf3071d Add option to add a single-quantity price-break when creating a new SupplierPart object
- Add unit testing!
2020-11-12 21:36:32 +11:00
Oliver Walters
534f43872f Bug fix for SupplierPart table 2020-11-12 20:14:10 +11:00
Oliver Walters
fd79f1ea0e Fixes for 'single pricing' for SupplierPart 2020-11-12 19:46:19 +11:00
Oliver Walters
7879c7565e More fixes to .travis.yml
Database in a strange location?
2020-11-12 19:11:12 +11:00
Oliver Walters
6e7224ee7c Add "purchase price" field to PurchaseOrderLineItem table 2020-11-12 18:05:24 +11:00
Oliver Walters
0988040172 Catch exception where InvenTree setting object is referenced but the database is not migrated yet 2020-11-12 18:04:50 +11:00
Oliver Walters
cb3c86f87a Merge remote-tracking branch 'inventree/master' into currency-support
# Conflicts:
#	InvenTree/InvenTree/settings.py
#	InvenTree/InvenTree/urls.py
#	InvenTree/templates/InvenTree/settings/tabs.html
#	InvenTree/users/models.py
#	requirements.txt

IMPORTANT: Had to merge some migration files due to different migrations applied on the part model tables
2020-11-12 17:24:48 +11:00
Oliver
265a29fa1a Merge pull request #1122 from SchrodingersGat/import-export-fix
Fixes for import / export of data
2020-11-12 17:06:50 +11:00
Oliver Walters
4765065eb0 Make sure to run database migrations first! (DUH) 2020-11-12 16:41:43 +11:00
Oliver Walters
563bfe9bf5 Further fixes to tasks.py 2020-11-12 16:10:00 +11:00
Oliver Walters
96ef5e1bde Travis fixes 2020-11-12 15:37:21 +11:00
Oliver Walters
fe9749ba4f Add missing fixture for settings 2020-11-12 14:54:03 +11:00
Oliver Walters
21315096d4 Further unit testing fixes 2020-11-12 14:53:49 +11:00
Oliver Walters
1738df9042 Update unit tests 2020-11-12 14:48:57 +11:00
Oliver Walters
ec8d8e5a64 Add more invoke commands:
- export-records: Exports all database records to external file
- import-records: Imports database records from external file
- import-fixtures: Fills the database with dummy records
2020-11-12 13:31:27 +11:00
Oliver Walters
4a8170079e Remove code which automatically created settings objects on server launch 2020-11-12 12:31:03 +11:00
Oliver Walters
b7187c5e06 Fixes for purchase order table displays 2020-11-12 12:27:01 +11:00
Oliver Walters
391eeb0e46 Specify default currency when creating a new stock item 2020-11-12 11:50:59 +11:00
Oliver Walters
51d2d85c26 When creating a new price break for a supplier part, default to using the currency code specified for the supplier company 2020-11-12 11:14:50 +11:00
Oliver Walters
1532be9c1e Add 'currency' option for company
- e.g. an external supplier might have a default currency
- Adds a form input which only allows selection of allowed currency codes
- Add unit testing for currency validation
2020-11-12 11:02:10 +11:00
Oliver
643589b4a9 Merge pull request #1096 from eeintech/categories_parameters
Categories parameter templates
2020-11-12 09:32:01 +11:00
eeintech
b4fa56fd96 Fixed PART_CATEGORY_PARAMETERS duplicate (bad merging... oopsy) 2020-11-11 12:40:03 -05:00
eeintech
bfdda847c4 Updated part migration reference in 0054 2020-11-11 11:18:10 -05:00
Francois
a7444a9926 Merge branch 'master' into categories_parameters 2020-11-11 06:40:11 -05:00
Oliver
4430098e98 Merge pull request #1120 from SchrodingersGat/used-in-fix
A little whoopsie-doo:
2020-11-11 16:47:34 +11:00
Oliver Walters
039a7badd1 A little whoopsie-doo:
- Part.clean() was incorrectly referencing a BomItem when it should have been referencing BomItem.part
2020-11-11 16:09:14 +11:00
Oliver
6d5bdaadbd Merge pull request #1118 from SchrodingersGat/log-viewer
Add requirement for django-error-report
2020-11-11 16:00:48 +11:00
Oliver Walters
56765d3f5a Fix for unit testing 2020-11-11 15:19:15 +11:00
Oliver Walters
6c667937c5 Add requirement for django-error-report
- Provides an error log viewer in the admin interface at /admin/error_report/error/
- Allows viewing of error logs even in a remote production environment (i.e. no access to command line)
2020-11-11 14:10:12 +11:00
Oliver Walters
ebac06ebee Add 'single_pricing' form to the EditSupplierPartForm
- Idea here is to automatically create a unit-pricing price-break when a new SupplierPart is created
2020-11-11 13:55:25 +11:00
Oliver Walters
fc89501a62 Fix for SQL cursor query
- What works in SQLite don't necessarily fly with the big boys
2020-11-11 08:06:14 +11:00
Oliver Walters
5567ad07fd Update tests and translations 2020-11-11 00:31:39 +11:00
Oliver Walters
a19cf1f27a PEP fixes 2020-11-11 00:26:59 +11:00
Oliver Walters
4dff18e4a6 Remove common_currency model entirely
- A lot of views / pages / etc needed to be updated too
- Now uses django-money fields entirely
- Create a manual rate exchange backend (needs more work!)
2020-11-11 00:21:06 +11:00
Oliver Walters
1fc2ef5f18 Custom migration for PartSellPriceBreak 2020-11-10 22:31:46 +11:00
Oliver Walters
83582ae87f Add custom migration for the part_supplierpricebreak model
- Copies across existing pricing data
- Yikes
2020-11-10 22:25:05 +11:00
Oliver Walters
e4f2eecb3b Remove defunct 'build_order' field from StockItem model
- This is now handled by the new-and-improved build system, no longer required
2020-11-10 20:12:39 +11:00
Oliver Walters
978fd7c683 Implement default currency selection
- Add 'choices' option to InvenTreeSetting class
- Add support for ChoiceField in InvenTreeSetting form
2020-11-10 17:08:08 +11:00
Oliver Walters
48c20c600a List supported currencies in the configuration template 2020-11-10 16:28:55 +11:00
Oliver Walters
734436b02e Add integration of django-money
- Proper currency support
- Add PurchasePrice field to StockItem model
- This keeps track of both the price and the currency
- Display purchase price on the stockitem detail page
2020-11-10 16:22:42 +11:00
Oliver
9d9ef5fc9c Merge pull request #1116 from SchrodingersGat/duplicate-ipn
Add setting to allow or prohibit duplicate IPN values
2020-11-10 10:52:30 +11:00
Oliver
9ac334ddd2 Merge pull request #1115 from eeintech/fix_form_errors
Fix for #1111 (missing logic to check for model errors)
2020-11-10 10:25:09 +11:00
Oliver Walters
a6028f027a Add setting to allow or prohibit duplicate IPN values 2020-11-10 09:03:26 +11:00
eeintech
b17b8db25c Fix for #1111 (missing logic) 2020-11-09 17:00:12 -05:00
Oliver
eead52a5dd Merge pull request #1114 from SchrodingersGat/part_options
Part options
2020-11-10 08:28:23 +11:00
Oliver Walters
7286281a06 Fix for unit testing 2020-11-10 07:14:38 +11:00
Oliver Walters
c4296ad4f1 Update migrations and translation 2020-11-09 23:47:31 +11:00
Oliver Walters
c95f124578 Add some helper magic for setting objects
- If the setting is defined as a "bool" then the returned value is automatically cast to a bool
- Add some more unit testing
2020-11-09 23:44:54 +11:00
Oliver Walters
75ab7b247b Push part settings into part/settings.py
- Use the user-configurable defaults in the database model itself
- This means they are observed even when using the API / etc
2020-11-09 23:16:04 +11:00
Oliver Walters
e1b70ff68f Add default values for create part form 2020-11-09 22:52:32 +11:00
Oliver Walters
8149759852 Add some more part options which set the default values for the following fields:
- Purchaseable
- Salable
- Trackable
2020-11-09 20:26:19 +11:00
Oliver
826c471179 Merge pull request #1107 from eeintech/fix_postgres_migration
Fix PostGreSQL migration (permissions handler)
2020-11-06 07:58:56 +11:00
Oliver
dadf4d4c13 Merge pull request #1110 from eeintech/order_save_fix
Fixed saving of purchase and sales order create forms
2020-11-06 07:53:41 +11:00
Oliver
d23444a86a Merge pull request #1111 from eeintech/disable_crispy_form_errors
Disable crispy form errors
2020-11-06 07:53:11 +11:00
eeintech
ba2da17f1e Disabled crispy form errors 2020-11-05 14:44:04 -05:00
eeintech
5b3dd63b89 Fixed saving of purchase and sales order forms 2020-11-05 14:38:54 -05:00
eeintech
684db67733 Added check for remove too 2020-11-05 09:37:01 -05:00
eeintech
0b76d1d036 Check if permission is not NoneType before adding to group 2020-11-05 09:34:18 -05:00
Oliver
15ea73a448 Merge pull request #1106 from SchrodingersGat/build-tabs
Rename tabs for build order
2020-11-05 20:39:25 +11:00
Oliver Walters
a35c4a5a95 Rename tabs for build order 2020-11-05 20:07:23 +11:00
Oliver
7e4b84f016 Merge pull request #1105 from SchrodingersGat/build-fix-fixes
Set the specified location of a build output
2020-11-05 18:25:00 +11:00
Oliver Walters
2591d34260 Fixed bug where "New output" button stopped working
- Build status was changing from "PENDING" to "PRODUCTION"
- Created new check for active builds
2020-11-05 15:57:46 +11:00
Oliver Walters
d44092b209 Fix issue with shadowed form field
- Rename "quantity" to "output_quantity" to address this
2020-11-05 15:52:38 +11:00
Oliver Walters
8b7789cdb3 Set the specified location of a build output 2020-11-05 15:46:42 +11:00
Oliver
6c89a2aaeb Merge pull request #1099 from eeintech/fix_related_parts
Fix PartRelated (based on updated AjaxCreateView class)
2020-11-05 09:51:06 +11:00
eeintech
324645b67c Added same level category checkbox and method when adding category template 2020-11-04 12:26:10 -05:00
eeintech
e401bb8e3c Improved tests, fixed admin, improved naming 2020-11-04 12:06:07 -05:00
eeintech
1c14c2237a Moved category templates processing to Part save() method 2020-11-04 09:52:26 -05:00
eeintech
9eba564ff6 Merge branch 'master' of git://github.com/inventree/InvenTree into categories_parameters 2020-11-04 07:52:16 -05:00
eeintech
142cea0cbb Removed custom form save method, remove unused model methods, restored InvenTree CreateAjaxView, improved part related testing 2020-11-04 07:44:06 -05:00
eeintech
853a821497 Merge branch 'master' of git://github.com/inventree/InvenTree into fix_related_parts 2020-11-04 06:46:20 -05:00
Oliver
dc626ed68b Merge pull request #1103 from SchrodingersGat/image-upload-fixes
Bug fix: Part thumbnail API list was not working
2020-11-04 16:24:04 +11:00
Oliver Walters
f560be1a9a Bug fix: Part thumbnail API list was not working
- Part images could not be selected from grid
2020-11-04 15:41:17 +11:00
Oliver
ede7d6dbde Merge pull request #1102 from SchrodingersGat/coveralls-fix
Updated to latest version of coverage and coveralls
2020-11-04 14:12:57 +11:00
Oliver Walters
5f6f722d6c Change from python-coveralls to coveralls 2020-11-04 13:30:17 +11:00
Oliver Walters
f8da15287c Updated to latest version of coverage and coveralls 2020-11-04 09:35:43 +11:00
Oliver
fc99086c8f Merge pull request #1101 from SchrodingersGat/delete-on-deplete-fix
Logic fix for editing stock item creation form
2020-11-04 09:33:52 +11:00
eeintech
4e157fe956 Fixed text for parent categories checkbox 2020-11-03 17:05:08 -05:00
eeintech
279d5a00ce Switched to get_ancestors to transverse all parents categories (not only root) 2020-11-03 16:58:53 -05:00
eeintech
5a5a36083e Finalized implementation when creating new part 2020-11-03 16:54:46 -05:00
Oliver Walters
56b287b2c8 Logic fix for editing stock item creation form 2020-11-04 08:29:09 +11:00
eeintech
72b5a105f8 Made all categories accessible for parameter templates configuration 2020-11-03 14:45:53 -05:00
eeintech
0882528b82 Missing class trailing space 2020-11-03 11:15:16 -05:00
eeintech
32b46cdc2a Added better PartRelated creation test 2020-11-03 11:14:31 -05:00
eeintech
de2b7e5daf Re-added post_save method in AjaxCreateView 2020-11-03 08:03:16 -05:00
eeintech
6b702ef676 Manually merged part migrations 2020-11-03 07:27:51 -05:00
Francois
b1885138de Merge branch 'master' into categories_parameters 2020-11-03 07:01:56 -05:00
Oliver
1e844c642f Merge pull request #1063 from SchrodingersGat/build-fixes
Build system updates
2020-11-03 22:58:38 +11:00
Oliver Walters
2e1a5a85a3 Bug fix for unit testing 2020-11-03 22:14:02 +11:00
Oliver Walters
3ea671986c Merge conflicting migration files 2020-11-03 21:29:25 +11:00
Oliver Walters
083dac1300 Merge remote-tracking branch 'inventree/master' into build-fixes 2020-11-03 21:26:39 +11:00
Oliver
1c503adced Merge pull request #1026 from eeintech/user_unique_group_validation
Added check for multiple groups assigned to user
2020-11-03 21:21:08 +11:00
Oliver
ef2c04baa8 Merge pull request #1048 from eeintech/related_parts
Related Parts
2020-11-03 21:18:27 +11:00
Oliver Walters
897d9b4831 Update translation files 2020-11-03 21:02:31 +11:00
Oliver Walters
5988e847ce Add serial number suggestions 2020-11-03 21:01:14 +11:00
Oliver Walters
8d0845d92b Mark a build as "production" whenever a build output is created 2020-11-03 20:43:49 +11:00
Oliver Walters
ac03dab8de Tweaks 2020-11-03 20:37:33 +11:00
Oliver Walters
2b91f69c7d Fix unit tests 2020-11-03 20:19:24 +11:00
Oliver Walters
b936f67d87 Various form fixes
- Updating forms, a lot has changed!
2020-11-03 16:21:40 +11:00
Oliver Walters
152801f06f Dramatic speed improvements for build completion
- Might still need to be a background task at some point..
2020-11-03 15:56:20 +11:00
Oliver Walters
3f03adba72 Bug fix for stock table
- Grouped rows were not displaying the part name
2020-11-03 15:05:13 +11:00
eeintech
13a07be728 Added PartCategoryParameterTemplate tests 2020-11-02 15:35:54 -05:00
eeintech
6320384ecb Fixed category parameter template edit form 2020-11-02 15:05:37 -05:00
eeintech
43fab8a8b3 Backtracked on setting category choices (fixed failed migration) 2020-11-02 13:28:34 -05:00
eeintech
34b784d1e4 Added setting, checkbox (PartCreateView only) and hook to create part parameters from category templates 2020-11-02 13:14:31 -05:00
eeintech
978b5f869d Added checkbox to add parameter template to all categories 2020-11-02 12:20:29 -05:00
Oliver Walters
05613b9642 Further build tweaks / improvements 2020-11-02 23:47:36 +11:00
Oliver Walters
f5d0d54ded Improve modal error message 2020-11-02 23:02:02 +11:00
Oliver Walters
500da8099b Add forms / views for creating a new build output, and completing the build
- Also some refactoring of how forms are handled and saved
2020-11-02 22:56:26 +11:00
Oliver Walters
b02c87ea50 Lots of work towards multiple build output 2020-11-02 01:24:31 +11:00
Oliver Walters
f1b83f1c17 Update fixtues for unit testing 2020-11-01 15:34:42 +11:00
eeintech
3a347fba21 Added edit/delete for category parameter templates 2020-10-31 12:55:52 -05:00
eeintech
2a563d7370 Added category list of parameter templates table to settings 2020-10-31 09:18:33 -05:00
eeintech
3e5d8d2b2d Added form to select category in settings and update context data 2020-10-31 08:35:47 -05:00
eeintech
5310ce8465 First step into managing Category Parameters to InvenTree settings 2020-10-30 17:17:18 -05:00
eeintech
34ff05d66e Created PartCategoryParameterTemplate model and admin interface 2020-10-30 16:09:27 -05:00
Oliver Walters
95fadf1300 Update unit testing 2020-10-30 23:08:12 +11:00
Oliver Walters
3a702266e6 Merge remote-tracking branch 'inventree/master' into build-fixes
# Conflicts:
#	InvenTree/InvenTree/views.py
#	InvenTree/build/views.py
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
#	InvenTree/order/views.py
#	InvenTree/part/api.py
#	InvenTree/part/views.py
#	InvenTree/templates/js/bom.js
2020-10-30 22:44:25 +11:00
Oliver
ad90adbc04 Merge pull request #1095 from SchrodingersGat/forms
Refactor how form errors are handled
2020-10-30 22:12:45 +11:00
Oliver Walters
1caa341f8e Fixes for unit tests 2020-10-30 21:34:56 +11:00
Oliver Walters
e049ca1a85 More refactoring 2020-10-30 16:54:05 +11:00
Oliver
87903f27ed Merge pull request #1094 from SchrodingersGat/typo-fix
Fixed a typo in bom.js
2020-10-30 16:23:07 +11:00
Oliver Walters
c533f59405 Refactor how form errors are handled
- Use form.add_error (as the django gods intended)
2020-10-30 16:04:56 +11:00
Oliver Walters
cabbdbb5cf Fixed a typo in bom.js 2020-10-30 15:53:13 +11:00
Oliver
fb28204dfd Merge pull request #1093 from SchrodingersGat/bom-filters
Add filtering for BOM table
2020-10-30 12:45:46 +11:00
Oliver Walters
2428e77969 Add filtering for BOM table 2020-10-30 11:45:54 +11:00
Oliver
1311e5fe58 Merge pull request #1092 from SchrodingersGat/copy-bom
Copy bom
2020-10-30 11:40:06 +11:00
Oliver Walters
5c5641d884 Update calls to post_save 2020-10-30 10:12:42 +11:00
Oliver Walters
2d583d19c2 Adds function to duplicate a BOM from a parent part
- Improves form validation workflow
- More 'djangoesque'
2020-10-30 10:08:06 +11:00
Oliver Walters
90cfb3496a Merge remote-tracking branch 'inventree/master' into build-fixes
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.mo
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
#	InvenTree/templates/js/bom.js
2020-10-29 15:23:51 +11:00
Oliver
a148cfe593 Merge pull request #1088 from SchrodingersGat/tweaks
Tweaks
2020-10-29 15:16:49 +11:00
Oliver Walters
1d6d1121a7 Add some more icons 2020-10-29 13:58:05 +11:00
Oliver Walters
f1a7ac3187 Add icon badges to bom.js 2020-10-29 13:26:32 +11:00
Oliver Walters
fda0bff14c Tweaks to part.js 2020-10-29 13:20:42 +11:00
Oliver Walters
8246e9c802 Add function makeIconBadge for tables
- Add filters for part variants table
2020-10-29 13:18:45 +11:00
Oliver Walters
b3ac261746 Add filter for supplier part table:
Filter by "active" status
2020-10-29 12:50:17 +11:00
Oliver Walters
60a8ef723b Simplify display of possible conflicting parts
- Round to single digit
- Only show 5 closest matches

(cherry picked from commit ed8be5225d)
2020-10-29 12:42:38 +11:00
Oliver Walters
05ce17f8df Tweaks 2020-10-29 09:45:42 +11:00
Oliver Walters
a263d2fdcd Fixes for "auto allocate" concept 2020-10-29 00:49:01 +11:00
Oliver Walters
551064b3a4 Bugfix: BOM API now works slightly differently 2020-10-29 00:07:51 +11:00
Oliver Walters
544b63cac5 Merge remote-tracking branch 'inventree/master' into build-fixes
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
2020-10-29 00:01:10 +11:00
Oliver Walters
4a7e9a2278 Update translations and PEP fixes 2020-10-28 23:59:18 +11:00
Oliver Walters
ed8be5225d Simplify display of possible conflicting parts
- Round to single digit
- Only show 5 closest matches
2020-10-28 23:48:35 +11:00
Oliver Walters
091a9d9803 Refactor how form errors are handled
- When in doubt, refer to the django docs
- There was a *much* better way (thanks, form.add_error)!
- The anti-pattern was deleted, and lo, there was much rejoicing
- Some other refactoring too
2020-10-28 23:33:33 +11:00
Oliver
6dc5ef0cdc Merge pull request #1085 from SchrodingersGat/more-icons
More template updates
2020-10-28 23:29:15 +11:00
Oliver Walters
d8ada930c8 More template updates
- Add icons to more action buttons
2020-10-28 22:37:58 +11:00
Oliver Walters
d06b4d7c9f Merge remote-tracking branch 'inventree/master' into build-fixes
# Conflicts:
#	InvenTree/InvenTree/urls.py
#	InvenTree/locale/de/LC_MESSAGES/django.mo
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
#	InvenTree/part/templates/part/bom.html
#	InvenTree/templates/js/build.js
#	InvenTree/templates/js/table_filters.js
#	InvenTree/templates/stock_table.html
#	tasks.py
2020-10-28 22:25:14 +11:00
Oliver
c8ec55a5fe Merge pull request #1084 from SchrodingersGat/used-in-table
Used in table
2020-10-28 21:21:44 +11:00
Oliver Walters
44010fe05b Translation updates 2020-10-28 18:30:50 +11:00
Oliver Walters
d0b7d91ca4 Update multiple templates with fontawesome icons 2020-10-28 18:30:38 +11:00
Oliver Walters
d272eec384 Update translation files 2020-10-28 18:13:19 +11:00
Oliver Walters
5e70d8df7e Rename javascript files from .html to .js 2020-10-28 18:13:02 +11:00
Oliver Walters
c63480c65b Improve table for displaying what parts a particular part is "used in" 2020-10-28 18:12:38 +11:00
Oliver Walters
3ec2396ec1 Updated allocation card view 2020-10-27 23:33:51 +11:00
Oliver Walters
22a5f921b8 Auto-generate build outputs when a build is created 2020-10-27 23:09:17 +11:00
Oliver Walters
170d55d64e Add custom form validation step 2020-10-27 22:52:01 +11:00
Oliver Walters
4055a36db2 Updated modal forms 2020-10-27 22:29:34 +11:00
Oliver Walters
646fe40950 Require either serial or batch number to be set for trackable part 2020-10-27 22:00:38 +11:00
Oliver Walters
54d5d2899e Update javascript callbacks 2020-10-27 21:47:24 +11:00
Oliver
43907fb129 Merge pull request #1082 from jnewlands/typo_fix_external_link
Fix typo in new / edit part forms ("extenel URL")
2020-10-27 16:43:14 +11:00
James Newlands
c61eeca3e4 Even though nothing happened to the database schema, the field description changed 2020-10-27 15:58:05 +11:00
James Newlands
8bf281e153 Fix typo in new / edit part forms ("extenel URL")
Capitalisation consistency in "Create New Part" form title
2020-10-27 14:52:31 +11:00
Oliver Walters
06a3899325 Disable "unallocate" button if there are not any allocations 2020-10-27 09:26:16 +11:00
Oliver Walters
b5e1d3f87a Sorter fixes 2020-10-27 08:58:29 +11:00
Oliver
9ed787b4da Merge pull request #1077 from SchrodingersGat/custom-tag-fix
Bug fix - re-introduce settings_value custom tag
2020-10-27 07:49:12 +11:00
Oliver Walters
4167e1fdb3 Update translation files 2020-10-26 22:51:57 +11:00
Oliver Walters
210d39c8b7 Bug fix - re-introduce settings_value custom tag
(cherry picked from commit 9203f541be)
2020-10-26 22:44:49 +11:00
Oliver Walters
d8a0ab8879 Fix for build table 2020-10-26 22:44:24 +11:00
Oliver Walters
9203f541be Bug fix - re-introduce settings_value custom tag 2020-10-26 22:44:16 +11:00
Oliver Walters
a4f6efc05d Merge remote-tracking branch 'inventree/master' into build-fixes
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
#	InvenTree/templates/js/build.html
2020-10-26 22:38:43 +11:00
Oliver Walters
b38fde85f2 Added some more buttons, etc 2020-10-26 22:34:40 +11:00
Oliver Walters
5e0d1fe25a Allocate "non tracked" parts separately from tracked ones 2020-10-26 18:21:45 +11:00
Oliver Walters
7525bc2ead Attachment functionality for BuildOrder 2020-10-26 17:00:31 +11:00
Oliver Walters
664dd0000c Add database table for storing file attachments against a BuildOrder 2020-10-26 15:21:03 +11:00
Oliver Walters
8f108d42d2 Add ability to filter BOM status by "validated" field 2020-10-26 14:43:43 +11:00
Oliver Walters
24ab48ef4c Filter BOM table by "trackable" status 2020-10-26 13:53:34 +11:00
Oliver Walters
1a4eb3f870 Display which parts are "trackable" in a BOM table 2020-10-26 13:24:17 +11:00
Oliver Walters
815d4bf7eb Add new template_tag for defining variables 2020-10-26 09:11:25 +11:00
Oliver Walters
ffe15763a7 Update validation "rules" for BuildItem
- A BuildItem which points to a trackable part must also point to a build output
- A BuildItem which points to a non-trackable part cannot point to a build output
2020-10-26 08:34:17 +11:00
Oliver Walters
6aaf178f0b Check "trackable" status of part
- Where a BomItem connects a trackable sub_part with a non-trackable part, force the Part to be trackable
2020-10-26 08:29:06 +11:00
Oliver
720579dcd7 Merge pull request #1070 from SchrodingersGat/global-settings
Global settings
2020-10-25 22:22:57 +11:00
Oliver Walters
e978e1df52 Style fixes 2020-10-25 22:11:24 +11:00
Oliver Walters
5908890726 Create setting if it does not exist 2020-10-25 22:07:11 +11:00
Oliver Walters
549f50ac3f Update translations 2020-10-25 21:54:53 +11:00
Oliver Walters
9284837da8 Bug fixing 2020-10-25 21:45:37 +11:00
Oliver Walters
7d95faa4f5 Cleanup code 2020-10-25 21:43:33 +11:00
Oliver Walters
432ecc1d96 Display boolean values as checkboxes 2020-10-25 21:33:13 +11:00
Oliver Walters
3a325399c6 Use a checkbox input when editing a boolean setting 2020-10-25 21:00:06 +11:00
Oliver Walters
f1e8afa314 Add boolean validator 2020-10-25 09:36:58 +11:00
Oliver Walters
73296eafcb Update translation files 2020-10-25 08:18:33 +11:00
Oliver Walters
4d96b385b1 Add page for global settings 2020-10-25 08:17:41 +11:00
Oliver Walters
b57a78dea4 Add some context data to the view for editing a setting 2020-10-25 08:10:52 +11:00
Oliver Walters
e3f5e8fbb1 PEP fixes 2020-10-25 08:04:04 +11:00
Oliver Walters
3e17bf3316 Edit setting directly 2020-10-25 08:02:46 +11:00
Oliver Walters
10758a9626 Improvements for global settings
- Name and description are defined in models.py
- Lookup functions for name / description / units / default
- Shortcut template for rending settings
- More unit testing
2020-10-25 07:49:38 +11:00
Oliver Walters
767ceed698 Update translation files 2020-10-24 22:13:40 +11:00
Oliver Walters
c63a09330f Hide some buttons if row is fully allocated already 2020-10-24 22:05:19 +11:00
Oliver Walters
42c1210fba Calculate required build quantity 2020-10-24 13:16:43 +11:00
Oliver Walters
a3265ef9fd Unallocate stock against a particular line item 2020-10-24 13:15:13 +11:00
Oliver Walters
b7e7543be6 Add some more buttons to build table 2020-10-24 12:59:05 +11:00
Oliver Walters
b45a11aa3d Refactor: Add "makeIconBadge" javascript function 2020-10-24 00:33:30 +11:00
Oliver Walters
ea7b1b65d6 Delete a build output entirely
TODO: Needs to describe in the confirmation dialog what is going to happen!
2020-10-24 00:14:27 +11:00
Oliver Walters
a71a51b848 Build can be "unallocated" against a single build output 2020-10-23 23:52:59 +11:00
Oliver Walters
fb7d9a7edf Move "getAvailableStockItems" to the build model 2020-10-23 23:33:27 +11:00
Oliver Walters
0752df26dc Bug fixes for BuildItemCreate view:
- Add option to calculate required quantity against a particular build output, not just the build
2020-10-23 23:09:22 +11:00
Oliver Walters
076d5c4f7f Cleanup get_required_parts function 2020-10-23 22:49:46 +11:00
Oliver
5e63ccc9f6 Merge pull request #1043 from eeintech/unique_email_company
[Company] Allow duplicate names - Unique name/email pair
2020-10-23 13:23:48 +11:00
Oliver
cd4cb12937 Merge pull request #1064 from eeintech/company_permissions
Company permissions
2020-10-23 13:20:59 +11:00
eeintech
647182237e Merge branch 'master' of git://github.com/inventree/InvenTree into unique_email_company 2020-10-22 12:05:22 -05:00
Oliver Walters
5db043ab4b Launch modal dialog to auto-allocate against a specific build output 2020-10-23 01:05:59 +11:00
Oliver Walters
f4f6253178 Better table sorting for allocation quantity 2020-10-23 00:58:35 +11:00
Oliver Walters
33c454ed5a Add action buttons to each build output 2020-10-23 00:51:01 +11:00
Oliver Walters
6245d65ebc Tweaks 2020-10-23 00:08:40 +11:00
Oliver Walters
23ac83d2a8 Change extension on "dynamic" js files
- Yay, the editor now highlights code properly!
2020-10-22 23:59:21 +11:00
Oliver Walters
ae20db0ec6 Add actions for the sub-table allocation list 2020-10-22 23:57:07 +11:00
Oliver Walters
d37cdd8e50 Improved filtering for stockitems going into a buildallocation 2020-10-22 23:49:23 +11:00
Oliver Walters
fae516b38e Add build output selection to builditem creation form 2020-10-22 23:28:15 +11:00
Oliver Walters
1ca08f8bff Filter builditem API by 'output' stock item 2020-10-22 21:43:53 +11:00
Oliver
5877b9616d Merge pull request #1066 from eeintech/fix_part_null_notes_template
Fixed Part notes template (check for NULL value before mardown render)
2020-10-22 09:53:15 +11:00
eeintech
9131edc43d Company index: swapped 'title' for 'pagetype' for adding company button 2020-10-21 09:34:49 -05:00
eeintech
1ef21700c0 Fixed Part notes template (check for NULL value before mardown render) 2020-10-21 09:26:07 -05:00
Oliver Walters
f989d3b3ec Change to using spinner icon 2020-10-21 17:02:04 +11:00
eeintech
46b889c572 Assigned all user permissions for company tests 2020-10-20 14:52:34 -05:00
eeintech
de65e1631d Updated company templates permissions 2020-10-20 14:46:10 -05:00
eeintech
39eddc7203 Added user permissions on company views 2020-10-20 14:11:40 -05:00
Oliver Walters
96277edcf1 Improvements to progress bar function 2020-10-21 00:49:17 +11:00
Oliver Walters
8ae16a125e Build - Add functions to access build outputs 2020-10-21 00:24:55 +11:00
Oliver Walters
e02536071d Add a "completed" field to the Build model
- Keeps track of how many outputs have been produced
- Will not be directly editable by the user
2020-10-20 23:59:37 +11:00
Oliver Walters
fd6d630037 Improve grouping in Stock table 2020-10-20 23:45:36 +11:00
eeintech
5793839a01 Added UniqueConstraint on name/email pair, renamed migration file 2020-10-20 07:37:07 -05:00
Oliver Walters
3bb247a135 Create an initial stockitem output when a new build is created 2020-10-20 23:27:43 +11:00
eeintech
7bc925d016 Merge branch 'master' of git://github.com/inventree/InvenTree into unique_email_company 2020-10-20 07:19:48 -05:00
Oliver Walters
652c2dbcbe Automagically disable 'serial_numbers' field for StockItemCreate form
- Yay, ajax magic!
2020-10-20 22:37:55 +11:00
Oliver Walters
2e4613e702 Updates to build forms / etc 2020-10-20 22:37:21 +11:00
Oliver Walters
2df0f03a9a Change "ALLOCATED" to "PRODUCTION" 2020-10-20 21:10:36 +11:00
Oliver Walters
ac79e131bc Add "destination" field to BuildOrder 2020-10-20 21:01:51 +11:00
Oliver Walters
28460b3023 Validate that the BuildItem quantity is an integer 2020-10-20 20:42:29 +11:00
Oliver Walters
fdcef7b699 Add "install_into" field for BuildItem
- Points to which output stock item it will be going into
2020-10-20 20:37:57 +11:00
Oliver
bc6f58cf26 Merge pull request #1061 from SchrodingersGat/migration-fix
Except IntegrityError
2020-10-20 20:35:59 +11:00
Oliver Walters
4193d2e7fe Except IntegrityError
- This error may be thrown if the correct migrations have not been applied
2020-10-20 19:52:04 +11:00
Oliver
85ac1bfb95 Merge pull request #1058 from SchrodingersGat/stock-table-ordering
Fix table sorting when groups are used.
2020-10-20 12:07:11 +11:00
Oliver Walters
73a1765a11 Fix table sorting when groups are used.
This is necessary because the field names of the tables are specified like "part_detail.IPN" and multi-level string-based object access is weird.
Luckily someone has worked out the hard part for me.

Ref: https://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference
2020-10-20 11:54:54 +11:00
Oliver
d242e04e64 Merge pull request #1055 from SchrodingersGat/build-reference
Build reference
2020-10-20 09:03:25 +11:00
Oliver Walters
a2ee172058 Updates tables for PurchaseOrder and SalesOrder 2020-10-20 08:45:17 +11:00
Oliver Walters
5a6697866f Update translations 2020-10-20 08:41:13 +11:00
Oliver Walters
406d7bcf80 Load build order prefix setting 2020-10-20 08:41:08 +11:00
Oliver Walters
7aa473712f Remove unused setting page 2020-10-20 08:32:00 +11:00
Oliver Walters
226a91718b Add a simple unit test for the settings model 2020-10-20 08:29:06 +11:00
Oliver Walters
c6e61c20fe Generate default settings for all InvenTreeSetting object 2020-10-20 08:24:23 +11:00
Oliver Walters
98d20bceeb Change "Build Title" to "Description" 2020-10-20 00:26:26 +11:00
Oliver Walters
e8a0095e50 Add some options for the build order settings page
- Not editable yet
2020-10-20 00:24:33 +11:00
Oliver Walters
a5639c380f Add regex validator to build order reference field 2020-10-20 00:13:43 +11:00
Oliver Walters
06040f94ee Remove "description" field from InvenTreeSettings key:value fields 2020-10-20 00:02:54 +11:00
Oliver Walters
92c1e3c1a5 Update settings pages 2020-10-19 23:50:39 +11:00
Oliver Walters
c13cee2407 Fixes for unit testing 2020-10-19 23:31:52 +11:00
Oliver Walters
9b7a9a3ee0 Update formatting of order pages 2020-10-19 23:23:16 +11:00
Oliver Walters
b5d15aab08 Add function to "predict" next build order reference value 2020-10-19 23:22:09 +11:00
Oliver Walters
5405ad566e Add 'reference' to API serializer 2020-10-19 22:53:40 +11:00
Oliver Walters
0b7cf9e7f3 Add "reference" to build order forms 2020-10-19 22:49:28 +11:00
Oliver Walters
a8d47c54f9 Upate admin interface 2020-10-19 22:40:19 +11:00
Oliver Walters
934078a42c Add "Reference" field to Build model 2020-10-19 22:36:14 +11:00
Oliver
416cfb99da Merge pull request #1053 from SchrodingersGat/modal-errors
Modal errors
2020-10-19 22:19:10 +11:00
Oliver Walters
6b99d923d7 Change "status code" to "error code" 2020-10-19 16:44:33 +11:00
Oliver Walters
396b7dba73 Extra error information when a modal dialog fails 2020-10-19 16:42:53 +11:00
Oliver
957c538136 Merge pull request #1052 from SchrodingersGat/barcode-add
Change text for barcode
2020-10-19 16:31:47 +11:00
Oliver Walters
647e2cf64d Change text for barcode 2020-10-19 16:06:18 +11:00
Oliver
ce1cce99bb Merge pull request #1051 from SchrodingersGat/po-stock-list
Display table of items received against a particular purchase order
2020-10-19 11:55:25 +11:00
Oliver Walters
634410294b Display table of items received against a particular purchase order
- Adds new tab to "Purchase Order" view
- Adds ability to filter StockList API by purchase_order ID
2020-10-19 11:40:57 +11:00
Oliver
2dc9109b11 Merge pull request #1047 from eeintech/add_ipn_supplier_part_str
Added IPN to Supplier Part string representation (global)
2020-10-19 11:21:34 +11:00
eeintech
dfa4d3f8ed Display IPN and pipe char only if IPN exists 2020-10-18 14:37:35 -05:00
eeintech
d1df647dde Merge branch 'master' of git://github.com/inventree/InvenTree into add_ipn_supplier_part_str 2020-10-18 14:33:38 -05:00
Oliver
529c4052ff Merge pull request #1038 from mpdgraev/fix_int_barcode
fix error when submitting some non-dict barcodes
2020-10-19 00:01:38 +11:00
Oliver
7edd08035f Merge pull request #1049 from SchrodingersGat/api-default-location
Update creation of StockItem via API
2020-10-18 22:49:09 +11:00
Oliver Walters
3c175a6c8d Update creation of StockItem via API
- If no location is specified, but a default location exists for the part, use that
- If a location is specified (even if it is null) then the specified value is used instead
2020-10-18 22:24:45 +11:00
Oliver
83077514cb Merge pull request #1041 from eeintech/api_default_location
Added part 'default_location' to serializer
2020-10-18 22:01:35 +11:00
Oliver
4d4f0e5cfc Merge pull request #1044 from eeintech/stock_permissions
Fixed insertion of backslash in the Stock barcode button group
2020-10-18 21:11:09 +11:00
eeintech
5a6cac43f5 Updated migration 2020-10-16 15:42:23 -05:00
eeintech
0b26d68d0f Added admin view, improved validation of part related relationship 2020-10-16 15:29:58 -05:00
eeintech
34e4409e7f Functional checkpoint: add/delete related parts from template 2020-10-16 13:50:31 -05:00
eeintech
8579abb9c2 Added related parts urls, views, form and templates
Adding related part relationships work but are still not shown in the part detail page
2020-10-15 16:58:39 -05:00
eeintech
3d9223c2ee Introduced PartRelated model to store part relationships 2020-10-15 14:11:24 -05:00
eeintech
af6b30eaca Added IPN to Supplier Part string representation
Improved Supplier Part templates and fixed 'Order Part' button in supplier_part_orders
2020-10-15 13:09:00 -05:00
eeintech
dbee26aaad Fixed insertion of backslash in the barcode button group 2020-10-13 10:29:34 -05:00
eeintech
70a3b7f891 Improved migration, still fails if email duplicates exist in current DB 2020-10-13 07:43:57 -05:00
eeintech
ac82640c6c Company: allowed duplicate names, made email field unique, custom migration 2020-10-12 17:51:48 -05:00
eeintech
3143242d13 Added category 'default_location' to serializer 2020-10-12 13:14:24 -05:00
eeintech
eb98496a79 Added part 'default_location' to serializer 2020-10-12 07:25:32 -05:00
mpdgraev
f1f31a1338 fix error caused by assumption that json.loads() returns an object with a .keys() function 2020-10-09 16:32:54 +02:00
Oliver
ca8472ac23 Merge pull request #1037 from SchrodingersGat/tz-support
Add support for setting timezone in config.yaml
2020-10-08 21:35:36 +11:00
Oliver Walters
3d60bccae0 Add support for setting timezone in config.yaml 2020-10-08 21:02:38 +11:00
Oliver
26ee3032f6 Merge pull request #1036 from SchrodingersGat/bom-quantity-export
Normalize quantity field when exporting BOM
2020-10-08 14:21:50 +11:00
Oliver Walters
8b16304e84 Custom 404 page 2020-10-08 14:09:08 +11:00
Oliver Walters
b595f3b732 Normalize quantity field when exporting BOM 2020-10-08 14:05:55 +11:00
Oliver
305920d1ac Merge pull request #1030 from eeintech/stock_permissions
Stock permissions
2020-10-07 14:11:52 +11:00
Oliver
ec4bc357df Merge pull request #1031 from eeintech/fix_superuser_permission
Fixed context permissions for superuser with no group assigned
2020-10-07 13:40:59 +11:00
eeintech
01eee4d208 Fixed style 2020-10-06 10:40:58 -05:00
eeintech
8499ced636 Changed from validation error to warning message when group instance is saved 2020-10-06 10:38:06 -05:00
eeintech
19a2326638 Merge branch 'master' of git://github.com/inventree/InvenTree into user_unique_group_validation 2020-10-06 10:04:35 -05:00
eeintech
1ce2166843 Fixed context permissions for superuser with no group assigned 2020-10-06 09:59:51 -05:00
eeintech
5bcf8529ff Only users with Part view permission have part URL shown 2020-10-06 09:16:38 -05:00
eeintech
e4ce19d22a Added Test user and all permissions 2020-10-06 09:02:10 -05:00
eeintech
095cfe9845 Updated Stock permission views and templates 2020-10-06 08:55:40 -05:00
Oliver
279b50d977 Merge pull request #1029 from SchrodingersGat/sales-order-permissions
Sales order permissions
2020-10-06 20:44:01 +11:00
Oliver Walters
8b37229e4b The real translations are the ones we made along the way 2020-10-06 20:31:38 +11:00
Oliver Walters
b80e4302ba Update permissions for build app 2020-10-06 20:29:16 +11:00
Oliver Walters
2325b1e4ba Unit test fixes 2020-10-06 20:10:14 +11:00
Oliver Walters
9abb211cdf Update template permissions 2020-10-06 20:09:55 +11:00
Oliver Walters
1c97aaf87a Set permissions for order views 2020-10-06 19:46:53 +11:00
Oliver
606c62078f Merge pull request #1024 from SchrodingersGat/part-permissions
Permissions
2020-10-06 18:29:05 +11:00
Oliver Walters
ab454e5ba4 More template changes: perms -> roles 2020-10-06 16:46:13 +11:00
Oliver Walters
88f73443ee Yet more style fixes 2020-10-06 16:43:39 +11:00
Oliver Walters
77a2b6de8b Merge branch 'part-permissions' of https://github.com/SchrodingersGat/InvenTree into part-permissions 2020-10-06 16:03:33 +11:00
Oliver Walters
b3e4efd96e Unit testing fixes 2020-10-06 16:03:19 +11:00
Oliver
e076470305 Merge branch 'master' into part-permissions 2020-10-06 12:35:45 +11:00
Oliver Walters
d691b15f4b Fix conflicts 2020-10-06 12:34:30 +11:00
Oliver Walters
11d31960c7 Change modal form permissions to use new "role" strategy 2020-10-06 11:42:16 +11:00
Oliver Walters
c740cce5e4 PEP fixes 2020-10-06 11:31:04 +11:00
Oliver Walters
dc2c9aa662 Add InvenTreeRoleMixin
- Simplifies permission requirements for views
- e.g. 'part.view' rather than 'part.view_partcategory'
2020-10-06 11:29:38 +11:00
Oliver Walters
d2e2e7511f Update templates: Change perms to roles 2020-10-06 10:07:39 +11:00
Oliver Walters
fa21d66c41 Fix logic for global context object 'roles'
- User may be a part of multiple groups
- Roles are additive across groups
2020-10-06 09:54:37 +11:00
Oliver Walters
23aee234f0 Change index page to use roles rather than perms to determine user permissions 2020-10-06 09:32:05 +11:00
Oliver Walters
556ffa1099 Change label for permissions to match django permission names 2020-10-06 09:28:05 +11:00
Oliver Walters
8b2189daca Add global context 'roles'
- Access via template e.g. {% if roles.part.view %}
- Always True if the user is a superuser
2020-10-06 09:27:22 +11:00
Oliver
e74bfb90a5 Merge pull request #1025 from eeintech/fixed_group_redundant_saves
Fixed Group model permissions redundant saves
2020-10-06 07:40:44 +11:00
eeintech
911b23ca24 Added validation logic for user list to Group admin form 2020-10-05 13:12:52 -05:00
eeintech
d980da7247 Fixed permission assign test unit 2020-10-05 10:52:47 -05:00
eeintech
c910307ce5 Only saving Group model rulesets on instance creation and when inlines are saved 2020-10-05 10:04:54 -05:00
Oliver Walters
3f59ce3f93 Update unit tests
- requires the user to actually have the necessary permissions!
2020-10-06 01:30:36 +11:00
Oliver Walters
16d720b62c Update permission requirements for API
- Automatically use model permissions by default!
-
2020-10-06 00:36:55 +11:00
Oliver Walters
8ee16d6f98 update translation files 2020-10-06 00:20:57 +11:00
Oliver Walters
ba4c829b10 Add permission requirements in various part templates 2020-10-06 00:20:45 +11:00
Oliver Walters
afadd51a14 Fix permissions in views.py
Silly, "add" not "create"
2020-10-06 00:19:44 +11:00
Oliver Walters
66bdce3d04 Hide elements on the PartCategory page, based on permissions 2020-10-05 23:53:24 +11:00
Oliver Walters
4d49cb029f Change part views to require permissions
Also adds custom 403 page
2020-10-05 23:49:32 +11:00
Oliver
796e89c921 Merge pull request #1023 from SchrodingersGat/index-permissions
Change what elements the user can see on the index page
2020-10-05 23:19:13 +11:00
Oliver Walters
3e9c7cda21 Change what elements the user can see on the index page, based on permissions! 2020-10-05 23:11:55 +11:00
Oliver
e5960f6ce4 Merge pull request #1022 from SchrodingersGat/permission-fixes
Fixes for role permissions
2020-10-05 23:04:50 +11:00
Oliver Walters
806a7f961d Fixes for role permissions
- Fixed a strange interaction if multiple rulesets referred to the same models
- Order of operations was incorrect.
- Now is good? Yes!
2020-10-05 22:57:05 +11:00
Oliver
731c796254 Merge pull request #1011 from SchrodingersGat/navbar-permissions
Hide main elements of navigation bar based on user permissions
2020-10-05 11:17:41 +11:00
Oliver
dc41231fcc Merge pull request #1018 from SchrodingersGat/group-roles
Roles and Permissions
2020-10-05 11:16:52 +11:00
Oliver
cc05220263 Merge pull request #1020 from SchrodingersGat/stock-building
Add "is_building" field to StockItem model
2020-10-05 10:08:40 +11:00
Oliver Walters
898c604b3b Fix incorrect permission names
- Uses the app_model name, *NOT* the name of the database table
- Adds extra tests to ensure that permissions get assigned and removed correctly
2020-10-05 08:55:15 +11:00
Oliver Walters
095ef51991 Cleanup unit testing 2020-10-05 08:29:36 +11:00
Oliver Walters
bce7eb1aad update translation files 2020-10-05 01:02:36 +11:00
Oliver Walters
13cd8624b2 Fix permissions 2020-10-05 01:01:56 +11:00
Oliver Walters
48e050d317 Add some more unit tests and validation code for the StockItem model
- Ensure that the build part matches the stockitem part!
2020-10-05 00:49:00 +11:00
Oliver Walters
3ee7be1d58 Add "optional" field to BomItem
- Defaults to False
- Indicates that the BomItem is "optional" for a build
- Will be used in the future when calculating if a Build output is fully allocated!
2020-10-05 00:42:09 +11:00
Oliver Walters
c1595396c4 Unit testing: fix PEP issues 2020-10-05 00:29:31 +11:00
Oliver Walters
fe3a72c6cc Add some unit testing 2020-10-05 00:29:06 +11:00
Oliver Walters
26d113e8ad Update IN_STOCK_FILTER to reject stock items which have is_building set to True 2020-10-05 00:14:04 +11:00
Oliver Walters
ee28b4eea5 Add "is_building" field to StockItem model
- This will be set to TRUE until a stock item has been completed
2020-10-05 00:12:42 +11:00
Oliver
7f3ce9b0b1 Merge pull request #1019 from SchrodingersGat/installed-stock-improvements
Improvements for the "Installed Items" tab for StockItem display
2020-10-05 00:09:23 +11:00
Oliver Walters
62734c4b72 Add a custom template for the install item form 2020-10-05 00:01:01 +11:00
Oliver Walters
3fe0886207 Remove a debug statement 2020-10-04 23:49:01 +11:00
Oliver Walters
852da6d696 Fix form validation 2020-10-04 23:48:15 +11:00
Oliver Walters
42a75a8238 Add hidden input to the InstallStockForm form
- keeps track of "part" object
- so we can filter the stock_items queryset if the form validation fails
- Is there a more djangonic way of doing this??
2020-10-04 23:45:52 +11:00
Oliver Walters
46f459b4c7 Better display of stock table 2020-10-04 23:34:02 +11:00
Oliver Walters
b9291c6705 Improve transaction note recording for the StockItem model 2020-10-04 23:33:43 +11:00
Oliver Walters
824ce6778f Progress bar tweaks
- If no maximum value supplied, just show the value (and fill to 100% width)
2020-10-04 23:33:20 +11:00
Oliver Walters
3c5968ef1a Add subrow table to the "installed items" view
Ah, javascript...
2020-10-04 22:58:41 +11:00
Oliver Walters
9c27680202 Finish function to install stock item(s) 2020-10-04 21:32:21 +11:00
Oliver Walters
45c888e13d Custom cleaning for form
Ok, looks like I've been doing this wrong the whole time!
The "djangonic" way is pretty cool
2020-10-04 21:31:44 +11:00
Oliver Walters
a686500df1 Calculate initial values for the view 2020-10-04 21:02:20 +11:00
Oliver Walters
fd22e713ff Filter available stock items by Part reference 2020-10-04 20:50:06 +11:00
Oliver Walters
f04977e7e1 Add form / view for installing a stock item into another stock item 2020-10-04 20:41:28 +11:00
Oliver Walters
b467c8a1ef Add front-end functions to render an "installed stock" table 2020-10-04 15:17:46 +11:00
Oliver Walters
b27f926310 Add ability to filter BOM API by "trackable" status of the sub_part object 2020-10-04 13:51:52 +11:00
Oliver Walters
fb09f53dc9 Add missing migration file 2020-10-04 12:58:45 +11:00
Oliver Walters
929411e49a Remove "general" ruleset 2020-10-04 12:53:24 +11:00
Oliver Walters
31b699d521 Hide "user permissions" view from the admin interface 2020-10-04 12:47:19 +11:00
Oliver Walters
cda52a58e3 Remove manual 'permissions' control from groups admin interface
- Does not actually *do* anything any more as the RuleSet approach overrides it anyway
2020-10-04 12:19:56 +11:00
Oliver Walters
c19c014f55 Add or remove permissions from groups as defined by the RuleSet links
- Only runs when the group is changed
- Does not add permissions if they already exist
- Does not remove permissions if they do not exist
2020-10-04 12:18:31 +11:00
Oliver Walters
d5c0c12d78 Add some more unit testing
- ALL models must be covered by rulesets
- Added a RULESET_IGNORE list for models we do not want permissions for
2020-10-04 11:03:14 +11:00
Oliver Walters
c09b4980ad PEP fixes 2020-10-04 00:43:02 +10:00
Oliver Walters
1ded9e1fc0 Add a warning showing which databases tables are not covered by defined rulesets 2020-10-04 00:38:53 +10:00
Oliver Walters
6c2eb959a6 More unit testing 2020-10-04 00:34:22 +10:00
Oliver Walters
2039100d3e Add some unit testing 2020-10-04 00:24:48 +10:00
Oliver Walters
6bc5fe2497 Tab fix 2020-10-04 00:03:10 +10:00
Oliver Walters
9e4cc73b1c Add migration files 2020-10-04 00:01:18 +10:00
Oliver Walters
16f1b4c784 Add hook to update group permission roles
(doesn't do anything yet)
2020-10-03 23:45:24 +10:00
Oliver Walters
bedda66949 Add custom admin view for the "Group" model
- Ref: https://github.com/Microdisseny/django-groupadmin-users
- Adds ability to edit users within a particular group from the group admin page!
2020-10-03 17:37:20 +10:00
Oliver
d81aa5c051 Merge pull request #1017 from SchrodingersGat/admin-shell
Add shell interface
2020-10-03 16:24:55 +10:00
Oliver Walters
c7403fd512 Add shell interface 2020-10-03 16:18:03 +10:00
Oliver
e6526288cd Merge pull request #1013 from SchrodingersGat/next-available-fix
Fix for "next avilable serial number" string
2020-10-02 14:01:25 +10:00
Oliver Walters
f12f8156bd Fix for "next avilable serial number" string 2020-10-02 13:54:23 +10:00
Oliver
7f3018ebf8 Merge pull request #1008 from eeintech/parametric_part_tables
Add parametric part tables to category detail page
2020-10-02 08:56:05 +10:00
eeintech
496232ed6d Added tests for Category parameters methods, some code clean-up 2020-10-01 13:46:56 -05:00
eeintech
9d3d9a190b Added bootstrap table 'filter-control' extension to use in parametric tables 2020-10-01 12:10:35 -05:00
eeintech
15e1c05791 Fixed 'Part' column sorting 2020-10-01 11:05:08 -05:00
eeintech
b7d25a75c4 Hide part toolbar, nicer part representation, improved parameters prefetching 2020-10-01 10:03:49 -05:00
eeintech
a71b5ef0a0 Merge branch 'master' of git://github.com/inventree/InvenTree into parametric_part_tables 2020-10-01 09:02:21 -05:00
Oliver
7356fc3dfc Merge pull request #1002 from eeintech/empty_search_query
Empty search query returned all elements from database
2020-10-01 09:34:02 +10:00
eeintech
4763f3ea46 Reformulated empty query message 2020-09-30 11:53:14 -05:00
eeintech
87d836617e Merge branch 'master' of git://github.com/inventree/InvenTree into empty_search_query 2020-09-30 11:50:12 -05:00
Oliver
4f648f8787 Merge pull request #1010 from SchrodingersGat/admin-permission-fixes
Update admin links to require specific permissions
2020-10-01 00:37:43 +10:00
Oliver Walters
756f3ddb0f Hide main elements of navigation bar based on user permissions 2020-10-01 00:25:24 +10:00
Oliver Walters
626d0266c8 Add framework for required permissions for any ajax modal forms
- Default permissions of "*" will not immediately change any modal forms
- Set the permission_required attribute of any modal form for this to be implemented
2020-10-01 00:16:04 +10:00
Oliver Walters
56660d52f2 Add "permission denied" message on modal forms 2020-10-01 00:09:21 +10:00
Oliver Walters
81864a6ab8 Fix button layout for stock table 2020-10-01 00:00:37 +10:00
Oliver Walters
27656633df Update admin links to require specific permissions 2020-09-30 23:57:23 +10:00
Oliver
400f183597 Merge pull request #1009 from SchrodingersGat/ipn-filter
Add filtering for parts which have an IPN set
2020-09-30 23:55:27 +10:00
Oliver Walters
a952dc38a3 Add filtering for parts which have an IPN set 2020-09-30 23:35:39 +10:00
Oliver
c4cae02170 Update version.py 2020-09-30 08:06:58 +10:00
Oliver
8ea2c627c4 Update version.py
Bump version number for release
2020-09-30 08:06:37 +10:00
Oliver
064a142d76 Merge pull request #1006 from SchrodingersGat/install_into
UI stuff
2020-09-30 08:03:34 +10:00
Oliver Walters
4f1d087654 PEP fix 2020-09-30 07:56:44 +10:00
eeintech
40d8a07acc Now loading data! Still need to be bonified 2020-09-29 16:49:53 -05:00
eeintech
d05a5978a0 Unique parameters names from category makes it to bootstrap table 2020-09-29 16:13:08 -05:00
eeintech
6b48977e7b Added 'Parametric Table' tab to category detail view, added part_count to 'Parts' tab 2020-09-29 15:16:12 -05:00
Oliver Walters
d1cce7df94 Add direct admin links if the user is staff 2020-09-30 00:02:10 +10:00
Oliver Walters
0e5f10c020 Add some more search terms to the admin interface 2020-09-29 23:41:50 +10:00
Oliver Walters
1f6cbd7408 Add action to uninstall a particular stock item 2020-09-29 23:11:37 +10:00
eeintech
18e19d7920 Empty search query returned all elements from database 2020-09-28 16:34:41 -05:00
Oliver
9e4a599c44 Merge pull request #1001 from SchrodingersGat/index-fix
Change layout for the index page
2020-09-28 22:23:08 +10:00
Oliver Walters
e78e649aa9 Change layout for the index page
- Expanding one table doesn't force the neighbouring one to be expanded also
2020-09-28 22:22:48 +10:00
Oliver
41d6ad2db9 Merge pull request #1000 from SchrodingersGat/installed-in
Installed in
2020-09-28 22:16:07 +10:00
Oliver Walters
38beaff01b peppy 2020-09-28 22:09:09 +10:00
Oliver Walters
d348d90fbe Cleanup errors in unit testing 2020-09-28 22:08:38 +10:00
Oliver Walters
ae55c81dae Updated translation files 2020-09-28 22:04:08 +10:00
Oliver Walters
54bfcff213 CHange "parts" to "items" 2020-09-28 22:03:41 +10:00
Oliver Walters
b2b22762ef style fixes 2020-09-28 22:01:45 +10:00
Oliver Walters
a18886f196 Add some unit tests for the new functions 2020-09-28 22:00:17 +10:00
Oliver Walters
df8d1fb32b Add functions to install and uninstall stock items 2020-09-28 21:52:23 +10:00
Oliver Walters
81ce284264 Select the "default" where we wish to uninstall parts 2020-09-28 21:41:35 +10:00
Oliver Walters
39cfe39172 View / form / url for stock-uninstall form 2020-09-28 21:27:27 +10:00
Oliver Walters
ca6994566d Add better terminal support for invoke server command 2020-09-28 21:26:40 +10:00
Oliver Walters
2ef8464a83 Add buttons to remove installed items from a stock item 2020-09-28 20:27:13 +10:00
Oliver
4de6cc3e4f Merge pull request #999 from SchrodingersGat/build_fix
Fix unit test
2020-09-28 20:20:08 +10:00
Oliver Walters
b58f7d7461 Custom table display for installed stock items 2020-09-28 20:19:56 +10:00
Oliver Walters
d684ed076b Improve table filter naming 2020-09-28 20:10:29 +10:00
Oliver Walters
d8a74ad8b7 Style fixes 2020-09-28 20:08:08 +10:00
Oliver Walters
f253bf1843 Add ability for stock API to be filtered by installed status 2020-09-28 20:07:25 +10:00
Oliver Walters
f409bfd72b More fixes 2020-09-28 19:41:41 +10:00
Oliver Walters
8dd8e69c05 Add "installed parts" tab for stock item 2020-09-28 19:34:43 +10:00
Oliver Walters
97b35d9269 Renamed related name "owned_parts" to "installed_parts" 2020-09-28 19:33:32 +10:00
Oliver Walters
042956ad48 Fix unit test 2020-09-28 19:27:18 +10:00
Oliver
a3f59d8115 Merge pull request #998 from SchrodingersGat/test-report-ordering
Bugfix: Test result ordering was reversed!
2020-09-28 09:02:52 +10:00
Oliver Walters
b76e6a5023 Bugfix: Test result ordering was reversed! 2020-09-28 09:02:17 +10:00
Oliver
3a5014da4b Merge pull request #996 from SchrodingersGat/batch-filtering
Adds ability to filter stock API results by batch code
2020-09-23 09:20:13 +10:00
Oliver Walters
8a4597be6a Adds ability to filter stock API results by batch code 2020-09-23 09:11:46 +10:00
Oliver
fb247c3dd8 Merge pull request #994 from SchrodingersGat/docs-update
Update links to documenation
2020-09-23 08:51:07 +10:00
Oliver
7dd988a7dc Merge pull request #995 from eeintech/stock_to_build_prefetch
Reduced SQL load for 'Require Stock to Complete Build' widget on homepage
2020-09-23 08:45:51 +10:00
eeintech
120a17241e Reduced SQL load for 'Require Stock to Complete Build' widget on homepage 2020-09-22 11:24:09 -05:00
Oliver Walters
07adee3c51 Update links to documenation 2020-09-21 22:44:48 +10:00
Oliver
12e43dcc46 Update README.md
Rearrange headers in README.md
2020-09-21 22:40:02 +10:00
Oliver
bc57845aaa Update README.md
Point to new documentation on readthedocs.io
2020-09-21 22:39:04 +10:00
Oliver
8f1e116c0b Merge pull request #992 from SchrodingersGat/build-table-refresh
Build display improvements
2020-09-21 08:14:25 +10:00
Oliver Walters
5d6e20d897 Build display improvements
- Reload AJAX table instead of entire page
- Clean up auto-allocate page
- Add extra message
2020-09-21 08:05:31 +10:00
Oliver
7dbb6c7c8e Merge pull request #988 from SchrodingersGat/sell-price
Sell price
2020-09-19 23:52:25 +10:00
Oliver
d6bca4d6ca Merge pull request #987 from SchrodingersGat/serial_number_filter
Stock Search
2020-09-19 23:48:11 +10:00
Oliver Walters
f19a727a02 Allow searching by stock item batch code 2020-09-19 23:40:06 +10:00
Oliver Walters
89b3290068 Add search results for stock items 2020-09-19 23:38:33 +10:00
Oliver Walters
083bfe05c0 Add ability to search stock API
- serial number
- part information
2020-09-19 21:49:07 +10:00
Oliver
5f81d650e9 Merge pull request #986 from SchrodingersGat/serial_number_filter
Filter stock tables by serial number
2020-09-19 21:47:40 +10:00
Oliver Walters
2e1388475e Filter stock tables by serial number 2020-09-19 21:39:43 +10:00
Oliver
2389bb9621 Merge pull request #984 from SchrodingersGat/index_page_fixes
Tweaks for new index page
2020-09-19 21:33:25 +10:00
Oliver Walters
b30754f561 Animate hourglass icons 2020-09-19 21:26:34 +10:00
Oliver Walters
b9594db832 Add some hourglass loading icons 2020-09-19 21:23:36 +10:00
Oliver Walters
597ab37ba6 Further cleanup 2020-09-19 21:18:29 +10:00
Oliver Walters
1b6843e72d Cleanup "bom_invalid" filter
- Allow filtering by bom either valid or invalid
- Use "bom_valid" as the filter (positive tense)
2020-09-19 21:03:49 +10:00
Oliver Walters
87d0d872e0 Fix spelling mistakes 2020-09-19 20:45:00 +10:00
Oliver Walters
b8509f7533 Add ability to filter builds by "active" status 2020-09-19 20:42:20 +10:00
Oliver Walters
11a17fb9b1 Implement a "simplified" part table which does not enforce extra filtering 2020-09-19 20:35:30 +10:00
Oliver Walters
eaf42b8abe Instead of creating a custom filter for "latest" parts,
simply make use of the existing "ordering" query as part of DRF
2020-09-19 20:26:17 +10:00
Oliver
a218b6b351 Merge pull request #982 from eeintech/new_homepage_layout
New homepage layout
2020-09-19 20:04:23 +10:00
Oliver Walters
86660a5f17 style fixes 2020-09-19 19:52:48 +10:00
eeintech
6540fb968e Merge branch 'master' of git://github.com/inventree/InvenTree into new_homepage_layout 2020-09-18 11:52:26 -05:00
eeintech
c55fa13cdb Added part list which require more stock to be built 2020-09-18 11:40:50 -05:00
Oliver Walters
ca1281ee10 Adds ajax table for part sale price information 2020-09-18 22:11:51 +10:00
Oliver Walters
ff7570aea4 VIews / forms / etc 2020-09-18 21:49:56 +10:00
Oliver Walters
1a90106bac Add a tab for part sale prices 2020-09-18 21:20:28 +10:00
Oliver Walters
a95dd86540 Limit choices for the 'Part' reference in the new model 2020-09-18 09:16:59 +10:00
Oliver Walters
71c0406cf3 Register new model in the admin interface 2020-09-18 09:16:41 +10:00
eeintech
945c3c214d Added outstanding purchase and sales orders views to homepage 2020-09-17 17:19:19 -05:00
eeintech
3d597cc3c3 Added 'Pending' builds report to homepage, includes builds with 'Allocated' status 2020-09-17 14:36:05 -05:00
Oliver Walters
8f1b018f0a Add table for price breaks for selling a part 2020-09-17 23:22:37 +10:00
Oliver Walters
e51fee081b SupplierPart price break table now uses API rather than django template 2020-09-17 23:19:50 +10:00
Oliver Walters
805e8daa57 Convert SupplierPriceBreak model to use the abstract PriceBreak class 2020-09-17 22:47:31 +10:00
Oliver Walters
95c5c4b575 Fix issues with circular imports 2020-09-17 22:44:17 +10:00
Oliver
25e73db455 Merge pull request #981 from wolffam/build-allocated-no-location-fix
Handle situation where allocated items within a build do not have a location set
2020-09-17 19:33:47 +10:00
alex
d10ba5edc3 handle case where stock item does not have a location set; also show header 2020-09-17 00:55:54 -07:00
alex
6ed604bbb8 fix erroring html 2020-09-17 00:49:17 -07:00
eeintech
28a55f0a58 Merge branch 'master' of git://github.com/inventree/InvenTree into new_homepage_layout 2020-09-16 17:03:59 -05:00
eeintech
a9fffe6a73 Added latest parts and invalid BOMs on homepage 2020-09-16 17:02:24 -05:00
Oliver
4af6b65ac3 Merge pull request #978 from eeintech/fix_navbar_barcode_border
Fixed borders of navbar barcode button
2020-09-17 07:54:28 +10:00
eeintech
472e2d0acd Fixed borders of navbar barcode button 2020-09-16 09:44:12 -05:00
Oliver
303db293b7 Merge pull request #976 from SchrodingersGat/path-fix
Ensure correct path separator is returned
2020-09-13 21:22:15 +10:00
Oliver Walters
d674eacd78 Ensure correct path separator is returned 2020-09-13 21:10:11 +10:00
Oliver
adaaa1e81d Merge pull request #975 from SchrodingersGat/dropdown-css
Dropdown css
2020-09-13 21:05:18 +10:00
Oliver Walters
32cde5d8f1 Fixx css for multiple button groups 2020-09-13 20:56:05 +10:00
Oliver Walters
04c702e1b8 Improve action buttons for part display 2020-09-13 20:42:59 +10:00
Oliver
eaf87294ce Merge pull request #974 from SchrodingersGat/toggle-fix
Fix for weird button toggles (it was a doozy!)
2020-09-13 17:56:08 +10:00
Oliver Walters
aa35c787b2 Fix for weird button toggles (it was a doozy!)
- Turning off autocomplete seems to have done the job
- https://stackoverflow.com/questions/36546775/html-checkboxes-keep-checked-after-refresh#36547079
2020-09-13 17:47:40 +10:00
Oliver
65bc23a516 Merge pull request #973 from SchrodingersGat/multi-bom-item-delete
Multi bom item delete
2020-09-13 00:47:44 +10:00
Oliver Walters
57e395de71 BOM: Allow multiple BOM items to be selected and deleted
(in editing mode)
2020-09-13 00:40:06 +10:00
Oliver Walters
7a7db97914 add inventreeDelete ajax function 2020-09-13 00:39:25 +10:00
Oliver Walters
36ac268b96 BOM Display: Multiple fixes
- Previous multi-level BOM display changes had broken the table in editing mode
- Simplify code
- Re-implement edit / delete / validate buttons
- Re-enable checkboxes in edit mode
2020-09-13 00:13:53 +10:00
Oliver
8c9491f3ca Merge pull request #970 from eeintech/color_themes
Color theme selection added to settings
2020-09-10 09:28:40 +10:00
eeintech
28585644ea Added automatic listing of custom CSS sheets (no more hardcoded), added error message when current selection is not valid and select default theme 2020-09-09 14:55:32 -05:00
eeintech
8198fad6d5 Updated common.colortheme migration 2020-09-08 16:36:58 -05:00
eeintech
35060ce8dc Merge branch 'master' of git://github.com/inventree/InvenTree into color_themes 2020-09-08 16:33:22 -05:00
eeintech
896fa131f0 Moved color themes CSS sheets to own folder, nicer crispy form for selecting theme 2020-09-08 16:24:22 -05:00
Oliver
700d522c3c Merge pull request #962 from eeintech/part_ipn_slug
Added PartDetailFromIPN view (subclass of PartDetail) and url pattern
2020-09-08 09:40:28 +10:00
eeintech
8e2d568a42 Style correction (missing ending new line), removed commented line in ColorThemeSelectForm 2020-09-07 17:01:05 -05:00
eeintech
10dd8fad80 Renamed Theme to ColorTheme, ColorTheme is now a per-user selection 2020-09-07 16:27:23 -05:00
eeintech
2e5ec5d249 Theme change works but applies to all user 2020-09-07 15:15:51 -05:00
eeintech
0548bee8ad Added Color Theme view in settings 2020-09-07 11:29:24 -05:00
eeintech
27241e217f Style correction 2020-09-07 08:46:39 -05:00
eeintech
c5efce36b6 Added PartDetailFromIPN view tests 2020-09-07 08:40:37 -05:00
eeintech
41071f0ed4 Moved IPN url pattern to right before Part index to avoid catching others 2020-09-05 12:03:07 -05:00
eeintech
8198e919b1 Merge branch 'master' of git://github.com/inventree/InvenTree into part_ipn_slug 2020-09-05 11:42:33 -05:00
Oliver
f0713ce01d Merge pull request #966 from SchrodingersGat/stock-item-link
Add link from stock item to base part
2020-09-06 00:01:36 +10:00
Oliver Walters
87f25eacc5 Add link from stock item to base part 2020-09-06 00:01:14 +10:00
Oliver
22e30903b6 Merge pull request #965 from SchrodingersGat/api-stock-fix
Major bugfix for multiple annotations in API querysets
2020-09-05 23:42:25 +10:00
Oliver Walters
46a8107be5 Refactor stock filter 2020-09-05 23:35:48 +10:00
Oliver Walters
2cf40c0e0b Translation updates 2020-09-05 23:32:36 +10:00
Oliver Walters
f7ad38dad5 Add unit tests for new aggregation annotation approach 2020-09-05 23:28:54 +10:00
Oliver Walters
5f2e4c3790 Update serializers for Order model 2020-09-05 23:08:59 +10:00
Oliver Walters
598e15af46 Fix annotations for Company serializers 2020-09-05 23:03:38 +10:00
Oliver Walters
db214dfd73 Update queryset annotation for StockItem
- Query time reduced from 4.1 to 3.5s (for sample data)
2020-09-05 22:50:17 +10:00
Oliver Walters
42967905bc New approach for multiple annotations
- Use the django-sql-utils addon - https://github.com/martsberger/django-sql-utils
- The "distinct=True" flag was not doing what I thought it was doing...
2020-09-05 22:35:19 +10:00
Oliver
a2efac4dbe Merge pull request #964 from SchrodingersGat/new-stock-item-form
Bugfix: CreateStockItem form
2020-09-05 20:51:36 +10:00
Oliver Walters
f737ad2d38 Bugfix: CreateStockItem form
- hide the field rather than popping it
2020-09-05 20:31:18 +10:00
Oliver
2667dc68d7 Merge pull request #963 from SchrodingersGat/variant-form
Allow selection of bom_copy and parameter_copy when making a new variant
2020-09-05 20:26:14 +10:00
Oliver Walters
c4989e59b2 Allow selection of bom_copy and parameter_copy when making a new variant 2020-09-05 20:10:18 +10:00
Oliver
6ef4390e29 Merge pull request #961 from eeintech/parameters_copy
Implemented part parameters copy from template/original part
2020-09-05 20:03:18 +10:00
eeintech
2fa284d37b Added PartDetailFromIPN view (subclass of PartDetail) and url pattern 2020-09-04 17:20:17 -05:00
eeintech
440a5fafea Implemented part parameters copy from template/original part 2020-09-04 14:02:12 -05:00
Oliver
11b751323e Merge pull request #953 from SchrodingersGat/part-import-fix
Part: Alter model fields to fix data import issues
2020-09-03 00:18:26 +10:00
Oliver Walters
34a334236a Part: Alter model fields to fix data import issues
Without setting 'null=True' on fields which may be empty,
the import subsequently fails if these fields are indeed empty
2020-09-03 00:11:20 +10:00
Oliver
81b50312e2 Merge pull request #952 from SchrodingersGat/variant-table
Add ability to filter part list by 'ancestor'
2020-09-03 00:09:53 +10:00
Oliver Walters
b89588ffb7 variant of link links to variants page 2020-09-03 00:00:03 +10:00
Oliver Walters
303572bc03 More translation updates 2020-09-02 23:57:51 +10:00
Oliver Walters
e3d92e1390 Fixes for translation script 2020-09-02 23:54:35 +10:00
Oliver Walters
eaec85398f Treegrid display for part variants 2020-09-02 23:51:28 +10:00
Oliver Walters
62c26c881d Add ability to filter part list by 'ancestor' 2020-09-02 23:18:26 +10:00
Oliver
104b9d2d44 Merge pull request #949 from SchrodingersGat/multi-db-unit-test
Add CI tests for MySQL database
2020-09-02 20:26:51 +10:00
Oliver Walters
36955d6d4f pep fixes 2020-09-02 20:16:46 +10:00
Oliver Walters
92ec849fc1 Add ci settings file for postgresql database 2020-09-02 20:09:11 +10:00
Oliver Walters
bb9e8fa97b Merge remote-tracking branch 'inventree/master' into multi-db-unit-test
# Conflicts:
#	InvenTree/build/test_build.py
2020-09-02 20:02:22 +10:00
Oliver Walters
911727f7b7 Update test fixtures
- Can't assume that pk values will be assigned sensibly!
- Need to hard-code them in
2020-09-02 19:47:07 +10:00
Oliver Walters
bc2f131144 travis fixes 2020-09-01 21:24:19 +10:00
Oliver Walters
b8856476be More CI file changes 2020-09-01 21:21:32 +10:00
Oliver Walters
37a43c8657 Install required PIP packages 2020-09-01 21:13:38 +10:00
Oliver Walters
85f635c975 Darn spelling misterks 2020-09-01 21:08:58 +10:00
Oliver Walters
3af704c453 Fix - tickmark 2020-09-01 21:05:52 +10:00
Oliver Walters
55c1ea750c Add CI tests for MySQL database 2020-09-01 21:01:38 +10:00
Oliver
cae6fb6731 Merge pull request #948 from SchrodingersGat/bcc-feature-non-int-serial
Bcc feature non int serial
2020-09-01 20:31:42 +10:00
Oliver Walters
4613730a19 PEP fixes 2020-09-01 20:24:14 +10:00
Oliver Walters
74f25ee7f9 Part: Extend logic for "latest" serial number
- Return value if it is a string
- Remove 'getNextSerialNumber' function
- Improve functionality of function which returns serial number placeholder string
2020-09-01 20:16:46 +10:00
Oliver Walters
e6c0a04131 Merge branch 'feature-non-int-serial' of git://github.com/bcc/InvenTree into bcc-feature-non-int-serial 2020-09-01 19:41:48 +10:00
Oliver Walters
1eeaa17085 Merge remote-tracking branch 'inventree/master' 2020-09-01 16:41:07 +10:00
Oliver
c3c5a86ea5 Merge pull request #946 from SchrodingersGat/field-focus
Add "focus" option when displaying a modal form
2020-09-01 13:04:02 +10:00
Oliver Walters
ffbdb0317f Add "focus" option when displaying a modal form 2020-09-01 12:43:37 +10:00
Oliver
90d2265dae Merge pull request #945 from SchrodingersGat/template-attachments
Part: add function to get part attachments for *all* parents of a part
2020-08-31 22:38:02 +10:00
Oliver Walters
73892e894e Refactoring 2020-08-31 22:30:38 +10:00
Oliver Walters
cd8214ff4a Part: add function to get part attachments for *all* parents of a part 2020-08-31 22:26:46 +10:00
Oliver
baaabd00d6 Merge pull request #939 from SchrodingersGat/column-remembering
Make checkbox field non-switchable for stock table
2020-08-31 22:08:56 +10:00
Oliver Walters
672936e2d4 Update many tables 2020-08-31 21:55:01 +10:00
Oliver Walters
97ed70502c Fix function which hides table columns based on saved selections 2020-08-31 20:42:11 +10:00
Oliver
35cd3923a5 Merge pull request #944 from SchrodingersGat/stock-item-api-fix
Stock item api fix
2020-08-31 20:13:57 +10:00
Oliver Walters
59e7474f75 Stock: More unit tests
- Add some more tests (would have caught a bug that was there already, darn it)
2020-08-31 20:09:43 +10:00
Oliver Walters
8615cad711 Stock: Fix serializers.py
- Use of read_only PrimaryKeyRelatedField was breaking POST via API
2020-08-31 20:08:07 +10:00
Oliver
fa540c0096 Merge pull request #943 from SchrodingersGat/order-details
Order: Improve help text(s)
2020-08-31 19:32:03 +10:00
Oliver Walters
eabb99053c Update requirements.txt 2020-08-31 19:20:16 +10:00
Oliver Walters
5c4781b5b4 Order: Improve help text(s) 2020-08-31 19:13:24 +10:00
Oliver
406dbc36fa Merge pull request #942 from bcc/bug-invoke-pty
Fix invoke pty error when running 'invoke superuser'
2020-08-30 21:32:17 +10:00
Ben Charlton
07f7b46a8a Fix invoke pty error when running 'invoke superuser' 2020-08-28 20:38:16 +01:00
Ben Charlton
06552832cb Style corrections 2020-08-28 17:30:16 +01:00
Ben Charlton
6b1696f8df Merge branch 'master' into feature-non-int-serial 2020-08-28 17:14:02 +01:00
Oliver Walters
7829e3654c Add callback when a column is shown / hidden 2020-08-28 10:51:55 +10:00
Oliver Walters
9c2e959ab0 Add function to turn a set of visible columns into a settings string for saving to session 2020-08-28 10:50:43 +10:00
Oliver Walters
86e675dbbd Make checkbox field non-switchable for stock table 2020-08-28 10:49:49 +10:00
Oliver Walters
f6d8a3f229 Merge remote-tracking branch 'upstream/master' 2020-08-27 22:50:52 +10:00
Oliver
2c1d585f8b Merge pull request #937 from SchrodingersGat/dynamic-form-fixes
Dynamic form fixes
2020-08-27 08:47:21 +10:00
Oliver Walters
b17c3f6e0f Fix for empty option 2020-08-27 08:41:38 +10:00
Oliver Walters
27f7745231 Follow link to newly created StockItem 2020-08-27 08:37:18 +10:00
Oliver Walters
19329a9627 Merge remote-tracking branch 'inventree/master' 2020-08-27 00:21:42 +10:00
Oliver
ce866c6d30 Merge pull request #934 from SchrodingersGat/reactive-forms
Reactive forms
2020-08-27 00:12:26 +10:00
Oliver Walters
146dae6d43 Toot toot - it's the refactor tractor!
- New function for launching a CreateStockItem form
- Wraps up the previous code improvements into a single function
- Oh, the ease!
2020-08-27 00:08:02 +10:00
Oliver Walters
4be1b2928b PEP fix 2020-08-26 23:50:49 +10:00
Oliver Walters
72899530cf Add helper function to simplify reloading of field options 2020-08-26 23:43:19 +10:00
Oliver Walters
9dcc23ee4e Hide 'supplier part' options if no part is selected in the form 2020-08-26 23:40:15 +10:00
Oliver Walters
3a75682878 Add "pretty" name to the SupplierPart API
- Quick way to ensure the supplier part objects are printed the same way
- Use the pythonic back-end to render the data
2020-08-26 23:23:57 +10:00
Oliver Walters
5aa11063a0 Add function to update the 'options' for a given field in a modal 2020-08-26 23:13:32 +10:00
Oliver Walters
2037474fad Option generation function now returns array, rather than flat text 2020-08-26 23:04:50 +10:00
Oliver Walters
02d17378a6 Add function to programatically generate a list of <option> elements 2020-08-26 23:02:25 +10:00
Oliver Walters
6ab34c3d0e SupplierPart - Improve API
- The default DRF behaviour throws errors if the supplied query params do not conform to the limit_choices_to field
- This is non optimum! Don't want to have to handle these cases
- Do the filtering ourselves!
2020-08-26 22:44:22 +10:00
Oliver Walters
d44ad541eb Add "callback" functionality for modal forms when a given field is changed
- Attach callback function
- Add a function to retrieve a field by name
2020-08-26 22:35:36 +10:00
Oliver
0b4f732160 Merge pull request #933 from SchrodingersGat/report-select-fix
Bugfix: Select test report template
2020-08-26 15:03:39 +10:00
Oliver Walters
54d0c4e8a8 Bugfix: Select test report template
- Actually, two bugs!
2020-08-26 14:29:49 +10:00
Oliver
ee0df29af0 Merge pull request #921 from eeintech/show_potential_bom_items_stock
Show 'available_stock' in Part string representation
2020-08-26 09:36:55 +10:00
Oliver
60c6d6d33e Merge pull request #919 from eeintech/bom_export_parameter_stock
BoM export: added option to export part parameters (#126) and stocks (#793)
2020-08-26 08:41:44 +10:00
eeintech
5d6def75cc BoM export, Part stock: changed 'Location' header to 'Default Location' 2020-08-25 16:02:46 -05:00
eeintech
109307858a Merge branch 'master' of git://github.com/inventree/InvenTree into bom_export_parameter_stock 2020-08-25 15:59:58 -05:00
Ben Charlton
7d6055f06f Merge branch 'master' into feature-non-int-serial 2020-08-25 09:28:42 +01:00
Oliver
788d497e87 Merge pull request #931 from bcc/bug-serialize-no-location
Fix internal server error when serializing stock with no location
2020-08-25 08:38:35 +10:00
Oliver
cd016d3f7d Merge pull request #930 from bcc/feature-custom-authentication
Allow custom authentication/middleware in config.yaml
2020-08-25 08:37:30 +10:00
Ben Charlton
e0a744b01d Remove no-longer-needed cast functions 2020-08-24 20:09:06 +01:00
Ben Charlton
9c2d13b487 test non-numeric serials are handled correctly for ranges 2020-08-24 20:04:10 +01:00
Ben Charlton
0da2682c68 handle non-int serial range suggestions cleanly 2020-08-24 20:00:19 +01:00
Ben Charlton
d5a374f1fd Make serial number suggestion DB independent, handle mixed types more cleanly and test 2020-08-24 19:49:32 +01:00
Ben Charlton
9149aa1536 Fix internal server error when serializing stock with no location 2020-08-24 18:04:22 +01:00
eeintech
946d824995 Switched to ModelChoiceField 2020-08-24 11:41:14 -05:00
eeintech
6f89f7dc7f Merge branch 'master' into show_potential_bom_items_stock 2020-08-24 10:35:59 -05:00
Ben Charlton
b6f9590d55 Add default config example to config template 2020-08-24 15:24:18 +01:00
Ben Charlton
988d263ef1 Allow custom authentication / middleware in config.yaml 2020-08-24 15:05:21 +01:00
Ben Charlton
471ece136e Merge branch 'master' into feature-non-int-serial 2020-08-24 11:12:07 +01:00
Oliver Walters
78826dc20b Merge remote-tracking branch 'inventree/master' 2020-08-23 21:21:18 +10:00
Oliver
2a4b9c6c5c Merge pull request #929 from SchrodingersGat/label-enable
Label enable
2020-08-23 21:18:11 +10:00
Oliver
c3bfcad4df Merge pull request #928 from Kedarius/small-device
Collapse navbar on small screen
2020-08-23 21:12:28 +10:00
Oliver Walters
ca1985e11a PEP fixes 2020-08-23 21:10:45 +10:00
Oliver Walters
9a35293126 Remove PartFilterMixin class 2020-08-23 21:08:41 +10:00
Oliver Walters
ed5ad3c047 Rename 'part_filters' field to 'filters' 2020-08-23 21:05:54 +10:00
Oliver Walters
c849f618d5 Clean up implementation of test report matching 2020-08-23 21:03:29 +10:00
Oliver Walters
b7ae95686e Add field "enabled" to Report template 2020-08-23 20:51:41 +10:00
Radek Hladik
f9149d041e Collapse navbar on small screen 2020-08-23 10:56:29 +02:00
Oliver Walters
116d966d29 Delete "ReportTemplate" class 2020-08-23 09:10:56 +10:00
Oliver Walters
771b2117c4 Remove duplicated function 2020-08-23 09:08:24 +10:00
Oliver Walters
8f1af0f5f9 Add "enabled" field to Label class
- Only list labels which are enabled
- Allows labels to be hidden / disabled without being deleted
2020-08-23 09:07:15 +10:00
Oliver
69a3ad3c5b Merge pull request #927 from bcc/bug-serialized-move
Fix disabled form item from preventing location moves for serialized stock
2020-08-22 09:13:40 +10:00
Ben Charlton
23cc3d9b06 Handle 'next serial' more gracefully 2020-08-21 19:17:58 +01:00
Ben Charlton
c31b30bf83 Fix simple tests 2020-08-21 18:53:51 +01:00
Ben Charlton
f7ed48809c Support non-integer serial numbers 2020-08-21 17:36:49 +01:00
Ben Charlton
eeca3effee Fix disabled form item from preventing stock location moves for items with serial numbers 2020-08-21 16:20:33 +01:00
Oliver Walters
98017cb8bd Merge remote-tracking branch 'inventree/master' 2020-08-21 22:11:02 +10:00
Oliver
de86418ede Merge pull request #925 from SchrodingersGat/make-replace
Change from using "make" to "invoke"
2020-08-21 21:58:19 +10:00
Oliver Walters
017c1ece89 Update docstring 2020-08-21 21:51:22 +10:00
Oliver Walters
d8f9f95cb4 Add command to run the development server 2020-08-21 21:49:03 +10:00
Oliver Walters
ef1e598341 Install PIP requirements as a part of "invoke install" 2020-08-21 21:32:08 +10:00
Oliver Walters
513142d487 Update travis file 2020-08-21 21:27:39 +10:00
Oliver Walters
592e87941d Add more targets
- superuser
- backup
2020-08-21 21:24:02 +10:00
Oliver Walters
f5fd0fc5be Migrate "mysql" and "postgresql" targets 2020-08-21 21:17:38 +10:00
Oliver Walters
af50e29e2c Migrate "translate" command 2020-08-21 21:13:28 +10:00
Oliver Walters
ec1e646de0 Migrate "style" task 2020-08-21 21:12:05 +10:00
Oliver Walters
ab75f85555 Migrate "test" command to invoke 2020-08-21 21:10:14 +10:00
Oliver Walters
05fae4be87 Are more methods to tasks.py:
- static
- update
- install
- key
- coverage

The functionality of setup.py is now included here!
2020-08-21 21:08:04 +10:00
Oliver Walters
f4debeac47 Moving to "invoke" framework
- Add "migrate" test
2020-08-21 20:39:43 +10:00
Oliver
7a0e1e9574 Merge pull request #924 from SchrodingersGat/stocktake-export-fixes
Stocktake export fixes
2020-08-21 20:14:02 +10:00
Oliver Walters
59b3d8b5bc Fix stocktake export
- Exclude MPTT fields
- Fix foreignkey field references
2020-08-21 20:08:47 +10:00
Oliver Walters
25cced3b90 Exclude MPTT fields from Part model resource 2020-08-21 20:08:16 +10:00
eeintech
9fa13aeae3 Show 'available_stock' in Part string representation 2020-08-20 15:38:41 -05:00
eeintech
89e63df1fb Corrected style 2020-08-20 14:53:03 -05:00
eeintech
6fc275ca30 BoM export: added option to export part paremeters (#126) and stocks (#793) 2020-08-20 13:53:27 -05:00
Oliver Walters
142a1462bb Merge remote-tracking branch 'inventree/master' 2020-08-20 16:02:18 +10:00
Oliver
852a680c09 Merge pull request #916 from SchrodingersGat/null-customer
StockItem: Allow customer field to be blank
2020-08-20 14:59:06 +10:00
Oliver Walters
90d34cdfcf StockItem: Allow customer field to be blank 2020-08-20 14:54:55 +10:00
Oliver Walters
2f88cc9fe0 Merge remote-tracking branch 'inventree/master' 2020-08-20 14:48:16 +10:00
Oliver
4f1b469cee Merge pull request #915 from SchrodingersGat/tex-response
Tex response
2020-08-20 14:14:24 +10:00
Oliver Walters
8e0dfa9c6f PEP fix 2020-08-20 14:05:55 +10:00
Oliver Walters
64ae181bf6 Add some more context data 2020-08-20 14:01:41 +10:00
Oliver Walters
5a8804f4bc If LaTeX template errors, return the raw LaTeX! 2020-08-20 13:57:29 +10:00
Oliver Walters
c1956d13b5 Merge remote-tracking branch 'inventree/master' 2020-08-20 09:04:17 +10:00
Oliver
71f3662ebc Merge pull request #914 from SchrodingersGat/recursive-bom
Bugfix: Recursive BOM display
2020-08-20 09:01:26 +10:00
Oliver Walters
0aeb7ddbdf Allow column show/hide on BOM table 2020-08-20 08:57:11 +10:00
Oliver Walters
41c4a5376b Bugfix: Recursive BOM display
- Actually request recursively! (duh)
- Fix the idField and parentIdField for the BOM display (was incredibly wrong)
- Sub-rows are initially displayed in the "collapsed" state
2020-08-20 08:52:22 +10:00
Oliver Walters
6930456e2b Merge remote-tracking branch 'inventree/master' 2020-08-19 14:19:43 +10:00
Oliver
8556bdec6a Merge pull request #913 from SchrodingersGat/supplier-data-in-bom
Supplier data in bom
2020-08-19 14:13:53 +10:00
Oliver Walters
0faba39dfc PEP: Remove unused variable
(cherry picked from commit e49a1c1ad2)
2020-08-19 14:08:52 +10:00
Oliver Walters
7e829e88af Add option for including supplier data for BOM export
(cherry picked from commit d0b5550c86)
2020-08-19 14:08:47 +10:00
Oliver Walters
3d0012a3bf Bugfix: accomodate missing manfufacturer links
If a supplier_part does not have an associated manufacturer, the code would break

(cherry picked from commit 965dba4739)
2020-08-19 14:08:41 +10:00
eeintech
b5bc8935a2 Added manufacturer data to BoM export
(cherry picked from commit c7ddccc4ec)
2020-08-19 14:08:34 +10:00
Oliver Walters
f8bb357e6c Merge remote-tracking branch 'inventree/master' 2020-08-18 21:30:08 +10:00
Oliver Walters
50460ed527 Merge branch 'master' of https://github.com/SchrodingersGat/InvenTree 2020-08-18 21:29:48 +10:00
Oliver
13b64c6a04 Merge pull request #910 from SchrodingersGat/multi-level-bom
Multi level bom
2020-08-18 21:28:47 +10:00
Oliver Walters
1767ef7a3a Fix issues with tree sorting
- Need to set parent ID based on the BOM items
- This is to prevent data duplication that was weird and dumb
2020-08-18 21:24:11 +10:00
Oliver Walters
82903d2bd6 BOM display is now heirarchical 2020-08-18 21:01:22 +10:00
Oliver Walters
4cd54203a2 Add jquery-treegrid plugin 2020-08-18 20:53:50 +10:00
Oliver Walters
37baec2db6 bootstrap-table: Add "extensions" 2020-08-18 20:53:05 +10:00
Oliver Walters
32133fecc7 Merge remote-tracking branch 'upstream/master' 2020-08-18 14:41:03 +10:00
Oliver
316dfe5e38 Merge pull request #909 from SchrodingersGat/bom-import-export
BOM upload: improve generation of "import" template
2020-08-18 14:37:48 +10:00
Oliver Walters
92ac93aac5 More intelligent checking for circular BOM
- Check all the way down a BOM "tree"
- Validate BOM tree before allowing BOM submission
2020-08-18 14:17:59 +10:00
Oliver Walters
ca4d3df287 Update translation files 2020-08-18 14:01:40 +10:00
Oliver Walters
68fb599c73 Major improvements to BOM upload
- Column headings now match the values provided in BOM import template
- Add a new column for part selection, while displaying all imported data
- Better code documentation
- Improve data validation
- Allow decimal quantity (not just integer!)
- Better matching logic
2020-08-18 14:01:01 +10:00
Oliver Walters
7349b396ca Merge remote-tracking branch 'upstream/master' into bom-import-export 2020-08-18 11:50:40 +10:00
Oliver
561516e8d7 Merge pull request #908 from eeintech/bom_upload_part_match_auto_and_ipn
BoM Upload: Automatic Part match using name or IPN
2020-08-18 11:50:10 +10:00
Oliver Walters
476cc5f661 BOM upload: improve generation of "import" template
- Better field naming
- Remove some fields which are not required here
- Better description of what is going to happen
2020-08-18 11:47:27 +10:00
Oliver Walters
badc306f33 Merge remote-tracking branch 'upstream/master' 2020-08-18 10:39:24 +10:00
eeintech
783a94acce Corrected MakeBomTemplate method's queryset 2020-08-17 16:42:28 -05:00
eeintech
84c0ec7937 BoM: added part matching based on IPN 2020-08-17 16:35:38 -05:00
eeintech
303157c586 Added part match auto-selection (if partial_ratio >= 100) to BoM part selection form 2020-08-17 14:10:24 -05:00
eeintech
685a58b807 Merge remote-tracking branch 'origin/master' into bom_dev 2020-08-17 12:05:54 -05:00
Oliver
89c7f72caf Merge pull request #907 from SchrodingersGat/bom-level-int
Make BOM levels integers
2020-08-17 10:43:31 +10:00
Oliver Walters
25d90f643a Make BOM levels integers 2020-08-17 10:39:35 +10:00
Oliver Walters
e67327953d Merge remote-tracking branch 'inventree/master' 2020-08-16 15:10:23 +10:00
Oliver
4dcd6ee136 Update version.py 2020-08-16 14:03:49 +10:00
Oliver
ab62f8fc59 Update version.py
Increment version number
2020-08-16 14:03:20 +10:00
Oliver
b5b882d3b6 Merge pull request #906 from SchrodingersGat/blabel
Label Printing Functionality
2020-08-16 14:02:38 +10:00
Oliver Walters
d52278e423 Icon tweak 2020-08-16 13:45:58 +10:00
Oliver Walters
da079b23dc Fix duplicate label printing menu action 2020-08-16 13:43:59 +10:00
Oliver Walters
ccda637e3c Fixes for barcode decoding 2020-08-16 13:42:27 +10:00
Oliver Walters
a4267f76e8 Fixes for barcode data rendering 2020-08-16 13:39:05 +10:00
Oliver Walters
2bbc65cc59 Add "brief" version of QR codes
- Use this to render to labels (as it contains much less information)
2020-08-16 13:29:38 +10:00
Oliver Walters
2f5e3efada Update translations 2020-08-16 12:11:22 +10:00
Oliver Walters
1807ba4e7b Add form for selecting label template for a StockItem 2020-08-16 12:10:58 +10:00
Oliver Walters
30e24f19d9 PEP fixes 2020-08-16 11:13:17 +10:00
Oliver Walters
cdde0f8c43 Add URL endpoint for downloading PDF labels 2020-08-16 11:12:21 +10:00
Oliver Walters
2b1d6c268c Render to an in-memory PDF 2020-08-16 10:29:03 +10:00
Oliver Walters
18b3fd3256 Add context data to StockItemLabel model 2020-08-16 10:24:15 +10:00
Oliver Walters
aefd70ce49 Add admin interface for StockItemLabel 2020-08-16 09:29:45 +10:00
Oliver
eb2422e6be Merge pull request #905 from SchrodingersGat/bom-depth
Allow user to set "depth" of exported multi-level BOM
2020-08-16 09:29:09 +10:00
Oliver Walters
a45902bd4f Add "label" app 2020-08-16 09:28:12 +10:00
Oliver Walters
dd77cc00b7 Add requirement for "blabel" plugin 2020-08-16 09:07:27 +10:00
Oliver Walters
e5406cae24 More PEP fixes 2020-08-16 09:05:16 +10:00
Oliver Walters
97103207b6 PEP fixes 2020-08-16 08:34:54 +10:00
Oliver Walters
b27ecf54d7 Allow user to set "depth" of exported multi-level BOM 2020-08-16 08:29:36 +10:00
Oliver
318c16f321 Merge pull request #904 from SchrodingersGat/query-speeds
Significant query speed improvements to stock list API
2020-08-15 21:56:55 +10:00
Oliver Walters
f1373e3bea Improve speed of BomItem API queries
- Including the pricing information takes absolutely ages, takes too long!!
2020-08-15 21:52:32 +10:00
Oliver Walters
e1a8772af6 Update serializers for SupplierPart 2020-08-15 21:24:01 +10:00
Oliver Walters
d34383e842 Specify serializer type for part category 2020-08-15 21:20:31 +10:00
Oliver Walters
2f77007dbe Significant query speed improvements to stock list API
- Thanks, django-debug-toolbar!
- Gah, django DRF is the worst. Enforcing a PrimaryKeyRelatedSerializer seems to really improve speed
2020-08-15 21:15:11 +10:00
Oliver
411e7507a3 Merge pull request #903 from SchrodingersGat/debug-toolbar
Debug toolbar
2020-08-15 20:08:04 +10:00
Oliver Walters
3c4cfc9a1b Flake fix 2020-08-15 19:56:02 +10:00
Oliver Walters
2bb669d7de Remove defunct "log_queries" option 2020-08-15 19:52:04 +10:00
Oliver Walters
b8b3a933ab Add django-debug-toolbar plugin
- Must be running in DEBUG mode
- Must set debug_toolbar to True in config file
2020-08-15 19:48:42 +10:00
Oliver Walters
2280558303 Add a method of return raw LaTeX for debugging 2020-08-15 19:27:31 +10:00
Oliver Walters
3b01614a38 Merge remote-tracking branch 'inventree/master' 2020-08-09 21:37:06 +10:00
Oliver
1f5d81ef93 Merge pull request #900 from SchrodingersGat/stock-display-improvements
Stock display improvements
2020-08-09 21:26:26 +10:00
Oliver Walters
cebba6909c Revert thing 2020-08-09 21:21:12 +10:00
Oliver Walters
3336eb9f45 Default stock list behaviour is to only show in_stock items 2020-08-09 21:12:49 +10:00
Oliver Walters
0da9e0f834 Add "sent_to_customer" filter 2020-08-09 21:10:21 +10:00
Oliver Walters
502702b3bc Add some more visual tags to the stock list 2020-08-09 21:04:41 +10:00
Oliver
bb6b3b965d Merge pull request #896 from SchrodingersGat/company-ordering
Add default ordering for Company model
2020-08-08 17:21:21 +10:00
Oliver
fcfd1f82d6 Merge pull request #898 from SchrodingersGat/filter-depleted
Filter depleted
2020-08-08 17:19:28 +10:00
Oliver Walters
19c036f50a Add migration files 2020-08-08 17:16:04 +10:00
Oliver Walters
ad11681369 Custom filter tag for company stock listing 2020-08-08 17:15:08 +10:00
Oliver Walters
bc3fda71a4 Display "depleted" label next to depleted stock 2020-08-08 17:11:50 +10:00
Oliver Walters
96a3f2920d Stock table filters now arranged in alphabetical order 2020-08-08 17:09:22 +10:00
Oliver Walters
099f56e779 Add "depleted" table filter 2020-08-08 17:08:18 +10:00
Oliver Walters
402301e165 Add ability to filter stock items by "depleted" status 2020-08-08 17:06:22 +10:00
Oliver
190610c6c9 Merge pull request #897 from SchrodingersGat/serialized-stock-adjust-fix
Cannot edit quantity for serialized stock when adjusting
2020-08-08 17:05:29 +10:00
Oliver Walters
732405f738 Cannot edit quantity for serialized stock when adjusting 2020-08-08 17:01:29 +10:00
Oliver Walters
a7ee323035 PEP fix 2020-08-08 16:59:48 +10:00
Oliver Walters
ad977d4d26 Add default ordering for Company model
- Now will sort by "name" in choice fields, etc
2020-08-08 16:54:09 +10:00
Oliver Walters
3831a04ce0 Merge remote-tracking branch 'inventree/master' 2020-08-08 09:52:48 +10:00
Oliver
eac53c836c Update README.md 2020-08-08 09:52:14 +10:00
Oliver
2cd6c0b9fc Merge pull request #895 from SchrodingersGat/return-to-stock
Return to stock
2020-08-08 09:48:44 +10:00
Oliver Walters
8d9cfd3678 Migration file for StockStatus codes 2020-08-08 09:44:21 +10:00
Oliver Walters
a2c3c1086c Catch unhandled javascript errors 2020-08-08 09:31:57 +10:00
Oliver Walters
ff71fe6e93 Fix "in_stock" logic for StockItem
- Not in stock if it is at a customer!
2020-08-08 09:20:42 +10:00
Oliver Walters
861a2982db Removed "SHIPPED" stock status code 2020-08-08 09:16:53 +10:00
Oliver Walters
54c1f2d9a2 Upgrade to latest flake8 2020-08-08 09:15:45 +10:00
Oliver Walters
459cc03aae Remove "ASSIGNED_TO_BUILD" status code 2020-08-08 09:08:15 +10:00
Oliver Walters
80173a9d43 Remove ASSIGNED_TO_OTHER_ITEM status code 2020-08-08 09:07:25 +10:00
Oliver Walters
bdea29df04 Add functionality to return stock item from customer 2020-08-08 09:05:33 +10:00
Oliver Walters
7b332d93ee Rearrange button layouts 2020-08-08 08:48:27 +10:00
Oliver
518ad3eb60 Merge pull request #892 from SchrodingersGat/import-fix
Allow default_keywords to be  null
2020-08-04 11:35:25 +10:00
Oliver Walters
0f199556df Add migration file 2020-08-04 11:21:27 +10:00
Oliver Walters
3a266cf322 Allow default_keywords to be null 2020-08-04 11:10:24 +10:00
Oliver Walters
d65d76653c Merge remote-tracking branch 'inventree/master' 2020-08-03 20:49:33 +10:00
Oliver
08bab0a1b9 Merge pull request #891 from SchrodingersGat/security-fix
Update requirements.txt
2020-08-03 19:53:34 +10:00
Oliver Walters
481eeb8338 Update requirements.txt 2020-08-03 19:36:41 +10:00
Oliver
e0e82dabf3 Merge pull request #889 from SchrodingersGat/allow-empty-stock
Allow creation of a stock item with zero quantity
2020-07-30 21:09:57 +10:00
Oliver Walters
10691b3d03 Allow creation of a stock item with zero quantity 2020-07-30 21:05:37 +10:00
Oliver
8a1f358505 Merge pull request #888 from SchrodingersGat/allow-staff-delete
Allow staff delete
2020-07-30 20:29:57 +10:00
Oliver Walters
b7f30ee136 Update translations 2020-07-30 20:26:14 +10:00
Oliver Walters
d90edab59f Staff users are allowed to delete stock items that otherwise are not able to be deleted 2020-07-30 20:23:46 +10:00
Oliver Walters
d1d5b45073 Merge remote-tracking branch 'inventree/master' 2020-07-22 14:52:57 +10:00
Oliver
daab81fa2c Merge pull request #887 from eeintech/allow_api_thumbnail_update
Allowing Part thumbnail (image) update via API
2020-07-22 09:19:43 +10:00
eeintech
f386039d5a Added validation method for uploaded file using imghdr library 2020-07-21 16:01:17 -05:00
eeintech
af70dd5dfe Allowing Part thumbnail (image) update via API 2020-07-20 16:16:26 -05:00
eeintech
51c194fb8f Merge branch 'master' of github.com:eeintech/InvenTree into bom_dev 2020-07-19 15:05:07 -05:00
Oliver Walters
6994af411d Merge remote-tracking branch 'inventree/master' 2020-07-18 13:31:07 +10:00
Oliver
5209a7a1b0 Merge pull request #884 from SchrodingersGat/fix-filters
Adds table filters for stock assigned to a particular customer
2020-07-14 16:05:44 +10:00
Oliver Walters
0152ae79ef Adds table filters for stock assigned to a particular customer 2020-07-14 15:54:03 +10:00
eeintech
3b98d85143 Merge branch 'master' of github:eeintech/InvenTree into bom_dev 2020-07-09 08:48:41 -05:00
eeintech
46586ba960 Corrected typo in part.models, simplified MakeBomTemplate function 2020-07-09 08:47:52 -05:00
Oliver
cfd1194a6e Merge pull request #883 from eeintech/api_delete_inactive_part
API: Allow part deletion if inactive
2020-07-09 19:42:51 +10:00
eeintech
9b7977a217 API: Allow part deletion if inactive 2020-07-08 10:56:23 -05:00
Oliver Walters
5f2ca784c9 Merge branch 'negative-stock-fix' 2020-06-28 19:26:56 +10:00
Oliver
3d7676e292 Merge pull request #880 from SchrodingersGat/negative-stock-fix
Improve logic of "quantity_to_order" function
2020-06-28 19:23:37 +10:00
Oliver
25b7f0b7ee Merge pull request #879 from SchrodingersGat/star-filter-fix
Fix filter logic for 'starred' parts
2020-06-28 19:14:55 +10:00
Oliver Walters
3d245c7ce3 Improve logic of "quantity_to_order" function 2020-06-28 19:14:51 +10:00
Oliver Walters
134a688e4a Fix filter logic for 'starred' parts 2020-06-28 19:08:13 +10:00
Oliver
8ac23c080f Merge pull request #875 from SchrodingersGat/tweaks
"Active" part toggle is always enabled
2020-06-22 11:33:39 +10:00
Oliver Walters
fa3d2d005a "Active" part toggle is always enabled 2020-06-22 11:27:59 +10:00
Oliver
da70af7ba0 Merge pull request #874 from SchrodingersGat/show_non_stock
Add ability to display "out of stock" items against a part
2020-06-22 10:55:12 +10:00
Oliver Walters
930f903f5d Add ability to display "out of stock" items against a part 2020-06-22 10:48:41 +10:00
Oliver
16bea33695 Merge pull request #867 from SchrodingersGat/name-conventions
Update verbose names for some fields
2020-06-13 20:52:15 +10:00
Oliver Walters
dedc25d681 Update verbose names for some fields 2020-06-13 20:46:19 +10:00
Oliver Walters
82433db1ea Merge remote-tracking branch 'inventree/master' 2020-06-12 18:16:23 +10:00
Oliver
2047b2d7d7 Merge pull request #866 from SchrodingersGat/moar-buttons
Reorganize buttons for "Part" view
2020-06-12 18:16:06 +10:00
Oliver Walters
2e91f64a96 Add (disabled) print-label button for Part display 2020-06-12 18:13:14 +10:00
Oliver Walters
1ad4b8b131 Reorganize buttons for "Part" view 2020-06-12 18:11:57 +10:00
Oliver
a63219466f Merge pull request #865 from SchrodingersGat/barcode-suppor
Barcode support
2020-06-12 17:57:36 +10:00
Oliver Walters
9757fb06db Fix a weird button issue
- reloadTable() was causing the button 'click' handler to fire...
- NFI why this is happening
2020-06-12 16:47:57 +10:00
Oliver Walters
ab4e6548dc Transfer stock items into a stock location using barcode scanning 2020-06-12 16:29:08 +10:00
Oliver Walters
351a55c9ea Add the concept of "action groups" to the buttons for the Stock Location view 2020-06-12 11:14:33 +10:00
Oliver Walters
e1c503836d Improve barcode icon in navbar 2020-06-12 10:56:52 +10:00
Oliver Walters
8cafaa0e62 Make barcode javascript translatable 2020-06-12 10:43:27 +10:00
Oliver Walters
6064c6ceb5 Add dialog for linking a barcode with a stock item 2020-06-12 10:26:23 +10:00
Oliver Walters
b559816dca Update translations 2020-06-12 10:25:07 +10:00
Oliver Walters
ba94b340dd Add function to un-link barcode from a stock item 2020-06-12 10:12:31 +10:00
Oliver Walters
beccbe8583 Flake fixes 2020-06-11 19:46:36 +10:00
Oliver Walters
07be08d0f3 "Simplify" qr code display 2020-06-11 19:40:44 +10:00
Oliver Walters
4bb9c4c559 Prevent barcode data being entered multiple times 2020-06-11 19:27:32 +10:00
Oliver Walters
2d9b75c6ae Include URL data in barcode scan endpoint 2020-06-11 19:21:38 +10:00
Oliver Walters
3aecb110a5 Add qrcode icon as prefix to barcode input 2020-06-11 19:05:55 +10:00
Oliver Walters
503d5a41b1 Add global 'barcode-scan' button 2020-06-11 18:09:43 +10:00
Oliver Walters
e943681baa Add translations for error messages 2020-06-11 18:09:06 +10:00
Oliver Walters
0559946791 Add unit testing framework for barcodes 2020-06-11 14:44:56 +10:00
Oliver Walters
22a8e82108 Add endpoint for assigning a particular barcode to a StockItem 2020-06-11 12:21:33 +10:00
Oliver Walters
a72ed11cb0 Skeleton for DigiKey barcode 2020-06-11 11:16:55 +10:00
Oliver Walters
1a15b46d65 Remove some debug statements 2020-06-11 11:14:02 +10:00
Oliver Walters
0068cd9825 Refactor barcode endoint
- Moved code into 'barcode' directory
2020-06-11 11:09:07 +10:00
Oliver Walters
290c0eb225 Add barcode javascript file 2020-06-11 09:56:59 +10:00
Oliver Walters
bc31cc550e Consolidate buttons for stock item 2020-06-10 15:27:30 +10:00
Oliver Walters
f40a9d1dad Merge remote-tracking branch 'inventree/master' 2020-06-09 16:28:59 +10:00
Oliver
218971e6f1 Merge pull request #864 from SchrodingersGat/translation-fixes
Update translation hooks
2020-06-09 16:28:34 +10:00
Oliver Walters
38dcdcad54 Update translation hooks 2020-06-09 16:18:38 +10:00
Oliver
aeba189c1a Merge pull request #863 from SchrodingersGat/decimalfix
Decimalize display of variant stock
2020-06-09 13:44:47 +10:00
Oliver Walters
09400fd66b Decimalize display of variant stock
(cherry picked from commit 6e45360c4b7a6bc91f584f498fb6e1988593db95)
2020-06-09 13:31:16 +10:00
Oliver
f3e3838782 Merge pull request #862 from SchrodingersGat/stock-buttons-fix
Fix display of buttons for stock item
2020-06-09 13:19:15 +10:00
Oliver Walters
c7586b83e9 Fix display of buttons for stock item
(cherry picked from commit b23017b6bf)
2020-06-09 13:15:12 +10:00
Oliver Walters
b23017b6bf Fix display of buttons for stock item 2020-06-09 13:14:29 +10:00
Oliver Walters
a6a58b299b Merge remote-tracking branch 'inventree/master' 2020-06-06 08:59:28 +10:00
Oliver
b2c302cb2c Merge pull request #858 from SchrodingersGat/stock-table-ipn
Add "IPN" column to stock list table
2020-06-06 08:58:59 +10:00
Oliver Walters
126e42a022 Add "IPN" column to stock list table 2020-06-06 08:47:06 +10:00
Oliver
22b30a0626 Merge pull request #857 from SchrodingersGat/security-fix
Update django version
2020-06-06 08:38:15 +10:00
Oliver Walters
84362ea790 Update django version 2020-06-06 08:27:13 +10:00
Oliver Walters
7be158722f Merge remote-tracking branch 'inventree/master' 2020-06-05 20:04:41 +10:00
Oliver
f563ac0dcb Merge pull request #855 from SchrodingersGat/part-table
Add "IPN" column to part table
2020-06-05 19:38:16 +10:00
Oliver Walters
16d261d956 Make description fields optional 2020-06-05 19:33:32 +10:00
Oliver Walters
15817ce61a Add "IPN" column to part table 2020-06-05 19:26:41 +10:00
Oliver
dedd87f20a Merge pull request #854 from SchrodingersGat/customer-stock-display
Customer stock display
2020-06-05 12:20:25 +10:00
Oliver Walters
fcd588cb01 Filter SalesOrder by status 2020-06-05 12:08:47 +10:00
Oliver Walters
6ebce2b2fd Add ability to filter purchase orders by "outstanding" status 2020-06-05 12:06:28 +10:00
Oliver Walters
544e217347 Add page to show stock which is assigned to a customer 2020-06-05 11:52:07 +10:00
Oliver Walters
9f599546de Use stock status for determining "in stock" 2020-06-05 09:08:46 +10:00
Oliver Walters
408c6a4040 Filter stock list by "customer" 2020-06-05 09:05:57 +10:00
Oliver Walters
2c7e0bd321 Merge remote-tracking branch 'inventree/master' 2020-06-04 20:07:59 +10:00
Oliver
96b79397c2 Merge pull request #852 from SchrodingersGat/send-to-customer
Send to customer
2020-06-04 19:55:57 +10:00
Oliver Walters
ca1526405b PEP fixes 2020-06-04 19:51:43 +10:00
Oliver Walters
80019a3ed8 Add forms/views for manually assigning a stock item to a customer 2020-06-04 19:45:41 +10:00
Oliver Walters
d907136264 Display customer in stock item 2020-06-04 19:13:37 +10:00
Oliver Walters
fbd21827fb Add 'customer' field to StockItem 2020-06-04 19:08:33 +10:00
Oliver Walters
4ddabb82ef Add a button to assign stock item to customer 2020-06-04 11:50:55 +10:00
Oliver
c1da4d5207 Merge pull request #850 from SchrodingersGat/bom-division-fix
Fix for case where BOM item quantity is zero
2020-06-04 11:42:39 +10:00
Oliver Walters
a3c0d35b20 Fix for case where BOM item quantity is zero 2020-06-04 11:37:55 +10:00
Oliver
7c7055c0a0 Merge pull request #845 from SchrodingersGat/tweaks
Tweaks
2020-05-30 22:03:15 +10:00
Oliver Walters
dd9584f487 Follow link when a new stock item is created 2020-05-30 20:58:52 +10:00
Oliver Walters
8459de7be2 Display a message if no stock location is set 2020-05-30 20:58:05 +10:00
Oliver Walters
b73044cd44 Merge remote-tracking branch 'inventree/master' 2020-05-29 13:47:19 +10:00
Oliver
55bfdc000b Merge pull request #844 from SchrodingersGat/part-validation-fixes
template parts are now allowed to be variants
2020-05-29 12:51:08 +10:00
Oliver Walters
5f3816212f template parts are now allowed to be variants
- Do not throw an error here!
2020-05-29 12:40:40 +10:00
Oliver
a6dab76ff6 Merge pull request #843 from SchrodingersGat/api-improvements
Api improvements
2020-05-28 21:31:28 +10:00
Oliver Walters
59d9e430b4 Remove unique-together requirement
- This is handled manually via the validate_unique function
2020-05-28 20:38:24 +10:00
Oliver Walters
774e26eb19 Mark some fields as not-required via the API 2020-05-28 20:33:33 +10:00
Oliver
f8e36c5468 Merge pull request #840 from SchrodingersGat/bom-queryset
Allow template parts to be specified for the BOM item
2020-05-27 10:47:46 +10:00
Oliver Walters
9b7b65374d Use rounding decimal field in BomItem form 2020-05-27 10:33:47 +10:00
Oliver Walters
7bcf9bf5be Allow template parts to be specified for the BOM item 2020-05-27 10:06:18 +10:00
Oliver Walters
d0b3e0bd7c Merge remote-tracking branch 'inventree/master' 2020-05-27 09:31:15 +10:00
Oliver
04858f8835 Merge pull request #839 from SchrodingersGat/serializer-fix
Fix serializer for stock item
2020-05-26 23:20:15 +10:00
Oliver Walters
78990a99e5 Fix serializer for stock item 2020-05-26 23:01:30 +10:00
Oliver Walters
fe69a8e7bb Merge remote-tracking branch 'inventree/master' 2020-05-26 21:53:20 +10:00
Oliver
002b896384 Merge pull request #838 from SchrodingersGat/attachies
Attachies
2020-05-26 20:33:06 +10:00
Oliver Walters
e128410d54 Update 'required' status for new serializers
(cherry picked from commit 2306e29743eb25266c78bec5357d1194e0778c58)
2020-05-26 20:29:09 +10:00
Oliver Walters
81e38eeb14 Add some more custom FileField serializers
(cherry picked from commit 7b9ff27baefacc977fef7852e99d8a9bb46a062a)
2020-05-26 20:29:04 +10:00
Oliver Walters
861e30e8d6 Add a special serializer class for FileField which has a custom to_representation function
- This was solving a very subtle bug which will probably only ever apply to a single installation instance
- Future me will most likely not remember what this was for or how it works
- In any case, there we go
- Ref: http://www.cdrf.co/3.9/rest_framework.fields/Field.html

(cherry picked from commit 7305094854)
2020-05-26 20:29:00 +10:00
Oliver Walters
03cc6892ea Merge remote-tracking branch 'inventree/master' 2020-05-26 12:52:17 +10:00
Oliver
3678c940eb Merge pull request #836 from SchrodingersGat/serial-number-fixes
Serial number fixes
2020-05-26 12:16:02 +10:00
Oliver Walters
c0f1966a2c Decimal filter on StockItem adjustment form 2020-05-26 12:08:00 +10:00
Oliver Walters
c92bb78ae8 Stock table display fixes 2020-05-26 12:06:38 +10:00
Oliver Walters
e63622341f Add description field to table filters 2020-05-26 11:57:35 +10:00
Oliver Walters
669a76c921 Add serial number range filtering options for the stock table 2020-05-26 11:54:23 +10:00
Oliver Walters
4cbf2099fa Add stock item filtering by serial number range 2020-05-26 11:49:48 +10:00
Oliver Walters
046a00026c remove debug print 2020-05-26 11:42:30 +10:00
Oliver Walters
47a4ab2ed8 Template changes 2020-05-26 11:38:17 +10:00
Oliver Walters
27ca84fd2a Part view shows next available serial number 2020-05-26 11:34:11 +10:00
Oliver Walters
ae4bfd07da StockItemCreate form now has better logic for auto-detecting the part 2020-05-26 11:31:08 +10:00
Oliver
8384071ac3 Merge pull request #834 from SchrodingersGat/api-bug-fix
Allow API upload of file attachments against StockItemTestResult objects
2020-05-25 22:24:33 +10:00
Oliver Walters
1bf696a052 Allow API upload of file attachments against StockItemTestResult objects 2020-05-25 22:19:28 +10:00
Oliver
835451c02c Merge pull request #833 from SchrodingersGat/latex-fix
Catch some errors related to missing system packages
2020-05-25 15:13:33 +10:00
Oliver Walters
75cdc7eb59 Catch some errors related to missing system packages 2020-05-25 14:57:15 +10:00
Oliver
9ad54c6579 Merge pull request #832 from SchrodingersGat/convert-variant
Convert variant
2020-05-25 14:27:55 +10:00
Oliver Walters
d2c1e9e2b0 Type fixes 2020-05-25 14:24:29 +10:00
Oliver Walters
0d052334e2 Allow stock items to be created for template parts 2020-05-25 14:20:35 +10:00
Oliver Walters
fdf57891fc Form / view / etc for performing StockItem conversion 2020-05-25 14:16:38 +10:00
Oliver Walters
009adaf528 Code to get and test for variants of a part 2020-05-25 13:13:28 +10:00
Oliver
cfc15582c1 Merge pull request #830 from SchrodingersGat/copy-test-results
Copy test results
2020-05-24 21:14:05 +10:00
Oliver Walters
22220493bd Add unit tests 2020-05-24 21:10:00 +10:00
Oliver Walters
95cc3d2a7a Copy test results when a stock item is split or serialized 2020-05-24 21:09:43 +10:00
Oliver
4292a32ab9 Merge pull request #829 from SchrodingersGat/bom-validation
Integer value required for trackable bom item
2020-05-24 20:26:18 +10:00
Oliver Walters
68b9a690f2 Integer value required for trackable bom item 2020-05-24 20:22:15 +10:00
Oliver
8537dc2a85 Merge pull request #828 from SchrodingersGat/api-stuff
Api stuff
2020-05-24 20:12:28 +10:00
Oliver Walters
c44205273c Simplify javascript 2020-05-24 20:05:34 +10:00
Oliver Walters
e4d10279fa Include 'key' field in StockItemTestResult serializer 2020-05-24 20:04:34 +10:00
Oliver Walters
01481ef5c9 Add function to get the number of required tests for a part 2020-05-23 14:28:25 +10:00
Oliver Walters
e63342418f Improve / simplify logic for file attachments against test result object 2020-05-23 11:30:42 +10:00
Oliver Walters
50987f47b0 Add a buttony thing 2020-05-22 23:37:26 +10:00
Oliver Walters
4bd0872b2c Expose some more stock item data over API 2020-05-22 23:33:27 +10:00
Oliver
203062a67a Merge pull request #824 from SchrodingersGat/reporting-app
Reporting app
2020-05-22 23:16:24 +10:00
Oliver Walters
34b40d205e Expose 'part' to the TestReport interface 2020-05-22 23:08:15 +10:00
Oliver Walters
5245442b11 Fixes 2020-05-22 22:27:52 +10:00
Oliver Walters
e6f56cb056 where one or more test report templates exist for a part,
provide a button for all stock-items of that part,
allowing the user to generate and download a test repotr
2020-05-22 22:25:05 +10:00
Oliver Walters
71681bfda1 Add a button if a stock item test report is available 2020-05-22 21:38:05 +10:00
Oliver Walters
1ad7e699a9 PEP 2020-05-22 21:31:21 +10:00
Oliver Walters
0ec880290b Functionality for retrieving test templates associated with a given part 2020-05-22 21:29:58 +10:00
Oliver Walters
7215a563b1 Add PartFilterMixin 2020-05-22 21:22:43 +10:00
Oliver Walters
616f17d08a Reset the report app migrations 2020-05-22 21:01:08 +10:00
Oliver Walters
d6cad372db Add migration 2020-05-22 13:05:30 +10:00
Oliver Walters
865a6db828 Fix subdirectory lookup 2020-05-22 13:05:12 +10:00
Oliver Walters
174c4cc591 Add subclass models for report types 2020-05-22 13:01:21 +10:00
Oliver Walters
251a23d127 Cleanup 2020-05-22 00:09:51 +10:00
Oliver Walters
cab87a6860 Update admin 2020-05-22 00:01:36 +10:00
Oliver Walters
b93ba6339a Option for rendering HTML template 2020-05-21 23:41:47 +10:00
Oliver Walters
c3dcabcaad Render an uploaded template to LaTeX 2020-05-21 23:03:01 +10:00
Oliver Walters
05be4da25c remove test code 2020-05-21 14:06:29 +10:00
Oliver Walters
70c5b27d22 Add ReportAsset model
- Files which can be embedded into a report
2020-05-21 14:05:25 +10:00
Oliver Walters
b78fe88c26 PEP fixes 2020-05-21 13:53:17 +10:00
Oliver Walters
3d8c059a43 Add "report" app
- Define ReportTemplate model which contains a report file template
2020-05-21 13:51:13 +10:00
Oliver
5018f899f7 Update README.md 2020-05-20 10:45:43 +10:00
Oliver
51074ef02b Merge pull request #819 from SchrodingersGat/fix
Remove a test (for now) which is causing issues...
2020-05-19 17:56:56 +10:00
Oliver Walters
b121262af1 pep FIX 2020-05-19 17:37:00 +10:00
Oliver Walters
9cb039f685 Remove a test (for now) which is causing issues... 2020-05-19 17:08:19 +10:00
Oliver
6b73c9e020 Merge pull request #818 from SchrodingersGat/test-features
Enable attachments to be uploaded via the API
2020-05-19 17:03:05 +10:00
Oliver Walters
1cfe445897 PEP fix 2020-05-19 16:59:21 +10:00
Oliver Walters
bf296057b3 Enable attachments to be uploaded via the API 2020-05-19 16:56:41 +10:00
Oliver
eb21a9027f Merge pull request #817 from SchrodingersGat/test-features
Add some more fields to the PartTestTemplate model
2020-05-18 19:34:32 +10:00
Oliver Walters
2f6d03388d Add serializer / table display 2020-05-18 19:15:40 +10:00
Oliver Walters
fc6cad475a Add validation for StockItemTestResult based on the matching PartTestTemplate 2020-05-18 19:11:43 +10:00
Oliver Walters
e8c402ecd9 Add some more fields to the PartTestTemplate model 2020-05-18 19:00:45 +10:00
Oliver
1c67bb6026 Merge pull request #815 from SchrodingersGat/delete-test-data
Delete test data
2020-05-18 14:36:36 +10:00
Oliver Walters
0bdb62f263 Fix pep 2020-05-18 14:32:30 +10:00
Oliver Walters
fce8e3fe05 add button to delete all test data for a given stock item 2020-05-18 14:29:35 +10:00
Oliver
05e4c8f825 Merge pull request #814 from SchrodingersGat/api-tweaks
Allow stock item filtering by IPN
2020-05-18 13:38:23 +10:00
Oliver Walters
18b7baa5b9 Allow stock item filtering by IPN
(cherry picked from commit bd9aad935594e4022299567667faeb149f6d2375)
2020-05-18 13:33:41 +10:00
Oliver Walters
59dfac2c9b Merge branch 'warning-mesages' 2020-05-17 22:58:21 +10:00
Oliver
915bbef3b4 Merge pull request #812 from SchrodingersGat/more-testing
Add function to generate "keys" for test results.
2020-05-17 22:38:19 +10:00
Oliver Walters
1cc0977816 Display testing status for a stock item 2020-05-17 22:33:41 +10:00
Oliver Walters
02b0c0831d Removed test that caused a bug 2020-05-17 22:29:07 +10:00
Oliver Walters
6cb017bbfd Add functions to test if a stock item has passed all tests 2020-05-17 22:03:55 +10:00
Oliver Walters
5f318799c1 Logic fix for table row grouping 2020-05-17 21:51:46 +10:00
Oliver Walters
8ace71ef56 Complete refactor of the test-result table for stock item 2020-05-17 21:09:49 +10:00
Oliver Walters
b9799e1824 Add some more part slidies 2020-05-17 17:05:04 +10:00
Oliver Walters
e30f6ec374 Add forms / views for creating / editing / deleting test templates 2020-05-17 16:50:34 +10:00
Oliver Walters
cd0e66e3c6 Add ability to edit / assign attatched files to test result data 2020-05-17 16:17:05 +10:00
Oliver Walters
e9ed50fc4b Add table displaying part test templates 2020-05-17 16:07:55 +10:00
Oliver Walters
66f2c01d5d Add (empty) page for displaying part test templates 2020-05-17 14:26:53 +10:00
Oliver Walters
bc8b3a68f0 Fixes for unit testing 2020-05-17 14:17:55 +10:00
Oliver Walters
69c748d018 PEP fix 2020-05-17 14:15:13 +10:00
Oliver Walters
95d07cd02b Add unit testing for new API features 2020-05-17 14:14:54 +10:00
Oliver Walters
4d992ea528 Expose test templates to the API 2020-05-17 13:56:49 +10:00
Oliver Walters
f791ac9f57 Register test template in the admin interface 2020-05-17 13:50:06 +10:00
Oliver Walters
badf9230a9 Add fixtures / unit testing for the stock item testing framework 2020-05-17 13:46:19 +10:00
Oliver Walters
8c8b704e38 Add PartTestTemplate model 2020-05-17 13:26:51 +10:00
Oliver Walters
17f241774f Add function to generate "keys" for test results.
- As the keys are to be used for dict-based lookup (in a template) then they cannot contains spaces.
- May as well enforce lower-case encoding!
2020-05-17 12:59:03 +10:00
Oliver Walters
1e94a597c9 Merge remote-tracking branch 'inventree/master' 2020-05-17 00:42:03 +10:00
Oliver
c54cb2b280 Merge pull request #811 from SchrodingersGat/stock-item-testing
Stock item testing
2020-05-17 00:37:53 +10:00
Oliver Walters
b3ca6a6ca7 PEP fixes 2020-05-17 00:26:44 +10:00
Oliver Walters
327682b719 Add forms / views / etc to create / edit / delete test results manually 2020-05-17 00:26:10 +10:00
Oliver Walters
82fe497787 Add buttons to edit / delete a Test result
- Don't do nuthin yet!
2020-05-17 00:04:45 +10:00
Oliver Walters
05856a72cf UI cleanup 2020-05-16 23:56:50 +10:00
Oliver Walters
e23a9c1269 Load testresult table for stock item
- Uses the API / bootstrap table
- Is pretty!
- Provides link to the attachment (if one exists)
2020-05-16 23:54:07 +10:00
Oliver Walters
3b53437f46 Add 'attachment_detail' to the TestResult serializer 2020-05-16 23:53:28 +10:00
Oliver Walters
608057da69 Add option for user_detail in stockitemtestresult serializer 2020-05-16 23:36:03 +10:00
Oliver Walters
e02b692ab2 Improve API filtering for StockItem 2020-05-16 23:19:16 +10:00
Oliver Walters
197a3e6731 Fixes for Stock API 2020-05-16 23:12:43 +10:00
Oliver Walters
fd11317409 Whoops 2020-05-16 23:04:37 +10:00
Oliver Walters
45556058d2 Allow files to be uploaded alongside a test report
- Attach the file to the stock item
- Link the uploaded attachment to the test report
2020-05-16 22:53:23 +10:00
Oliver Walters
247cfcc514 Add API unit tests 2020-05-16 21:57:41 +10:00
Oliver Walters
d6a56da441 PEP fixes 2020-05-16 21:15:14 +10:00
Oliver Walters
a17ab9bfbd Add an (empty) page for dispalying test results 2020-05-16 21:10:27 +10:00
Oliver Walters
fe99e92bfc Refactor table_filters javascript file to prevent loading on every single page 2020-05-16 21:02:25 +10:00
Oliver Walters
f3c71bd96f API interface for StockItemTestResult 2020-05-16 20:56:36 +10:00
Oliver Walters
880a0a4af8 Add StockItemTestResult to the admin interface 2020-05-16 20:55:30 +10:00
Oliver Walters
df91b8cf4d Add function to get all test results as a map
- This will be required for pushing out to a test report
2020-05-16 20:45:10 +10:00
Oliver Walters
2bb9fd9955 Add some unit testing for the new model 2020-05-16 20:27:01 +10:00
Oliver Walters
f39f5e5825 Add StockItemTestResult model 2020-05-16 19:56:18 +10:00
Oliver
e550831efa Merge pull request #810 from SchrodingersGat/serial-auto-fill
Serial auto fill
2020-05-16 19:30:18 +10:00
Oliver Walters
8a99062704 PEP fixes 2020-05-16 17:52:25 +10:00
Oliver Walters
a6ad263ee7 Fix clean functions so unit tests pass 2020-05-16 17:43:32 +10:00
Oliver Walters
40735d66a1 Translation tweaks 2020-05-16 17:32:20 +10:00
Oliver Walters
7190a8ef69 Serial number placeholder text for BuildComplete form 2020-05-16 17:29:41 +10:00
Oliver Walters
6552d011a4 Better calculatation of placeholder text for serial number 2020-05-16 16:42:34 +10:00
Oliver Walters
3df8f33080 Logic fixes for CreateStockItem form
- Improved data validation
- Fix bug where form was not checked for validity
2020-05-16 12:04:53 +10:00
Oliver Walters
3d0bea15ae Refactor function naming 2020-05-16 12:03:18 +10:00
Oliver Walters
4cb97b1340 Add some more form candy 2020-05-16 11:55:10 +10:00
Oliver Walters
498ad4162c Bugfix: Turns out 'prefix' and 'suffix' were protected fields! 2020-05-16 11:05:45 +10:00
Oliver Walters
08d177e55f Update refactor for editing PO and SO forms 2020-05-16 09:36:43 +10:00
Oliver Walters
8fae32e3c7 Refactor HelperForm to easily allow setting prepended text / placeholder / etc 2020-05-16 09:33:34 +10:00
Oliver Walters
0ccac09962 Auto-fill serial numbers for the SerializeStock form 2020-05-16 09:06:39 +10:00
Oliver Walters
10762fc1cf Refactor tractor 2020-05-16 08:55:19 +10:00
Oliver Walters
ea88a03b5a More serial number validation and unit testing
-
2020-05-16 08:43:57 +10:00
Oliver Walters
2d6c531fda Unit testing for part variant MPTT 2020-05-15 22:01:21 +10:00
Oliver Walters
0652579312 Update fixture for part model to match MPTT requirements 2020-05-15 21:44:25 +10:00
Oliver Walters
0a78432a0f Convert 'part" to MPTT model - based on the 'variant_of' field
- Now recursive variants can be implemented properly
2020-05-15 21:35:53 +10:00
Oliver Walters
72cfaccac5 Pass StockItem object through to the SerializeStock form 2020-05-15 21:16:00 +10:00
Oliver
5b5b848a98 Merge pull request #805 from SchrodingersGat/form-candy
Form candy
2020-05-14 21:56:55 +10:00
Oliver Walters
0f00205256 PEP fix 2020-05-14 21:52:39 +10:00
Oliver Walters
007d2d4054 Add prepended text to order references for forms 2020-05-14 21:51:44 +10:00
Oliver Walters
16aa18429a Use bootstrap3 styling for django crispy forms 2020-05-14 16:55:33 +10:00
Oliver
cf9891398a Merge pull request #804 from SchrodingersGat/order-auto-increment
Order auto increment
2020-05-14 15:36:05 +10:00
Oliver Walters
5167f54268 Fix unit tests 2020-05-14 15:20:40 +10:00
Oliver Walters
6175c5408c Javascript indent cleanup 2020-05-14 15:10:48 +10:00
Oliver Walters
d3758981b4 Fix "New Sales Order" button in Customer detail view 2020-05-14 15:09:31 +10:00
Oliver Walters
b619f26074 Auto-increment sales order reference number 2020-05-14 15:05:55 +10:00
Oliver Walters
08903f357e Auto-increment the purchase-order number when creating a new one 2020-05-14 15:02:46 +10:00
Oliver Walters
cebfe9a30f Function to predict the next purchase order number 2020-05-14 15:00:00 +10:00
Oliver Walters
41eff97c7c Add function to "increment" a number or a number-like string
- Observe string width
- Keep prefix if one exists
2020-05-14 14:59:49 +10:00
Oliver
65f081d252 Merge pull request #803 from SchrodingersGat/attachment-drag-and-drop
Attachment drag and drop
2020-05-13 11:38:18 +10:00
Oliver Walters
30b5f7d507 Drag and drop for order attachments 2020-05-13 11:28:45 +10:00
Oliver Walters
7143c32fc9 Drag-and-drop attachments for stock item 2020-05-13 11:22:57 +10:00
Oliver Walters
db01f3646a Enable drag-and-drop attachment upload for Part 2020-05-13 11:13:26 +10:00
Oliver Walters
cedf9a9108 Attachment comment field is optional 2020-05-13 10:16:26 +10:00
Oliver Walters
dcf00d816d Merge remote-tracking branch 'inventree/master' 2020-05-12 22:14:20 +10:00
Oliver
a0e1645ca1 Update README.md 2020-05-12 22:13:50 +10:00
Oliver
c26d22e599 Merge pull request #802 from SchrodingersGat/attachment-user
Attachment Improvements
2020-05-12 22:10:44 +10:00
Oliver Walters
f5b97da5d2 Refactor "attachment" table into template 2020-05-12 22:05:38 +10:00
Oliver Walters
366d4b2143 Add new attechment functionality to new models
- Giving the ol' refactor tractor a fresh coat of paint
2020-05-12 21:40:42 +10:00
Oliver Walters
2369b40bbf Ensure user gets saved when uploading attachment via API 2020-05-12 21:11:38 +10:00
Oliver Walters
5d716d0cdd Add "upload date" field to fileattachment base class 2020-05-12 20:57:41 +10:00
Oliver Walters
d4fa7d936e Add 'user' field to attachment 2020-05-12 20:50:03 +10:00
Oliver
2948dad831 Merge pull request #800 from SchrodingersGat/stock-api
Stock api
2020-05-12 20:26:30 +10:00
Oliver Walters
0851a925fb Add ability to filter by whether the part is serialized or not 2020-05-12 20:18:28 +10:00
Oliver Walters
4615fbc0d8 Abillty to filter stock list by serial number 2020-05-12 20:15:37 +10:00
Oliver Walters
e4872d9f67 Merge remote-tracking branch 'inventree/master' 2020-05-12 09:16:04 +10:00
Oliver
c371a9a8e8 Merge pull request #799 from SchrodingersGat/stock-track-api
Stock track api
2020-05-12 08:49:18 +10:00
Oliver Walters
b9d0c60189 Pepper 2020-05-12 08:12:42 +10:00
Oliver Walters
c6cff1fb2e Fixes for StockItem tracking API
- Make the tracking API consistent with other API endpoints
2020-05-12 08:12:12 +10:00
Oliver
18fbe2d2dd Merge pull request #798 from SchrodingersGat/transa
Typo fix
2020-05-12 07:11:20 +10:00
Oliver Walters
ac5e26ca0e Typo fix 2020-05-12 07:07:29 +10:00
Oliver Walters
a86513e15d Merge remote-tracking branch 'inventree/master' 2020-05-12 00:29:33 +10:00
Oliver
d2a7961895 Merge pull request #795 from SchrodingersGat/attachment-api
Attachment api
2020-05-12 00:10:13 +10:00
Oliver
65fe6bfaca Merge pull request #796 from SchrodingersGat/newer-icon
Newer icon
2020-05-12 00:09:42 +10:00
Oliver Walters
3151612962 PEP fix 2020-05-12 00:07:08 +10:00
Oliver Walters
693af04c11 Export large version of the logo 2020-05-12 00:06:26 +10:00
Oliver Walters
4b1d96faad Icon tweaks 2020-05-12 00:01:56 +10:00
Oliver Walters
645e5b6449 Add "larger" version of the icon 2020-05-11 23:58:35 +10:00
Oliver Walters
99af98c5a7 Update iconset 2020-05-11 23:58:27 +10:00
Oliver Walters
cfc0145180 Add some unit tests 2020-05-11 23:44:22 +10:00
Oliver Walters
a7e5a79f4c Expose salesorder and purchaseorder attachments to the API 2020-05-11 23:41:57 +10:00
Oliver Walters
17d0a015f2 Add API endpoint for StockItem attachment items 2020-05-11 23:32:40 +10:00
Oliver Walters
f36c5137dd Add ability to add part file attachments via the API 2020-05-11 23:25:55 +10:00
Oliver Walters
c5999f7186 Merge remote-tracking branch 'inventree/master' 2020-05-11 23:10:29 +10:00
Oliver
f71bfb5700 Update version.py 2020-05-07 10:08:37 +10:00
Oliver
00ccfdf11b Update version.py 2020-05-07 10:08:20 +10:00
Oliver
5747a07f7b Merge pull request #792 from SchrodingersGat/stock-item-attachment
Stock item attachment
2020-05-07 10:07:31 +10:00
Oliver Walters
003b384abd Slight adjustment to page tabs for StockItem view 2020-05-07 10:04:16 +10:00
Oliver Walters
ea0d32fd3d PEP fixes 2020-05-07 09:58:29 +10:00
Oliver Walters
14132a6efa Add views / models / etc etc to support StockItem attachment 2020-05-07 09:57:54 +10:00
Oliver Walters
64f6238351 Add StockItemAttachment model 2020-05-07 09:39:28 +10:00
Oliver
e83a0610af Merge pull request #790 from SchrodingersGat/secondary-dialog
Add "new manufacturer" button
2020-05-04 20:05:10 +10:00
Oliver Walters
6318b0bddf Hide a silly button which does nothing 2020-05-04 19:51:06 +10:00
Oliver Walters
0933cf859c Add "new manufacturer" button 2020-05-04 19:48:09 +10:00
Oliver Walters
bbf6f6f93d Merge remote-tracking branch 'inventree/master' 2020-05-04 12:04:02 +10:00
Oliver
7afb2a6a75 Merge pull request #786 from SchrodingersGat/stats-fix
Table colspan fix
2020-05-04 10:01:05 +10:00
Oliver Walters
ec3e02af94 Table colspan fix 2020-05-04 09:52:50 +10:00
Oliver Walters
15011b7b20 Merge remote-tracking branch 'inventree/master' 2020-05-04 09:46:43 +10:00
Oliver
9823c3c81b Merge pull request #785 from SchrodingersGat/bug-icon
Update icon
2020-05-04 09:46:19 +10:00
Oliver Walters
ce610490b6 Update icon
- Simple test to see if the travis integration is working correctly now
2020-05-04 09:43:09 +10:00
Oliver Walters
1c3878829d Merge remote-tracking branch 'inventree/master' 2020-05-04 09:39:19 +10:00
Oliver
78cc3a9cf3 Merge pull request #783 from SchrodingersGat/redirect-tweaks
Redirect tweaks
2020-05-04 08:58:35 +10:00
Oliver Walters
436fb3bf30 PEP fixes 2020-05-04 08:54:16 +10:00
Oliver Walters
2c44104c9c Small tweak for login redirect 2020-05-04 08:53:47 +10:00
Oliver
461d694cf8 Merge pull request #782 from andyseracuse/redirect-after-login
after a login redirect and a successful login, the user is now redirected to the originally desired url
2020-05-04 08:49:13 +10:00
Oliver
779c1e1d58 Merge pull request #780 from SchrodingersGat/rejected-stock
Rejected stock
2020-05-04 08:41:34 +10:00
Oliver Walters
5a100962fe Merge remote-tracking branch 'inventree/master' into rejected-stock
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
2020-05-04 08:10:14 +10:00
Oliver
c505080527 Merge pull request #781 from chschlue/updloc2
Update de translation
2020-05-04 08:07:37 +10:00
Oliver Walters
53149ab4dc Merge remote-tracking branch 'inventree/master' into rejected-stock
# Conflicts:
#	InvenTree/locale/de/LC_MESSAGES/django.po
#	InvenTree/locale/en/LC_MESSAGES/django.po
#	InvenTree/locale/es/LC_MESSAGES/django.po
2020-05-04 08:06:50 +10:00
Andy Seracuse
85c948ef67 made changed middleware and made necessary changes to settings and urls fles so that the user is redirected to their desired page after a login redirect unless the desired page was logout, in which case the user will be redirect 2020-05-03 14:11:57 -06:00
Christian Schlüter
0a5a1ec5fd Update de translation 2020-05-03 11:37:51 +02:00
Oliver Walters
54c903f637 translation updates 2020-05-03 09:51:59 +10:00
Oliver Walters
7430abc237 Add ability to set stock status when receiving goods 2020-05-03 09:50:00 +10:00
Oliver Walters
fe87bba577 Link fix for purchase order table 2020-05-03 09:46:42 +10:00
Oliver
ca1b9e6403 Merge pull request #778 from SchrodingersGat/dynamic-js
Update translations
2020-05-03 09:29:34 +10:00
Oliver Walters
29335fa665 Add "rejected" status code for StockItem 2020-05-03 09:09:17 +10:00
Oliver
45fc8ce6bd Merge pull request #779 from SchrodingersGat/translation-helper
Translation helper
2020-05-03 09:03:06 +10:00
Oliver Walters
275cd063e1 PEP fixes 2020-05-03 08:59:44 +10:00
Oliver Walters
88e28edba9 Script now manually adjusts the translation file 2020-05-02 23:10:18 +10:00
Oliver Walters
979cf10c66 First pass at a translation helper script 2020-05-02 22:52:32 +10:00
Oliver Walters
034f70c491 Update translations 2020-05-02 22:39:56 +10:00
Oliver
9ee9664e65 Merge pull request #777 from SchrodingersGat/dynamic-js
Fix stock thing
2020-05-02 22:22:28 +10:00
Oliver Walters
d59f22febb Fix stock thing 2020-05-02 22:18:08 +10:00
Oliver
1a4f5cf719 Merge pull request #776 from SchrodingersGat/dynamic-js
Add endpoint for dynamic javascript files
2020-05-02 22:16:35 +10:00
Oliver Walters
af6dd83f05 Rename .js files to .html
This is required so they are parsed by the translation engine
2020-05-02 22:13:14 +10:00
Oliver Walters
314b8fdbff regenerate translation files 2020-05-02 22:08:25 +10:00
Oliver Walters
853ba825c0 Translation layer for bom.js 2020-05-02 22:07:24 +10:00
Oliver Walters
6c3dc2a25d Translation layer for company.js 2020-05-02 22:01:40 +10:00
Oliver Walters
2c9b76575e Add translation layer for order.js 2020-05-02 21:55:09 +10:00
Oliver Walters
23bd9afaf8 Add translation layer for build.js 2020-05-02 21:48:28 +10:00
Oliver Walters
24a816e9a2 More translations for part.js and stock.js 2020-05-02 21:43:07 +10:00
Oliver Walters
b1a642918c Add translation layer for stock.js 2020-05-02 21:36:18 +10:00
Oliver Walters
9b1e387a8b Translations for part.js 2020-05-02 21:27:45 +10:00
Oliver Walters
5160165669 Add endpoint for dynamic javascript files 2020-05-02 21:19:34 +10:00
Oliver Walters
fb0ebbb1e4 Merge remote-tracking branch 'inventree/master' 2020-05-02 21:05:00 +10:00
Oliver
e998098e4f Merge pull request #775 from SchrodingersGat/sentry-integration
Add option for sentry.io integration
2020-05-02 21:04:07 +10:00
Oliver Walters
b1d33ef3bc Add option for sentry.io integration 2020-05-02 20:58:29 +10:00
Oliver
873c03376a Merge pull request #774 from SchrodingersGat/part-display
Part display
2020-05-02 20:32:33 +10:00
Oliver Walters
b39283a18f Separate allocation counters 2020-05-02 20:29:20 +10:00
Oliver Walters
26f0338f1d Auto-select a purchase order when ordering parts 2020-05-02 20:25:47 +10:00
Oliver Walters
0199760e1c Bug fix 2020-05-02 20:10:12 +10:00
Oliver Walters
b89002a450 Add button to order a supplier part 2020-05-02 20:10:00 +10:00
Oliver Walters
937211288e Merge remote-tracking branch 'inventree/master' 2020-05-02 17:30:08 +10:00
Oliver
0b2c6cfd70 Merge pull request #773 from SchrodingersGat/moar-speed-fix-plz
Reduce company list from 100 queries to 4 queries
2020-05-02 15:41:39 +10:00
Oliver Walters
6912899f41 Merge remote-tracking branch 'inventree/master' 2020-05-02 15:37:24 +10:00
Oliver Walters
b0f4475a83 Fixes 2020-05-02 15:36:48 +10:00
Oliver Walters
094ef38e27 Merge remote-tracking branch 'inventree/master' 2020-05-02 15:29:47 +10:00
Oliver Walters
a8e3a3f1ac Reduce company list from 100 queries to 4 queries 2020-05-02 15:23:28 +10:00
Oliver
5f6599a950 Merge pull request #772 from SchrodingersGat/new-logo
New logo
2020-05-02 15:19:52 +10:00
Oliver Walters
6aa6e3b924 Adjust icon size in nav bar 2020-05-02 15:03:49 +10:00
Oliver Walters
24a9a1127b Update favicon
https://www.favicon-generator.org/
2020-05-02 14:58:07 +10:00
Oliver Walters
a51aab6dd0 Update translations
(cherry picked from commit 032f3337cddf684839586728e47864d22a890024)
2020-05-02 14:55:31 +10:00
Oliver Walters
b44dbba150 New logo design
(cherry picked from commit b59e26b4629ea97e0ac8b3503cc50c59049d81c1)
2020-05-02 14:55:27 +10:00
Oliver
d276c48fef Merge pull request #771 from SchrodingersGat/query-speed
Query speed
2020-05-02 14:15:05 +10:00
Oliver Walters
9b2045025b StockItem page tweaks 2020-05-02 14:05:52 +10:00
Oliver Walters
cc11df917e Part list API adjustments 2020-05-02 14:03:17 +10:00
Oliver Walters
7fca496de8 Bug fix for StockItem list API
- The wrong detail data was being set
2020-05-02 13:51:29 +10:00
Oliver Walters
4197e29fce Major major major (improvements for StockItem list API)
OK LISTEN UP - Lots of work went into making this speedier:

- For related detail fields (e.g. part_detail), we pre-fetch and cache the model data
- This eliminates duplicate database hits for the same model instances
- Perform all field filtering manually, rather than using the DRF 'filter_fields' concept (this seems to add a lot of overhead)
- Use query annotations to getch calculated fields rather than fetching one-at-a-time
- And finally, if the request is AJAX then return a JsonResponse which is SO FREAKING MUCH FASTER
2020-05-02 13:46:19 +10:00
Oliver Walters
44319d24e4 Custom list serializer for 'location_detail' 2020-05-02 10:05:35 +10:00
Oliver Walters
a537b6df6e PEP fixes 2020-05-02 09:50:18 +10:00
Oliver Walters
4a60da67fd Significant increase in query speed for Part list
- Custom list method
- Cache PartCategory objects in memory
2020-05-02 09:49:05 +10:00
Oliver
acea0d6e92 Merge pull request #770 from SchrodingersGat/missing-git
Catch an error if git cannot be found
2020-05-01 17:08:42 +10:00
Oliver Walters
7fff0a7427 Catch an error if git cannot be found 2020-05-01 17:02:11 +10:00
Oliver
68bbb372dc Merge pull request #769 from SchrodingersGat/migration-ixes
Bug fix for custom migration
2020-05-01 16:23:53 +10:00
Oliver Walters
af00d88555 Bug fix for custom migration
Ref: https://stackoverflow.com/questions/13410982/attributeerror-long-object-has-no-attribute-fetchall#13411358
2020-05-01 15:57:10 +10:00
Oliver
86c00f54b7 Merge pull request #767 from SchrodingersGat/fix
Fix for BOM table display
2020-04-28 23:31:52 +10:00
Oliver Walters
a345e0e8da Removed unused serializer field 2020-04-28 23:26:27 +10:00
Oliver Walters
753fab2498 Fix url links in BOM table 2020-04-28 23:23:59 +10:00
Oliver Walters
3b42b5e27e Typo fix for part api 2020-04-28 23:17:59 +10:00
Oliver Walters
087001f29d Fix BOM table rendering
- Price was not being sent in the PartBriefSerializer!
2020-04-28 23:17:15 +10:00
Oliver Walters
df218a5193 Fix rendering of "used in" page 2020-04-28 22:57:18 +10:00
Oliver Walters
36ad69091b Merge remote-tracking branch 'inventree/master' 2020-04-28 12:34:47 +10:00
Oliver
24ad4f5332 Merge pull request #765 from SchrodingersGat/markdowner
DO NOT DRINK BLEACH
2020-04-28 12:34:21 +10:00
Oliver Walters
f84636fc20 DO NOT DRINK BLEACH 2020-04-28 12:29:28 +10:00
Oliver Walters
351e825ba8 Merge remote-tracking branch 'inventree/master' 2020-04-28 10:51:55 +10:00
Oliver
2be8aad29c Merge pull request #763 from SchrodingersGat/fixes
Update buttons for part BOM view
2020-04-28 10:51:11 +10:00
Oliver Walters
ee906fc6e6 Unit test fixes 2020-04-28 10:46:02 +10:00
Oliver Walters
9add3d4409 Much better rendering and calculation of part allocations 2020-04-28 10:43:46 +10:00
Oliver Walters
fb70da0331 Cleanup part allocation calculation functions 2020-04-28 10:35:19 +10:00
Oliver Walters
6bdf371490 Moar UI and translation string fixes 2020-04-28 09:41:47 +10:00
Oliver Walters
bbecc8c900 Reverse URL bug fix 2020-04-28 09:35:24 +10:00
Oliver Walters
b913971008 Add more translatable strings 2020-04-28 09:32:33 +10:00
Oliver Walters
440fe155ff Change glyphicons for fontawesome
I think I gottem all
2020-04-28 09:31:51 +10:00
Oliver Walters
abbd0bb16a Bug fix in supplier-part table rendering 2020-04-28 09:05:06 +10:00
Oliver Walters
5727e27ae6 Filter by 'in stock' items when auto-allocating to build 2020-04-28 08:44:10 +10:00
Oliver Walters
4fd7b24e3c Update buttons for part BOM view 2020-04-28 08:36:13 +10:00
Oliver Walters
b338834146 Merge remote-tracking branch 'inventree/master' 2020-04-27 22:18:45 +10:00
Oliver
c621780a2a Merge pull request #748 from SchrodingersGat/sales-order
Sales order [WIP]
2020-04-27 22:14:45 +10:00
Oliver Walters
394a9208a1 Merge remote-tracking branch 'inventree/master' into sales-order
# Conflicts:
#	InvenTree/InvenTree/version.py
2020-04-27 22:04:05 +10:00
Oliver Walters
79836c77ef Bumped version thing 2020-04-27 22:03:15 +10:00
Oliver Walters
db9970e5df Add some further unit tests for the Build model 2020-04-27 21:44:59 +10:00
Oliver Walters
cb3fe0fc35 Add some more unit testing for the builds 2020-04-27 21:28:44 +10:00
Oliver Walters
35f48ed899 Delete BuildItem objects once a Build has been completed
- Much more complicated template for build allocation page!
- This will require some refactoring at some point ...
2020-04-27 20:46:34 +10:00
Oliver Walters
489dfa1823 Bug fix for a code path which resulted in a form failing validation but not showing any errors!
This one has been here for a while!
2020-04-27 20:45:01 +10:00
Oliver Walters
2b99cf353a Fix for build complete form 2020-04-27 20:16:41 +10:00
Oliver Walters
646dd65d27 Re-enable auto-allocation for build 2020-04-27 20:05:02 +10:00
Oliver Walters
3685ca4b95 Add some unit testing for the SalesOrder model 2020-04-27 11:32:20 +10:00
Oliver Walters
5e309a62f7 Display "Fulfilled" items
- Once a salesorder has been marked as "shipped" then the table is displayed differently
- The sub rows show stock items which have been fulfilled against the sales order
2020-04-27 10:31:38 +10:00
Oliver Walters
9b882f4d17 Update to latest version of django-qr-code 2020-04-27 09:17:17 +10:00
Oliver Walters
5167117067 Calculate 'fulfilled' quantity once a sales order is marked as shipped
- This allows us to delete the SalesOrderAllocation objects from the database
2020-04-27 08:58:18 +10:00
Oliver Walters
3c5ba75d27 PEP fixes 2020-04-26 16:44:35 +10:00
Oliver Walters
e768ada83b More work
- Consolidated "in_stock" filter to single code location
- Improve 'limit_choices_to' for BuildItem and SalesOrderAllocation
- Various template improvements etc
2020-04-26 16:38:29 +10:00
Oliver Walters
4147163418 Improve status code label rendering 2020-04-26 15:29:21 +10:00
Oliver
48c51151c8 Merge pull request #756 from SchrodingersGat/moar-migration-fixes-plz
Remove the problematic migration entirely
2020-04-26 09:00:23 +10:00
Oliver Walters
ae4717401f Add "sudo" to makefile 2020-04-26 08:56:36 +10:00
Oliver Walters
1f4bd95d75 Remove the problematic migration entirely
- The thumbnail check code is run every time the server is started anyway!
2020-04-26 08:50:37 +10:00
Oliver Walters
0892b160c6 "Fixes" for completing a build
- This will require a lot of unit testing to get right
2020-04-26 00:32:09 +10:00
Oliver Walters
72c43d0c2d Bug fix for build completion form 2020-04-25 23:59:28 +10:00
Oliver Walters
50dbebdf59 Improve rendering of BuildComplete template 2020-04-25 23:44:03 +10:00
Oliver Walters
81f789d857 Add link to parent build 2020-04-25 23:26:56 +10:00
Oliver Walters
4f0efec39f PEP and unit testing fixes 2020-04-25 23:24:00 +10:00
Oliver Walters
77361bd0a2 Update templates 2020-04-25 23:20:55 +10:00
Oliver Walters
01a68270ea Add verbose names for multiple Build model fields
- Improve methods for different models
2020-04-25 23:17:07 +10:00
Oliver Walters
181d1d6b91 Factor out function to calculate total allocations 2020-04-25 21:31:58 +10:00
Oliver Walters
912a3c4b99 Update progress bar based on sum of allocated quantities 2020-04-25 21:21:52 +10:00
Oliver Walters
b0891c921c Working towards better build allocation:
- Improve data serialization in API
- Javascript bug fixes
- Load the build allocation table using jQuery
2020-04-25 21:13:38 +10:00
Oliver Walters
c11b433d94 Make Build object into a MPTT tree model
- Builds can have child builds
2020-04-25 15:25:17 +10:00
Oliver Walters
2f0bbecc3d Refactored status code label generation
- Larger style available
2020-04-25 15:13:55 +10:00
Oliver Walters
4e40d92db7 PEP fix 2020-04-25 13:31:42 +10:00
Oliver Walters
66b6036827 Add two new "build orders" tab to the "sales order" view 2020-04-25 13:29:18 +10:00
Oliver Walters
d5f3498238 Add a "sales_order" reference to the Build model
- If a build order is made to fulfil a sales order
- Add sales_order filtering to the Build API
- Pass initial information through to the BuildCreate view
2020-04-25 13:15:45 +10:00
Oliver Walters
b351976ae9 Mark a SalesOrder as "shipped"
- Option to hide non-stock items from stock list
- Update models with new feature
2020-04-25 08:46:28 +10:00
Oliver Walters
c5b93e2392 Update pillow version
- Addresses a security patch requirement
2020-04-24 20:40:56 +10:00
Oliver Walters
41a4033427 Selective display of sales order ilne buttons 2020-04-24 17:18:18 +10:00
Oliver Walters
429bb688d0 Template fixes 2020-04-24 13:03:38 +10:00
Oliver Walters
9d25ed335c Rebuild the "PurchaseOrder" detail
- Use AJAX and bootstrap-table
- Display progress bar
2020-04-24 12:52:08 +10:00
Oliver Walters
ba1d2063af Remove some debug messages and fix PIP 2020-04-24 10:22:33 +10:00
Oliver Walters
77471cb89c Form for shipping a SalesOrder
- Returns "False" for now
2020-04-24 10:20:56 +10:00
Oliver Walters
b45fec221c Expose more status code data to the templates
- Status codes are now exposed globally to every page
- Much simplified so wow
- https://stackoverflow.com/questions/3221592/how-to-pass-common-dictionary-data-to-every-page-in-django
2020-04-24 09:27:42 +10:00
Oliver Walters
2c9b112562 PEP fixes 2020-04-23 21:48:39 +10:00
Oliver Walters
e5fa94b4f8 Add functionality to cancel a sales order 2020-04-23 21:38:40 +10:00
Oliver Walters
e384f9e94c Order date adjustment
Sales order now has a "shipment date"
2020-04-23 20:42:59 +10:00
Oliver Walters
435c13cf7c Separate concept of "OrderStatus" into "SalesOrderStatus" and "PurchaseOrderStatus" 2020-04-23 20:38:09 +10:00
Oliver Walters
7f020cbbf6 Enbiggen a whole lotta buttons 2020-04-23 19:41:14 +10:00
Oliver Walters
426aa9258c URL cleanup 2020-04-23 17:37:53 +10:00
Oliver Walters
5d71cf85cc Add separate 'quantity' and 'allocated' columns in sales order view 2020-04-23 16:00:09 +10:00
Oliver Walters
c9ea33e22e Fix order of javascript table events 2020-04-23 10:58:26 +10:00
Oliver Walters
d59c6711bb Update translations 2020-04-23 09:20:25 +10:00
Oliver Walters
1a0f091e0c Improve progress bar rendering 2020-04-23 09:20:18 +10:00
Oliver Walters
a803f21e0c Add buttons to create new builds or orders for sales order parts
- Need to pre-fill the forms a bit better
2020-04-22 23:34:27 +10:00
Oliver Walters
6112be2df0 Add forms for editing and deleting a SalesOrderAllocation item 2020-04-22 23:21:54 +10:00
Oliver Walters
2a4e903785 Add button to delete a SalesOrderLineItem 2020-04-22 22:36:55 +10:00
Oliver Walters
26d1a25f31 PEP style fixes 2020-04-22 22:24:06 +10:00
Oliver Walters
fd42149f67 More stuff 2020-04-22 22:22:22 +10:00
Oliver Walters
6ab03bd05a Add form for creating a new StockItem allocation 2020-04-22 21:26:38 +10:00
Oliver Walters
2972aec759 Cleverer rendering of sales order allocations 2020-04-22 20:26:05 +10:00
Oliver Walters
b70e79b778 Optionally add all SalesOrderAllocations to the SalesOrderLineItem serializer 2020-04-22 20:10:23 +10:00
Oliver Walters
5d1754ec32 Better display of where a StockItem is allocated 2020-04-22 17:39:59 +10:00
Oliver Walters
eb7b49784b StockItem serializer now includes the allocated quantity 2020-04-22 15:24:11 +10:00
Oliver Walters
d9698b10cc PEP fixes 2020-04-22 13:21:45 +10:00
Oliver Walters
1373425c29 Update definition for StockItemAllocation model
- Limit foreignkey choices
- Error checking
- Check if a StockItem is over-allocated
- Fix API serialization and filtering
2020-04-22 13:11:19 +10:00
Oliver Walters
2cb1b076f6 Create "SalesOrderAllocation" object
- Links multiple StockItem objects to a single SalesOrderLineItem
2020-04-22 12:12:48 +10:00
Oliver Walters
3a71a4f63a Fix for StockItem model
- Allow sales_order_line to be blank
2020-04-22 10:16:54 +10:00
Oliver Walters
6dd79af0b6 Expose "is_allocated" parameter on StockItem API 2020-04-22 10:11:40 +10:00
Oliver Walters
12daf15406 Update build page 2020-04-22 09:53:11 +10:00
Oliver Walters
372958d939 Migrate more pages to the two_column template 2020-04-22 09:50:10 +10:00
Oliver Walters
808a636484 Move "Company" view to new two-column template 2020-04-22 09:01:52 +10:00
Oliver Walters
79ea744280 Supplier part rendering fix 2020-04-21 22:39:47 +10:00
Oliver Walters
09ccd6c5e2 PEP style fixes 2020-04-21 22:37:35 +10:00
Oliver Walters
b75c343236 Add action buttons to the sales order page 2020-04-21 22:02:17 +10:00
Oliver Walters
15166c7797 Add a custom "id" to the progress bar 2020-04-21 21:43:04 +10:00
Oliver Walters
4979c690d9 Prevent BOM price calculation from becoming too recursive 2020-04-21 21:38:22 +10:00
Oliver Walters
cb636e000d Display a sub-list of stock items which are allocated to a SalseOrderLineItem 2020-04-21 21:38:04 +10:00
Oliver Walters
b40234e403 UI tweaks 2020-04-21 20:05:15 +10:00
Oliver Walters
399dcafede Use the existing bootstrap CSS for progress bars 2020-04-21 18:14:02 +10:00
Oliver Walters
2c6e8da90e Ability to filter StockItemList API by sales_order or sales_order_line 2020-04-21 17:33:02 +10:00
Oliver Walters
0d1919f10b Display an alert on a stock item page if that stock item is allocated to a salesorder 2020-04-21 16:59:14 +10:00
Oliver Walters
89ede3e103 Fix for SalesOrderLineItem allocation calculation
Also function to render a progress bar
2020-04-21 16:45:44 +10:00
Oliver Walters
a1376eeb9e The 'StockItem' model now has a reference to a SalesOrderLineItem 2020-04-21 15:04:21 +10:00
Oliver Walters
8052a1989c Serialize the allocated quantity for a purchase-order line item 2020-04-21 11:41:08 +10:00
Oliver Walters
7385099194 Add a model to map multiple StockItem objects to a single SalesOrderLineItem 2020-04-21 10:14:55 +10:00
Oliver Walters
19cd0707a2 Add / edit / delete attachments for SalesOrder 2020-04-21 09:42:11 +10:00
Oliver Walters
a06595c152 Add line numbering to SalesOrderLineItem table 2020-04-21 09:20:44 +10:00
Oliver Walters
22c96ad2b7 Add ability to filter SalesOrder list by part 2020-04-21 09:17:50 +10:00
Oliver Walters
3d2e907d5e Add a 'sales order' view for each part 2020-04-21 09:15:01 +10:00
Oliver Walters
b204618e79 Button / view / form to create a new SalesOrderLineItem 2020-04-21 09:02:10 +10:00
Oliver Walters
617fbf2f02 Moar stuffs:
- Expose part_detail and order_detail to SOLineItem serializer
- Update SalesOrder line item table
2020-04-21 08:57:13 +10:00
Oliver Walters
a2c0c7c76a Add "part" reference to SalesOrderLineItem model 2020-04-21 08:33:32 +10:00
Oliver Walters
34d3dca8b7 Add ability to filter parts by "purchasable" status 2020-04-20 22:40:52 +10:00
Oliver Walters
9e4d09343c Add ability to filter parts list by "salable" status 2020-04-20 22:39:00 +10:00
Oliver Walters
0c56079b41 Create missing tabs for sales orders
- Attachments
- Notes
2020-04-20 22:33:49 +10:00
Oliver Walters
e12824df2e Add form to edit a SalesOrder 2020-04-20 22:20:03 +10:00
Oliver Walters
ce1dd88129 Form for creating a new SalesOrder 2020-04-20 22:13:07 +10:00
Oliver Walters
ebbcff3c7f Render a table of line items 2020-04-20 21:22:34 +10:00
Oliver Walters
b2569d5cba Expose SalesOrderLineItem objects to the REST API 2020-04-20 21:11:59 +10:00
Oliver Walters
47ada25315 Add detail view for SalesOrder 2020-04-20 20:59:14 +10:00
Oliver Walters
1ebf26ab7c Add page for displaying all sales orders 2020-04-20 20:40:45 +10:00
Oliver Walters
627c50e465 Render a table of sales orders 2020-04-20 20:27:52 +10:00
Oliver Walters
c7fd22924f Register salesorder classes in the admin interface 2020-04-20 20:27:35 +10:00
Oliver Walters
9f97d81e83 API endpoint for serializing SalesOrder objects 2020-04-20 20:11:21 +10:00
Oliver Walters
5901b21e78 UI elements
- Add a "sales order" menu item to the main navbar
- Add a "sales order" tab to customer detail page
2020-04-20 19:47:29 +10:00
Oliver Walters
974c98c95a Add "SalesOrder" concept
- SalesOrder model
- SalesOrderLineItem
- SalesOrderAttachment
2020-04-20 19:41:58 +10:00
Oliver
c5166ec845 Update version.py 2020-04-20 19:30:58 +10:00
Oliver Walters
87d8b4674a Merge remote-tracking branch 'inventree/master' 2020-04-20 09:58:49 +10:00
Oliver Walters
c49cd9ffde Merge remote-tracking branch 'inventree/master' 2020-04-20 01:28:31 +10:00
Oliver Walters
51e2f5c46b Merge remote-tracking branch 'inventree/master' 2020-04-18 15:46:33 +10:00
Oliver Walters
4822d3fd63 Merge remote-tracking branch 'inventree/master' 2020-04-17 21:49:00 +10:00
Oliver Walters
cbfb3b55e6 Merge remote-tracking branch 'upstream/master' 2020-04-17 19:14:15 +10:00
Oliver Walters
762d735618 Merge remote-tracking branch 'inventree/master' 2020-04-16 21:55:59 +10:00
Oliver Walters
2e1c4e9792 Merge remote-tracking branch 'inventree/master' 2020-04-13 20:43:00 +10:00
Oliver Walters
a8ceddc8e4 Merge remote-tracking branch 'inventree/master' 2020-04-12 01:05:42 +10:00
Oliver Walters
ba2b1ce581 Merge remote-tracking branch 'inventree/master' 2020-04-10 01:12:11 +10:00
Oliver Walters
4a02a90954 Merge remote-tracking branch 'inventree/master' 2020-04-07 00:08:44 +10:00
Oliver Walters
93eeeec2f3 Merge remote-tracking branch 'inventree/master' 2020-04-06 21:15:06 +10:00
Oliver Walters
b8f7555a73 Merge remote-tracking branch 'inventree/master' 2020-04-06 16:25:48 +10:00
Oliver Walters
efaa532162 Merge remote-tracking branch 'inventree/master' 2020-04-05 22:07:57 +10:00
Oliver Walters
428b52693a Merge remote-tracking branch 'inventree/master' 2020-04-05 01:00:00 +11:00
Oliver Walters
55e831f4b4 Merge remote-tracking branch 'inventree/master' 2020-04-03 14:24:35 +11:00
Oliver Walters
aada5f91cb Merge remote-tracking branch 'inventree/master' 2020-03-31 22:15:58 +11:00
Oliver Walters
b0edd0eb05 Merge remote-tracking branch 'inventree/master' 2020-03-30 19:06:30 +11:00
Oliver Walters
5b77ff4a4c Merge remote-tracking branch 'inventree/master' 2020-03-26 18:08:34 +11:00
Oliver Walters
ed6abcdf32 Merge remote-tracking branch 'inventree/master' 2020-03-22 20:20:22 +11:00
Oliver Walters
dc0a0f9dc2 Merge branch 'master' of https://github.com/inventree/inventree 2020-03-22 20:14:34 +11:00
Oliver Walters
02ec1d4fa2 Merge remote-tracking branch 'inventree/master' 2020-03-19 10:29:26 +11:00
Oliver Walters
d8f5255572 Merge remote-tracking branch 'inventree/master' 2020-03-18 22:24:52 +11:00
Oliver Walters
7424cc1352 Merge remote-tracking branch 'inventree/master' 2020-03-18 21:33:09 +11:00
Oliver Walters
41259f520f Merge remote-tracking branch 'inventree/master' 2020-03-18 21:12:49 +11:00
Oliver Walters
388b26dad2 Merge remote-tracking branch 'inventree/master' 2020-02-25 12:42:49 +11:00
Oliver Walters
ef83480f65 Merge remote-tracking branch 'inventree/master' 2020-02-19 00:03:32 +11:00
Oliver Walters
0498fd633a Merge remote-tracking branch 'inventree/master' 2020-02-12 12:56:17 +11:00
Oliver Walters
3479528d5b Merge branch 'cascading-bom' 2020-02-11 22:48:33 +11:00
Oliver Walters
bb4c25ba68 Merge remote-tracking branch 'inventree/master' 2020-02-11 20:36:13 +11:00
Oliver Walters
bb0c991965 Merge branch 'inventree-settings' 2020-02-03 21:34:08 +11:00
Oliver Walters
8412885e09 Merge remote-tracking branch 'inventree/master' 2020-02-02 22:26:18 +11:00
Oliver Walters
22e3dc634b Merge remote-tracking branch 'inventree/master' 2020-02-02 21:11:52 +11:00
Oliver Walters
e03d8f55ea Merge remote-tracking branch 'inventree/master' 2020-02-02 18:10:05 +11:00
Oliver Walters
40037d826d Merge remote-tracking branch 'inventree/master' 2020-02-02 12:48:04 +11:00
Oliver Walters
8d924eb300 Merge remote-tracking branch 'inventree/master' 2020-01-19 21:39:22 +11:00
Oliver Walters
07f3cd5644 Merge remote-tracking branch 'inventree/master' 2020-01-07 21:31:28 +11:00
Oliver Walters
f217650cec Merge remote-tracking branch 'inventree/master' 2020-01-06 21:11:00 +11:00
Oliver Walters
07de23f120 Merge remote-tracking branch 'inventree/master' 2020-01-06 10:11:18 +11:00
Oliver Walters
881931c6b1 Merge remote-tracking branch 'inventree/master' 2020-01-02 21:08:56 +11:00
Oliver Walters
6bbe818e9c Merge remote-tracking branch 'inventree/master' 2019-12-09 22:27:06 +11:00
Oliver Walters
f6d5f2e426 Merge remote-tracking branch 'inventree/master' 2019-12-05 23:11:54 +11:00
Oliver Walters
0e57a4caec Merge remote-tracking branch 'inventree/master' 2019-12-05 16:36:23 +11:00
Oliver Walters
b29e1ded64 Merge branch 'decimal-quantity' 2019-11-19 21:47:22 +11:00
Oliver Walters
6e54c49142 Merge remote-tracking branch 'inventree/master' 2019-11-16 20:45:34 +11:00
Oliver Walters
f7a1fb0a9d Merge remote-tracking branch 'upstream/master' 2019-09-30 13:54:49 +10:00
Oliver Walters
cfe33deb8e Merge remote-tracking branch 'upstream/master' 2019-09-29 09:04:47 +10:00
Oliver Walters
e891f117f3 Merge remote-tracking branch 'inventree/master' 2019-09-27 10:25:11 +10:00
Oliver Walters
6d628a77fd Merge remote-tracking branch 'inventree/master' 2019-09-24 08:10:00 +10:00
Oliver Walters
14217ff648 Merge remote-tracking branch 'inventree/master' 2019-09-24 08:06:11 +10:00
Oliver Walters
d6749dfb24 Merge remote-tracking branch 'inventree/master' 2019-09-22 22:34:34 +10:00
Oliver Walters
41d91a8f9b Merge remote-tracking branch 'inventree/master' 2019-09-19 15:43:15 +10:00
Oliver Walters
119cccc318 Merge remote-tracking branch 'inventree/master' 2019-09-17 20:32:30 +10:00
Oliver Walters
0a7ea27e9f Merge remote-tracking branch 'inventree/master' 2019-09-17 14:22:04 +10:00
Oliver Walters
420b16104c Merge remote-tracking branch 'inventree/master' 2019-09-16 00:09:20 +10:00
Oliver Walters
f64758eb03 Merge remote-tracking branch 'inventree/master' 2019-09-15 23:29:36 +10:00
Oliver Walters
d0ad3f0e37 Merge remote-tracking branch 'inventree/master' 2019-09-15 22:28:55 +10:00
Oliver Walters
5fde9777fb Merge remote-tracking branch 'inventree/master' 2019-09-14 00:19:17 +10:00
Oliver Walters
4b33b15dd2 Merge remote-tracking branch 'inventree/master' 2019-09-13 23:38:07 +10:00
Oliver Walters
2be99be4de Merge remote-tracking branch 'inventree/master' 2019-09-13 16:41:34 +10:00
Oliver Walters
625ab33bc8 Merge remote-tracking branch 'inventree/master' 2019-09-13 15:38:41 +10:00
Oliver Walters
9681372a84 Merge remote-tracking branch 'inventree/master' 2019-09-13 11:20:39 +10:00
Oliver Walters
0683911076 Merge remote-tracking branch 'inventree/master' 2019-09-12 22:55:58 +10:00
Oliver Walters
d703e48ecb Merge remote-tracking branch 'inventree/master' 2019-09-10 14:50:47 +10:00
Oliver Walters
015ed66967 Merge remote-tracking branch 'inventree/master' 2019-09-09 20:54:55 +10:00
Oliver Walters
0a4f7a55b8 Merge remote-tracking branch 'inventree/master' 2019-09-09 16:20:01 +10:00
Oliver Walters
a6e850e39f Merge remote-tracking branch 'inventree/master' 2019-09-09 15:03:57 +10:00
Oliver Walters
abecb4856f Merge remote-tracking branch 'inventree/master' 2019-09-09 00:09:58 +10:00
Oliver Walters
dbf88f8485 Merge remote-tracking branch 'upstream/master' 2019-09-08 01:48:20 +10:00
Oliver Walters
83af318ad0 Merge remote-tracking branch 'inventree/master' 2019-09-07 21:23:50 +10:00
Oliver Walters
7be1edd896 Merge remote-tracking branch 'inventree/master' 2019-09-07 20:37:30 +10:00
Oliver Walters
d6ca21273d Merge remote-tracking branch 'inventree/master' 2019-09-07 15:03:54 +10:00
Oliver Walters
dd934f0e34 Merge remote-tracking branch 'inventree/master' 2019-09-06 14:42:40 +10:00
Oliver Walters
612851fd48 Merge remote-tracking branch 'inventree/master' 2019-09-06 11:19:48 +10:00
Oliver Walters
755962c6a2 Merge remote-tracking branch 'inventree/master' 2019-09-05 20:13:17 +10:00
Oliver Walters
153dde4129 Merge remote-tracking branch 'inventree/master' 2019-09-04 11:02:27 +10:00
Oliver Walters
8f3a022b3c Merge remote-tracking branch 'inventree/master' 2019-09-04 08:57:24 +10:00
Oliver Walters
017bf187f9 Merge remote-tracking branch 'inventree/master' 2019-09-03 10:42:14 +10:00
Oliver Walters
7b8d7c9fe0 Merge remote-tracking branch 'upstream/master' 2019-09-01 23:33:39 +10:00
Oliver Walters
d319c79abb Merge remote-tracking branch 'upstream/master' 2019-08-30 02:59:01 +10:00
Oliver Walters
1e62528d2a Merge remote-tracking branch 'upstream/master' 2019-08-29 21:37:03 +10:00
Oliver Walters
7ae7c19a24 Merge remote-tracking branch 'inventree/master' 2019-08-29 08:21:21 +10:00
Oliver Walters
0dce5fab7b Merge remote-tracking branch 'inventree/master' 2019-08-28 19:48:46 +10:00
Oliver Walters
d1dc0fae19 Merge remote-tracking branch 'inventree/master' 2019-08-15 22:02:45 +10:00
Oliver Walters
dd33209b1c Merge remote-tracking branch 'inventree/master' 2019-08-15 19:54:21 +10:00
Oliver Walters
c3fe101571 Merge remote-tracking branch 'inventree/master' 2019-08-15 13:41:50 +10:00
Oliver Walters
2c1b20b5d5 Merge branch 'mysql-install' 2019-08-14 13:19:13 +10:00
Oliver Walters
c1ab004c0c Merge remote-tracking branch 'inventree/master' 2019-08-09 20:37:46 +10:00
Oliver Walters
348f2e1df8 Merge remote-tracking branch 'inventree/master' 2019-08-07 10:29:32 +10:00
Oliver Walters
3098c8c155 Merge branch 'bom-output' 2019-08-07 09:27:31 +10:00
Oliver Walters
55ed483b13 Merge remote-tracking branch 'inventree/master' 2019-08-07 08:55:01 +10:00
Oliver Walters
84ea95181d Merge remote-tracking branch 'inventree/master' 2019-08-02 22:37:26 +10:00
Oliver Walters
163f076565 Merge remote-tracking branch 'inventree/master' 2019-07-23 12:07:13 +10:00
Oliver Walters
7d2d6a79e4 Merge remote-tracking branch 'inventree/master' 2019-07-12 00:20:54 +10:00
Oliver Walters
40695b3288 Merge remote-tracking branch 'inventree/master' 2019-07-10 20:13:35 +10:00
Oliver Walters
bd9d5b92dc Merge remote-tracking branch 'inventree/master' 2019-06-25 21:04:02 +10:00
Oliver Walters
39a62d1cb9 Merge remote-tracking branch 'origin/master' 2019-06-25 16:39:50 +10:00
Oliver Walters
fd5b902e1f Merge remote-tracking branch 'inventree/master' 2019-06-25 16:39:41 +10:00
Oliver Walters
c7877c67ff Add a simple endpoint with server information 2019-06-24 23:51:46 +10:00
Oliver Walters
5d0369958f Merge remote-tracking branch 'inventree/master' 2019-06-24 08:27:58 +10:00
Oliver Walters
6da0106aa2 Merge remote-tracking branch 'inventree/master' 2019-06-20 21:49:30 +10:00
Oliver Walters
e0bfda2b14 Merge remote-tracking branch 'inventree/master' 2019-06-20 21:49:19 +10:00
Oliver Walters
e5c2ee5587 Merge remote-tracking branch 'inventree/master' 2019-06-19 08:12:14 +10:00
Oliver Walters
d4391f99bb Merge remote-tracking branch 'inventree/master' 2019-06-18 23:26:48 +10:00
Oliver Walters
346c713cd2 Merge remote-tracking branch 'inventree/master' 2019-06-18 22:26:47 +10:00
Oliver Walters
ec44a480a8 Merge remote-tracking branch 'inventree/master' 2019-06-18 11:51:02 +10:00
Oliver Walters
f417ddb8e0 Merge remote-tracking branch 'inventree/master' 2019-06-18 01:50:50 +10:00
Oliver Walters
1b43f151df Merge remote-tracking branch 'inventree/master' 2019-06-17 23:28:35 +10:00
Oliver Walters
6b5bed7786 Merge remote-tracking branch 'inventree/master' 2019-06-13 23:07:54 +10:00
Oliver Walters
c906cbe2c2 Merge branch 'stock-endpoint' 2019-06-13 23:06:08 +10:00
Oliver Walters
1dea5f1624 Merge remote-tracking branch 'inventree/master' 2019-06-13 22:54:10 +10:00
Oliver Walters
0fea7f2a22 Merge remote-tracking branch 'inventree/master' 2019-06-11 08:57:14 +10:00
Oliver Walters
45d19e3a4e Merge remote-tracking branch 'inventree/master' 2019-06-11 08:40:11 +10:00
Oliver Walters
8a46dda07f Merge remote-tracking branch 'inventree/master' 2019-06-10 23:22:04 +10:00
Oliver Walters
166b41196b Merge remote-tracking branch 'inventree/master' 2019-06-04 21:22:36 +10:00
Oliver Walters
a13e50445e Merge branch 'tweeeek' 2019-06-03 14:19:21 +10:00
Oliver Walters
c00b19bc5b Merge remote-tracking branch 'inventree/master' 2019-06-02 20:42:37 +10:00
Oliver Walters
9577e4e505 Merge remote-tracking branch 'inventree/master'
# Conflicts:
#	InvenTree/static/script/inventree/stock.js
#	InvenTree/stock/forms.py
#	InvenTree/stock/urls.py
#	InvenTree/stock/views.py
2019-06-02 12:51:56 +10:00
Oliver Walters
72dc75512b Pass list of selected stock items to the view 2019-05-29 22:23:45 +10:00
Oliver Walters
f4a052ee2b Redirect non-ajax forms to / 2019-05-29 22:11:03 +10:00
Oliver Walters
080f9da9c8 Beginning to move the stocktake forms server side 2019-05-29 22:05:13 +10:00
Oliver Walters
1c1cc670f8 Merge remote-tracking branch 'inventree/master' 2019-05-29 01:06:27 +10:00
Oliver Walters
141d9b779d Merge remote-tracking branch 'inventree/master' 2019-05-26 16:09:20 +10:00
Oliver Walters
dbfa812d37 Merge remote-tracking branch 'inventree/master' 2019-05-26 00:48:45 +10:00
Oliver Walters
026ffde807 Merge remote-tracking branch 'inventree/master' 2019-05-25 22:11:21 +10:00
Oliver Walters
e07d7e3874 Merge remote-tracking branch 'inventree/master' 2019-05-23 23:24:11 +10:00
Oliver Walters
413e996e92 Merge remote-tracking branch 'inventree/master' 2019-05-23 23:01:17 +10:00
Oliver Walters
bebf2c9bee Merge remote-tracking branch 'inventree/master' 2019-05-23 00:48:05 +10:00
Oliver Walters
afb927258c Merge remote-tracking branch 'inventree/master' 2019-05-21 16:37:16 +10:00
Oliver Walters
a15f46c972 Merge remote-tracking branch 'inventree/master' 2019-05-21 14:13:30 +10:00
Oliver Walters
92b0ed6599 Merge remote-tracking branch 'inventree/master' 2019-05-21 08:58:08 +10:00
Oliver Walters
29ab493cbe Merge remote-tracking branch 'inventree/master' 2019-05-21 00:58:19 +10:00
Oliver Walters
90915f8dc0 Merge remote-tracking branch 'inventree/master' 2019-05-19 00:14:35 +10:00
Oliver Walters
1f4471ccc3 Merge remote-tracking branch 'inventree/master' 2019-05-18 15:40:50 +10:00
Oliver Walters
5d4ec2154b Merge remote-tracking branch 'inventree/master' 2019-05-16 23:15:02 +10:00
Oliver Walters
9d9f30e41f Merge branch 'secondary-modals' 2019-05-14 23:53:14 +10:00
Oliver Walters
e3a8bb23c1 Merge remote-tracking branch 'inventree/master' 2019-05-14 18:54:23 +10:00
Oliver Walters
787ab0a2e4 Merge remote-tracking branch 'inventree/master' 2019-05-13 23:07:12 +10:00
Oliver Walters
c140ecf14b Merge remote-tracking branch 'inventree/master' 2019-05-13 19:00:51 +10:00
Oliver Walters
980116b33b Merge remote-tracking branch 'inventree/master' 2019-05-12 20:58:06 +10:00
Oliver Walters
142a7659bd Merge remote-tracking branch 'inventree/master' 2019-05-12 16:39:02 +10:00
Oliver Walters
6fbe588aee Merge branch 'case-insensitive-names' 2019-05-11 20:28:54 +10:00
Oliver Walters
17eb8237da Merge remote-tracking branch 'inventree/master' 2019-05-11 09:00:41 +10:00
Oliver Walters
f11cee7197 Merge remote-tracking branch 'inventree/master' 2019-05-10 23:29:16 +10:00
Oliver Walters
1b28326c5e Merge branch 'part-revision' 2019-05-10 20:19:21 +10:00
Oliver Walters
6ffb6db248 Merge remote-tracking branch 'inventree/master' 2019-05-10 08:52:45 +10:00
Oliver Walters
9b0825739a Merge remote-tracking branch 'inventree/master' 2019-05-09 23:07:42 +10:00
Oliver Walters
b42f7fce44 Merge remote-tracking branch 'inventree/master' 2019-05-09 18:44:29 +10:00
Oliver Walters
30f491795d Merge remote-tracking branch 'inventree/master' 2019-05-09 18:33:36 +10:00
Oliver Walters
55f7557b5e Merge remote-tracking branch 'inventree/master' 2019-05-09 18:30:49 +10:00
Oliver Walters
5a0de7088b Merge remote-tracking branch 'inventree/master' 2019-05-09 12:03:36 +10:00
Oliver Walters
9319b9f433 Merge remote-tracking branch 'inventree/master' 2019-05-09 00:53:20 +10:00
Oliver Walters
b8942acfed Merge remote-tracking branch 'inventree/master' 2019-05-09 00:44:19 +10:00
Oliver Walters
a0d8fbede3 Merge remote-tracking branch 'inventree/master' 2019-05-09 00:42:50 +10:00
Oliver Walters
8e8930d51f Merge branch 'help-text' 2019-05-09 00:20:31 +10:00
Oliver Walters
09b7578c35 Merge remote-tracking branch 'inventree/master' 2019-05-08 23:33:55 +10:00
Oliver Walters
fdd4d09714 Merge remote-tracking branch 'inventree/master' 2019-05-08 23:05:49 +10:00
Oliver Walters
0deb6e8bea Merge remote-tracking branch 'inventree/master' 2019-05-08 22:09:40 +10:00
Oliver Walters
586bad4876 Merge remote-tracking branch 'inventree/master' 2019-05-07 21:17:42 +10:00
Oliver Walters
47fd317a11 Merge remote-tracking branch 'inventree/master' 2019-05-07 14:53:31 +10:00
Oliver Walters
0c229ede24 Merge remote-tracking branch 'inventree/master' 2019-05-07 10:30:07 +10:00
Oliver Walters
64a6ee0f3b Merge remote-tracking branch 'inventree/master' 2019-05-07 08:14:12 +10:00
Oliver Walters
364f78d20c Merge remote-tracking branch 'inventree/master' 2019-05-07 00:19:18 +10:00
Oliver Walters
ff0d163a95 Limit SupplierPart choices in EditStockItem view 2019-05-06 18:05:29 +10:00
Oliver Walters
a7a37437a1 Merge remote-tracking branch 'inventree/master' 2019-05-06 18:00:43 +10:00
Oliver Walters
e333f5f726 Merge remote-tracking branch 'inventree/master' 2019-05-06 07:36:37 +10:00
Oliver Walters
c822450792 Merge remote-tracking branch 'inventree/master' 2019-05-05 20:22:41 +10:00
Oliver Walters
e6d77273c4 Merge remote-tracking branch 'inventree/master' 2019-05-05 11:53:50 +10:00
Oliver Walters
c203c3542f Merge remote-tracking branch 'inventree/master' 2019-05-05 11:49:58 +10:00
Oliver Walters
d218f07940 Merge remote-tracking branch 'inventree/master' 2019-05-05 01:07:35 +10:00
Oliver Walters
0da2999c75 Merge remote-tracking branch 'inventree/master' 2019-05-05 00:39:36 +10:00
Oliver Walters
67cfd22084 Merge branch 'part-image-hover' 2019-05-05 00:30:23 +10:00
Oliver Walters
d97484b30b Merge remote-tracking branch 'inventree/master' 2019-05-04 22:03:18 +10:00
Oliver Walters
d5ad888b0a Merge remote-tracking branch 'inventree/master' 2019-05-04 21:59:48 +10:00
Oliver Walters
a7cec1627f Merge remote-tracking branch 'inventree/master' 2019-05-04 11:49:49 +10:00
Oliver Walters
e42a1b7b88 Merge remote-tracking branch 'inventree/master' 2019-05-04 10:47:55 +10:00
Oliver Walters
dc03283e14 Merge branch 'image-upload-fix' 2019-05-04 00:43:47 +10:00
Oliver Walters
4aef7643a0 Fixed part image upload
- Image was being saved twice
- Don't call super().post in AjaxUpdateView
- Instead, handle properly
2019-05-04 00:37:08 +10:00
Oliver Walters
ac17cf0121 Merge remote-tracking branch 'inventree/master' 2019-05-04 00:03:46 +10:00
Oliver Walters
e19061c902 Merge remote-tracking branch 'inventree/master' 2019-05-03 23:53:37 +10:00
Oliver Walters
db71993905 Merge remote-tracking branch 'inventree/master' 2019-05-03 08:08:31 +10:00
Oliver Walters
3f8f7ed32c Merge remote-tracking branch 'inventree/master' 2019-05-02 21:33:51 +10:00
Oliver Walters
b7ac86fab4 Merge remote-tracking branch 'inventree/master' 2019-05-02 21:30:34 +10:00
Oliver Walters
79e0f972e7 Merge remote-tracking branch 'inventree/master' 2019-05-02 17:47:17 +10:00
Oliver Walters
255d754045 Merge remote-tracking branch 'inventree/master' 2019-05-02 01:05:08 +10:00
Oliver Walters
385c13148d Merge branch 'migration-test' 2019-05-02 01:03:08 +10:00
Oliver Walters
4de3445c58 Merge remote-tracking branch 'inventree/master' 2019-05-02 00:56:42 +10:00
Oliver Walters
a2314074d3 Merge remote-tracking branch 'inventree/master' 2019-05-02 00:30:17 +10:00
Oliver Walters
460ff571e4 Merge remote-tracking branch 'inventree/master' 2019-05-02 00:26:34 +10:00
Oliver Walters
3a10d235c1 Merge remote-tracking branch 'inventree/master' 2019-04-29 00:05:18 +10:00
Oliver Walters
207d2bb4d3 Merge remote-tracking branch 'inventree/master' 2019-04-28 21:26:33 +10:00
Oliver Walters
2076faaa6c Added docstring 2019-04-28 11:49:20 +10:00
Oliver Walters
ec166c906f Merge remote-tracking branch 'inventree/master' 2019-04-28 11:29:23 +10:00
Oliver Walters
c0e69d7a99 Merge remote-tracking branch 'inventree/master' 2019-04-28 01:18:32 +10:00
Oliver Walters
a8348aa674 Merge remote-tracking branch 'inventree/master' 2019-04-27 18:01:57 +10:00
Oliver Walters
b17590942d Merge remote-tracking branch 'inventree/master' 2019-04-27 17:56:49 +10:00
Oliver Walters
062b3fd0fe Merge remote-tracking branch 'inventree/master' 2019-04-27 15:32:46 +10:00
Oliver Walters
f2f40e4758 Merge branch 'stockitem-note' 2019-04-27 13:56:41 +10:00
Oliver Walters
922feec7f4 Merge remote-tracking branch 'inventree/master' 2019-04-27 01:08:14 +10:00
Oliver Walters
64636a6d60 Merge remote-tracking branch 'inventree/master' 2019-04-27 01:05:12 +10:00
Oliver Walters
ac46a4a413 Merge remote-tracking branch 'inventree/master' 2019-04-26 21:44:44 +10:00
Oliver Walters
7593d855cb Merge remote-tracking branch 'inventree/master' 2019-04-26 21:40:26 +10:00
Oliver Walters
27c7f6589c Merge remote-tracking branch 'inventree/master' 2019-04-26 21:25:00 +10:00
Oliver Walters
edad4f9cf1 Merge branch 'master' of https://github.com/SchrodingersGat/InvenTree
# Conflicts:
#	Makefile
2019-04-26 21:24:03 +10:00
Oliver Walters
14e9b71ebb Remove comment line in Makefile which doesn't play nice on Windows 2019-04-26 18:51:37 +10:00
890 changed files with 191162 additions and 13759 deletions

View File

@@ -1,8 +1,6 @@
[run]
source = ./InvenTree
omit =
# Do not run coverage on migration files
*/migrations/*
InvenTree/manage.py
InvenTree/setup.py
InvenTree/InvenTree/middleware.py

5
.gitattributes vendored
View File

@@ -4,3 +4,8 @@
*.md text
*.html text
*.txt text
*.yml text
*.yaml text
*.conf text
*.sh text
*.js text

60
.github/workflows/coverage.yaml vendored Normal file
View File

@@ -0,0 +1,60 @@
# Perform CI checks, and calculate code coverage
name: SQLite
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
# Run tests on SQLite database
# These tests are used for code coverage analysis
coverage:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_NAME: './test_db.sqlite'
INVENTREE_DB_ENGINE: django.db.backends.sqlite3
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Coverage Tests
run: |
invoke coverage
- name: Data Import Export
run: |
invoke migrate
invoke import-fixtures
invoke export-records -f data.json
rm test_db.sqlite
invoke migrate
invoke import-records -f data.json
invoke import-records -f data.json
- name: Test Translations
run: invoke translate
- name: Check Migration Files
run: python3 ci/check_migration_files.py
- name: Upload Coverage Report
run: coveralls

37
.github/workflows/docker_build.yaml vendored Normal file
View File

@@ -0,0 +1,37 @@
# Build and push latest docker image on push to master branch
name: Docker Build
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push
uses: docker/build-push-action@v2
with:
context: ./docker
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
target: production
repository: inventree/inventree
tags: inventree/inventree:latest
- name: Image Digest
run: echo ${{ steps.docker_build.outputs.digest }}

33
.github/workflows/docker_publish.yaml vendored Normal file
View File

@@ -0,0 +1,33 @@
# Publish docker images to dockerhub
name: Docker Publish
on:
release:
types: [published]
jobs:
publish_image:
name: Push InvenTree web server image to dockerhub
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push
uses: docker/build-push-action@v2
with:
context: ./docker
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
target: production
repository: inventree/inventree
tags: inventree/inventree:${{ github.event.release.tag_name }}

67
.github/workflows/mysql.yaml vendored Normal file
View File

@@ -0,0 +1,67 @@
# MySQL Unit Testing
name: MySQL
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
test:
runs-on: ubuntu-latest
env:
# Database backend configuration
INVENTREE_DB_ENGINE: django.db.backends.mysql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_USER: root
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 3306
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
services:
mysql:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: inventree
MYSQL_USER: inventree
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
ports:
- 3306:3306
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get install mysql-server libmysqlclient-dev
pip3 install invoke
pip3 install mysqlclient
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json

63
.github/workflows/postgresql.yaml vendored Normal file
View File

@@ -0,0 +1,63 @@
# PostgreSQL Unit Testing
name: PostgreSQL
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
test:
runs-on: ubuntu-latest
env:
# Database backend configuration
INVENTREE_DB_ENGINE: django.db.backends.postgresql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_USER: inventree
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 5432
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
services:
postgres:
image: postgres
env:
POSTGRES_USER: inventree
POSTGRES_PASSWORD: password
ports:
- 5432:5432
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get install libpq-dev
pip3 install invoke
pip3 install psycopg2
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json

34
.github/workflows/style.yaml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Style Checks
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
style:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.7]
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install deps
run: |
pip install flake8==3.8.3
pip install pep8-naming==0.11.1
- name: flake8
run: |
flake8 InvenTree

60
.github/workflows/translations.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Update Translation Files
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_NAME: './test_db.sqlite'
INVENTREE_DB_ENGINE: django.db.backends.sqlite3
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- uses: actions/checkout@v2
- name: Get Current Translations
run: |
git fetch
git checkout origin/l10 -- `git ls-tree origin/l10 -r --name-only | grep ".po"`
git reset
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y gettext
pip3 install invoke
invoke install
- name: Make Translations
run: |
invoke translate
- name: stash changes
run: |
git stash
- name: Checkout Translation Branch
uses: actions/checkout@v2.3.4
with:
ref: l10
- name: Commit files
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git checkout stash -- .
git reset
git add "*.po"
git commit -m "updated translation base"
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: l10

7
.gitignore vendored
View File

@@ -31,6 +31,7 @@ var/
*.log
local_settings.py
*.sqlite3
*.sqlite3-journal
*.backup
*.old
@@ -40,10 +41,16 @@ docs/_build
# Local static and media file storage (only when running in development mode)
inventree_media
inventree_static
static_i18n
# Local config file
config.yaml
# Default data file
data.json
*.json.tmp
*.tmp.json
# Key file
secret_key.txt

View File

@@ -1,17 +0,0 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
formats: all
# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.5
install:
- requirements: docs/requirements.txt

View File

@@ -1,27 +0,0 @@
dist: xenial
language: python
python:
- 3.6
- 3.7
addons:
apt-packages:
- sqlite3
before_install:
- sudo apt-get update
- sudo apt-get install gettext
- make install
- make migrate
- cd InvenTree && python3 manage.py createsuperuser --username InvenTreeAdmin --email admin@inventree.com --noinput && cd ..
script:
- cd InvenTree && python3 manage.py makemigrations && cd ..
- python3 ci/check_migration_files.py
- make coverage
- make translate
- make style
after_success:
- coveralls

View File

@@ -6,7 +6,7 @@ No pushing to master! New featues must be submitted in a separate branch (one br
## Include Migration Files
Any required migration files **must** be included in the commit, or the pull-request will be rejected. If you change the underlying database schema, make sure you run `make migrate` and commit the migration files before submitting the PR.
Any required migration files **must** be included in the commit, or the pull-request will be rejected. If you change the underlying database schema, make sure you run `invoke migrate` and commit the migration files before submitting the PR.
## Update Translation Files
@@ -14,7 +14,7 @@ Any PRs which update translatable strings (i.e. text strings that will appear in
*This does not mean that all translations must be provided, but that the translation files must include locations for the translated strings to be written.*
To perform this step, simply run `make_translate` from the top level directory before submitting the PR.
To perform this step, simply run `invoke translate` from the top level directory before submitting the PR.
## Testing
@@ -22,9 +22,8 @@ Any new code should be covered by unit tests - a submitted PR may not be accepte
## Documentation
New features or updates to existing features should be accompanied by user documentation.
A PR with associated documentation should link to the matching PR at https://github.com/inventree/InvenTree.github.io
New features or updates to existing features should be accompanied by user documentation. A PR with associated documentation should link to the matching PR at https://github.com/inventree/inventree-docs/
## Code Style
Sumbitted Python code is automatically checked against PEP style guidelines. Locally you can run `make style` to ensure the style checks will pass, before submitting the PR.
Sumbitted Python code is automatically checked against PEP style guidelines. Locally you can run `invoke style` to ensure the style checks will pass, before submitting the PR.

View File

@@ -5,22 +5,29 @@ Main JSON interface views
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.utils.translation import ugettext as _
import logging
from django.utils.translation import ugettext_lazy as _
from django.http import JsonResponse
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from .views import AjaxView
from .version import inventreeVersion, inventreeInstanceName
from .version import inventreeVersion, inventreeApiVersion, inventreeInstanceName
from .status import is_worker_running
from plugins import plugins as inventree_plugins
# Load barcode plugins
print("INFO: Loading plugins")
barcode_plugins = inventree_plugins.load_barcode_plugins()
logger = logging.getLogger("inventree")
logger.info("Loading action plugins...")
action_plugins = inventree_plugins.load_action_plugins()
@@ -29,17 +36,60 @@ class InfoView(AjaxView):
Use to confirm that the server is running, etc.
"""
permission_classes = [permissions.AllowAny]
def get(self, request, *args, **kwargs):
data = {
'server': 'InvenTree',
'version': inventreeVersion(),
'instance': inventreeInstanceName(),
'apiVersion': inventreeApiVersion(),
'worker_running': is_worker_running(),
}
return JsonResponse(data)
class NotFoundView(AjaxView):
"""
Simple JSON view when accessing an invalid API view.
"""
permission_classes = [permissions.AllowAny]
def get(self, request, *args, **kwargs):
data = {
'details': _('API endpoint not found'),
'url': request.build_absolute_uri(),
}
return JsonResponse(data, status=404)
class AttachmentMixin:
"""
Mixin for creating attachment objects,
and ensuring the user information is saved correctly.
"""
permission_classes = [permissions.IsAuthenticated]
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
def perform_create(self, serializer):
""" Save the user information when a file is uploaded """
attachment = serializer.save()
attachment.user = self.request.user
attachment.save()
class ActionPluginView(APIView):
"""
Endpoint for running custom action plugins.
@@ -74,69 +124,3 @@ class ActionPluginView(APIView):
'error': _("No matching action found"),
"action": action,
})
class BarcodePluginView(APIView):
"""
Endpoint for handling barcode scan requests.
Barcode data are decoded by the client application,
and sent to this endpoint (as a JSON object) for validation.
A barcode could follow the internal InvenTree barcode format,
or it could match to a third-party barcode format (e.g. Digikey).
"""
permission_classes = [
permissions.IsAuthenticated,
]
def post(self, request, *args, **kwargs):
response = {}
barcode_data = request.data.get('barcode', None)
print("Barcode data:")
print(barcode_data)
if barcode_data is None:
response['error'] = _('No barcode data provided')
else:
# Look for a barcode plugin that knows how to handle the data
for plugin_class in barcode_plugins:
# Instantiate the plugin with the provided plugin data
plugin = plugin_class(barcode_data)
if plugin.validate():
# Plugin should return a dict response
response = plugin.decode()
if type(response) is dict:
if 'success' not in response.keys() and 'error' not in response.keys():
response['success'] = _('Barcode successfully decoded')
else:
response = {
'error': _('Barcode plugin returned incorrect response')
}
response['plugin'] = plugin.plugin_name()
response['hash'] = plugin.hash()
break
if 'error' not in response and 'success' not in response:
response = {
'error': _('Unknown barcode format'),
}
# Include the original barcode data
response['barcode_data'] = barcode_data
print("Response:")
print(response)
return Response(response)

View File

@@ -0,0 +1,94 @@
"""
Helper functions for performing API unit tests
"""
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from rest_framework.test import APITestCase
class InvenTreeAPITestCase(APITestCase):
"""
Base class for running InvenTree API tests
"""
# User information
username = 'testuser'
password = 'mypassword'
email = 'test@testing.com'
superuser = False
auto_login = True
# Set list of roles automatically associated with the user
roles = []
def setUp(self):
super().setUp()
# Create a user to log in with
self.user = get_user_model().objects.create_user(
username=self.username,
password=self.password,
email=self.email
)
# Create a group for the user
self.group = Group.objects.create(name='my_test_group')
self.user.groups.add(self.group)
if self.superuser:
self.user.is_superuser = True
self.user.save()
for role in self.roles:
self.assignRole(role)
if self.auto_login:
self.client.login(username=self.username, password=self.password)
def assignRole(self, role):
"""
Set the user roles for the registered user
"""
# role is of the format 'rule.permission' e.g. 'part.add'
rule, perm = role.split('.')
for ruleset in self.group.rule_sets.all():
if ruleset.name == rule:
if perm == 'view':
ruleset.can_view = True
elif perm == 'change':
ruleset.can_change = True
elif perm == 'delete':
ruleset.can_delete = True
elif perm == 'add':
ruleset.can_add = True
ruleset.save()
break
def get(self, url, data={}, code=200):
"""
Issue a GET request
"""
response = self.client.get(url, data, format='json')
self.assertEqual(response.status_code, code)
return response
def post(self, url, data):
"""
Issue a POST request
"""
response = self.client.post(url, data=data, format='json')
return response

105
InvenTree/InvenTree/apps.py Normal file
View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
import logging
from django.apps import AppConfig
from django.core.exceptions import AppRegistryNotReady
from django.conf import settings
from InvenTree.ready import isInTestMode, canAppAccessDatabase
import InvenTree.tasks
logger = logging.getLogger("inventree")
class InvenTreeConfig(AppConfig):
name = 'InvenTree'
def ready(self):
if canAppAccessDatabase():
self.start_background_tasks()
if not isInTestMode():
self.update_exchange_rates()
def start_background_tasks(self):
try:
from django_q.models import Schedule
except (AppRegistryNotReady):
return
logger.info("Starting background tasks...")
InvenTree.tasks.schedule_task(
'InvenTree.tasks.delete_successful_tasks',
schedule_type=Schedule.DAILY,
)
InvenTree.tasks.schedule_task(
'InvenTree.tasks.check_for_updates',
schedule_type=Schedule.DAILY
)
InvenTree.tasks.schedule_task(
'InvenTree.tasks.heartbeat',
schedule_type=Schedule.MINUTES,
minutes=15
)
InvenTree.tasks.schedule_task(
'InvenTree.tasks.update_exchange_rates',
schedule_type=Schedule.DAILY,
)
def update_exchange_rates(self):
"""
Update exchange rates each time the server is started, *if*:
a) Have not been updated recently (one day or less)
b) The base exchange rate has been altered
"""
try:
from djmoney.contrib.exchange.models import ExchangeBackend
from datetime import datetime, timedelta
from InvenTree.tasks import update_exchange_rates
except AppRegistryNotReady:
pass
base_currency = settings.BASE_CURRENCY
update = False
try:
backend = ExchangeBackend.objects.get(name='InvenTreeExchange')
last_update = backend.last_update
if last_update is not None:
delta = datetime.now().date() - last_update.date()
if delta > timedelta(days=1):
print(f"Last update was {last_update}")
update = True
else:
# Never been updated
print("Exchange backend has never been updated")
update = True
# Backend currency has changed?
if not base_currency == backend.base_currency:
print(f"Base currency changed from {backend.base_currency} to {base_currency}")
update = True
except (ExchangeBackend.DoesNotExist):
print("Exchange backend not found - updating")
update = True
except:
# Some other error - potentially the tables are not ready yet
return
if update:
update_exchange_rates()

View File

@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
"""
Provides extra global data to all templates.
"""
from InvenTree.status_codes import SalesOrderStatus, PurchaseOrderStatus
from InvenTree.status_codes import BuildStatus, StockStatus
from InvenTree.status_codes import StockHistoryCode
import InvenTree.status
from users.models import RuleSet
def health_status(request):
"""
Provide system health status information to the global context.
- Not required for AJAX requests
- Do not provide if it is already provided to the context
"""
if request.path.endswith('.js'):
# Do not provide to script requests
return {}
if hasattr(request, '_inventree_health_status'):
# Do not duplicate efforts
return {}
request._inventree_health_status = True
status = {
'django_q_running': InvenTree.status.is_worker_running(),
'email_configured': InvenTree.status.is_email_configured(),
}
all_healthy = True
for k in status.keys():
if status[k] is not True:
all_healthy = False
status['system_healthy'] = all_healthy
status['up_to_date'] = InvenTree.version.isInvenTreeUpToDate()
return status
def status_codes(request):
"""
Provide status code enumerations.
"""
if hasattr(request, '_inventree_status_codes'):
# Do not duplicate efforts
return {}
request._inventree_status_codes = True
return {
# Expose the StatusCode classes to the templates
'SalesOrderStatus': SalesOrderStatus,
'PurchaseOrderStatus': PurchaseOrderStatus,
'BuildStatus': BuildStatus,
'StockStatus': StockStatus,
'StockHistoryCode': StockHistoryCode,
}
def user_roles(request):
"""
Return a map of the current roles assigned to the user.
Roles are denoted by their simple names, and then the permission type.
Permissions can be access as follows:
- roles.part.view
- roles.build.delete
Each value will return a boolean True / False
"""
user = request.user
roles = {
}
if user.is_superuser:
for ruleset in RuleSet.RULESET_MODELS.keys():
roles[ruleset] = {
'view': True,
'add': True,
'change': True,
'delete': True,
}
else:
for group in user.groups.all():
for rule in group.rule_sets.all():
# Ensure the role name is in the dict
if rule.name not in roles:
roles[rule.name] = {
'view': user.is_superuser,
'add': user.is_superuser,
'change': user.is_superuser,
'delete': user.is_superuser
}
# Roles are additive across groups
roles[rule.name]['view'] |= rule.can_view
roles[rule.name]['add'] |= rule.can_add
roles[rule.name]['change'] |= rule.can_change
roles[rule.name]['delete'] |= rule.can_delete
return {'roles': roles}

View File

@@ -0,0 +1,29 @@
from django.conf import settings as inventree_settings
from djmoney.contrib.exchange.backends.base import SimpleExchangeBackend
class InvenTreeExchange(SimpleExchangeBackend):
"""
Backend for automatically updating currency exchange rates.
Uses the exchangerate.host service API
"""
name = "InvenTreeExchange"
def __init__(self):
self.url = "https://api.exchangerate.host/latest"
super().__init__()
def get_params(self):
# No API key is required
return {
}
def update_rates(self, base_currency=inventree_settings.BASE_CURRENCY):
symbols = ','.join(inventree_settings.CURRENCIES)
super().update_rates(base=base_currency, symbols=symbols)

View File

@@ -5,13 +5,16 @@ from __future__ import unicode_literals
from .validators import allowable_url_schemes
from django.utils.translation import ugettext_lazy as _
from django.forms.fields import URLField as FormURLField
from django.db import models as models
from django.core import validators
from django import forms
from decimal import Decimal
from InvenTree.helpers import normalize
import InvenTree.helpers
class InvenTreeURLFormField(FormURLField):
@@ -31,6 +34,34 @@ class InvenTreeURLField(models.URLField):
})
class DatePickerFormField(forms.DateField):
"""
Custom date-picker field
"""
def __init__(self, **kwargs):
help_text = kwargs.get('help_text', _('Enter date'))
label = kwargs.get('label', None)
required = kwargs.get('required', False)
initial = kwargs.get('initial', None)
widget = forms.DateInput(
attrs={
'type': 'date',
}
)
forms.DateField.__init__(
self,
required=required,
initial=initial,
help_text=help_text,
widget=widget,
label=label
)
def round_decimal(value, places):
"""
Round value to the specified number of places.
@@ -55,7 +86,7 @@ class RoundingDecimalFormField(forms.DecimalField):
"""
if type(value) == Decimal:
return normalize(value)
return InvenTree.helpers.normalize(value)
else:
return value
@@ -69,5 +100,7 @@ class RoundingDecimalField(models.DecimalField):
defaults = {
'form_class': RoundingDecimalFormField
}
defaults.update(kwargs)
return super(RoundingDecimalField, self).formfield(**kwargs)
return super().formfield(**kwargs)

View File

@@ -5,19 +5,117 @@ Helper forms which subclass Django forms to provide additional functionality
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django import forms
from crispy_forms.helper import FormHelper
from django.contrib.auth.models import User
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
from common.models import ColorTheme
from part.models import PartCategory
class HelperForm(forms.ModelForm):
""" Provides simple integration of crispy_forms extension. """
# Custom field decorations can be specified here, per form class
field_prefix = {}
field_suffix = {}
field_placeholder = {}
def __init__(self, *args, **kwargs):
super(forms.ModelForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_show_errors = True
"""
Create a default 'layout' for this form.
Ref: https://django-crispy-forms.readthedocs.io/en/latest/layouts.html
This is required to do fancy things later (like adding PrependedText, etc).
Simply create a 'blank' layout for each available field.
"""
self.rebuild_layout()
def is_valid(self):
valid = super(HelperForm, self).is_valid()
return valid
def rebuild_layout(self):
layouts = []
for field in self.fields:
prefix = self.field_prefix.get(field, None)
suffix = self.field_suffix.get(field, None)
placeholder = self.field_placeholder.get(field, '')
# Look for font-awesome icons
if prefix and prefix.startswith('fa-'):
prefix = r"<i class='fas {fa}'/>".format(fa=prefix)
if suffix and suffix.startswith('fa-'):
suffix = r"<i class='fas {fa}'/>".format(fa=suffix)
if prefix and suffix:
layouts.append(
Field(
PrependedAppendedText(
field,
prepended_text=prefix,
appended_text=suffix,
placeholder=placeholder
)
)
)
elif prefix:
layouts.append(
Field(
PrependedText(
field,
prefix,
placeholder=placeholder
)
)
)
elif suffix:
layouts.append(
Field(
AppendedText(
field,
suffix,
placeholder=placeholder
)
)
)
else:
layouts.append(Field(field, placeholder=placeholder))
self.helper.layout = Layout(*layouts)
class ConfirmForm(forms.Form):
""" Generic confirmation form """
confirm = forms.BooleanField(
required=False, initial=False,
help_text=_("Confirm")
)
class Meta:
fields = [
'confirm'
]
class DeleteForm(forms.Form):
@@ -27,7 +125,8 @@ class DeleteForm(forms.Form):
confirm_delete = forms.BooleanField(
required=False,
initial=False,
help_text='Confirm item deletion'
label=_('Confirm delete'),
help_text=_('Confirm item deletion')
)
class Meta:
@@ -59,14 +158,16 @@ class SetPasswordForm(HelperForm):
required=True,
initial='',
widget=forms.PasswordInput(attrs={'autocomplete': 'off'}),
help_text='Enter new password')
label=_('Enter password'),
help_text=_('Enter new password'))
confirm_password = forms.CharField(max_length=100,
min_length=8,
required=True,
initial='',
widget=forms.PasswordInput(attrs={'autocomplete': 'off'}),
help_text='Confirm new password')
label=_('Confirm password'),
help_text=_('Confirm new password'))
class Meta:
model = User
@@ -74,3 +175,66 @@ class SetPasswordForm(HelperForm):
'enter_password',
'confirm_password'
]
class ColorThemeSelectForm(forms.ModelForm):
""" Form for setting color theme """
name = forms.ChoiceField(choices=(), required=False)
class Meta:
model = ColorTheme
fields = [
'name'
]
def __init__(self, *args, **kwargs):
super(ColorThemeSelectForm, self).__init__(*args, **kwargs)
# Populate color themes choices
self.fields['name'].choices = ColorTheme.get_color_themes_choices()
self.helper = FormHelper()
# Form rendering
self.helper.form_show_labels = False
self.helper.layout = Layout(
Div(
Div(Field('name'),
css_class='col-sm-6',
style='width: 200px;'),
Div(StrictButton(_('Apply Theme'), css_class='btn btn-primary', type='submit'),
css_class='col-sm-6',
style='width: auto;'),
css_class='row',
),
)
class SettingCategorySelectForm(forms.ModelForm):
""" Form for setting category settings """
category = forms.ModelChoiceField(queryset=PartCategory.objects.all())
class Meta:
model = PartCategory
fields = [
'category'
]
def __init__(self, *args, **kwargs):
super(SettingCategorySelectForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
# Form rendering
self.helper.form_show_labels = False
self.helper.layout = Layout(
Div(
Div(Field('category'),
css_class='col-sm-6',
style='width: 70%;'),
Div(StrictButton(_('Select Category'), css_class='btn btn-primary', type='submit'),
css_class='col-sm-6',
style='width: 30%; padding-left: 0;'),
css_class='row',
),
)

View File

@@ -8,17 +8,46 @@ import json
import os.path
from PIL import Image
from decimal import Decimal
from decimal import Decimal, InvalidOperation
from wsgiref.util import FileWrapper
from django.http import StreamingHttpResponse
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError, FieldError
from django.utils.translation import ugettext_lazy as _
from .version import inventreeVersion, inventreeInstanceName
from django.contrib.auth.models import Permission
import InvenTree.version
from common.models import InvenTreeSetting
from .settings import MEDIA_URL, STATIC_URL
def getSetting(key, backup_value=None):
"""
Shortcut for reading a setting value from the database
"""
return InvenTreeSetting.get_setting(key, backup_value=backup_value)
def generateTestKey(test_name):
"""
Generate a test 'key' for a given test name.
This must not have illegal chars as it will be used for dict lookup in a template.
Tests must be named such that they will have unique keys.
"""
key = test_name.strip().lower()
key = key.replace(" ", "")
# Remove any characters that cannot be used to represent a variable
key = re.sub(r'[^a-zA-Z0-9]', '', key)
return key
def getMediaUrl(filename):
"""
Return the qualified access path for the given file,
@@ -73,7 +102,7 @@ def TestIfImageURL(url):
'.tif', '.tiff',
'.webp', '.gif',
]
def str2bool(text, test=True):
""" Test if a string 'looks' like a boolean value.
@@ -91,14 +120,27 @@ def str2bool(text, test=True):
return str(text).lower() in ['0', 'n', 'no', 'none', 'f', 'false', 'off', ]
def is_bool(text):
"""
Determine if a string value 'looks' like a boolean.
"""
if str2bool(text, True):
return True
elif str2bool(text, False):
return True
else:
return False
def isNull(text):
"""
Test if a string 'looks' like a null value.
This is useful for querying the API against a null key.
Args:
text: Input text
Returns:
True if the text looks like a null value
"""
@@ -115,11 +157,64 @@ def normalize(d):
d = Decimal(d)
d = d.normalize()
# Ref: https://docs.python.org/3/library/decimal.html
return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
def increment(n):
"""
Attempt to increment an integer (or a string that looks like an integer!)
e.g.
001 -> 002
2 -> 3
AB01 -> AB02
QQQ -> QQQ
"""
value = str(n).strip()
# Ignore empty strings
if not value:
return value
pattern = r"(.*?)(\d+)?$"
result = re.search(pattern, value)
# No match!
if result is None:
return value
groups = result.groups()
# If we cannot match the regex, then simply return the provided value
if not len(groups) == 2:
return value
prefix, number = groups
# No number extracted? Simply return the prefix (without incrementing!)
if not number:
return prefix
# Record the width of the number
width = len(number)
try:
number = int(number) + 1
number = str(number)
except ValueError:
pass
number = number.zfill(width)
return prefix + number
def decimal2string(d):
"""
Format a Decimal number as a string,
@@ -172,7 +267,7 @@ def WrapWithQuotes(text, quote='"'):
return text
def MakeBarcode(object_name, object_data):
def MakeBarcode(object_name, object_pk, object_data={}, **kwargs):
""" Generate a string for a barcode. Adds some global InvenTree parameters.
Args:
@@ -185,19 +280,41 @@ def MakeBarcode(object_name, object_data):
json string of the supplied data plus some other data
"""
data = {
'tool': 'InvenTree',
'version': inventreeVersion(),
'instance': inventreeInstanceName(),
object_name: object_data
}
url = kwargs.get('url', False)
brief = kwargs.get('brief', True)
data = {}
if url:
request = object_data.get('request', None)
item_url = object_data.get('item_url', None)
absolute_url = None
if request and item_url:
absolute_url = request.build_absolute_uri(item_url)
# Return URL (No JSON)
return absolute_url
if item_url:
# Return URL (No JSON)
return item_url
elif brief:
data[object_name] = object_pk
else:
data['tool'] = 'InvenTree'
data['version'] = InvenTree.version.inventreeVersion()
data['instance'] = InvenTree.version.inventreeInstanceName()
# Ensure PK is included
object_data['id'] = object_pk
data[object_name] = object_data
return json.dumps(data, sort_keys=True)
def GetExportFormats():
""" Return a list of allowable file formats for exporting data """
return [
'csv',
'tsv',
@@ -210,7 +327,7 @@ def GetExportFormats():
def DownloadFile(data, filename, content_type='application/text'):
""" Create a dynamic file for the user to download.
Args:
data: Raw file data (string or bytes)
filename: Filename for the file download
@@ -234,12 +351,14 @@ def DownloadFile(data, filename, content_type='application/text'):
return response
def ExtractSerialNumbers(serials, expected_quantity):
def extract_serial_numbers(serials, expected_quantity):
""" Attempt to extract serial numbers from an input string.
- Serial numbers must be integer values
- Serial numbers must be positive
- Serial numbers can be split by whitespace / newline / commma chars
- Serial numbers can be supplied as an inclusive range using hyphen char e.g. 10-20
- Serial numbers can be supplied as <start>+ for getting all expecteded numbers starting from <start>
- Serial numbers can be supplied as <start>+<length> for getting <length> numbers starting from <start>
Args:
expected_quantity: The number of (unique) serial numbers we expect
@@ -252,6 +371,13 @@ def ExtractSerialNumbers(serials, expected_quantity):
numbers = []
errors = []
# helpers
def number_add(n):
if n in numbers:
errors.append(_('Duplicate serial: {n}').format(n=n))
else:
numbers.append(n)
try:
expected_quantity = int(expected_quantity)
except ValueError:
@@ -278,29 +404,47 @@ def ExtractSerialNumbers(serials, expected_quantity):
if a < b:
for n in range(a, b + 1):
if n in numbers:
errors.append(_('Duplicate serial: {n}'.format(n=n)))
else:
numbers.append(n)
number_add(n)
else:
errors.append(_("Invalid group: {g}".format(g=group)))
errors.append(_("Invalid group: {g}").format(g=group))
except ValueError:
errors.append(_("Invalid group: {g}".format(g=group)))
errors.append(_("Invalid group: {g}").format(g=group))
continue
else:
errors.append(_("Invalid group: {g}".format(g=group)))
errors.append(_("Invalid group: {g}").format(g=group))
continue
# plus signals either
# 1: 'start+': expected number of serials, starting at start
# 2: 'start+number': number of serials, starting at start
elif '+' in group:
items = group.split('+')
# case 1, 2
if len(items) == 2:
start = int(items[0])
# case 2
if bool(items[1]):
end = start + int(items[1]) + 1
# case 1
else:
end = start + expected_quantity
for n in range(start, end):
number_add(n)
# no case
else:
errors.append(_("Invalid group: {g}").format(g=group))
continue
else:
try:
n = int(group)
if n in numbers:
errors.append(_("Duplicate serial: {n}".format(n=n)))
else:
numbers.append(n)
except ValueError:
errors.append(_("Invalid group: {g}".format(g=group)))
if group in numbers:
errors.append(_("Duplicate serial: {g}".format(g=group)))
else:
numbers.append(group)
if len(errors) > 0:
raise ValidationError(errors)
@@ -310,6 +454,171 @@ def ExtractSerialNumbers(serials, expected_quantity):
# The number of extracted serial numbers must match the expected quantity
if not expected_quantity == len(numbers):
raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})".format(s=len(numbers), q=expected_quantity))])
raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})").format(s=len(numbers), q=expected_quantity)])
return numbers
def validateFilterString(value, model=None):
"""
Validate that a provided filter string looks like a list of comma-separated key=value pairs
These should nominally match to a valid database filter based on the model being filtered.
e.g. "category=6, IPN=12"
e.g. "part__name=widget"
The ReportTemplate class uses the filter string to work out which items a given report applies to.
For example, an acceptance test report template might only apply to stock items with a given IPN,
so the string could be set to:
filters = "IPN = ACME0001"
Returns a map of key:value pairs
"""
# Empty results map
results = {}
value = str(value).strip()
if not value or len(value) == 0:
return results
groups = value.split(',')
for group in groups:
group = group.strip()
pair = group.split('=')
if not len(pair) == 2:
raise ValidationError(
"Invalid group: {g}".format(g=group)
)
k, v = pair
k = k.strip()
v = v.strip()
if not k or not v:
raise ValidationError(
"Invalid group: {g}".format(g=group)
)
results[k] = v
# If a model is provided, verify that the provided filters can be used against it
if model is not None:
try:
model.objects.filter(**results)
except FieldError as e:
raise ValidationError(
str(e),
)
return results
def addUserPermission(user, permission):
"""
Shortcut function for adding a certain permission to a user.
"""
perm = Permission.objects.get(codename=permission)
user.user_permissions.add(perm)
def addUserPermissions(user, permissions):
"""
Shortcut function for adding multiple permissions to a user.
"""
for permission in permissions:
addUserPermission(user, permission)
def getMigrationFileNames(app):
"""
Return a list of all migration filenames for provided app
"""
local_dir = os.path.dirname(os.path.abspath(__file__))
migration_dir = os.path.join(local_dir, '..', app, 'migrations')
files = os.listdir(migration_dir)
# Regex pattern for migration files
pattern = r"^[\d]+_.*\.py$"
migration_files = []
for f in files:
if re.match(pattern, f):
migration_files.append(f)
return migration_files
def getOldestMigrationFile(app, exclude_extension=True, ignore_initial=True):
"""
Return the filename associated with the oldest migration
"""
oldest_num = -1
oldest_file = None
for f in getMigrationFileNames(app):
if ignore_initial and f.startswith('0001_initial'):
continue
num = int(f.split('_')[0])
if oldest_file is None or num < oldest_num:
oldest_num = num
oldest_file = f
if exclude_extension:
oldest_file = oldest_file.replace('.py', '')
return oldest_file
def getNewestMigrationFile(app, exclude_extension=True):
"""
Return the filename associated with the newest migration
"""
newest_file = None
newest_num = -1
for f in getMigrationFileNames(app):
num = int(f.split('_')[0])
if newest_file is None or num > newest_num:
newest_num = num
newest_file = f
if exclude_extension:
newest_file = newest_file.replace('.py', '')
return newest_file
def clean_decimal(number):
""" Clean-up decimal value """
# Check if empty
if number is None or number == '':
return Decimal(0)
# Check if decimal type
try:
clean_number = Decimal(number)
except InvalidOperation:
clean_number = number
return clean_number.quantize(Decimal(1)) if clean_number == clean_number.to_integral() else clean_number.normalize()

View File

@@ -0,0 +1,61 @@
"""
Custom management command to prerender files
"""
from django.core.management.base import BaseCommand
from django.conf import settings
from django.template.loader import render_to_string
from django.utils.module_loading import import_string
from django.http.request import HttpRequest
from django.utils.translation import override as lang_over
import os
def render_file(file_name, source, target, locales, ctx):
""" renders a file into all provided locales """
for locale in locales:
target_file = os.path.join(target, locale + '.' + file_name)
with open(target_file, 'w') as localised_file:
with lang_over(locale):
renderd = render_to_string(os.path.join(source, file_name), ctx)
localised_file.write(renderd)
class Command(BaseCommand):
"""
django command to prerender files
"""
def handle(self, *args, **kwargs):
# static directories
LC_DIR = settings.LOCALE_PATHS[0]
SOURCE_DIR = settings.STATICFILES_I18_SRC
TARGET_DIR = settings.STATICFILES_I18_TRG
# ensure static directory exists
if not os.path.exists(TARGET_DIR):
os.makedirs(TARGET_DIR, exist_ok=True)
# collect locales
locales = {}
for locale in os.listdir(LC_DIR):
path = os.path.join(LC_DIR, locale)
if os.path.exists(path) and os.path.isdir(path):
locales[locale] = locale
# render!
request = HttpRequest()
ctx = {}
processors = tuple(import_string(path) for path in settings.STATFILES_I18_PROCESSORS)
for processor in processors:
ctx.update(processor(request))
for file in os.listdir(SOURCE_DIR, ):
path = os.path.join(SOURCE_DIR, file)
if os.path.exists(path) and os.path.isfile(path):
print(f"render {file}")
render_file(file, SOURCE_DIR, TARGET_DIR, locales, ctx)
else:
raise NotImplementedError('Using multi-level directories is not implemented at this point') # TODO multilevel dir if needed
print(f"rendered all files in {SOURCE_DIR}")

View File

@@ -0,0 +1,42 @@
"""
Custom management command, wait for the database to be ready!
"""
from django.core.management.base import BaseCommand
from django.db import connection
from django.db.utils import OperationalError, ImproperlyConfigured
import time
class Command(BaseCommand):
"""
django command to pause execution until the database is ready
"""
def handle(self, *args, **kwargs):
self.stdout.write("Waiting for database...")
connected = False
while not connected:
time.sleep(5)
try:
connection.ensure_connection()
connected = True
except OperationalError as e:
self.stdout.write(f"Could not connect to database: {e}")
except ImproperlyConfigured as e:
self.stdout.write(f"Improperly configured: {e}")
else:
if not connection.is_usable():
self.stdout.write("Database configuration is not usable")
if connected:
self.stdout.write("Database connection sucessful!")

View File

@@ -1,13 +1,14 @@
from django.shortcuts import HttpResponseRedirect
from django.urls import reverse_lazy
from django.db import connection
from django.shortcuts import redirect
import logging
import time
import operator
from rest_framework.authtoken.models import Token
logger = logging.getLogger(__name__)
logger = logging.getLogger("inventree")
class AuthRequiredMiddleware(object):
@@ -46,7 +47,16 @@ class AuthRequiredMiddleware(object):
authorized = False
if 'Authorization' in request.headers.keys():
# Allow static files to be accessed without auth
# Important for e.g. login page
if request.path_info.startswith('/static/'):
authorized = True
# Unauthorized users can access the login page
elif request.path_info.startswith('/accounts/'):
authorized = True
elif 'Authorization' in request.headers.keys():
auth = request.headers['Authorization'].strip()
if auth.startswith('Token') and len(auth.split()) == 2:
@@ -55,7 +65,7 @@ class AuthRequiredMiddleware(object):
# Does the provided token match a valid user?
if Token.objects.filter(key=token).exists():
allowed = ['/media/', '/static/']
allowed = ['/api/', '/media/']
# Only allow token-auth for /media/ or /static/ dirs!
if any([request.path_info.startswith(a) for a in allowed]):
@@ -63,9 +73,25 @@ class AuthRequiredMiddleware(object):
# No authorization was found for the request
if not authorized:
if not request.path_info == reverse_lazy('login') and not request.path_info.startswith('/api/'):
# A logout request will redirect the user to the login screen
if request.path_info == reverse_lazy('logout'):
return HttpResponseRedirect(reverse_lazy('login'))
path = request.path_info
# List of URL endpoints we *do not* want to redirect to
urls = [
reverse_lazy('login'),
reverse_lazy('logout'),
reverse_lazy('admin:login'),
reverse_lazy('admin:logout'),
]
if path not in urls and not path.startswith('/api/'):
# Save the 'next' parameter to pass through to the login view
return redirect('%s?next=%s' % (reverse_lazy('login'), request.path))
# Code to be executed for each request/response after
# the view is called.
@@ -82,6 +108,8 @@ class QueryCountMiddleware(object):
To enable this middleware, set 'log_queries: True' in the local InvenTree config file.
Reference: https://www.dabapps.com/blog/logging-sql-queries-django-13/
Note: 2020-08-15 - This is no longer used, instead we now rely on the django-debug-toolbar addon
"""
def __init__(self, get_response):

View File

@@ -7,6 +7,7 @@ from __future__ import unicode_literals
import os
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _
@@ -41,6 +42,8 @@ class InvenTreeAttachment(models.Model):
Attributes:
attachment: File
comment: String descriptor for the attachment
user: User associated with file upload
upload_date: Date the file was uploaded
"""
def getSubdir(self):
"""
@@ -50,10 +53,23 @@ class InvenTreeAttachment(models.Model):
return "attachments"
attachment = models.FileField(upload_to=rename_attachment,
def __str__(self):
return os.path.basename(self.attachment.name)
attachment = models.FileField(upload_to=rename_attachment, verbose_name=_('Attachment'),
help_text=_('Select file to attach'))
comment = models.CharField(max_length=100, help_text=_('File comment'))
comment = models.CharField(blank=True, max_length=100, verbose_name=_('Comment'), help_text=_('File comment'))
user = models.ForeignKey(
User,
on_delete=models.SET_NULL,
blank=True, null=True,
verbose_name=_('User'),
help_text=_('User'),
)
upload_date = models.DateField(auto_now_add=True, null=True, blank=True, verbose_name=_('upload date'))
@property
def basename(self):
@@ -87,12 +103,16 @@ class InvenTreeTree(MPTTModel):
name = models.CharField(
blank=False,
max_length=100,
validators=[validate_tree_name]
validators=[validate_tree_name],
verbose_name=_("Name"),
help_text=_("Name"),
)
description = models.CharField(
blank=False,
max_length=250
blank=True,
max_length=250,
verbose_name=_("Description"),
help_text=_("Description (optional)")
)
# When a category is deleted, graft the children onto its parent
@@ -100,6 +120,7 @@ class InvenTreeTree(MPTTModel):
on_delete=models.DO_NOTHING,
blank=True,
null=True,
verbose_name=_("parent"),
related_name='children')
@property
@@ -108,7 +129,7 @@ class InvenTreeTree(MPTTModel):
Here an 'item' is considered to be the 'leaf' at the end of each branch,
and the exact nature here will depend on the class implementation.
The default implementation returns zero
"""
return 0

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from rest_framework import permissions
import users.models
class RolePermission(permissions.BasePermission):
"""
Role mixin for API endpoints, allowing us to specify the user "role"
which is required for certain operations.
Each endpoint can have one or more of the following actions:
- GET
- POST
- PUT
- PATCH
- DELETE
Specify the required "role" using the role_required attribute.
e.g.
role_required = "part"
The RoleMixin class will then determine if the user has the required permission
to perform the specified action.
For example, a DELETE action will be rejected unless the user has the "part.remove" permission
"""
def has_permission(self, request, view):
"""
Determine if the current user has the specified permissions
"""
user = request.user
# Superuser can do it all
if user.is_superuser:
return True
# Map the request method to a permission type
rolemap = {
'GET': 'view',
'OPTIONS': 'view',
'POST': 'add',
'PUT': 'change',
'PATCH': 'change',
'DELETE': 'delete',
}
permission = rolemap[request.method]
try:
# Extract the model name associated with this request
model = view.serializer_class.Meta.model
app_label = model._meta.app_label
model_name = model._meta.model_name
table = f"{app_label}_{model_name}"
except AttributeError:
# We will assume that if the serializer class does *not* have a Meta,
# then we don't need a permission
return True
result = users.models.RuleSet.check_table_permission(user, table, permission)
return result

View File

@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
import inspect
import importlib
import pkgutil
def iter_namespace(pkg):
return pkgutil.iter_modules(pkg.__path__, pkg.__name__ + ".")
def get_modules(pkg):
# Return all modules in a given package
return [importlib.import_module(name) for finder, name, ispkg in iter_namespace(pkg)]
def get_classes(module):
# Return all classes in a given module
return inspect.getmembers(module, inspect.isclass)
def get_plugins(pkg, baseclass):
"""
Return a list of all modules under a given package.
- Modules must be a subclass of the provided 'baseclass'
- Modules must have a non-empty PLUGIN_NAME parameter
"""
plugins = []
modules = get_modules(pkg)
# Iterate through each module in the package
for mod in modules:
# Iterate through each class in the module
for item in get_classes(mod):
plugin = item[1]
if issubclass(plugin, baseclass) and plugin.PLUGIN_NAME:
plugins.append(plugin)
return plugins

View File

@@ -0,0 +1,46 @@
import sys
def isInTestMode():
"""
Returns True if the database is in testing mode
"""
if 'test' in sys.argv:
return True
return False
def canAppAccessDatabase():
"""
Returns True if the apps.py file can access database records.
There are some circumstances where we don't want the ready function in apps.py
to touch the database
"""
# If any of the following management commands are being executed,
# prevent custom "on load" code from running!
excluded_commands = [
'flush',
'loaddata',
'dumpdata',
'makemirations',
'migrate',
'check',
'mediarestore',
'shell',
'createsuperuser',
'wait_for_db',
'prerender',
'collectstatic',
'makemessages',
'compilemessages',
]
for cmd in excluded_commands:
if cmd in sys.argv:
return False
return True

View File

@@ -8,6 +8,9 @@ from __future__ import unicode_literals
from rest_framework import serializers
import os
from django.conf import settings
from django.contrib.auth.models import User
@@ -41,7 +44,7 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
In addition to running validators on the serializer fields,
this class ensures that the underlying model is also validated.
"""
# Run any native validation checks first (may throw an ValidationError)
data = super(serializers.ModelSerializer, self).validate(data)
@@ -50,3 +53,32 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
instance.clean()
return data
class InvenTreeAttachmentSerializerField(serializers.FileField):
"""
Override the DRF native FileField serializer,
to remove the leading server path.
For example, the FileField might supply something like:
http://127.0.0.1:8000/media/foo/bar.jpg
Whereas we wish to return:
/media/foo/bar.jpg
Why? You can't handle the why!
Actually, if the server process is serving the data at 127.0.0.1,
but a proxy service (e.g. nginx) is then providing DNS lookup to the outside world,
then an attachment which prefixes the "address" of the internal server
will not be accessible from the outside world.
"""
def to_representation(self, value):
if not value:
return None
return os.path.join(str(settings.MEDIA_URL), str(value))

View File

@@ -11,42 +11,161 @@ database setup in this file.
"""
import sys
import os
import logging
import tempfile
import yaml
import os
import random
import string
import shutil
import sys
from datetime import datetime
import moneyed
import yaml
from django.utils.translation import gettext_lazy as _
def eprint(*args, **kwargs):
""" Print a warning message to stderr """
print(*args, file=sys.stderr, **kwargs)
def _is_true(x):
# Shortcut function to determine if a value "looks" like a boolean
return str(x).lower() in ['1', 'y', 'yes', 't', 'true']
def get_setting(environment_var, backup_val, default_value=None):
"""
Helper function for retrieving a configuration setting value
- First preference is to look for the environment variable
- Second preference is to look for the value of the settings file
- Third preference is the default value
"""
val = os.getenv(environment_var)
if val is not None:
return val
if backup_val is not None:
return backup_val
return default_value
# Determine if we are running in "test" mode e.g. "manage.py test"
TESTING = 'test' in sys.argv
# New requirement for django 3.2+
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
cfg_filename = os.path.join(BASE_DIR, 'config.yaml')
# Specify where the "config file" is located.
# By default, this is 'config.yaml'
cfg_filename = os.getenv('INVENTREE_CONFIG_FILE')
if cfg_filename:
cfg_filename = cfg_filename.strip()
cfg_filename = os.path.abspath(cfg_filename)
else:
# Config file is *not* specified - use the default
cfg_filename = os.path.join(BASE_DIR, 'config.yaml')
if not os.path.exists(cfg_filename):
CONFIG = {}
eprint("Warning: config.yaml not found - using default settings")
else:
with open(cfg_filename, 'r') as cfg:
CONFIG = yaml.safe_load(cfg)
print("InvenTree configuration file 'config.yaml' not found - creating default file")
# Read the autogenerated key-file
key_file = open(os.path.join(BASE_DIR, 'secret_key.txt'), 'r')
cfg_template = os.path.join(BASE_DIR, "config_template.yaml")
shutil.copyfile(cfg_template, cfg_filename)
print(f"Created config file {cfg_filename}")
SECRET_KEY = key_file.read().strip()
with open(cfg_filename, 'r') as cfg:
CONFIG = yaml.safe_load(cfg)
# Default action is to run the system in Debug mode
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = CONFIG.get('debug', True)
DEBUG = _is_true(get_setting(
'INVENTREE_DEBUG',
CONFIG.get('debug', True)
))
DOCKER = _is_true(get_setting(
'INVENTREE_DOCKER',
False
))
# Configure logging settings
log_level = get_setting(
'INVENTREE_LOG_LEVEL',
CONFIG.get('log_level', 'DEBUG')
)
logging.basicConfig(
level=log_level,
format="%(asctime)s %(levelname)s %(message)s",
)
if log_level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
log_level = 'WARNING'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': log_level,
},
}
# Get a logger instance for this setup file
logger = logging.getLogger("inventree")
"""
Specify a secret key to be used by django.
Following options are tested, in descending order of preference:
A) Check for environment variable INVENTREE_SECRET_KEY => Use raw key data
B) Check for environment variable INVENTREE_SECRET_KEY_FILE => Load key data from file
C) Look for default key file "secret_key.txt"
d) Create "secret_key.txt" if it does not exist
"""
if os.getenv("INVENTREE_SECRET_KEY"):
# Secret key passed in directly
SECRET_KEY = os.getenv("INVENTREE_SECRET_KEY").strip()
logger.info("SECRET_KEY loaded by INVENTREE_SECRET_KEY")
else:
# Secret key passed in by file location
key_file = os.getenv("INVENTREE_SECRET_KEY_FILE")
if key_file:
key_file = os.path.abspath(key_file)
else:
# default secret key location
key_file = os.path.join(BASE_DIR, "secret_key.txt")
key_file = os.path.abspath(key_file)
if not os.path.exists(key_file):
logger.info(f"Generating random key file at '{key_file}'")
# Create a random key file
with open(key_file, 'w') as f:
options = string.digits + string.ascii_letters + string.punctuation
key = ''.join([random.choice(options) for i in range(100)])
f.write(key)
logger.info(f"Loading SECRET_KEY from '{key_file}'")
try:
SECRET_KEY = open(key_file, "r").read().strip()
except Exception:
logger.exception(f"Couldn't load keyfile {key_file}")
sys.exit(-1)
# List of allowed hosts (default = allow all)
ALLOWED_HOSTS = CONFIG.get('allowed_hosts', ['*'])
@@ -65,12 +184,51 @@ if cors_opt:
if not CORS_ORIGIN_ALLOW_ALL:
CORS_ORIGIN_WHITELIST = cors_opt.get('whitelist', [])
if DEBUG:
# will output to your console
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s',
# Web URL endpoint for served static files
STATIC_URL = '/static/'
# The filesystem location for served static files
STATIC_ROOT = os.path.abspath(
get_setting(
'INVENTREE_STATIC_ROOT',
CONFIG.get('static_root', '/home/inventree/static')
)
)
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'InvenTree', 'static'),
]
# Translated Template settings
STATICFILES_I18_PREFIX = 'i18n'
STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js')
STATICFILES_I18_TRG = STATICFILES_DIRS[0] + '_' + STATICFILES_I18_PREFIX
STATICFILES_DIRS.append(STATICFILES_I18_TRG)
STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX)
STATFILES_I18_PROCESSORS = [
'InvenTree.context.status_codes',
]
# Color Themes Directory
STATIC_COLOR_THEMES_DIR = os.path.join(STATIC_ROOT, 'css', 'color-themes')
# Web URL endpoint for served media files
MEDIA_URL = '/media/'
# The filesystem location for served static files
MEDIA_ROOT = os.path.abspath(
get_setting(
'INVENTREE_MEDIA_ROOT',
CONFIG.get('media_root', '/home/inventree/data/media')
)
)
if DEBUG:
logger.info("InvenTree running in DEBUG mode")
logger.info(f"MEDIA_ROOT: '{MEDIA_ROOT}'")
logger.info(f"STATIC_ROOT: '{STATIC_ROOT}'")
# Application definition
@@ -85,40 +243,37 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
# InvenTree apps
'common.apps.CommonConfig',
'part.apps.PartConfig',
'stock.apps.StockConfig',
'company.apps.CompanyConfig',
'build.apps.BuildConfig',
'common.apps.CommonConfig',
'company.apps.CompanyConfig',
'label.apps.LabelConfig',
'order.apps.OrderConfig',
'part.apps.PartConfig',
'report.apps.ReportConfig',
'stock.apps.StockConfig',
'users.apps.UsersConfig',
'InvenTree.apps.InvenTreeConfig', # InvenTree app runs last
# Third part add-ons
'django_filters', # Extended filter functionality
'dbbackup', # Database backup / restore
'rest_framework', # DRF (Django Rest Framework)
'rest_framework.authtoken', # Token authentication for API
'corsheaders', # Cross-origin Resource Sharing for DRF
'crispy_forms', # Improved form rendering
'import_export', # Import / export tables to file
'django_cleanup', # Automatically delete orphaned MEDIA files
'qr_code', # Generate QR codes
'mptt', # Modified Preorder Tree Traversal
'markdownx', # Markdown editing
'markdownify', # Markdown template rendering
'django_filters', # Extended filter functionality
'rest_framework', # DRF (Django Rest Framework)
'rest_framework.authtoken', # Token authentication for API
'corsheaders', # Cross-origin Resource Sharing for DRF
'crispy_forms', # Improved form rendering
'import_export', # Import / export tables to file
'django_cleanup.apps.CleanupConfig', # Automatically delete orphaned MEDIA files
'mptt', # Modified Preorder Tree Traversal
'markdownx', # Markdown editing
'markdownify', # Markdown template rendering
'django_admin_shell', # Python shell for the admin interface
'djmoney', # django-money integration
'djmoney.contrib.exchange', # django-money exchange rates
'error_report', # Error reporting in the admin interface
'django_q',
'formtools', # Form wizard tools
]
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
}
MIDDLEWARE = [
MIDDLEWARE = CONFIG.get('middleware', [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
@@ -128,25 +283,44 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'InvenTree.middleware.AuthRequiredMiddleware',
]
'InvenTree.middleware.AuthRequiredMiddleware'
])
if CONFIG.get('log_queries', False):
MIDDLEWARE.append('InvenTree.middleware.QueryCountMiddleware')
# Error reporting middleware
MIDDLEWARE.append('error_report.middleware.ExceptionProcessor')
AUTHENTICATION_BACKENDS = CONFIG.get('authentication_backends', [
'django.contrib.auth.backends.ModelBackend'
])
# If the debug toolbar is enabled, add the modules
if DEBUG and CONFIG.get('debug_toolbar', False):
logger.info("Running with DEBUG_TOOLBAR enabled")
INSTALLED_APPS.append('debug_toolbar')
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
ROOT_URLCONF = 'InvenTree.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
# Allow templates in the reporting directory to be accessed
os.path.join(MEDIA_ROOT, 'report'),
os.path.join(MEDIA_ROOT, 'label'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.i18n',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'InvenTree.context.health_status',
'InvenTree.context.status_codes',
'InvenTree.context.user_roles',
],
},
},
@@ -160,11 +334,29 @@ REST_FRAMEWORK = {
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
'rest_framework.permissions.DjangoModelPermissions',
'InvenTree.permissions.RolePermission',
),
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
WSGI_APPLICATION = 'InvenTree.wsgi.application'
# django-q configuration
Q_CLUSTER = {
'name': 'InvenTree',
'workers': 4,
'timeout': 90,
'retry': 120,
'queue_limit': 50,
'bulk': 10,
'orm': 'default',
'sync': False,
}
# Markdownx configuration
# Ref: https://neutronx.github.io/django-markdownx/customization/
MARKDOWNX_MEDIA_PATH = datetime.now().strftime('markdownx/%Y/%m/%d')
@@ -194,45 +386,86 @@ MARKDOWNIFY_WHITELIST_ATTRS = [
'alt',
]
MARKDOWNIFY_BLEACH = True
MARKDOWNIFY_BLEACH = False
DATABASES = {}
"""
When running unit tests, enforce usage of sqlite3 database,
so that the tests can be run in RAM without any setup requirements
"""
if 'test' in sys.argv:
eprint('Running tests - Using sqlite3 memory database')
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_db.sqlite3'
}
Configure the database backend based on the user-specified values.
# Database backend selection
else:
if 'database' in CONFIG:
DATABASES['default'] = CONFIG['database']
else:
eprint("Warning: Database backend not specified - using default (sqlite)")
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'inventree_db.sqlite3'),
}
- Primarily this configuration happens in the config.yaml file
- However there may be reason to configure the DB via environmental variables
- The following code lets the user "mix and match" database configuration
"""
logger.info("Configuring database backend:")
# Extract database configuration from the config.yaml file
db_config = CONFIG.get('database', {})
if not db_config:
db_config = {}
# Environment variables take preference over config file!
db_keys = ['ENGINE', 'NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']
for key in db_keys:
# First, check the environment variables
env_key = f"INVENTREE_DB_{key}"
env_var = os.environ.get(env_key, None)
if env_var:
# Override configuration value
db_config[key] = env_var
# Check that required database configuration options are specified
reqiured_keys = ['ENGINE', 'NAME']
for key in reqiured_keys:
if key not in db_config:
error_msg = f'Missing required database configuration value {key}'
logger.error(error_msg)
print('Error: ' + error_msg)
sys.exit(-1)
"""
Special considerations for the database 'ENGINE' setting.
It can be specified in config.yaml (or envvar) as either (for example):
- sqlite3
- django.db.backends.sqlite3
- django.db.backends.postgresql
"""
db_engine = db_config['ENGINE'].lower()
# Correct common misspelling
if db_engine == 'sqlite':
db_engine = 'sqlite3'
if db_engine in ['sqlite3', 'postgresql', 'mysql']:
# Prepend the required python module string
db_engine = f'django.db.backends.{db_engine}'
db_config['ENGINE'] = db_engine
db_name = db_config['NAME']
db_host = db_config.get('HOST', "''")
print("InvenTree Database Configuration")
print("================================")
print(f"ENGINE: {db_engine}")
print(f"NAME: {db_name}")
print(f"HOST: {db_host}")
DATABASES['default'] = db_config
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
},
'qr-code': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'qr-code-cache',
'TIMEOUT': 3600
}
}
QR_CODE_CACHE_ALIAS = 'qr-code'
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
@@ -257,72 +490,124 @@ AUTH_PASSWORD_VALIDATORS = [
EXTRA_URL_SCHEMES = CONFIG.get('extra_url_schemes', [])
if not type(EXTRA_URL_SCHEMES) in [list]:
eprint("Warning: extra_url_schemes not correctly formatted")
logger.warning("extra_url_schemes not correctly formatted")
EXTRA_URL_SCHEMES = []
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
# https://docs.djangoproject.com/en/dev/topics/i18n/
LANGUAGE_CODE = CONFIG.get('language', 'en-us')
# If a new language translation is supported, it must be added here
LANGUAGES = [
('en', _('English')),
('de', _('German')),
('fr', _('French')),
('pk', _('Polish')),
('de', _('German')),
('pl', _('Polish')),
('tr', _('Turkish')),
]
# Currencies available for use
CURRENCIES = CONFIG.get(
'currencies',
[
'AUD', 'CAD', 'EUR', 'GBP', 'JPY', 'NZD', 'USD',
],
)
# Check that each provided currency is supported
for currency in CURRENCIES:
if currency not in moneyed.CURRENCIES:
print(f"Currency code '{currency}' is not supported")
sys.exit(1)
BASE_CURRENCY = get_setting(
'INVENTREE_BASE_CURRENCY',
CONFIG.get('base_currency', 'USD')
)
# Custom currency exchange backend
EXCHANGE_BACKEND = 'InvenTree.exchange.InvenTreeExchange'
# Extract email settings from the config file
email_config = CONFIG.get('email', {})
EMAIL_BACKEND = get_setting(
'INVENTREE_EMAIL_BACKEND',
email_config.get('backend', 'django.core.mail.backends.smtp.EmailBackend')
)
# Email backend settings
EMAIL_HOST = get_setting(
'INVENTREE_EMAIL_HOST',
email_config.get('host', '')
)
EMAIL_PORT = get_setting(
'INVENTREE_EMAIL_PORT',
email_config.get('port', 25)
)
EMAIL_HOST_USER = get_setting(
'INVENTREE_EMAIL_USERNAME',
email_config.get('username', ''),
)
EMAIL_HOST_PASSWORD = get_setting(
'INVENTREE_EMAIL_PASSWORD',
email_config.get('password', ''),
)
DEFAULT_FROM_EMAIL = get_setting(
'INVENTREE_EMAIL_SENDER',
email_config.get('sender', ''),
)
EMAIL_SUBJECT_PREFIX = '[InvenTree] '
EMAIL_USE_LOCALTIME = False
EMAIL_USE_TLS = get_setting(
'INVENTREE_EMAIL_TLS',
email_config.get('tls', False),
)
EMAIL_USE_SSL = get_setting(
'INVENTREE_EMAIL_SSL',
email_config.get('ssl', False),
)
EMAIL_TIMEOUT = 60
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale/'),
)
TIME_ZONE = 'UTC'
TIME_ZONE = get_setting(
'INVENTREE_TIMEZONE',
CONFIG.get('timezone', 'UTC')
)
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Do not use native timezone support in "test" mode
# It generates a *lot* of cruft in the logs
if not TESTING:
USE_TZ = True
DATE_INPUT_FORMATS = [
"%Y-%m-%d",
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
# Web URL endpoint for served static files
STATIC_URL = '/static/'
# The filesystem location for served static files
STATIC_ROOT = os.path.abspath(CONFIG.get('static_root', os.path.join(BASE_DIR, 'static')))
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'InvenTree', 'static'),
]
# Web URL endpoint for served media files
MEDIA_URL = '/media/'
# The filesystem location for served static files
MEDIA_ROOT = os.path.abspath(CONFIG.get('media_root', os.path.join(BASE_DIR, 'media')))
if DEBUG:
print("InvenTree running in DEBUG mode")
print("MEDIA_ROOT:", MEDIA_ROOT)
print("STATIC_ROOT:", STATIC_ROOT)
# crispy forms use the bootstrap templates
CRISPY_TEMPLATE_PACK = 'bootstrap'
CRISPY_TEMPLATE_PACK = 'bootstrap3'
# Use database transactions when importing / exporting data
IMPORT_EXPORT_USE_TRANSACTIONS = True
# Settings for dbbsettings app
DBBACKUP_STORAGE = 'django.core.files.storage.FileSystemStorage'
DBBACKUP_STORAGE_OPTIONS = {
'location': CONFIG.get('backup_dir', tempfile.gettempdir()),
}
# Internal IP addresses allowed to see the debug toolbar
INTERNAL_IPS = [
'127.0.0.1',
]

View File

@@ -0,0 +1,170 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update: zhixin wen <wenzhixin2010@gmail.com>
*/
!($ => {
const diacriticsMap = {}
const defaultAccentsDiacritics = [
{base: 'A', letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
{base: 'AA',letters: '\uA732'},
{base: 'AE',letters: '\u00C6\u01FC\u01E2'},
{base: 'AO',letters: '\uA734'},
{base: 'AU',letters: '\uA736'},
{base: 'AV',letters: '\uA738\uA73A'},
{base: 'AY',letters: '\uA73C'},
{base: 'B', letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
{base: 'C', letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
{base: 'D', letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
{base: 'DZ',letters: '\u01F1\u01C4'},
{base: 'Dz',letters: '\u01F2\u01C5'},
{base: 'E', letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
{base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
{base: 'G', letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
{base: 'H', letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
{base: 'I', letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
{base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248'},
{base: 'K', letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
{base: 'L', letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
{base: 'LJ',letters: '\u01C7'},
{base: 'Lj',letters: '\u01C8'},
{base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
{base: 'N', letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
{base: 'NJ',letters: '\u01CA'},
{base: 'Nj',letters: '\u01CB'},
{base: 'O', letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
{base: 'OI',letters: '\u01A2'},
{base: 'OO',letters: '\uA74E'},
{base: 'OU',letters: '\u0222'},
{base: 'OE',letters: '\u008C\u0152'},
{base: 'oe',letters: '\u009C\u0153'},
{base: 'P', letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
{base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A'},
{base: 'R', letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
{base: 'S', letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
{base: 'T', letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
{base: 'TZ',letters: '\uA728'},
{base: 'U', letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
{base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
{base: 'VY',letters: '\uA760'},
{base: 'W', letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
{base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C'},
{base: 'Y', letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
{base: 'Z', letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
{base: 'a', letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
{base: 'aa',letters: '\uA733'},
{base: 'ae',letters: '\u00E6\u01FD\u01E3'},
{base: 'ao',letters: '\uA735'},
{base: 'au',letters: '\uA737'},
{base: 'av',letters: '\uA739\uA73B'},
{base: 'ay',letters: '\uA73D'},
{base: 'b', letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
{base: 'c', letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
{base: 'd', letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
{base: 'dz',letters: '\u01F3\u01C6'},
{base: 'e', letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
{base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
{base: 'g', letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
{base: 'h', letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
{base: 'hv',letters: '\u0195'},
{base: 'i', letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
{base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
{base: 'k', letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
{base: 'l', letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
{base: 'lj',letters: '\u01C9'},
{base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
{base: 'n', letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
{base: 'nj',letters: '\u01CC'},
{base: 'o', letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
{base: 'oi',letters: '\u01A3'},
{base: 'ou',letters: '\u0223'},
{base: 'oo',letters: '\uA74F'},
{base: 'p',letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
{base: 'q',letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759'},
{base: 'r',letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
{base: 's',letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
{base: 't',letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
{base: 'tz',letters: '\uA729'},
{base: 'u',letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
{base: 'v',letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
{base: 'vy',letters: '\uA761'},
{base: 'w',letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
{base: 'x',letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D'},
{base: 'y',letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
{base: 'z',letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
]
const initNeutraliser = () => {
for (const diacritic of defaultAccentsDiacritics) {
const letters = diacritic.letters
for (let i = 0; i < letters.length; i++) {
diacriticsMap[letters[i]] = diacritic.base
}
}
}
/* eslint-disable no-control-regex */
const removeDiacritics = str => str.replace(/[^\u0000-\u007E]/g, a => diacriticsMap[a] || a)
$.extend($.fn.bootstrapTable.defaults, {
searchAccentNeutralise: false
})
$.BootstrapTable = class extends $.BootstrapTable {
init () {
if (this.options.searchAccentNeutralise) {
initNeutraliser()
}
super.init()
}
initSearch () {
if (this.options.sidePagination !== 'server') {
let s = this.searchText && this.searchText.toLowerCase()
const f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns
// Check filter
this.data = f ? this.options.data.filter((item, i) => {
for (const key in f) {
if (item[key] !== f[key]) {
return false
}
}
return true
}) : this.options.data
this.data = s ? this.options.data.filter((item, i) => {
for (let [key, value] of Object.entries(item)) {
key = $.isNumeric(key) ? parseInt(key, 10) : key
const column = this.columns[this.fieldsColumnsIndex[key]]
const j = this.header.fields.indexOf(key)
if (column && column.searchFormatter) {
value = $.fn.bootstrapTable.utils.calculateObjectValue(column,
this.header.formatters[j], [value, item, i], value)
}
const index = this.header.fields.indexOf(key)
if (index !== -1 && this.header.searchables[index] && typeof value === 'string') {
if (this.options.searchAccentNeutralise) {
value = removeDiacritics(value)
s = removeDiacritics(s)
}
if (this.options.strictSearch) {
if ((`${value}`).toLowerCase() === s) {
return true
}
} else {
if ((`${value}`).toLowerCase().includes(s)) {
return true
}
}
}
}
return false
}) : this.data
}
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Accent Neutralise",
"version": "1.0.0",
"description": "Plugin to neutralise the words.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/accent-neutralise",
"example": "#",
"plugins": [{
"name": "bootstrap-table-accent-neutralise",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/accent-neutralise"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,116 @@
/**
* @author: general
* @website: note.generals.space
* @email: generals.space@gmail.com
* @github: https://github.com/generals-space/bootstrap-table-addrbar
* @update: zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
/*
* function: 获取浏览器地址栏中的指定参数.
* key: 参数名
* url: 默认为当前地址栏
*/
function _GET (key, url = window.location.search) {
/*
* 注意这里正则表达式的书写方法
* (^|&)key匹配: 直接以key开始或以&key开始的字符串
* 同理(&|$)表示以&结束或是直接结束的字符串
* ...当然, 我并不知道这种用法.
*/
const reg = new RegExp(`(^|&)${key}=([^&]*)(&|$)`)
const result = url.substr(1).match(reg)
if (result) {
return decodeURIComponent(result[2])
}
return null
}
/*
* function: 根据给定参数生成url地址
* var dic = {name: 'genreal', age: 24}
* var url = 'https://www.baidu.com?age=22';
* _buildUrl(dic, url);
* 将得到"https://www.baidu.com?age=24&name=genreal"
* 哦, 忽略先后顺序吧...
*
* 补充: 可以参考浏览器URLSearchParams对象, 更加方便和强大.
* 考虑到兼容性, 暂时不使用这个工具.
*/
function _buildUrl (dict, url = window.location.search) {
for (const [key, val] of Object.entries(dict)) {
// 搜索name=general这种形式的字符串(&是分隔符)
const pattern = `${key}=([^&]*)`
const targetStr = `${key}=${val}`
/*
* 如果目标url中包含了key键, 我们需要将它替换成我们自己的val
* 不然就直接添加好了.
*/
if (url.match(pattern)) {
const tmp = new RegExp(`(${key}=)([^&]*)`, 'gi')
url = url.replace(tmp, targetStr)
} else {
const seperator = url.match('[?]') ? '&' : '?'
url = url + seperator + targetStr
}
}
if (location.hash) {
url += location.hash
}
return url
}
$.BootstrapTable = class extends $.BootstrapTable {
init () {
// 拥有addrbar选项并且其值为true的才会继续执行
if (this.options.addrbar) {
// 标志位, 初始加载后关闭
this.addrbarInit = true
const _prefix = this.options.addrPrefix || ''
// 优先级排序: 用户指定值最优先, 未指定时从地址栏获取, 未获取到时采用默认值
this.options.pageSize = this.options.pageSize || (
_GET(`${_prefix}limit`) ? parseInt(_GET(`${_prefix}limit`)) : $.BootstrapTable.DEFAULTS.pageSize
)
this.options.pageNumber = this.options.pageNumber || (
_GET(`${_prefix}page`) ? parseInt(_GET(`${_prefix}page`)) : $.BootstrapTable.DEFAULTS.pageNumber
)
this.options.sortOrder = this.options.sortOrder || (
_GET(`${_prefix}order`) ? _GET(`${_prefix}order`) : $.BootstrapTable.DEFAULTS.sortOrder
)
this.options.sortName = this.options.sortName || (
_GET(`${_prefix}sort`) ? _GET(`${_prefix}sort`) : 'id'
)
this.options.searchText = this.options.searchText || (
_GET(`${_prefix}search`) ? _GET(`${_prefix}search`) : $.BootstrapTable.DEFAULTS.searchText
)
const _onLoadSuccess = this.options.onLoadSuccess
this.options.onLoadSuccess = data => {
if (this.addrbarInit) {
this.addrbarInit = false
} else {
const params = {}
params[`${_prefix}page`] = this.options.pageNumber,
params[`${_prefix}limit`] = this.options.pageSize,
params[`${_prefix}order`] = this.options.sortOrder,
params[`${_prefix}sort`] = this.options.sortName,
params[`${_prefix}search`] = this.options.searchText
// h5提供的修改浏览器地址栏的方法
window.history.pushState({}, '', _buildUrl(params))
}
if (_onLoadSuccess) {
_onLoadSuccess.call(this, data)
}
}
}
super.init()
}
}
})(jQuery)

View File

@@ -0,0 +1,78 @@
/**
* @author: Alec Fenichel
* @webSite: https://fenichelar.com
* @update: zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
autoRefresh: false,
autoRefreshInterval: 60,
autoRefreshSilent: true,
autoRefreshStatus: true,
autoRefreshFunction: null
})
$.extend($.fn.bootstrapTable.defaults.icons, {
autoRefresh: Utils.bootstrapVersion === 4 ? 'fa-clock' : 'glyphicon-time icon-time'
})
$.extend($.fn.bootstrapTable.locales, {
formatAutoRefresh () {
return 'Auto Refresh'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.BootstrapTable = class extends $.BootstrapTable {
init (...args) {
super.init(...args)
if (this.options.autoRefresh && this.options.autoRefreshStatus) {
this.options.autoRefreshFunction = setInterval(() => {
this.refresh({silent: this.options.autoRefreshSilent})
}, this.options.autoRefreshInterval * 1000)
}
}
initToolbar (...args) {
super.initToolbar(...args)
if (this.options.autoRefresh) {
const $btnGroup = this.$toolbar.find('>.btn-group')
let $btnAutoRefresh = $btnGroup.find('.auto-refresh')
if (!$btnAutoRefresh.length) {
$btnAutoRefresh = $(`
<button class="auto-refresh btn${Utils.sprintf(' btn-%s', this.options.buttonsClass)}
${Utils.sprintf(' btn-%s', this.options.iconSize)}
${this.options.autoRefreshStatus ? 'active' : ''}"
type="button" title="${this.options.formatAutoRefresh()}">
<i class="${this.options.iconsPrefix} ${this.options.icons.autoRefresh}"></i>
</button>
`).appendTo($btnGroup)
$btnAutoRefresh.on('click', $.proxy(this.toggleAutoRefresh, this))
}
}
}
toggleAutoRefresh () {
if (this.options.autoRefresh) {
if (this.options.autoRefreshStatus) {
clearInterval(this.options.autoRefreshFunction)
this.$toolbar.find('>.btn-group').find('.auto-refresh').removeClass('active')
} else {
this.options.autoRefreshFunction = setInterval(() => {
this.refresh({silent: this.options.autoRefreshSilent})
}, this.options.autoRefreshInterval * 1000)
this.$toolbar.find('>.btn-group').find('.auto-refresh').addClass('active')
}
this.options.autoRefreshStatus = !this.options.autoRefreshStatus
}
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Auto Refresh",
"version": "1.0.0",
"description": "Plugin to automatically refresh the table on an interval.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/auto-refresh",
"example": "#",
"plugins": [{
"name": "bootstrap-table-auto-refresh",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/auto-refresh"
}],
"author": {
"name": "fenichaler",
"image": "https://avatars.githubusercontent.com/u/3437075"
}
}

View File

@@ -0,0 +1,401 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
const UtilsCookie = {
cookieIds: {
sortOrder: 'bs.table.sortOrder',
sortName: 'bs.table.sortName',
pageNumber: 'bs.table.pageNumber',
pageList: 'bs.table.pageList',
columns: 'bs.table.columns',
searchText: 'bs.table.searchText',
filterControl: 'bs.table.filterControl',
filterBy: 'bs.table.filterBy'
},
getCurrentHeader (that) {
let header = that.$header
if (that.options.height) {
header = that.$tableHeader
}
return header
},
getCurrentSearchControls (that) {
let searchControls = 'select, input'
if (that.options.height) {
searchControls = 'table select, table input'
}
return searchControls
},
cookieEnabled () {
return !!(navigator.cookieEnabled)
},
inArrayCookiesEnabled (cookieName, cookiesEnabled) {
let index = -1
for (let i = 0; i < cookiesEnabled.length; i++) {
if (cookieName.toLowerCase() === cookiesEnabled[i].toLowerCase()) {
index = i
break
}
}
return index
},
setCookie (that, cookieName, cookieValue) {
if ((!that.options.cookie) || (!UtilsCookie.cookieEnabled()) || (that.options.cookieIdTable === '')) {
return
}
if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
return
}
cookieName = `${that.options.cookieIdTable}.${cookieName}`
switch (that.options.cookieStorage) {
case 'cookieStorage':
document.cookie = [
cookieName, '=', encodeURIComponent(cookieValue),
`; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
that.options.cookieSecure ? '; secure' : ''
].join('')
break
case 'localStorage':
localStorage.setItem(cookieName, cookieValue)
break
case 'sessionStorage':
sessionStorage.setItem(cookieName, cookieValue)
break
default:
return false
}
return true
},
getCookie (that, tableName, cookieName) {
if (!cookieName) {
return null
}
if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
return null
}
cookieName = `${tableName}.${cookieName}`
switch (that.options.cookieStorage) {
case 'cookieStorage':
const value = `; ${document.cookie}`
const parts = value.split(`; ${cookieName}=`)
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
case 'localStorage':
return localStorage.getItem(cookieName)
case 'sessionStorage':
return sessionStorage.getItem(cookieName)
default:
return null
}
},
deleteCookie (that, tableName, cookieName) {
cookieName = `${tableName}.${cookieName}`
switch (that.options.cookieStorage) {
case 'cookieStorage':
document.cookie = [
encodeURIComponent(cookieName), '=',
'; expires=Thu, 01 Jan 1970 00:00:00 GMT',
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : ''
].join('')
break
case 'localStorage':
localStorage.removeItem(cookieName)
break
case 'sessionStorage':
sessionStorage.removeItem(cookieName)
break
default:
return false
}
return true
},
calculateExpiration (cookieExpire) {
const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
switch (time.toLowerCase()) {
case 's':
cookieExpire = +cookieExpire
break
case 'mi':
cookieExpire *= 60
break
case 'h':
cookieExpire = cookieExpire * 60 * 60
break
case 'd':
cookieExpire = cookieExpire * 24 * 60 * 60
break
case 'm':
cookieExpire = cookieExpire * 30 * 24 * 60 * 60
break
case 'y':
cookieExpire = cookieExpire * 365 * 24 * 60 * 60
break
default:
cookieExpire = undefined
break
}
if (!cookieExpire) {
return ''
}
const d = new Date()
d.setTime(d.getTime() + cookieExpire * 1000)
return d.toGMTString()
},
initCookieFilters (bootstrapTable) {
setTimeout(() => {
const parsedCookieFilters = JSON.parse(UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
if (!bootstrapTable.options.filterControlValuesLoaded && parsedCookieFilters) {
const cachedFilters = {}
const header = UtilsCookie.getCurrentHeader(bootstrapTable)
const searchControls = UtilsCookie.getCurrentSearchControls(bootstrapTable)
const applyCookieFilters = (element, filteredCookies) => {
$(filteredCookies).each((i, cookie) => {
if (cookie.text !== '') {
$(element).val(cookie.text)
cachedFilters[cookie.field] = cookie.text
}
})
}
header.find(searchControls).each(function () {
const field = $(this).closest('[data-field]').data('field')
const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
applyCookieFilters(this, filteredCookies)
})
bootstrapTable.initColumnSearch(cachedFilters)
bootstrapTable.options.filterControlValuesLoaded = true
bootstrapTable.initServer()
}
}, 250)
}
}
$.extend($.fn.bootstrapTable.defaults, {
cookie: false,
cookieExpire: '2h',
cookiePath: null,
cookieDomain: null,
cookieSecure: null,
cookieIdTable: '',
cookiesEnabled: [
'bs.table.sortOrder', 'bs.table.sortName',
'bs.table.pageNumber', 'bs.table.pageList',
'bs.table.columns', 'bs.table.searchText',
'bs.table.filterControl', 'bs.table.filterBy'
],
cookieStorage: 'cookieStorage', // localStorage, sessionStorage
// internal variable
filterControls: [],
filterControlValuesLoaded: false
})
$.fn.bootstrapTable.methods.push('getCookies')
$.fn.bootstrapTable.methods.push('deleteCookie')
$.extend($.fn.bootstrapTable.utils, {
setCookie: UtilsCookie.setCookie,
getCookie: UtilsCookie.getCookie
})
$.BootstrapTable = class extends $.BootstrapTable {
init () {
// FilterBy logic
const filterByCookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterBy))
this.filterColumns = filterByCookie ? filterByCookie : {}
// FilterControl logic
this.options.filterControls = []
this.options.filterControlValuesLoaded = false
this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
this.options.cookiesEnabled.replace('[', '').replace(']', '')
.replace(/ /g, '').toLowerCase().split(',') :
this.options.cookiesEnabled
if (this.options.filterControl) {
const that = this
this.$el.on('column-search.bs.table', (e, field, text) => {
let isNewField = true
for (let i = 0; i < that.options.filterControls.length; i++) {
if (that.options.filterControls[i].field === field) {
that.options.filterControls[i].text = text
isNewField = false
break
}
}
if (isNewField) {
that.options.filterControls.push({
field,
text
})
}
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that.options.filterControls))
}).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
}
super.init()
}
initServer (...args) {
if (
this.options.cookie &&
this.options.filterControl &&
!this.options.filterControlValuesLoaded
) {
const cookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
if (cookie) {
return
}
}
super.initServer(...args)
}
initTable (...args) {
super.initTable(...args)
this.initCookie()
}
onSort (...args) {
super.onSort(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
}
onPageNumber (...args) {
super.onPageNumber(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
}
onPageListChange (...args) {
super.onPageListChange(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList, this.options.pageSize)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
}
onPagePre (...args) {
super.onPagePre(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
}
onPageNext (...args) {
super.onPageNext(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
}
toggleColumn (...args) {
super.toggleColumn(...args)
const visibleColumns = []
$.each(this.columns, (i, column) => {
if (column.visible) {
visibleColumns.push(column.field)
}
})
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(visibleColumns))
}
selectPage (page) {
super.selectPage(page)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
}
onSearch (event) {
super.onSearch(event)
if ($(event.currentTarget).parent().hasClass('search')) {
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
}
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
}
filterBy (...args) {
super.filterBy(...args)
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
}
initCookie () {
if (!this.options.cookie) {
return
}
if ((this.options.cookieIdTable === '') || (this.options.cookieExpire === '') || (!UtilsCookie.cookieEnabled())) {
console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
this.options.cookie = false // Make sure that the cookie extension is disabled
return
}
const sortOrderCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortOrder)
const sortOrderNameCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortName)
const pageNumberCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageNumber)
const pageListCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageList)
const columnsCookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.columns))
const searchTextCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.searchText)
// sortOrder
this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
// sortName
this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
// pageNumber
this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
// pageSize
this.options.pageSize = pageListCookie ? pageListCookie === this.options.formatAllRows() ? pageListCookie : +pageListCookie : this.options.pageSize
// searchText
this.options.searchText = searchTextCookie ? searchTextCookie : ''
if (columnsCookie) {
$.each(this.columns, (i, column) => {
column.visible = $.inArray(column.field, columnsCookie) !== -1
})
}
}
getCookies () {
const bootstrapTable = this
const cookies = {}
$.each(UtilsCookie.cookieIds, (key, value) => {
cookies[key] = UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, value)
if (key === 'columns') {
cookies[key] = JSON.parse(cookies[key])
}
})
return cookies
}
deleteCookie (cookieName) {
if ((cookieName === '') || (!UtilsCookie.cookieEnabled())) {
return
}
UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds[cookieName])
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Cookie",
"version": "1.2.1",
"description": "Plugin to use the cookie of the browser.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/cookie",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/cookie.html",
"plugins": [{
"name": "bootstrap-table-cookie",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/cookie"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,102 @@
/**
* @author Homer Glascock <HopGlascock@gmail.com>
* @version: v1.0.0
*/
!function ($) {
"use strict";
var calculateObjectValue = $.fn.bootstrapTable.utils.calculateObjectValue,
sprintf = $.fn.bootstrapTable.utils.sprintf;
var copytext = function (text) {
var textField = document.createElement('textarea');
$(textField).html(text);
document.body.appendChild(textField);
textField.select();
try {
document.execCommand('copy');
}
catch (e) {
console.log("Oops, unable to copy");
}
$(textField).remove();
};
$.extend($.fn.bootstrapTable.defaults, {
copyBtn: false,
copyWHiddenBtn: false,
copyDelemeter: ", "
});
$.fn.bootstrapTable.methods.push('copyColumnsToClipboard', 'copyColumnsToClipboardWithHidden');
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initToolbar = BootstrapTable.prototype.initToolbar;
BootstrapTable.prototype.initToolbar = function () {
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
var that = this,
$btnGroup = this.$toolbar.find('>.btn-group');
if (this.options.clickToSelect || this.options.singleSelect) {
if (this.options.copyBtn) {
var copybtn = "<button class='btn btn-default' id='copyBtn'><span class='glyphicon glyphicon-copy icon-pencil'></span></button>";
$btnGroup.append(copybtn);
$btnGroup.find('#copyBtn').click(function () { that.copyColumnsToClipboard(); });
}
if (this.options.copyWHiddenBtn) {
var copyhiddenbtn = "<button class='btn btn-default' id='copyWHiddenBtn'><span class='badge'><span class='glyphicon glyphicon-copy icon-pencil'></span></span></button>";
$btnGroup.append(copyhiddenbtn);
$btnGroup.find('#copyWHiddenBtn').click(function () { that.copyColumnsToClipboardWithHidden(); });
}
}
};
BootstrapTable.prototype.copyColumnsToClipboard = function () {
var that = this,
ret = "",
delimet = this.options.copyDelemeter;
$.each(that.getSelections(), function (index, row) {
$.each(that.options.columns[0], function (indy, column) {
if (column.field !== "state" && column.field !== "RowNumber" && column.visible) {
if (row[column.field] !== null) {
ret += calculateObjectValue(column, that.header.formatters[indy], [row[column.field], row, index], row[column.field]);
}
ret += delimet;
}
});
ret += "\r\n";
});
copytext(ret);
};
BootstrapTable.prototype.copyColumnsToClipboardWithHidden = function () {
var that = this,
ret = "",
delimet = this.options.copyDelemeter;
$.each(that.getSelections(), function (index, row) {
$.each(that.options.columns[0], function (indy, column) {
if (column.field != "state" && column.field !== "RowNumber") {
if (row[column.field] !== null) {
ret += calculateObjectValue(column, that.header.formatters[indy], [row[column.field], row, index], row[column.field]);
}
ret += delimet;
}
});
ret += "\r\n";
});
copytext(ret);
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Copy Rows",
"version": "1.0.0",
"description": "Allows pushing of selected column data to the clipboard.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/copy-rows",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/copy-rows.html",
"plugins": [{
"name": "copy-rows",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/copy-rows"
}],
"author": {
"name": "Homer Glascock",
"image": "https://avatars1.githubusercontent.com/u/5546710"
}
}

View File

@@ -0,0 +1,32 @@
/**
* When using server-side processing, the default mode of operation for
* bootstrap-table is to simply throw away any data that currently exists in the
* table and make a request to the server to get the first page of data to
* display. This is fine for an empty table, but if you already have the first
* page of data displayed in the plain HTML, it is a waste of resources. As
* such, you can use data-defer-url instead of data-url to allow you to instruct
* bootstrap-table to not make that initial request, rather it will use the data
* already on the page.
*
* @author: Ruben Suarez
* @webSite: http://rubensa.eu.org
* @version: v1.0.0
*/
(function($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
deferUrl : undefined
});
var BootstrapTable = $.fn.bootstrapTable.Constructor, _init = BootstrapTable.prototype.init;
BootstrapTable.prototype.init = function() {
_init.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.deferUrl) {
this.options.url = this.options.deferUrl;
}
}
})(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "DeferURL",
"version": "1.0.0",
"description": "Plugin to defer server side processing.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/defer-url",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/defer-url.html",
"plugins": [{
"name": "bootstrap-table-defer-url",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/defer-url"
}],
"author": {
"name": "rubensa",
"image": "https://avatars1.githubusercontent.com/u/1469340"
}
}

View File

@@ -0,0 +1,149 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* extensions: https://github.com/vitalets/x-editable
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
editable: true,
onEditableInit () {
return false
},
onEditableSave (field, row, oldValue, $el) {
return false
},
onEditableShown (field, row, $el, editable) {
return false
},
onEditableHidden (field, row, $el, reason) {
return false
}
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'editable-init.bs.table': 'onEditableInit',
'editable-save.bs.table': 'onEditableSave',
'editable-shown.bs.table': 'onEditableShown',
'editable-hidden.bs.table': 'onEditableHidden'
})
$.BootstrapTable = class extends $.BootstrapTable {
initTable () {
super.initTable()
if (!this.options.editable) {
return
}
$.each(this.columns, (i, column) => {
if (!column.editable) {
return
}
const editableOptions = {}
const editableDataMarkup = []
const editableDataPrefix = 'editable-'
const processDataOptions = (key, value) => {
// Replace camel case with dashes.
const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`)
if (dashKey.indexOf(editableDataPrefix) === 0) {
editableOptions[dashKey.replace(editableDataPrefix, 'data-')] = value
}
}
$.each(this.options, processDataOptions)
column.formatter = column.formatter || (value => value)
column._formatter = column._formatter ? column._formatter : column.formatter
column.formatter = (value, row, index) => {
const result = Utils.calculateObjectValue(column,
column._formatter, [value, row, index], value)
$.each(column, processDataOptions)
$.each(editableOptions, (key, value) => {
editableDataMarkup.push(` ${key}="${value}"`)
})
let _dont_edit_formatter = false
if (column.editable.hasOwnProperty('noeditFormatter')) {
_dont_edit_formatter = column.editable.noeditFormatter(value, row, index)
}
if (_dont_edit_formatter === false) {
return `<a href="javascript:void(0)"
data-name="${column.field}"
data-pk="${row[this.options.idField]}"
data-value="${result}"
${editableDataMarkup.join('')}></a>`
}
return _dont_edit_formatter
}
})
}
initBody (fixedScroll) {
super.initBody(fixedScroll)
if (!this.options.editable) {
return
}
$.each(this.columns, (i, column) => {
if (!column.editable) {
return
}
const data = this.getData()
const $field = this.$body.find(`a[data-name="${column.field}"]`)
$field.each((i, element) => {
const $element = $(element)
const $tr = $element.closest('tr')
const index = $tr.data('index')
const row = data[index]
const editableOpts = Utils.calculateObjectValue(column,
column.editable, [index, row, $element], {})
$element.editable(editableOpts)
})
$field.off('save').on('save', ({currentTarget}, {submitValue}) => {
const $this = $(currentTarget)
const data = this.getData()
const index = $this.parents('tr[data-index]').data('index')
const row = data[index]
const oldValue = row[column.field]
$this.data('value', submitValue)
row[column.field] = submitValue
this.trigger('editable-save', column.field, row, oldValue, $this)
this.resetFooter()
})
$field.off('shown').on('shown', ({currentTarget}, editable) => {
const $this = $(currentTarget)
const data = this.getData()
const index = $this.parents('tr[data-index]').data('index')
const row = data[index]
this.trigger('editable-shown', column.field, row, $this, editable)
})
$field.off('hidden').on('hidden', ({currentTarget}, reason) => {
const $this = $(currentTarget)
const data = this.getData()
const index = $this.parents('tr[data-index]').data('index')
const row = data[index]
this.trigger('editable-hidden', column.field, row, $this, reason)
})
})
this.trigger('editable-init')
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Table Editable",
"version": "1.1.0",
"description": "Use the x-editable to in-place editing your table.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/editable",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/editable.html",
"plugins": [{
"name": "x-editable",
"url": "https://github.com/vitalets/x-editable"
}],
"author": {
"name": "wenzhixin",
"image": "https://avatars1.githubusercontent.com/u/2117018"
}
}

View File

@@ -0,0 +1,225 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* extensions: https://github.com/hhurz/tableExport.jquery.plugin
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
const bootstrap = {
3: {
icons: {
export: 'glyphicon-export icon-share'
},
html: {
dropmenu: '<ul class="dropdown-menu" role="menu"></ul>',
dropitem: '<li role="menuitem" data-type="%s"><a href="javascript:">%s</a></li>'
}
},
4: {
icons: {
export: 'fa-download'
},
html: {
dropmenu: '<div class="dropdown-menu dropdown-menu-right"></div>',
dropitem: '<a class="dropdown-item" data-type="%s" href="javascript:">%s</a>'
}
}
}[Utils.bootstrapVersion]
const TYPE_NAME = {
json: 'JSON',
xml: 'XML',
png: 'PNG',
csv: 'CSV',
txt: 'TXT',
sql: 'SQL',
doc: 'MS-Word',
excel: 'MS-Excel',
xlsx: 'MS-Excel (OpenXML)',
powerpoint: 'MS-Powerpoint',
pdf: 'PDF'
}
$.extend($.fn.bootstrapTable.defaults, {
showExport: false,
exportDataType: 'basic', // basic, all, selected
exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
exportOptions: {},
exportFooter: false
})
$.extend($.fn.bootstrapTable.defaults.icons, {
export: bootstrap.icons.export
})
$.extend($.fn.bootstrapTable.locales, {
formatExport () {
return 'Export data'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.fn.bootstrapTable.methods.push('exportTable')
$.BootstrapTable = class extends $.BootstrapTable {
initToolbar () {
const o = this.options
this.showToolbar = this.showToolbar || o.showExport
super.initToolbar()
if (!this.options.showExport) {
return
}
const $btnGroup = this.$toolbar.find('>.btn-group')
this.$export = $btnGroup.find('div.export')
if (this.$export.length) {
this.updateExportButton()
return
}
this.$export = $(`
<div class="export btn-group">
<button class="btn btn-${o.buttonsClass} btn-${o.iconSize} dropdown-toggle"
aria-label="export type"
title="${o.formatExport()}"
data-toggle="dropdown"
type="button">
<i class="${o.iconsPrefix} ${o.icons.export}"></i>
<span class="caret"></span>
</button>
${bootstrap.html.dropmenu}
</div>
`).appendTo($btnGroup)
this.updateExportButton()
const $menu = this.$export.find('.dropdown-menu')
let exportTypes = o.exportTypes
if (typeof exportTypes === 'string') {
const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',')
exportTypes = types.map(t => t.slice(1, -1))
}
for (const type of exportTypes) {
if (TYPE_NAME.hasOwnProperty(type)) {
$menu.append(Utils.sprintf(bootstrap.html.dropitem, type, TYPE_NAME[type]))
}
}
$menu.find('>li, >a').click(({currentTarget}) => {
const type = $(currentTarget).data('type')
const exportOptions = {
type,
escape: false
}
this.exportTable(exportOptions)
})
}
exportTable (options) {
const o = this.options
const stateField = this.header.stateField
const isCardView = o.cardView
const doExport = callback => {
if (stateField) {
this.hideColumn(stateField)
}
if (isCardView) {
this.toggleView()
}
const data = this.getData()
if (o.exportFooter) {
const $footerRow = this.$tableFooter.find('tr').first()
const footerData = {}
const footerHtml = []
$.each($footerRow.children(), (index, footerCell) => {
const footerCellHtml = $(footerCell).children('.th-inner').first().html()
footerData[this.columns[index].field] = footerCellHtml === '&nbsp;' ? null : footerCellHtml
// grab footer cell text into cell index-based array
footerHtml.push(footerCellHtml)
})
this.append(footerData)
const $lastTableRow = this.$body.children().last()
$.each($lastTableRow.children(), (index, lastTableRowCell) => {
$(lastTableRowCell).html(footerHtml[index])
})
}
this.$el.tableExport($.extend({
onAfterSaveToFile: () => {
if (o.exportFooter) {
this.load(data)
}
if (stateField) {
this.showColumn(stateField)
}
if (isCardView) {
this.toggleView()
}
callback()
}
}, o.exportOptions, options))
}
if (o.exportDataType === 'all' && o.pagination) {
const eventName = o.sidePagination === 'server'
? 'post-body.bs.table' : 'page-change.bs.table'
this.$el.one(eventName, () => {
doExport(() => {
this.togglePagination()
})
})
this.togglePagination()
} else if (o.exportDataType === 'selected') {
let data = this.getData()
let selectedData = this.getSelections()
if (!selectedData.length) {
return
}
if (o.sidePagination === 'server') {
data = {
total: o.totalRows,
[this.options.dataField]: data
}
selectedData = {
total: selectedData.length,
[this.options.dataField]: selectedData
}
}
this.load(selectedData)
doExport(() => {
this.load(data)
})
} else {
doExport()
}
}
updateSelected () {
super.updateSelected()
this.updateExportButton()
}
updateExportButton () {
if (this.options.exportDataType === 'selected') {
this.$export.find('> button')
.prop('disabled', !this.getSelections().length)
}
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Table Export",
"version": "1.1.0",
"description": "Export your table data to JSON, XML, CSV, TXT, SQL, Word, Excel, PNG, PDF.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/export",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/export.html",
"plugins": [{
"name": "tableExport.jquery.plugin",
"url": "https://github.com/hhurz/tableExport.jquery.plugin"
}],
"author": {
"name": "wenzhixin",
"image": "https://avatars1.githubusercontent.com/u/2117018"
}
}

View File

@@ -0,0 +1,13 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v2.1.1
*/
.no-filter-control {
height: 34px;
}
.filter-control {
margin: 0 2px 2px 2px;
}

View File

@@ -0,0 +1,917 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v2.2.0
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
const UtilsFilterControl = {
getOptionsFromSelectControl (selectControl) {
return selectControl.get(selectControl.length - 1).options
},
hideUnusedSelectOptions (selectControl, uniqueValues) {
const options = UtilsFilterControl.getOptionsFromSelectControl(
selectControl
)
for (let i = 0; i < options.length; i++) {
if (options[i].value !== '') {
if (!uniqueValues.hasOwnProperty(options[i].value)) {
selectControl
.find(Utils.sprintf('option[value=\'%s\']', options[i].value))
.hide()
} else {
selectControl
.find(Utils.sprintf('option[value=\'%s\']', options[i].value))
.show()
}
}
}
},
addOptionToSelectControl (selectControl, _value, text) {
const value = $.trim(_value)
const $selectControl = $(selectControl.get(selectControl.length - 1))
if (
!UtilsFilterControl.existOptionInSelectControl(selectControl, value)
) {
$selectControl.append(
$('<option></option>')
.attr('value', value)
.text(
$('<div />')
.html(text)
.text()
)
)
}
},
sortSelectControl (selectControl) {
const $selectControl = $(selectControl.get(selectControl.length - 1))
const $opts = $selectControl.find('option:gt(0)')
$opts.sort((a, b) => {
let aa = $(a).text().toLowerCase()
let bb = $(b).text().toLowerCase()
if ($.isNumeric(a) && $.isNumeric(b)) {
// Convert numerical values from string to float.
aa = parseFloat(aa)
bb = parseFloat(bb)
}
return aa > bb ? 1 : aa < bb ? -1 : 0
})
$selectControl.find('option:gt(0)').remove()
$selectControl.append($opts)
},
existOptionInSelectControl (selectControl, value) {
const options = UtilsFilterControl.getOptionsFromSelectControl(
selectControl
)
for (let i = 0; i < options.length; i++) {
if (options[i].value === value.toString()) {
// The value is not valid to add
return true
}
}
// If we get here, the value is valid to add
return false
},
fixHeaderCSS ({ $tableHeader }) {
$tableHeader.css('height', '77px')
},
getCurrentHeader ({ $header, options, $tableHeader }) {
let header = $header
if (options.height) {
header = $tableHeader
}
return header
},
getCurrentSearchControls ({ options }) {
let searchControls = 'select, input'
if (options.height) {
searchControls = 'table select, table input'
}
return searchControls
},
getCursorPosition (el) {
if (Utils.isIEBrowser()) {
if ($(el).is('input[type=text]')) {
let pos = 0
if ('selectionStart' in el) {
pos = el.selectionStart
} else if ('selection' in document) {
el.focus()
const Sel = document.selection.createRange()
const SelLength = document.selection.createRange().text.length
Sel.moveStart('character', -el.value.length)
pos = Sel.text.length - SelLength
}
return pos
}
return -1
}
return -1
},
setCursorPosition (el) {
$(el).val(el.value)
},
copyValues (that) {
const header = UtilsFilterControl.getCurrentHeader(that)
const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
that.options.valuesFilterControl = []
header.find(searchControls).each(function () {
that.options.valuesFilterControl.push({
field: $(this)
.closest('[data-field]')
.data('field'),
value: $(this).val(),
position: UtilsFilterControl.getCursorPosition($(this).get(0)),
hasFocus: $(this).is(':focus')
})
})
},
setValues (that) {
let field = null
let result = []
const header = UtilsFilterControl.getCurrentHeader(that)
const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
if (that.options.valuesFilterControl.length > 0) {
// Callback to apply after settings fields values
let fieldToFocusCallback = null
header.find(searchControls).each(function (index, ele) {
field = $(this)
.closest('[data-field]')
.data('field')
result = that.options.valuesFilterControl.filter(valueObj => valueObj.field === field)
if (result.length > 0) {
$(this).val(result[0].value)
if (result[0].hasFocus) {
// set callback if the field had the focus.
fieldToFocusCallback = ((fieldToFocus, carretPosition) => {
// Closure here to capture the field and cursor position
const closedCallback = () => {
fieldToFocus.focus()
UtilsFilterControl.setCursorPosition(fieldToFocus, carretPosition)
}
return closedCallback
})($(this).get(0), result[0].position)
}
}
})
// Callback call.
if (fieldToFocusCallback !== null) {
fieldToFocusCallback()
}
}
},
collectBootstrapCookies () {
const cookies = []
const foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g)
if (foundCookies) {
$.each(foundCookies, (i, _cookie) => {
let cookie = _cookie
if (/./.test(cookie)) {
cookie = cookie.split('.').pop()
}
if ($.inArray(cookie, cookies) === -1) {
cookies.push(cookie)
}
})
return cookies
}
},
escapeID (id) {
return String(id).replace(/(:|\.|\[|\]|,)/g, '\\$1')
},
isColumnSearchableViaSelect ({ filterControl, searchable }) {
return filterControl &&
filterControl.toLowerCase() === 'select' &&
searchable
},
isFilterDataNotGiven ({ filterData }) {
return filterData === undefined ||
filterData.toLowerCase() === 'column'
},
hasSelectControlElement (selectControl) {
return selectControl && selectControl.length > 0
},
initFilterSelectControls (that) {
const data = that.data
const itemsPerPage = that.pageTo < that.options.data.length ? that.options.data.length : that.pageTo
const z = that.options.pagination
? that.options.sidePagination === 'server'
? that.pageTo
: that.options.totalRows
: that.pageTo
$.each(that.header.fields, (j, field) => {
const column = that.columns[that.fieldsColumnsIndex[field]]
const selectControl = $(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
if (
UtilsFilterControl.isColumnSearchableViaSelect(column) &&
UtilsFilterControl.isFilterDataNotGiven(column) &&
UtilsFilterControl.hasSelectControlElement(selectControl)
) {
if (selectControl.get(selectControl.length - 1).options.length === 0) {
// Added the default option
UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
}
const uniqueValues = {}
for (let i = 0; i < z; i++) {
// Added a new value
const fieldValue = data[i][field]
const formattedValue = Utils.calculateObjectValue(that.header, that.header.formatters[j], [fieldValue, data[i], i], fieldValue)
uniqueValues[formattedValue] = fieldValue
}
// eslint-disable-next-line guard-for-in
for (const key in uniqueValues) {
UtilsFilterControl.addOptionToSelectControl(selectControl, uniqueValues[key], key)
}
UtilsFilterControl.sortSelectControl(selectControl)
if (that.options.hideUnusedSelectOptions) {
UtilsFilterControl.hideUnusedSelectOptions(selectControl, uniqueValues)
}
}
})
that.trigger('created-controls')
},
getFilterDataMethod (objFilterDataMethod, searchTerm) {
const keys = Object.keys(objFilterDataMethod)
for (let i = 0; i < keys.length; i++) {
if (keys[i] === searchTerm) {
return objFilterDataMethod[searchTerm]
}
}
return null
},
createControls (that, header) {
let addedFilterControl = false
let isVisible
let html
$.each(that.columns, (i, column) => {
isVisible = 'hidden'
html = []
if (!column.visible) {
return
}
if (!column.filterControl) {
html.push('<div class="no-filter-control"></div>')
} else {
html.push('<div class="filter-control">')
const nameControl = column.filterControl.toLowerCase()
if (column.searchable && that.options.filterTemplate[nameControl]) {
addedFilterControl = true
isVisible = 'visible'
html.push(
that.options.filterTemplate[nameControl](
that,
column.field,
isVisible,
column.filterControlPlaceholder
? column.filterControlPlaceholder
: '',
`filter-control-${i}`
)
)
}
}
$.each(header.children().children(), (i, tr) => {
const $tr = $(tr)
if ($tr.data('field') === column.field) {
$tr.find('.fht-cell').append(html.join(''))
return false
}
})
if (
column.filterData !== undefined &&
column.filterData.toLowerCase() !== 'column'
) {
const filterDataType = UtilsFilterControl.getFilterDataMethod(
/* eslint-disable no-use-before-define */
filterDataMethods,
column.filterData.substring(0, column.filterData.indexOf(':'))
)
let filterDataSource
let selectControl
if (filterDataType !== null) {
filterDataSource = column.filterData.substring(
column.filterData.indexOf(':') + 1,
column.filterData.length
)
selectControl = $(
`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`
)
UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
filterDataType(filterDataSource, selectControl)
} else {
throw new SyntaxError(
'Error. You should use any of these allowed filter data methods: var, json, url.' +
' Use like this: var: {key: "value"}'
)
}
let variableValues
let key
// eslint-disable-next-line default-case
switch (filterDataType) {
case 'url':
$.ajax({
url: filterDataSource,
dataType: 'json',
success (data) {
// eslint-disable-next-line guard-for-in
for (const key in data) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
}
})
break
case 'var':
variableValues = window[filterDataSource]
// eslint-disable-next-line guard-for-in
for (key in variableValues) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
break
case 'jso':
variableValues = JSON.parse(filterDataSource)
// eslint-disable-next-line guard-for-in
for (key in variableValues) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
break
}
}
})
if (addedFilterControl) {
header.off('keyup', 'input').on('keyup', 'input', (event, obj) => {
// Simulate enter key action from clear button
event.keyCode = obj ? obj.keyCode : event.keyCode
if (that.options.searchOnEnterKey && event.keyCode !== 13) {
return
}
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
return
}
const $currentTarget = $(event.currentTarget)
if ($currentTarget.is(':checkbox') || $currentTarget.is(':radio')) {
return
}
clearTimeout(event.currentTarget.timeoutId || 0)
event.currentTarget.timeoutId = setTimeout(() => {
that.onColumnSearch(event)
}, that.options.searchTimeOut)
})
header.off('change', 'select').on('change', 'select', event => {
if (that.options.searchOnEnterKey && event.keyCode !== 13) {
return
}
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
return
}
clearTimeout(event.currentTarget.timeoutId || 0)
event.currentTarget.timeoutId = setTimeout(() => {
that.onColumnSearch(event)
}, that.options.searchTimeOut)
})
header.off('mouseup', 'input').on('mouseup', 'input', function (event) {
const $input = $(this)
const oldValue = $input.val()
if (oldValue === '') {
return
}
setTimeout(() => {
const newValue = $input.val()
if (newValue === '') {
clearTimeout(event.currentTarget.timeoutId || 0)
event.currentTarget.timeoutId = setTimeout(() => {
that.onColumnSearch(event)
}, that.options.searchTimeOut)
}
}, 1)
})
if (header.find('.date-filter-control').length > 0) {
$.each(that.columns, (i, { filterControl, field, filterDatepickerOptions }) => {
if (
filterControl !== undefined &&
filterControl.toLowerCase() === 'datepicker'
) {
header
.find(
`.date-filter-control.bootstrap-table-filter-control-${field}`
)
.datepicker(filterDatepickerOptions)
.on('changeDate', ({ currentTarget }) => {
$(currentTarget).val(
currentTarget.value
)
// Fired the keyup event
$(currentTarget).keyup()
})
}
})
}
} else {
header.find('.filterControl').hide()
}
},
getDirectionOfSelectOptions (_alignment) {
const alignment = _alignment === undefined ? 'left' : _alignment.toLowerCase()
switch (alignment) {
case 'left':
return 'ltr'
case 'right':
return 'rtl'
case 'auto':
return 'auto'
default:
return 'ltr'
}
}
}
const filterDataMethods = {
var (filterDataSource, selectControl) {
const variableValues = window[filterDataSource]
// eslint-disable-next-line guard-for-in
for (const key in variableValues) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
},
url (filterDataSource, selectControl) {
$.ajax({
url: filterDataSource,
dataType: 'json',
success (data) {
// eslint-disable-next-line guard-for-in
for (const key in data) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
}
})
},
json (filterDataSource, selectControl) {
const variableValues = JSON.parse(filterDataSource)
// eslint-disable-next-line guard-for-in
for (const key in variableValues) {
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
}
UtilsFilterControl.sortSelectControl(selectControl)
}
}
const bootstrap = {
3: {
icons: {
clear: 'glyphicon-trash icon-clear'
}
},
4: {
icons: {
clear: 'fa-trash icon-clear'
}
}
}[Utils.bootstrapVersion]
$.extend($.fn.bootstrapTable.defaults, {
filterControl: false,
onColumnSearch (field, text) {
return false
},
onCreatedControls () {
return true
},
filterShowClear: false,
alignmentSelectControlOptions: undefined,
filterTemplate: {
input (that, field, isVisible, placeholder) {
return Utils.sprintf(
'<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" placeholder="%s">',
field,
isVisible,
placeholder
)
},
select ({ options }, field, isVisible) {
return Utils.sprintf(
'<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" dir="%s"></select>',
field,
isVisible,
UtilsFilterControl.getDirectionOfSelectOptions(
options.alignmentSelectControlOptions
)
)
},
datepicker (that, field, isVisible) {
return Utils.sprintf(
'<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s">',
field,
isVisible
)
}
},
disableControlWhenSearch: false,
searchOnEnterKey: false,
// internal variables
valuesFilterControl: []
})
$.extend($.fn.bootstrapTable.columnDefaults, {
filterControl: undefined,
filterData: undefined,
filterDatepickerOptions: undefined,
filterStrictSearch: false,
filterStartsWithSearch: false,
filterControlPlaceholder: ''
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'column-search.bs.table': 'onColumnSearch',
'created-controls.bs.table': 'onCreatedControls'
})
$.extend($.fn.bootstrapTable.defaults.icons, {
clear: bootstrap.icons.clear
})
$.extend($.fn.bootstrapTable.locales, {
formatClearFilters () {
return 'Clear Filters'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.fn.bootstrapTable.methods.push('triggerSearch')
$.fn.bootstrapTable.methods.push('clearFilterControl')
$.BootstrapTable = class extends $.BootstrapTable {
init () {
// Make sure that the filterControl option is set
if (this.options.filterControl) {
const that = this
// Make sure that the internal variables are set correctly
this.options.valuesFilterControl = []
this.$el
.on('reset-view.bs.table', () => {
// Create controls on $tableHeader if the height is set
if (!that.options.height) {
return
}
// Avoid recreate the controls
if (
that.$tableHeader.find('select').length > 0 ||
that.$tableHeader.find('input').length > 0
) {
return
}
UtilsFilterControl.createControls(that, that.$tableHeader)
})
.on('post-header.bs.table', () => {
UtilsFilterControl.setValues(that)
})
.on('post-body.bs.table', () => {
if (that.options.height) {
UtilsFilterControl.fixHeaderCSS(that)
}
})
.on('column-switch.bs.table', () => {
UtilsFilterControl.setValues(that)
})
.on('load-success.bs.table', () => {
that.EnableControls(true)
})
.on('load-error.bs.table', () => {
that.EnableControls(true)
})
}
super.init()
}
initToolbar () {
this.showToolbar =
this.showToolbar ||
(this.options.filterControl && this.options.filterShowClear)
super.initToolbar()
if (this.options.filterControl && this.options.filterShowClear) {
const $btnGroup = this.$toolbar.find('>.btn-group')
let $btnClear = $btnGroup.find('.filter-show-clear')
if (!$btnClear.length) {
$btnClear = $(
[
Utils.sprintf(
'<button class="btn btn-%s filter-show-clear" ',
this.options.buttonsClass
),
Utils.sprintf(
'type="button" title="%s">',
this.options.formatClearFilters()
),
Utils.sprintf(
'<i class="%s %s"></i> ',
this.options.iconsPrefix,
this.options.icons.clear
),
'</button>'
].join('')
).appendTo($btnGroup)
$btnClear
.off('click')
.on('click', $.proxy(this.clearFilterControl, this))
}
}
}
initHeader () {
super.initHeader()
if (!this.options.filterControl) {
return
}
UtilsFilterControl.createControls(this, this.$header)
}
initBody () {
super.initBody()
UtilsFilterControl.initFilterSelectControls(this)
}
initSearch () {
const that = this
const fp = $.isEmptyObject(that.filterColumnsPartial)
? null
: that.filterColumnsPartial
if (fp === null || Object.keys(fp).length <= 1) {
super.initSearch()
}
if (this.options.sidePagination === 'server') {
return
}
if (fp === null) {
return
}
// Check partial column filter
that.data = fp
? that.options.data.filter((item, i) => {
const itemIsExpected = []
Object.keys(item).forEach((key, index) => {
const thisColumn = that.columns[that.fieldsColumnsIndex[key]]
const fval = (fp[key] || '').toLowerCase()
let value = item[key]
if (fval === '') {
itemIsExpected.push(true)
} else {
// Fix #142: search use formated data
if (thisColumn && thisColumn.searchFormatter) {
value = $.fn.bootstrapTable.utils.calculateObjectValue(
that.header,
that.header.formatters[$.inArray(key, that.header.fields)],
[value, item, i],
value
)
}
if ($.inArray(key, that.header.fields) !== -1) {
if (typeof value === 'string' || typeof value === 'number') {
if (thisColumn.filterStrictSearch) {
if (value.toString().toLowerCase() === fval.toString().toLowerCase()) {
itemIsExpected.push(true)
} else {
itemIsExpected.push(false)
}
} else if (thisColumn.filterStartsWithSearch) {
if ((`${value}`).toLowerCase().indexOf(fval) === 0) {
itemIsExpected.push(true)
} else {
itemIsExpected.push(false)
}
} else {
if ((`${value}`).toLowerCase().includes(fval)) {
itemIsExpected.push(true)
} else {
itemIsExpected.push(false)
}
}
}
}
}
})
return !itemIsExpected.includes(false)
})
: that.data
}
initColumnSearch (filterColumnsDefaults) {
UtilsFilterControl.copyValues(this)
if (filterColumnsDefaults) {
this.filterColumnsPartial = filterColumnsDefaults
this.updatePagination()
// eslint-disable-next-line guard-for-in
for (const filter in filterColumnsDefaults) {
this.trigger('column-search', filter, filterColumnsDefaults[filter])
}
}
}
onColumnSearch (event) {
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
return
}
UtilsFilterControl.copyValues(this)
const text = $.trim($(event.currentTarget).val())
const $field = $(event.currentTarget)
.closest('[data-field]')
.data('field')
if ($.isEmptyObject(this.filterColumnsPartial)) {
this.filterColumnsPartial = {}
}
if (text) {
this.filterColumnsPartial[$field] = text
} else {
delete this.filterColumnsPartial[$field]
}
// if the searchText is the same as the previously selected column value,
// bootstrapTable will not try searching again (even though the selected column
// may be different from the previous search). As a work around
// we're manually appending some text to bootrap's searchText field
// to guarantee that it will perform a search again when we call this.onSearch(event)
this.searchText += 'randomText'
this.options.pageNumber = 1
this.EnableControls(false)
this.onSearch(event)
this.trigger('column-search', $field, text)
}
clearFilterControl () {
if (this.options.filterControl && this.options.filterShowClear) {
const that = this
const cookies = UtilsFilterControl.collectBootstrapCookies()
const header = UtilsFilterControl.getCurrentHeader(that)
const table = header.closest('table')
const controls = header.find(UtilsFilterControl.getCurrentSearchControls(that))
const search = that.$toolbar.find('.search input')
let hasValues = false
let timeoutId = 0
$.each(that.options.valuesFilterControl, (i, item) => {
hasValues = hasValues ? true : item.value !== ''
item.value = ''
})
UtilsFilterControl.setValues(that)
// clear cookies once the filters are clean
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
if (cookies && cookies.length > 0) {
$.each(cookies, (i, item) => {
if (that.deleteCookie !== undefined) {
that.deleteCookie(item)
}
})
}
}, that.options.searchTimeOut)
// If there is not any value in the controls exit this method
if (!hasValues) {
return
}
// Clear each type of filter if it exists.
// Requires the body to reload each time a type of filter is found because we never know
// which ones are going to be present.
if (controls.length > 0) {
this.filterColumnsPartial = {}
$(controls[0]).trigger(
controls[0].tagName === 'INPUT' ? 'keyup' : 'change', { keyCode: 13 }
)
} else {
return
}
if (search.length > 0) {
that.resetSearch()
}
// use the default sort order if it exists. do nothing if it does not
if (
that.options.sortName !== table.data('sortName') ||
that.options.sortOrder !== table.data('sortOrder')
) {
const sorter = header.find(
Utils.sprintf(
'[data-field="%s"]',
$(controls[0])
.closest('table')
.data('sortName')
)
)
if (sorter.length > 0) {
that.onSort({ type: 'keypress', currentTarget: sorter })
$(sorter)
.find('.sortable')
.trigger('click')
}
}
}
}
triggerSearch () {
const header = UtilsFilterControl.getCurrentHeader(this)
const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
header.find(searchControls).each(function () {
const el = $(this)
if (el.is('select')) {
el.change()
} else {
el.keyup()
}
})
}
EnableControls (enable) {
if (
this.options.disableControlWhenSearch &&
this.options.sidePagination === 'server'
) {
const header = UtilsFilterControl.getCurrentHeader(this)
const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
if (!enable) {
header.find(searchControls).prop('disabled', 'disabled')
} else {
header.find(searchControls).removeProp('disabled')
}
}
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Filter Control",
"version": "2.1.0",
"description": "Plugin to add input/select element on the top of the columns in order to filter the data.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/filter-control.html",
"plugins": [{
"name": "bootstrap-table-filter-control",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,27 @@
.fixed-table-header-columns,
.fixed-table-body-columns {
position: absolute;
background-color: #fff;
box-sizing: border-box;
overflow: hidden;
z-index: 1;
}
.fixed-table-header-columns {
z-index: 2;
}
.fixed-table-header-columns .table,
.fixed-table-body-columns .table {
border-right: 1px solid #ddd;
}
.fixed-table-header-columns .table.table-no-bordered,
.fixed-table-body-columns .table.table-no-bordered {
border-right: 1px solid transparent;
}
.fixed-table-body-columns table {
position: absolute;
animation: none;
}

View File

@@ -0,0 +1,115 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
$.extend($.fn.bootstrapTable.defaults, {
fixedColumns: false,
fixedNumber: 1
})
$.BootstrapTable = class extends $.BootstrapTable {
fitHeader (...args) {
super.fitHeader(...args)
if (!this.options.fixedColumns) {
return
}
if (this.$el.is(':hidden')) {
return
}
this.$container.find('.fixed-table-header-columns').remove()
this.$fixedHeader = $('<div class="fixed-table-header-columns"></div>')
this.$fixedHeader.append(this.$tableHeader.find('>table').clone(true))
this.$tableHeader.after(this.$fixedHeader)
const width = this.getFixedColumnsWidth()
this.$fixedHeader.css({
top: 0,
width,
height: this.$tableHeader.outerHeight(true)
})
this.initFixedColumnsBody()
this.$fixedBody.css({
top: this.$tableHeader.outerHeight(true),
width,
height: this.$tableBody.outerHeight(true) - 1
})
this.initFixedColumnsEvents()
}
initBody (...args) {
super.initBody(...args)
if (!this.options.fixedColumns) {
return
}
if (this.options.showHeader && this.options.height) {
return
}
this.initFixedColumnsBody()
this.$fixedBody.css({
top: 0,
width: this.getFixedColumnsWidth(),
height: this.$tableHeader.outerHeight(true) + this.$tableBody.outerHeight(true)
})
this.initFixedColumnsEvents()
}
initFixedColumnsBody () {
this.$container.find('.fixed-table-body-columns').remove()
this.$fixedBody = $('<div class="fixed-table-body-columns"></div>')
this.$fixedBody.append(this.$tableBody.find('>table').clone(true))
this.$tableBody.after(this.$fixedBody)
}
getFixedColumnsWidth () {
const visibleFields = this.getVisibleFields()
let width = 0
for (let i = 0; i < this.options.fixedNumber; i++) {
width += this.$header.find(`th[data-field="${visibleFields[i]}"]`).outerWidth(true)
}
return width + 1
}
initFixedColumnsEvents () {
// events
this.$tableBody.off('scroll.fixed-columns').on('scroll.fixed-columns', e => {
this.$fixedBody.find('table').css('top', -$(e.currentTarget).scrollTop())
})
this.$body.find('> tr[data-index]').off('hover').hover(e => {
const index = $(e.currentTarget).data('index')
this.$fixedBody.find(`tr[data-index="${index}"]`)
.css('background-color', $(e.currentTarget).css('background-color'))
}, e => {
const index = $(e.currentTarget).data('index')
const $tr = this.$fixedBody.find(`tr[data-index="${index}"]`)
$tr.attr('style', $tr.attr('style').replace(/background-color:.*;/, ''))
})
this.$fixedBody.find('tr[data-index]').off('hover').hover(e => {
const index = $(e.currentTarget).data('index')
this.$body.find(`tr[data-index="${index}"]`)
.css('background-color', $(e.currentTarget).css('background-color'))
}, e => {
const index = $(e.currentTarget).data('index')
const $tr = this.$body.find(`> tr[data-index="${index}"]`)
$tr.attr('style', $tr.attr('style').replace(/background-color:.*;/, ''))
})
}
}
})(jQuery)

View File

@@ -0,0 +1,11 @@
.bootstrap-table .table > tbody > tr.groupBy {
cursor: pointer;
}
.bootstrap-table .table > tbody > tr.groupBy.expanded {
}
.bootstrap-table .table > tbody > tr.hidden + tr.detail-view {
display: none;
}

View File

@@ -0,0 +1,230 @@
/**
* @author: Yura Knoxville
* @version: v1.1.0
*/
(function ($) {
'use strict';
var initBodyCaller,
tableGroups;
// it only does '%s', and return '' when arguments are undefined
var sprintf = function (str) {
var args = arguments,
flag = true,
i = 1;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
};
var groupBy = function (array , f) {
var groups = {};
array.forEach(function(o) {
var group = f(o);
groups[group] = groups[group] || [];
groups[group].push(o);
});
return groups;
};
$.extend($.fn.bootstrapTable.defaults, {
groupBy: false,
groupByField: '',
groupByFormatter: undefined
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initSort = BootstrapTable.prototype.initSort,
_initBody = BootstrapTable.prototype.initBody,
_updateSelected = BootstrapTable.prototype.updateSelected;
BootstrapTable.prototype.initSort = function () {
_initSort.apply(this, Array.prototype.slice.apply(arguments));
var that = this;
tableGroups = [];
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
if ((this.options.sortName != this.options.groupByField)) {
this.data.sort(function(a, b) {
return a[that.options.groupByField].localeCompare(b[that.options.groupByField]);
});
}
var that = this;
var groups = groupBy(that.data, function (item) {
return [item[that.options.groupByField]];
});
var index = 0;
$.each(groups, function(key, value) {
tableGroups.push({
id: index,
name: key,
data: value
});
value.forEach(function(item) {
if (!item._data) {
item._data = {};
}
item._data['parent-index'] = index;
});
index++;
});
}
}
BootstrapTable.prototype.initBody = function () {
initBodyCaller = true;
_initBody.apply(this, Array.prototype.slice.apply(arguments));
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
var that = this,
checkBox = false,
visibleColumns = 0;
this.columns.forEach(function(column) {
if (column.checkbox) {
checkBox = true;
} else {
if (column.visible) {
visibleColumns += 1;
}
}
});
if (this.options.detailView && !this.options.cardView) {
visibleColumns += 1;
}
tableGroups.forEach(function(item){
var html = [];
html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id));
if (that.options.detailView && !that.options.cardView) {
html.push('<td class="detail"></td>');
}
if (checkBox) {
html.push('<td class="bs-checkbox">',
'<input name="btSelectGroup" type="checkbox" />',
'</td>'
);
}
var formattedValue = item.name;
if (typeof(that.options.groupByFormatter) == "function") {
formattedValue = that.options.groupByFormatter(item.name, item.id, item.data);
}
html.push('<td',
sprintf(' colspan="%s"', visibleColumns),
'>', formattedValue, '</td>'
);
html.push('</tr>');
that.$body.find('tr[data-parent-index='+item.id+']:first').before($(html.join('')));
});
this.$selectGroup = [];
this.$body.find('[name="btSelectGroup"]').each(function() {
var self = $(this);
that.$selectGroup.push({
group: self,
item: that.$selectItem.filter(function () {
return ($(this).closest('tr').data('parent-index') ===
self.closest('tr').data('group-index'));
})
});
});
this.$container.off('click', '.groupBy')
.on('click', '.groupBy', function() {
$(this).toggleClass('expanded');
that.$body.find('tr[data-parent-index='+$(this).closest('tr').data('group-index')+']').toggleClass('hidden');
});
this.$container.off('click', '[name="btSelectGroup"]')
.on('click', '[name="btSelectGroup"]', function (event) {
event.stopImmediatePropagation();
var self = $(this);
var checked = self.prop('checked');
that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'));
});
}
initBodyCaller = false;
this.updateSelected();
};
BootstrapTable.prototype.updateSelected = function () {
if (!initBodyCaller) {
_updateSelected.apply(this, Array.prototype.slice.apply(arguments));
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
this.$selectGroup.forEach(function (item) {
var checkGroup = item.item.filter(':enabled').length ===
item.item.filter(':enabled').filter(':checked').length;
item.group.prop('checked', checkGroup);
});
}
}
};
BootstrapTable.prototype.getGroupSelections = function (index) {
var that = this;
return $.grep(this.data, function (row) {
return (row[that.header.stateField] && (row._data['parent-index'] === index));
});
};
BootstrapTable.prototype.checkGroup = function (index) {
this.checkGroup_(index, true);
};
BootstrapTable.prototype.uncheckGroup = function (index) {
this.checkGroup_(index, false);
};
BootstrapTable.prototype.checkGroup_ = function (index, checked) {
var rows;
var filter = function() {
return ($(this).closest('tr').data('parent-index') === index);
};
if (!checked) {
rows = this.getGroupSelections(index);
}
this.$selectItem.filter(filter).prop('checked', checked);
this.updateRows();
this.updateSelected();
if (checked) {
rows = this.getGroupSelections(index);
}
this.trigger(checked ? 'check-all' : 'uncheck-all', rows);
};
})(jQuery);

View File

@@ -0,0 +1,12 @@
{
"name": "Group By V2",
"version": "1.0.0",
"description": "Group the data by field",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by-v2",
"example": "",
"plugins": [],
"author": {
"name": "Knoxvillekm",
"image": "https://avatars3.githubusercontent.com/u/11072464"
}
}

View File

@@ -0,0 +1,53 @@
table.treetable tbody tr td {
cursor: default;
}
table.treetable span {
background-position: center left;
background-repeat: no-repeat;
padding: .2em 0 .2em 1.5em;
}
table.treetable tr.collapsed span.indenter a {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHlJREFUeNrcU1sNgDAQ6wgmcAM2MICGGlg1gJnNzWQcvwQGy1j4oUl/7tH0mpwzM7SgQyO+EZAUWh2MkkzSWhJwuRAlHYsJwEwyvs1gABDuzqoJcTw5qxaIJN0bgQRgIjnlmn1heSO5PE6Y2YXe+5Cr5+h++gs12AcAS6FS+7YOsj4AAAAASUVORK5CYII=);
padding-right: 12px;
}
table.treetable tr.expanded span.indenter a {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHFJREFUeNpi/P//PwMlgImBQsA44C6gvhfa29v3MzAwOODRc6CystIRbxi0t7fjDJjKykpGYrwwi1hxnLHQ3t7+jIGBQRJJ6HllZaUUKYEYRYBPOB0gBShKwKGA////48VtbW3/8clTnBIH3gCKkzJgAGvBX0dDm0sCAAAAAElFTkSuQmCC);
padding-right: 12px;
}
table.treetable tr.branch {
background-color: #f9f9f9;
}
table.treetable tr.selected {
background-color: #3875d7;
color: #fff;
}
table.treetable tr span.indenter a {
outline: none; /* Expander shows outline after upgrading to 3.0 (#141) */
}
table.treetable tr.collapsed.selected span.indenter a {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==);
}
table.treetable tr.expanded.selected span.indenter a {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=);
}
table.treetable tr.accept {
background-color: #a3bce4;
color: #fff
}
table.treetable tr.collapsed.accept td span.indenter a {
background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==);
}
table.treetable tr.expanded.accept td span.indenter a {
background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=);
}

View File

@@ -0,0 +1,243 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.1.0
*/
!function ($) {
'use strict';
var originalRowAttr,
dataTTId = 'data-tt-id',
dataTTParentId = 'data-tt-parent-id',
obj = {},
parentId = undefined;
var getParentRowId = function (that, id) {
var parentRows = that.$body.find('tr').not('[' + 'data-tt-parent-id]');
for (var i = 0; i < parentRows.length; i++) {
if (i === id) {
return $(parentRows[i]).attr('data-tt-id');
}
}
return undefined;
};
var sumData = function (that, data) {
var sumRow = {};
$.each(data, function (i, row) {
if (!row.IsParent) {
for (var prop in row) {
if (!isNaN(parseFloat(row[prop]))) {
if (that.columns[that.fieldsColumnsIndex[prop]].groupBySumGroup) {
if (sumRow[prop] === undefined) {
sumRow[prop] = 0;
}
sumRow[prop] += +row[prop];
}
}
}
}
});
return sumRow;
};
var rowAttr = function (row, index) {
//Call the User Defined Function
originalRowAttr.apply([row, index]);
obj[dataTTId.toString()] = index;
if (!row.IsParent) {
obj[dataTTParentId.toString()] = parentId === undefined ? index : parentId;
} else {
parentId = index;
delete obj[dataTTParentId.toString()];
}
return obj;
};
var setObjectKeys = function () {
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Object.keys = function (o) {
if (o !== Object(o)) {
throw new TypeError('Object.keys called on a non-object');
}
var k = [],
p;
for (p in o) {
if (Object.prototype.hasOwnProperty.call(o, p)) {
k.push(p);
}
}
return k;
}
};
var getDataArrayFromItem = function (that, item) {
var itemDataArray = [];
for (var i = 0; i < that.options.groupByField.length; i++) {
itemDataArray.push(item[that.options.groupByField[i]]);
}
return itemDataArray;
};
var getNewRow = function (that, result, index) {
var newRow = {};
for (var i = 0; i < that.options.groupByField.length; i++) {
newRow[that.options.groupByField[i].toString()] = result[index][0][that.options.groupByField[i]];
}
newRow.IsParent = true;
return newRow;
};
var groupBy = function (array, f) {
var groups = {};
$.each(array, function (i, o) {
var group = JSON.stringify(f(o));
groups[group] = groups[group] || [];
groups[group].push(o);
});
return Object.keys(groups).map(function (group) {
return groups[group];
});
};
var makeGrouped = function (that, data) {
var newData = [],
sumRow = {};
var result = groupBy(data, function (item) {
return getDataArrayFromItem(that, item);
});
for (var i = 0; i < result.length; i++) {
result[i].unshift(getNewRow(that, result, i));
if (that.options.groupBySumGroup) {
sumRow = sumData(that, result[i]);
if (!$.isEmptyObject(sumRow)) {
result[i].push(sumRow);
}
}
}
newData = newData.concat.apply(newData, result);
if (!that.options.loaded && newData.length > 0) {
that.options.loaded = true;
that.options.originalData = that.options.data;
that.options.data = newData;
}
return newData;
};
$.extend($.fn.bootstrapTable.defaults, {
groupBy: false,
groupByField: [],
groupBySumGroup: false,
groupByInitExpanded: undefined, //node, 'all'
//internal variables
loaded: false,
originalData: undefined
});
$.fn.bootstrapTable.methods.push('collapseAll', 'expandAll', 'refreshGroupByField');
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
groupBySumGroup: false
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initData = BootstrapTable.prototype.initData;
BootstrapTable.prototype.init = function () {
//Temporal validation
if (!this.options.sortName) {
if ((this.options.groupBy) && (this.options.groupByField.length > 0)) {
var that = this;
// Compatibility: IE < 9 and old browsers
if (!Object.keys) {
$.fn.bootstrapTable.utils.objectKeys();
}
//Make sure that the internal variables are set correctly
this.options.loaded = false;
this.options.originalData = undefined;
originalRowAttr = this.options.rowAttributes;
this.options.rowAttributes = rowAttr;
this.$el.off('post-body.bs.table').on('post-body.bs.table', function () {
that.$el.treetable({
expandable: true,
onNodeExpand: function () {
if (that.options.height) {
that.resetHeader();
}
},
onNodeCollapse: function () {
if (that.options.height) {
that.resetHeader();
}
}
}, true);
if (that.options.groupByInitExpanded !== undefined) {
if (typeof that.options.groupByInitExpanded === 'number') {
that.expandNode(that.options.groupByInitExpanded);
} else if (that.options.groupByInitExpanded.toLowerCase() === 'all') {
that.expandAll();
}
}
});
}
}
_init.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.initData = function (data, type) {
//Temporal validation
if (!this.options.sortName) {
if ((this.options.groupBy) && (this.options.groupByField.length > 0)) {
this.options.groupByField = typeof this.options.groupByField === 'string' ?
this.options.groupByField.replace('[', '').replace(']', '')
.replace(/ /g, '').toLowerCase().split(',') : this.options.groupByField;
data = makeGrouped(this, data ? data : this.options.data);
}
}
_initData.apply(this, [data, type]);
};
BootstrapTable.prototype.expandAll = function () {
this.$el.treetable('expandAll');
};
BootstrapTable.prototype.collapseAll = function () {
this.$el.treetable('collapseAll');
};
BootstrapTable.prototype.expandNode = function (id) {
id = getParentRowId(this, id);
if (id !== undefined) {
this.$el.treetable('expandNode', id);
}
};
BootstrapTable.prototype.refreshGroupByField = function (groupByFields) {
if (!$.fn.bootstrapTable.utils.compareObjects(this.options.groupByField, groupByFields)) {
this.options.groupByField = groupByFields;
this.load(this.options.originalData);
}
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Group By",
"version": "1.1.0",
"description": "Plugin to group the data by fields.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by",
"example": "#",
"plugins": [{
"name": "bootstrap-table-group-by",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,35 @@
/**
* @author: Jewway
* @version: v1.0.0
*/
!function ($) {
'use strict';
var BootstrapTable = $.fn.bootstrapTable.Constructor;
BootstrapTable.prototype.changeTitle = function (locale) {
$.each(this.options.columns, function (idx, columnList) {
$.each(columnList, function (idx, column) {
if (column.field) {
column.title = locale[column.field];
}
});
});
this.initHeader();
this.initBody();
this.initToolbar();
};
BootstrapTable.prototype.changeLocale = function (localeId) {
this.options.locale = localeId;
this.initLocale();
this.initPagination();
this.initBody();
this.initToolbar();
};
$.fn.bootstrapTable.methods.push('changeTitle');
$.fn.bootstrapTable.methods.push('changeLocale');
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "i18n Enhance",
"version": "1.0.0",
"description": "Plugin to add i18n API in order to change column's title and table locale.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/i18n-enhance.html",
"plugins": [{
"name": "bootstrap-table-i18n-enhance",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance"
}],
"author": {
"name": "Jewway",
"image": "https://avatars0.githubusercontent.com/u/3501899"
}
}

View File

@@ -0,0 +1,80 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.0.0
*
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
!function ($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
keyEvents: false
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init;
BootstrapTable.prototype.init = function () {
_init.apply(this, Array.prototype.slice.apply(arguments));
this.initKeyEvents();
};
BootstrapTable.prototype.initKeyEvents = function () {
if (this.options.keyEvents) {
var that = this;
$(document).off('keydown').on('keydown', function (e) {
var $search = that.$toolbar.find('.search input'),
$refresh = that.$toolbar.find('button[name="refresh"]'),
$toggle = that.$toolbar.find('button[name="toggle"]'),
$paginationSwitch = that.$toolbar.find('button[name="paginationSwitch"]');
if (document.activeElement === $search.get(0) || !$.contains(document.activeElement ,that.$toolbar.get(0))) {
return true;
}
switch (e.keyCode) {
case 83: //s
if (!that.options.search) {
return;
}
$search.focus();
return false;
case 82: //r
if (!that.options.showRefresh) {
return;
}
$refresh.click();
return false;
case 84: //t
if (!that.options.showToggle) {
return;
}
$toggle.click();
return false;
case 80: //p
if (!that.options.showPaginationSwitch) {
return;
}
$paginationSwitch.click();
return false;
case 37: // left
if (!that.options.pagination) {
return;
}
that.prevPage();
return false;
case 39: // right
if (!that.options.pagination) {
return;
}
that.nextPage();
return;
}
});
}
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Key Events",
"version": "1.0.0",
"description": "Plugin to support the key events in the bootstrap table.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/key-events.html",
"plugins": [{
"name": "bootstrap-table-key-events",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,136 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.1.0
*/
!function ($) {
'use strict';
var showHideColumns = function (that, checked) {
if (that.options.columnsHidden.length > 0 ) {
$.each(that.columns, function (i, column) {
if (that.options.columnsHidden.indexOf(column.field) !== -1) {
if (column.visible !== checked) {
that.toggleColumn(that.fieldsColumnsIndex[column.field], checked, true);
}
}
});
}
};
var resetView = function (that) {
if (that.options.height || that.options.showFooter) {
setTimeout(function(){
that.resetView.call(that);
}, 1);
}
};
var changeView = function (that, width, height) {
if (that.options.minHeight) {
if ((width <= that.options.minWidth) && (height <= that.options.minHeight)) {
conditionCardView(that);
} else if ((width > that.options.minWidth) && (height > that.options.minHeight)) {
conditionFullView(that);
}
} else {
if (width <= that.options.minWidth) {
conditionCardView(that);
} else if (width > that.options.minWidth) {
conditionFullView(that);
}
}
resetView(that);
};
var conditionCardView = function (that) {
changeTableView(that, false);
showHideColumns(that, false);
};
var conditionFullView = function (that) {
changeTableView(that, true);
showHideColumns(that, true);
};
var changeTableView = function (that, cardViewState) {
that.options.cardView = cardViewState;
that.toggleView();
};
var debounce = function(func,wait) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
func.apply(context,args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
$.extend($.fn.bootstrapTable.defaults, {
mobileResponsive: false,
minWidth: 562,
minHeight: undefined,
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
checkOnInit: true,
columnsHidden: []
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init;
BootstrapTable.prototype.init = function () {
_init.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.mobileResponsive) {
return;
}
if (!this.options.minWidth) {
return;
}
if (this.options.minWidth < 100 && this.options.resizable) {
console.log("The minWidth when the resizable extension is active should be greater or equal than 100");
this.options.minWidth = 100;
}
var that = this,
old = {
width: $(window).width(),
height: $(window).height()
};
$(window).on('resize orientationchange',debounce(function (evt) {
// reset view if height has only changed by at least the threshold.
var height = $(this).height(),
width = $(this).width();
if (Math.abs(old.height - height) > that.options.heightThreshold || old.width != width) {
changeView(that, width, height);
old = {
width: width,
height: height
};
}
},200));
if (this.options.checkOnInit) {
var height = $(window).height(),
width = $(window).width();
changeView(this, width, height);
old = {
width: width,
height: height
};
}
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Mobile",
"version": "1.1.0",
"description": "Plugin to support the responsive feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/mobile.html",
"plugins": [{
"name": "bootstrap-table-mobile",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,88 @@
/**
* @author Homer Glascock <HopGlascock@gmail.com>
* @version: v1.0.0
*/
!function ($) {
"use strict";
var sprintf = $.fn.bootstrapTable.utils.sprintf;
var reInit = function (self) {
self.initHeader();
self.initSearch();
self.initPagination();
self.initBody();
};
$.extend($.fn.bootstrapTable.defaults, {
showToggleBtn: false,
multiToggleDefaults: [], //column names go here
});
$.fn.bootstrapTable.methods.push('hideAllColumns', 'showAllColumns');
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initToolbar = BootstrapTable.prototype.initToolbar;
BootstrapTable.prototype.initToolbar = function () {
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
var that = this,
$btnGroup = this.$toolbar.find('>.btn-group');
if (typeof this.options.multiToggleDefaults === 'string') {
this.options.multiToggleDefaults = JSON.parse(this.options.multiToggleDefaults);
}
if (this.options.showToggleBtn && this.options.showColumns) {
var showbtn = "<button class='btn btn-default hidden' id='showAllBtn'><span class='glyphicon glyphicon-resize-full icon-zoom-in'></span></button>",
hidebtn = "<button class='btn btn-default' id='hideAllBtn'><span class='glyphicon glyphicon-resize-small icon-zoom-out'></span></button>";
$btnGroup.append(showbtn + hidebtn);
$btnGroup.find('#showAllBtn').click(function () { that.showAllColumns();
$btnGroup.find('#hideAllBtn').toggleClass('hidden');
$btnGroup.find('#showAllBtn').toggleClass('hidden');
});
$btnGroup.find('#hideAllBtn').click(function () { that.hideAllColumns();
$btnGroup.find('#hideAllBtn').toggleClass('hidden');
$btnGroup.find('#showAllBtn').toggleClass('hidden');
});
}
};
BootstrapTable.prototype.hideAllColumns = function () {
var that = this,
defaults = that.options.multiToggleDefaults;
$.each(this.columns, function (index, column) {
//if its one of the defaults dont touch it
if (defaults.indexOf(column.field) == -1 && column.switchable) {
column.visible = false;
var $items = that.$toolbar.find('.keep-open input').prop('disabled', false);
$items.filter(sprintf('[value="%s"]', index)).prop('checked', false);
}
});
reInit(that);
};
BootstrapTable.prototype.showAllColumns = function () {
var that = this;
$.each(this.columns, function (index, column) {
if (column.switchable) {
column.visible = true;
}
var $items = that.$toolbar.find('.keep-open input').prop('disabled', false);
$items.filter(sprintf('[value="%s"]', index)).prop('checked', true);
});
reInit(that);
that.toggleColumn(0, that.columns[0].visible, false);
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Multi Column Toggle",
"version": "1.0.0",
"description": "Allows hiding and showing of multiple columns at once.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multi-column-toggle",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/multi-column-toggle.html",
"plugins": [{
"name": "multi-column-toggle",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multi-column-toggle"
}],
"author": {
"name": "Homer Glascock",
"image": "https://avatars1.githubusercontent.com/u/5546710"
}
}

View File

@@ -0,0 +1,71 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.0.0
*/
!function ($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
multipleSearch: false,
delimeter: " "
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initSearch = BootstrapTable.prototype.initSearch;
BootstrapTable.prototype.initSearch = function () {
if (this.options.multipleSearch) {
if (this.searchText === undefined) {
return;
}
var strArray = this.searchText.split(this.options.delimeter),
that = this,
f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns,
dataFiltered = [];
if (strArray.length === 1) {
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
} else {
for (var i = 0; i < strArray.length; i++) {
var str = strArray[i].trim();
dataFiltered = str ? $.grep(dataFiltered.length === 0 ? this.options.data : dataFiltered, function (item, i) {
for (var key in item) {
key = $.isNumeric(key) ? parseInt(key, 10) : key;
var value = item[key],
column = that.columns[that.fieldsColumnsIndex[key]],
j = $.inArray(key, that.header.fields);
// Fix #142: search use formated data
if (column && column.searchFormatter) {
value = $.fn.bootstrapTable.utils.calculateObjectValue(column,
that.header.formatters[j], [value, item, i], value);
}
var index = $.inArray(key, that.header.fields);
if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) {
if (that.options.strictSearch) {
if ((value + '').toLowerCase() === str) {
return true;
}
} else {
if ((value + '').toLowerCase().indexOf(str) !== -1) {
return true;
}
}
}
}
return false;
}) : this.data;
}
this.data = dataFiltered;
}
} else {
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
}
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Multiple Search",
"version": "1.0.0",
"description": "Plugin to support the multiple search.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-search",
"example": "#",
"plugins": [{
"name": "bootstrap-table-multiple-search",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-search"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,17 @@
.multiple-select-row-selected {
background: lightBlue
}
.table tbody tr:hover td,
.table tbody tr:hover th {
background-color: transparent;
}
.table-striped tbody tr:nth-child(odd):hover td {
background-color: #F9F9F9;
}
.fixed-table-container tbody .selected td {
background: lightBlue;
}

View File

@@ -0,0 +1,127 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.0.0
*/
!function ($) {
'use strict';
document.onselectstart = function() {
return false;
};
var getTableObjectFromCurrentTarget = function (currentTarget) {
currentTarget = $(currentTarget);
return currentTarget.is("table") ? currentTarget : currentTarget.parents().find(".table");
};
var getRow = function (target) {
target = $(target);
return target.parent().parent();
};
var onRowClick = function (e) {
var that = getTableObjectFromCurrentTarget(e.currentTarget);
if (window.event.ctrlKey) {
toggleRow(e.currentTarget, that, false, false);
}
if (window.event.button === 0) {
if (!window.event.ctrlKey && !window.event.shiftKey) {
clearAll(that);
toggleRow(e.currentTarget, that, false, false);
}
if (window.event.shiftKey) {
selectRowsBetweenIndexes([that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow.rowIndex, e.currentTarget.rowIndex], that)
}
}
};
var onCheckboxChange = function (e) {
var that = getTableObjectFromCurrentTarget(e.currentTarget);
clearAll(that);
toggleRow(getRow(e.currentTarget), that, false, false);
};
var toggleRow = function (row, that, clearAll, useShift) {
if (clearAll) {
row = $(row);
that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow = undefined;
row.removeClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
that.bootstrapTable("uncheck", row.data("index"));
} else {
that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow = row;
row = $(row);
if (useShift) {
row.addClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
that.bootstrapTable("check", row.data("index"));
} else {
if(row.hasClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass)) {
row.removeClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass)
that.bootstrapTable("uncheck", row.data("index"));
} else {
row.addClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
that.bootstrapTable("check", row.data("index"));
}
}
}
};
var selectRowsBetweenIndexes = function (indexes, that) {
indexes.sort(function(a, b) {
return a - b;
});
for (var i = indexes[0]; i <= indexes[1]; i++) {
toggleRow(that.bootstrapTable("getOptions").multipleSelectRowRows[i-1], that, false, true);
}
};
var clearAll = function (that) {
for (var i = 0; i < that.bootstrapTable("getOptions").multipleSelectRowRows.length; i++) {
toggleRow(that.bootstrapTable("getOptions").multipleSelectRowRows[i], that, true, false);
}
};
$.extend($.fn.bootstrapTable.defaults, {
multipleSelectRow: false,
multipleSelectRowCssClass: 'multiple-select-row-selected',
//internal variables used by the extension
multipleSelectRowLastSelectedRow: undefined,
multipleSelectRowRows: []
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initBody = BootstrapTable.prototype.initBody;
BootstrapTable.prototype.init = function () {
if (this.options.multipleSelectRow) {
var that = this;
//Make sure that the internal variables have the correct value
this.options.multipleSelectRowLastSelectedRow = undefined;
this.options.multipleSelectRowRows = [];
this.$el.on("post-body.bs.table", function (e) {
setTimeout(function () {
that.options.multipleSelectRowRows = that.$body.children();
that.options.multipleSelectRowRows.click(onRowClick);
that.options.multipleSelectRowRows.find("input[type=checkbox]").change(onCheckboxChange);
}, 1);
});
}
_init.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.clearAllMultipleSelectionRow = function () {
clearAll(this);
};
$.fn.bootstrapTable.methods.push('clearAllMultipleSelectionRow');
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Multiple Selection Row",
"version": "1.0.0",
"description": "Plugin to enable the multiple selection row. You can use the ctrl+click to select one row or use ctrl+shift+click to select a range of rows.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-selection-row",
"example": "",
"plugins": [{
"name": "bootstrap-table-multiple-selection-row",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-selection-row"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,412 @@
/**
* @author Nadim Basalamah <dimbslmh@gmail.com>
* @version: v1.1.0
* https://github.com/dimbslmh/bootstrap-table/tree/master/src/extensions/multiple-sort/bootstrap-table-multiple-sort.js
* Modification: ErwannNevou <https://github.com/ErwannNevou>
*/
(function($) {
'use strict';
var isSingleSort = false;
var showSortModal = function(that) {
var _selector = that.sortModalSelector,
_id = '#' + _selector;
if (!$(_id).hasClass("modal")) {
var sModal = ' <div class="modal fade" id="' + _selector + '" tabindex="-1" role="dialog" aria-labelledby="' + _selector + 'Label" aria-hidden="true">';
sModal += ' <div class="modal-dialog">';
sModal += ' <div class="modal-content">';
sModal += ' <div class="modal-header">';
sModal += ' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>';
sModal += ' <h4 class="modal-title" id="' + _selector + 'Label">' + that.options.formatMultipleSort() + '</h4>';
sModal += ' </div>';
sModal += ' <div class="modal-body">';
sModal += ' <div class="bootstrap-table">';
sModal += ' <div class="fixed-table-toolbar">';
sModal += ' <div class="bars">';
sModal += ' <div id="toolbar">';
sModal += ' <button id="add" type="button" class="btn btn-default"><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.plus + '"></i> ' + that.options.formatAddLevel() + '</button>';
sModal += ' <button id="delete" type="button" class="btn btn-default" disabled><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.minus + '"></i> ' + that.options.formatDeleteLevel() + '</button>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' <div class="fixed-table-container">';
sModal += ' <table id="multi-sort" class="table">';
sModal += ' <thead>';
sModal += ' <tr>';
sModal += ' <th></th>';
sModal += ' <th><div class="th-inner">' + that.options.formatColumn() + '</div></th>';
sModal += ' <th><div class="th-inner">' + that.options.formatOrder() + '</div></th>';
sModal += ' </tr>';
sModal += ' </thead>';
sModal += ' <tbody></tbody>';
sModal += ' </table>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' <div class="modal-footer">';
sModal += ' <button type="button" class="btn btn-default" data-dismiss="modal">' + that.options.formatCancel() + '</button>';
sModal += ' <button type="button" class="btn btn-primary">' + that.options.formatSort() + '</button>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' </div>';
sModal += ' </div>';
$('body').append($(sModal));
that.$sortModal = $(_id);
var $rows = that.$sortModal.find('tbody > tr');
that.$sortModal.off('click', '#add').on('click', '#add', function() {
var total = that.$sortModal.find('.multi-sort-name:first option').length,
current = that.$sortModal.find('tbody tr').length;
if (current < total) {
current++;
that.addLevel();
that.setButtonStates();
}
});
that.$sortModal.off('click', '#delete').on('click', '#delete', function() {
var total = that.$sortModal.find('.multi-sort-name:first option').length,
current = that.$sortModal.find('tbody tr').length;
if (current > 1 && current <= total) {
current--;
that.$sortModal.find('tbody tr:last').remove();
that.setButtonStates();
}
});
that.$sortModal.off('click', '.btn-primary').on('click', '.btn-primary', function() {
var $rows = that.$sortModal.find('tbody > tr'),
$alert = that.$sortModal.find('div.alert'),
fields = [],
results = [];
that.options.sortPriority = $.map($rows, function(row) {
var $row = $(row),
name = $row.find('.multi-sort-name').val(),
order = $row.find('.multi-sort-order').val();
fields.push(name);
return {
sortName: name,
sortOrder: order
};
});
var sorted_fields = fields.sort();
for (var i = 0; i < fields.length - 1; i++) {
if (sorted_fields[i + 1] == sorted_fields[i]) {
results.push(sorted_fields[i]);
}
}
if (results.length > 0) {
if ($alert.length === 0) {
$alert = '<div class="alert alert-danger" role="alert"><strong>' + that.options.formatDuplicateAlertTitle() + '</strong> ' + that.options.formatDuplicateAlertDescription() + '</div>';
$($alert).insertBefore(that.$sortModal.find('.bars'));
}
} else {
if ($alert.length === 1) {
$($alert).remove();
}
that.$sortModal.modal('hide');
that.options.sortName = '';
if (that.options.sidePagination === 'server') {
var t = that.options.queryParams;
that.options.queryParams = function(params) {
params.multiSort = that.options.sortPriority;
return t(params);
};
isSingleSort=false;
that.initServer(that.options.silentSort);
return;
}
that.onMultipleSort();
}
});
if (that.options.sortPriority === null || that.options.sortPriority.length === 0) {
if (that.options.sortName) {
that.options.sortPriority = [{
sortName: that.options.sortName,
sortOrder: that.options.sortOrder
}];
}
}
if (that.options.sortPriority !== null && that.options.sortPriority.length > 0) {
if ($rows.length < that.options.sortPriority.length && typeof that.options.sortPriority === 'object') {
for (var i = 0; i < that.options.sortPriority.length; i++) {
that.addLevel(i, that.options.sortPriority[i]);
}
}
} else {
that.addLevel(0);
}
that.setButtonStates();
}
};
$.fn.bootstrapTable.methods.push('multipleSort');
$.extend($.fn.bootstrapTable.defaults, {
showMultiSort: false,
showMultiSortButton: true,
sortPriority: null,
onMultipleSort: function() {
return false;
}
});
$.extend($.fn.bootstrapTable.defaults.icons, {
sort: 'glyphicon-sort',
plus: 'glyphicon-plus',
minus: 'glyphicon-minus'
});
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'multiple-sort.bs.table': 'onMultipleSort'
});
$.extend($.fn.bootstrapTable.locales, {
formatMultipleSort: function() {
return 'Multiple Sort';
},
formatAddLevel: function() {
return 'Add Level';
},
formatDeleteLevel: function() {
return 'Delete Level';
},
formatColumn: function() {
return 'Column';
},
formatOrder: function() {
return 'Order';
},
formatSortBy: function() {
return 'Sort by';
},
formatThenBy: function() {
return 'Then by';
},
formatSort: function() {
return 'Sort';
},
formatCancel: function() {
return 'Cancel';
},
formatDuplicateAlertTitle: function() {
return 'Duplicate(s) detected!';
},
formatDuplicateAlertDescription: function() {
return 'Please remove or change any duplicate column.';
},
formatSortOrders: function() {
return {
asc: 'Ascending',
desc: 'Descending'
};
}
});
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initToolbar = BootstrapTable.prototype.initToolbar;
BootstrapTable.prototype.initToolbar = function() {
this.showToolbar = this.showToolbar || this.options.showMultiSort;
var that = this,
sortModalSelector = 'sortModal_' + this.$el.attr('id'),
sortModalId = '#' + sortModalSelector;
this.$sortModal = $(sortModalId);
this.sortModalSelector = sortModalSelector;
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
if (that.options.sidePagination === 'server' && !isSingleSort && that.options.sortPriority !== null){
var t = that.options.queryParams;
that.options.queryParams = function(params) {
params.multiSort = that.options.sortPriority;
return t(params);
};
}
if (this.options.showMultiSort) {
var $btnGroup = this.$toolbar.find('>.btn-group').first(),
$multiSortBtn = this.$toolbar.find('div.multi-sort');
if (!$multiSortBtn.length && this.options.showMultiSortButton) {
$multiSortBtn = ' <button class="multi-sort btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" data-toggle="modal" data-target="' + sortModalId + '" title="' + this.options.formatMultipleSort() + '">';
$multiSortBtn += ' <i class="' + this.options.iconsPrefix + ' ' + this.options.icons.sort + '"></i>';
$multiSortBtn += '</button>';
$btnGroup.append($multiSortBtn);
showSortModal(that);
}
this.$el.on('sort.bs.table', function() {
isSingleSort = true;
});
this.$el.on('multiple-sort.bs.table', function() {
isSingleSort = false;
});
this.$el.on('load-success.bs.table', function() {
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
that.onMultipleSort();
}
});
this.$el.on('column-switch.bs.table', function(field, checked) {
for (var i = 0; i < that.options.sortPriority.length; i++) {
if (that.options.sortPriority[i].sortName === checked) {
that.options.sortPriority.splice(i, 1);
}
}
that.assignSortableArrows();
that.$sortModal.remove();
showSortModal(that);
});
this.$el.on('reset-view.bs.table', function() {
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object') {
that.assignSortableArrows();
}
});
}
};
BootstrapTable.prototype.multipleSort = function() {
var that = this;
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
that.onMultipleSort();
}
};
BootstrapTable.prototype.onMultipleSort = function() {
var that = this;
var cmp = function(x, y) {
return x > y ? 1 : x < y ? -1 : 0;
};
var arrayCmp = function(a, b) {
var arr1 = [],
arr2 = [];
for (var i = 0; i < that.options.sortPriority.length; i++) {
var order = that.options.sortPriority[i].sortOrder === 'desc' ? -1 : 1,
aa = a[that.options.sortPriority[i].sortName],
bb = b[that.options.sortPriority[i].sortName];
if (aa === undefined || aa === null) {
aa = '';
}
if (bb === undefined || bb === null) {
bb = '';
}
if ($.isNumeric(aa) && $.isNumeric(bb)) {
aa = parseFloat(aa);
bb = parseFloat(bb);
}
if (typeof aa !== 'string') {
aa = aa.toString();
}
arr1.push(
order * cmp(aa, bb));
arr2.push(
order * cmp(bb, aa));
}
return cmp(arr1, arr2);
};
this.data.sort(function(a, b) {
return arrayCmp(a, b);
});
this.initBody();
this.assignSortableArrows();
this.trigger('multiple-sort');
};
BootstrapTable.prototype.addLevel = function(index, sortPriority) {
var text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy();
this.$sortModal.find('tbody')
.append($('<tr>')
.append($('<td>').text(text))
.append($('<td>').append($('<select class="form-control multi-sort-name">')))
.append($('<td>').append($('<select class="form-control multi-sort-order">')))
);
var $multiSortName = this.$sortModal.find('.multi-sort-name').last(),
$multiSortOrder = this.$sortModal.find('.multi-sort-order').last();
$.each(this.columns, function(i, column) {
if (column.sortable === false || column.visible === false) {
return true;
}
$multiSortName.append('<option value="' + column.field + '">' + column.title + '</option>');
});
$.each(this.options.formatSortOrders(), function(value, order) {
$multiSortOrder.append('<option value="' + value + '">' + order + '</option>');
});
if (sortPriority !== undefined) {
$multiSortName.find('option[value="' + sortPriority.sortName + '"]').attr("selected", true);
$multiSortOrder.find('option[value="' + sortPriority.sortOrder + '"]').attr("selected", true);
}
};
BootstrapTable.prototype.assignSortableArrows = function() {
var that = this,
headers = that.$header.find('th');
for (var i = 0; i < headers.length; i++) {
for (var c = 0; c < that.options.sortPriority.length; c++) {
if ($(headers[i]).data('field') === that.options.sortPriority[c].sortName) {
$(headers[i]).find('.sortable').removeClass('desc asc').addClass(that.options.sortPriority[c].sortOrder);
}
}
}
};
BootstrapTable.prototype.setButtonStates = function() {
var total = this.$sortModal.find('.multi-sort-name:first option').length,
current = this.$sortModal.find('tbody tr').length;
if (current == total) {
this.$sortModal.find('#add').attr('disabled', 'disabled');
}
if (current > 1) {
this.$sortModal.find('#delete').removeAttr('disabled');
}
if (current < total) {
this.$sortModal.find('#add').removeAttr('disabled');
}
if (current == 1) {
this.$sortModal.find('#delete').attr('disabled', 'disabled');
}
};
})(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Multiple Sort",
"version": "1.1.0",
"description": "Plugin to support the multiple sort.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort",
"example": "#",
"plugins": [{
"name": "bootstrap-table-multiple-sort",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort"
}],
"author": {
"name": "dimbslmh",
"image": "https://avatars1.githubusercontent.com/u/745635"
}
}

View File

@@ -0,0 +1,67 @@
/**
* @author: Brian Huisman
* @webSite: http://www.greywyvern.com
* @version: v1.0.0
* JS functions to allow natural sorting on bootstrap-table columns
* add data-sorter="alphanum" or data-sorter="numericOnly" to any th
*
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
* @update Duane May
*/
function alphanum(a, b) {
function chunkify(t) {
var tz = [],
x = 0,
y = -1,
n = 0,
i,
j;
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
var m = (i === 46 || (i >= 48 && i <= 57));
if (m !== n) {
tz[++y] = "";
n = m;
}
tz[y] += j;
}
return tz;
}
function stringfy(v) {
if (typeof(v) === "number") {
v = "" + v;
}
if (!v) {
v = "";
}
return v;
}
var aa = chunkify(stringfy(a));
var bb = chunkify(stringfy(b));
for (x = 0; aa[x] && bb[x]; x++) {
if (aa[x] !== bb[x]) {
var c = Number(aa[x]),
d = Number(bb[x]);
if (c == aa[x] && d == bb[x]) {
return c - d;
} else {
return (aa[x] > bb[x]) ? 1 : -1;
}
}
}
return aa.length - bb.length;
}
function numericOnly(a, b) {
function stripNonNumber(s) {
s = s.replace(new RegExp(/[^0-9]/g), "");
return parseInt(s, 10);
}
return stripNonNumber(a) - stripNonNumber(b);
}

View File

@@ -0,0 +1,17 @@
{
"name": "Natural Sorting",
"version": "1.0.0",
"description": "Plugin to support the natural sorting.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/natural-sorting",
"example": "#",
"plugins": [{
"name": "bootstrap-table-natural-sorting",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/natural-sorting"
}],
"author": {
"name": "GreyWyvern",
"image": "https://avatars1.githubusercontent.com/u/137631"
}
}

View File

@@ -0,0 +1,8 @@
.jumpto input {
height: 31px;
width: 50px;
margin-left: 5px;
margin-right: 5px;
text-align: center;
display: inline-block;
}

View File

@@ -0,0 +1,50 @@
/**
* @author Jay <jwang@dizsoft.com>
*/
(function ($) {
'use strict';
var sprintf = $.fn.bootstrapTable.utils.sprintf;
$.extend($.fn.bootstrapTable.defaults, {
showJumpto: false,
exportOptions: {}
});
$.extend($.fn.bootstrapTable.locales, {
formatJumpto: function () {
return 'GO';
}
});
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initPagination = BootstrapTable.prototype.initPagination;
BootstrapTable.prototype.initPagination = function () {
_initPagination.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.showJumpto) {
var that = this,
$pageGroup = this.$pagination.find('ul.pagination'),
$jumpto = $pageGroup.find('li.jumpto');
if (!$jumpto.length) {
$jumpto = $([
'<li class="jumpto">',
'<input type="text" class="form-control">',
'<button class="btn' +
sprintf(' btn-%s', this.options.buttonsClass) +
sprintf(' btn-%s', this.options.iconSize) +
'" title="' + this.options.formatJumpto() + '" ' +
' type="button">'+this.options.formatJumpto(),
'</button>',
'</li>'].join('')).appendTo($pageGroup);
$jumpto.find('button').click(function () {
that.selectPage(parseInt($jumpto.find('input').val()));
});
}
}
};
})(jQuery);

View File

@@ -0,0 +1,21 @@
(The MIT License)
Copyright (c) 2019 doug-the-guy <badlydrawnsun@yahoo.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,92 @@
# Bootstrap Table Pipelining
Use Plugin: [bootstrap-table-pipeline]
This plugin enables client side data caching for server side requests which will
eliminate the need to issue a new request every page change. This will allow
for a performance balance for a large data set between returning all data at once
(client side paging) and a new server side request (server side paging).
There are two new options:
- usePipeline: enables this feature
- pipelineSize: the size of each cache window
The size of the pipeline must be evenly divisible by the current page size. This is
assured by rounding up to the nearest evenly divisible value. For example, if
the pipeline size is 4990 and the current page size is 25, then pipeline size will
be dynamically set to 5000.
The cache windows are computed based on the pipeline size and the total number of rows
returned by the server side query. For example, with pipeline size 500 and total rows
1300, the cache windows will be:
[{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
**MUST** return only the data in the requested cache window **AND** the total number of rows.
To wit, the server side code must use the offset and limit parameters to prepare the response
data.
On a page change, the new offset is checked if it is within the current cache window. If so,
the requested page data is returned from the cached data set. Otherwise, a new server side
request will be issued for the new cache window.
The current cached data is only invalidated on these events:
- sorting
- searching
- page size change
- page change moves into a new cache window
There are two new events:
- cached-data-hit.bs.table: issued when cached data is used on a page change
- cached-data-reset.bs.table: issued when the cached data is invalidated and new server side request is issued
## Features
* Created with Bootstrap 4
## Usage
```
# assumed import of bootstrap and bootstrap-table assets
<script src="/path/to/bootstrap-table-pipeline.js"></script>
...
<table id="pipeline_table"
class="table table-striped"
data-method='post'
data-use-pipeline="true"
data-pipeline-size="5000"
data-pagination="true"
data-side-pagination="server"
data-page-size="50">
<thead><tr>
<th data-field="type" data-sortable="true">Type</th>
<th data-field="value" data-sortable="true">Value</th>
<th data-field="date" data-sortable="true">Date</th>
</tr></thead>
</table>
```
## Options
### usePipeline
* type: Boolean
* description: Set true to enable pipelining
* default: `false`
## pipelineSize
* type: Integer
* description: Size of each cache window. Must be greater than 0
* default: `1000`
## Events
### onCachedDataHit(cached-data-hit.bs.table)
* Fires when paging was able to use the locally cached data.
### onCachedDataReset(cached-data-reset.bs.table)
* Fires when the locally cached data needed to be reset (i.e. on sorting, searching, page size change or paged out of current cache window)

View File

@@ -0,0 +1,330 @@
/**
* @author doug-the-guy
* @version v1.0.0
*
* Boostrap Table Pipeline
* -----------------------
*
* This plugin enables client side data caching for server side requests which will
* eliminate the need to issue a new request every page change. This will allow
* for a performance balance for a large data set between returning all data at once
* (client side paging) and a new server side request (server side paging).
*
* There are two new options:
* - usePipeline: enables this feature
* - pipelineSize: the size of each cache window
*
* The size of the pipeline must be evenly divisible by the current page size. This is
* assured by rounding up to the nearest evenly divisible value. For example, if
* the pipeline size is 4990 and the current page size is 25, then pipeline size will
* be dynamically set to 5000.
*
* The cache windows are computed based on the pipeline size and the total number of rows
* returned by the server side query. For example, with pipeline size 500 and total rows
* 1300, the cache windows will be:
*
* [{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
*
* Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
* **MUST** return only the data in the requested cache window **AND** the total number of rows.
* To wit, the server side code must use the offset and limit parameters to prepare the response
* data.
*
* On a page change, the new offset is checked if it is within the current cache window. If so,
* the requested page data is returned from the cached data set. Otherwise, a new server side
* request will be issued for the new cache window.
*
* The current cached data is only invalidated on these events:
* * sorting
* * searching
* * page size change
* * page change moves into a new cache window
*
* There are two new events:
* - cached-data-hit.bs.table: issued when cached data is used on a page change
* - cached-data-reset.bs.table: issued when the cached data is invalidated and a
* new server side request is issued
*
**/
(function ($) {
'use strict';
var Utils = $.fn.bootstrapTable.utils;
$.extend($.fn.bootstrapTable.defaults, {
usePipeline: false,
pipelineSize: 1000,
onCachedDataHit: function(data) {
return false;
},
onCachedDataReset: function(data){
return false;
}
});
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'cached-data-hit.bs.table': 'onCachedDataHit',
'cached-data-reset.bs.table': 'onCachedDataReset'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initServer = BootstrapTable.prototype.initServer,
_onSearch = BootstrapTable.prototype.onSearch,
_onSort = BootstrapTable.prototype.onSort,
_onPageListChange = BootstrapTable.prototype.onPageListChange;
BootstrapTable.prototype.init = function () {
// needs to be called before initServer()
this.initPipeline();
_init.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.initPipeline = function() {
this.cacheRequestJSON = {};
this.cacheWindows = [];
this.currWindow = 0;
this.resetCache = true;
};
BootstrapTable.prototype.onSearch = function(event) {
/* force a cache reset on search */
if (this.options.usePipeline) {
this.resetCache = true;
}
_onSearch.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.onSort = function(event) {
/* force a cache reset on sort */
if (this.options.usePipeline) {
this.resetCache = true;
}
_onSort.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.onPageListChange = function (event) {
/* rebuild cache window on page size change */
var target = $(event.currentTarget);
var newPageSize = parseInt(target.text());
this.options.pipelineSize = this.calculatePipelineSize(this.options.pipelineSize, newPageSize);
this.resetCache = true;
_onPageListChange.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.calculatePipelineSize = function(pipelineSize, pageSize) {
/* calculate pipeline size by rounding up to the nearest value evenly divisible
* by the pageSize */
if(pageSize == 0) return 0;
return Math.ceil(pipelineSize/pageSize) * pageSize;
};
BootstrapTable.prototype.setCacheWindows = function() {
/* set cache windows based on the total number of rows returned by server side
* request and the pipelineSize */
this.cacheWindows = [];
var numWindows = this.options.totalRows / this.options.pipelineSize;
for(var i = 0; i <= numWindows; i++){
var b = i * this.options.pipelineSize;
this.cacheWindows[i] = {'lower': b, 'upper': b + this.options.pipelineSize - 1};
}
};
BootstrapTable.prototype.setCurrWindow = function(offset) {
/* set the current cache window index, based on where the current offset falls */
this.currWindow = 0;
for(var i = 0; i < this.cacheWindows.length; i++){
if(this.cacheWindows[i].lower <= offset && offset <= this.cacheWindows[i].upper){
this.currWindow = i;
break;
}
}
};
BootstrapTable.prototype.drawFromCache = function(offset, limit) {
/* draw rows from the cache using offset and limit */
var res = $.extend(true, {}, this.cacheRequestJSON);
var drawStart = offset - this.cacheWindows[this.currWindow].lower;
var drawEnd = drawStart + limit;
res.rows = res.rows.slice(drawStart, drawEnd);
return res;
};
BootstrapTable.prototype.initServer = function(silent, query, url){
/* determine if requested data is in cache (on paging) or if
* a new ajax request needs to be issued (sorting, searching, paging
* moving outside of cached data, page size change)
* initial version of this extension will entirely override base initServer
**/
var data = {};
var index = this.header.fields.indexOf(this.options.sortName);
var params = {
searchText: this.searchText,
sortName: this.options.sortName,
sortOrder: this.options.sortOrder
};
var request = null;
if (this.header.sortNames[index]) {
params.sortName = this.header.sortNames[index];
}
if (this.options.pagination && this.options.sidePagination === 'server') {
params.pageSize = this.options.pageSize === this.options.formatAllRows()
? this.options.totalRows : this.options.pageSize
params.pageNumber = this.options.pageNumber
}
if (!(url || this.options.url) && !this.options.ajax) {
return;
}
var useAjax = true;
if (this.options.queryParamsType === 'limit') {
params = {
searchText: params.searchText,
sortName: params.sortName,
sortOrder: params.sortOrder
}
if (this.options.pagination && this.options.sidePagination === 'server') {
params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;
params.offset = (this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize) * (this.options.pageNumber - 1);
if (this.options.usePipeline) {
// if cacheWindows is empty, this is the initial request
if(!this.cacheWindows.length){
useAjax = true;
params.drawOffset = params.offset;
// cache exists: determine if the page request is entirely within the current cached window
} else {
var w = this.cacheWindows[this.currWindow];
// case 1: reset cache but stay within current window (e.g. column sort)
// case 2: move outside of the current window (e.g. search or paging)
// since each cache window is aligned with the current page size
// checking if params.offset is outside the current window is sufficient.
// need to requery for preceding or succeeding cache window
// also handle case
if(this.resetCache || (params.offset < w.lower || params.offset > w.upper)){
useAjax = true;
this.setCurrWindow(params.offset);
// store the relative offset for drawing the page data afterwards
params.drawOffset = params.offset;
// now set params.offset to the lower bound of the new cache window
// the server will return that whole cache window
params.offset = this.cacheWindows[this.currWindow].lower;
// within current cache window
} else {
useAjax = false;
}
}
} else {
if (params.limit === 0) {
delete params.limit;
}
}
}
}
// force an ajax call - this is on search, sort or page size change
if (this.resetCache) {
useAjax = true;
this.resetCache = false;
}
if(this.options.usePipeline && useAjax) {
/* in this scenario limit is used on the server to get the cache window
* and drawLimit is used to get the page data afterwards */
params.drawLimit = params.limit;
params.limit = this.options.pipelineSize;
}
// cached results can be used
if(!useAjax) {
var res = this.drawFromCache(params.offset, params.limit);
this.load(res);
this.trigger('load-success', res);
this.trigger('cached-data-hit', res);
return;
}
// cached results can't be used
// continue base initServer code
if (!($.isEmptyObject(this.filterColumnsPartial))) {
params.filter = JSON.stringify(this.filterColumnsPartial, null);
}
data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data);
$.extend(data, query || {});
// false to stop request
if (data === false) {
return;
}
if (!silent) {
this.$tableLoading.show();
}
var self = this;
request = $.extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), {
type: this.options.method,
url: url || this.options.url,
data: this.options.contentType === 'application/json' && this.options.method === 'post'
? JSON.stringify(data) : data,
cache: this.options.cache,
contentType: this.options.contentType,
dataType: this.options.dataType,
success: function(res){
res = Utils.calculateObjectValue(self.options, self.options.responseHandler, [res], res);
// cache results if using pipelining
if(self.options.usePipeline){
// store entire request in cache
self.cacheRequestJSON = $.extend(true, {}, res);
// this gets set in load() also but needs to be set before
// setting cacheWindows
self.options.totalRows = res[self.options.totalField];
// if this is a search, potentially less results will be returned
// so cache windows need to be rebuilt. Otherwise it
// will come out the same
self.setCacheWindows();
self.setCurrWindow(params.drawOffset);
// just load data for the page
res = self.drawFromCache(params.drawOffset, params.drawLimit);
self.trigger('cached-data-reset', res);
}
self.load(res);
self.trigger('load-success', res);
if (!silent) self.$tableLoading.hide();
},
error: function(res){
var data = [];
if (self.options.sidePagination === 'server') {
data = {};
data[self.options.totalField] = 0;
data[self.options.dataField] = [];
}
self.load(data);
self.trigger('load-error', res.status, res);
if (!silent) self.$tableLoading.hide();
}
});
if (this.options.ajax) {
Utils.calculateObjectValue(this, this.options.ajax, [request], null);
} else {
if (this._xhr && this._xhr.readyState !== 4) {
this._xhr.abort();
}
this._xhr = $.ajax(request);
}
}
$.fn.bootstrapTable.methods.push();
})(jQuery);

View File

@@ -0,0 +1,18 @@
{
"name": "Pipeline",
"version": "1.0.0",
"description": "Plugin to support a hybrid approach to server/client side paging.",
"url": "",
"example": "#",
"plugins": [{
"name": "bootstrap-table-pipeline",
"url": ""
}],
"author": {
"name": "doug-the-guy",
"image": ""
}
}

View File

@@ -0,0 +1,149 @@
(function ($) {
'use strict';
var sprintf = $.fn.bootstrapTable.utils.sprintf;
function printPageBuilderDefault(table) {
return '<html><head>' +
'<style type="text/css" media="print">' +
' @page { size: auto; margin: 25px 0 25px 0; }' +
'</style>' +
'<style type="text/css" media="all">' +
'table{border-collapse: collapse; font-size: 12px; }\n' +
'table, th, td {border: 1px solid grey}\n' +
'th, td {text-align: center; vertical-align: middle;}\n' +
'p {font-weight: bold; margin-left:20px }\n' +
'table { width:94%; margin-left:3%; margin-right:3%}\n' +
'div.bs-table-print { text-align:center;}\n' +
'</style></head><title>Print Table</title><body>' +
'<p>Printed on: ' + new Date + ' </p>' +
'<div class="bs-table-print">' + table + "</div></body></html>";
}
$.extend($.fn.bootstrapTable.defaults, {
showPrint: false,
printAsFilteredAndSortedOnUI: true, //boolean, when true - print table as sorted and filtered on UI.
//Please note that if true is set, along with explicit predefined print options for filtering and sorting (printFilter, printSortOrder, printSortColumn)- then they will be applied on data already filtered and sorted by UI controls.
//For printing data as filtered and sorted on UI - do not set these 3 options:printFilter, printSortOrder, printSortColumn
printSortColumn: undefined , //String, set column field name to be sorted by
printSortOrder: 'asc', //String: 'asc' , 'desc' - relevant only if printSortColumn is set
printPageBuilder: function(table){return printPageBuilderDefault(table)} // function, receive html <table> element as string, returns html string for printing. by default delegates to function printPageBuilderDefault(table). used for styling and adding header or footer
});
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
printFilter: undefined, //set value to filter by in print page
printIgnore: false, //boolean, set true to ignore this column in the print page
printFormatter:undefined //function(value, row, index), formats the cell value for this column in the printed table. Function behaviour is similar to the 'formatter' column option
});
$.extend($.fn.bootstrapTable.defaults.icons, {
print: 'glyphicon-print icon-share'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initToolbar = BootstrapTable.prototype.initToolbar;
BootstrapTable.prototype.initToolbar = function () {
this.showToolbar = this.showToolbar || this.options.showPrint;
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.showPrint) {
var that = this,
$btnGroup = this.$toolbar.find('>.btn-group'),
$print = $btnGroup.find('button.bs-print');
if (!$print.length) {
$print = $([
'<button class="bs-print btn btn-default' + sprintf(' btn-%s"', this.options.iconSize) + ' name="print" title="print" type="button">',
sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.print),
'</button>'].join('')).appendTo($btnGroup);
$print.click(function () {
function formatValue(row, i, column ) {
var value = row[column.field];
if (typeof column.printFormatter === 'function') {
return column.printFormatter.apply(column, [value, row, i]);
}
else {
return typeof value === 'undefined' ? "-" : value;
}
}
function buildTable(data, columnsArray) {
var html = ['<table><thead>'];
for (var k = 0; k < columnsArray.length; k++) {
var columns = columnsArray[k];
html.push('<tr>');
for (var h = 0; h < columns.length; h++) {
if (!columns[h].printIgnore) {
html.push(
'<th',
sprintf(' rowspan="%s"', columns[h].rowspan),
sprintf(' colspan="%s"', columns[h].colspan),
sprintf('>%s</th>', columns[h].title)
);
}
}
html.push('</tr>');
}
html.push('</thead><tbody>');
for (var i = 0; i < data.length; i++) {
html.push('<tr>');
for(var l = 0; l < columnsArray.length; l++) {
var columns = columnsArray[l];
for(var j = 0; j < columns.length; j++) {
if (!columns[j].printIgnore && columns[j].field) {
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>');
}
}
}
html.push('</tr>');
}
html.push('</tbody></table>');
return html.join('');
}
function sortRows(data,colName,sortOrder) {
if(!colName){
return data;
}
var reverse = sortOrder != 'asc';
reverse = -((+reverse) || -1);
return data.sort(function (a, b) {
return reverse * (a[colName].localeCompare(b[colName]));
});
}
function filterRow(row,filters) {
for (var index = 0; index < filters.length; ++index) {
if(row[filters[index].colName]!=filters[index].value) {
return false;
}
}
return true;
}
function filterRows(data,filters) {
return data.filter(function (row) {
return filterRow(row,filters)
});
}
function getColumnFilters(columns) {
return !columns || !columns[0] ? [] : columns[0].filter(function (col) {
return col.printFilter;
}).map(function (col) {
return {colName:col.field, value:col.printFilter};
});
}
var doPrint = function (data) {
data=filterRows(data,getColumnFilters(that.options.columns));
data=sortRows(data,that.options.printSortColumn,that.options.printSortOrder);
var table=buildTable(data,that.options.columns);
var newWin = window.open("");
newWin.document.write(that.options.printPageBuilder.call(this, table));
newWin.print();
newWin.close();
};
doPrint(that.options.printAsFilteredAndSortedOnUI? that.getData() : that.options.data.slice(0));
});
}
}
};
})(jQuery);

View File

@@ -0,0 +1,181 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.1.0
*/
!function ($) {
'use strict';
//From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var filterFn = function () {
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function') {
throw new TypeError();
}
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But that method's new, and collisions should be
// rare, so use the more-compatible alternative.
if (fun.call(thisArg, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
};
$.extend($.fn.bootstrapTable.defaults, {
reorderableColumns: false,
maxMovingRows: 10,
onReorderColumn: function (headerFields) {
return false;
},
dragaccept: null
});
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'reorder-column.bs.table': 'onReorderColumn'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initHeader = BootstrapTable.prototype.initHeader,
_toggleColumn = BootstrapTable.prototype.toggleColumn,
_toggleView = BootstrapTable.prototype.toggleView,
_resetView = BootstrapTable.prototype.resetView;
BootstrapTable.prototype.initHeader = function () {
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.reorderableColumns) {
return;
}
this.makeRowsReorderable();
};
BootstrapTable.prototype.toggleColumn = function () {
_toggleColumn.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.reorderableColumns) {
return;
}
this.makeRowsReorderable();
};
BootstrapTable.prototype.toggleView = function () {
_toggleView.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.reorderableColumns) {
return;
}
if (this.options.cardView) {
return;
}
this.makeRowsReorderable();
};
BootstrapTable.prototype.resetView = function () {
_resetView.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.reorderableColumns) {
return;
}
this.makeRowsReorderable();
};
BootstrapTable.prototype.makeRowsReorderable = function () {
var that = this;
try {
$(this.$el).dragtable('destroy');
} catch (e) {}
$(this.$el).dragtable({
maxMovingRows: that.options.maxMovingRows,
dragaccept: that.options.dragaccept,
clickDelay:200,
beforeStop: function() {
var ths = [],
formatters = [],
columns = [],
columnsHidden = [],
columnIndex = -1,
optionsColumns = [];
that.$header.find('th').each(function (i) {
ths.push($(this).data('field'));
formatters.push($(this).data('formatter'));
});
//Exist columns not shown
if (ths.length < that.columns.length) {
columnsHidden = $.grep(that.columns, function (column) {
return !column.visible;
});
for (var i = 0; i < columnsHidden.length; i++) {
ths.push(columnsHidden[i].field);
formatters.push(columnsHidden[i].formatter);
}
}
for (var i = 0; i < this.length; i++ ) {
columnIndex = that.fieldsColumnsIndex[ths[i]];
if (columnIndex !== -1) {
that.columns[columnIndex].fieldIndex = i;
columns.push(that.columns[columnIndex]);
that.columns.splice(columnIndex, 1);
}
}
that.columns = that.columns.concat(columns);
filterFn(); //Support <IE9
$.each(that.columns, function(i, column) {
var found = false,
field = column.field;
that.options.columns[0].filter(function(item) {
if(!found && item["field"] == field) {
optionsColumns.push(item);
found = true;
return false;
} else
return true;
})
});
that.options.columns[0] = optionsColumns;
that.header.fields = ths;
that.header.formatters = formatters;
that.initHeader();
that.initToolbar();
that.initBody();
that.resetView();
that.trigger('reorder-column', ths);
}
});
};
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Reorder Columns",
"version": "1.1.0",
"description": "Plugin to support the reordering columns feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-columns.html",
"plugins": [{
"name": "bootstrap-table-reorder-columns",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,14 @@
.reorder_rows_onDragClass td {
background-color: #eee;
-webkit-box-shadow: 11px 5px 12px 2px #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-webkit-box-shadow: 6px 3px 5px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-moz-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
}
.reorder_rows_onDragClass td:last-child {
-webkit-box-shadow: 8px 7px 12px 0 #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-webkit-box-shadow: 1px 8px 6px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-moz-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
}

View File

@@ -0,0 +1,118 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v1.0.1
*/
(function ($) {
'use strict';
var isSearch = false;
var rowAttr = function (row, index) {
return {
id: 'customId_' + index
};
};
$.extend($.fn.bootstrapTable.defaults, {
reorderableRows: false,
onDragStyle: null,
onDropStyle: null,
onDragClass: "reorder_rows_onDragClass",
dragHandle: null,
useRowAttrFunc: false,
onReorderRowsDrag: function (table, row) {
return false;
},
onReorderRowsDrop: function (table, row) {
return false;
},
onReorderRow: function (newData) {
return false;
}
});
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'reorder-row.bs.table': 'onReorderRow'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initSearch = BootstrapTable.prototype.initSearch;
BootstrapTable.prototype.init = function () {
if (!this.options.reorderableRows) {
_init.apply(this, Array.prototype.slice.apply(arguments));
return;
}
var that = this;
if (this.options.useRowAttrFunc) {
this.options.rowAttributes = rowAttr;
}
var onPostBody = this.options.onPostBody;
this.options.onPostBody = function () {
setTimeout(function () {
that.makeRowsReorderable();
onPostBody.apply();
}, 1);
};
_init.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.initSearch = function () {
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
if (!this.options.reorderableRows) {
return;
}
//Known issue after search if you reorder the rows the data is not display properly
//isSearch = true;
};
BootstrapTable.prototype.makeRowsReorderable = function () {
if (this.options.cardView) {
return;
}
var that = this;
this.$el.tableDnD({
onDragStyle: that.options.onDragStyle,
onDropStyle: that.options.onDropStyle,
onDragClass: that.options.onDragClass,
onDrop: that.onDrop,
onDragStart: that.options.onReorderRowsDrag,
dragHandle: that.options.dragHandle
});
};
BootstrapTable.prototype.onDrop = function (table, droppedRow) {
var tableBs = $(table),
tableBsData = tableBs.data('bootstrap.table'),
tableBsOptions = tableBs.data('bootstrap.table').options,
row = null,
newData = [];
for (var i = 0; i < table.tBodies[0].rows.length; i++) {
row = $(table.tBodies[0].rows[i]);
newData.push(tableBsOptions.data[row.data('index')]);
row.data('index', i).attr('data-index', i);
}
tableBsOptions.data = tableBsOptions.data.slice(0, tableBsData.pageFrom - 1)
.concat(newData)
.concat(tableBsOptions.data.slice(tableBsData.pageTo));
//Call the user defined function
tableBsOptions.onReorderRowsDrop.apply(table, [table, droppedRow]);
//Call the event reorder-row
tableBsData.trigger('reorder-row', newData);
};
})(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Reorder Rows",
"version": "1.0.0",
"description": "Plugin to support the reordering rows feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-rows.html",
"plugins": [{
"name": "bootstrap-table-reorder-rows",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,72 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v2.0.0
*/
(function($) {
"use strict";
var initResizable = function(that) {
if (that.options.resizable && !that.options.cardView && !isInit(that)) {
that.$el.resizableColumns();
}
};
var reInitResizable = function(that) {
destroy(that);
initResizable(that);
};
var destroy = function(that) {
if (isInit(that)) {
that.$el.data("resizableColumns").destroy();
}
};
var isInit = function(that) {
return that.$el.data("resizableColumns") !== undefined;
};
$.extend($.fn.bootstrapTable.defaults, {
resizable: false
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initBody = BootstrapTable.prototype.initBody,
_toggleView = BootstrapTable.prototype.toggleView,
_resetView = BootstrapTable.prototype.resetView;
BootstrapTable.prototype.initBody = function() {
var that = this;
_initBody.apply(this, Array.prototype.slice.apply(arguments));
that.$el
.off("column-switch.bs.table, page-change.bs.table")
.on("column-switch.bs.table, page-change.bs.table", function() {
reInitResizable(that);
});
};
BootstrapTable.prototype.toggleView = function() {
_toggleView.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.resizable && this.options.cardView) {
//Destroy the plugin
destroy(this);
}
};
BootstrapTable.prototype.resetView = function() {
var that = this;
_resetView.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.resizable) {
// because in fitHeader function, we use setTimeout(func, 100);
setTimeout(function() {
initResizable(that);
}, 100);
}
};
})(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Resizable",
"version": "1.1.0",
"description": "Plugin to support the resizable feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/resizable.html",
"plugins": [{
"name": "bootstrap-table-resizable",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1,332 @@
/**
* @author: Jewway
* @version: v1.1.1
*/
! function ($) {
'use strict';
function getCurrentHeader(that) {
var header = that.$header;
if (that.options.height) {
header = that.$tableHeader;
}
return header;
}
function initFilterValues(that) {
if (!$.isEmptyObject(that.filterColumnsPartial)) {
var $header = getCurrentHeader(that);
$.each(that.columns, function (idx, column) {
var value = that.filterColumnsPartial[column.field];
if (column.filter) {
if (column.filter.setFilterValue) {
var $filter = $header.find('[data-field=' + column.field + '] .filter');
column.filter.setFilterValue($filter, column.field, value);
} else {
var $ele = $header.find('[data-filter-field=' + column.field + ']');
switch (column.filter.type) {
case 'input':
$ele.val(value);
case 'select':
$ele.val(value).trigger('change');
}
}
}
});
}
}
function createFilter(that, header) {
var enableFilter = false,
isVisible,
html,
timeoutId = 0;
$.each(that.columns, function (i, column) {
isVisible = 'hidden';
html = null;
if (!column.visible) {
return;
}
if (!column.filter) {
html = $('<div class="no-filter"></div>');
} else {
var filterClass = column.filter.class ? ' ' + column.filter.class : '';
html = $('<div style="margin: 0px 2px 2px 2px;" class="filter' + filterClass + '">');
if (column.searchable) {
enableFilter = true;
isVisible = 'visible'
}
if (column.filter.template) {
html.append(column.filter.template(that, column, isVisible));
} else {
var $filter = $(that.options.filterTemplate[column.filter.type.toLowerCase()](that, column, isVisible));
switch (column.filter.type) {
case 'input':
var cpLock = true;
$filter.off('compositionstart').on('compositionstart', function (event) {
cpLock = false;
});
$filter.off('compositionend').on('compositionend', function (event) {
cpLock = true;
var $input = $(this);
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
that.onColumnSearch(event, column.field, $input.val());
}, that.options.searchTimeOut);
});
$filter.off('keyup').on('keyup', function (event) {
if (cpLock) {
var $input = $(this);
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
that.onColumnSearch(event, column.field, $input.val());
}, that.options.searchTimeOut);
}
});
$filter.off('mouseup').on('mouseup', function (event) {
var $input = $(this),
oldValue = $input.val();
if (oldValue === "") {
return;
}
setTimeout(function () {
var newValue = $input.val();
if (newValue === "") {
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
that.onColumnSearch(event, column.field, newValue);
}, that.options.searchTimeOut);
}
}, 1);
});
break;
case 'select':
$filter.on('select2:select', function (event) {
that.onColumnSearch(event, column.field, $(this).val());
});
$filter.on("select2:unselecting", function (event) {
var $select2 = $(this);
event.preventDefault();
$select2.val(null).trigger('change');
that.searchText = undefined;
that.onColumnSearch(event, column.field, $select2.val());
});
break;
}
html.append($filter);
}
}
$.each(header.children().children(), function (i, tr) {
tr = $(tr);
if (tr.data('field') === column.field) {
tr.find('.fht-cell').append(html);
return false;
}
});
});
if (!enableFilter) {
header.find('.filter').hide();
}
}
function initSelect2(that) {
var $header = getCurrentHeader(that);
$.each(that.columns, function (idx, column) {
if (column.filter && column.filter.type === 'select') {
var $selectEle = $header.find('select[data-filter-field="' + column.field + '"]');
if ($selectEle.length > 0 && !$selectEle.data().select2) {
var select2Opts = {
placeholder: "",
allowClear: true,
data: column.filter.data,
dropdownParent: that.$el.closest(".bootstrap-table")
};
$selectEle.select2(select2Opts);
}
}
});
}
$.extend($.fn.bootstrapTable.defaults, {
filter: false,
filterValues: {},
filterTemplate: {
input: function (instance, column, isVisible) {
return '<input type="text" class="form-control" data-filter-field="' + column.field + '" style="width: 100%; visibility:' + isVisible + '">';
},
select: function (instance, column, isVisible) {
return '<select data-filter-field="' + column.field + '" style="width: 100%; visibility:' + isVisible + '"></select>';
}
},
onColumnSearch: function (field, text) {
return false;
}
});
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
filter: undefined
});
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'column-search.bs.table': 'onColumnSearch'
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initHeader = BootstrapTable.prototype.initHeader,
_initSearch = BootstrapTable.prototype.initSearch;
BootstrapTable.prototype.init = function () {
//Make sure that the filtercontrol option is set
if (this.options.filter) {
var that = this;
if (that.options.filterTemplate) {
that.options.filterTemplate = $.extend({}, $.fn.bootstrapTable.defaults.filterTemplate, that.options.filterTemplate);
}
if (!$.isEmptyObject(that.options.filterValues)) {
that.filterColumnsPartial = that.options.filterValues;
that.options.filterValues = {};
}
this.$el.on('reset-view.bs.table', function () {
//Create controls on $tableHeader if the height is set
if (!that.options.height) {
return;
}
//Avoid recreate the controls
if (that.$tableHeader.find('select').length > 0 || that.$tableHeader.find('input').length > 0) {
return;
}
createFilter(that, that.$tableHeader);
}).on('post-header.bs.table', function () {
var timeoutId = 0;
initSelect2(that);
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
initFilterValues(that);
}, that.options.searchTimeOut - 1000);
}).on('column-switch.bs.table', function (field, checked) {
initFilterValues(that);
});
}
_init.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.initHeader = function () {
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
if (this.options.filter) {
createFilter(this, this.$header);
}
};
BootstrapTable.prototype.initSearch = function () {
var that = this,
filterValues = that.filterColumnsPartial;
// Filter for client
if (that.options.sidePagination === 'client') {
this.data = $.grep(this.data, function (row, idx) {
for (var field in filterValues) {
var column = that.columns[that.fieldsColumnsIndex[field]],
filterValue = filterValues[field].toLowerCase(),
rowValue = row[field];
rowValue = $.fn.bootstrapTable.utils.calculateObjectValue(
that.header,
that.header.formatters[$.inArray(field, that.header.fields)], [rowValue, row, idx], rowValue);
if (column.filterStrictSearch) {
if (!($.inArray(field, that.header.fields) !== -1 &&
(typeof rowValue === 'string' || typeof rowValue === 'number') &&
rowValue.toString().toLowerCase() === filterValue.toString().toLowerCase())) {
return false;
}
} else {
if (!($.inArray(field, that.header.fields) !== -1 &&
(typeof rowValue === 'string' || typeof rowValue === 'number') &&
(rowValue + '').toLowerCase().indexOf(filterValue) !== -1)) {
return false;
}
}
}
return true;
});
}
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
};
BootstrapTable.prototype.onColumnSearch = function (event, field, value) {
if ($.isEmptyObject(this.filterColumnsPartial)) {
this.filterColumnsPartial = {};
}
if (value) {
this.filterColumnsPartial[field] = value;
} else {
delete this.filterColumnsPartial[field];
}
this.options.pageNumber = 1;
this.onSearch(event);
this.trigger('column-search', field, value);
};
BootstrapTable.prototype.setSelect2Data = function (field, data) {
var that = this,
$header = getCurrentHeader(that),
$selectEle = $header.find('select[data-filter-field=\"' + field + '\"]');
$selectEle.empty();
$selectEle.select2({
data: data,
placeholder: "",
allowClear: true,
dropdownParent: that.$el.closest(".bootstrap-table")
});
$.each(this.columns, function (idx, column) {
if (column.field === field) {
column.filter.data = data;
return false;
}
});
};
BootstrapTable.prototype.setFilterValues = function (values) {
this.filterColumnsPartial = values;
};
$.fn.bootstrapTable.methods.push('setSelect2Data');
$.fn.bootstrapTable.methods.push('setFilterValues');
}(jQuery);

View File

@@ -0,0 +1,17 @@
{
"name": "Select2 Filter",
"version": "1.1.0",
"description": "Plugin to add select2 filter on the top of the columns in order to filter the data.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/select2-filter",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/select2-filter.html",
"plugins": [{
"name": "bootstrap-table-select2-filter",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/select2-filter"
}],
"author": {
"name": "Jewway",
"image": "https://avatars0.githubusercontent.com/u/3501899"
}
}

View File

@@ -0,0 +1,22 @@
/**
* @author vincent loh <vincent.ml@gmail.com>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
.fix-sticky {
position: fixed !important;
overflow: hidden;
z-index: 100;
}
.fix-sticky table thead {
background: #fff;
}
.fix-sticky table thead.thead-light {
background: #e9ecef;
}
.fix-sticky table thead.thead-light {
background: #212529;
}

View File

@@ -0,0 +1,76 @@
/**
* @author vincent loh <vincent.ml@gmail.com>
* @update J Manuel Corona <jmcg92@gmail.com>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
stickyHeader: false,
stickyHeaderOffsetY: 0
})
const hiddenClass = Utils.bootstrapVersion === 4 ? 'd-none' : 'hidden'
$.BootstrapTable = class extends $.BootstrapTable {
initHeader (...args) {
super.initHeader(...args)
if (!this.options.stickyHeader) {
return
}
this.$el.before('<div class="sticky-header-container"></div>')
this.$el.before('<div class="sticky_anchor_begin"></div>')
this.$el.after('<div class="sticky_anchor_end"></div>')
this.$header.addClass('sticky-header')
// clone header just once, to be used as sticky header
// deep clone header, using source header affects tbody>td width
this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
this.$stickyHeader = this.$header.clone(true, true)
// render sticky on window scroll or resize
$(window).on('resize.sticky-header-table', () => this.renderStickyHeader())
$(window).on('scroll.sticky-header-table', () => this.renderStickyHeader())
this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
}
renderStickyHeader () {
const top = $(window).scrollTop()
// top anchor scroll position, minus header height
const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
// bottom anchor scroll position, minus header height, minus sticky height
const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
// show sticky when top anchor touches header, and when bottom anchor not exceeded
if (top > start && top <= end) {
// ensure clone and source column widths are the same
this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
$(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
})
// match bootstrap table style
this.$stickyContainer.removeClass(hiddenClass).addClass('fix-sticky fixed-table-container')
// stick it in position
this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}px`)
// create scrollable container for header
this.$stickyTable = $('<table/>')
this.$stickyTable.addClass(this.options.classes)
// append cloned header to dom
this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
// match clone and source header positions when left-right scroll
this.matchPositionX()
} else {
this.$stickyContainer.removeClass('fix-sticky').addClass(hiddenClass)
}
}
matchPositionX () {
this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Sticky Header",
"version": "1.0.0",
"description": "An extension which provides a sticky header for table columns when scrolling on a long page and / or table. Works for tables with many columns and narrow width with horizontal scrollbars too.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/sticky-header.html",
"plugins": [{
"name": "bootstrap-table-sticky-header",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header"
}],
"author": {
"name": "vinzloh",
"image": "https://avatars0.githubusercontent.com/u/5501845"
}
}

View File

@@ -0,0 +1,228 @@
/**
* @author: aperez <aperez@datadec.es>
* @version: v2.0.0
*
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
($ => {
const Utils = $.fn.bootstrapTable.utils
const bootstrap = {
3: {
icons: {
advancedSearchIcon: 'glyphicon-chevron-down'
},
html: {
modalHeader: `
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">%s</h4>
</div>
`
}
},
4: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
html: {
modalHeader: `
<div class="modal-header">
<h4 class="modal-title">%s</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
`
}
}
}[Utils.bootstrapVersion]
$.extend($.fn.bootstrapTable.defaults, {
advancedSearch: false,
idForm: 'advancedSearch',
actionForm: '',
idTable: undefined,
onColumnAdvancedSearch (field, text) {
return false
}
})
$.extend($.fn.bootstrapTable.defaults.icons, {
advancedSearchIcon: bootstrap.icons.advancedSearchIcon
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
})
$.extend($.fn.bootstrapTable.locales, {
formatAdvancedSearch () {
return 'Advanced search'
},
formatAdvancedCloseButton () {
return 'Close'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.BootstrapTable = class extends $.BootstrapTable {
initToolbar () {
const o = this.options
this.showToolbar = this.showToolbar ||
(o.search &&
o.advancedSearch &&
o.idTable)
super.initToolbar()
if (!o.search || !o.advancedSearch || !o.idTable) {
return
}
this.$toolbar.find('>.btn-group').append(`
<button class="btn btn-default${Utils.sprintf(' btn-%s', o.buttonsClass)}${Utils.sprintf(' btn-%s', o.iconSize)}"
type="button"
name="advancedSearch"
aria-label="advanced search"
title="${o.formatAdvancedSearch()}">
<i class="${o.iconsPrefix} ${o.icons.advancedSearchIcon}"></i>
</button>
`)
this.$toolbar.find('button[name="advancedSearch"]').off('click').on('click', () => this.showAvdSearch())
}
showAvdSearch () {
const o = this.options
if (!$(`#avdSearchModal_${o.idTable}`).hasClass('modal')) {
$('body').append(`
<div id="avdSearchModal_${o.idTable}" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xs">
<div class="modal-content">
${Utils.sprintf(bootstrap.html.modalHeader, o.formatAdvancedSearch())}
<div class="modal-body modal-body-custom">
<div class="container-fluid" id="avdSearchModalContent_${o.idTable}"
style="padding-right: 0px; padding-left: 0px;" >
</div>
</div>
<div class="modal-footer">
<button type="button" id="btnCloseAvd_${o.idTable}" class="btn btn-${o.buttonsClass}">
${o.formatAdvancedCloseButton()}
</button>
</div>
</div>
</div>
</div>
`)
let timeoutId = 0
$(`#avdSearchModalContent_${o.idTable}`).append(this.createFormAvd().join(''))
$(`#${o.idForm}`).off('keyup blur', 'input').on('keyup blur', 'input', e => {
if (o.sidePagination === 'server') {
this.onColumnAdvancedSearch(e)
} else {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
this.onColumnAdvancedSearch(e)
}, o.searchTimeOut)
}
})
$(`#btnCloseAvd_${o.idTable}`).click(() => {
$(`#avdSearchModal_${o.idTable}`).modal('hide')
if (o.sidePagination === 'server') {
this.options.pageNumber = 1
this.updatePagination()
this.trigger('column-advanced-search', this.filterColumnsPartial)
}
})
$(`#avdSearchModal_${o.idTable}`).modal()
} else {
$(`#avdSearchModal_${o.idTable}`).modal()
}
}
createFormAvd () {
const o = this.options
const html = [`<form class="form-horizontal" id="${o.idForm}" action="${o.actionForm}">`]
for (const column of this.columns) {
if (!column.checkbox && column.visible && column.searchable) {
html.push(`
<div class="form-group row">
<label class="col-sm-4 control-label">${column.title}</label>
<div class="col-sm-6">
<input type="text" class="form-control input-md" name="${column.field}" placeholder="${column.title}" id="${column.field}">
</div>
</div>
`)
}
}
html.push('</form>')
return html
}
initSearch () {
super.initSearch()
if (!this.options.advancedSearch || this.options.sidePagination === 'server') {
return
}
const fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial
this.data = fp ? $.grep(this.data, (item, i) => {
for (const [key, v] of Object.entries(fp)) {
const fval = v.toLowerCase()
let value = item[key]
const index = this.header.fields.indexOf(key)
value = Utils.calculateObjectValue(this.header,
this.header.formatters[index], [value, item, i], value)
if (
!(index !== -1 &&
(typeof value === 'string' || typeof value === 'number') &&
(`${value}`).toLowerCase().includes(fval))
) {
return false
}
}
return true
}) : this.data
}
onColumnAdvancedSearch (e) {
const text = $.trim($(e.currentTarget).val())
const $field = $(e.currentTarget)[0].id
if ($.isEmptyObject(this.filterColumnsPartial)) {
this.filterColumnsPartial = {}
}
if (text) {
this.filterColumnsPartial[$field] = text
} else {
delete this.filterColumnsPartial[$field]
}
if (this.options.sidePagination !== 'server') {
this.options.pageNumber = 1
this.onSearch(e)
this.updatePagination()
this.trigger('column-advanced-search', $field, text)
}
}
}
})(jQuery)

View File

@@ -0,0 +1,17 @@
{
"name": "Toolbar",
"version": "2.0.0",
"description": "Plugin to support the advanced search.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/toolbar.html",
"plugins": [{
"name": "bootstrap-table-toolbar",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}

View File

@@ -0,0 +1 @@
.table:not(.table-condensed)>tbody>tr>td.treenode{padding-top:0;padding-bottom:0;border-bottom:solid #fff 1px}.table:not(.table-condensed)>tbody>tr:last-child>td.treenode{border-bottom:none}.treenode .text{float:left;display:block;padding-top:6px;padding-bottom:6px}.treenode .vertical,.treenode .vertical.last{float:left;display:block;width:1px;border-left:dashed silver 1px;height:38px;margin-left:8px}.treenode .vertical.last{height:15px}.treenode .space,.treenode .node{float:left;display:block;width:15px;height:5px;margin-top:15px}.treenode .node{border-top:dashed silver 1px}

View File

@@ -0,0 +1,130 @@
/**
* @author: KingYang
* @webSite: https://github.com/kingyang
* @version: v1.0.0
*/
! function ($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
treeShowField: null,
idField: 'id',
parentIdField: 'pid',
treeVerticalcls: 'vertical',
treeVerticalLastcls: 'vertical last',
treeSpacecls: 'space',
treeNodecls: 'node',
treeCellcls: 'treenode',
treeTextcls: 'text',
onTreeFormatter: function (row) {
var that = this,
options = that.options,
level = row._level || 0,
plevel = row._parent && row._parent._level || 0,
paddings = [];
for (var i = 0; i < plevel; i++) {
paddings.push('<i class="' + options.treeVerticalcls + '"></i>');
paddings.push('<i class="' + options.treeSpacecls + '"></i>');
}
for (var i = plevel; i < level; i++) {
if (row._last && i === (level - 1)) {
paddings.push('<i class="' + options.treeVerticalLastcls + '"></i>');
} else {
paddings.push('<i class="' + options.treeVerticalcls + '"></i>');
}
paddings.push('<i class="' + options.treeNodecls + '"></i>');
}
return paddings.join('');
}, onGetNodes: function (row, data) {
var that = this;
var nodes = [];
$.each(data, function (i, item) {
if (row[that.options.idField] === item[that.options.parentIdField]) {
nodes.push(item);
}
});
return nodes;
},
onCheckLeaf: function (row, data) {
if (row.isLeaf !== undefined) {
return row.isLeaf;
}
return !row._nodes || !row._nodes.length;
}, onCheckRoot: function (row, data) {
var that = this;
return !row[that.options.parentIdField];
}
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initRow = BootstrapTable.prototype.initRow,
_initHeader = BootstrapTable.prototype.initHeader;
BootstrapTable.prototype.initHeader = function () {
var that = this;
_initHeader.apply(that, Array.prototype.slice.apply(arguments));
var treeShowField = that.options.treeShowField;
if (treeShowField) {
$.each(this.header.fields, function (i, field) {
if (treeShowField === field) {
that.treeEnable = true;
var _formatter = that.header.formatters[i];
var _class = [that.options.treeCellcls];
if (that.header.classes[i]) {
_class.push(that.header.classes[i].split('"')[1] || '');
}
that.header.classes[i] = ' class="' + _class.join(' ') + '"';
that.header.formatters[i] = function (value, row, index) {
var colTree = [that.options.onTreeFormatter.apply(that, [row])];
colTree.push('<span class="' + that.options.treeTextcls + '">');
if (_formatter) {
colTree.push(_formatter.apply(this, Array.prototype.slice.apply(arguments)));
} else {
colTree.push(value);
}
colTree.push('</span>');
return colTree.join('');
};
return false;
}
});
}
};
var initNode = function (item, idx, data, parentDom) {
var that = this;
var nodes = that.options.onGetNodes.apply(that, [item, data]);
item._nodes = nodes;
parentDom.append(_initRow.apply(that, [item, idx, data, parentDom]));
var len = nodes.length - 1;
for (var i = 0; i <= len; i++) {
var node = nodes[i];
node._level = item._level + 1;
node._parent = item;
if (i === len)
node._last = 1;
initNode.apply(that, [node, $.inArray(node, data), data, parentDom]);
}
};
BootstrapTable.prototype.initRow = function (item, idx, data, parentDom) {
var that = this;
if (that.treeEnable) {
if (that.options.onCheckRoot.apply(that, [item, data])) {
if (item._level === undefined) {
item._level = 0;
}
initNode.apply(that, [item, idx, data, parentDom]);
return true;
}
return false;
}
return _initRow.apply(that, Array.prototype.slice.apply(arguments));
};
} (jQuery);

View File

@@ -0,0 +1,43 @@
.table:not(.table-condensed) > tbody > tr > td.treenode {
padding-top: 0;
padding-bottom: 0;
border-bottom: solid #fff 1px;
}
.table:not(.table-condensed) > tbody > tr:last-child > td.treenode {
border-bottom: none;
}
.treenode {
.text {
float: left;
display: block;
padding-top: 6px;
padding-bottom: 6px;
}
.vertical,
.vertical.last {
float: left;
display: block;
width: 1px;
border-left: dashed silver 1px;
height: 38px;
margin-left: 8px;
}
.vertical.last {
height: 15px;
}
.space,
.node {
float: left;
display: block;
width: 15px;
height: 5px;
margin-top: 15px;
}
.node {
border-top: dashed silver 1px;
}
}

View File

@@ -0,0 +1,17 @@
{
"name": "Tree column",
"version": "1.0.0",
"description": "Plugin to support display tree data column.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/tree-column.html",
"plugins": [{
"name": "bootstrap-table-reorder-rows",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column"
}],
"author": {
"name": "KingYang",
"image": "https://avatars3.githubusercontent.com/u/1540211"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

View File

@@ -0,0 +1,111 @@
/**
* @author: YL
* @version: v1.0.0
*/
!function ($) {
'use strict';
$.extend($.fn.bootstrapTable.defaults, {
treeShowField: null,
idField: 'id',
parentIdField: 'pid',
rootParentId: null,
onGetNodes: function (row, data) {
var that = this;
var nodes = [];
$.each(data, function (i, item) {
if (row[that.options.idField] === item[that.options.parentIdField]) {
nodes.push(item);
}
});
return nodes;
},
onCheckRoot: function (row, data) {
var that = this;
return that.options.rootParentId === row[that.options.parentIdField] ||
!row[that.options.parentIdField];
}
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_init = BootstrapTable.prototype.init,
_initRow = BootstrapTable.prototype.initRow,
_initHeader = BootstrapTable.prototype.initHeader,
_rowStyle = null;
BootstrapTable.prototype.init = function () {
_rowStyle = this.options.rowStyle;
_init.apply(this, Array.prototype.slice.apply(arguments));
};
// td
BootstrapTable.prototype.initHeader = function () {
var that = this;
_initHeader.apply(that, Array.prototype.slice.apply(arguments));
var treeShowField = that.options.treeShowField;
if (treeShowField) {
$.each(this.header.fields, function (i, field) {
if (treeShowField === field) {
that.treeEnable = true;
return false;
}
});
}
};
var initTr = function (item, idx, data, parentDom) {
var that = this;
var nodes = that.options.onGetNodes.apply(that, [item, data]);
item._nodes = nodes;
parentDom.append(_initRow.apply(that, [item, idx, data, parentDom]));
// init sub node
var len = nodes.length - 1;
for (var i = 0; i <= len; i++) {
var node = nodes[i];
node._level = item._level + 1;
node._parent = item;
if (i === len)
node._last = 1;
// jquery.treegrid.js
that.options.rowStyle = function (item, idx) {
var res = _rowStyle.apply(that, Array.prototype.slice.apply(arguments));
var id = item[that.options.idField] ? item[that.options.idField] : 0;
var pid = item[that.options.parentIdField] ? item[that.options.parentIdField] : 0;
res.classes = [
res.classes || '',
'treegrid-' + id,
'treegrid-parent-' + pid
].join(' ');
return res;
};
initTr.apply(that, [node, $.inArray(node, data), data, parentDom]);
}
};
// tr
BootstrapTable.prototype.initRow = function (item, idx, data, parentDom) {
var that = this;
if (that.treeEnable) {
// init root node
if (that.options.onCheckRoot.apply(that, [item, data])) {
if (item._level === undefined) {
item._level = 0;
}
// jquery.treegrid.js
that.options.rowStyle = function (item, idx) {
var res = _rowStyle.apply(that, Array.prototype.slice.apply(arguments));
var x = item[that.options.idField] ? item[that.options.idField] : 0;
res.classes = [
res.classes || '',
'treegrid-' + x
].join(' ');
return res;
};
initTr.apply(that, [item, idx, data, parentDom]);
return true;
}
return false;
}
return _initRow.apply(that, Array.prototype.slice.apply(arguments));
};
}(jQuery);

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