diff --git a/.badges/code_style-prettier-ff69b4.svg b/.badges/code_style-prettier-ff69b4.svg new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmJhZGdlcy9jb2RlX3N0eWxlLXByZXR0aWVyLWZmNjliNC5zdmc= --- /dev/null +++ b/.badges/code_style-prettier-ff69b4.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="129" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="129" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h72v20H0z" /> + <path fill="#ff69b4" d="M72 0h57v20H72z" /> + <path fill="url(#b)" d="M0 0h129v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="37.0" y="15" fill="#010101" fill-opacity=".3">code style</text> + <text x="36.0" y="14">code style</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="101.5" y="15" fill="#010101" fill-opacity=".3">prettier</text> + <text x="100.5" y="14">prettier</text> + </g> +</svg> diff --git a/.badges/code_style-ruff.svg b/.badges/code_style-ruff.svg new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmJhZGdlcy9jb2RlX3N0eWxlLXJ1ZmYuc3Zn --- /dev/null +++ b/.badges/code_style-ruff.svg @@ -0,0 +1,49 @@ +<svg + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="53" + height="20" + role="img" + aria-label="Ruff" +> + <title>Ruff</title> + <linearGradient id="s" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <clipPath id="r"> + <rect width="53" height="20" rx="3" fill="#fff" /> + </clipPath> + <g clip-path="url(#r)"> + <rect width="20" height="20" fill="#555" /> + <rect x="20" width="33" height="20" fill="#261230" /> + <rect width="53" height="20" fill="url(#s)" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="Verdana,Geneva,DejaVu Sans,sans-serif" + text-rendering="geometricPrecision" + font-size="110" + > + <image + x="5" + y="3" + width="10" + height="14" + xlink:href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEwIiBoZWlnaHQ9IjYyMiIgdmlld0JveD0iMCAwIDUxMCA2MjIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMDYuNzAxIDBDMjAwLjk2NCAwIDE5Ni4zMTQgNC42NDEzMSAxOTYuMzE0IDEwLjM2NjdWNDEuNDY2N0MxOTYuMzE0IDQ3LjE5MiAxOTEuNjYzIDUxLjgzMzMgMTg1LjkyNyA1MS44MzMzSDE1Ni44NDNDMTUxLjEwNyA1MS44MzMzIDE0Ni40NTYgNTYuNDc0NiAxNDYuNDU2IDYyLjJWMTQ1LjEzM0MxNDYuNDU2IDE1MC44NTkgMTQxLjgwNiAxNTUuNSAxMzYuMDY5IDE1NS41SDEwNi45ODZDMTAxLjI0OSAxNTUuNSA5Ni41OTg4IDE2MC4xNDEgOTYuNTk4OCAxNjUuODY3VjIyMi44ODNDOTYuNTk4OCAyMjguNjA5IDkxLjk0ODQgMjMzLjI1IDg2LjIxMTggMjMzLjI1SDU3LjEyODNDNTEuMzkxNyAyMzMuMjUgNDYuNzQxMyAyMzcuODkxIDQ2Ljc0MTMgMjQzLjYxN1YzMDAuNjMzQzQ2Ljc0MTMgMzA2LjM1OSA0Mi4wOTA5IDMxMSAzNi4zNTQ0IDMxMUgxMC4zODdDNC42NTA0IDMxMSAwIDMxNS42NDEgMCAzMjEuMzY3VjM1Mi40NjdDMCAzNTguMTkyIDQuNjUwNCAzNjIuODMzIDEwLjM4NyAzNjIuODMzSDE0NS40MThDMTUxLjE1NCAzNjIuODMzIDE1NS44MDQgMzY3LjQ3NSAxNTUuODA0IDM3My4yVjQzMC4yMTdDMTU1LjgwNCA0MzUuOTQyIDE1MS4xNTQgNDQwLjU4MyAxNDUuNDE4IDQ0MC41ODNIMTE2LjMzNEMxMTAuNTk3IDQ0MC41ODMgMTA1Ljk0NyA0NDUuMjI1IDEwNS45NDcgNDUwLjk1VjUwNy45NjdDMTA1Ljk0NyA1MTMuNjkyIDEwMS4yOTcgNTE4LjMzMyA5NS41NjAxIDUxOC4zMzNINjYuNDc2NkM2MC43NCA1MTguMzMzIDU2LjA4OTYgNTIyLjk3NSA1Ni4wODk2IDUyOC43VjYxMS42MzNDNTYuMDg5NiA2MTcuMzU5IDYwLjc0IDYyMiA2Ni40NzY2IDYyMkgxNDkuNTcyQzE1NS4zMDkgNjIyIDE1OS45NTkgNjE3LjM1OSAxNTkuOTU5IDYxMS42MzNWNTcwLjE2N0gyMDEuNTA3QzIwNy4yNDQgNTcwLjE2NyAyMTEuODk0IDU2NS41MjUgMjExLjg5NCA1NTkuOFY1MjguN0MyMTEuODk0IDUyMi45NzUgMjE2LjU0NCA1MTguMzMzIDIyMi4yODEgNTE4LjMzM0gyNTEuMzY1QzI1Ny4xMDEgNTE4LjMzMyAyNjEuNzUyIDUxMy42OTIgMjYxLjc1MiA1MDcuOTY3VjQ3Ni44NjdDMjYxLjc1MiA0NzEuMTQxIDI2Ni40MDIgNDY2LjUgMjcyLjEzOCA0NjYuNUgzMDEuMjIyQzMwNi45NTkgNDY2LjUgMzExLjYwOSA0NjEuODU5IDMxMS42MDkgNDU2LjEzM1Y0MjUuMDMzQzMxMS42MDkgNDE5LjMwOCAzMTYuMjU5IDQxNC42NjcgMzIxLjk5NiA0MTQuNjY3SDM1MS4wNzlDMzU2LjgxNiA0MTQuNjY3IDM2MS40NjYgNDEwLjAyNSAzNjEuNDY2IDQwNC4zVjM3My4yQzM2MS40NjYgMzY3LjQ3NSAzNjYuMTE3IDM2Mi44MzMgMzcxLjg1MyAzNjIuODMzSDQwMC45MzdDNDA2LjY3MyAzNjIuODMzIDQxMS4zMjQgMzU4LjE5MiA0MTEuMzI0IDM1Mi40NjdWMzIxLjM2N0M0MTEuMzI0IDMxNS42NDEgNDE1Ljk3NCAzMTEgNDIxLjcxMSAzMTFINDUwLjc5NEM0NTYuNTMxIDMxMSA0NjEuMTgxIDMwNi4zNTkgNDYxLjE4MSAzMDAuNjMzVjIxNy43QzQ2MS4xODEgMjExLjk3NSA0NTYuNTMxIDIwNy4zMzMgNDUwLjc5NCAyMDcuMzMzSDQyMC42NzJDNDE0LjkzNiAyMDcuMzMzIDQxMC4yODUgMjAyLjY5MiA0MTAuMjg1IDE5Ni45NjdWMTY1Ljg2N0M0MTAuMjg1IDE2MC4xNDEgNDE0LjkzNiAxNTUuNSA0MjAuNjcyIDE1NS41SDQ0OS43NTZDNDU1LjQ5MiAxNTUuNSA0NjAuMTQzIDE1MC44NTkgNDYwLjE0MyAxNDUuMTMzVjExNC4wMzNDNDYwLjE0MyAxMDguMzA4IDQ2NC43OTMgMTAzLjY2NyA0NzAuNTMgMTAzLjY2N0g0OTkuNjEzQzUwNS4zNSAxMDMuNjY3IDUxMCA5OS4wMjUzIDUxMCA5My4zVjEwLjM2NjdDNTEwIDQuNjQxMzIgNTA1LjM1IDAgNDk5LjYxMyAwSDIwNi43MDFaTTE2OC4yNjkgNDQwLjU4M0MxNjIuNTMyIDQ0MC41ODMgMTU3Ljg4MiA0NDUuMjI1IDE1Ny44ODIgNDUwLjk1VjUwNy45NjdDMTU3Ljg4MiA1MTMuNjkyIDE1My4yMzEgNTE4LjMzMyAxNDcuNDk1IDUxOC4zMzNIMTE4LjQxMUMxMTIuNjc1IDUxOC4zMzMgMTA4LjAyNCA1MjIuOTc1IDEwOC4wMjQgNTI4LjdWNTU5LjhDMTA4LjAyNCA1NjUuNTI1IDExMi42NzUgNTcwLjE2NyAxMTguNDExIDU3MC4xNjdIMTU5Ljk1OVY1MjguN0MxNTkuOTU5IDUyMi45NzUgMTY0LjYxIDUxOC4zMzMgMTcwLjM0NiA1MTguMzMzSDE5OS40M0MyMDUuMTY2IDUxOC4zMzMgMjA5LjgxNyA1MTMuNjkyIDIwOS44MTcgNTA3Ljk2N1Y0NzYuODY3QzIwOS44MTcgNDcxLjE0MSAyMTQuNDY3IDQ2Ni41IDIyMC4yMDQgNDY2LjVIMjQ5LjI4N0MyNTUuMDI0IDQ2Ni41IDI1OS42NzQgNDYxLjg1OSAyNTkuNjc0IDQ1Ni4xMzNWNDI1LjAzM0MyNTkuNjc0IDQxOS4zMDggMjY0LjMyNSA0MTQuNjY3IDI3MC4wNjEgNDE0LjY2N0gyOTkuMTQ1QzMwNC44ODEgNDE0LjY2NyAzMDkuNTMyIDQxMC4wMjUgMzA5LjUzMiA0MDQuM1YzNzMuMkMzMDkuNTMyIDM2Ny40NzUgMzE0LjE4MiAzNjIuODMzIDMxOS45MTkgMzYyLjgzM0gzNDkuMDAyQzM1NC43MzkgMzYyLjgzMyAzNTkuMzg5IDM1OC4xOTIgMzU5LjM4OSAzNTIuNDY3VjMyMS4zNjdDMzU5LjM4OSAzMTUuNjQxIDM2NC4wMzkgMzExIDM2OS43NzYgMzExSDM5OC44NTlDNDA0LjU5NiAzMTEgNDA5LjI0NiAzMDYuMzU5IDQwOS4yNDYgMzAwLjYzM1YyNjkuNTMzQzQwOS4yNDYgMjYzLjgwOCA0MDQuNTk2IDI1OS4xNjcgMzk4Ljg1OSAyNTkuMTY3SDMxOC44OEMzMTMuMTQzIDI1OS4xNjcgMzA4LjQ5MyAyNTQuNTI1IDMwOC40OTMgMjQ4LjhWMjE3LjdDMzA4LjQ5MyAyMTEuOTc1IDMxMy4xNDMgMjA3LjMzMyAzMTguODggMjA3LjMzM0gzNDcuOTYzQzM1My43IDIwNy4zMzMgMzU4LjM1IDIwMi42OTIgMzU4LjM1IDE5Ni45NjdWMTY1Ljg2N0MzNTguMzUgMTYwLjE0MSAzNjMuMDAxIDE1NS41IDM2OC43MzcgMTU1LjVIMzk3LjgyMUM0MDMuNTU3IDE1NS41IDQwOC4yMDggMTUwLjg1OSA0MDguMjA4IDE0NS4xMzNWMTE0LjAzM0M0MDguMjA4IDEwOC4zMDggNDEyLjg1OCAxMDMuNjY3IDQxOC41OTUgMTAzLjY2N0g0NDcuNjc4QzQ1My40MTUgMTAzLjY2NyA0NTguMDY1IDk5LjAyNTMgNDU4LjA2NSA5My4zVjYyLjJDNDU4LjA2NSA1Ni40NzQ2IDQ1My40MTUgNTEuODMzMyA0NDcuNjc4IDUxLjgzMzNIMjA4Ljc3OEMyMDMuMDQxIDUxLjgzMzMgMTk4LjM5MSA1Ni40NzQ2IDE5OC4zOTEgNjIuMlYxNDUuMTMzQzE5OC4zOTEgMTUwLjg1OSAxOTMuNzQxIDE1NS41IDE4OC4wMDQgMTU1LjVIMTU4LjkyMUMxNTMuMTg0IDE1NS41IDE0OC41MzQgMTYwLjE0MSAxNDguNTM0IDE2NS44NjdWMjIyLjg4M0MxNDguNTM0IDIyOC42MDkgMTQzLjg4MyAyMzMuMjUgMTM4LjE0NyAyMzMuMjVIMTA5LjA2M0MxMDMuMzI3IDIzMy4yNSA5OC42NzYyIDIzNy44OTEgOTguNjc2MiAyNDMuNjE3VjMwMC42MzNDOTguNjc2MiAzMDYuMzU5IDEwMy4zMjcgMzExIDEwOS4wNjMgMzExSDE5Ny4zNTJDMjAzLjA4OSAzMTEgMjA3LjczOSAzMTUuNjQxIDIwNy43MzkgMzIxLjM2N1Y0MzAuMjE3QzIwNy43MzkgNDM1Ljk0MiAyMDMuMDg5IDQ0MC41ODMgMTk3LjM1MiA0NDAuNTgzSDE2OC4yNjlaIiBmaWxsPSIjRDdGRjY0Ii8+PC9zdmc+" + /> + <text + aria-hidden="true" + x="355" + y="150" + fill="#010101" + fill-opacity=".3" + transform="scale(.1)" + textLength="230" + > + Ruff + </text> + <text x="355" y="140" transform="scale(.1)" fill="#fff" textLength="230">Ruff</text> + </g> +</svg> diff --git a/.badges/licence-AGPL--3-blue.svg b/.badges/licence-AGPL--3-blue.svg new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmJhZGdlcy9saWNlbmNlLUFHUEwtLTMtYmx1ZS5zdmc= --- /dev/null +++ b/.badges/licence-AGPL--3-blue.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="107" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="107" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h53v20H0z" /> + <path fill="#0000FF" d="M53 0h54v20H53z" /> + <path fill="url(#b)" d="M0 0h107v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="27.5" y="15" fill="#010101" fill-opacity=".3">licence</text> + <text x="26.5" y="14">licence</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="81.0" y="15" fill="#010101" fill-opacity=".3">AGPL-3</text> + <text x="80.0" y="14">AGPL-3</text> + </g> +</svg> diff --git a/.badges/maturity.svg b/.badges/maturity.svg new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmJhZGdlcy9tYXR1cml0eS5zdmc= --- /dev/null +++ b/.badges/maturity.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<svg xmlns="http://www.w3.org/2000/svg" width="103" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <mask id="anybadge_1"> + <rect width="103" height="20" rx="3" fill="#fff" /> + </mask> + <g mask="url(#anybadge_1)"> + <path fill="#555" d="M0 0h61v20H0z" /> + <path fill="#e05d44" d="M61 0h42v20H61z" /> + <path fill="url(#b)" d="M0 0h103v20H0z" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="31.5" y="15" fill="#010101" fill-opacity=".3">maturity</text> + <text x="30.5" y="14">maturity</text> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" + font-size="11" + > + <text x="83.0" y="15" fill="#010101" fill-opacity=".3">Alpha</text> + <text x="82.0" y="14">Alpha</text> + </g> +</svg> diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmVkaXRvcmNvbmZpZw== --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# Configuration for known file extensions +[*.{css,htm,html,js,json,jsx,less,markdown,md,py,rst,sass,scss,toml,xml,yaml,yml}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{json,yml,yaml,rst,markdown,md,toml}] +indent_size = 2 + +# Do not configure editor for libs +[*/static/{lib,src/lib}/**] +charset = unset +end_of_line = unset +indent_size = unset +indent_style = unset +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmVzbGludHJjLnltbA== --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,187 @@ +env: + browser: true + es6: true + +# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 +parserOptions: + ecmaVersion: 2019 + +overrides: + - files: + - "**/*.esm.js" + parserOptions: + sourceType: module + +# Globals available in Odoo that shouldn't produce errorings +globals: + _: readonly + $: readonly + fuzzy: readonly + jQuery: readonly + moment: readonly + odoo: readonly + openerp: readonly + owl: readonly + +# Styling is handled by Prettier, so we only need to enable AST rules; +# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 +rules: + accessor-pairs: warn + array-callback-return: warn + callback-return: warn + capitalized-comments: + - warn + - always + - ignoreConsecutiveComments: true + ignoreInlineComments: true + complexity: + - warn + - 15 + constructor-super: warn + dot-notation: warn + eqeqeq: warn + global-require: warn + handle-callback-err: warn + id-blacklist: warn + id-match: warn + init-declarations: error + max-depth: warn + max-nested-callbacks: warn + max-statements-per-line: warn + no-alert: warn + no-array-constructor: warn + no-caller: warn + no-case-declarations: warn + no-class-assign: warn + no-cond-assign: error + no-const-assign: error + no-constant-condition: warn + no-control-regex: warn + no-debugger: error + no-delete-var: warn + no-div-regex: warn + no-dupe-args: error + no-dupe-class-members: error + no-dupe-keys: error + no-duplicate-case: error + no-duplicate-imports: error + no-else-return: warn + no-empty-character-class: warn + no-empty-function: error + no-empty-pattern: error + no-empty: warn + no-eq-null: error + no-eval: error + no-ex-assign: error + no-extend-native: warn + no-extra-bind: warn + no-extra-boolean-cast: warn + no-extra-label: warn + no-fallthrough: warn + no-func-assign: error + no-global-assign: error + no-implicit-coercion: + - warn + - allow: ["~"] + no-implicit-globals: warn + no-implied-eval: warn + no-inline-comments: warn + no-inner-declarations: warn + no-invalid-regexp: warn + no-irregular-whitespace: warn + no-iterator: warn + no-label-var: warn + no-labels: warn + no-lone-blocks: warn + no-lonely-if: error + no-mixed-requires: error + no-multi-str: warn + no-native-reassign: error + no-negated-condition: warn + no-negated-in-lhs: error + no-new-func: warn + no-new-object: warn + no-new-require: warn + no-new-symbol: warn + no-new-wrappers: warn + no-new: warn + no-obj-calls: warn + no-octal-escape: warn + no-octal: warn + no-param-reassign: warn + no-path-concat: warn + no-process-env: warn + no-process-exit: warn + no-proto: warn + no-prototype-builtins: warn + no-redeclare: warn + no-regex-spaces: warn + no-restricted-globals: warn + no-restricted-imports: warn + no-restricted-modules: warn + no-restricted-syntax: warn + no-return-assign: error + no-script-url: warn + no-self-assign: warn + no-self-compare: warn + no-sequences: warn + no-shadow-restricted-names: warn + no-shadow: warn + no-sparse-arrays: warn + no-sync: warn + no-this-before-super: warn + no-throw-literal: warn + no-undef-init: warn + no-undef: error + no-unmodified-loop-condition: warn + no-unneeded-ternary: error + no-unreachable: error + no-unsafe-finally: error + no-unused-expressions: error + no-unused-labels: error + no-unused-vars: error + no-use-before-define: error + no-useless-call: warn + no-useless-computed-key: warn + no-useless-concat: warn + no-useless-constructor: warn + no-useless-escape: warn + no-useless-rename: warn + no-void: warn + no-with: warn + operator-assignment: [error, always] + prefer-const: warn + radix: warn + require-yield: warn + sort-imports: warn + spaced-comment: [error, always] + strict: [error, function] + use-isnan: error + valid-jsdoc: + - warn + - prefer: + arg: param + argument: param + augments: extends + constructor: class + exception: throws + func: function + method: function + prop: property + return: returns + virtual: abstract + yield: yields + preferType: + array: Array + bool: Boolean + boolean: Boolean + number: Number + object: Object + str: String + string: String + requireParamDescription: false + requireReturn: false + requireReturnDescription: false + requireReturnType: false + valid-typeof: warn + yoda: warn diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmdpdGxhYi1jaS55bWw= --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,3 @@ +include: + - project: xcg/ci-templates + file: /odoo/17.0/gitlab-ci.yaml diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LmhnaWdub3Jl --- /dev/null +++ b/.hgignore @@ -0,0 +1,3 @@ +syntax: glob +./doc/_build +./doc/autotodo diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LnByZXR0aWVycmMueW1s --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,8 @@ +# Defaults for all prettier-supported languages. +# Prettier will complete this with settings from .editorconfig file. +bracketSpacing: false +printWidth: 88 +proseWrap: always +semi: true +trailingComma: "es5" +xmlWhitespaceSensitivity: "ignore" diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_LnlhbWxsaW50LnlhbWw= --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,4 @@ +rules: + document-start: disable + indentation: + indent-sequences: true diff --git a/NEWS.rst b/NEWS.rst new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_TkVXUy5yc3Q= --- /dev/null +++ b/NEWS.rst @@ -0,0 +1,7 @@ +Changelog +========= + +17.0.1.0.0 +---------- + +Initial version. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_UkVBRE1FLnJzdA== --- /dev/null +++ b/README.rst @@ -0,0 +1,52 @@ +==================== +Template Odoo Module +==================== + +.. |maturity| image:: .badges/maturity.svg + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |license| image:: .badges/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |ruff| image:: .badges/code_style-ruff.svg + :target: https://github.com/astral-sh/ruff + :alt: Ruff +.. |prettier| image:: .badges/code_style-prettier-ff69b4.svg + :target: https://github.com/prettier/prettier + :alt: Prettier + +|maturity| |license| |ruff| |prettier| + +This module add a wizard to call force_storage. + +Configuration +============= + +Usage +===== + +Development +=========== + +Known Issues / Roadmap +====================== + +Bug Tracker +=========== + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +- XCG Consulting, part of `Orbeet <https://orbeet.io>`_ + + - `Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr>`_ + +Maintainers +----------- + +XCG Consulting diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_X19pbml0X18ucHk= --- /dev/null +++ b/__init__.py @@ -0,0 +1,1 @@ +from . import wizards diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_X19tYW5pZmVzdF9fLnB5 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,30 @@ +############################################################################## +# +# Force Storage Wizard, for Odoo +# Copyright © 2024 XCG Consulting <https://xcg-consulting.fr> +# +# Force Storage Wizard is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Force Storage Wizard is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Template Odoo Module. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## +{ + "name": "Force Storage Wizard", + "license": "AGPL-3", + "summary": "This module adds a wizard to force storage on attachments", + "version": "17.0.1.0.0", + "category": "Technical", + "author": "XCG Consulting", + "website": "https://orbeet.io/", + "depends": ["base"], + "data": ["security/ir.model.access.csv", "wizards/force_storage_wizard.xml"], +} diff --git a/i18n/fr.po b/i18n/fr.po new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_aTE4bi9mci5wbw== --- /dev/null +++ b/i18n/fr.po @@ -0,0 +1,110 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_force_storage_wizard +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-09-06 15:22+0200\n" +"PO-Revision-Date: 2024-09-06 15:25+0200\n" +"Last-Translator: Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr>\n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.2.2\n" + +#. module: base_force_storage_wizard +#. odoo-python +#: code:addons/base_force_storage_wizard/wizards/force_storage_wizard.py:0 +#, python-format +msgid "- In database: %d." +msgstr "– Dans la base de données : %d." + +#. module: base_force_storage_wizard +#. odoo-python +#: code:addons/base_force_storage_wizard/wizards/force_storage_wizard.py:0 +#, python-format +msgid "- In fs storage “%(location)sâ€: %(count)d." +msgstr "– Dans le fs storage « %(location)s » : %(count)d." + +#. module: base_force_storage_wizard +#. odoo-python +#: code:addons/base_force_storage_wizard/wizards/force_storage_wizard.py:0 +#, python-format +msgid "- On disk: %d." +msgstr "– Sur disque : %d." + +#. module: base_force_storage_wizard +#: model_terms:ir.ui.view,arch_db:base_force_storage_wizard.force_storage_wizard_view +msgid "Apply" +msgstr "Appliquer" + +#. module: base_force_storage_wizard +#: model_terms:ir.ui.view,arch_db:base_force_storage_wizard.force_storage_wizard_view +msgid "Attachment Force Storage" +msgstr "Forcer le stockage des pièces jointes" + +#. module: base_force_storage_wizard +#: model_terms:ir.ui.view,arch_db:base_force_storage_wizard.force_storage_wizard_view +msgid "Close" +msgstr "Fermer" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: base_force_storage_wizard +#. odoo-python +#: code:addons/base_force_storage_wizard/wizards/force_storage_wizard.py:0 +#, python-format +msgid "Current storage:" +msgstr "Statistiques du stockage :" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__display_name +msgid "Display Name" +msgstr "Nom d’affichage" + +#. module: base_force_storage_wizard +#: model:ir.actions.act_window,name:base_force_storage_wizard.force_storage_wizard_action +#: model:ir.model,name:base_force_storage_wizard.model_force_storage_wizard +#: model:ir.ui.menu,name:base_force_storage_wizard.force_storage_wizard_menu +msgid "Force Storage Wizard" +msgstr "Assistant pour forcer le stockage" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__id +msgid "ID" +msgstr "" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__write_date +msgid "Last Updated on" +msgstr "Dernière modification le" + +#. module: base_force_storage_wizard +#: model:ir.model.fields,field_description:base_force_storage_wizard.field_force_storage_wizard__stats +msgid "Stats" +msgstr "Statistiques" + +#. module: base_force_storage_wizard +#. odoo-python +#: code:addons/base_force_storage_wizard/wizards/force_storage_wizard.py:0 +#, python-format +msgid "URL in attachments: %d" +msgstr "URL dans la table des pièces jointes : %d" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_cHlwcm9qZWN0LnRvbWw= --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,94 @@ +[project] +name = "odoo-addon-base_force_storage_wizard" +dynamic = ["version"] +readme = "README.rst" +requires-python = "~=3.11" +license = { file = "LICENSE", name = "GNU Affero General Public License v3" } +keywords = ["odoo"] +authors = [{ name = "XCG Consulting" }] +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Framework :: Odoo", + "Framework :: Odoo :: 17.0", + "License :: OSI Approved :: GNU Affero General Public License v3" +] +dependencies = ["odoo==17.0.*"] + +[project.optional-dependencies] +doc = ["sphinx", "sphinx-odoo-autodoc", "odoo-scripts"] +test = [] + +[project.urls] +repository = "https://orus.io/xcg/odoo-modules/base_force_storage_wizard" +changelog = "https://orus.io/xcg/odoo-modules/base_force_storage_wizard/-/blob/branch/17.0/NEWS.rst" + +[build-system] +requires = ["hatchling >=1.19", "hatch-vcs"] +build-backend = "hatchling.build" + +[tool.hatch.build] +exclude = [ + "/doc/", + "/.editorconfig", + "/.eslintrc.yml", + "/.gitlab-ci.yml", + "/.hgignore", + "/.hgtags", + "/.prettierrc.yml", + "/.yamllint.yaml" +] + +[tool.hatch.build.targets.wheel] +include = [ + "*.csv", + "/i18n/", + "/static/", + "README.rst", + "*.xml", + "*.py", + "*.svg", + "*.png" +] + +[tool.hatch.build.targets.wheel.sources] +"" = "odoo/addons/base_force_storage_wizard" + +[tool.hatch.version] +source = "vcs" + +[tool.isort] +section-order = [ + "future", + "standard-library", + "third-party", + "odoo", + "odoo-addons", + "first-party", + "local-folder" +] + +[tool.isort.sections] +"odoo" = ["odoo"] +"odoo-addons" = ["odoo.addons"] + +[tool.ruff.lint.mccabe] +max-complexity = 16 + +[tool.ruff] +target-version = "py311" + +[tool.ruff.lint] +extend-select = [ + "B", + "C90", + "E501", # line too long (default 88) + "I", # isort + "UP", # pyupgrade + +] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py +"__manifest__.py" = ["B018"] # useless expression diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_c2VjdXJpdHkvaXIubW9kZWwuYWNjZXNzLmNzdg== --- /dev/null +++ b/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +base_force_storage_wizard.access_force_storage_wizard,access_force_storage_wizard,base_force_storage_wizard.model_force_storage_wizard,base.group_erp_manager,1,1,1,1 diff --git a/wizards/__init__.py b/wizards/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_d2l6YXJkcy9fX2luaXRfXy5weQ== --- /dev/null +++ b/wizards/__init__.py @@ -0,0 +1,1 @@ +from . import force_storage_wizard diff --git a/wizards/force_storage_wizard.py b/wizards/force_storage_wizard.py new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_d2l6YXJkcy9mb3JjZV9zdG9yYWdlX3dpemFyZC5weQ== --- /dev/null +++ b/wizards/force_storage_wizard.py @@ -0,0 +1,79 @@ +############################################################################## +# +# Force Storage Wizard, for Odoo +# Copyright © 2024 XCG Consulting <https://xcg-consulting.fr> +# +# Force Storage Wizard is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Force Storage Wizard is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Template Odoo Module. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## +from odoo import _, fields, models + + +class ForceStorageWizard(models.TransientModel): + """This wizard…""" + + _name = "force_storage.wizard" + _description = "Force Storage Wizard" + + def _default_stats(self): + if self.env.is_admin(): + self.env.cr.execute( + "SELECT COUNT(*) FROM ir_attachment WHERE db_datas IS NOT NULL " + "AND type != 'url'" + ) + (count,) = self.env.cr.fetchone() + message = [_("Current storage:"), _("- In database: %d.") % count] + # defined in OCA module fs_storage + if "fs.storage" in self.env: + self.env.cr.execute( + "SELECT COUNT(*) FROM ir_attachment WHERE fs_storage_id IS NULL " + "AND db_datas IS NULL AND type != 'url'" + ) + (count,) = self.env.cr.fetchone() + message.append(_("- On disk: %d.", count)) + for location in self.env["fs.storage"].search([]): + self.env.cr.execute( + "SELECT COUNT(*) FROM ir_attachment WHERE fs_storage_id = %s " + "AND type != 'url'", + (location.id,), + ) + (count,) = self.env.cr.fetchone() + message.append( + _( + "- In fs storage “%(location)sâ€: %(count)d.", + count=count, + location=location.name, + ) + ) + else: + self.env.cr.execute( + "SELECT COUNT(*) FROM ir_attachment WHERE store_fname IS NOT NULL " + "AND type != 'url'" + ) + (count,) = self.env.cr.fetchone() + message.append(_("- On disk: %d.", count)) + + self.env.cr.execute("SELECT COUNT(*) FROM ir_attachment WHERE type = 'url'") + (count,) = self.env.cr.fetchone() + message.append("") + message.append(_("URL in attachments: %d", count)) + + return "\n".join(message) + return "" + + stats = fields.Text(default=_default_stats, readonly=True) + + def action_force_storage(self): + """Run force_storage on attachments""" + self.env["ir.attachment"].force_storage() diff --git a/wizards/force_storage_wizard.xml b/wizards/force_storage_wizard.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0445096b8ee18d8321b0d67b51a076892d029f5_d2l6YXJkcy9mb3JjZV9zdG9yYWdlX3dpemFyZC54bWw= --- /dev/null +++ b/wizards/force_storage_wizard.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8" ?> +<odoo> + <record id="force_storage_wizard_view" model="ir.ui.view"> + <field name="name">Force Storage Wizard</field> + <field name="model">force_storage.wizard</field> + <field name="arch" type="xml"> + <form string="Attachment Force Storage"> + <div role="info"> + <field name="stats" nolabel="1" /> + </div> + <footer> + <button + name="action_force_storage" + string="Apply" + type="object" + class="btn-primary" + /> + <button + string="Close" + class="btn-secondary" + special="cancel" + data-hotkey="x" + /> + </footer> + </form> + </field> + </record> + <record id="force_storage_wizard_action" model="ir.actions.act_window"> + <field name="name">Force Storage Wizard</field> + <field name="res_model">force_storage.wizard</field> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> + <menuitem + id="force_storage_wizard_menu" + action="force_storage_wizard_action" + parent="base.next_id_9" + /> +</odoo>