From 62d877ba5429c4db589b7efe26d32ec229c9de50 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 16:40:06 +1000 Subject: [PATCH 01/36] Adds script to pull down "rendered" versions of javascript files --- ci/.gitignore | 1 + ci/pull_js_files.py | 111 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 ci/.gitignore create mode 100644 ci/pull_js_files.py diff --git a/ci/.gitignore b/ci/.gitignore new file mode 100644 index 0000000000..b8ba69cb91 --- /dev/null +++ b/ci/.gitignore @@ -0,0 +1 @@ +js_tmp/ \ No newline at end of file diff --git a/ci/pull_js_files.py b/ci/pull_js_files.py new file mode 100644 index 0000000000..b69268e0e2 --- /dev/null +++ b/ci/pull_js_files.py @@ -0,0 +1,111 @@ +""" +Pull 'rendered' copies of the templated JS files down from the InvenTree server. + +These files can then be used for linting and unit testing +""" + +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import sys +import re +import os +import json +import pathlib +import argparse +import requests +from requests.auth import HTTPBasicAuth + + +here = os.path.abspath(os.path.dirname(__file__)) +js_template_dir = os.path.abspath(os.path.join(here, '..', 'InvenTree', 'templates', 'js')) + +js_tmp_dir = os.path.join(here, 'js_tmp') + +def get_token(server, username, password): + + url = os.path.join( + server, + 'api', + 'user', + 'token', + ) + + auth = HTTPBasicAuth(username, password) + + response = requests.get(url, auth=auth, allow_redirects=False) + + data = json.loads(response.text) + + return data['token'] + + +def download_file(url, filename, token): + """ + Download a single javascript file + """ + + print(f"Downloading '{url}'") + + headers = { + 'AUTHORIZATION': f'Token {token}' + } + + response = requests.get( + url, + allow_redirects=False, + headers=headers + ) + + output_file = os.path.join( + js_tmp_dir, + filename, + ) + + with open(output_file, 'wb') as output: + output.write(response.content) + + +def download_js_files(subdir, url, token): + """ + Returns a flattened list of all javascript files + """ + + d = os.path.join(js_template_dir, subdir) + + files = pathlib.Path(d).rglob('*.js') + + for filename in files: + js = os.path.basename(filename) + + js_url = os.path.join(url, js) + + download_file(js_url, js, token) + +if __name__ == '__main__': + + parser = argparse.ArgumentParser("Download JavaScript files") + + parser.add_argument('-s', '--server', help='InvenTree server', action='store') + parser.add_argument('-u', '--username', help='Username', action='store') + parser.add_argument('-p', '--password', help='password', action='store') + + args = parser.parse_args() + + if not os.path.exists(js_tmp_dir): + os.mkdir(js_tmp_dir) + + auth = HTTPBasicAuth(args.username, args.password) + + # Get an auth token from the server + token = get_token(args.server, args.username, args.password) + + # Dynamic javascript files + dynamic_url = os.path.join(args.server, 'js', 'dynamic') + + download_js_files('dynamic', dynamic_url, token) + + # Translated JS files + i18n_url = os.path.join(args.server, 'js', 'i18n') + + download_js_files("translated", i18n_url, token) \ No newline at end of file From 880a701881f668e2bbef169507103472dd04f63f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 16:55:59 +1000 Subject: [PATCH 02/36] eslint configuration file --- ci/.eslintrc.yml | 251 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 ci/.eslintrc.yml diff --git a/ci/.eslintrc.yml b/ci/.eslintrc.yml new file mode 100644 index 0000000000..3040a512c2 --- /dev/null +++ b/ci/.eslintrc.yml @@ -0,0 +1,251 @@ +env: + commonjs: true + es6: true + browser: true + es2021: true + jquery: true +extends: 'eslint:recommended' +parserOptions: + ecmaVersion: 12 +rules: + accessor-pairs: error + array-bracket-newline: 'off' + array-bracket-spacing: + - error + - never + array-callback-return: error + array-element-newline: 'off' + arrow-body-style: error + arrow-parens: + - error + - as-needed + arrow-spacing: 'off' + block-scoped-var: 'off' + block-spacing: 'off' + brace-style: 'off' + camelcase: 'off' + capitalized-comments: 'off' + class-methods-use-this: error + comma-dangle: 'off' + comma-spacing: 'off' + comma-style: + - error + - last + complexity: 'off' + computed-property-spacing: + - error + - never + consistent-return: 'off' + consistent-this: 'off' + curly: 'off' + default-case: 'off' + default-case-last: 'off' + default-param-last: error + dot-location: error + dot-notation: 'off' + eol-last: 'off' + eqeqeq: 'off' + func-call-spacing: error + func-name-matching: error + func-names: 'off' + func-style: + - error + - declaration + function-call-argument-newline: 'off' + function-paren-newline: 'off' + generator-star-spacing: error + grouped-accessor-pairs: error + guard-for-in: 'off' + id-denylist: error + id-length: 'off' + id-match: error + implicit-arrow-linebreak: + - error + - beside + indent: 'off' + init-declarations: error + jsx-quotes: error + key-spacing: 'off' + keyword-spacing: 'off' + line-comment-position: 'off' + linebreak-style: + - error + - unix + lines-around-comment: 'off' + lines-between-class-members: error + max-classes-per-file: error + max-depth: error + max-len: 'off' + max-lines: 'off' + max-lines-per-function: 'off' + max-nested-callbacks: error + max-params: 'off' + max-statements: 'off' + max-statements-per-line: 'off' + multiline-comment-style: 'off' + new-cap: error + new-parens: error + newline-per-chained-call: 'off' + no-alert: 'off' + no-array-constructor: 'off' + no-await-in-loop: error + no-bitwise: error + no-caller: error + no-confusing-arrow: error + no-console: 'off' + no-constructor-return: error + no-continue: 'off' + no-div-regex: error + no-duplicate-imports: error + no-else-return: 'off' + no-empty-function: 'off' + no-eq-null: 'off' + no-eval: error + no-extend-native: error + no-extra-bind: error + no-extra-label: error + no-extra-parens: 'off' + no-floating-decimal: error + no-implicit-coercion: + - error + - boolean: false + disallowTemplateShorthand: false + number: false + string: false + no-implicit-globals: 'off' + no-implied-eval: error + no-inline-comments: 'off' + no-inner-declarations: + - error + - functions + no-invalid-this: error + no-iterator: error + no-label-var: error + no-labels: error + no-lone-blocks: error + no-lonely-if: error + no-loop-func: 'off' + no-loss-of-precision: error + no-magic-numbers: 'off' + no-mixed-operators: + - error + - allowSamePrecedence: true + no-multi-assign: error + no-multi-spaces: + - error + - ignoreEOLComments: true + no-multi-str: error + no-multiple-empty-lines: 'off' + no-negated-condition: 'off' + no-nested-ternary: error + no-new: error + no-new-func: error + no-new-object: error + no-new-wrappers: error + no-nonoctal-decimal-escape: error + no-octal-escape: error + no-param-reassign: 'off' + no-plusplus: 'off' + no-promise-executor-return: error + no-proto: error + no-restricted-exports: error + no-restricted-globals: error + no-restricted-imports: error + no-restricted-properties: error + no-restricted-syntax: error + no-return-assign: error + no-return-await: error + no-script-url: error + no-self-compare: error + no-sequences: 'off' + no-shadow: 'off' + no-tabs: error + no-template-curly-in-string: error + no-ternary: 'off' + no-throw-literal: error + no-trailing-spaces: 'off' + no-undef-init: error + no-undefined: 'off' + no-underscore-dangle: 'off' + no-unmodified-loop-condition: error + no-unneeded-ternary: error + no-unreachable-loop: error + no-unsafe-optional-chaining: error + no-unused-expressions: 'off' + no-use-before-define: 'off' + no-useless-backreference: error + no-useless-call: error + no-useless-computed-key: error + no-useless-concat: error + no-useless-constructor: error + no-useless-rename: error + no-useless-return: error + no-var: 'off' + no-void: error + no-warning-comments: 'off' + no-whitespace-before-property: error + nonblock-statement-body-position: error + object-curly-newline: error + object-curly-spacing: 'off' + object-property-newline: 'off' + object-shorthand: 'off' + one-var: 'off' + one-var-declaration-per-line: error + operator-assignment: + - error + - always + operator-linebreak: error + padded-blocks: 'off' + padding-line-between-statements: error + prefer-arrow-callback: 'off' + prefer-const: 'off' + prefer-destructuring: 'off' + prefer-exponentiation-operator: error + prefer-named-capture-group: 'off' + prefer-numeric-literals: error + prefer-object-spread: error + prefer-promise-reject-errors: error + prefer-regex-literals: error + prefer-rest-params: error + prefer-spread: 'off' + prefer-template: 'off' + quote-props: 'off' + quotes: 'off' + radix: 'off' + require-atomic-updates: error + require-await: error + require-unicode-regexp: 'off' + rest-spread-spacing: error + semi: 'off' + semi-spacing: + - error + - after: true + before: false + semi-style: + - error + - last + sort-imports: error + sort-keys: 'off' + sort-vars: error + space-before-blocks: 'off' + space-before-function-paren: 'off' + space-in-parens: 'off' + space-infix-ops: 'off' + space-unary-ops: 'off' + spaced-comment: 'off' + strict: 'off' + switch-colon-spacing: error + symbol-description: error + template-curly-spacing: + - error + - never + template-tag-spacing: error + unicode-bom: + - error + - never + vars-on-top: 'off' + wrap-regex: error + yield-star-spacing: error + yoda: + - error + - never From f57a31c9b512e85cb513e6aeff7381d396722f6e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 20:46:51 +1000 Subject: [PATCH 03/36] Add a test framework script to pull down rendered javascript files - Use the testing framework so we don't need to spin up a server --- ci/.eslintrc.yml => .eslintrc.yml | 0 .gitignore | 3 + InvenTree/InvenTree/ci_render_js.py | 93 +++++++++++++++++++++++ ci/.gitignore | 1 - ci/pull_js_files.py | 111 ---------------------------- 5 files changed, 96 insertions(+), 112 deletions(-) rename ci/.eslintrc.yml => .eslintrc.yml (100%) create mode 100644 InvenTree/InvenTree/ci_render_js.py delete mode 100644 ci/.gitignore delete mode 100644 ci/pull_js_files.py diff --git a/ci/.eslintrc.yml b/.eslintrc.yml similarity index 100% rename from ci/.eslintrc.yml rename to .eslintrc.yml diff --git a/.gitignore b/.gitignore index f3fa0ac8c1..6f253ee8ea 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,9 @@ secret_key.txt .coverage htmlcov/ +# Temporary javascript files (used for testing) +js_tmp/ + # Development files dev/ diff --git a/InvenTree/InvenTree/ci_render_js.py b/InvenTree/InvenTree/ci_render_js.py new file mode 100644 index 0000000000..c45caf604d --- /dev/null +++ b/InvenTree/InvenTree/ci_render_js.py @@ -0,0 +1,93 @@ +""" +Pull rendered copies of the templated +""" + +from django.http import response +from django.test import TestCase, testcases +from django.contrib.auth import get_user_model + +import os +import pathlib + + +class RenderJavascriptFiles(TestCase): + """ + A unit test to "render" javascript files. + + The server renders templated javascript files, + we need the fully-rendered files for linting and static tests. + """ + + def setUp(self): + + user = get_user_model() + + self.user = user.objects.create_user( + username='testuser', + password='testpassword', + email='user@gmail.com', + ) + + self.client.login(username='testuser', password='testpassword') + + def download_file(self, filename, prefix): + + url = os.path.join(prefix, filename) + + response = self.client.get(url) + + here = os.path.abspath(os.path.dirname(__file__)) + + output_dir = os.path.join( + here, + '..', + '..', + 'js_tmp', + ) + + output_dir = os.path.abspath(output_dir) + + if not os.path.exists(output_dir): + os.mkdir(output_dir) + + output_file = os.path.join( + output_dir, + filename, + ) + + with open(output_file, 'wb') as output: + output.write(response.content) + + def download_files(self, subdir, prefix): + here = os.path.abspath(os.path.dirname(__file__)) + + js_template_dir = os.path.join( + here, + '..', + 'templates', + 'js', + ) + + directory = os.path.join(js_template_dir, subdir) + + directory = os.path.abspath(directory) + + js_files = pathlib.Path(directory).rglob('*.js') + + for f in js_files: + js = os.path.basename(f) + + self.download_file(js, prefix) + + def test_render_files(self): + """ + Look for all javascript files + """ + + self.download_files('translated', '/js/i18n') + self.download_files('dynamic', '/js/dynamic') + + + + + diff --git a/ci/.gitignore b/ci/.gitignore deleted file mode 100644 index b8ba69cb91..0000000000 --- a/ci/.gitignore +++ /dev/null @@ -1 +0,0 @@ -js_tmp/ \ No newline at end of file diff --git a/ci/pull_js_files.py b/ci/pull_js_files.py deleted file mode 100644 index b69268e0e2..0000000000 --- a/ci/pull_js_files.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -Pull 'rendered' copies of the templated JS files down from the InvenTree server. - -These files can then be used for linting and unit testing -""" - -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import sys -import re -import os -import json -import pathlib -import argparse -import requests -from requests.auth import HTTPBasicAuth - - -here = os.path.abspath(os.path.dirname(__file__)) -js_template_dir = os.path.abspath(os.path.join(here, '..', 'InvenTree', 'templates', 'js')) - -js_tmp_dir = os.path.join(here, 'js_tmp') - -def get_token(server, username, password): - - url = os.path.join( - server, - 'api', - 'user', - 'token', - ) - - auth = HTTPBasicAuth(username, password) - - response = requests.get(url, auth=auth, allow_redirects=False) - - data = json.loads(response.text) - - return data['token'] - - -def download_file(url, filename, token): - """ - Download a single javascript file - """ - - print(f"Downloading '{url}'") - - headers = { - 'AUTHORIZATION': f'Token {token}' - } - - response = requests.get( - url, - allow_redirects=False, - headers=headers - ) - - output_file = os.path.join( - js_tmp_dir, - filename, - ) - - with open(output_file, 'wb') as output: - output.write(response.content) - - -def download_js_files(subdir, url, token): - """ - Returns a flattened list of all javascript files - """ - - d = os.path.join(js_template_dir, subdir) - - files = pathlib.Path(d).rglob('*.js') - - for filename in files: - js = os.path.basename(filename) - - js_url = os.path.join(url, js) - - download_file(js_url, js, token) - -if __name__ == '__main__': - - parser = argparse.ArgumentParser("Download JavaScript files") - - parser.add_argument('-s', '--server', help='InvenTree server', action='store') - parser.add_argument('-u', '--username', help='Username', action='store') - parser.add_argument('-p', '--password', help='password', action='store') - - args = parser.parse_args() - - if not os.path.exists(js_tmp_dir): - os.mkdir(js_tmp_dir) - - auth = HTTPBasicAuth(args.username, args.password) - - # Get an auth token from the server - token = get_token(args.server, args.username, args.password) - - # Dynamic javascript files - dynamic_url = os.path.join(args.server, 'js', 'dynamic') - - download_js_files('dynamic', dynamic_url, token) - - # Translated JS files - i18n_url = os.path.join(args.server, 'js', 'i18n') - - download_js_files("translated", i18n_url, token) \ No newline at end of file From d0ccf8647de2741206dea4af408f5999b850fd1b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 20:59:41 +1000 Subject: [PATCH 04/36] Add js linting to github workflow --- .github/workflows/javascript.yaml | 12 ++++++++++-- InvenTree/InvenTree/ci_render_js.py | 15 +++++++++++---- tasks.py | 9 +++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index 908a87e31c..d59098da75 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -18,11 +18,19 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + INVENTREE_DB_ENGINE: sqlite3 + INVENTREE_DB_NAME: inventree steps: + - name: Install node.js + uses: actions/setup-node@v2 + - run: npm install - name: Checkout Code uses: actions/checkout@v2 - - name: Check Files + - name: Check Templated Files run: | cd ci python check_js_templates.py - \ No newline at end of file + - name: Lint Javascript Files + run: | + invoke render-js-files + npx eslint js_tmp/*.js \ No newline at end of file diff --git a/InvenTree/InvenTree/ci_render_js.py b/InvenTree/InvenTree/ci_render_js.py index c45caf604d..62e3fc4667 100644 --- a/InvenTree/InvenTree/ci_render_js.py +++ b/InvenTree/InvenTree/ci_render_js.py @@ -74,20 +74,27 @@ class RenderJavascriptFiles(TestCase): js_files = pathlib.Path(directory).rglob('*.js') + n = 0 + for f in js_files: js = os.path.basename(f) self.download_file(js, prefix) + n += 1 + + return n + def test_render_files(self): """ Look for all javascript files """ - self.download_files('translated', '/js/i18n') - self.download_files('dynamic', '/js/dynamic') - - + n = 0 + print("Rendering javascript files...") + n += self.download_files('translated', '/js/i18n') + n += self.download_files('dynamic', '/js/dynamic') + print(f"Rendered {n} javascript files.") diff --git a/tasks.py b/tasks.py index 3de0241c07..1abbf23bc6 100644 --- a/tasks.py +++ b/tasks.py @@ -457,3 +457,12 @@ def server(c, address="127.0.0.1:8000"): """ manage(c, "runserver {address}".format(address=address), pty=True) + + +@task +def render_js_files(c): + """ + Render templated javascript files (used for static testing). + """ + + manage(c, "test InvenTree.ci_render_js") From 09a7a7d2e48011336eb3457dee06acb6ccdfc6b2 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 21:03:09 +1000 Subject: [PATCH 05/36] Install required files --- .github/workflows/javascript.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index d59098da75..6adb42e3e4 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -26,6 +26,16 @@ jobs: - run: npm install - 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 - name: Check Templated Files run: | cd ci From f7c515b889c521dbdb63579addc6f71ecca850d3 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 21:05:55 +1000 Subject: [PATCH 06/36] add "invoke static" step --- .github/workflows/javascript.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index 6adb42e3e4..caf82505f0 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -36,6 +36,7 @@ jobs: sudo apt-get install gettext pip3 install invoke invoke install + invoke static - name: Check Templated Files run: | cd ci From e85ddf3579528223fa7f1903debe4615045c89d5 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 21:10:31 +1000 Subject: [PATCH 07/36] Add required env vars --- .github/workflows/javascript.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index caf82505f0..110f5ffbe1 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -20,6 +20,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} INVENTREE_DB_ENGINE: sqlite3 INVENTREE_DB_NAME: inventree + INVENTREE_MEDIA_ROOT: ./media + INVENTREE_STATIC_ROOT: ./static steps: - name: Install node.js uses: actions/setup-node@v2 From 0620e656a060a066b152392de1ce5dc6d1307cf7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 22:12:41 +1000 Subject: [PATCH 08/36] Fix linting errors or tables.js --- .eslintrc.yml | 1 + InvenTree/templates/js/dynamic/inventree.js | 65 ++++----------------- InvenTree/templates/js/dynamic/settings.js | 4 +- InvenTree/templates/js/translated/tables.js | 28 ++++----- 4 files changed, 28 insertions(+), 70 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 3040a512c2..58952de736 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,6 +7,7 @@ env: extends: 'eslint:recommended' parserOptions: ecmaVersion: 12 + sourceType: module rules: accessor-pairs: error array-bracket-newline: 'off' diff --git a/InvenTree/templates/js/dynamic/inventree.js b/InvenTree/templates/js/dynamic/inventree.js index acfd57762c..a93d6efc0f 100644 --- a/InvenTree/templates/js/dynamic/inventree.js +++ b/InvenTree/templates/js/dynamic/inventree.js @@ -1,6 +1,6 @@ {% load inventree_extras %} -function attachClipboard(selector, containerselector, textElement) { +export function attachClipboard(selector, containerselector, textElement) { // set container if (containerselector){ containerselector = document.getElementById(containerselector); @@ -28,7 +28,7 @@ function attachClipboard(selector, containerselector, textElement) { } -function inventreeDocReady() { +export function inventreeDocReady() { /* Run this function when the HTML document is loaded. * This will be called for every page that extends "base.html" */ @@ -132,7 +132,7 @@ function inventreeDocReady() { }); } -function isFileTransfer(transfer) { +export function isFileTransfer(transfer) { /* Determine if a transfer (e.g. drag-and-drop) is a file transfer */ @@ -140,27 +140,7 @@ function isFileTransfer(transfer) { } -function isOnlineTransfer(transfer) { - /* Determine if a drag-and-drop transfer is from another website. - * e.g. dragged from another browser window - */ - - return transfer.items.length > 0; -} - - -function getImageUrlFromTransfer(transfer) { - /* Extract external image URL from a drag-and-dropped image - */ - - var url = transfer.getData('text/html').match(/src\s*=\s*"(.+?)"/)[1]; - - console.log('Image URL: ' + url); - - return url; -} - -function makeIconBadge(icon, title) { +export function makeIconBadge(icon, title) { // Construct an 'icon badge' which floats to the right of an object var html = ``; @@ -168,7 +148,8 @@ function makeIconBadge(icon, title) { return html; } -function makeIconButton(icon, cls, pk, title, options={}) { + +export function makeIconButton(icon, cls, pk, title, options={}) { // Construct an 'icon button' using the fontawesome set var classes = `btn btn-default btn-glyph ${cls}`; @@ -190,7 +171,7 @@ function makeIconButton(icon, cls, pk, title, options={}) { return html; } -function makeProgressBar(value, maximum, opts={}) { +export function makeProgressBar(value, maximum, opts={}) { /* * Render a progessbar! * @@ -258,7 +239,7 @@ function makeProgressBar(value, maximum, opts={}) { } -function enableDragAndDrop(element, url, options) { +export function enableDragAndDrop(element, url, options) { /* Enable drag-and-drop file uploading for a given element. Params: @@ -315,7 +296,7 @@ function enableDragAndDrop(element, url, options) { }); } -function imageHoverIcon(url) { +export function imageHoverIcon(url) { /* Render a small thumbnail icon for an image. * On mouseover, display a full-size version of the image */ @@ -334,7 +315,7 @@ function imageHoverIcon(url) { return html; } -function inventreeSave(name, value) { +export function inventreeSave(name, value) { /* * Save a key:value pair to local storage */ @@ -343,7 +324,7 @@ function inventreeSave(name, value) { localStorage.setItem(key, value); } -function inventreeLoad(name, defaultValue) { +export function inventreeLoad(name, defaultValue) { /* * Retrieve a key:value pair from local storage */ @@ -358,27 +339,3 @@ function inventreeLoad(name, defaultValue) { return value; } } - -function inventreeLoadInt(name) { - /* - * Retrieve a value from local storage, and attempt to cast to integer - */ - - var data = inventreeLoad(name); - - return parseInt(data, 10); -} - -function inventreeLoadFloat(name) { - - var data = inventreeLoad(name); - - return parseFloat(data); -} - -function inventreeDel(name) { - - var key = 'inventree-' + name; - - localStorage.removeItem(key); -} \ No newline at end of file diff --git a/InvenTree/templates/js/dynamic/settings.js b/InvenTree/templates/js/dynamic/settings.js index 60172ead64..21ae8b5330 100644 --- a/InvenTree/templates/js/dynamic/settings.js +++ b/InvenTree/templates/js/dynamic/settings.js @@ -3,7 +3,7 @@ {% user_settings request.user as USER_SETTINGS %} -var user_settings = { +export const user_settings = { {% for key, value in USER_SETTINGS.items %} {{ key }}: {% primitive_to_javascript value %}, {% endfor %} @@ -11,7 +11,7 @@ var user_settings = { {% global_settings as GLOBAL_SETTINGS %} -var global_settings = { +export const global_settings = { {% for key, value in GLOBAL_SETTINGS.items %} {{ key }}: {% primitive_to_javascript value %}, {% endfor %} diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index 88d9a5f99a..2b817f1bd9 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -1,30 +1,30 @@ {% load i18n %} +import { inventreeLoad, inventreeSave } from '{% url "inventree.js" %}'; -function reloadtable(table) { + +export function reloadtable(table) { $(table).bootstrapTable('refresh'); } -function editButton(url, text='Edit') { +export function editButton(url, text='{% trans "Edit" %}') { return ""; } -function deleteButton(url, text='Delete') { +export function deleteButton(url, text='{% trans "Delete" %}') { return ""; } -function renderLink(text, url, options={}) { +export function renderLink(text, url, options={}) { if (url === null || url === undefined || url === '') { return text; } var max_length = options.max_length || -1; - var remove_http = options.remove_http || false; - // Shorten the displayed length if required if ((max_length > 0) && (text.length > max_length)) { var slice_length = (max_length - 3) / 2; @@ -39,14 +39,14 @@ function renderLink(text, url, options={}) { } -function enableButtons(elements, enabled) { +export function enableButtons(elements, enabled) { for (let item of elements) { $(item).prop('disabled', !enabled); } } -function linkButtonsToSelection(table, buttons) { +export function linkButtonsToSelection(table, buttons) { /* Link a bootstrap-table object to one or more buttons. * The buttons will only be enabled if there is at least one row selected */ @@ -59,7 +59,7 @@ function linkButtonsToSelection(table, buttons) { enableButtons(buttons, table.bootstrapTable('getSelections').length > 0); // Add a callback - table.on('check.bs.table uncheck.bs.table check-some.bs.table uncheck-some.bs.table check-all.bs.table uncheck-all.bs.table', function(row) { + table.on('check.bs.table uncheck.bs.table check-some.bs.table uncheck-some.bs.table check-all.bs.table uncheck-all.bs.table', function() { enableButtons(buttons, table.bootstrapTable('getSelections').length > 0); }); } @@ -74,7 +74,7 @@ function isNumeric(n) { * Reload a table which has already been made into a bootstrap table. * New filters can be optionally provided, to change the query params. */ -function reloadTableFilters(table, filters) { +export function reloadTableFilters(table, filters) { // Simply perform a refresh if (filters == null) { @@ -88,8 +88,8 @@ function reloadTableFilters(table, filters) { // Construct a new list of filters to use for the query var params = {}; - for (var key in filters) { - params[key] = filters[key]; + for (var k in filters) { + params[k] = filters[k]; } // Original query params will override @@ -220,7 +220,7 @@ $.fn.inventreeTable = function(options) { }; // Callback when a column is changed - options.onColumnSwitch = function(field, checked) { + options.onColumnSwitch = function() { var columns = table.bootstrapTable('getVisibleColumns'); @@ -263,7 +263,7 @@ $.fn.inventreeTable = function(options) { } } -function customGroupSorter(sortName, sortOrder, sortData) { +export function customGroupSorter(sortName, sortOrder, sortData) { var order = sortOrder === 'desc' ? -1 : 1; From 140a2092c84659ef36c451cab9a27a2801194501 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 28 Aug 2021 22:18:20 +1000 Subject: [PATCH 09/36] fixes for table_filters.js --- InvenTree/templates/js/translated/table_filters.js | 4 +++- InvenTree/templates/status_codes.html | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index 9e173a7b37..cb8d9047d7 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -2,6 +2,8 @@ {% load status_codes %} {% load inventree_extras %} +import { global_settings } from '{% url "settings.js" %}'; + {% include "status_codes.html" with label='stock' options=StockStatus.list %} {% include "status_codes.html" with label='stockHistory' options=StockHistoryCode.list %} {% include "status_codes.html" with label='build' options=BuildStatus.list %} @@ -9,7 +11,7 @@ {% include "status_codes.html" with label='salesOrder' options=SalesOrderStatus.list %} -function getAvailableTableFilters(tableKey) { +export function getAvailableTableFilters(tableKey) { tableKey = tableKey.toLowerCase(); diff --git a/InvenTree/templates/status_codes.html b/InvenTree/templates/status_codes.html index e7bc2e951c..cfca5ea77b 100644 --- a/InvenTree/templates/status_codes.html +++ b/InvenTree/templates/status_codes.html @@ -1,12 +1,13 @@ /* * Status codes for the {{ label }} model. */ -var {{ label }}Codes = { +export const {{ label }}Codes = { {% for opt in options %}'{{ opt.key }}': { key: '{{ opt.key }}', value: '{{ opt.value }}',{% if opt.color %} label: 'label-{{ opt.color }}',{% endif %} - },{% endfor %} + }, + {% endfor %} }; /* @@ -14,7 +15,7 @@ var {{ label }}Codes = { * Uses the values specified in "status_codes.py" * This function is generated by the "status_codes.html" template */ -function {{ label }}StatusDisplay(key, options={}) { +export function {{ label }}StatusDisplay(key, options={}) { key = String(key); From 24ca1c56412840694c5e38b6c637ea7ff40d27cb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 13:06:02 +1000 Subject: [PATCH 10/36] Add "helpers.js" for common functions --- InvenTree/InvenTree/urls.py | 1 + InvenTree/templates/base.html | 1 + InvenTree/templates/js/dynamic/inventree.js | 129 +------------- InvenTree/templates/js/dynamic/settings.js | 6 +- InvenTree/templates/js/translated/helpers.js | 158 ++++++++++++++++++ .../templates/js/translated/table_filters.js | 2 +- InvenTree/templates/js/translated/tables.js | 16 +- 7 files changed, 177 insertions(+), 136 deletions(-) create mode 100644 InvenTree/templates/js/translated/helpers.js diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 71f6388c68..7d51c6a4cf 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -111,6 +111,7 @@ translated_javascript_urls = [ url(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'), url(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'), url(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'), + url(r'^helpers.js', DynamicJsView.as_view(template_name='js/translated/helpers.js'), name='helpers.js'), url(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'), url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'), url(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'), diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index 6f0cbe4acd..c2316ce4b0 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -160,6 +160,7 @@ + diff --git a/InvenTree/templates/js/dynamic/inventree.js b/InvenTree/templates/js/dynamic/inventree.js index a93d6efc0f..9813c30207 100644 --- a/InvenTree/templates/js/dynamic/inventree.js +++ b/InvenTree/templates/js/dynamic/inventree.js @@ -1,6 +1,6 @@ {% load inventree_extras %} -export function attachClipboard(selector, containerselector, textElement) { +function attachClipboard(selector, containerselector, textElement) { // set container if (containerselector){ containerselector = document.getElementById(containerselector); @@ -28,7 +28,7 @@ export function attachClipboard(selector, containerselector, textElement) { } -export function inventreeDocReady() { +function inventreeDocReady() { /* Run this function when the HTML document is loaded. * This will be called for every page that extends "base.html" */ @@ -132,7 +132,7 @@ export function inventreeDocReady() { }); } -export function isFileTransfer(transfer) { +function isFileTransfer(transfer) { /* Determine if a transfer (e.g. drag-and-drop) is a file transfer */ @@ -140,106 +140,7 @@ export function isFileTransfer(transfer) { } -export function makeIconBadge(icon, title) { - // Construct an 'icon badge' which floats to the right of an object - - var html = ``; - - return html; -} - - -export function makeIconButton(icon, cls, pk, title, options={}) { - // Construct an 'icon button' using the fontawesome set - - var classes = `btn btn-default btn-glyph ${cls}`; - - var id = `${cls}-${pk}`; - - var html = ''; - - var extraProps = ''; - - if (options.disabled) { - extraProps += "disabled='true' "; - } - - html += ``; - - return html; -} - -export function makeProgressBar(value, maximum, opts={}) { - /* - * Render a progessbar! - * - * @param value is the current value of the progress bar - * @param maximum is the maximum value of the progress bar - */ - - var options = opts || {}; - - value = parseFloat(value); - - var percent = 100; - - // Prevent div-by-zero or null value - if (maximum && maximum > 0) { - maximum = parseFloat(maximum); - percent = parseInt(value / maximum * 100); - } - - if (percent > 100) { - percent = 100; - } - - var extraclass = ''; - - if (value > maximum) { - extraclass='progress-bar-over'; - } else if (value < maximum) { - extraclass = 'progress-bar-under'; - } - - var style = options.style || ''; - - var text = ''; - - if (style == 'percent') { - // Display e.g. "50%" - - text = `${percent}%`; - } else if (style == 'max') { - // Display just the maximum value - text = `${maximum}`; - } else if (style == 'value') { - // Display just the current value - text = `${value}`; - } else if (style == 'blank') { - // No display! - text = ''; - } else { - /* Default style - * Display e.g. "5 / 10" - */ - - text = `${value} / ${maximum}`; - } - - var id = options.id || 'progress-bar'; - - return ` -
-
-
${text}
-
- `; -} - - -export function enableDragAndDrop(element, url, options) { +function enableDragAndDrop(element, url, options) { /* Enable drag-and-drop file uploading for a given element. Params: @@ -296,26 +197,8 @@ export function enableDragAndDrop(element, url, options) { }); } -export function imageHoverIcon(url) { - /* Render a small thumbnail icon for an image. - * On mouseover, display a full-size version of the image - */ - if (!url) { - url = '/static/img/blank_image.png'; - } - - var html = ` - - - - - `; - - return html; -} - -export function inventreeSave(name, value) { +function inventreeSave(name, value) { /* * Save a key:value pair to local storage */ @@ -324,7 +207,7 @@ export function inventreeSave(name, value) { localStorage.setItem(key, value); } -export function inventreeLoad(name, defaultValue) { +function inventreeLoad(name, defaultValue) { /* * Retrieve a key:value pair from local storage */ diff --git a/InvenTree/templates/js/dynamic/settings.js b/InvenTree/templates/js/dynamic/settings.js index 21ae8b5330..49d2650bef 100644 --- a/InvenTree/templates/js/dynamic/settings.js +++ b/InvenTree/templates/js/dynamic/settings.js @@ -2,16 +2,14 @@ // InvenTree settings {% user_settings request.user as USER_SETTINGS %} - -export const user_settings = { +const user_settings = { {% for key, value in USER_SETTINGS.items %} {{ key }}: {% primitive_to_javascript value %}, {% endfor %} }; {% global_settings as GLOBAL_SETTINGS %} - -export const global_settings = { +const global_settings = { {% for key, value in GLOBAL_SETTINGS.items %} {{ key }}: {% primitive_to_javascript value %}, {% endfor %} diff --git a/InvenTree/templates/js/translated/helpers.js b/InvenTree/templates/js/translated/helpers.js new file mode 100644 index 0000000000..446df773fe --- /dev/null +++ b/InvenTree/templates/js/translated/helpers.js @@ -0,0 +1,158 @@ +/* + * A set of simple helper functions + */ + + +function blankImage() { + return `/static/img/blank_image.png`; +} + +/* Render a small thumbnail icon for an image. + * On mouseover, display a full-size version of the image + */ +function imageHoverIcon(url) { + + if (!url) { + url = blankImage(); + } + + var html = ` + + + + + `; + + return html; +} + + +// Render a select2 thumbnail image +function select2Thumbnail(image) { + if (!image) { + image = blankImage(); + } + + return ``; +} + + +function makeIconBadge(icon, title) { + // Construct an 'icon badge' which floats to the right of an object + + var html = ``; + + return html; +} + + +function makeIconButton(icon, cls, pk, title, options={}) { + // Construct an 'icon button' using the fontawesome set + + var classes = `btn btn-default btn-glyph ${cls}`; + + var id = `${cls}-${pk}`; + + var html = ''; + + var extraProps = ''; + + if (options.disabled) { + extraProps += "disabled='true' "; + } + + html += ``; + + return html; +} + + +/* + * Render a progessbar! + * + * @param value is the current value of the progress bar + * @param maximum is the maximum value of the progress bar + */ +function makeProgressBar(value, maximum, opts={}) { + + var options = opts || {}; + + value = parseFloat(value); + + var percent = 100; + + // Prevent div-by-zero or null value + if (maximum && maximum > 0) { + maximum = parseFloat(maximum); + percent = parseInt(value / maximum * 100); + } + + if (percent > 100) { + percent = 100; + } + + var extraclass = ''; + + if (value > maximum) { + extraclass='progress-bar-over'; + } else if (value < maximum) { + extraclass = 'progress-bar-under'; + } + + var style = options.style || ''; + + var text = ''; + + if (style == 'percent') { + // Display e.g. "50%" + + text = `${percent}%`; + } else if (style == 'max') { + // Display just the maximum value + text = `${maximum}`; + } else if (style == 'value') { + // Display just the current value + text = `${value}`; + } else if (style == 'blank') { + // No display! + text = ''; + } else { + /* Default style + * Display e.g. "5 / 10" + */ + + text = `${value} / ${maximum}`; + } + + var id = options.id || 'progress-bar'; + + return ` +
+
+
${text}
+
+ `; +} + + +function renderLink(text, url, options={}) { + if (url === null || url === undefined || url === '') { + return text; + } + + var max_length = options.max_length || -1; + + // Shorten the displayed length if required + if ((max_length > 0) && (text.length > max_length)) { + var slice_length = (max_length - 3) / 2; + + var text_start = text.slice(0, slice_length); + var text_end = text.slice(-slice_length); + + text = `${text_start}...${text_end}`; + } + + return '' + text + ''; +} \ No newline at end of file diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index cb8d9047d7..423c3c989f 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -11,7 +11,7 @@ import { global_settings } from '{% url "settings.js" %}'; {% include "status_codes.html" with label='salesOrder' options=SalesOrderStatus.list %} -export function getAvailableTableFilters(tableKey) { +function getAvailableTableFilters(tableKey) { tableKey = tableKey.toLowerCase(); diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index 2b817f1bd9..a1249d0176 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -3,22 +3,22 @@ import { inventreeLoad, inventreeSave } from '{% url "inventree.js" %}'; -export function reloadtable(table) { +function reloadtable(table) { $(table).bootstrapTable('refresh'); } -export function editButton(url, text='{% trans "Edit" %}') { +function editButton(url, text='{% trans "Edit" %}') { return ""; } -export function deleteButton(url, text='{% trans "Delete" %}') { +function deleteButton(url, text='{% trans "Delete" %}') { return ""; } -export function renderLink(text, url, options={}) { +function renderLink(text, url, options={}) { if (url === null || url === undefined || url === '') { return text; } @@ -39,14 +39,14 @@ export function renderLink(text, url, options={}) { } -export function enableButtons(elements, enabled) { +function enableButtons(elements, enabled) { for (let item of elements) { $(item).prop('disabled', !enabled); } } -export function linkButtonsToSelection(table, buttons) { +function linkButtonsToSelection(table, buttons) { /* Link a bootstrap-table object to one or more buttons. * The buttons will only be enabled if there is at least one row selected */ @@ -74,7 +74,7 @@ function isNumeric(n) { * Reload a table which has already been made into a bootstrap table. * New filters can be optionally provided, to change the query params. */ -export function reloadTableFilters(table, filters) { +function reloadTableFilters(table, filters) { // Simply perform a refresh if (filters == null) { @@ -263,7 +263,7 @@ $.fn.inventreeTable = function(options) { } } -export function customGroupSorter(sortName, sortOrder, sortData) { +function customGroupSorter(sortName, sortOrder, sortData) { var order = sortOrder === 'desc' ? -1 : 1; From 5d45fce240d5f2446f09a907ca40ae8bf4d15ce6 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 13:10:58 +1000 Subject: [PATCH 11/36] remove import / export calls --- InvenTree/templates/js/translated/helpers.js | 11 +++++++++++ InvenTree/templates/js/translated/part.js | 9 --------- InvenTree/templates/js/translated/table_filters.js | 2 -- InvenTree/templates/js/translated/tables.js | 2 -- InvenTree/templates/status_codes.html | 4 ++-- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/InvenTree/templates/js/translated/helpers.js b/InvenTree/templates/js/translated/helpers.js index 446df773fe..a66a634ece 100644 --- a/InvenTree/templates/js/translated/helpers.js +++ b/InvenTree/templates/js/translated/helpers.js @@ -1,3 +1,14 @@ +{% load i18n %} + +function yesNoLabel(value) { + if (value) { + return `{% trans "YES" %}`; + } else { + return `{% trans "NO" %}`; + } +} + + /* * A set of simple helper functions */ diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 052a33ec5c..98a9be5358 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -5,15 +5,6 @@ * Requires api.js to be loaded first */ -function yesNoLabel(value) { - if (value) { - return `{% trans "YES" %}`; - } else { - return `{% trans "NO" %}`; - } -} - - function partGroups(options={}) { return { diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index 423c3c989f..9e173a7b37 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -2,8 +2,6 @@ {% load status_codes %} {% load inventree_extras %} -import { global_settings } from '{% url "settings.js" %}'; - {% include "status_codes.html" with label='stock' options=StockStatus.list %} {% include "status_codes.html" with label='stockHistory' options=StockHistoryCode.list %} {% include "status_codes.html" with label='build' options=BuildStatus.list %} diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index a1249d0176..c3f938f9c8 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -1,7 +1,5 @@ {% load i18n %} -import { inventreeLoad, inventreeSave } from '{% url "inventree.js" %}'; - function reloadtable(table) { $(table).bootstrapTable('refresh'); diff --git a/InvenTree/templates/status_codes.html b/InvenTree/templates/status_codes.html index cfca5ea77b..453a7914e2 100644 --- a/InvenTree/templates/status_codes.html +++ b/InvenTree/templates/status_codes.html @@ -1,7 +1,7 @@ /* * Status codes for the {{ label }} model. */ -export const {{ label }}Codes = { +const {{ label }}Codes = { {% for opt in options %}'{{ opt.key }}': { key: '{{ opt.key }}', value: '{{ opt.value }}',{% if opt.color %} @@ -15,7 +15,7 @@ export const {{ label }}Codes = { * Uses the values specified in "status_codes.py" * This function is generated by the "status_codes.html" template */ -export function {{ label }}StatusDisplay(key, options={}) { +function {{ label }}StatusDisplay(key, options={}) { key = String(key); From 65874447edc5c25e11a6b4e6fefd3b45133e416e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 13:13:12 +1000 Subject: [PATCH 12/36] bug fix --- InvenTree/templates/js/translated/helpers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/templates/js/translated/helpers.js b/InvenTree/templates/js/translated/helpers.js index a66a634ece..2382633e8d 100644 --- a/InvenTree/templates/js/translated/helpers.js +++ b/InvenTree/templates/js/translated/helpers.js @@ -29,8 +29,8 @@ function imageHoverIcon(url) { var html = ` - - + + `; From c846aeb60fc16cb17fbdcd98fca07ae85d6a5526 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:07:34 +1000 Subject: [PATCH 13/36] stock.js --- .eslintrc.yml | 4 +- InvenTree/templates/js/translated/helpers.js | 26 ++- InvenTree/templates/js/translated/stock.js | 160 ++++++++++++------ .../templates/js/translated/table_filters.js | 13 ++ InvenTree/templates/js/translated/tables.js | 22 +-- 5 files changed, 157 insertions(+), 68 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 58952de736..966a822732 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,5 +1,5 @@ env: - commonjs: true + commonjs: false es6: true browser: true es2021: true @@ -7,7 +7,7 @@ env: extends: 'eslint:recommended' parserOptions: ecmaVersion: 12 - sourceType: module + sourceType: 'script' rules: accessor-pairs: error array-bracket-newline: 'off' diff --git a/InvenTree/templates/js/translated/helpers.js b/InvenTree/templates/js/translated/helpers.js index 2382633e8d..d65d201da3 100644 --- a/InvenTree/templates/js/translated/helpers.js +++ b/InvenTree/templates/js/translated/helpers.js @@ -1,5 +1,18 @@ {% load i18n %} +/* exported + blankImage, + deleteButton, + editButton, + imageHoverIcon, + makeIconBadge, + makeIconButton, + makeProgressBar, + renderLink, + select2Thumbnail, + yesNoLabel, +*/ + function yesNoLabel(value) { if (value) { return `{% trans "YES" %}`; @@ -9,9 +22,14 @@ function yesNoLabel(value) { } -/* - * A set of simple helper functions - */ +function editButton(url, text='{% trans "Edit" %}') { + return ""; +} + + +function deleteButton(url, text='{% trans "Delete" %}') { + return ""; +} function blankImage() { @@ -165,5 +183,5 @@ function renderLink(text, url, options={}) { text = `${text_start}...${text_end}`; } - return '' + text + ''; + return `${text}`; } \ No newline at end of file diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js index 99c3824cac..7b7c1b6272 100644 --- a/InvenTree/templates/js/translated/stock.js +++ b/InvenTree/templates/js/translated/stock.js @@ -2,6 +2,63 @@ {% load inventree_extras %} {% load status_codes %} +/* globals + attachSelect, + attachToggle, + blankImage, + enableField, + clearField, + clearFieldOptions, + closeModal, + constructFormBody, + constructNumberInput, + createNewModal, + getFormFieldValue, + global_settings, + handleFormErrors, + imageHoverIcon, + inventreeDelete, + inventreeGet, + inventreePut, + launchModalForm, + linkButtonsToSelection, + loadTableFilters, + makeIconBadge, + makeIconButton, + makeOptionsList, + makePartIcons, + modalEnable, + modalSetContent, + modalSetTitle, + modalSubmit, + moment, + openModal, + printStockItemLabels, + printTestReports, + renderLink, + reloadFieldOptions, + scanItemsIntoLocation, + showAlertDialog, + setFieldValue, + setupFilterList, + showApiError, + stockStatusDisplay, +*/ + +/* exported + createNewStockItem, + exportStock, + loadInstalledInTable, + loadStockLocationTable, + loadStockTable, + loadStockTestResultsTable, + loadStockTrackingTable, + loadTableFilters, + locationFields, + removeStockRow, + stockStatusCodes, +*/ + function locationFields() { return { @@ -209,7 +266,7 @@ function adjustStock(action, items, options={}) { title: readonly ? '{% trans "Quantity cannot be adjusted for serialized stock" %}' : '{% trans "Specify stock quantity" %}', } ) - }; + } var buttons = `
`; @@ -283,7 +340,7 @@ function adjustStock(action, items, options={}) { confirm: true, confirmMessage: '{% trans "Confirm stock adjustment" %}', modal: modal, - onSubmit: function(fields, opts) { + onSubmit: function(fields) { // "Delete" action gets handled differently if (action == 'delete') { @@ -327,7 +384,7 @@ function adjustStock(action, items, options={}) { }); // Add in extra field data - for (field_name in extraFields) { + for (var field_name in extraFields) { data[field_name] = getFormFieldValue( field_name, fields[field_name], @@ -342,7 +399,7 @@ function adjustStock(action, items, options={}) { data, { method: 'POST', - success: function(response, status) { + success: function() { // Destroy the modal window $(modal).modal('hide'); @@ -544,7 +601,7 @@ function loadStockTestResultsTable(table, options) { { success: function(data) { // Iterate through the returned test data - data.forEach(function(item, index) { + data.forEach(function(item) { var match = false; var override = false; @@ -683,8 +740,8 @@ function loadStockTable(table, options) { var original = {}; - for (var key in params) { - original[key] = params[key]; + for (var k in params) { + original[k] = params[k]; } setupFilterList(filterKey, table, filterListElement); @@ -700,10 +757,13 @@ function loadStockTable(table, options) { grouping = options.grouping; } + var col = null; + // Explicitly disable part grouping functionality // Might be able to add this in later on, // but there is a bug which makes this crash if paginating on the server side. // Ref: https://github.com/wenzhixin/bootstrap-table/issues/3250 + // eslint-disable-next-line no-unused-vars grouping = false; var columns = [ @@ -727,22 +787,24 @@ function loadStockTable(table, options) { sortName: 'part__name', visible: params['part_detail'], switchable: params['part_detail'], - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/stock/item/${row.pk}/`; var thumb = row.part_detail.thumbnail; var name = row.part_detail.full_name; - html = imageHoverIcon(thumb) + renderLink(name, url); + var html = imageHoverIcon(thumb) + renderLink(name, url); html += makePartIcons(row.part_detail); return html; } }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { @@ -751,13 +813,15 @@ function loadStockTable(table, options) { sortName: 'part__IPN', visible: params['part_detail'], switchable: params['part_detail'], - formatter: function(value, row, index, field) { + formatter: function(value, row) { return row.part_detail.IPN; }, }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); columns.push({ @@ -765,7 +829,7 @@ function loadStockTable(table, options) { title: '{% trans "Description" %}', visible: params['part_detail'], switchable: params['part_detail'], - formatter: function(value, row, index, field) { + formatter: function(value, row) { return row.part_detail.description; } }); @@ -773,7 +837,7 @@ function loadStockTable(table, options) { col = { field: 'quantity', title: '{% trans "Stock" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var val = parseFloat(value); @@ -834,51 +898,61 @@ function loadStockTable(table, options) { return html; } }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'status', title: '{% trans "Status" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { return stockStatusDisplay(value); }, }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'batch', title: '{% trans "Batch" %}', }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'location_detail.pathstring', title: '{% trans "Location" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return locationDetail(row); } }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'stocktake_date', title: '{% trans "Stocktake" %}', }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { @@ -887,18 +961,22 @@ function loadStockTable(table, options) { visible: global_settings.STOCK_ENABLE_EXPIRY, switchable: global_settings.STOCK_ENABLE_EXPIRY, }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'updated', title: '{% trans "Last Updated" %}', }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); columns.push({ @@ -963,7 +1041,7 @@ function loadStockTable(table, options) { if (!options.params.ordering) { col.sortable = true; col.sortName = 'purchase_price'; - }; + } columns.push(col); @@ -1368,8 +1446,8 @@ function loadStockLocationTable(table, options) { var original = {}; - for (var key in params) { - original[key] = params[key]; + for (var k in params) { + original[k] = params[k]; } setupFilterList(filterKey, table, filterListElement); @@ -1437,7 +1515,7 @@ function loadStockTrackingTable(table, options) { field: 'date', title: '{% trans "Date" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value) { var m = moment(value); if (m.isValid()) { @@ -1453,7 +1531,7 @@ function loadStockTrackingTable(table, options) { cols.push({ field: 'label', title: '{% trans "Description" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var html = "" + value + ""; if (row.notes) { @@ -1468,7 +1546,7 @@ function loadStockTrackingTable(table, options) { cols.push({ field: 'deltas', title: '{% trans "Details" %}', - formatter: function(details, row, index, field) { + formatter: function(details, row) { var html = ``; if (!details) { @@ -1603,7 +1681,7 @@ function loadStockTrackingTable(table, options) { cols.push({ field: 'user', title: '{% trans "User" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value) { // TODO - Format the user's first and last names @@ -1741,26 +1819,6 @@ function loadInstalledInTable(table, options) { * Display a table showing the stock items which are installed in this stock item. */ - function updateCallbacks() { - // Setup callback functions when buttons are pressed - table.find('.button-install').click(function() { - var pk = $(this).attr('pk'); - - launchModalForm( - `/stock/item/${options.stock_item}/install/`, - { - data: { - part: pk, - }, - success: function() { - // Refresh entire table! - table.bootstrapTable('refresh'); - } - } - ); - }); - } - table.inventreeTable({ url: "{% url 'api-stock-list' %}", queryParams: { @@ -1802,7 +1860,7 @@ function loadInstalledInTable(table, options) { { field: 'status', title: '{% trans "Status" %}', - formatter: function(value, row) { + formatter: function(value) { return stockStatusDisplay(value); } }, diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index 9e173a7b37..922e4f2497 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -8,6 +8,19 @@ {% include "status_codes.html" with label='purchaseOrder' options=PurchaseOrderStatus.list %} {% include "status_codes.html" with label='salesOrder' options=SalesOrderStatus.list %} +/* globals + global_settings +*/ + +/* exported + buildStatusDisplay, + getAvailableTableFilters, + purchaseOrderStatusDisplay, + salesOrderStatusDisplay, + stockHistoryStatusDisplay, + stockStatusDisplay, +*/ + function getAvailableTableFilters(tableKey) { diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index c3f938f9c8..d5c9021806 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -1,21 +1,21 @@ {% load i18n %} +/* global + inventreeLoad, + inventreeSave, +*/ + +/* exported + customGroupSorter, + reloadtable, + renderLink, + reloadTableFilters, +*/ function reloadtable(table) { $(table).bootstrapTable('refresh'); } - -function editButton(url, text='{% trans "Edit" %}') { - return ""; -} - - -function deleteButton(url, text='{% trans "Delete" %}') { - return ""; -} - - function renderLink(text, url, options={}) { if (url === null || url === undefined || url === '') { return text; From 3e03b1c31d44330354d0b389cfec512c32836b0e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:12:35 +1000 Subject: [PATCH 14/36] report.js --- InvenTree/templates/js/dynamic/settings.js | 6 ++++- InvenTree/templates/js/translated/report.js | 30 +++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/InvenTree/templates/js/dynamic/settings.js b/InvenTree/templates/js/dynamic/settings.js index 49d2650bef..7f606b7548 100644 --- a/InvenTree/templates/js/dynamic/settings.js +++ b/InvenTree/templates/js/dynamic/settings.js @@ -1,5 +1,9 @@ {% load inventree_extras %} -// InvenTree settings + +/* exported + user_settings, + global_settings, +*/ {% user_settings request.user as USER_SETTINGS %} const user_settings = { diff --git a/InvenTree/templates/js/translated/report.js b/InvenTree/templates/js/translated/report.js index 370978be04..ff7cef941a 100644 --- a/InvenTree/templates/js/translated/report.js +++ b/InvenTree/templates/js/translated/report.js @@ -1,5 +1,25 @@ {% load i18n %} +/* globals + attachSelect, + closeModal, + inventreeGet, + openModal, + makeOptionsList, + modalEnable, + modalSetContent, + modalSetTitle, + modalSubmit, + showAlertDialog, +*/ + +/* exported + printBomReports, + printBuildReports, + printPurchaseOrderReports, + printSalesOrderReports, + printTestReports, +*/ function selectReport(reports, items, options={}) { /** @@ -88,7 +108,7 @@ function selectReport(reports, items, options={}) { } -function printTestReports(items, options={}) { +function printTestReports(items) { /** * Print test reports for the provided stock item(s) */ @@ -142,7 +162,7 @@ function printTestReports(items, options={}) { } -function printBuildReports(builds, options={}) { +function printBuildReports(builds) { /** * Print Build report for the provided build(s) */ @@ -195,7 +215,7 @@ function printBuildReports(builds, options={}) { } -function printBomReports(parts, options={}) { +function printBomReports(parts) { /** * Print BOM reports for the provided part(s) */ @@ -249,7 +269,7 @@ function printBomReports(parts, options={}) { } -function printPurchaseOrderReports(orders, options={}) { +function printPurchaseOrderReports(orders) { /** * Print PO reports for the provided purchase order(s) */ @@ -303,7 +323,7 @@ function printPurchaseOrderReports(orders, options={}) { } -function printSalesOrderReports(orders, options={}) { +function printSalesOrderReports(orders) { /** * Print SO reports for the provided purchase order(s) */ From 7d5b85923357ef268a0ed0596c483607354b5863 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:39:58 +1000 Subject: [PATCH 15/36] part.js --- InvenTree/templates/js/translated/part.js | 93 +++++++++++++++++------ 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 98a9be5358..b0c2330360 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -1,11 +1,48 @@ {% load i18n %} {% load inventree_extras %} +/* globals + Chart, + constructForm, + global_settings, + imageHoverIcon, + inventreeGet, + inventreePut, + launchModalForm, + linkButtonsToSelection, + loadTableFilters, + makeIconBadge, + makeIconButton, + printPartLabels, + renderLink, + setFormGroupVisibility, + setupFilterList, + yesNoLabel, +*/ + +/* exported + duplicatePart, + editCategory, + editPart, + initPriceBreakSet, + loadBomChart, + loadParametricPartTable, + loadPartCategoryTable, + loadPartParameterTable, + loadPartTable, + loadPartTestTemplateTable, + loadPartVariantTable, + loadSellPricingChart, + loadSimplePartTable, + loadStockPricingChart, + toggleStar, +*/ + /* Part API functions * Requires api.js to be loaded first */ -function partGroups(options={}) { +function partGroups() { return { attributes: { @@ -36,7 +73,7 @@ function partFields(options={}) { category: { secondary: { title: '{% trans "Add Part Category" %}', - fields: function(data) { + fields: function() { var fields = categoryFields(); return fields; @@ -255,7 +292,7 @@ function categoryFields() { // Edit a PartCategory via the API -function editCategory(pk, options={}) { +function editCategory(pk) { var url = `/api/part/category/${pk}/`; @@ -270,7 +307,7 @@ function editCategory(pk, options={}) { } -function editPart(pk, options={}) { +function editPart(pk) { var url = `/api/part/${pk}/`; @@ -282,7 +319,7 @@ function editPart(pk, options={}) { constructForm(url, { fields: fields, - groups: partGroups(), + groups: groups, title: '{% trans "Edit Part" %}', reload: true, }); @@ -361,7 +398,7 @@ function toggleStar(options) { } -function makePartIcons(part, options={}) { +function makePartIcons(part) { /* Render a set of icons for the given part. */ @@ -388,7 +425,7 @@ function makePartIcons(part, options={}) { } if (part.salable) { - html += makeIconBadge('fa-dollar-sign', title='{% trans "Salable part" %}'); + html += makeIconBadge('fa-dollar-sign', '{% trans "Salable part" %}'); } if (!part.active) { @@ -428,7 +465,7 @@ function loadPartVariantTable(table, partId, options={}) { field: 'name', title: '{% trans "Name" %}', switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var html = ''; var name = ''; @@ -646,14 +683,14 @@ function loadParametricPartTable(table, options={}) { var columns = []; - for (header of table_headers) { + for (var header of table_headers) { if (header === 'part') { columns.push({ field: header, title: '{% trans "Part" %}', sortable: true, sortName: 'name', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var name = ''; @@ -776,6 +813,8 @@ function loadPartTable(table, url, options={}) { var filters = {}; + var col = null; + if (!options.disableFilters) { filters = loadTableFilters("parts"); } @@ -809,16 +848,18 @@ function loadPartTable(table, url, options={}) { field: 'IPN', title: 'IPN', }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'name', title: '{% trans "Part" %}', switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var name = ''; @@ -844,16 +885,18 @@ function loadPartTable(table, url, options={}) { return display; } - }; + } + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); columns.push({ field: 'description', title: '{% trans "Description" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (row.is_template) { value = '' + value + ''; @@ -867,7 +910,7 @@ function loadPartTable(table, url, options={}) { sortName: 'category', field: 'category_detail', title: '{% trans "Category" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (row.category) { return renderLink(value.pathstring, "/part/category/" + row.category + "/"); } @@ -876,16 +919,18 @@ function loadPartTable(table, url, options={}) { } } }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); col = { field: 'in_stock', title: '{% trans "Stock" %}', searchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var link = "stock"; if (value) { @@ -912,15 +957,17 @@ function loadPartTable(table, url, options={}) { return renderLink(value, '/part/' + row.pk + "/" + link + "/"); } }; + if (!options.params.ordering) { col['sortable'] = true; - }; + } + columns.push(col); columns.push({ field: 'link', title: '{% trans "Link" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { return renderLink( value, value, { @@ -1122,8 +1169,8 @@ function loadPartTestTemplateTable(table, options) { var original = {}; - for (var key in params) { - original[key] = params[key]; + for (var k in params) { + original[k] = params[k]; } setupFilterList("parttests", table, filterListElement); @@ -1268,7 +1315,7 @@ function loadPriceBreakTable(table, options) { field: 'price', title: '{% trans "Price" %}', sortable: true, - formatter: function(value, row, index) { + formatter: function(value, row) { var html = value; html += `
` From 90a75ac7cbf86c2aabf0111c8e31d4b548a4ea9d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:44:44 +1000 Subject: [PATCH 16/36] nav.js --- InvenTree/templates/js/dynamic/nav.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/InvenTree/templates/js/dynamic/nav.js b/InvenTree/templates/js/dynamic/nav.js index 601c0f4dcf..0b49be23c6 100644 --- a/InvenTree/templates/js/dynamic/nav.js +++ b/InvenTree/templates/js/dynamic/nav.js @@ -1,3 +1,10 @@ +/* globals +*/ + +/* exported + attachNavCallbacks, + onPanelLoad, +*/ /* * Attach callbacks to navigation bar elements. @@ -55,7 +62,7 @@ function activatePanel(panelName, options={}) { // Iterate through the available 'select' elements until one matches panelName = null; - $('.nav-toggle').each(function(item) { + $('.nav-toggle').each(function() { var panel_name = $(this).attr('id').replace('select-', ''); if ($(`#panel-${panel_name}`).length && (panelName == null)) { @@ -83,9 +90,9 @@ function activatePanel(panelName, options={}) { $('.list-group-item').removeClass('active'); // Find the associated selector - var select = `#select-${panelName}`; + var selectElement = `#select-${panelName}`; - $(select).parent('.list-group-item').addClass('active'); + $(selectElement).parent('.list-group-item').addClass('active'); } @@ -96,7 +103,7 @@ function onPanelLoad(panel, callback) { var panelId = `#panel-${panel}`; - $(panelId).on('fadeInStarted', function(e) { + $(panelId).on('fadeInStarted', function() { // Trigger the callback callback(); From 00f012311dcc7bc231b6134aba27756a8419e844 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:49:40 +1000 Subject: [PATCH 17/36] inventree.js --- InvenTree/templates/js/dynamic/inventree.js | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/InvenTree/templates/js/dynamic/inventree.js b/InvenTree/templates/js/dynamic/inventree.js index 9813c30207..2a151fcdaf 100644 --- a/InvenTree/templates/js/dynamic/inventree.js +++ b/InvenTree/templates/js/dynamic/inventree.js @@ -1,5 +1,20 @@ {% load inventree_extras %} +/* globals + ClipboardJS, + inventreeFormDataUpload, + launchModalForm, + user_settings, +*/ + +/* exported + attachClipboard, + enableDragAndDrop, + inventreeDocReady, + inventreeLoad, + inventreeSave, +*/ + function attachClipboard(selector, containerselector, textElement) { // set container if (containerselector){ @@ -8,6 +23,8 @@ function attachClipboard(selector, containerselector, textElement) { containerselector = document.body; } + var text = null; + // set text-function if (textElement){ text = function() { @@ -21,6 +38,7 @@ function attachClipboard(selector, containerselector, textElement) { } // create Clipboard + // eslint-disable-next-line no-unused-vars var cis = new ClipboardJS(selector, { text: text, container: containerselector @@ -51,12 +69,13 @@ function inventreeDocReady() { // TODO - Only indicate that a drop event will occur if a file is being dragged var transfer = event.originalEvent.dataTransfer; + // eslint-disable-next-line no-constant-condition if (true || isFileTransfer(transfer)) { $(this).addClass('dragover'); } }); - $('.dropzone').on('dragleave drop', function(event) { + $('.dropzone').on('dragleave drop', function() { $(this).removeClass('dragover'); }); @@ -154,7 +173,7 @@ function enableDragAndDrop(element, url, options) { method - HTTP method */ - data = options.data || {}; + var data = options.data || {}; $(element).on('drop', function(event) { From 50b54f096624628f495d833e703dc2fe784d9041 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 14:57:17 +1000 Subject: [PATCH 18/36] order.js --- InvenTree/templates/js/translated/order.js | 44 +++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index c6dd773373..371bcf974d 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -1,6 +1,33 @@ {% load i18n %} {% load inventree_extras %} +/* globals + companyFormFields, + constructForm, + createSupplierPart, + global_settings, + imageHoverIcon, + inventreeGet, + launchModalForm, + loadTableFilters, + makeIconBadge, + purchaseOrderStatusDisplay, + renderLink, + salesOrderStatusDisplay, + setupFilterList, +*/ + +/* exported + createSalesOrder, + editPurchaseOrderLineItem, + loadPurchaseOrderTable, + loadSalesOrderAllocationTable, + loadSalesOrderTable, + newPurchaseOrderFromOrderWizard, + newSupplierPartFromOrderWizard, + removeOrderRowFromOrderWizard, + removePurchaseOrderLineItem, +*/ // Create a new SalesOrder function createSalesOrder(options={}) { @@ -15,7 +42,7 @@ function createSalesOrder(options={}) { value: options.customer, secondary: { title: '{% trans "Add Customer" %}', - fields: function(data) { + fields: function() { var fields = companyFormFields(); fields.is_customer.value = true; @@ -56,7 +83,7 @@ function createPurchaseOrder(options={}) { value: options.supplier, secondary: { title: '{% trans "Add Supplier" %}', - fields: function(data) { + fields: function() { var fields = companyFormFields(); fields.is_supplier.value = true; @@ -278,7 +305,7 @@ function loadPurchaseOrderTable(table, options) { title: '{% trans "Purchase Order" %}', sortable: true, switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var prefix = global_settings.PURCHASEORDER_REFERENCE_PREFIX; @@ -300,7 +327,7 @@ function loadPurchaseOrderTable(table, options) { title: '{% trans "Supplier" %}', sortable: true, sortName: 'supplier__name', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return imageHoverIcon(row.supplier_detail.image) + renderLink(row.supplier_detail.name, `/company/${row.supplier}/purchase-orders/`); } }, @@ -316,7 +343,7 @@ function loadPurchaseOrderTable(table, options) { field: 'status', title: '{% trans "Status" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { return purchaseOrderStatusDisplay(row.status, row.status_text); } }, @@ -373,7 +400,7 @@ function loadSalesOrderTable(table, options) { sortable: true, field: 'reference', title: '{% trans "Sales Order" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var prefix = global_settings.SALESORDER_REFERENCE_PREFIX; @@ -395,7 +422,7 @@ function loadSalesOrderTable(table, options) { sortName: 'customer__name', field: 'customer_detail', title: '{% trans "Customer" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (!row.customer_detail) { return '{% trans "Invalid Customer" %}'; @@ -418,7 +445,7 @@ function loadSalesOrderTable(table, options) { sortable: true, field: 'status', title: '{% trans "Status" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return salesOrderStatusDisplay(row.status, row.status_text); } }, @@ -486,7 +513,6 @@ function loadSalesOrderAllocationTable(table, options={}) { field: 'order', switchable: false, title: '{% trans "Order" %}', - switchable: false, formatter: function(value, row) { var prefix = global_settings.SALESORDER_REFERENCE_PREFIX; From e0e7788af6b3ad63e6f1380f8c5e7ca091c697d8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 15:32:01 +1000 Subject: [PATCH 19/36] More js fixes --- InvenTree/templates/js/dynamic/calendar.js | 9 ++++ InvenTree/templates/js/translated/api.js | 18 ++++++-- .../templates/js/translated/attachment.js | 10 +++++ InvenTree/templates/js/translated/filters.js | 26 ++++++----- InvenTree/templates/js/translated/modals.js | 45 ++++++++++++------- .../js/translated/model_renderers.js | 38 ++++++++++------ 6 files changed, 101 insertions(+), 45 deletions(-) diff --git a/InvenTree/templates/js/dynamic/calendar.js b/InvenTree/templates/js/dynamic/calendar.js index 861bbe1727..fd36d689f5 100644 --- a/InvenTree/templates/js/dynamic/calendar.js +++ b/InvenTree/templates/js/dynamic/calendar.js @@ -1,5 +1,14 @@ {% load i18n %} +/* globals +*/ + +/* exported + clearEvents, + endDate, + startDate, +*/ + /** * Helper functions for calendar display */ diff --git a/InvenTree/templates/js/translated/api.js b/InvenTree/templates/js/translated/api.js index 4cf07638dc..8b72e166a2 100644 --- a/InvenTree/templates/js/translated/api.js +++ b/InvenTree/templates/js/translated/api.js @@ -1,7 +1,17 @@ {% load i18n %} {% load inventree_extras %} -var jQuery = window.$; +/* globals + renderErrorMessage, + showAlertDialog, +*/ + +/* exported + inventreeGet, + inventreeDelete, + inventreeFormDataUpload, + showApiError, +*/ $.urlParam = function(name){ var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); @@ -35,7 +45,7 @@ function inventreeGet(url, filters={}, options={}) { var csrftoken = getCookie('csrftoken'); return $.ajax({ - beforeSend: function(xhr, settings) { + beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRFToken', csrftoken); }, url: url, @@ -73,7 +83,7 @@ function inventreeFormDataUpload(url, data, options={}) { var csrftoken = getCookie('csrftoken'); return $.ajax({ - beforeSend: function(xhr, settings) { + beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRFToken', csrftoken); }, url: url, @@ -105,7 +115,7 @@ function inventreePut(url, data={}, options={}) { var csrftoken = getCookie('csrftoken'); return $.ajax({ - beforeSend: function(xhr, settings) { + beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRFToken', csrftoken); }, url: url, diff --git a/InvenTree/templates/js/translated/attachment.js b/InvenTree/templates/js/translated/attachment.js index bffe3d9995..3264bd9413 100644 --- a/InvenTree/templates/js/translated/attachment.js +++ b/InvenTree/templates/js/translated/attachment.js @@ -1,5 +1,15 @@ {% load i18n %} +/* globals + makeIconButton, + renderLink, +*/ + +/* exported + loadAttachmentTable, + reloadAttachmentTable, +*/ + function reloadAttachmentTable() { $('#attachment-table').bootstrapTable("refresh"); diff --git a/InvenTree/templates/js/translated/filters.js b/InvenTree/templates/js/translated/filters.js index bc0dc1b958..8d70715ff0 100644 --- a/InvenTree/templates/js/translated/filters.js +++ b/InvenTree/templates/js/translated/filters.js @@ -1,5 +1,16 @@ {% load i18n %} +/* globals + getAvailableTableFilters, + inventreeLoad, + inventreeSave, + reloadTableFilters, +*/ + +/* exported + setupFilterList, +*/ + /** * Code for managing query filters / table options. * @@ -42,7 +53,7 @@ function loadTableFilters(tableKey) { var filters = {}; - filterstring.split("&").forEach(function(item, index) { + filterstring.split("&").forEach(function(item) { item = item.trim(); if (item.length > 0) { @@ -227,7 +238,7 @@ function generateFilterInput(tableKey, filterKey) { html = ``; @@ -1838,7 +1867,7 @@ function constructChoiceInput(name, parameters, options) { * be converted into a select2 input. * This will then be served custom data from the API (as required)... */ -function constructRelatedFieldInput(name, parameters, options) { +function constructRelatedFieldInput(name) { var html = ``; @@ -1851,7 +1880,7 @@ function constructRelatedFieldInput(name, parameters, options) { /* * Construct a field for file upload */ -function constructFileUploadInput(name, parameters, options) { +function constructFileUploadInput(name, parameters) { var cls = 'clearablefileinput'; @@ -1871,7 +1900,7 @@ function constructFileUploadInput(name, parameters, options) { /* * Construct a field for a date input */ -function constructDateInput(name, parameters, options) { +function constructDateInput(name, parameters) { return constructInputOptions( name, @@ -1886,7 +1915,7 @@ function constructDateInput(name, parameters, options) { * Construct a "candy" field input * No actual field data! */ -function constructCandyInput(name, parameters, options) { +function constructCandyInput(name, parameters) { return parameters.html; @@ -1901,7 +1930,7 @@ function constructCandyInput(name, parameters, options) { * - parameters: Field parameters returned by the OPTIONS method * */ -function constructHelpText(name, parameters, options) { +function constructHelpText(name, parameters) { var style = ''; From 0835fe92a05acd3eb29330b52538ba6a43acae27 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 15:54:31 +1000 Subject: [PATCH 22/36] bom.js --- InvenTree/templates/js/translated/bom.js | 42 +++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/InvenTree/templates/js/translated/bom.js b/InvenTree/templates/js/translated/bom.js index 37a3eb23b0..399d2a08f3 100644 --- a/InvenTree/templates/js/translated/bom.js +++ b/InvenTree/templates/js/translated/bom.js @@ -1,5 +1,25 @@ {% load i18n %} +/* globals + constructForm, + imageHoverIcon, + inventreeGet, + inventreePut, + launchModalForm, + loadTableFilters, + makePartIcons, + renderLink, + setupFilterList, + yesNoLabel, +*/ + +/* exported + newPartFromBomWizard, + loadBomTable, + removeRowFromBomWizard, + removeColFromBomWizard, +*/ + /* BOM management functions. * Requires follwing files to be loaded first: * - api.js @@ -28,7 +48,7 @@ function bomItemFields() { } -function reloadBomTable(table, options) { +function reloadBomTable(table) { table.bootstrapTable('refresh'); } @@ -157,7 +177,7 @@ function loadBomTable(table, options) { checkbox: true, visible: true, switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { // Disable checkbox if the row is defined for a *different* part! if (row.part != options.parent_id) { return { @@ -182,7 +202,7 @@ function loadBomTable(table, options) { field: 'sub_part', title: '{% trans "Part" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.sub_part}/`; var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, url); @@ -225,7 +245,7 @@ function loadBomTable(table, options) { title: '{% trans "Quantity" %}', searchable: false, sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var text = value; // The 'value' is a text string with (potentially) multiple trailing zeros @@ -250,7 +270,7 @@ function loadBomTable(table, options) { title: '{% trans "Available" %}', searchable: false, sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.sub_part_detail.pk}/?display=stock`; var text = value; @@ -284,7 +304,7 @@ function loadBomTable(table, options) { field: 'price_range', title: '{% trans "Supplier Cost" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value) { if (value) { return value; } else { @@ -314,7 +334,7 @@ function loadBomTable(table, options) { field: 'inherited', title: '{% trans "Inherited" %}', searchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { // This BOM item *is* inheritable, but is defined for this BOM if (!row.inherited) { return yesNoLabel(false); @@ -334,7 +354,7 @@ function loadBomTable(table, options) { { 'field': 'can_build', 'title': '{% trans "Can Build" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var can_build = 0; if (row.quantity > 0) { @@ -379,7 +399,7 @@ function loadBomTable(table, options) { switchable: false, field: 'pk', visible: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (row.part == options.parent_id) { @@ -459,7 +479,7 @@ function loadBomTable(table, options) { name: 'bom', sortable: true, search: true, - rowStyle: function(row, index) { + rowStyle: function(row) { var classes = []; @@ -532,7 +552,6 @@ function loadBomTable(table, options) { table.on('click', '.bom-delete-button', function() { var pk = $(this).attr('pk'); - var url = `/part/bom/${pk}/delete/`; constructForm(`/api/bom/${pk}/`, { method: 'DELETE', @@ -546,7 +565,6 @@ function loadBomTable(table, options) { table.on('click', '.bom-edit-button', function() { var pk = $(this).attr('pk'); - var url = `/part/bom/${pk}/edit/`; var fields = bomItemFields(); From 7d4945d302802a6d99f30562b6b8d2aac673693a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 16:01:45 +1000 Subject: [PATCH 23/36] company.js --- InvenTree/templates/js/translated/company.js | 55 ++++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/InvenTree/templates/js/translated/company.js b/InvenTree/templates/js/translated/company.js index 9c67e77db7..6c936c157a 100644 --- a/InvenTree/templates/js/translated/company.js +++ b/InvenTree/templates/js/translated/company.js @@ -1,5 +1,28 @@ {% load i18n %} +/* globals + constructForm, + imageHoverIcon, + inventreeDelete, + loadTableFilters, + makeIconButton, + renderLink, + setupFilterList, + showQuestionDialog, +*/ + +/* exported + createCompany, + createManufacturerPart, + createSupplierPart, + deleteManufacturerParts, + editCompany, + loadCompanyTable, + loadManufacturerPartTable, + loadManufacturerPartParameterTable, + loadSupplierPartTable, +*/ + function manufacturerPartFields() { @@ -32,7 +55,7 @@ function createManufacturerPart(options={}) { fields.manufacturer.secondary = { title: '{% trans "Add Manufacturer" %}', - fields: function(data) { + fields: function() { var company_fields = companyFormFields(); company_fields.is_manufacturer.value = true; @@ -126,7 +149,7 @@ function createSupplierPart(options={}) { // Add a secondary modal for the supplier fields.supplier.secondary = { title: '{% trans "Add Supplier" %}', - fields: function(data) { + fields: function() { var company_fields = companyFormFields(); company_fields.is_supplier.value = true; @@ -185,7 +208,7 @@ function deleteSupplierPart(part, options={}) { // Returns a default form-set for creating / editing a Company object -function companyFormFields(options={}) { +function companyFormFields() { return { name: {}, @@ -228,7 +251,7 @@ function editCompany(pk, options={}) { title: '{% trans "Edit Company" %}', } ); -}; +} /* * Launches a form to create a new company. @@ -285,7 +308,7 @@ function loadCompanyTable(table, url, options={}) { title: '{% trans "Company" %}', sortable: true, switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var html = imageHoverIcon(row.image) + renderLink(value, row.url); if (row.is_customer) { @@ -310,7 +333,7 @@ function loadCompanyTable(table, url, options={}) { { field: 'website', title: '{% trans "Website" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { if (value) { return renderLink(value, value); } @@ -445,7 +468,7 @@ function loadManufacturerPartTable(table, url, options) { sortable: true, field: 'part_detail.full_name', title: '{% trans "Part" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.part}/`; @@ -470,7 +493,7 @@ function loadManufacturerPartTable(table, url, options) { sortable: true, field: 'manufacturer', title: '{% trans "Manufacturer" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value && row.manufacturer_detail) { var name = row.manufacturer_detail.name; var url = `/company/${value}/`; @@ -486,14 +509,14 @@ function loadManufacturerPartTable(table, url, options) { sortable: true, field: 'MPN', title: '{% trans "MPN" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return renderLink(value, `/manufacturer-part/${row.pk}/`); } }, { field: 'link', title: '{% trans "Link" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { if (value) { return renderLink(value, value); } else { @@ -695,7 +718,7 @@ function loadSupplierPartTable(table, url, options) { sortable: true, field: 'part_detail.full_name', title: '{% trans "Part" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.part}/`; @@ -720,7 +743,7 @@ function loadSupplierPartTable(table, url, options) { sortable: true, field: 'supplier', title: '{% trans "Supplier" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value) { var name = row.supplier_detail.name; var url = `/company/${value}/`; @@ -736,7 +759,7 @@ function loadSupplierPartTable(table, url, options) { sortable: true, field: 'SKU', title: '{% trans "Supplier Part" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return renderLink(value, `/supplier-part/${row.pk}/`); } }, @@ -746,7 +769,7 @@ function loadSupplierPartTable(table, url, options) { sortable: true, field: 'manufacturer_detail.name', title: '{% trans "Manufacturer" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value && row.manufacturer_detail) { var name = value; var url = `/company/${row.manufacturer_detail.pk}/`; @@ -764,7 +787,7 @@ function loadSupplierPartTable(table, url, options) { sortable: true, field: 'manufacturer_part_detail.MPN', title: '{% trans "MPN" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value && row.manufacturer_part) { return renderLink(value, `/manufacturer-part/${row.manufacturer_part}/`); } else { @@ -775,7 +798,7 @@ function loadSupplierPartTable(table, url, options) { { field: 'link', title: '{% trans "Link" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { if (value) { return renderLink(value, value); } else { From 2112c6a9ad3c6e6bb99b9bd55fd9b1f48c33bed9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 19:33:43 +1000 Subject: [PATCH 24/36] barcode.js --- InvenTree/templates/js/translated/barcode.js | 27 ++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/InvenTree/templates/js/translated/barcode.js b/InvenTree/templates/js/translated/barcode.js index 5f255f44d6..42aaf3c416 100644 --- a/InvenTree/templates/js/translated/barcode.js +++ b/InvenTree/templates/js/translated/barcode.js @@ -3,18 +3,23 @@ /* globals imageHoverIcon, inventreePut, + makeIconButton, modalEnable, modalSetContent, modalSetTitle, + modalSetSubmitText, modalShowSubmitButton, modalSubmit, showAlertOrCache, + showQuestionDialog, */ /* exported + barcodeCheckIn, barcodeScanDialog, linkBarcodeDialog, - barcodeCheckIn, + scanItemsIntoLocation, + unlinkBarcode, */ function makeBarcodeInput(placeholderText='', hintText='') { @@ -297,7 +302,7 @@ function barcodeScanDialog() { /* * Dialog for linking a particular barcode to a stock item. */ -function linkBarcodeDialog(stockitem, options={}) { +function linkBarcodeDialog(stockitem) { var modal = '#modal-form'; @@ -308,7 +313,7 @@ function linkBarcodeDialog(stockitem, options={}) { data: { stockitem: stockitem, }, - onScan: function(response) { + onScan: function() { $(modal).modal('hide'); location.reload(); @@ -341,7 +346,7 @@ function unlinkBarcode(stockitem) { }, { method: 'PATCH', - success: function(response, status) { + success: function() { location.reload(); }, }, @@ -355,7 +360,7 @@ function unlinkBarcode(stockitem) { /* * Display dialog to check multiple stock items in to a stock location. */ -function barcodeCheckIn(location_id, options={}) { +function barcodeCheckIn(location_id) { var modal = '#modal-form'; @@ -447,7 +452,9 @@ function barcodeCheckIn(location_id, options={}) { // Called when the 'check-in' button is pressed - var data = {location: location_id}; + var data = { + location: location_id + }; // Extract 'notes' field data.notes = $(modal + ' #notes').val(); @@ -484,7 +491,7 @@ function barcodeCheckIn(location_id, options={}) { }, onScan: function(response) { if ('stockitem' in response) { - stockitem = response.stockitem; + var stockitem = response.stockitem; var duplicate = false; @@ -542,12 +549,12 @@ function scanItemsIntoLocation(item_id_list, options={}) { function updateLocationInfo(location) { var div = $(modal + ' #header-div'); - if (stock_location && stock_location.pk) { + if (location && location.pk) { div.html(`
{% trans "Location" %}
- ${stock_location.name}
- ${stock_location.description} + ${location.name}
+ ${location.description}
`); } else { From 6177fe0c5ae07e9bb6930cb67460eea332df91d9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 19:52:28 +1000 Subject: [PATCH 25/36] build.js --- InvenTree/templates/js/translated/api.js | 1 + InvenTree/templates/js/translated/build.js | 86 +++++++++++++--------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/InvenTree/templates/js/translated/api.js b/InvenTree/templates/js/translated/api.js index 8b72e166a2..6ca4b2672d 100644 --- a/InvenTree/templates/js/translated/api.js +++ b/InvenTree/templates/js/translated/api.js @@ -14,6 +14,7 @@ */ $.urlParam = function(name){ + // eslint-disable-next-line no-useless-escape var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); if (results==null) { return null; diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index 26f3876af3..a1485c5adf 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -1,6 +1,33 @@ {% load i18n %} {% load inventree_extras %} +/* globals + buildStatusDisplay, + constructForm, + getFieldByName, + global_settings, + imageHoverIcon, + inventreeGet, + launchModalForm, + linkButtonsToSelection, + loadTableFilters, + makeIconBadge, + makeIconButton, + makePartIcons, + makeProgressBar, + renderLink, + setupFilterList, +*/ + +/* exported + editBuildOrder, + loadAllocationTable, + loadBuildOrderAllocationTable, + loadBuildOutputAllocationTable, + loadBuildPartsTable, + loadBuildTable, +*/ + function buildFormFields() { return { @@ -32,7 +59,7 @@ function buildFormFields() { } -function editBuildOrder(pk, options={}) { +function editBuildOrder(pk) { var fields = buildFormFields(); @@ -76,10 +103,10 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) { var buildId = buildInfo.pk; + var outputId = 'untracked'; + if (output) { outputId = output.pk; - } else { - outputId = 'untracked'; } var panel = `#allocation-panel-${outputId}`; @@ -400,10 +427,8 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { // Callback for 'buy' button $(table).find('.button-buy').click(function() { - var pk = $(this).attr('pk'); - var idx = $(this).closest('tr').attr('data-index'); - var row = $(table).bootstrapTable('getData')[idx]; + var pk = $(this).attr('pk'); launchModalForm('{% url "order-parts" %}', { data: { @@ -573,8 +598,6 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { element.html(html); - var lineItem = row; - var subTable = $(`#${subTableId}`); subTable.bootstrapTable({ @@ -595,7 +618,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { width: '50%', field: 'quantity', title: '{% trans "Assigned Stock" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var text = ''; var url = ''; @@ -618,7 +641,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { { field: 'location', title: '{% trans "Location" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (row.stock_item_detail.location) { var text = row.stock_item_detail.location_name; var url = `/stock/location/${row.stock_item_detail.location}/`; @@ -631,7 +654,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { }, { field: 'actions', - formatter: function(value, row, index, field) { + formatter: function(value, row) { /* Actions available for a particular stock item allocation: * * - Edit the allocation quantity @@ -678,7 +701,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { field: 'sub_part_detail.full_name', title: '{% trans "Required Part" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.sub_part}/`; var thumb = row.sub_part_detail.thumbnail; var name = row.sub_part_detail.full_name; @@ -709,7 +732,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { field: 'allocated', title: '{% trans "Allocated" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var allocated = 0; if (row.allocations) { @@ -757,7 +780,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { { field: 'actions', title: '{% trans "Actions" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { // Generate action buttons for this build output var html = `
`; @@ -846,7 +869,7 @@ function loadBuildTable(table, options) { title: '{% trans "Build" %}', sortable: true, switchable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var prefix = global_settings.BUILDORDER_REFERENCE_PREFIX; @@ -873,7 +896,7 @@ function loadBuildTable(table, options) { title: '{% trans "Part" %}', sortable: true, sortName: 'part__name', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var html = imageHoverIcon(row.part_detail.thumbnail); @@ -887,7 +910,7 @@ function loadBuildTable(table, options) { field: 'quantity', title: '{% trans "Completed" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { return makeProgressBar( row.completed, row.quantity, @@ -901,7 +924,7 @@ function loadBuildTable(table, options) { field: 'status', title: '{% trans "Status" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value) { return buildStatusDisplay(value); }, }, @@ -914,7 +937,7 @@ function loadBuildTable(table, options) { field: 'issued_by', title: '{% trans "Issued by" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value) { return row.issued_by_detail.username; @@ -929,7 +952,7 @@ function loadBuildTable(table, options) { field: 'responsible', title: '{% trans "Responsible" %}', sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { if (value) { return row.responsible_detail.name; @@ -991,21 +1014,21 @@ function loadAllocationTable(table, part_id, part, url, required, button) { { field: 'stock_item_detail', title: '{% trans "Stock Item" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { return '' + parseFloat(value.quantity) + ' x ' + value.part_name + ' @ ' + value.location_name; } }, { field: 'stock_item_detail.quantity', title: '{% trans "Available" %}', - formatter: function(value, row, index, field) { + formatter: function(value) { return parseFloat(value); } }, { field: 'quantity', title: '{% trans "Allocated" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { var html = parseFloat(value); var bEdit = ""; @@ -1028,7 +1051,7 @@ function loadAllocationTable(table, part_id, part, url, required, button) { }); }); - table.on('load-success.bs.table', function(data) { + table.on('load-success.bs.table', function() { // Extract table data var results = table.bootstrapTable('getData'); @@ -1106,9 +1129,6 @@ function loadBuildPartsTable(table, options={}) { $(table).find('.button-buy').click(function() { var pk = $(this).attr('pk'); - var idx = $(this).closest('tr').attr('data-index'); - var row = $(table).bootstrapTable('getData')[idx]; - launchModalForm('{% url "order-parts" %}', { data: { parts: [ @@ -1122,10 +1142,6 @@ function loadBuildPartsTable(table, options={}) { $(table).find('.button-build').click(function() { var pk = $(this).attr('pk'); - // Extract row data from the table - var idx = $(this).closest('tr').attr('data-index'); - var row = $(table).bootstrapTable('getData')[idx]; - newBuildOrder({ part: pk, parent: options.build, @@ -1139,7 +1155,7 @@ function loadBuildPartsTable(table, options={}) { title: '{% trans "Part" %}', switchable: false, sortable: true, - formatter: function(value, row, index, field) { + formatter: function(value, row) { var url = `/part/${row.sub_part}/`; var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, url); @@ -1177,7 +1193,7 @@ function loadBuildPartsTable(table, options={}) { switchable: false, field: 'sub_part_detail.stock', title: '{% trans "Available" %}', - formatter: function(value, row, index, field) { + formatter: function(value, row) { return makeProgressBar( value, row.quantity * options.build_remaining, @@ -1201,7 +1217,7 @@ function loadBuildPartsTable(table, options={}) { field: 'actions', title: '{% trans "Actions" %}', switchable: false, - formatter: function(value, row, index, field) { + formatter: function(value, row) { // Generate action buttons against the part var html = `
`; @@ -1228,7 +1244,7 @@ function loadBuildPartsTable(table, options={}) { sortable: true, search: true, onPostBody: setupTableCallbacks, - rowStyle: function(row, index) { + rowStyle: function(row) { var classes = []; // Shade rows differently if they are for different parent parts From e1adef5010de5fb6000fe4b6747f433ec7f69eb9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 20:08:18 +1000 Subject: [PATCH 26/36] typo fix --- InvenTree/templates/js/translated/forms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index 61a1596fc5..6d5e7cce66 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -467,7 +467,7 @@ function constructFormBody(fields, options) { break; } - html += constructField(name, field, options); + html += constructField(field_name, field, options); } if (options.current_group) { From 4c39607e0092e97636bc5f1b09dc90a7bad401f1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 20:30:26 +1000 Subject: [PATCH 27/36] Brace style fixes --- .../templates/js/translated/attachment.js | 4 +++- InvenTree/templates/js/translated/build.js | 18 ++++++--------- InvenTree/templates/js/translated/company.js | 14 +++++++---- InvenTree/templates/js/translated/forms.js | 10 ++++++-- InvenTree/templates/js/translated/modals.js | 23 ++++++++----------- InvenTree/templates/js/translated/order.js | 12 +++++++--- InvenTree/templates/js/translated/part.js | 19 ++++++++++----- InvenTree/templates/js/translated/stock.js | 15 ++++-------- 8 files changed, 64 insertions(+), 51 deletions(-) diff --git a/InvenTree/templates/js/translated/attachment.js b/InvenTree/templates/js/translated/attachment.js index f8780e727a..1c4e9f2781 100644 --- a/InvenTree/templates/js/translated/attachment.js +++ b/InvenTree/templates/js/translated/attachment.js @@ -23,7 +23,9 @@ function loadAttachmentTable(url, options) { $(table).inventreeTable({ url: url, name: options.name || 'attachments', - formatNoMatches: function() { return '{% trans "No attachments found" %}'}, + formatNoMatches: function() { + return '{% trans "No attachments found" %}' + }, sortable: true, search: false, queryParams: options.filters || {}, diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index a1485c5adf..703e843d76 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -938,12 +938,9 @@ function loadBuildTable(table, options) { title: '{% trans "Issued by" %}', sortable: true, formatter: function(value, row) { - if (value) - { + if (value) { return row.issued_by_detail.username; - } - else - { + } else { return `{% trans "No user information" %}`; } } @@ -953,12 +950,9 @@ function loadBuildTable(table, options) { title: '{% trans "Responsible" %}', sortable: true, formatter: function(value, row) { - if (value) - { + if (value) { return row.responsible_detail.name; - } - else - { + } else { return '{% trans "No information" %}'; } } @@ -1009,7 +1003,9 @@ function loadAllocationTable(table, part_id, part, url, required, button) { table.bootstrapTable({ url: url, sortable: false, - formatNoMatches: function() { return '{% trans "No parts allocated for" %} ' + part; }, + formatNoMatches: function() { + return '{% trans "No parts allocated for" %} ' + part; + }, columns: [ { field: 'stock_item_detail', diff --git a/InvenTree/templates/js/translated/company.js b/InvenTree/templates/js/translated/company.js index 6c936c157a..e490f8914e 100644 --- a/InvenTree/templates/js/translated/company.js +++ b/InvenTree/templates/js/translated/company.js @@ -368,7 +368,9 @@ function loadCompanyTable(table, url, options={}) { queryParams: filters, groupBy: false, sidePagination: 'server', - formatNoMatches: function() { return "{% trans "No company information found" %}"; }, + formatNoMatches: function() { + return '{% trans "No company information found" %}'; + }, showColumns: true, name: options.pagetype || 'company', columns: columns, @@ -456,7 +458,9 @@ function loadManufacturerPartTable(table, url, options) { queryParams: filters, name: 'manufacturerparts', groupBy: false, - formatNoMatches: function() { return '{% trans "No manufacturer parts found" %}'; }, + formatNoMatches: function() { + return '{% trans "No manufacturer parts found" %}'; + }, columns: [ { checkbox: true, @@ -850,8 +854,9 @@ function loadSupplierPartTable(table, url, options) { { onSuccess: function() { $(table).bootstrapTable('refresh'); + } } - }); + ); }); $(table).find('.button-supplier-part-delete').click(function() { @@ -862,8 +867,9 @@ function loadSupplierPartTable(table, url, options) { { onSuccess: function() { $(table).bootstrapTable('refresh'); + } } - }); + ); }) } }); diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index 6d5e7cce66..596a6d15c9 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -703,7 +703,9 @@ function updateFieldValues(fields, options) { var field = fields[name] || null; - if (field == null) { continue; } + if (field == null) { + continue; + } var value = field.value; @@ -711,7 +713,9 @@ function updateFieldValues(fields, options) { value = field.default; } - if (value == null) { continue; } + if (value == null) { + continue; + } updateFieldValue(name, value, field, options); } @@ -1086,6 +1090,8 @@ function initializeRelatedFields(fields, options) { case 'choice': initializeChoiceField(field, fields, options); break; + default: + break; } } } diff --git a/InvenTree/templates/js/translated/modals.js b/InvenTree/templates/js/translated/modals.js index e398fc43fd..216dfceee8 100644 --- a/InvenTree/templates/js/translated/modals.js +++ b/InvenTree/templates/js/translated/modals.js @@ -418,12 +418,15 @@ function afterForm(response, options) { if (response.success) { showAlertOrCache("alert-success", response.success, cache); } + if (response.info) { showAlertOrCache("alert-info", response.info, cache); } + if (response.warning) { showAlertOrCache("alert-warning", response.warning, cache); } + if (response.danger) { showAlertOrCache("alert-danger", response.danger, cache); } @@ -431,14 +434,11 @@ function afterForm(response, options) { // Was a callback provided? if (options.success) { options.success(response); - } - else if (options.follow && response.url) { + } else if (options.follow && response.url) { window.location.href = response.url; - } - else if (options.redirect) { + } else if (options.redirect) { window.location.href = options.redirect; - } - else if (options.reload) { + } else if (options.reload) { location.reload(); } } @@ -883,9 +883,8 @@ function handleModalForm(url, options) { if (response.form_valid) { $(modal).modal('hide'); afterForm(response, options); - } - // Form was returned, invalid! - else { + } else { + // Form was returned, invalid! // Disable error message with option or response if (!options.hideErrorMessage && !response.hideErrorMessage) { @@ -916,14 +915,12 @@ function handleModalForm(url, options) { if (response.buttons) { attachButtons(modal, response.buttons); } - } - else { + } else { $(modal).modal('hide'); showAlertDialog('{% trans "Invalid response from server" %}', '{% trans "Form data missing from server response" %}'); } } - } - else { + } else { $(modal).modal('hide'); afterForm(response, options); } diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 371bcf974d..82818e66f0 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -292,7 +292,9 @@ function loadPurchaseOrderTable(table, options) { groupBy: false, sidePagination: 'server', original: options.params, - formatNoMatches: function() { return '{% trans "No purchase orders found" %}'; }, + formatNoMatches: function() { + return '{% trans "No purchase orders found" %}'; + }, columns: [ { title: '', @@ -388,7 +390,9 @@ function loadSalesOrderTable(table, options) { groupBy: false, sidePagination: 'server', original: options.params, - formatNoMatches: function() { return '{% trans "No sales orders found" %}'; }, + formatNoMatches: function() { + return '{% trans "No sales orders found" %}'; + }, columns: [ { title: '', @@ -502,7 +506,9 @@ function loadSalesOrderAllocationTable(table, options={}) { search: false, paginationVAlign: 'bottom', original: options.params, - formatNoMatches: function() { return '{% trans "No sales order allocations found" %}'; }, + formatNoMatches: function() { + return '{% trans "No sales order allocations found" %}'; + }, columns: [ { field: 'pk', diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index b0c2330360..5cc8409cb2 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -539,7 +539,9 @@ function loadPartVariantTable(table, partId, options={}) { showColumns: true, original: params, queryParams: filters, - formatNoMatches: function() { return '{% trans "No variants found" %}'; }, + formatNoMatches: function() { + return '{% trans "No variants found" %}'; + }, columns: cols, treeEnable: true, rootParentId: partId, @@ -587,7 +589,9 @@ function loadPartParameterTable(table, url, options) { queryParams: filters, name: 'partparameters', groupBy: false, - formatNoMatches: function() { return '{% trans "No parameters found" %}'; }, + formatNoMatches: function() { + return '{% trans "No parameters found" %}'; + }, columns: [ { checkbox: true, @@ -726,7 +730,9 @@ function loadParametricPartTable(table, options={}) { queryParams: table_headers, groupBy: false, name: options.name || 'parametric', - formatNoMatches: function() { return '{% trans "No parts found" %}'; }, + formatNoMatches: function() { + return '{% trans "No parts found" %}'; + }, columns: columns, showColumns: true, data: table_data, @@ -913,8 +919,7 @@ function loadPartTable(table, url, options={}) { formatter: function(value, row) { if (row.category) { return renderLink(value.pathstring, "/part/category/" + row.category + "/"); - } - else { + } else { return '{% trans "No category" %}'; } } @@ -987,7 +992,9 @@ function loadPartTable(table, url, options={}) { original: params, sidePagination: 'server', pagination: 'true', - formatNoMatches: function() { return '{% trans "No parts found" %}'; }, + formatNoMatches: function() { + return '{% trans "No parts found" %}'; + }, columns: columns, showColumns: true, showCustomView: false, diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js index 7b7c1b6272..81120d82f9 100644 --- a/InvenTree/templates/js/translated/stock.js +++ b/InvenTree/templates/js/translated/stock.js @@ -881,13 +881,9 @@ function loadStockTable(table, options) { // REJECTED if (row.status == {{ StockStatus.REJECTED }}) { html += makeIconBadge('fa-times-circle icon-red', '{% trans "Stock item has been rejected" %}'); - } - - // LOST - else if (row.status == {{ StockStatus.LOST }}) { + } else if (row.status == {{ StockStatus.LOST }}) { html += makeIconBadge('fa-question-circle','{% trans "Stock item is lost" %}'); - } - else if (row.status == {{ StockStatus.DESTROYED }}) { + } else if (row.status == {{ StockStatus.DESTROYED }}) { html += makeIconBadge('fa-skull-crossbones', '{% trans "Stock item is destroyed" %}'); } @@ -1682,13 +1678,10 @@ function loadStockTrackingTable(table, options) { field: 'user', title: '{% trans "User" %}', formatter: function(value, row) { - if (value) - { + if (value) { // TODO - Format the user's first and last names return row.user_detail.username; - } - else - { + } else { return `{% trans "No user information" %}`; } } From 3d5144b9bcfd5cf39444922385d051f6c888fe47 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 20:30:44 +1000 Subject: [PATCH 28/36] Simplify eslintrc file --- .eslintrc.yml | 248 +------------------------------------------------- .gitignore | 5 + 2 files changed, 8 insertions(+), 245 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 966a822732..a10f4abbd8 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,252 +1,10 @@ env: commonjs: false - es6: true browser: true es2021: true jquery: true -extends: 'eslint:recommended' +extends: + - google parserOptions: ecmaVersion: 12 - sourceType: 'script' -rules: - accessor-pairs: error - array-bracket-newline: 'off' - array-bracket-spacing: - - error - - never - array-callback-return: error - array-element-newline: 'off' - arrow-body-style: error - arrow-parens: - - error - - as-needed - arrow-spacing: 'off' - block-scoped-var: 'off' - block-spacing: 'off' - brace-style: 'off' - camelcase: 'off' - capitalized-comments: 'off' - class-methods-use-this: error - comma-dangle: 'off' - comma-spacing: 'off' - comma-style: - - error - - last - complexity: 'off' - computed-property-spacing: - - error - - never - consistent-return: 'off' - consistent-this: 'off' - curly: 'off' - default-case: 'off' - default-case-last: 'off' - default-param-last: error - dot-location: error - dot-notation: 'off' - eol-last: 'off' - eqeqeq: 'off' - func-call-spacing: error - func-name-matching: error - func-names: 'off' - func-style: - - error - - declaration - function-call-argument-newline: 'off' - function-paren-newline: 'off' - generator-star-spacing: error - grouped-accessor-pairs: error - guard-for-in: 'off' - id-denylist: error - id-length: 'off' - id-match: error - implicit-arrow-linebreak: - - error - - beside - indent: 'off' - init-declarations: error - jsx-quotes: error - key-spacing: 'off' - keyword-spacing: 'off' - line-comment-position: 'off' - linebreak-style: - - error - - unix - lines-around-comment: 'off' - lines-between-class-members: error - max-classes-per-file: error - max-depth: error - max-len: 'off' - max-lines: 'off' - max-lines-per-function: 'off' - max-nested-callbacks: error - max-params: 'off' - max-statements: 'off' - max-statements-per-line: 'off' - multiline-comment-style: 'off' - new-cap: error - new-parens: error - newline-per-chained-call: 'off' - no-alert: 'off' - no-array-constructor: 'off' - no-await-in-loop: error - no-bitwise: error - no-caller: error - no-confusing-arrow: error - no-console: 'off' - no-constructor-return: error - no-continue: 'off' - no-div-regex: error - no-duplicate-imports: error - no-else-return: 'off' - no-empty-function: 'off' - no-eq-null: 'off' - no-eval: error - no-extend-native: error - no-extra-bind: error - no-extra-label: error - no-extra-parens: 'off' - no-floating-decimal: error - no-implicit-coercion: - - error - - boolean: false - disallowTemplateShorthand: false - number: false - string: false - no-implicit-globals: 'off' - no-implied-eval: error - no-inline-comments: 'off' - no-inner-declarations: - - error - - functions - no-invalid-this: error - no-iterator: error - no-label-var: error - no-labels: error - no-lone-blocks: error - no-lonely-if: error - no-loop-func: 'off' - no-loss-of-precision: error - no-magic-numbers: 'off' - no-mixed-operators: - - error - - allowSamePrecedence: true - no-multi-assign: error - no-multi-spaces: - - error - - ignoreEOLComments: true - no-multi-str: error - no-multiple-empty-lines: 'off' - no-negated-condition: 'off' - no-nested-ternary: error - no-new: error - no-new-func: error - no-new-object: error - no-new-wrappers: error - no-nonoctal-decimal-escape: error - no-octal-escape: error - no-param-reassign: 'off' - no-plusplus: 'off' - no-promise-executor-return: error - no-proto: error - no-restricted-exports: error - no-restricted-globals: error - no-restricted-imports: error - no-restricted-properties: error - no-restricted-syntax: error - no-return-assign: error - no-return-await: error - no-script-url: error - no-self-compare: error - no-sequences: 'off' - no-shadow: 'off' - no-tabs: error - no-template-curly-in-string: error - no-ternary: 'off' - no-throw-literal: error - no-trailing-spaces: 'off' - no-undef-init: error - no-undefined: 'off' - no-underscore-dangle: 'off' - no-unmodified-loop-condition: error - no-unneeded-ternary: error - no-unreachable-loop: error - no-unsafe-optional-chaining: error - no-unused-expressions: 'off' - no-use-before-define: 'off' - no-useless-backreference: error - no-useless-call: error - no-useless-computed-key: error - no-useless-concat: error - no-useless-constructor: error - no-useless-rename: error - no-useless-return: error - no-var: 'off' - no-void: error - no-warning-comments: 'off' - no-whitespace-before-property: error - nonblock-statement-body-position: error - object-curly-newline: error - object-curly-spacing: 'off' - object-property-newline: 'off' - object-shorthand: 'off' - one-var: 'off' - one-var-declaration-per-line: error - operator-assignment: - - error - - always - operator-linebreak: error - padded-blocks: 'off' - padding-line-between-statements: error - prefer-arrow-callback: 'off' - prefer-const: 'off' - prefer-destructuring: 'off' - prefer-exponentiation-operator: error - prefer-named-capture-group: 'off' - prefer-numeric-literals: error - prefer-object-spread: error - prefer-promise-reject-errors: error - prefer-regex-literals: error - prefer-rest-params: error - prefer-spread: 'off' - prefer-template: 'off' - quote-props: 'off' - quotes: 'off' - radix: 'off' - require-atomic-updates: error - require-await: error - require-unicode-regexp: 'off' - rest-spread-spacing: error - semi: 'off' - semi-spacing: - - error - - after: true - before: false - semi-style: - - error - - last - sort-imports: error - sort-keys: 'off' - sort-vars: error - space-before-blocks: 'off' - space-before-function-paren: 'off' - space-in-parens: 'off' - space-infix-ops: 'off' - space-unary-ops: 'off' - spaced-comment: 'off' - strict: 'off' - switch-colon-spacing: error - symbol-description: error - template-curly-spacing: - - error - - never - template-tag-spacing: error - unicode-bom: - - error - - never - vars-on-top: 'off' - wrap-regex: error - yield-star-spacing: error - yoda: - - error - - never +rules: {} diff --git a/.gitignore b/.gitignore index 6f253ee8ea..420524d06f 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,8 @@ dev/ # Locale stats file locale_stats.json + +# node.js +package-lock.json +package.json +node_modules/ \ No newline at end of file From 9781d585b07e649ae235d01825f629575b6cc116 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 21:08:46 +1000 Subject: [PATCH 29/36] Install eslint-config-google --- .github/workflows/javascript.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index 110f5ffbe1..9b7199a191 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -25,7 +25,9 @@ jobs: steps: - name: Install node.js uses: actions/setup-node@v2 - - run: npm install + - run: | + npm install + npm install eslint eslint-config-google - name: Checkout Code uses: actions/checkout@v2 - name: Setup Python From fc125ca20c3293eb6a7cef86d9b4cc870975ace1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 21:16:54 +1000 Subject: [PATCH 30/36] Fix workflow file --- .github/workflows/javascript.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index 9b7199a191..a07b516ac6 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -25,9 +25,7 @@ jobs: steps: - name: Install node.js uses: actions/setup-node@v2 - - run: | - npm install - npm install eslint eslint-config-google + - run: npm install - name: Checkout Code uses: actions/checkout@v2 - name: Setup Python @@ -47,5 +45,6 @@ jobs: python check_js_templates.py - name: Lint Javascript Files run: | + npm install eslint eslint-config-google invoke render-js-files npx eslint js_tmp/*.js \ No newline at end of file From 4ffcf48ab3e58a2d51f6978d26e0ecd5cdac2e2b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 21:21:26 +1000 Subject: [PATCH 31/36] 4 spaces for indent --- .eslintrc.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index a10f4abbd8..8c4ed784f1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,4 +7,8 @@ extends: - google parserOptions: ecmaVersion: 12 -rules: {} +rules: { + indent: + - error + - 4 +} From 6dde353646d7c11513d9cf5dbb749cbe9f1cd608 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 21:25:43 +1000 Subject: [PATCH 32/36] Fix indent rule --- .eslintrc.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 8c4ed784f1..c6a003fe06 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,8 +7,6 @@ extends: - google parserOptions: ecmaVersion: 12 -rules: { +rules: indent: - - error - 4 -} From a1b7239b7eb50a871fa36ebd1abc8123cc73c18b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 21:30:10 +1000 Subject: [PATCH 33/36] indent error --- .eslintrc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index c6a003fe06..156526e394 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -9,4 +9,5 @@ parserOptions: ecmaVersion: 12 rules: indent: + - error - 4 From cb403a5b295efc2b679306be20069a3f0d1116d3 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 30 Aug 2021 22:28:01 +1000 Subject: [PATCH 34/36] More work --- .eslintrc.yml | 7 ++++ InvenTree/templates/js/translated/tables.js | 42 ++++++++++++++------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 156526e394..ba0e8d6cac 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -8,6 +8,13 @@ extends: parserOptions: ecmaVersion: 12 rules: + no-var: off + guard-for-in: off + no-trailing-spaces: off + camelcase: off + padded-blocks: off + prefer-const: off + max-len: off indent: - error - 4 diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index d5c9021806..1fc4610f95 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -12,10 +12,22 @@ reloadTableFilters, */ +/** + * Reload a named table + * @param table + */ function reloadtable(table) { $(table).bootstrapTable('refresh'); } + +/** + * Render a URL for display + * @param {String} text + * @param {String} url + * @param {object} options + * @returns link text + */ function renderLink(text, url, options={}) { if (url === null || url === undefined || url === '') { return text; @@ -63,6 +75,11 @@ function linkButtonsToSelection(table, buttons) { } +/** + * Returns true if the input looks like a valid number + * @param {String} n + * @returns + */ function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } @@ -134,7 +151,6 @@ function convertQueryParameters(params, filters) { var ordering = params['sort'] || null; if (ordering) { - if (order == 'desc') { ordering = `-${ordering}`; } @@ -332,42 +348,42 @@ function customGroupSorter(sortName, sortOrder, sortData) { } // Expose default bootstrap table string literals to translation layer -(function ($) { +(function($) { 'use strict'; $.fn.bootstrapTable.locales['en-US-custom'] = { - formatLoadingMessage: function () { + formatLoadingMessage: function() { return '{% trans "Loading data" %}'; }, - formatRecordsPerPage: function (pageNumber) { + formatRecordsPerPage: function(pageNumber) { return `${pageNumber} {% trans "rows per page" %}`; }, - formatShowingRows: function (pageFrom, pageTo, totalRows) { + formatShowingRows: function(pageFrom, pageTo, totalRows) { return `{% trans "Showing" %} ${pageFrom} {% trans "to" %} ${pageTo} {% trans "of" %} ${totalRows} {% trans "rows" %}`; }, - formatSearch: function () { + formatSearch: function() { return '{% trans "Search" %}'; }, - formatNoMatches: function () { + formatNoMatches: function() { return '{% trans "No matching results" %}'; }, - formatPaginationSwitch: function () { + formatPaginationSwitch: function() { return '{% trans "Hide/Show pagination" %}'; }, - formatRefresh: function () { + formatRefresh: function() { return '{% trans "Refresh" %}'; }, - formatToggle: function () { + formatToggle: function() { return '{% trans "Toggle" %}'; }, - formatColumns: function () { + formatColumns: function() { return '{% trans "Columns" %}'; }, - formatAllRows: function () { + formatAllRows: function() { return '{% trans "All" %}'; } }; $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['en-US-custom']); -})(jQuery); \ No newline at end of file +})(jQuery); From 888fa51cd79e8d1de75b6a0cd68b8303270b6419 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 3 Sep 2021 22:54:17 +1000 Subject: [PATCH 35/36] lots of linting fixes for JS files --- .eslintrc.yml | 5 + InvenTree/templates/js/dynamic/calendar.js | 8 +- InvenTree/templates/js/dynamic/inventree.js | 64 +-- InvenTree/templates/js/dynamic/nav.js | 2 +- InvenTree/templates/js/dynamic/settings.js | 2 +- InvenTree/templates/js/translated/api.js | 35 +- .../templates/js/translated/attachment.js | 8 +- InvenTree/templates/js/translated/barcode.js | 32 +- InvenTree/templates/js/translated/bom.js | 32 +- InvenTree/templates/js/translated/build.js | 47 +- InvenTree/templates/js/translated/company.js | 79 ++-- InvenTree/templates/js/translated/filters.js | 26 +- InvenTree/templates/js/translated/forms.js | 412 +++++++++--------- InvenTree/templates/js/translated/helpers.js | 8 +- InvenTree/templates/js/translated/label.js | 2 +- InvenTree/templates/js/translated/modals.js | 66 +-- .../js/translated/model_renderers.js | 16 +- InvenTree/templates/js/translated/order.js | 21 +- InvenTree/templates/js/translated/part.js | 137 +++--- InvenTree/templates/js/translated/report.js | 14 +- InvenTree/templates/js/translated/stock.js | 215 ++++----- .../templates/js/translated/table_filters.js | 38 +- InvenTree/templates/js/translated/tables.js | 7 +- 23 files changed, 673 insertions(+), 603 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index ba0e8d6cac..43363404b3 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -15,6 +15,11 @@ rules: padded-blocks: off prefer-const: off max-len: off + require-jsdoc: off + valid-jsdoc: off + no-multiple-empty-lines: off + comma-dangle: off + prefer-spread: off indent: - error - 4 diff --git a/InvenTree/templates/js/dynamic/calendar.js b/InvenTree/templates/js/dynamic/calendar.js index fd36d689f5..268337bd52 100644 --- a/InvenTree/templates/js/dynamic/calendar.js +++ b/InvenTree/templates/js/dynamic/calendar.js @@ -15,12 +15,12 @@ function startDate(calendar) { // Extract the first displayed date on the calendar - return calendar.currentData.dateProfile.activeRange.start.toISOString().split("T")[0]; + return calendar.currentData.dateProfile.activeRange.start.toISOString().split('T')[0]; } function endDate(calendar) { // Extract the last display date on the calendar - return calendar.currentData.dateProfile.activeRange.end.toISOString().split("T")[0]; + return calendar.currentData.dateProfile.activeRange.end.toISOString().split('T')[0]; } function clearEvents(calendar) { @@ -30,5 +30,5 @@ function clearEvents(calendar) { events.forEach(function(event) { event.remove(); - }) -} \ No newline at end of file + }); +} diff --git a/InvenTree/templates/js/dynamic/inventree.js b/InvenTree/templates/js/dynamic/inventree.js index 2a151fcdaf..7d608c1886 100644 --- a/InvenTree/templates/js/dynamic/inventree.js +++ b/InvenTree/templates/js/dynamic/inventree.js @@ -17,7 +17,7 @@ function attachClipboard(selector, containerselector, textElement) { // set container - if (containerselector){ + if (containerselector) { containerselector = document.getElementById(containerselector); } else { containerselector = document.body; @@ -26,15 +26,15 @@ function attachClipboard(selector, containerselector, textElement) { var text = null; // set text-function - if (textElement){ + if (textElement) { text = function() { return document.getElementById(textElement).textContent; - } + }; } else { text = function(trigger) { var content = trigger.parentElement.parentElement.textContent; return content.trim(); - } + }; } // create Clipboard @@ -51,15 +51,15 @@ function inventreeDocReady() { * This will be called for every page that extends "base.html" */ - window.addEventListener("dragover",function(e){ + window.addEventListener('dragover', function(e) { e = e || event; e.preventDefault(); - },false); + }, false); - window.addEventListener("drop",function(e){ + window.addEventListener('drop', function(e) { e = e || event; e.preventDefault(); - },false); + }, false); /* Add drag-n-drop functionality to any element * marked with the class 'dropzone' @@ -93,19 +93,19 @@ function inventreeDocReady() { // Callback to launch the 'Database Stats' window $('#launch-stats').click(function() { - launchModalForm("/stats/", { + launchModalForm('/stats/', { no_post: true, }); }); // Initialize clipboard-buttons attachClipboard('.clip-btn'); - attachClipboard('.clip-btn', 'modal-about'); // modals - attachClipboard('.clip-btn-version', 'modal-about', 'about-copy-text'); // version-text + attachClipboard('.clip-btn', 'modal-about'); + attachClipboard('.clip-btn-version', 'modal-about', 'about-copy-text'); // Add autocomplete to the search-bar - $("#search-bar" ).autocomplete({ - source: function (request, response) { + $('#search-bar').autocomplete({ + source: function(request, response) { $.ajax({ url: '/api/part/', data: { @@ -113,8 +113,8 @@ function inventreeDocReady() { limit: user_settings.SEARCH_PREVIEW_RESULTS, offset: 0 }, - success: function (data) { - var transformed = $.map(data.results, function (el) { + success: function(data) { + var transformed = $.map(data.results, function(el) { return { label: el.name, id: el.pk, @@ -123,13 +123,13 @@ function inventreeDocReady() { }); response(transformed); }, - error: function () { + error: function() { response([]); } }); }, - create: function () { - $(this).data('ui-autocomplete')._renderItem = function (ul, item) { + create: function() { + $(this).data('ui-autocomplete')._renderItem = function(ul, item) { var html = ``; @@ -147,7 +147,9 @@ function inventreeDocReady() { window.location = '/part/' + ui.item.id + '/'; }, minLength: 2, - classes: {'ui-autocomplete': 'dropdown-menu search-menu'}, + classes: { + 'ui-autocomplete': 'dropdown-menu search-menu', + }, }); } @@ -217,21 +219,27 @@ function enableDragAndDrop(element, url, options) { } +/** + * Save a key:value pair to local storage + * @param {String} name - settting key + * @param {String} value - setting value + */ function inventreeSave(name, value) { - /* - * Save a key:value pair to local storage - */ - var key = "inventree-" + name; + var key = `inventree-${name}`; localStorage.setItem(key, value); } -function inventreeLoad(name, defaultValue) { - /* - * Retrieve a key:value pair from local storage - */ - var key = "inventree-" + name; +/** + * Retrieve a key:value pair from local storage + * @param {*} name - setting key + * @param {*} defaultValue - default value (returned if no matching key:value pair is found) + * @returns + */ +function inventreeLoad(name, defaultValue) { + + var key = `inventree-${name}`; var value = localStorage.getItem(key); diff --git a/InvenTree/templates/js/dynamic/nav.js b/InvenTree/templates/js/dynamic/nav.js index 0b49be23c6..cf652724ed 100644 --- a/InvenTree/templates/js/dynamic/nav.js +++ b/InvenTree/templates/js/dynamic/nav.js @@ -112,4 +112,4 @@ function onPanelLoad(panel, callback) { $(panelId).off('fadeInStarted'); }); -} \ No newline at end of file +} diff --git a/InvenTree/templates/js/dynamic/settings.js b/InvenTree/templates/js/dynamic/settings.js index 7f606b7548..cb21e1fefc 100644 --- a/InvenTree/templates/js/dynamic/settings.js +++ b/InvenTree/templates/js/dynamic/settings.js @@ -17,4 +17,4 @@ const global_settings = { {% for key, value in GLOBAL_SETTINGS.items %} {{ key }}: {% primitive_to_javascript value %}, {% endfor %} -}; \ No newline at end of file +}; diff --git a/InvenTree/templates/js/translated/api.js b/InvenTree/templates/js/translated/api.js index 6ca4b2672d..841cf467ba 100644 --- a/InvenTree/templates/js/translated/api.js +++ b/InvenTree/templates/js/translated/api.js @@ -13,14 +13,17 @@ showApiError, */ -$.urlParam = function(name){ +$.urlParam = function(name) { // eslint-disable-next-line no-useless-escape var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); - if (results==null) { - return null; + + if (results == null) { + return null; } + return decodeURI(results[1]) || 0; -} +}; + // using jQuery function getCookie(name) { @@ -42,7 +45,6 @@ function getCookie(name) { function inventreeGet(url, filters={}, options={}) { // Middleware token required for data update - //var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); var csrftoken = getCookie('csrftoken'); return $.ajax({ @@ -112,7 +114,6 @@ function inventreePut(url, data={}, options={}) { var method = options.method || 'PUT'; // Middleware token required for data update - //var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); var csrftoken = getCookie('csrftoken'); return $.ajax({ @@ -168,29 +169,35 @@ function showApiError(xhr) { var message = null; switch (xhr.status) { - case 0: // No response + // No response + case 0: title = '{% trans "No Response" %}'; message = '{% trans "No response from the InvenTree server" %}'; break; - case 400: // Bad request + // Bad request + case 400: // Note: Normally error code 400 is handled separately, // and should now be shown here! title = '{% trans "Error 400: Bad request" %}'; message = '{% trans "API request returned error code 400" %}'; break; - case 401: // Not authenticated + // Not authenticated + case 401: title = '{% trans "Error 401: Not Authenticated" %}'; message = '{% trans "Authentication credentials not supplied" %}'; break; - case 403: // Permission denied + // Permission denied + case 403: title = '{% trans "Error 403: Permission Denied" %}'; message = '{% trans "You do not have the required permissions to access this function" %}'; break; - case 404: // Resource not found + // Resource not found + case 404: title = '{% trans "Error 404: Resource Not Found" %}'; message = '{% trans "The requested resource could not be located on the server" %}'; break; - case 408: // Timeout + // Timeout + case 408: title = '{% trans "Error 408: Timeout" %}'; message = '{% trans "Connection timeout while requesting data from server" %}'; break; @@ -200,8 +207,8 @@ function showApiError(xhr) { break; } - message += "
"; + message += '
'; message += renderErrorMessage(xhr); showAlertDialog(title, message); -} \ No newline at end of file +} diff --git a/InvenTree/templates/js/translated/attachment.js b/InvenTree/templates/js/translated/attachment.js index 1c4e9f2781..88c73ed3e3 100644 --- a/InvenTree/templates/js/translated/attachment.js +++ b/InvenTree/templates/js/translated/attachment.js @@ -12,7 +12,7 @@ function reloadAttachmentTable() { - $('#attachment-table').bootstrapTable("refresh"); + $('#attachment-table').bootstrapTable('refresh'); } @@ -24,7 +24,7 @@ function loadAttachmentTable(url, options) { url: url, name: options.name || 'attachments', formatNoMatches: function() { - return '{% trans "No attachments found" %}' + return '{% trans "No attachments found" %}'; }, sortable: true, search: false, @@ -67,7 +67,7 @@ function loadAttachmentTable(url, options) { } else { var images = ['.png', '.jpg', '.bmp', '.gif', '.svg', '.tif']; - images.forEach(function (suffix) { + images.forEach(function(suffix) { if (fn.endsWith(suffix)) { icon = 'fa-file-image'; } @@ -118,4 +118,4 @@ function loadAttachmentTable(url, options) { } ] }); -} \ No newline at end of file +} diff --git a/InvenTree/templates/js/translated/barcode.js b/InvenTree/templates/js/translated/barcode.js index 42aaf3c416..a1d6fb7adf 100644 --- a/InvenTree/templates/js/translated/barcode.js +++ b/InvenTree/templates/js/translated/barcode.js @@ -121,7 +121,7 @@ function postBarcodeData(barcode_data, options={}) { } } } - ) + ); } @@ -131,7 +131,7 @@ function showBarcodeMessage(modal, message, style='danger') { html += message; - html += "
"; + html += '
'; $(modal + ' #barcode-error-message').html(html); } @@ -278,7 +278,7 @@ function barcodeScanDialog() { var modal = '#modal-form'; barcodeDialog( - "Scan Barcode", + '{% trans "Scan Barcode" %}', { onScan: function(response) { if ('url' in response) { @@ -307,7 +307,7 @@ function linkBarcodeDialog(stockitem) { var modal = '#modal-form'; barcodeDialog( - "{% trans 'Link Barcode to Stock Item' %}", + '{% trans "Link Barcode to Stock Item" %}', { url: '/api/barcode/link/', data: { @@ -330,13 +330,13 @@ function unlinkBarcode(stockitem) { var html = `{% trans "Unlink Barcode" %}
`; - html += "{% trans 'This will remove the association between this stock item and the barcode' %}"; + html += '{% trans "This will remove the association between this stock item and the barcode" %}'; showQuestionDialog( - "{% trans 'Unlink Barcode' %}", + '{% trans "Unlink Barcode" %}', html, { - accept_text: "{% trans 'Unlink' %}", + accept_text: '{% trans "Unlink" %}', accept: function() { inventreePut( `/api/stock/${stockitem}/`, @@ -471,7 +471,7 @@ function barcodeCheckIn(location_id) { data.items = entries; inventreePut( - "{% url 'api-stock-transfer' %}", + '{% url "api-stock-transfer" %}', data, { method: 'POST', @@ -502,7 +502,7 @@ function barcodeCheckIn(location_id) { }); if (duplicate) { - showBarcodeMessage(modal, '{% trans "Stock Item already scanned" %}', "warning"); + showBarcodeMessage(modal, '{% trans "Stock Item already scanned" %}', 'warning'); } else { if (stockitem.location == location_id) { @@ -513,14 +513,14 @@ function barcodeCheckIn(location_id) { // Add this stock item to the list items.push(stockitem); - showBarcodeMessage(modal, '{% trans "Added stock item" %}', "success"); + showBarcodeMessage(modal, '{% trans "Added stock item" %}', 'success'); reloadTable(); } } else { // Barcode does not match a stock item - showBarcodeMessage(modal, '{% trans "Barcode does not match Stock Item" %}', "warning"); + showBarcodeMessage(modal, '{% trans "Barcode does not match Stock Item" %}', 'warning'); } }, } @@ -585,7 +585,7 @@ function scanItemsIntoLocation(item_id_list, options={}) { items.push({ pk: pk, }); - }) + }); var data = { location: stock_location.pk, @@ -611,7 +611,7 @@ function scanItemsIntoLocation(item_id_list, options={}) { } } } - ) + ); }, onScan: function(response) { updateLocationInfo(null); @@ -627,10 +627,10 @@ function scanItemsIntoLocation(item_id_list, options={}) { showBarcodeMessage( modal, '{% trans "Barcode does not match a valid location" %}', - "warning", + 'warning', ); } } } - ) -} \ No newline at end of file + ); +} diff --git a/InvenTree/templates/js/translated/bom.js b/InvenTree/templates/js/translated/bom.js index 399d2a08f3..bcfa7ef5ff 100644 --- a/InvenTree/templates/js/translated/bom.js +++ b/InvenTree/templates/js/translated/bom.js @@ -146,7 +146,7 @@ function loadBomTable(table, options) { var params = { part: options.parent_id, ordering: 'name', - } + }; if (options.part_detail) { params.part_detail = true; @@ -264,8 +264,7 @@ function loadBomTable(table, options) { }, }); - cols.push( - { + cols.push({ field: 'sub_part_detail.stock', title: '{% trans "Available" %}', searchable: false, @@ -283,24 +282,21 @@ function loadBomTable(table, options) { } }); - cols.push( - { + cols.push({ field: 'purchase_price_range', title: '{% trans "Purchase Price Range" %}', searchable: false, sortable: true, }); - cols.push( - { + cols.push({ field: 'purchase_price_avg', title: '{% trans "Purchase Price Average" %}', searchable: false, sortable: true, }); - cols.push( - { + cols.push({ field: 'price_range', title: '{% trans "Supplier Cost" %}', sortable: true, @@ -308,7 +304,7 @@ function loadBomTable(table, options) { if (value) { return value; } else { - return "{% trans 'No supplier pricing available' %}"; + return `{% trans 'No supplier pricing available' %}`; } } }); @@ -328,7 +324,7 @@ function loadBomTable(table, options) { formatter: function(value) { return yesNoLabel(value); } - }) + }); cols.push({ field: 'inherited', @@ -352,8 +348,8 @@ function loadBomTable(table, options) { cols.push( { - 'field': 'can_build', - 'title': '{% trans "Can Build" %}', + field: 'can_build', + title: '{% trans "Can Build" %}', formatter: function(value, row) { var can_build = 0; @@ -380,7 +376,7 @@ function loadBomTable(table, options) { }, sortable: true, } - ) + ); // Part notes cols.push( @@ -411,7 +407,7 @@ function loadBomTable(table, options) { var bDelt = ``; - var html = "
"; + var html = `
`; html += bEdit; html += bDelt; @@ -422,7 +418,7 @@ function loadBomTable(table, options) { html += bValid; } - html += "
"; + html += `
`; return html; } else { @@ -454,7 +450,7 @@ function loadBomTable(table, options) { response[idx].parentId = bom_pk; if (response[idx].sub_part_detail.assembly) { - requestSubItems(response[idx].pk, response[idx].sub_part) + requestSubItems(response[idx].pk, response[idx].sub_part); } } @@ -466,7 +462,7 @@ function loadBomTable(table, options) { console.log('Error requesting BOM for part=' + part_pk); } } - ) + ); } table.inventreeTable({ diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index 703e843d76..d359d6cf4e 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -125,7 +125,7 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) { html += makeIconButton( 'fa-magic icon-blue', 'button-output-auto', outputId, '{% trans "Auto-allocate stock items to this output" %}', - ); + ); } if (lines > 0) { @@ -133,7 +133,7 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) { html += makeIconButton( 'fa-minus-circle icon-red', 'button-output-unallocate', outputId, '{% trans "Unallocate stock from build output" %}', - ); + ); } @@ -144,7 +144,7 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) { 'fa-check icon-green', 'button-output-complete', outputId, '{% trans "Complete build output" %}', { - //disabled: true + // disabled: true } ); @@ -152,7 +152,7 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) { html += makeIconButton( 'fa-trash-alt icon-red', 'button-output-delete', outputId, '{% trans "Delete build output" %}', - ); + ); // TODO - Add a button to "destroy" the particular build output (mark as damaged, scrap) } @@ -229,13 +229,13 @@ function loadBuildOrderAllocationTable(table, options={}) { options.params['build_detail'] = true; options.params['location_detail'] = true; - var filters = loadTableFilters("buildorderallocation"); + var filters = loadTableFilters('buildorderallocation'); for (var key in options.params) { filters[key] = options.params[key]; } - setupFilterList("buildorderallocation", $(table)); + setupFilterList('buildorderallocation', $(table)); $(table).inventreeTable({ url: '{% url "api-build-item-list" %}', @@ -246,7 +246,7 @@ function loadBuildOrderAllocationTable(table, options={}) { paginationVAlign: 'bottom', original: options.params, formatNoMatches: function() { - return '{% trans "No build order allocations found" %}' + return '{% trans "No build order allocations found" %}'; }, columns: [ { @@ -372,13 +372,13 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { // Register button callbacks once table data are loaded // Callback for 'allocate' button - $(table).find(".button-add").click(function() { + $(table).find('.button-add').click(function() { // Primary key of the 'sub_part' var pk = $(this).attr('pk'); // Launch form to allocate new stock against this output - launchModalForm("{% url 'build-item-create' %}", { + launchModalForm('{% url "build-item-create" %}', { success: reloadTable, data: { part: pk, @@ -418,7 +418,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { } } } - ) + ); } } ] @@ -472,7 +472,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { // Load table of BOM items $(table).inventreeTable({ - url: "{% url 'api-bom-list' %}", + url: '{% url "api-bom-list" %}', queryParams: { part: partId, sub_part_detail: true, @@ -492,7 +492,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { build: buildId, part_detail: true, location_detail: true, - } + }; if (output) { params.sub_part_trackable = true; @@ -521,7 +521,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { var key = parseInt(part); if (!(key in allocations)) { - allocations[key] = new Array(); + allocations[key] = []; } allocations[key].push(item); @@ -827,7 +827,7 @@ function loadBuildTable(table, options) { params['part_detail'] = true; if (!options.disableFilters) { - filters = loadTableFilters("build"); + filters = loadTableFilters('build'); } for (var key in params) { @@ -838,7 +838,7 @@ function loadBuildTable(table, options) { var filterTarget = options.filterTarget || null; - setupFilterList("build", table, filterTarget); + setupFilterList('build', table, filterTarget); $(table).inventreeTable({ method: 'get', @@ -915,7 +915,7 @@ function loadBuildTable(table, options) { row.completed, row.quantity, { - //style: 'max', + // style: 'max', } ); } @@ -985,7 +985,7 @@ function updateAllocationTotal(id, count, required) { $('#allocation-total-'+id).html(count); - var el = $("#allocation-panel-" + id); + var el = $('#allocation-panel-' + id); el.removeClass('part-allocation-pass part-allocation-underallocated part-allocation-overallocated'); if (count < required) { @@ -1027,10 +1027,15 @@ function loadAllocationTable(table, part_id, part, url, required, button) { formatter: function(value, row) { var html = parseFloat(value); - var bEdit = ""; - var bDel = ""; + var bEdit = ``; + var bDel = ``; - html += "
" + bEdit + bDel + "
"; + html += ` +
+ ${bEdit} + ${bDel} +
+ `; return html; } @@ -1266,4 +1271,4 @@ function loadBuildPartsTable(table, options={}) { original: params, columns: columns, }); -} \ No newline at end of file +} diff --git a/InvenTree/templates/js/translated/company.js b/InvenTree/templates/js/translated/company.js index e490f8914e..c014139e1b 100644 --- a/InvenTree/templates/js/translated/company.js +++ b/InvenTree/templates/js/translated/company.js @@ -24,6 +24,10 @@ */ +/** + * Construct a set of form fields for creating / editing a ManufacturerPart + * @returns + */ function manufacturerPartFields() { return { @@ -40,6 +44,10 @@ function manufacturerPartFields() { } +/** + * Launches a form to create a new ManufacturerPart + * @param {object} options + */ function createManufacturerPart(options={}) { var fields = manufacturerPartFields(); @@ -62,7 +70,7 @@ function createManufacturerPart(options={}) { return company_fields; } - } + }; constructForm('{% url "api-manufacturer-part-list" %}', { fields: fields, @@ -73,6 +81,11 @@ function createManufacturerPart(options={}) { } +/** + * Launches a form to edit a ManufacturerPart + * @param {integer} part - ID of a ManufacturerPart + * @param {object} options + */ function editManufacturerPart(part, options={}) { var url = `/api/company/part/manufacturer/${part}/`; @@ -288,13 +301,13 @@ function loadCompanyTable(table, url, options={}) { // Query parameters var params = options.params || {}; - var filters = loadTableFilters("company"); + var filters = loadTableFilters('company'); for (var key in params) { filters[key] = params[key]; } - setupFilterList("company", $(table)); + setupFilterList('company', $(table)); var columns = [ { @@ -391,18 +404,18 @@ function deleteManufacturerParts(selections, options={}) {

{% trans "The following manufacturer parts will be deleted" %}:

    `; - selections.forEach(function(item) { - parts.push(item.pk); + selections.forEach(function(item) { + parts.push(item.pk); - text += ` -
  • -

    ${item.MPN} - ${item.part_detail.full_name}

    -
  • `; - }); - text += ` -
-
`; +
  • +

    ${item.MPN} - ${item.part_detail.full_name}

    +
  • `; + }); + + text += ` + + `; showQuestionDialog( '{% trans "Delete Manufacturer Parts" %}', @@ -426,7 +439,7 @@ function deleteManufacturerParts(selections, options={}) { if (options.onSuccess) { options.onSuccess(); } - }) + }); } } ); @@ -443,13 +456,13 @@ function loadManufacturerPartTable(table, url, options) { var params = options.params || {}; // Load filters - var filters = loadTableFilters("manufacturer-part"); + var filters = loadTableFilters('manufacturer-part'); for (var key in params) { filters[key] = params[key]; } - setupFilterList("manufacturer-part", $(table)); + setupFilterList('manufacturer-part', $(table)); $(table).inventreeTable({ url: url, @@ -505,7 +518,7 @@ function loadManufacturerPartTable(table, url, options) { return html; } else { - return "-"; + return '-'; } } }, @@ -563,8 +576,9 @@ function loadManufacturerPartTable(table, url, options) { { onSuccess: function() { $(table).bootstrapTable('refresh'); + } } - }); + ); }); $(table).find('.button-manufacturer-part-delete').click(function() { @@ -575,9 +589,10 @@ function loadManufacturerPartTable(table, url, options) { { onSuccess: function() { $(table).bootstrapTable('refresh'); + } } - }); - }) + ); + }); } }); } @@ -591,7 +606,7 @@ function loadManufacturerPartParameterTable(table, url, options) { var params = options.params || {}; // Load filters - var filters = loadTableFilters("manufacturer-part-parameters"); + var filters = loadTableFilters('manufacturer-part-parameters'); // Overwrite explicit parameters for (var key in params) { @@ -607,7 +622,9 @@ function loadManufacturerPartParameterTable(table, url, options) { queryParams: filters, name: 'manufacturerpartparameters', groupBy: false, - formatNoMatches: function() { return '{% trans "No parameters found" %}'; }, + formatNoMatches: function() { + return '{% trans "No parameters found" %}'; + }, columns: [ { checkbox: true, @@ -695,13 +712,13 @@ function loadSupplierPartTable(table, url, options) { var params = options.params || {}; // Load filters - var filters = loadTableFilters("supplier-part"); + var filters = loadTableFilters('supplier-part'); for (var key in params) { filters[key] = params[key]; } - setupFilterList("supplier-part", $(table)); + setupFilterList('supplier-part', $(table)); $(table).inventreeTable({ url: url, @@ -710,7 +727,9 @@ function loadSupplierPartTable(table, url, options) { queryParams: filters, name: 'supplierparts', groupBy: false, - formatNoMatches: function() { return '{% trans "No supplier parts found" %}'; }, + formatNoMatches: function() { + return '{% trans "No supplier parts found" %}'; + }, columns: [ { checkbox: true, @@ -755,7 +774,7 @@ function loadSupplierPartTable(table, url, options) { return html; } else { - return "-"; + return '-'; } }, }, @@ -781,7 +800,7 @@ function loadSupplierPartTable(table, url, options) { return html; } else { - return "-"; + return '-'; } } }, @@ -795,7 +814,7 @@ function loadSupplierPartTable(table, url, options) { if (value && row.manufacturer_part) { return renderLink(value, `/manufacturer-part/${row.manufacturer_part}/`); } else { - return "-"; + return '-'; } } }, @@ -870,7 +889,7 @@ function loadSupplierPartTable(table, url, options) { } } ); - }) + }); } }); -} \ No newline at end of file +} diff --git a/InvenTree/templates/js/translated/filters.js b/InvenTree/templates/js/translated/filters.js index 8d70715ff0..d7e8f45ca5 100644 --- a/InvenTree/templates/js/translated/filters.js +++ b/InvenTree/templates/js/translated/filters.js @@ -27,12 +27,12 @@ function defaultFilters() { return { - stock: "cascade=1&in_stock=1", - build: "", - parts: "cascade=1", - company: "", - salesorder: "", - purchaseorder: "", + stock: 'cascade=1&in_stock=1', + build: '', + parts: 'cascade=1', + company: '', + salesorder: '', + purchaseorder: '', }; } @@ -45,7 +45,7 @@ function defaultFilters() { */ function loadTableFilters(tableKey) { - var lookup = "table-filters-" + tableKey.toLowerCase(); + var lookup = 'table-filters-' + tableKey.toLowerCase(); var defaults = defaultFilters()[tableKey] || ''; @@ -53,7 +53,7 @@ function loadTableFilters(tableKey) { var filters = {}; - filterstring.split("&").forEach(function(item) { + filterstring.split('&').forEach(function(item) { item = item.trim(); if (item.length > 0) { @@ -78,7 +78,7 @@ function loadTableFilters(tableKey) { * @param {*} filters - object of string:string pairs */ function saveTableFilters(tableKey, filters) { - var lookup = "table-filters-" + tableKey.toLowerCase(); + var lookup = 'table-filters-' + tableKey.toLowerCase(); var strings = []; @@ -201,7 +201,7 @@ function generateAvailableFilterList(tableKey) { var html = `