Compare commits
No commits in common. '14.0' and '9.0' have entirely different histories.
-
1.DINAR/build-date.txt
-
15.DINAR/config.yaml
-
4.DINAR/image/README.md
-
2.DINAR/image/dependencies/pip.txt
-
1.DINAR/image/src/addons.yaml
-
12.DINAR/image/src/repos.yaml
-
20.editorconfig
-
184.eslintrc.yml
-
11.flake8
-
2.github/FUNDING.yml
-
145.github/workflows/DINAR-PORT.yml
-
264.github/workflows/DINAR-pr.yml
-
2.github/workflows/DINAR-readme.yml
-
116.github/workflows/DINAR.yml
-
19.github/workflows/main.yml
-
58.gitignore
-
13.isort.cfg
-
111.pre-commit-config.yaml
-
8.prettierrc.yml
-
86.pylintrc
-
65.pylintrc-mandatory
-
45.travis.yml
-
166LICENSE
-
22README.md
-
17mail_all/README.rst
-
3mail_all/__init__.py
-
26mail_all/__openerp__.py
-
7mail_all/doc/changelog.rst
-
9mail_all/doc/index.rst
-
BINmail_all/images/1.jpg
-
1mail_all/models/__init__.py
-
BINmail_all/static/description/1.png
-
BINmail_all/static/description/2.png
-
BINmail_all/static/description/icon.png
-
45mail_all/static/description/index.html
-
65mail_all/static/src/js/mail_all.js
-
19mail_all/static/src/xml/menu.xml
-
3mail_all/tests/__init__.py
-
18mail_all/tests/test_js.py
-
12mail_all/views/templates.xml
-
19mail_archives/README.rst
-
1mail_archives/__init__.py
-
24mail_archives/__openerp__.py
-
BINmail_archives/images/1.jpg
-
BINmail_archives/static/description/1.png
-
BINmail_archives/static/description/2.png
-
BINmail_archives/static/description/icon.png
-
82mail_archives/static/description/index.html
-
85mail_archives/static/src/js/archives.js
-
19mail_archives/static/src/xml/menu.xml
-
3mail_archives/tests/__init__.py
-
18mail_archives/tests/test_js.py
-
12mail_archives/views/templates.xml
-
26mail_attachment_popup/README.rst
-
0mail_attachment_popup/__init__.py
-
26mail_attachment_popup/__openerp__.py
-
4mail_attachment_popup/doc/changelog.rst
-
16mail_attachment_popup/doc/index.rst
-
BINmail_attachment_popup/images/popup_image.png
-
BINmail_attachment_popup/static/description/attach_image.png
-
BINmail_attachment_popup/static/description/download.png
-
BINmail_attachment_popup/static/description/icon.png
-
84mail_attachment_popup/static/description/index.html
-
BINmail_attachment_popup/static/description/popup.png
-
429mail_attachment_popup/static/lib/js/jquery.arcticmodal.js
-
8mail_attachment_popup/static/src/css/jquery.arcticmodal.css
-
11mail_attachment_popup/static/src/css/simple.css
-
16mail_attachment_popup/static/src/css/styles.css
-
BINmail_attachment_popup/static/src/img/loading.gif
-
29mail_attachment_popup/static/src/xml/mail_attachment_popup.xml
-
13mail_attachment_popup/views/mail_attachment_popup_template.xml
-
26mail_base/README.rst
-
4mail_base/__init__.py
-
22mail_base/__openerp__.py
-
1mail_base/controllers/__init__.py
-
15mail_base/controllers/main.py
-
9mail_base/doc/changelog.rst
-
4mail_base/doc/index.rst
-
31mail_base/models.py
-
BINmail_base/static/description/icon.png
-
1197mail_base/static/lib/base.js
-
12mail_base/views/templates.xml
-
12mail_move_message/README.rst
-
3mail_move_message/__init__.py
-
19mail_move_message/__openerp__.py
-
2mail_move_message/controllers/__init__.py
-
69mail_move_message/controllers/main.py
-
9mail_move_message/data/mail_move_message_data.xml
-
21mail_move_message/doc/changelog.rst
-
173mail_move_message/i18n/mail_move_message.pot
-
160mail_move_message/i18n/sl.po
-
BINmail_move_message/images/inbox.png
-
413mail_move_message/mail_move_message_models.py
-
122mail_move_message/mail_move_message_views.xml
-
BINmail_move_message/static/description/delete-message.png
-
BINmail_move_message/static/description/html-message-viewer.png
-
BINmail_move_message/static/description/html-message-viewer1.png
-
BINmail_move_message/static/description/html-message.png
-
BINmail_move_message/static/description/icon.png
-
BINmail_move_message/static/description/inbox-move.png
@ -1 +0,0 @@ |
|||
new repo readme files |
@ -1,15 +0,0 @@ |
|||
addons: |
|||
# modules to install before running tests |
|||
include: |
|||
- contacts |
|||
# "contacts" already has mail in dependencies, |
|||
# but without the following line DINAR may run odoo odoo with --init=mail,.... |
|||
# which leads to error on loading mail's demo data |
|||
- mail |
|||
|
|||
# modules to exclude from installation/testing |
|||
exclude: |
|||
- hw_proxy |
|||
|
|||
server_wide_modules: |
|||
- web |
@ -1,4 +0,0 @@ |
|||
This folder is attached on image building as `custom/` folder in |
|||
[doobba](https://github.com/Tecnativa/doodba#image-usage). Few additional |
|||
[files](https://github.com/itpp-labs/DINAR/tree/master/embedded-files/.DINAR/image) are |
|||
attached temporary on image building. |
@ -1,2 +0,0 @@ |
|||
# Python dependencies |
|||
pycryptodome |
@ -1 +0,0 @@ |
|||
# see https://github.com/Tecnativa/doodba#optodoocustomsrcaddonsyaml |
@ -1,12 +0,0 @@ |
|||
# Documentation: https://github.com/Tecnativa/doodba#optodoocustomsrcreposyaml |
|||
|
|||
# Odoo source. |
|||
# Update this section to switch to OCA/OCB or apply custom patches |
|||
odoo: |
|||
defaults: |
|||
depth: 1 |
|||
remotes: |
|||
origin: https://github.com/odoo/odoo.git |
|||
target: origin $ODOO_VERSION |
|||
merges: |
|||
- origin $ODOO_VERSION |
@ -1,20 +0,0 @@ |
|||
# Configuration for known file extensions |
|||
[*.{css,js,json,less,md,py,rst,sass,scss,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,md}] |
|||
indent_size = 2 |
|||
|
|||
# Do not configure editor for libs and autogenerated content |
|||
[{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] |
|||
charset = unset |
|||
end_of_line = unset |
|||
indent_size = unset |
|||
indent_style = unset |
|||
insert_final_newline = false |
|||
trim_trailing_whitespace = false |
@ -1,184 +0,0 @@ |
|||
env: |
|||
browser: true |
|||
|
|||
# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 |
|||
parserOptions: |
|||
ecmaVersion: 2017 |
|||
|
|||
# Globals available in Odoo that shouldn't produce errorings |
|||
globals: |
|||
_: readonly |
|||
$: readonly |
|||
fuzzy: readonly |
|||
jQuery: readonly |
|||
moment: readonly |
|||
odoo: readonly |
|||
openerp: readonly |
|||
Promise: 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: off |
|||
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 |
|||
- args: none |
|||
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] |
|||
space-before-function-paren: ["warn", {"anonymous": "always", "named": "never"}] |
|||
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 |
@ -1,11 +0,0 @@ |
|||
[flake8] |
|||
max-line-length = 80 |
|||
max-complexity = 16 |
|||
# B = bugbear |
|||
# B9 = bugbear opinionated (incl line length) |
|||
select = C,E,F,W,B,B9 |
|||
# E203: whitespace before ':' (black behaviour) |
|||
# E501: flake8 line length (covered by bugbear B950) |
|||
# W503: line break before binary operator (black behaviour) |
|||
# C901: "method is too complex" -- it's too complex to fix existing modules. Disable for now |
|||
ignore = E203,E501,W503,B950,C901 |
@ -1,2 +0,0 @@ |
|||
ko_fi: itprojectsllc # This is supposed to bring some coffee for us |
|||
patreon: itpp # become our patron |
@ -1,145 +0,0 @@ |
|||
# Copyright 2020 IT Projects Labs |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
name: "Port module" |
|||
|
|||
on: |
|||
issues: |
|||
types: |
|||
- opened |
|||
- reopened |
|||
|
|||
jobs: |
|||
port: |
|||
runs-on: ubuntu-latest |
|||
if: "startsWith(github.event.issue.title, 'DINAR-PORT ')" |
|||
steps: |
|||
- name: Post link |
|||
uses: KeisukeYamashita/create-comment@v1 |
|||
with: |
|||
comment: |
|||
"Porting is started. Check logs: https://github.com/${{ github.repository |
|||
}}/actions/runs/${{ github.run_id }}" |
|||
- name: Checkout DINAR |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: DINAR |
|||
repository: itpp-labs/DINAR-fork |
|||
ref: master |
|||
- uses: actions/setup-python@v2 |
|||
with: |
|||
python-version: "3.7.x" |
|||
- name: Install python tools |
|||
run: | |
|||
pip install plumbum pre-commit git-aggregator |
|||
- name: Check Python Version |
|||
run: |
|||
echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> |
|||
$GITHUB_ENV |
|||
- name: Analyze request |
|||
env: |
|||
TITLE: ${{ github.event.issue.title }} |
|||
run: | |
|||
# sets environment variables that available in next steps via $ {{ env.PORT_... }} notation |
|||
python DINAR/workflow-files/analyze_port_trigger.py "$TITLE" |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: REPO |
|||
fetch-depth: 0 |
|||
ref: ${{ env.PORT_TO_BRANCH }} |
|||
- uses: actions/cache@v1 |
|||
with: |
|||
path: ~/.cache/pre-commit |
|||
key: pre-commit|${{ env.PY }}|${{ hashFiles('REPO/.pre-commit-config.yaml') }} |
|||
- name: Copy module to new branch |
|||
run: | |
|||
git config --global user.email "itpp-bot@users.noreply.github.com" |
|||
git config --global user.name "Mitchell Admin" |
|||
cd REPO |
|||
if [ ! -d ${{ env.PORT_MODULE }} ] |
|||
then |
|||
# apply original commit history |
|||
if ! git format-patch --keep-subject --stdout origin/${{ env.PORT_TO_BRANCH }}..origin/${{ env.PORT_FROM_BRANCH }} -- ${{ env.PORT_MODULE }} | git am -3 --keep |
|||
then |
|||
# git am failed |
|||
git am --abort |
|||
|
|||
# just copy source |
|||
git checkout origin/${{ env.PORT_FROM_BRANCH }} -- ${{ env.PORT_MODULE }} |
|||
git commit -m ":tada:${{ env.PORT_FROM_BRANCH_TAGS }} ${{ env.PORT_MODULE }} |
|||
previous commits history: https://github.com/${{ github.repository }}/commits/${{ env.PORT_FROM_BRANCH }}/${{ env.PORT_MODULE }} |
|||
|
|||
> Made via .github/workflows/DINAR-PORT.yml" |
|||
fi |
|||
fi |
|||
- name: make OCA/odoo-module-migrator |
|||
run: | |
|||
gitaggregate -c DINAR/workflow-files/odoo-module-migrator-mix.yml |
|||
pip install -e ./odoo-module-migrator |
|||
- name: apply OCA/odoo-module-migrator |
|||
run: | |
|||
LOG_FILE=../odoo-module-migrator.logs |
|||
cd REPO |
|||
odoo-module-migrate \ |
|||
--modules ${{ env.PORT_MODULE }} \ |
|||
--init-version-name ${{ env.PORT_FROM_BRANCH }} \ |
|||
--target-version-name ${{ env.PORT_TO_BRANCH }} \ |
|||
--no-commit \ |
|||
--no-pre-commit \ |
|||
2> $LOG_FILE || true |
|||
cat $LOG_FILE |
|||
|
|||
# remove colors |
|||
sed -r -i "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" $LOG_FILE |
|||
# escape character |
|||
# TODO: update KeisukeYamashita/create-comment to support reading comment's body from file |
|||
echo 'MIGRATOR_LOGS<<EOF' >> $GITHUB_ENV |
|||
cat $LOG_FILE >> $GITHUB_ENV |
|||
echo 'EOF' >> $GITHUB_ENV |
|||
|
|||
git add -A |
|||
git commit -m ":arrow_up:${{ env.PORT_TO_BRANCH_TAGS }} OCA/odoo-module-migrator |
|||
|
|||
close #${{ github.event.issue.number }} |
|||
|
|||
> Made via .github/workflows/DINAR-PORT.yml" |
|||
- name: pre-commit |
|||
run: | |
|||
cd REPO |
|||
pre-commit run --files $(find ${{ env.PORT_MODULE }} -type f) || true |
|||
git add -A |
|||
git commit -m ":rainbow: pre-commit |
|||
> Made via .github/workflows/DINAR-PORT.yml" || echo "pre-commit: no changes" |
|||
- name: PR |
|||
uses: peter-evans/create-pull-request@v3 |
|||
id: cpr |
|||
with: |
|||
path: REPO |
|||
# GITHUB_TOKEN would not trigger PR checks |
|||
token: ${{ secrets.DINAR_TOKEN }} |
|||
branch: ${{ env.PORT_TO_BRANCH }}-${{ env.PORT_MODULE }} |
|||
title: "[${{ env.PORT_TO_BRANCH }}] ${{ env.PORT_MODULE }}" |
|||
body: | |
|||
Made by [DINAR](https://github.com/itpp-labs/DINAR#readme) by request in #${{ github.event.issue.number }} |
|||
- name: Post logs |
|||
uses: KeisukeYamashita/create-comment@v1 |
|||
with: |
|||
number: ${{ steps.cpr.outputs.pull-request-number }} |
|||
comment: | |
|||
[Migrator](https://github.com/OCA/odoo-module-migrator/)'s [logs](https://github.com/${{ github.repository |
|||
}}/actions/runs/${{ github.run_id }}): |
|||
|
|||
``` |
|||
${{ env.MIGRATOR_LOGS }} |
|||
``` |
@ -1,264 +0,0 @@ |
|||
# Copyright 2020 IT Projects Labs |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
name: "DINAR" |
|||
|
|||
on: |
|||
pull_request: |
|||
|
|||
jobs: |
|||
pre-commit: |
|||
name: "pre-commit" |
|||
# Let Quick Review/Tests run first |
|||
needs: |
|||
- review |
|||
- tests |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
- uses: actions/setup-python@v1 |
|||
with: |
|||
python-version: "3.7.x" |
|||
- name: Check Python Version |
|||
run: |
|||
echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> |
|||
$GITHUB_ENV |
|||
- uses: actions/cache@v1 |
|||
with: |
|||
path: ~/.cache/pre-commit |
|||
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} |
|||
- uses: pre-commit/action@v1.0.1 |
|||
|
|||
review: |
|||
name: "Quick Review" |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: REPO |
|||
- name: Checkout DINAR |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: DINAR |
|||
repository: itpp-labs/DINAR-fork |
|||
ref: master |
|||
- uses: actions/setup-python@v1 |
|||
with: |
|||
python-version: "3.7.x" |
|||
- name: Install python tools |
|||
run: | |
|||
pip install plumbum PyGithub pyyaml |
|||
- name: Analyze PR |
|||
run: | |
|||
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
|||
cd REPO |
|||
python ../DINAR/workflow-files/analyze-modules.py updated ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.number }} |
|||
- name: Configure docker |
|||
run: | |
|||
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
|||
echo "PR_FILES=../../REPO" >> $GITHUB_ENV |
|||
- name: HOW TO RUN ODOO LOCALLY |
|||
if: always() |
|||
run: | |
|||
export MODULES=${{ env.PR_MODULES }} |
|||
export LOAD_MODULES=${{ env.PR_MODULES_LOAD }} |
|||
export PR_NUM=${{ github.event.number }} |
|||
export VERSION=${{ github.event.pull_request.base.ref }} |
|||
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
|||
export DINAR_REPO="itpp-labs/DINAR-fork" |
|||
bash DINAR/workflow-files/how-to-run-locally.sh |
|||
- name: Check Python Version |
|||
run: |
|||
echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> |
|||
$GITHUB_ENV |
|||
- uses: actions/cache@v1 |
|||
with: |
|||
path: ~/.cache/pre-commit |
|||
key: pre-commit|${{ env.PY }}|${{ hashFiles('REPO/.pre-commit-config.yaml') }} |
|||
- name: Install pre-commit |
|||
run: | |
|||
pip install pre-commit |
|||
- name: PRE-COMMIT against updated files only |
|||
run: | |
|||
cd REPO |
|||
git fetch origin ${{ github.event.pull_request.base.ref }} |
|||
echo "CHANGED FILES:" |
|||
git diff --name-only --no-ext-diff FETCH_HEAD..HEAD -- . |
|||
echo "RUN PRE-COMMIT:" |
|||
pre-commit run --show-diff-on-failure --color=always --show-diff-on-failure --files $(git diff --name-only --no-ext-diff FETCH_HEAD..HEAD -- .) |
|||
|
|||
tests: |
|||
name: "Quick Tests" |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: REPO |
|||
- name: Checkout DINAR |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: DINAR |
|||
repository: itpp-labs/DINAR-fork |
|||
ref: master |
|||
- name: Configure docker |
|||
run: | |
|||
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
|||
echo "PR_FILES=../../REPO" >> $GITHUB_ENV |
|||
- name: Install python tools |
|||
run: | |
|||
pip install plumbum PyGithub pyyaml |
|||
- name: Download Docker images with preinstalled modules |
|||
run: | |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml pull |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --no-start |
|||
- name: Analyze PR |
|||
run: | |
|||
# Get list of installed modules |
|||
ODOO_BASE_MODULES=$(docker inspect \ |
|||
--format '{{ index .Config.Labels "dinar.odoo.modules"}}' \ |
|||
dinar_odoo_1) |
|||
echo "ODOO_BASE_MODULES=$ODOO_BASE_MODULES" |
|||
|
|||
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
|||
cd REPO |
|||
python ../DINAR/workflow-files/analyze-modules.py updated ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.number }} $ODOO_BASE_MODULES |
|||
- name: Install json parser |
|||
run: | |
|||
sudo apt-get install jq |
|||
- name: Install Additional Dependencies (Modules) |
|||
if: env.PR_MODULES_DEPS != '' |
|||
run: | |
|||
# Install new dependencies without tests |
|||
export MODULES="${{ env.PR_MODULES_DEPS }}" |
|||
export LOAD_MODULES="${{ env.PR_MODULES_LOAD }}" |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
|||
- name: Install Additional Dependencies (Packages) |
|||
if: env.PR_DEPS != '' |
|||
run: | |
|||
# TODO https://github.com/itpp-labs/DINAR/issues/42 |
|||
exit 1 |
|||
- name: Prepare Artifact Folder |
|||
run: | |
|||
mkdir new-deps/ |
|||
# create dummy file to be sure that Artifact will be uploaded |
|||
echo ok > new-deps/.empty |
|||
echo "ARTIFACT=empty" >> $GITHUB_ENV |
|||
- name: Prepare DINAR with additional dependencies |
|||
if: env.PR_MODULES_DEPS != '' || env.PR_DEPS != '' |
|||
run: | |
|||
# Save artifacts for local run and for integrations Tests |
|||
bash DINAR/workflow-files/save-docker-layers.sh new-deps/ |
|||
echo "${{ env.PR_MODULES_DEPS }}" > new-deps/modules.txt |
|||
echo "ARTIFACT=yes" >> $GITHUB_ENV |
|||
- name: Save DINAR with dependencies |
|||
uses: actions/upload-artifact@v1 |
|||
with: |
|||
name: new-deps |
|||
path: new-deps/ |
|||
- name: HOW TO RUN QUICK TESTS LOCALLY |
|||
if: always() |
|||
run: | |
|||
export MODULES=${{ env.PR_MODULES }} |
|||
export LOAD_MODULES=${{ env.PR_MODULES_LOAD }} |
|||
export PR_NUM=${{ github.event.number }} |
|||
export VERSION=${{ github.event.pull_request.base.ref }} |
|||
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
|||
export DINAR_REPO="itpp-labs/DINAR-fork" |
|||
export ODOO_EXTRA_ARG=--test-enable |
|||
bash DINAR/workflow-files/how-to-run-locally.sh ${{ secrets.GITHUB_TOKEN }} |
|||
- name: Test updated modules |
|||
if: env.PR_MODULES != '' |
|||
run: | |
|||
export MODULES="${{ env.PR_MODULES }}" |
|||
export LOAD_MODULES="${{ env.PR_MODULES_LOAD }}" |
|||
export ODOO_EXTRA_ARG=--test-enable |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
|||
|
|||
tests-all: |
|||
name: Integration Tests |
|||
# Let Quick Review/Tests run first |
|||
# This job uses artifacts from "Quick Tests" |
|||
needs: |
|||
- tests |
|||
- review |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: REPO |
|||
- name: Checkout DINAR |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: DINAR |
|||
repository: itpp-labs/DINAR-fork |
|||
ref: master |
|||
- name: Install python tools |
|||
run: | |
|||
pip install plumbum pyyaml |
|||
- name: Download Additional Dependencies artifact |
|||
uses: actions/download-artifact@v1 |
|||
with: |
|||
name: new-deps |
|||
path: new-deps/ |
|||
- name: Check artifact |
|||
run: | |
|||
if [ ! -f new-deps/modules.txt ]; then |
|||
echo "ARTIFACT=empty" >> $GITHUB_ENV |
|||
fi |
|||
- name: Configure Docker |
|||
run: | |
|||
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
|||
echo "PR_FILES=../../REPO" >> $GITHUB_ENV |
|||
- name: Analyze PR |
|||
run: | |
|||
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
|||
DEPS_MODULES=$(cat new-deps/modules.txt || true) |
|||
cd REPO |
|||
python ../DINAR/workflow-files/analyze-modules.py all "$DEPS_MODULES" |
|||
- name: Install json parser |
|||
run: | |
|||
sudo apt-get install jq |
|||
- name: HOW TO RUN TESTS LOCALLY |
|||
if: always() |
|||
run: | |
|||
export MODULES=${{ env.ALL_MODULES }} |
|||
export LOAD_MODULES=${{ env.ALL_MODULES_LOAD }} |
|||
export PR_NUM=${{ github.event.number }} |
|||
export VERSION=${{ github.event.pull_request.base.ref }} |
|||
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
|||
export DINAR_REPO="itpp-labs/DINAR-fork" |
|||
export ODOO_EXTRA_ARG=--test-enable |
|||
bash DINAR/workflow-files/how-to-run-locally.sh ${{ secrets.GITHUB_TOKEN }} |
|||
- name: Download base images |
|||
run: | |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml pull |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --no-start |
|||
- name: Apply new-deps artifact |
|||
if: env.ARTIFACT != 'empty' |
|||
run: | |
|||
bash DINAR/workflow-files/load-docker-layers.sh new-deps/ |
|||
- name: Test all modules |
|||
run: | |
|||
export MODULES="${{ env.ALL_MODULES }}" |
|||
export LOAD_MODULES="${{ env.ALL_MODULES_LOAD }}" |
|||
export ODOO_EXTRA_ARG=--test-enable |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
|||
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
@ -1,116 +0,0 @@ |
|||
# Copyright 2020 IT Projects Labs |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
name: "DINAR: Docker Image Building" |
|||
|
|||
on: |
|||
push: |
|||
paths: |
|||
- ".DINAR/**" |
|||
- ".github/workflows/DINAR.yml" |
|||
|
|||
# Cron works only for defaul branch. See https://github.com/itpp-labs/DINAR/issues/48 |
|||
schedule: |
|||
- cron: "5 5 * * 0" |
|||
|
|||
jobs: |
|||
check-secret: |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Check that DINAR_TOKEN is set |
|||
run: | |
|||
if [ -z "${{ secrets.DINAR_TOKEN }}" ] |
|||
then |
|||
echo "DINAR_TOKEN is not set" |
|||
exit 1 |
|||
fi |
|||
|
|||
check-branch: |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Check that this branch needs docker images |
|||
run: | |
|||
REF=${GITHUB_BASE_REF:-${GITHUB_REF}} |
|||
BRANCH=${REF##*/} |
|||
CHECK=$( echo "$BRANCH" | grep -E "^(master|[0-9]+\.[0-9]+)(-dev-.+)?$" || true) |
|||
if [ -z "$CHECK" ] |
|||
then |
|||
echo "This branch is not supposed to be a target of pull requests, so docker image is not needed." |
|||
echo "For information check https://github.com/itpp-labs/DINAR/issues/60" |
|||
exit 1 |
|||
fi |
|||
|
|||
rebuild-images: |
|||
runs-on: ubuntu-latest |
|||
needs: |
|||
- check-secret |
|||
- check-branch |
|||
steps: |
|||
- name: Checkout Repo |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: REPO |
|||
- name: Checkout DINAR |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
path: DINAR |
|||
repository: itpp-labs/DINAR-fork |
|||
ref: master |
|||
- uses: actions/setup-python@v1 |
|||
with: |
|||
python-version: "3.7.x" |
|||
- name: Prepare build folder |
|||
run: | |
|||
cp -rnT DINAR/embedded-files/ REPO/ |
|||
|
|||
- name: Configure Docker |
|||
run: | |
|||
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN }} |
|||
|
|||
cat <<- EOF > REPO/.DINAR/image/.netrc |
|||
machine github.com |
|||
login $GITHUB_ACTOR |
|||
password ${{ secrets.DINAR_TOKEN }} |
|||
EOF |
|||
- name: Build ${{ env.IMAGE_ODOO_BASE }} |
|||
uses: elgohr/Publish-Docker-Github-Action@master |
|||
env: |
|||
LOCAL_CUSTOM_DIR: ./image |
|||
AGGREGATE: true |
|||
PIP_INSTALL_ODOO: false |
|||
CLEAN: false |
|||
COMPILE: false |
|||
with: |
|||
name: ${{ env.IMAGE_ODOO_BASE }} |
|||
registry: ${{ env.REGISTRY }} |
|||
username: ${{ env.REGISTRY_USERNAME }} |
|||
password: ${{ env.REGISTRY_PASSWORD }} |
|||
buildargs: ODOO_VERSION,AGGREGATE,PIP_INSTALL_ODOO,CLEAN,COMPILE,LOCAL_CUSTOM_DIR |
|||
workdir: REPO/.DINAR/ |
|||
- name: Install python tools |
|||
run: | |
|||
pip install plumbum pyyaml |
|||
- name: Compute Modules Dependencies |
|||
run: | |
|||
# sets environment variables that available in next steps via $ {{ env.VAR_NAME }} notation |
|||
cd REPO |
|||
python ../DINAR/workflow-files/analyze-modules.py all |
|||
- name: Install Base Addons |
|||
run: | |
|||
export MODULES=$ALL_MODULES_DEPENDENCIES |
|||
|
|||
export DOODBA_WITHOUT_DEMO=all |
|||
bash DINAR/workflow-files/images-with-preinstalled-modules.sh $IMAGE_DB-nodemo $IMAGE_ODOO-nodemo |
|||
|
|||
export DOODBA_WITHOUT_DEMO=false |
|||
bash DINAR/workflow-files/images-with-preinstalled-modules.sh $IMAGE_DB $IMAGE_ODOO |
@ -1,19 +0,0 @@ |
|||
name: Telegram Notifications |
|||
|
|||
on: |
|||
issues: |
|||
types: [opened, reopened, deleted, closed] |
|||
|
|||
jobs: |
|||
notify: |
|||
runs-on: ubuntu-latest |
|||
|
|||
steps: |
|||
- name: Send notifications to Telegram |
|||
run: |
|||
curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_TOKEN |
|||
}}/sendMessage -d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} -d text="${MESSAGE}" |
|||
>> /dev/null |
|||
env: |
|||
MESSAGE: |
|||
"Issue ${{ github.event.action }}: \n${{ github.event.issue.html_url }}" |
@ -0,0 +1,58 @@ |
|||
# Byte-compiled / optimized / DLL files |
|||
__pycache__/ |
|||
*.py[cod] |
|||
|
|||
# C extensions |
|||
*.so |
|||
|
|||
# Distribution / packaging |
|||
.Python |
|||
env/ |
|||
bin/ |
|||
build/ |
|||
develop-eggs/ |
|||
dist/ |
|||
eggs/ |
|||
lib64/ |
|||
parts/ |
|||
sdist/ |
|||
var/ |
|||
*.egg-info/ |
|||
.installed.cfg |
|||
*.egg |
|||
|
|||
# Installer logs |
|||
pip-log.txt |
|||
pip-delete-this-directory.txt |
|||
|
|||
# Unit test / coverage reports |
|||
htmlcov/ |
|||
.tox/ |
|||
.coverage |
|||
.cache |
|||
nosetests.xml |
|||
coverage.xml |
|||
|
|||
# Translations |
|||
*.mo |
|||
|
|||
# Pycharm |
|||
.idea |
|||
|
|||
# Mr Developer |
|||
.mr.developer.cfg |
|||
.project |
|||
.pydevproject |
|||
|
|||
# Rope |
|||
.ropeproject |
|||
|
|||
# Sphinx documentation |
|||
docs/_build/ |
|||
|
|||
# Backup files |
|||
*~ |
|||
*.swp |
|||
|
|||
# odoo |
|||
!static/lib/ |
@ -1,13 +0,0 @@ |
|||
[settings] |
|||
; see https://github.com/psf/black |
|||
multi_line_output=3 |
|||
include_trailing_comma=True |
|||
force_grid_wrap=0 |
|||
combine_as_imports=True |
|||
use_parentheses=True |
|||
line_length=88 |
|||
known_odoo=odoo |
|||
known_odoo_addons=odoo.addons |
|||
sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER |
|||
default_section=THIRDPARTY |
|||
known_third_party= |
@ -1,111 +0,0 @@ |
|||
exclude: | |
|||
(?x) |
|||
# Files and folders generated by bots, to avoid loops |
|||
^setup/|/static/description/index\.html$|/i18n/.*\.pot?$| |
|||
# Maybe reactivate this when all README files include prettier ignore tags? |
|||
^README\.md$| |
|||
# Library files can have extraneous formatting (even minimized) |
|||
/static/(src/)?lib/| |
|||
# Repos using Sphinx to generate docs don't need prettying |
|||
^docs/_templates/.*\.html$| |
|||
# You don't usually want a bot to modify your legal texts |
|||
(LICENSE.*|COPYING.*) |
|||
default_language_version: |
|||
python: python3 |
|||
node: "14.13.0" |
|||
repos: |
|||
- repo: https://github.com/myint/autoflake |
|||
rev: v1.4 |
|||
hooks: |
|||
- id: autoflake |
|||
args: ["-i", "--ignore-init-module-imports"] |
|||
- repo: https://github.com/psf/black |
|||
rev: 20.8b1 |
|||
hooks: |
|||
- id: black |
|||
- repo: https://github.com/pre-commit/mirrors-prettier |
|||
rev: v2.1.2 |
|||
hooks: |
|||
- id: prettier |
|||
name: prettier + plugin-xml |
|||
additional_dependencies: |
|||
- "prettier@2.1.2" |
|||
- "@prettier/plugin-xml@0.12.0" |
|||
args: |
|||
- --plugin=@prettier/plugin-xml |
|||
- repo: https://github.com/pre-commit/mirrors-eslint |
|||
rev: v7.8.1 |
|||
hooks: |
|||
- id: eslint |
|||
verbose: true |
|||
args: |
|||
- --color |
|||
- --fix |
|||
- repo: https://github.com/pre-commit/pre-commit-hooks |
|||
rev: v2.4.0 |
|||
hooks: |
|||
- id: trailing-whitespace |
|||
# exclude autogenerated files |
|||
exclude: /README\.rst$ |
|||
- id: end-of-file-fixer |
|||
# exclude autogenerated files |
|||
exclude: /README\.rst$ |
|||
- id: debug-statements |
|||
- id: fix-encoding-pragma |
|||
args: ["--remove"] |
|||
- id: check-case-conflict |
|||
- id: check-docstring-first |
|||
- id: check-executables-have-shebangs |
|||
- id: check-merge-conflict |
|||
- id: check-symlinks |
|||
- id: check-xml |
|||
- id: mixed-line-ending |
|||
args: ["--fix=lf"] |
|||
- repo: https://github.com/PyCQA/pylint |
|||
rev: pylint-2.5.3 |
|||
hooks: |
|||
- id: pylint |
|||
name: pylint with optional checks |
|||
args: ["--rcfile=.pylintrc", "--exit-zero"] |
|||
verbose: true |
|||
additional_dependencies: &pylint_deps |
|||
- pylint-odoo==3.5.0 |
|||
- id: pylint |
|||
name: pylint with mandatory checks |
|||
args: ["--rcfile=.pylintrc-mandatory"] |
|||
additional_dependencies: *pylint_deps |
|||
- repo: https://github.com/asottile/pyupgrade |
|||
rev: v1.26.2 |
|||
hooks: |
|||
- id: pyupgrade |
|||
args: ["--keep-percent-format"] |
|||
- repo: https://github.com/acsone/setuptools-odoo |
|||
rev: 2.6.0 |
|||
hooks: |
|||
- id: setuptools-odoo-make-default |
|||
- id: setuptools-odoo-get-requirements |
|||
args: |
|||
- --output |
|||
- requirements.txt |
|||
- --header |
|||
- "# generated from manifests external_dependencies" |
|||
- repo: https://gitlab.com/PyCQA/flake8 |
|||
rev: 3.8.3 |
|||
hooks: |
|||
- id: flake8 |
|||
name: flake8 except __init__.py |
|||
exclude: /__init__\.py$ |
|||
additional_dependencies: ["flake8-bugbear==20.1.4"] |
|||
- id: flake8 |
|||
name: flake8 only __init__.py |
|||
args: ["--extend-ignore=F401"] # ignore unused imports in __init__.py |
|||
files: /__init__\.py$ |
|||
additional_dependencies: ["flake8-bugbear==20.1.4"] |
|||
- repo: https://github.com/PyCQA/isort |
|||
rev: 5.5.1 |
|||
hooks: |
|||
- id: isort |
|||
name: isort except __init__.py |
|||
args: |
|||
- --settings=. |
|||
exclude: /__init__\.py$ |
@ -1,8 +0,0 @@ |
|||
# 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" |
@ -1,86 +0,0 @@ |
|||
[MASTER] |
|||
load-plugins=pylint_odoo |
|||
score=n |
|||
|
|||
[ODOOLINT] |
|||
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" |
|||
manifest_required_authors=IT Projects Labs |
|||
manifest_required_keys=license |
|||
manifest_deprecated_keys=description,active |
|||
license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3,MIT,Other OSI approved licence,OPL-1 |
|||
valid_odoo_versions=14.0 |
|||
|
|||
[MESSAGES CONTROL] |
|||
disable=all |
|||
|
|||
# This .pylintrc contains optional AND mandatory checks and is meant to be |
|||
# loaded in an IDE to have it check everything, in the hope this will make |
|||
# optional checks more visible to contributors who otherwise never look at a |
|||
# green travis to see optional checks that failed. |
|||
# .pylintrc-mandatory containing only mandatory checks is used the pre-commit |
|||
# config as a blocking check. |
|||
|
|||
enable=anomalous-backslash-in-string, |
|||
api-one-deprecated, |
|||
api-one-multi-together, |
|||
assignment-from-none, |
|||
attribute-deprecated, |
|||
class-camelcase, |
|||
dangerous-default-value, |
|||
dangerous-view-replace-wo-priority, |
|||
duplicate-id-csv, |
|||
duplicate-key, |
|||
duplicate-xml-fields, |
|||
duplicate-xml-record-id, |
|||
eval-referenced, |
|||
eval-used, |
|||
incoherent-interpreter-exec-perm, |
|||
license-allowed, |
|||
manifest-author-string, |
|||
manifest-deprecated-key, |
|||
#manifest-required-author, |
|||
manifest-required-key, |
|||
manifest-version-format, |
|||
method-compute, |
|||
method-inverse, |
|||
method-required-super, |
|||
method-search, |
|||
missing-manifest-dependency, |
|||
openerp-exception-warning, |
|||
pointless-statement, |
|||
pointless-string-statement, |
|||
print-used, |
|||
redundant-keyword-arg, |
|||
redundant-modulename-xml, |
|||
reimported, |
|||
relative-import, |
|||
return-in-init, |
|||
rst-syntax-error, |
|||
sql-injection, |
|||
too-few-format-args, |
|||
translation-field, |
|||
translation-required, |
|||
unreachable, |
|||
use-vim-comment, |
|||
wrong-tabs-instead-of-spaces, |
|||
xml-syntax-error, |
|||
# messages that do not cause the lint step to fail |
|||
consider-merging-classes-inherited, |
|||
create-user-wo-reset-password, |
|||
dangerous-filter-wo-user, |
|||
deprecated-module, |
|||
file-not-used, |
|||
invalid-commit, |
|||
missing-newline-extrafiles, |
|||
missing-readme, |
|||
no-utf8-coding-comment, |
|||
odoo-addons-relative-import, |
|||
old-api7-method-defined, |
|||
redefined-builtin, |
|||
too-complex, |
|||
unnecessary-utf8-coding-comment |
|||
|
|||
[REPORTS] |
|||
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} |
|||
output-format=colorized |
|||
reports=no |
@ -1,65 +0,0 @@ |
|||
[MASTER] |
|||
load-plugins=pylint_odoo |
|||
score=n |
|||
|
|||
[ODOOLINT] |
|||
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" |
|||
manifest_required_authors=IT Projects Labs |
|||
manifest_required_keys=license |
|||
manifest_deprecated_keys=description,active |
|||
license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3,MIT,Other OSI approved licence,OPL-1 |
|||
valid_odoo_versions=14.0 |
|||
|
|||
[MESSAGES CONTROL] |
|||
disable=all |
|||
|
|||
enable=anomalous-backslash-in-string, |
|||
api-one-deprecated, |
|||
api-one-multi-together, |
|||
assignment-from-none, |
|||
attribute-deprecated, |
|||
class-camelcase, |
|||
dangerous-default-value, |
|||
dangerous-view-replace-wo-priority, |
|||
duplicate-id-csv, |
|||
duplicate-key, |
|||
duplicate-xml-fields, |
|||
duplicate-xml-record-id, |
|||
eval-referenced, |
|||
eval-used, |
|||
incoherent-interpreter-exec-perm, |
|||
license-allowed, |
|||
manifest-author-string, |
|||
manifest-deprecated-key, |
|||
#manifest-required-author, |
|||
manifest-required-key, |
|||
manifest-version-format, |
|||
method-compute, |
|||
method-inverse, |
|||
method-required-super, |
|||
method-search, |
|||
missing-import-error, |
|||
missing-manifest-dependency, |
|||
openerp-exception-warning, |
|||
pointless-statement, |
|||
pointless-string-statement, |
|||
print-used, |
|||
redundant-keyword-arg, |
|||
redundant-modulename-xml, |
|||
reimported, |
|||
relative-import, |
|||
return-in-init, |
|||
rst-syntax-error, |
|||
sql-injection, |
|||
too-few-format-args, |
|||
translation-field, |
|||
translation-required, |
|||
unreachable, |
|||
use-vim-comment, |
|||
wrong-tabs-instead-of-spaces, |
|||
xml-syntax-error |
|||
|
|||
[REPORTS] |
|||
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} |
|||
output-format=colorized |
|||
reports=no |
@ -0,0 +1,45 @@ |
|||
language: python |
|||
|
|||
python: |
|||
- "2.7" |
|||
|
|||
#dist: trusty |
|||
sudo: false |
|||
cache: pip |
|||
|
|||
addons: |
|||
apt: |
|||
packages: |
|||
- expect-dev # provides unbuffer utility |
|||
- python-lxml # because pip installation is slow |
|||
|
|||
env: |
|||
global: |
|||
- VERSION="9.0" TESTS="0" LINT_CHECK="0" TRANSIFEX="0" UNIT_TEST="0" |
|||
- EXCLUDE="hw_printer_network" |
|||
- PYLINT_ODOO_JSLINTRC="/home/travis/maintainer-quality-tools/travis/cfg/.jslintrc" |
|||
|
|||
|
|||
matrix: |
|||
- LINT_CHECK="1" |
|||
- TESTS="1" ODOO_REPO="odoo/odoo" |
|||
- TESTS="1" ODOO_REPO="OCA/OCB" |
|||
- TESTS="1" UNIT_TEST="1" |
|||
|
|||
virtualenv: |
|||
system_site_packages: true |
|||
|
|||
install: |
|||
- pip install anybox.testing.openerp |
|||
- git clone https://github.com/it-projects-llc/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools |
|||
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} |
|||
- travis_install_nightly |
|||
|
|||
script: |
|||
- travis_run_tests |
|||
|
|||
after_success: |
|||
coveralls |
|||
|
|||
notifications: |
|||
email: false |
@ -0,0 +1,166 @@ |
|||
GNU LESSER GENERAL PUBLIC LICENSE |
|||
Version 3, 29 June 2007 |
|||
|
|||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|||
Everyone is permitted to copy and distribute verbatim copies |
|||
of this license document, but changing it is not allowed. |
|||
|
|||
|
|||
This version of the GNU Lesser General Public License incorporates |
|||
the terms and conditions of version 3 of the GNU General Public |
|||
License, supplemented by the additional permissions listed below. |
|||
|
|||
0. Additional Definitions. |
|||
|
|||
As used herein, "this License" refers to version 3 of the GNU Lesser |
|||
General Public License, and the "GNU GPL" refers to version 3 of the GNU |
|||
General Public License. |
|||
|
|||
"The Library" refers to a covered work governed by this License, |
|||
other than an Application or a Combined Work as defined below. |
|||
|
|||
An "Application" is any work that makes use of an interface provided |
|||
by the Library, but which is not otherwise based on the Library. |
|||
Defining a subclass of a class defined by the Library is deemed a mode |
|||
of using an interface provided by the Library. |
|||
|
|||
A "Combined Work" is a work produced by combining or linking an |
|||
Application with the Library. The particular version of the Library |
|||
with which the Combined Work was made is also called the "Linked |
|||
Version". |
|||
|
|||
The "Minimal Corresponding Source" for a Combined Work means the |
|||
Corresponding Source for the Combined Work, excluding any source code |
|||
for portions of the Combined Work that, considered in isolation, are |
|||
based on the Application, and not on the Linked Version. |
|||
|
|||
The "Corresponding Application Code" for a Combined Work means the |
|||
object code and/or source code for the Application, including any data |
|||
and utility programs needed for reproducing the Combined Work from the |
|||
Application, but excluding the System Libraries of the Combined Work. |
|||
|
|||
1. Exception to Section 3 of the GNU GPL. |
|||
|
|||
You may convey a covered work under sections 3 and 4 of this License |
|||
without being bound by section 3 of the GNU GPL. |
|||
|
|||
2. Conveying Modified Versions. |
|||
|
|||
If you modify a copy of the Library, and, in your modifications, a |
|||
facility refers to a function or data to be supplied by an Application |
|||
that uses the facility (other than as an argument passed when the |
|||
facility is invoked), then you may convey a copy of the modified |
|||
version: |
|||
|
|||
a) under this License, provided that you make a good faith effort to |
|||
ensure that, in the event an Application does not supply the |
|||
function or data, the facility still operates, and performs |
|||
whatever part of its purpose remains meaningful, or |
|||
|
|||
b) under the GNU GPL, with none of the additional permissions of |
|||
this License applicable to that copy. |
|||
|
|||
3. Object Code Incorporating Material from Library Header Files. |
|||
|
|||
The object code form of an Application may incorporate material from |
|||
a header file that is part of the Library. You may convey such object |
|||
code under terms of your choice, provided that, if the incorporated |
|||
material is not limited to numerical parameters, data structure |
|||
layouts and accessors, or small macros, inline functions and templates |
|||
(ten or fewer lines in length), you do both of the following: |
|||
|
|||
a) Give prominent notice with each copy of the object code that the |
|||
Library is used in it and that the Library and its use are |
|||
covered by this License. |
|||
|
|||
b) Accompany the object code with a copy of the GNU GPL and this license |
|||
document. |
|||
|
|||
4. Combined Works. |
|||
|
|||
You may convey a Combined Work under terms of your choice that, |
|||
taken together, effectively do not restrict modification of the |
|||
portions of the Library contained in the Combined Work and reverse |
|||
engineering for debugging such modifications, if you also do each of |
|||
the following: |
|||
|
|||
a) Give prominent notice with each copy of the Combined Work that |
|||
the Library is used in it and that the Library and its use are |
|||
covered by this License. |
|||
|
|||
b) Accompany the Combined Work with a copy of the GNU GPL and this license |
|||
document. |
|||
|
|||
c) For a Combined Work that displays copyright notices during |
|||
execution, include the copyright notice for the Library among |
|||
these notices, as well as a reference directing the user to the |
|||
copies of the GNU GPL and this license document. |
|||
|
|||
d) Do one of the following: |
|||
|
|||
0) Convey the Minimal Corresponding Source under the terms of this |
|||
License, and the Corresponding Application Code in a form |
|||
suitable for, and under terms that permit, the user to |
|||
recombine or relink the Application with a modified version of |
|||
the Linked Version to produce a modified Combined Work, in the |
|||
manner specified by section 6 of the GNU GPL for conveying |
|||
Corresponding Source. |
|||
|
|||
1) Use a suitable shared library mechanism for linking with the |
|||
Library. A suitable mechanism is one that (a) uses at run time |
|||
a copy of the Library already present on the user's computer |
|||
system, and (b) will operate properly with a modified version |
|||
of the Library that is interface-compatible with the Linked |
|||
Version. |
|||
|
|||
e) Provide Installation Information, but only if you would otherwise |
|||
be required to provide such information under section 6 of the |
|||
GNU GPL, and only to the extent that such information is |
|||
necessary to install and execute a modified version of the |
|||
Combined Work produced by recombining or relinking the |
|||
Application with a modified version of the Linked Version. (If |
|||
you use option 4d0, the Installation Information must accompany |
|||
the Minimal Corresponding Source and Corresponding Application |
|||
Code. If you use option 4d1, you must provide the Installation |
|||
Information in the manner specified by section 6 of the GNU GPL |
|||
for conveying Corresponding Source.) |
|||
|
|||
5. Combined Libraries. |
|||
|
|||
You may place library facilities that are a work based on the |
|||
Library side by side in a single library together with other library |
|||
facilities that are not Applications and are not covered by this |
|||
License, and convey such a combined library under terms of your |
|||
choice, if you do both of the following: |
|||
|
|||
a) Accompany the combined library with a copy of the same work based |
|||
on the Library, uncombined with any other library facilities, |
|||
conveyed under the terms of this License. |
|||
|
|||
b) Give prominent notice with the combined library that part of it |
|||
is a work based on the Library, and explaining where to find the |
|||
accompanying uncombined form of the same work. |
|||
|
|||
6. Revised Versions of the GNU Lesser General Public License. |
|||
|
|||
The Free Software Foundation may publish revised and/or new versions |
|||
of the GNU Lesser General Public License from time to time. Such new |
|||
versions will be similar in spirit to the present version, but may |
|||
differ in detail to address new problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the |
|||
Library as you received it specifies that a certain numbered version |
|||
of the GNU Lesser General Public License "or any later version" |
|||
applies to it, you have the option of following the terms and |
|||
conditions either of that published version or of any later version |
|||
published by the Free Software Foundation. If the Library as you |
|||
received it does not specify a version number of the GNU Lesser |
|||
General Public License, you may choose any version of the GNU Lesser |
|||
General Public License ever published by the Free Software Foundation. |
|||
|
|||
If the Library as you received it specifies that a proxy can decide |
|||
whether future versions of the GNU Lesser General Public License shall |
|||
apply, that proxy's public statement of acceptance of any version is |
|||
permanent authorization for you to choose that version for the |
|||
Library. |
|||
|
@ -0,0 +1,17 @@ |
|||
.. image:: https://itpp.dev/images/infinity-readme.png |
|||
:alt: Tested and maintained by IT Projects Labs |
|||
:target: https://itpp.dev |
|||
|
|||
=================== |
|||
Show all messages |
|||
=================== |
|||
|
|||
Adds ``Discuss / All`` menu, that shows all messages accesable by current user |
|||
|
|||
Further information |
|||
------------------- |
|||
|
|||
Odoo Apps Store: https://apps.odoo.com/apps/modules/9.0/mail_all/ |
|||
|
|||
|
|||
Tested on `Odoo 9.0 <https://github.com/odoo/odoo/commit/d3dd4161ad0598ebaa659fbd083457c77aa9448d>`_ |
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from . import models |
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
{ |
|||
"name": "Show all messages", |
|||
"summary": """Checkout all messages where you have access""", |
|||
"category": "Discuss", |
|||
"images": ['images/1.jpg'], |
|||
"version": "1.0.0", |
|||
|
|||
"author": "IT-Projects LLC, Pavel Romanchenko", |
|||
"website": "https://twitter.com/OdooFree", |
|||
"license": "LGPL-3", |
|||
|
|||
"depends": [ |
|||
"mail_base" |
|||
], |
|||
"external_dependencies": {"python": [], "bin": []}, |
|||
"data": [ |
|||
"views/templates.xml", |
|||
], |
|||
"qweb": [ |
|||
"static/src/xml/menu.xml", |
|||
], |
|||
"demo": [], |
|||
'installable': True, |
|||
"auto_install": False, |
|||
} |
@ -0,0 +1,7 @@ |
|||
Updates |
|||
======= |
|||
|
|||
`1.0.0` |
|||
------- |
|||
|
|||
- Init version |
@ -0,0 +1,9 @@ |
|||
=================== |
|||
Show all messages |
|||
=================== |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
* Open menu ``Discuss / All messages`` |
|||
* You see all messages |
After Width: 334 | Height: 171 | Size: 11 KiB |
@ -0,0 +1 @@ |
|||
# -*- coding: utf-8 -*- |
After Width: 300 | Height: 270 | Size: 15 KiB |
After Width: 765 | Height: 400 | Size: 22 KiB |
After Width: 100 | Height: 100 | Size: 2.1 KiB |
@ -0,0 +1,45 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h2 class="oe_slogan">Show all messages</h2> |
|||
<h3 class="oe_slogan">Checkout all messages where you have access</h3> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="1.png"/> |
|||
</div> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<p class="oe_mt32"> |
|||
The module adds usual menu. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
This menu shows all messages. |
|||
</p> |
|||
</div> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="2.png"/> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h2>Need our service?</h2> |
|||
<p class="oe_mt32">Contact us by <a href="mailto:it@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p> |
|||
<ul> |
|||
<li><a href="mailto:it@it-projects.info">it@it-projects.info <i class="fa fa-envelope-o"></i></a></li> |
|||
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank"> |
|||
https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</section> |
@ -0,0 +1,65 @@ |
|||
odoo.define('mail_all.all', function (require) { |
|||
"use strict"; |
|||
|
|||
var base_obj = require('mail_base.base'); |
|||
|
|||
//-------------------------------------------------------------------------------
|
|||
var bus = require('bus.bus').bus; |
|||
var config = require('web.config'); |
|||
var core = require('web.core'); |
|||
var data = require('web.data'); |
|||
var Model = require('web.Model'); |
|||
var session = require('web.session'); |
|||
var time = require('web.time'); |
|||
var web_client = require('web.web_client'); |
|||
|
|||
var _lt = core._lt; |
|||
//-------------------------------------------------------------------------------
|
|||
|
|||
var ChatAction = core.action_registry.get('mail.chat.instant_messaging'); |
|||
ChatAction.include({ |
|||
get_thread_rendering_options: function (messages) { |
|||
var options = this._super.apply(this, arguments); |
|||
options.display_subject = options.display_subject || this.channel.id === "channel_all"; |
|||
return options; |
|||
} |
|||
}); |
|||
|
|||
// Inherit class and override methods
|
|||
base_obj.MailTools.include({ |
|||
get_properties: function(msg){ |
|||
var properties = this._super.apply(this, arguments); |
|||
properties.is_all = this.property_descr("channel_all", msg, this); |
|||
return properties; |
|||
}, |
|||
|
|||
set_channel_flags: function(data, msg){ |
|||
this._super.apply(this, arguments); |
|||
msg.is_all = true; |
|||
return msg; |
|||
}, |
|||
|
|||
get_channel_array: function(msg){ |
|||
var arr = this._super.apply(this, arguments); |
|||
return arr.concat('channel_all'); |
|||
}, |
|||
|
|||
get_domain: function(channel){ |
|||
return (channel.id === "channel_all") ? [] : this._super.apply(this, arguments); |
|||
} |
|||
}); |
|||
|
|||
base_obj.chat_manager.is_ready.then(function(){ |
|||
// Add all channel
|
|||
base_obj.chat_manager.mail_tools.add_channel({ |
|||
id: "channel_all", |
|||
name: _lt("All messages"), |
|||
type: "static" |
|||
}); |
|||
|
|||
return $.when(); |
|||
}); |
|||
|
|||
return base_obj.chat_manager; |
|||
|
|||
}); |
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<template> |
|||
<!--Inherit Sidebar and add All messages menu item after Starred --> |
|||
<t t-extend="mail.chat.Sidebar"> |
|||
<t t-jquery="div[data-channel-id=channel_starred]" t-operation="after"> |
|||
<div t-attf-class="o_mail_chat_channel_item #{(active_channel_id == 'channel_all') ? 'o_active': ''}" data-channel-id="channel_all"> |
|||
<span class="o_channel_name mail_all"> <i class="fa fa-database"/> All messages </span> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
<!--Add message about empty all messages page--> |
|||
<t t-extend="mail.EmptyChannel"> |
|||
<t t-jquery="t:last-child" t-operation="after"> |
|||
<t t-if="options.channel_id==='channel_all'"> |
|||
<div class="o_thread_title">No messages</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</template> |
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from . import test_js |
@ -0,0 +1,18 @@ |
|||
# -*- coding: utf-8 -*- |
|||
import openerp.tests |
|||
|
|||
|
|||
@openerp.tests.common.at_install(False) |
|||
@openerp.tests.common.post_install(True) |
|||
class TestUi(openerp.tests.HttpCase): |
|||
|
|||
def test_01_mail_all(self): |
|||
# wait till page loaded and then click and wait again |
|||
code = """ |
|||
setTimeout(function () { |
|||
$(".mail_all").click(); |
|||
setTimeout(function () {console.log('ok');}, 3000); |
|||
}, 1000); |
|||
""" |
|||
link = '/web#action=%s' % self.ref('mail.mail_channel_action_client_chat') |
|||
self.phantom_js(link, code, "odoo.__DEBUG__.services['mail_all.all']", login="admin") |
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="mail_all_assets_backend" |
|||
name="mail_all_assets_backend" |
|||
inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script src="/mail_all/static/src/js/mail_all.js" type="text/javascript"></script> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,19 @@ |
|||
.. image:: https://itpp.dev/images/infinity-readme.png |
|||
:alt: Tested and maintained by IT Projects Labs |
|||
:target: https://itpp.dev |
|||
|
|||
Mail Archives |
|||
============= |
|||
|
|||
Adds Archive menu, which shows sent/received messages |
|||
|
|||
Usage |
|||
----- |
|||
Click Discuss/Archive menu -- sent/received messages are displayed |
|||
|
|||
Further information |
|||
------------------- |
|||
|
|||
Odoo Apps Store: https://apps.odoo.com/apps/modules/9.0/mail_archives/ |
|||
|
|||
Tested on `Odoo 9.0 <https://github.com/odoo/odoo/commit/b9f206953e3f877adf18643f154d1262842564ee>`_ |
@ -0,0 +1 @@ |
|||
# -*- coding: utf-8 -*- |
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
{ |
|||
"name": "Mail archives", |
|||
"summary": """Adds menu to find old messages""", |
|||
"category": "Discuss", |
|||
"images": ['images/1.jpg'], |
|||
"version": "1.0.0", |
|||
|
|||
"author": "IT-Projects LLC, Pavel Romanchenko", |
|||
"website": "https://twitter.com/OdooFree", |
|||
"license": "LGPL-3", |
|||
|
|||
"depends": [ |
|||
"mail_base", |
|||
], |
|||
|
|||
"data": [ |
|||
"views/templates.xml", |
|||
], |
|||
"qweb": [ |
|||
"static/src/xml/menu.xml", |
|||
], |
|||
'installable': True, |
|||
} |
After Width: 334 | Height: 171 | Size: 18 KiB |
After Width: 300 | Height: 270 | Size: 24 KiB |
After Width: 765 | Height: 400 | Size: 40 KiB |
After Width: 100 | Height: 100 | Size: 2.1 KiB |
@ -0,0 +1,82 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h2 class="oe_slogan">Look up old mails</h2> |
|||
<h3 class="oe_slogan">Browse archived mails like in odoo 8</h3> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="1.png"/> |
|||
</div> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<p class="oe_mt32"> |
|||
The module adds usual menu. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
This menu shows archive messages, i.e. ones you sent or received. |
|||
</p> |
|||
</div> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="2.png"/> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span8"> |
|||
<h2>Need our service?</h2> |
|||
<p class="oe_mt32">Contact us by <a href="mailto:it@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p> |
|||
<ul> |
|||
<li><a href="mailto:it@it-projects.info">it@it-projects.info <i class="fa fa-envelope-o"></i></a></li> |
|||
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="oe_span4"> |
|||
<div class="stamp" style="width:200px;"> |
|||
<div style="margin-top: 15px; |
|||
position: relative; |
|||
font-family:'Vollkorn', serif; |
|||
font-size: 16px; |
|||
line-height: 25px; |
|||
text-transform: uppercase; |
|||
font-weight: bold; |
|||
color: #75526b; |
|||
border: 3px dashed #75526b; |
|||
float: left; |
|||
padding: 4px 12px; |
|||
-webkit-transform: rotate(6deg); |
|||
-o-transform: rotate(6deg); |
|||
-moz-transform: rotate(6deg); |
|||
-ms-transform: rotate(6deg);"> |
|||
Tested on Odoo<br/>9.0 community |
|||
</div> |
|||
<div style="margin-top: 15px; |
|||
position: relative; |
|||
font-family:'Vollkorn', serif; |
|||
font-size: 16px; |
|||
line-height: 25px; |
|||
text-transform: uppercase; |
|||
font-weight: bold; |
|||
color: #75526b; |
|||
border: 3px dashed #75526b; |
|||
float: left; |
|||
padding: 4px 12px; |
|||
-webkit-transform: rotate(-7deg); |
|||
-o-transform: rotate(-7deg); |
|||
-moz-transform: rotate(-7deg); |
|||
-ms-transform: rotate(-7deg);"> |
|||
Tested on Odoo<br/>9.0 enterprise |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
@ -0,0 +1,85 @@ |
|||
odoo.define('mail_archives.archives', function (require) { |
|||
"use strict"; |
|||
|
|||
var base_obj = require('mail_base.base'); |
|||
|
|||
//-------------------------------------------------------------------------------
|
|||
var bus = require('bus.bus').bus; |
|||
var config = require('web.config'); |
|||
var core = require('web.core'); |
|||
var data = require('web.data'); |
|||
var Model = require('web.Model'); |
|||
var session = require('web.session'); |
|||
var time = require('web.time'); |
|||
var web_client = require('web.web_client'); |
|||
|
|||
var _lt = core._lt; |
|||
//-------------------------------------------------------------------------------
|
|||
|
|||
var ChatAction = core.action_registry.get('mail.chat.instant_messaging'); |
|||
ChatAction.include({ |
|||
init: function(parent, action, options) { |
|||
this._super.apply(this, arguments); |
|||
var channel_name = 'channel_archive'; |
|||
// Add channel Archive for enable "display_subject" option
|
|||
this.channels_display_subject.push(channel_name); |
|||
}, |
|||
|
|||
update_message_on_current_channel: function(current_channel_id, message){ |
|||
var result = this._super.apply(this, arguments); |
|||
var archive = current_channel_id === "channel_archive" && !message.is_archive; |
|||
return archive || result; |
|||
} |
|||
}); |
|||
|
|||
// Inherit class and override methods
|
|||
base_obj.MailTools.include({ |
|||
get_properties: function(msg){ |
|||
var properties = this._super.apply(this, arguments); |
|||
properties.is_archive = this.property_descr("channel_archive", msg, this); |
|||
return properties; |
|||
}, |
|||
|
|||
set_channel_flags: function(data, msg){ |
|||
this._super.apply(this, arguments); |
|||
// Get recipients ids
|
|||
var recipients_ids = []; |
|||
for (var i = 0; i < data.partner_ids.length; i++){ |
|||
recipients_ids.push(data.partner_ids[i][0]); |
|||
} |
|||
|
|||
// If author or recipient
|
|||
if (data.author_id[0] == session.partner_id || recipients_ids.indexOf(session.partner_id) != -1) { |
|||
msg.is_archive = true; |
|||
} |
|||
|
|||
return msg; |
|||
}, |
|||
|
|||
get_channel_array: function(msg){ |
|||
var arr = this._super.apply(this, arguments); |
|||
return arr.concat('channel_archive'); |
|||
}, |
|||
|
|||
get_domain: function(channel){ |
|||
return (channel.id === "channel_archive") ? [ |
|||
'|', ['partner_ids', 'in', [openerp.session.partner_id]], |
|||
['author_id.user_ids', 'in', [openerp.session.uid]] |
|||
] : this._super.apply(this, arguments); |
|||
} |
|||
}); |
|||
|
|||
base_obj.chat_manager.is_ready.then(function(){ |
|||
// Add archive channel
|
|||
base_obj.chat_manager.mail_tools.add_channel({ |
|||
id: "channel_archive", |
|||
name: _lt("Archive"), |
|||
type: "static" |
|||
}); |
|||
|
|||
return $.when(); |
|||
}); |
|||
|
|||
return base_obj.chat_manager; |
|||
|
|||
}); |
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<template> |
|||
<!--Inherit Sidebar and add Archive menu item after Starred --> |
|||
<t t-extend="mail.chat.Sidebar"> |
|||
<t t-jquery="div[data-channel-id=channel_starred]" t-operation="after"> |
|||
<div t-attf-class="o_mail_chat_channel_item #{(active_channel_id == 'channel_archive') ? 'o_active': ''}" data-channel-id="channel_archive"> |
|||
<span class="o_channel_name mail_archives"> <i class="fa fa-archive"/> Archive </span> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
<!--Add message about empty archive page--> |
|||
<t t-extend="mail.EmptyChannel"> |
|||
<t t-jquery="t:last-child" t-operation="after"> |
|||
<t t-if="options.channel_id==='channel_archive'"> |
|||
<div class="o_thread_title">Archive is empty</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</template> |
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from . import test_js |
@ -0,0 +1,18 @@ |
|||
# -*- coding: utf-8 -*- |
|||
import openerp.tests |
|||
|
|||
|
|||
@openerp.tests.common.at_install(False) |
|||
@openerp.tests.common.post_install(True) |
|||
class TestUi(openerp.tests.HttpCase): |
|||
|
|||
def test_01_mail_archives(self): |
|||
# wait till page loaded and then click and wait again |
|||
code = """ |
|||
setTimeout(function () { |
|||
$(".mail_archives").click(); |
|||
setTimeout(function () {console.log('ok');}, 3000); |
|||
}, 1000); |
|||
""" |
|||
link = '/web#action=%s' % self.ref('mail.mail_channel_action_client_chat') |
|||
self.phantom_js(link, code, "odoo.__DEBUG__.services['mail_archives.archives']", login="admin") |
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="res_partner_mails_count_assets_backend" |
|||
name="res_partner_mails_count_assets_backend" |
|||
inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script src="/mail_archives/static/src/js/archives.js" type="text/javascript"></script> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,26 @@ |
|||
.. image:: https://itpp.dev/images/infinity-readme.png |
|||
:alt: Tested and maintained by IT Projects Labs |
|||
:target: https://itpp.dev |
|||
|
|||
=================== |
|||
Popup Attachments |
|||
=================== |
|||
|
|||
The module opens attached mail images in popup. |
|||
|
|||
Questions? |
|||
========== |
|||
|
|||
To get an assistance on this module contact us by email :arrow_right: help@itpp.dev |
|||
|
|||
Contributors |
|||
============ |
|||
* Dinar Gabbasov <gabbasov@it-projects.info> |
|||
|
|||
Further information |
|||
=================== |
|||
|
|||
Odoo Apps Store: https://apps.odoo.com/apps/modules/9.0/mail_attachment_popup/ |
|||
|
|||
|
|||
Tested on `Odoo 9.0 <https://github.com/odoo/odoo/commit/021878f9c41c6d652abf345c3c5537fe92f8bc5b>`_ |
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
{ |
|||
"name": """Popup Attachments""", |
|||
"summary": """Open attached mail images in popup""", |
|||
"category": "Extra Tools", |
|||
"version": "1.0.0", |
|||
"images": ['images/popup_image.png'], |
|||
|
|||
"author": "IT-Projects LLC, Dinar Gabbasov", |
|||
'website': "https://twitter.com/gabbasov_dinar", |
|||
"license": "GPL-3", |
|||
|
|||
"depends": [ |
|||
"mail", |
|||
], |
|||
"external_dependencies": {"python": [], "bin": []}, |
|||
"data": [ |
|||
"views/mail_attachment_popup_template.xml", |
|||
], |
|||
"qweb": [ |
|||
"static/src/xml/mail_attachment_popup.xml", |
|||
], |
|||
|
|||
"installable": True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,4 @@ |
|||
`1.0.0` |
|||
------- |
|||
|
|||
- Init version |
@ -0,0 +1,16 @@ |
|||
=================== |
|||
Popup Attachments |
|||
=================== |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
* Open 'Messaging' menu |
|||
* Find any message with image in attachments |
|||
* Click on the image |
|||
* Browser opens image in popup instead of downloading it |
After Width: 749 | Height: 371 | Size: 128 KiB |
After Width: 361 | Height: 382 | Size: 63 KiB |
After Width: 361 | Height: 381 | Size: 131 KiB |
After Width: 100 | Height: 100 | Size: 2.1 KiB |
@ -0,0 +1,84 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h2 class="oe_slogan">Popup Attachments</h2> |
|||
<h3 class="oe_slogan">Open attachments in popup</h3> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
The module allows to open attachments (images) in popup. It is convenient if you want to display them only without downloading. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h3 class="oe_slogan">How it works</h3> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span6"> |
|||
<p class="oe_mt32"> |
|||
Go to "Messaging" menu and open email that contains image(s) in attachment. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_demo oe_picture oe_screenshot" src="attach_image.png"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span6"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_demo oe_picture oe_screenshot" src="popup.png"/> |
|||
</div> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<p class="oe_mt32"> |
|||
Click on the image and see how popup is appear. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span6"> |
|||
<p class="oe_mt32"> |
|||
Moreover, you can download it to your device by clicking on the "Download" button if needed. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span6"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_demo oe_picture oe_screenshot" src="download.png"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<h2>Need our service?</h2> |
|||
<p class="oe_mt32">Contact us by <a href="mailto:it@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p> |
|||
<ul> |
|||
<li><a href="mailto:it@it-projects.info">it@it-projects.info <i class="fa fa-envelope-o"></i></a></li> |
|||
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</section> |
After Width: 365 | Height: 382 | Size: 150 KiB |
@ -0,0 +1,429 @@ |
|||
/* |
|||
|
|||
arcticModal — jQuery plugin |
|||
Version: 0.3 |
|||
Author: Sergey Predvoditelev (sergey.predvoditelev@gmail.com) |
|||
Company: Arctic Laboratory (http://arcticlab.ru/)
|
|||
|
|||
Docs & Examples: http://arcticlab.ru/arcticmodal/
|
|||
|
|||
*/ |
|||
(function($) { |
|||
|
|||
|
|||
var default_options = { |
|||
|
|||
type: 'html', // ajax или html
|
|||
content: '', |
|||
url: '', |
|||
ajax: {}, |
|||
ajax_request: null, |
|||
|
|||
closeOnEsc: true, |
|||
closeOnOverlayClick: true, |
|||
|
|||
clone: false, |
|||
|
|||
overlay: { |
|||
block: undefined, |
|||
tpl: '<div class="arcticmodal-overlay"></div>', |
|||
css: { |
|||
backgroundColor: '#000', |
|||
opacity: .6 |
|||
} |
|||
}, |
|||
|
|||
container: { |
|||
block: undefined, |
|||
tpl: '<div class="arcticmodal-container"><table class="arcticmodal-container_i"><tr><td class="arcticmodal-container_i2"></td></tr></table></div>' |
|||
}, |
|||
|
|||
wrap: undefined, |
|||
body: undefined, |
|||
|
|||
errors: { |
|||
tpl: '<div class="arcticmodal-error arcticmodal-close"></div>', |
|||
autoclose_delay: 2000, |
|||
ajax_unsuccessful_load: 'Error' |
|||
}, |
|||
|
|||
openEffect: { |
|||
type: 'fade', |
|||
speed: 400 |
|||
}, |
|||
closeEffect: { |
|||
type: 'fade', |
|||
speed: 400 |
|||
}, |
|||
|
|||
beforeOpen: $.noop, |
|||
afterOpen: $.noop, |
|||
beforeClose: $.noop, |
|||
afterClose: $.noop, |
|||
afterLoading: $.noop, |
|||
afterLoadingOnShow: $.noop, |
|||
errorLoading: $.noop |
|||
|
|||
}; |
|||
|
|||
|
|||
var modalID = 0; |
|||
var modals = $([]); |
|||
|
|||
|
|||
var utils = { |
|||
|
|||
|
|||
// Определяет произошло ли событие e вне блока block
|
|||
isEventOut: function(blocks, e) { |
|||
var r = true; |
|||
$(blocks).each(function() { |
|||
if ($(e.target).get(0)==$(this).get(0)) r = false; |
|||
if ($(e.target).closest('HTML', $(this).get(0)).length==0) r = false; |
|||
}); |
|||
return r; |
|||
} |
|||
|
|||
|
|||
}; |
|||
|
|||
|
|||
var modal = { |
|||
|
|||
|
|||
// Возвращает элемент, которым был вызван плагин
|
|||
getParentEl: function(el) { |
|||
var r = $(el); |
|||
if (r.data('arcticmodal')) return r; |
|||
r = $(el).closest('.arcticmodal-container').data('arcticmodalParentEl'); |
|||
if (r) return r; |
|||
return false; |
|||
}, |
|||
|
|||
|
|||
// Переход
|
|||
transition: function(el, action, options, callback) { |
|||
callback = callback==undefined ? $.noop : callback; |
|||
switch (options.type) { |
|||
case 'fade': |
|||
action=='show' ? el.fadeIn(options.speed, callback) : el.fadeOut(options.speed, callback); |
|||
break; |
|||
case 'none': |
|||
action=='show' ? el.show() : el.hide(); |
|||
callback(); |
|||
break; |
|||
} |
|||
}, |
|||
|
|||
|
|||
// Подготвка содержимого окна
|
|||
prepare_body: function(D, $this) { |
|||
|
|||
// Обработчик закрытия
|
|||
$('.arcticmodal-close', D.body).unbind('click.arcticmodal').bind('click.arcticmodal', function() { |
|||
$this.arcticmodal('close'); |
|||
return false; |
|||
}); |
|||
|
|||
}, |
|||
|
|||
|
|||
// Инициализация элемента
|
|||
init_el: function($this, options) { |
|||
var D = $this.data('arcticmodal'); |
|||
if (D) return; |
|||
|
|||
D = options; |
|||
modalID++; |
|||
D.modalID = modalID; |
|||
|
|||
// Overlay
|
|||
D.overlay.block = $(D.overlay.tpl); |
|||
D.overlay.block.css(D.overlay.css); |
|||
|
|||
// Container
|
|||
D.container.block = $(D.container.tpl); |
|||
|
|||
// BODY
|
|||
D.body = $('.arcticmodal-container_i2', D.container.block); |
|||
if (options.clone) { |
|||
D.body.html($this.clone(true)); |
|||
} else { |
|||
$this.before('<div id="arcticmodalReserve' + D.modalID + '" style="display: none" />'); |
|||
D.body.html($this); |
|||
} |
|||
|
|||
// Подготовка содержимого
|
|||
modal.prepare_body(D, $this); |
|||
|
|||
// Закрытие при клике на overlay
|
|||
if (D.closeOnOverlayClick) |
|||
D.overlay.block.add(D.container.block).click(function(e) { |
|||
if (utils.isEventOut($('>*', D.body), e)) |
|||
$this.arcticmodal('close'); |
|||
}); |
|||
|
|||
// Запомним настройки
|
|||
D.container.block.data('arcticmodalParentEl', $this); |
|||
$this.data('arcticmodal', D); |
|||
modals = $.merge(modals, $this); |
|||
|
|||
// Показать
|
|||
$.proxy(actions.show, $this)(); |
|||
if (D.type=='html') return $this; |
|||
|
|||
// Ajax-загрузка
|
|||
if (D.ajax.beforeSend!=undefined) { |
|||
var fn_beforeSend = D.ajax.beforeSend; |
|||
delete D.ajax.beforeSend; |
|||
} |
|||
if (D.ajax.success!=undefined) { |
|||
var fn_success = D.ajax.success; |
|||
delete D.ajax.success; |
|||
} |
|||
if (D.ajax.error!=undefined) { |
|||
var fn_error = D.ajax.error; |
|||
delete D.ajax.error; |
|||
} |
|||
var o = $.extend(true, { |
|||
url: D.url, |
|||
beforeSend: function() { |
|||
if (fn_beforeSend==undefined) { |
|||
D.body.html('<div class="arcticmodal-loading" />'); |
|||
} else { |
|||
fn_beforeSend(D, $this); |
|||
} |
|||
}, |
|||
success: function(responce) { |
|||
|
|||
// Событие после загрузки до показа содержимого
|
|||
$this.trigger('afterLoading'); |
|||
D.afterLoading(D, $this, responce); |
|||
|
|||
if (fn_success==undefined) { |
|||
D.body.html(responce); |
|||
} else { |
|||
fn_success(D, $this, responce); |
|||
} |
|||
modal.prepare_body(D, $this); |
|||
|
|||
// Событие после загрузки после отображения содержимого
|
|||
$this.trigger('afterLoadingOnShow'); |
|||
D.afterLoadingOnShow(D, $this, responce); |
|||
|
|||
}, |
|||
error: function() { |
|||
|
|||
// Событие при ошибке загрузки
|
|||
$this.trigger('errorLoading'); |
|||
D.errorLoading(D, $this); |
|||
|
|||
if (fn_error==undefined) { |
|||
D.body.html(D.errors.tpl); |
|||
$('.arcticmodal-error', D.body).html(D.errors.ajax_unsuccessful_load); |
|||
$('.arcticmodal-close', D.body).click(function() { |
|||
$this.arcticmodal('close'); |
|||
return false; |
|||
}); |
|||
if (D.errors.autoclose_delay) |
|||
setTimeout(function() { |
|||
$this.arcticmodal('close'); |
|||
}, D.errors.autoclose_delay); |
|||
} else { |
|||
fn_error(D, $this); |
|||
} |
|||
} |
|||
}, D.ajax); |
|||
D.ajax_request = $.ajax(o); |
|||
|
|||
// Запомнить настройки
|
|||
$this.data('arcticmodal', D); |
|||
|
|||
}, |
|||
|
|||
|
|||
// Инициализация
|
|||
init: function(options) { |
|||
options = $.extend(true, {}, default_options, options); |
|||
if ($.isFunction(this)) { |
|||
if (options==undefined) { |
|||
$.error('jquery.arcticmodal: Uncorrect parameters'); |
|||
return; |
|||
} |
|||
if (options.type=='') { |
|||
$.error('jquery.arcticmodal: Don\'t set parameter "type"'); |
|||
return; |
|||
} |
|||
switch (options.type) { |
|||
case 'html': |
|||
if (options.content=='') { |
|||
$.error('jquery.arcticmodal: Don\'t set parameter "content"'); |
|||
return |
|||
} |
|||
var c = options.content; |
|||
options.content = ''; |
|||
|
|||
return modal.init_el($(c), options); |
|||
break; |
|||
case 'ajax': |
|||
if (options.url=='') { |
|||
$.error('jquery.arcticmodal: Don\'t set parameter "url"'); |
|||
return; |
|||
} |
|||
return modal.init_el($('<div />'), options); |
|||
break; |
|||
} |
|||
} else { |
|||
return this.each(function() { |
|||
modal.init_el($(this), $.extend(true, {}, options)); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
|
|||
}; |
|||
|
|||
|
|||
var actions = { |
|||
|
|||
|
|||
// Показать
|
|||
show: function() { |
|||
var $this = modal.getParentEl(this); |
|||
if ($this===false) { |
|||
$.error('jquery.arcticmodal: Uncorrect call'); |
|||
return; |
|||
} |
|||
var D = $this.data('arcticmodal'); |
|||
|
|||
// Добавить overlay и container
|
|||
D.overlay.block.hide(); |
|||
D.container.block.hide(); |
|||
$('BODY').append(D.overlay.block); |
|||
$('BODY').append(D.container.block); |
|||
|
|||
// Событие
|
|||
D.beforeOpen(D, $this); |
|||
$this.trigger('beforeOpen'); |
|||
|
|||
// Wrap
|
|||
if (D.wrap.css('overflow')!='hidden') { |
|||
D.wrap.data('arcticmodalOverflow', D.wrap.css('overflow')); |
|||
var w1 = D.wrap.outerWidth(true); |
|||
D.wrap.css('overflow', 'hidden'); |
|||
var w2 = D.wrap.outerWidth(true); |
|||
if (w2!=w1) |
|||
D.wrap.css('marginRight', (w2 - w1) + 'px'); |
|||
} |
|||
|
|||
// Скрыть предыдущие оверлеи
|
|||
modals.not($this).each(function() { |
|||
var d = $(this).data('arcticmodal'); |
|||
d.overlay.block.hide(); |
|||
}); |
|||
|
|||
// Показать
|
|||
modal.transition(D.overlay.block, 'show', modals.length>1 ? {type: 'none'} : D.openEffect); |
|||
modal.transition(D.container.block, 'show', modals.length>1 ? {type: 'none'} : D.openEffect, function() { |
|||
D.afterOpen(D, $this); |
|||
$this.trigger('afterOpen'); |
|||
}); |
|||
|
|||
return $this; |
|||
}, |
|||
|
|||
|
|||
// Закрыть
|
|||
close: function() { |
|||
if ($.isFunction(this)) { |
|||
modals.each(function() { |
|||
$(this).arcticmodal('close'); |
|||
}); |
|||
} else { |
|||
return this.each(function() { |
|||
var $this = modal.getParentEl(this); |
|||
if ($this===false) { |
|||
$.error('jquery.arcticmodal: Uncorrect call'); |
|||
return; |
|||
} |
|||
var D = $this.data('arcticmodal'); |
|||
|
|||
// Событие перед закрытием
|
|||
if (D.beforeClose(D, $this)===false) return; |
|||
$this.trigger('beforeClose'); |
|||
|
|||
// Показать предыдущие оверлеи
|
|||
modals.not($this).last().each(function() { |
|||
var d = $(this).data('arcticmodal'); |
|||
d.overlay.block.show(); |
|||
}); |
|||
|
|||
modal.transition(D.overlay.block, 'hide', modals.length>1 ? {type: 'none'} : D.closeEffect); |
|||
modal.transition(D.container.block, 'hide', modals.length>1 ? {type: 'none'} : D.closeEffect, function() { |
|||
|
|||
// Событие после закрытия
|
|||
D.afterClose(D, $this); |
|||
$this.trigger('afterClose'); |
|||
|
|||
// Если не клонировали - вернём на место
|
|||
if (!D.clone) |
|||
$('#arcticmodalReserve' + D.modalID).replaceWith(D.body.find('>*')); |
|||
|
|||
D.overlay.block.remove(); |
|||
D.container.block.remove(); |
|||
$this.data('arcticmodal', null); |
|||
if (!$('.arcticmodal-container').length) { |
|||
if (D.wrap.data('arcticmodalOverflow')) |
|||
D.wrap.css('overflow', D.wrap.data('arcticmodalOverflow')); |
|||
D.wrap.css('marginRight', 0); |
|||
} |
|||
|
|||
}); |
|||
|
|||
if (D.type=='ajax') |
|||
D.ajax_request.abort(); |
|||
|
|||
modals = modals.not($this); |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
|
|||
// Установить опции по-умолчанию
|
|||
setDefault: function(options) { |
|||
$.extend(true, default_options, options); |
|||
} |
|||
|
|||
|
|||
}; |
|||
|
|||
|
|||
$(function() { |
|||
default_options.wrap = $((document.all && !document.querySelector) ? 'html' : 'body'); |
|||
}); |
|||
|
|||
|
|||
// Закрытие при нажатии Escape
|
|||
$(document).bind('keyup.arcticmodal', function(e) { |
|||
var m = modals.last(); |
|||
if (!m.length) return; |
|||
var D = m.data('arcticmodal'); |
|||
if (D.closeOnEsc && (e.keyCode===27)) |
|||
m.arcticmodal('close'); |
|||
}); |
|||
|
|||
|
|||
$.arcticmodal = $.fn.arcticmodal = function(method) { |
|||
|
|||
if (actions[method]) { |
|||
return actions[method].apply(this, Array.prototype.slice.call(arguments, 1)); |
|||
} else if (typeof method==='object' || !method) { |
|||
return modal.init.apply(this, arguments); |
|||
} else { |
|||
$.error('jquery.arcticmodal: Method ' + method + ' does not exist'); |
|||
} |
|||
|
|||
}; |
|||
|
|||
|
|||
})(jQuery); |
@ -0,0 +1,8 @@ |
|||
.arcticmodal-overlay, |
|||
.arcticmodal-container { position: fixed; left: 0; top: 0; right: 0; bottom: 0; z-index: 1010; } |
|||
.arcticmodal-container { overflow: auto; margin: 0; padding: 0; border: 0; border-collapse: collapse; } |
|||
*:first-child+html .arcticmodal-container { height: 100% } |
|||
.arcticmodal-container_i { height: 100%; margin: 0 auto; } |
|||
.arcticmodal-container_i2 { padding: 24px; margin: 0; border: 0; vertical-align: middle; padding-top: 50px;} |
|||
.arcticmodal-error { padding: 20px; border-radius: 10px; background: #000; color: #fff; } |
|||
.arcticmodal-loading { width: 80px; height: 80px; border-radius: 10px; background: #000 url(/mail_attachment_popup/static/src/img/loading.gif) no-repeat 50% 50%; } |
@ -0,0 +1,11 @@ |
|||
.box-modal { |
|||
position: relative; |
|||
padding: 16px; |
|||
background: #fff; |
|||
color: #3c3c3c; |
|||
font: 14px/18px Arial, "Helvetica CY", "Nimbus Sans L", sans-serif; |
|||
box-shadow: 0 0 0 6px rgba(153, 153, 153, .3); |
|||
border-radius: 6px; |
|||
} |
|||
.box-modal_close { position: absolute; right: -25px; top: -25px; font-size: 30px; line-height: 15px; color: #ffffff; cursor: pointer; } |
|||
.box-modal_close:hover { color: #B1B1B1; } |
@ -0,0 +1,16 @@ |
|||
.g-hidden { |
|||
display: none; |
|||
} |
|||
.box-modal img { |
|||
max-width: 900px; |
|||
width: 100%; |
|||
} |
|||
.box-modal-li li { |
|||
list-style-type: none; |
|||
} |
|||
.box-modal-li { |
|||
padding-left: 0; |
|||
} |
|||
.o_attachment .o_image { |
|||
cursor: pointer; |
|||
} |
After Width: 32 | Height: 32 | Size: 3.1 KiB |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<template> |
|||
<t t-extend="mail.Attachment"> |
|||
<t t-jquery="div[t-att-title='attachment.name'] .o_image" t-operation="replace"> |
|||
<t t-if="attachment.mimetype and attachment.mimetype.search('image/') !== -1"> |
|||
<span class="m-dotted" t-attf-onclick="$('#ImageModal{{ attachment.id }}').arcticmodal()"> |
|||
<div class="o_image" target="_blank" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/100x80"> |
|||
<span class='o_attachment_name'><t t-esc='attachment.name'/></span> |
|||
</div> |
|||
</span> |
|||
<div class="g-hidden"> |
|||
<div class="box-modal" t-attf-id="ImageModal{{ attachment.id }}"> |
|||
<div class="box-modal_close arcticmodal-close">X</div> |
|||
<img t-att-data-mimetype="attachment.mimetype" t-attf-src="/web/image/#{attachment.id}"></img> |
|||
<ul class="box-modal-li"> |
|||
<li><span class='o_attachment_name'><t t-esc='attachment.name'/></span></li> |
|||
<li><span class='oe_download_original_img'><a t-att-href='attachment.url' target="_blank">Download</a></span></li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
<t t-if="! (attachment.mimetype and attachment.mimetype.search('image/') !== -1)"> |
|||
<a class="o_image" t-att-href='attachment.url' target="_blank" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/100x80"> |
|||
<span class='o_attachment_name'><t t-esc='attachment.name'/></span> |
|||
</a> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
</template> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="assets_backend" name="mail attachment popup assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<link rel="stylesheet" href="/mail_attachment_popup/static/src/css/jquery.arcticmodal.css"/> |
|||
<link rel="stylesheet" href="/mail_attachment_popup/static/src/css/simple.css"/> |
|||
<link rel="stylesheet" href="/mail_attachment_popup/static/src/css/styles.css"/> |
|||
<script type="text/javascript" src="/mail_attachment_popup/static/lib/js/jquery.arcticmodal.js"></script> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,26 @@ |
|||
.. image:: https://itpp.dev/images/infinity-readme.png |
|||
:alt: Tested and maintained by IT Projects Labs |
|||
:target: https://itpp.dev |
|||
|
|||
Mail Base |
|||
========= |
|||
|
|||
* makes built-in mail js features extendable. |
|||
* handles ``search_default_*`` parameters in context. |
|||
* fixes toggling left bar |
|||
* fixes Recipients field. Out-of-box this field could be empty. |
|||
|
|||
One can say, that the module do this todo from `addons/mail/static/src/js/chat_manager.js <https://github.com/odoo/odoo/blob/9.0/addons/mail/static/src/js/chat_manager.js#L57>`__ |
|||
|
|||
// to do: move this to mail.utils |
|||
|
|||
|
|||
Note. Due to odoo restrictions, module makes mail initialization again. That is browser loads emoji and other chat data twice. This is the only way to make Mail feature extendable. |
|||
|
|||
Further information |
|||
=================== |
|||
|
|||
.. Odoo Apps Store: https://apps.odoo.com/apps/modules/9.0/mail_base/ |
|||
|
|||
|
|||
Tested on `Odoo 9.0 <https://github.com/odoo/odoo/commit/ed463864366029f8d4289db831fcdc196fc716cb>`_ |
@ -0,0 +1,4 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from . import models |
|||
from . import controllers |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
{ |
|||
"name": "Mail Base", |
|||
"summary": """Makes Mail extendable""", |
|||
"category": "Discuss", |
|||
"images": [], |
|||
"version": "1.0.1", |
|||
|
|||
"author": "IT-Projects LLC, Pavel Romanchenko", |
|||
"website": "https://twitter.com/OdooFree", |
|||
"license": "LGPL-3", |
|||
|
|||
"depends": [ |
|||
"base", |
|||
"mail" |
|||
], |
|||
|
|||
"data": [ |
|||
"views/templates.xml", |
|||
], |
|||
'installable': True, |
|||
} |
@ -0,0 +1 @@ |
|||
from . import main |
@ -0,0 +1,15 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from openerp.http import request |
|||
from openerp.addons.bus.controllers.main import BusController |
|||
|
|||
|
|||
class MailChatController(BusController): |
|||
# ----------------------------- |
|||
# Extends BUS Controller Poll |
|||
# ----------------------------- |
|||
|
|||
def _poll(self, dbname, channels, last, options): |
|||
if request.session.uid: |
|||
channels.append((request.db, 'mail_base.mail_sent')) |
|||
|
|||
return super(MailChatController, self)._poll(dbname, channels, last, options) |
@ -0,0 +1,9 @@ |
|||
`1.0.1` |
|||
------- |
|||
|
|||
- **FIX**: clear messages cache on sending message via Mail Composer. Otherwise Sent, Arhives menus will have new message until user refresh whole web page |
|||
|
|||
`1.0.0` |
|||
------- |
|||
|
|||
- Init version |
@ -0,0 +1,4 @@ |
|||
Mail Base |
|||
========= |
|||
|
|||
To use this module you need either install module that depends on it or create new module. |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from openerp import api, models |
|||
|
|||
|
|||
class MailMessage(models.Model): |
|||
_inherit = 'mail.message' |
|||
|
|||
@api.multi |
|||
def write(self, values): |
|||
if values.get('needaction_partner_ids'): |
|||
if not values.get('partner_ids'): |
|||
values['partner_ids'] = [] |
|||
for triplet in values.get('needaction_partner_ids'): |
|||
if triplet[0] == 6: |
|||
for id in triplet[2]: |
|||
values['partner_ids'].append((4, id, False)) |
|||
return super(MailMessage, self).write(values) |
|||
|
|||
|
|||
class MailComposer(models.TransientModel): |
|||
|
|||
_inherit = 'mail.compose.message' |
|||
|
|||
@api.multi |
|||
def send_mail(self, auto_commit=False): |
|||
res = super(MailComposer, self).send_mail(auto_commit=auto_commit) |
|||
notification = {} |
|||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail_base.mail_sent'), notification) |
|||
|
|||
return res |
After Width: 100 | Height: 100 | Size: 2.1 KiB |
1197
mail_base/static/lib/base.js
File diff suppressed because it is too large
View File
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="mail_base_assets_backend" |
|||
name="mail_base_assets_backend" |
|||
inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script src="/mail_base/static/lib/base.js" type="text/javascript"></script> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,12 @@ |
|||
.. image:: https://itpp.dev/images/infinity-readme.png |
|||
:alt: Tested and maintained by IT Projects Labs |
|||
:target: https://itpp.dev |
|||
|
|||
Mail relocation |
|||
=============== |
|||
|
|||
Description: https://www.odoo.com/apps/modules/9.0/mail_move_message/ |
|||
|
|||
Further information and discussion: http://yelizariev.github.io/odoo/module/2015/04/10/mail-relocation.html |
|||
|
|||
Tested on `Odoo 8.0 <https://github.com/odoo/odoo/commit/d023c079ed86468436f25da613bf486a4a17d625>`_ |
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import controllers |
|||
from . import mail_move_message_models |
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
{ |
|||
'name': 'Mail relocation', |
|||
'version': '1.0.4', |
|||
'author': 'IT-Projects LLC, Ivan Yelizariev, Pavel Romanchenko', |
|||
'license': 'LGPL-3', |
|||
'category': 'Discuss', |
|||
'website': 'https://twitter.com/yelizariev', |
|||
'depends': ['mail_all', 'web_polymorphic_field'], |
|||
'images': ['images/inbox.png'], |
|||
'data': [ |
|||
'mail_move_message_views.xml', |
|||
'data/mail_move_message_data.xml', |
|||
], |
|||
'qweb': [ |
|||
'static/src/xml/mail_move_message_main.xml', |
|||
], |
|||
'installable': True, |
|||
} |
@ -0,0 +1,2 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import main |
@ -0,0 +1,69 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from openerp.addons.web.controllers.main import DataSet |
|||
from openerp.tools.translate import _ |
|||
from openerp import http |
|||
from openerp.http import request |
|||
import openerp |
|||
|
|||
|
|||
class MailChatController(openerp.addons.bus.controllers.main.BusController): |
|||
# ----------------------------- |
|||
# Extends BUS Controller Poll |
|||
# ----------------------------- |
|||
|
|||
def _poll(self, dbname, channels, last, options): |
|||
if request.session.uid: |
|||
channels.append((request.db, 'mail_move_message')) |
|||
channels.append((request.db, 'mail_move_message.delete_message')) |
|||
return super(MailChatController, self)._poll(dbname, channels, last, options) |
|||
|
|||
|
|||
class DataSetCustom(DataSet): |
|||
|
|||
def _extend_name(self, model, records): |
|||
cr, uid, context = request.cr, request.uid, request.context |
|||
Model = request.registry[model] |
|||
fields = Model.fields_get(cr, uid, False, context) |
|||
contact_field = False |
|||
for n, f in fields.iteritems(): |
|||
if f['type'] == 'many2one' and f['relation'] == 'res.partner': |
|||
contact_field = n |
|||
break |
|||
partner_info = {} |
|||
if contact_field: |
|||
partner_info = Model.read(cr, uid, [r[0] for r in records], [contact_field], context) |
|||
partner_info = dict([(p['id'], p[contact_field]) for p in partner_info]) |
|||
res = [] |
|||
for r in records: |
|||
if partner_info.get(r[0]): |
|||
res.append((r[0], _('%s [%s] ID %s') % (r[1], partner_info.get(r[0])[1], r[0]))) |
|||
else: |
|||
res.append((r[0], _('%s ID %s') % (r[1], r[0]))) |
|||
return res |
|||
|
|||
@http.route('/web/dataset/call_kw/<model>/name_search', type='json', auth="user") |
|||
def name_search(self, model, method, args, kwargs): |
|||
context = kwargs.get('context') |
|||
if context and context.get('extended_name_with_contact'): |
|||
# add order by ID desc |
|||
cr, uid = request.cr, request.uid |
|||
Model = request.registry[model] |
|||
search_args = list(kwargs.get('args') or []) |
|||
limit = int(kwargs.get('limit') or 100) |
|||
operator = kwargs.get('operator') |
|||
name = kwargs.get('name') |
|||
if Model._rec_name and (not name == '' and operator == 'ilike'): |
|||
search_args += [(Model._rec_name, operator, name)] |
|||
ids = Model.search(cr, uid, search_args, limit=limit, order='id desc', context=context) |
|||
res = Model.name_get(cr, uid, ids, context) |
|||
return self._extend_name(model, res) |
|||
|
|||
return self._call_kw(model, method, args, kwargs) |
|||
|
|||
@http.route('/web/dataset/call_kw/<model>/name_get', type='json', auth="user") |
|||
def name_get(self, model, method, args, kwargs): |
|||
res = self._call_kw(model, method, args, kwargs) |
|||
context = kwargs.get('context') |
|||
if context and context.get('extended_name_with_contact'): |
|||
res = self._extend_name(model, res) |
|||
return res |
@ -0,0 +1,9 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
<record id="mail_relocation_models" model="ir.config_parameter"> |
|||
<field name="key">mail_relocation_models</field> |
|||
<field name="value">crm.lead,project.task</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,21 @@ |
|||
`1.0.4` |
|||
------- |
|||
|
|||
- FIX: don't allow to relocate message to itself as it cause infinitive loop |
|||
- ADD: 'Move Followers' option -- Add followers of current record to a new record. |
|||
|
|||
`1.0.3` |
|||
------- |
|||
|
|||
- FIX email_from parsing. There was an error with specific email_from value (e.g. '"name @ example" <name@example.com>') |
|||
|
|||
`1.0.2` |
|||
------- |
|||
|
|||
- big improvements in interface |
|||
|
|||
`1.0.1` |
|||
------- |
|||
|
|||
- fix bug "some messages are not shown in inbox after relocation" |
|||
- improve "Move back" tool |
@ -0,0 +1,173 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_move_message |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-08-11 06:53+0000\n" |
|||
"PO-Revision-Date: 2015-08-11 06:53+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Cancel" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,id:0 |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,is_moved:0 |
|||
msgid "Is moved" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,record_url:0 |
|||
msgid "Link to record" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: model:ir.model,name:mail_move_message.model_mail_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
#: field:mail_move_message.wizard,message_id:0 |
|||
msgid "Message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Move" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail_move_message.wizard,move_back:0 |
|||
msgid "Move message and submessages to original place" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Move Message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,move_back:0 |
|||
msgid "Move to origin" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#. openerp-web |
|||
#: code:addons/mail_move_message/static/src/xml/mail_move_message_main.xml:5 |
|||
#, python-format |
|||
msgid "Move to thread" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_by_message_id:0 |
|||
msgid "Moved by message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_by_user_id:0 |
|||
msgid "Moved by user" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Open message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_parent_id:0 |
|||
msgid "Parent Message (Original)" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: code:addons/mail_move_message/mail_move_message_models.py:107 |
|||
#, python-format |
|||
msgid "Record" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,res_id:0 |
|||
msgid "Record ID" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,model_id:0 |
|||
msgid "Record type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_res_id:0 |
|||
msgid "Related Document ID (Original)" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_model:0 |
|||
msgid "Related Document Model (Original)" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#. openerp-web |
|||
#: code:addons/mail_move_message/static/src/js/mail_move_message.js:17 |
|||
#, python-format |
|||
msgid "Relocate Message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,parent_id:0 |
|||
msgid "Search by name" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail.message,moved_by_message_id:0 |
|||
msgid "Top message, that initate moving this message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "You cannot move this message. It was already moved with a message bellow. Open one and apply changes there." |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail_move_message.wizard,model_id:0 |
|||
msgid "List available Models is configured at Settings\Technical\Emails\Mail Relocation. Empty for unassigned email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail_move_message.wizard,filter_by_partner:0 |
|||
msgid "Show only records with the same partner as email author" |
|||
msgstr "" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail_move_message.wizard,move_followers:0 |
|||
msgid "Add followers of current record to a new record.\nYou must use this option, if new record has restricted access.\nYou can change default value for this option at Settings/System Parameters" |
|||
msgstr "" |
@ -0,0 +1,160 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_move_message |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-08-11 06:53+0000\n" |
|||
"PO-Revision-Date: 2015-08-11 08:58+0200\n" |
|||
"Last-Translator: Matjaz Mozetic <m.mozetic@matmoz.si>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"Plural-Forms: \n" |
|||
"Language: sl\n" |
|||
"X-Generator: Poedit 1.8.2\n" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Cancel" |
|||
msgstr "Preklic" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "Ustvaril" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "Ustvarjeno" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,id:0 |
|||
msgid "ID" |
|||
msgstr "ID" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,is_moved:0 |
|||
msgid "Is moved" |
|||
msgstr "Je premaknjeno" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "Zadnjič posodobil" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "Zadnjič posodobljeno" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,record_url:0 |
|||
msgid "Link to record" |
|||
msgstr "Povezava do zapisa" |
|||
|
|||
#. module: mail_move_message |
|||
#: model:ir.model,name:mail_move_message.model_mail_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
#: field:mail_move_message.wizard,message_id:0 |
|||
msgid "Message" |
|||
msgstr "Sporočilo" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Move" |
|||
msgstr "Premik" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail_move_message.wizard,move_back:0 |
|||
msgid "Move message and submessages to original place" |
|||
msgstr "Premik sporočila in podrejenih sporočil na izvorno mesto" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Move Message" |
|||
msgstr "Premik sporočila" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,move_back:0 |
|||
msgid "Move to origin" |
|||
msgstr "Premik na izvor" |
|||
|
|||
#. module: mail_move_message |
|||
#. openerp-web |
|||
#: code:addons/mail_move_message/static/src/xml/mail_move_message_main.xml:5 |
|||
#, python-format |
|||
msgid "Move to thread" |
|||
msgstr "Premik v nit" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_by_message_id:0 |
|||
msgid "Moved by message" |
|||
msgstr "Premaknjeno s sporočilom" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_by_user_id:0 |
|||
msgid "Moved by user" |
|||
msgstr "Premaknil uporabnik" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "Open message" |
|||
msgstr "Odpri sporočilo" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_parent_id:0 |
|||
msgid "Parent Message (Original)" |
|||
msgstr "Nadrejeno sporočilo (original)" |
|||
|
|||
#. module: mail_move_message |
|||
#: code:addons/mail_move_message/mail_move_message_models.py:107 |
|||
#, python-format |
|||
msgid "Record" |
|||
msgstr "Zapis" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,res_id:0 |
|||
msgid "Record ID" |
|||
msgstr "ID zapisa" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,model_id:0 |
|||
msgid "Record type" |
|||
msgstr "Tip zapisa" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_res_id:0 |
|||
msgid "Related Document ID (Original)" |
|||
msgstr "ID povezanega dokumenta (original)" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail.message,moved_from_model:0 |
|||
msgid "Related Document Model (Original)" |
|||
msgstr "Model povezanega dokumenta (original)" |
|||
|
|||
#. module: mail_move_message |
|||
#. openerp-web |
|||
#: code:addons/mail_move_message/static/src/js/mail_move_message.js:17 |
|||
#, python-format |
|||
msgid "Relocate Message" |
|||
msgstr "Premik sporočila" |
|||
|
|||
#. module: mail_move_message |
|||
#: field:mail_move_message.wizard,parent_id:0 |
|||
msgid "Search by name" |
|||
msgstr "Iskanje po nazivu" |
|||
|
|||
#. module: mail_move_message |
|||
#: help:mail.message,moved_by_message_id:0 |
|||
msgid "Top message, that initate moving this message" |
|||
msgstr "Zgornje sporočilo, ki je sprožilo premik tega sporočila" |
|||
|
|||
#. module: mail_move_message |
|||
#: view:mail_move_message.wizard:mail_move_message.view_wizard |
|||
msgid "You cannot move this message. It was already moved with a message bellow. Open one and apply changes there." |
|||
msgstr "Tega sporočila ne morete premakniti, ker je bilo že premaknjeno s spodnjim sporočilom. Tam lahko uveljavljate spremembe." |
After Width: 861 | Height: 628 | Size: 58 KiB |
@ -0,0 +1,413 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from openerp import api |
|||
from openerp import fields |
|||
from openerp import models |
|||
from openerp.tools import email_split |
|||
from openerp.tools.translate import _ |
|||
|
|||
|
|||
class Wizard(models.TransientModel): |
|||
_name = 'mail_move_message.wizard' |
|||
|
|||
def _model_selection(self): |
|||
selection = [] |
|||
config_parameters = self.env['ir.config_parameter'] |
|||
model_names = config_parameters.get_param('mail_relocation_models') |
|||
model_names = model_names.split(',') if model_names else [] |
|||
|
|||
if 'default_message_id' in self.env.context: |
|||
message = self.env['mail.message'].browse(self.env.context['default_message_id']) |
|||
if message.model and message.model not in model_names: |
|||
model_names.append(message.model) |
|||
if message.moved_from_model and message.moved_from_model not in model_names: |
|||
model_names.append(message.moved_from_model) |
|||
if model_names: |
|||
selection = [(m.model, m.display_name) for m in self.env['ir.model'].search([('model', 'in', model_names)])] |
|||
|
|||
return selection |
|||
|
|||
@api.model |
|||
def default_get(self, fields_list): |
|||
res = super(Wizard, self).default_get(fields_list) |
|||
|
|||
model_fields = self.fields_get() |
|||
if model_fields['model']['selection']: |
|||
res['model'] = model_fields['model']['selection'] and model_fields['model']['selection'][0][0] |
|||
|
|||
if 'message_id' in res: |
|||
message = self.env['mail.message'].browse(res['message_id']) |
|||
email_from = message.email_from |
|||
parts = email_split(email_from.replace(' ', ',')) |
|||
if parts: |
|||
email = parts[0] |
|||
name = email_from.find(email) != -1 and email_from[:email_from.index(email)].replace('"', '').replace('<', '').strip() or email_from |
|||
else: |
|||
name, email = email_from |
|||
res['message_name_from'] = name |
|||
res['message_email_from'] = email |
|||
|
|||
res['partner_id'] = message.author_id.id |
|||
if message.author_id and self.env.uid not in [u.id for u in message.author_id.user_ids]: |
|||
res['filter_by_partner'] = True |
|||
if message.author_id and res.get('model'): |
|||
res_id = self.env[res['model']].search([], order='id desc', limit=1) |
|||
res['res_id'] = res_id and res_id[0].id |
|||
|
|||
config_parameters = self.env['ir.config_parameter'] |
|||
res['move_followers'] = config_parameters.get_param('mail_relocation_move_followers') |
|||
|
|||
res['uid'] = self.env.uid |
|||
|
|||
return res |
|||
|
|||
message_id = fields.Many2one('mail.message', string='Message') |
|||
message_body = fields.Html(related='message_id.body', string='Message to move', readonly=True) |
|||
message_from = fields.Char(related='message_id.email_from', string='From', readonly=True) |
|||
message_subject = fields.Char(related='message_id.subject', string='Subject', readonly=True) |
|||
message_moved_by_message_id = fields.Many2one('mail.message', related='message_id.moved_by_message_id', string='Moved with', readonly=True) |
|||
message_moved_by_user_id = fields.Many2one('res.users', related='message_id.moved_by_user_id', string='Moved by', readonly=True) |
|||
message_is_moved = fields.Boolean(string='Is Moved', related='message_id.is_moved', readonly=True) |
|||
parent_id = fields.Many2one('mail.message', string='Search by name', ) |
|||
model = fields.Selection(_model_selection, string='Model') |
|||
res_id = fields.Integer(string='Record') |
|||
can_move = fields.Boolean('Can move', compute='get_can_move') |
|||
move_back = fields.Boolean('MOVE TO ORIGIN', help='Move message and submessages to original place') |
|||
partner_id = fields.Many2one('res.partner', string='Author') |
|||
filter_by_partner = fields.Boolean('Filter Records by partner') |
|||
message_email_from = fields.Char() |
|||
message_name_from = fields.Char() |
|||
# FIXME message_to_read should be True even if current message or any his childs are unread |
|||
message_to_read = fields.Boolean(related='message_id.needaction') |
|||
uid = fields.Integer() |
|||
move_followers = fields.Boolean( |
|||
'Move Followers', |
|||
help="Add followers of current record to a new record.\n" |
|||
"You must use this option, if new record has restricted access.\n" |
|||
"You can change default value for this option at Settings/System Parameters") |
|||
|
|||
@api.depends('message_id') |
|||
@api.one |
|||
def get_can_move(self): |
|||
# message was not moved before OR message is a top message of previous move |
|||
self.can_move = not self.message_id.moved_by_message_id or self.message_id.moved_by_message_id.id == self.message_id.id |
|||
|
|||
@api.onchange('move_back') |
|||
def on_change_move_back(self): |
|||
if not self.move_back: |
|||
return |
|||
self.parent_id = self.message_id.moved_from_parent_id |
|||
model = self.message_id.moved_from_model |
|||
if self.message_id.is_moved: |
|||
self.model = model |
|||
self.res_id = self.message_id.moved_from_res_id |
|||
|
|||
@api.onchange('parent_id', 'res_id', 'model') |
|||
def update_move_back(self): |
|||
model = self.message_id.moved_from_model |
|||
self.move_back = self.parent_id == self.message_id.moved_from_parent_id \ |
|||
and self.res_id == self.message_id.moved_from_res_id \ |
|||
and (self.model == model or (not self.model and not model)) |
|||
|
|||
@api.onchange('parent_id') |
|||
def on_change_parent_id(self): |
|||
if self.parent_id and self.parent_id.model: |
|||
self.model = self.parent_id.model |
|||
self.res_id = self.parent_id.res_id |
|||
else: |
|||
self.model = None |
|||
self.res_id = None |
|||
|
|||
@api.onchange('model', 'filter_by_partner', 'partner_id') |
|||
def on_change_partner(self): |
|||
domain = {'res_id': [('id', '!=', self.message_id.res_id)]} |
|||
if self.model and self.filter_by_partner and self.partner_id: |
|||
fields = self.env[self.model].fields_get(False) |
|||
contact_field = False |
|||
for n, f in fields.iteritems(): |
|||
if f['type'] == 'many2one' and f['relation'] == 'res.partner': |
|||
contact_field = n |
|||
break |
|||
if contact_field: |
|||
domain['res_id'].append((contact_field, '=', self.partner_id.id)) |
|||
if self.model: |
|||
res_id = self.env[self.model].search(domain['res_id'], order='id desc', limit=1) |
|||
self.res_id = res_id and res_id[0].id |
|||
else: |
|||
self.res_id = None |
|||
return {'domain': domain} |
|||
|
|||
@api.one |
|||
def check_access(self): |
|||
cr = self._cr |
|||
uid = self.env.user.id |
|||
operation = 'write' |
|||
context = self._context |
|||
|
|||
if not (self.model and self.res_id): |
|||
return True |
|||
model_obj = self.pool[self.model] |
|||
mids = model_obj.exists(cr, uid, [self.res_id]) |
|||
if hasattr(model_obj, 'check_mail_message_access'): |
|||
model_obj.check_mail_message_access(cr, uid, mids, operation, context=context) |
|||
else: |
|||
self.pool['mail.thread'].check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context) |
|||
|
|||
@api.multi |
|||
def open_moved_by_message_id(self): |
|||
message_id = None |
|||
for r in self: |
|||
message_id = r.message_moved_by_message_id.id |
|||
return { |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': 'mail_move_message.wizard', |
|||
'view_mode': 'form', |
|||
'view_type': 'form', |
|||
'views': [[False, 'form']], |
|||
'target': 'new', |
|||
'context': {'default_message_id': message_id}, |
|||
} |
|||
|
|||
@api.multi |
|||
def move(self): |
|||
for r in self: |
|||
r.check_access() |
|||
if not r.parent_id or not (r.parent_id.model == r.model and |
|||
r.parent_id.res_id == r.res_id): |
|||
# link with the first message of record |
|||
parent = self.env['mail.message'].search([('model', '=', r.model), ('res_id', '=', r.res_id)], order='id', limit=1) |
|||
r.parent_id = parent.id or None |
|||
|
|||
r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back, r.move_followers) |
|||
|
|||
if not (r.model and r.res_id): |
|||
r.message_id.needaction = False |
|||
return { |
|||
'type': 'ir.actions.client', |
|||
'name': 'All messages', |
|||
'tag': 'reload', |
|||
} |
|||
return { |
|||
'name': _('Record'), |
|||
'view_type': 'form', |
|||
'view_mode': 'form', |
|||
'res_model': r.model, |
|||
'res_id': r.res_id, |
|||
'views': [(False, 'form')], |
|||
'type': 'ir.actions.act_window', |
|||
} |
|||
|
|||
@api.one |
|||
def delete(self): |
|||
msg_id = self.message_id.id |
|||
|
|||
# Send notification |
|||
notification = {'id': msg_id} |
|||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail_move_message.delete_message'), notification) |
|||
|
|||
self.message_id.unlink() |
|||
return {} |
|||
|
|||
@api.model |
|||
def create_partner(self, message_id, relation, partner_id, message_name_from, message_email_from): |
|||
model = self.env[relation] |
|||
message = self.env['mail.message'].browse(message_id) |
|||
if not partner_id and message_name_from: |
|||
partner_id = self.env['res.partner'].with_context({'update_message_author': True}).create({ |
|||
'name': message_name_from, |
|||
'email': message_email_from |
|||
}).id |
|||
|
|||
context = {'partner_id': partner_id} |
|||
if model._rec_name: |
|||
context.update({'default_%s' % model._rec_name: message.subject}) |
|||
|
|||
fields = model.fields_get() |
|||
contact_field = False |
|||
for n, f in fields.iteritems(): |
|||
if f['type'] == 'many2one' and f['relation'] == 'res.partner': |
|||
contact_field = n |
|||
break |
|||
if contact_field: |
|||
context.update({'default_%s' % contact_field: partner_id}) |
|||
return context |
|||
|
|||
@api.one |
|||
def read_close(self): |
|||
self.message_id.set_message_done() |
|||
self.message_id.child_ids.set_message_done() |
|||
return {'type': 'ir.actions.act_window_close'} |
|||
|
|||
|
|||
class MailMessage(models.Model): |
|||
_inherit = 'mail.message' |
|||
|
|||
is_moved = fields.Boolean('Is moved') |
|||
moved_from_res_id = fields.Integer('Related Document ID (Original)') |
|||
moved_from_model = fields.Char('Related Document Model (Original)') |
|||
moved_from_parent_id = fields.Many2one('mail.message', 'Parent Message (Original)', ondelete='set null') |
|||
moved_by_message_id = fields.Many2one('mail.message', 'Moved by message', ondelete='set null', help='Top message, that initate moving this message') |
|||
moved_by_user_id = fields.Many2one('res.users', 'Moved by user', ondelete='set null') |
|||
all_child_ids = fields.One2many('mail.message', string='All childs', compute='_get_all_childs', help='all childs, including subchilds') |
|||
|
|||
@api.one |
|||
def _get_all_childs(self, include_myself=True): |
|||
ids = [] |
|||
if include_myself: |
|||
ids.append(self.id) |
|||
while True: |
|||
new_ids = self.search([('parent_id', 'in', ids), ('id', 'not in', ids)]).ids |
|||
if new_ids: |
|||
ids = ids + new_ids |
|||
continue |
|||
break |
|||
moved_childs = self.search([('moved_by_message_id', '=', self.id)]).ids |
|||
self.all_child_ids = ids + moved_childs |
|||
|
|||
@api.multi |
|||
def move_followers(self, model, ids): |
|||
fol_obj = self.env['mail.followers'] |
|||
for message in self: |
|||
followers = fol_obj.sudo().search([('res_model', '=', message.model), |
|||
('res_id', '=', message.res_id)]) |
|||
for f in followers: |
|||
self.env[model].browse(ids).message_subscribe([f.partner_id.id], [s.id for s in f.subtype_ids]) |
|||
|
|||
@api.one |
|||
def move(self, parent_id, res_id, model, move_back, move_followers=False): |
|||
if parent_id == res_id: |
|||
return |
|||
vals = {} |
|||
if move_back: |
|||
# clear variables if we move everything back |
|||
vals['is_moved'] = False |
|||
vals['moved_by_user_id'] = None |
|||
vals['moved_by_message_id'] = None |
|||
|
|||
vals['moved_from_res_id'] = None |
|||
vals['moved_from_model'] = None |
|||
vals['moved_from_parent_id'] = None |
|||
else: |
|||
vals['parent_id'] = parent_id |
|||
vals['res_id'] = res_id |
|||
vals['model'] = model |
|||
|
|||
vals['is_moved'] = True |
|||
vals['moved_by_user_id'] = self.env.user.id |
|||
vals['moved_by_message_id'] = self.id |
|||
|
|||
# Update record_name in message |
|||
vals['record_name'] = self._get_record_name(vals) |
|||
|
|||
for r in self.all_child_ids: |
|||
r_vals = vals.copy() |
|||
if not r.is_moved: |
|||
# moved_from_* variables contain not last, but original |
|||
# reference |
|||
r_vals['moved_from_parent_id'] = r.parent_id.id |
|||
r_vals['moved_from_res_id'] = r.res_id |
|||
r_vals['moved_from_model'] = r.model |
|||
elif move_back: |
|||
r_vals['parent_id'] = r.moved_from_parent_id.id |
|||
r_vals['res_id'] = r.moved_from_res_id |
|||
r_vals['model'] = r.moved_from_model |
|||
# print 'update message', r, r_vals |
|||
if move_followers: |
|||
r.sudo().move_followers(r_vals.get('model'), r_vals.get('res_id')) |
|||
r.sudo().write(r_vals) |
|||
r.attachment_ids.sudo().write({ |
|||
'res_id': r_vals.get('res_id'), |
|||
'res_model': r_vals.get('model') |
|||
}) |
|||
|
|||
# Send notification |
|||
notification = { |
|||
'id': self.id, |
|||
'res_id': vals.get('res_id'), |
|||
'model': vals.get('model'), |
|||
'is_moved': vals['is_moved'], |
|||
'record_name': vals['record_name'] |
|||
} |
|||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail_move_message'), notification) |
|||
|
|||
def name_get(self, cr, uid, ids, context=None): |
|||
if not (context or {}).get('extended_name'): |
|||
return super(MailMessage, self).name_get(cr, uid, ids, context=context) |
|||
if isinstance(ids, (list, tuple)) and not len(ids): |
|||
return [] |
|||
if isinstance(ids, (long, int)): |
|||
ids = [ids] |
|||
reads = self.read(cr, uid, ids, ['record_name', 'model', 'res_id'], context=context) |
|||
res = [] |
|||
for record in reads: |
|||
name = record['record_name'] or '' |
|||
extended_name = ' [%s] ID %s' % (record.get('model', 'UNDEF'), record.get('res_id', 'UNDEF')) |
|||
res.append((record['id'], name + extended_name)) |
|||
return res |
|||
|
|||
def _message_read_dict(self, cr, uid, message, parent_id=False, context=None): |
|||
res = super(MailMessage, self)._message_read_dict(cr, uid, message, parent_id, context) |
|||
res['is_moved'] = message.is_moved |
|||
return res |
|||
|
|||
@api.multi |
|||
def message_format(self): |
|||
message_values = super(MailMessage, self).message_format() |
|||
message_index = {message['id']: message for message in message_values} |
|||
for item in self: |
|||
msg = message_index.get(item.id) |
|||
if msg: |
|||
msg['is_moved'] = item.is_moved |
|||
return message_values |
|||
|
|||
|
|||
class MailMoveMessageConfiguration(models.TransientModel): |
|||
_name = 'mail_move_message.config.settings' |
|||
_inherit = 'res.config.settings' |
|||
|
|||
model_ids = fields.Many2many(comodel_name='ir.model', string='Models') |
|||
move_followers = fields.Boolean('Move Followers') |
|||
|
|||
@api.model |
|||
def get_default_move_message_configs(self, fields): |
|||
config_parameters = self.env['ir.config_parameter'] |
|||
model_obj = self.env['ir.model'] |
|||
model_names = config_parameters.get_param('mail_relocation_models') |
|||
if not model_names: |
|||
return {} |
|||
model_names = model_names.split(',') |
|||
model_ids = model_obj.search([('model', 'in', model_names)]) |
|||
return { |
|||
'model_ids': [m.id for m in model_ids], |
|||
'move_followers': config_parameters.get_param('mail_relocation_move_followers') |
|||
} |
|||
|
|||
@api.multi |
|||
def set_move_message_configs(self): |
|||
config_parameters = self.env['ir.config_parameter'] |
|||
model_names = '' |
|||
for record in self: |
|||
model_names = ','.join([m.model for m in record.model_ids]) |
|||
config_parameters.set_param('mail_relocation_models', model_names) |
|||
config_parameters.set_param('mail_relocation_move_followers', record.move_followers or '') |
|||
|
|||
|
|||
class ResPartner(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
res = super(ResPartner, self).create(vals) |
|||
if 'update_message_author' in self.env.context and 'email' in vals: |
|||
mail_message_obj = self.env['mail.message'] |
|||
# Escape special SQL characters in email_address to avoid invalid matches |
|||
email_address = (vals['email'].replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_')) |
|||
email_brackets = "<%s>" % email_address |
|||
messages = mail_message_obj.search([ |
|||
'|', |
|||
('email_from', '=ilike', email_address), |
|||
('email_from', 'ilike', email_brackets), |
|||
('author_id', '=', False) |
|||
]) |
|||
if messages: |
|||
messages.sudo().write({'author_id': res.id}) |
|||
return res |
@ -0,0 +1,122 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp><data> |
|||
|
|||
<template id="assets_backend" name="custom bar assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<link rel="stylesheet" href="/mail_move_message/static/src/css/mail_move_message.css"/> |
|||
<script type="text/javascript" src="/mail_move_message/static/src/js/mail_move_message.js"></script> |
|||
</xpath> |
|||
</template> |
|||
|
|||
<record id="view_wizard" model="ir.ui.view"> |
|||
<field name="name">mail_move_message.wizard.view</field> |
|||
<field name="model">mail_move_message.wizard</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Move Message"> |
|||
|
|||
<field name="can_move" invisible="1"/> |
|||
<field name="message_is_moved" invisible="1"/> |
|||
<field name="message_name_from" invisible="1"/> |
|||
<field name="message_email_from" invisible="1"/> |
|||
<field name="message_to_read" invisible="1"/> |
|||
<field name="uid" invisible="1"/> |
|||
|
|||
<p attrs="{'invisible':[('can_move', '!=', False)]}">You cannot move this message. It was already moved with a message bellow. Open one and apply changes there.</p> |
|||
<group attrs="{'invisible':[('can_move', '!=', False)]}"> |
|||
<field name="message_moved_by_message_id" context="{'extended_name':1}"/> |
|||
<field name="message_moved_by_user_id"/> |
|||
<button name="open_moved_by_message_id" string="Open message" type="object" class="oe_highlight"/> |
|||
</group> |
|||
|
|||
<group attrs="{'invisible':[('can_move', '=', False)]}" colspan="2"> |
|||
<label for="model"/> |
|||
<div> |
|||
<field name="model" widget="polymorphic" polymorphic="res_id" class="oe_inline"/> |
|||
</div> |
|||
<label for="filter_by_partner"/> |
|||
<div> |
|||
<field name="filter_by_partner"/> |
|||
<field name="partner_id" style="width:50%"/> |
|||
<button string="Create Partner" attrs="{'invisible':[('partner_id','!=',False)]}" class="oe_highlight" special="quick_create" field="partner_id" context="{'force_email':True,'default_email':message_email_from,'default_name':message_name_from, 'update_message_author':True}"/> |
|||
</div> |
|||
<label for="res_id"/> |
|||
<div> |
|||
<field name="res_id" context="{'extended_name_with_contact':1}" widget="many2one" attrs="{'readonly': [('model','=',False)]}" style="width:50%"/> |
|||
<button string="Create new record" name="create_record" type="object" class="oe_highlight" attrs="{'invisible':['|',('model','=',False)]}" special="quick_create" field="res_id" use_for_mail_move_message="True"/> |
|||
</div> |
|||
<label for="move_back" attrs="{'invisible':[('message_is_moved','=',False)]}"/> |
|||
<div attrs="{'invisible':[('message_is_moved','=',False)]}"> |
|||
<field name="move_back"/> |
|||
</div> |
|||
<label for="move_followers"/> |
|||
<div> |
|||
<field name="move_followers"/> |
|||
</div> |
|||
</group> |
|||
<button name="move" string="Move" type="object" class="oe_highlight" attrs="{'invisible':[('can_move', '=', False)]}"/> |
|||
<button string="Close" class="" special="cancel" /> |
|||
<separator string="Message"/> |
|||
<group> |
|||
<field name="message_subject"/> |
|||
<field name="message_from"/> |
|||
<field name="message_id" invisible="1"/> |
|||
</group> |
|||
<div class="openerp mail_move_message"> |
|||
<div class="oe_mail"> |
|||
<div class="oe_msg"> |
|||
<div class="oe_msg_content"> |
|||
<div class="oe_msg_body"> |
|||
<!-- use built-in css for messages --> |
|||
<field name="message_body"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<footer> |
|||
<button name="read_close" string="Mark as read and Close" type="object" class="oe_highlight"/> or |
|||
<button special="cancel" string="Close" class="oe_link"/> |
|||
|
|||
|
|||
<button name="delete" string="Delete message" type="object" class="oe_highlight oe_right" confirm="Do you really want to delete this message?" attrs="{'invisible':[('uid','!=',1)]}"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<!-- Relocation config wizard --> |
|||
<record id="view_mail_move_message_config_settings" model="ir.ui.view"> |
|||
<field name="name">relocation settings</field> |
|||
<field name="model">mail_move_message.config.settings</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Configure Mail Relocation" class="oe_form_configuration"> |
|||
<header> |
|||
<button string="Apply" type="object" name="execute" class="oe_highlight"/> |
|||
or |
|||
<button string="Cancel" type="object" name="cancel" class="oe_link"/> |
|||
</header> |
|||
<div name="general"> |
|||
<separator string="Models"/> |
|||
<field name="model_ids" widget="many2many_tags"/> |
|||
<separator string="Options"/> |
|||
<label for="move_followers"/> |
|||
<field name="move_followers"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_mail_move_message_config" model="ir.actions.act_window"> |
|||
<field name="name">Mail Relocation</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">mail_move_message.config.settings</field> |
|||
<field name="view_id" ref="view_mail_move_message_config_settings"/> |
|||
<field name="view_mode">form</field> |
|||
<field name="target">inline</field> |
|||
</record> |
|||
|
|||
<!-- Add menu entry in Settings/Email --> |
|||
<menuitem name="Mail Relocation" id="menu_mail_move_message" parent="base.menu_email" sequence="99" action="action_mail_move_message_config"/> |
|||
|
|||
</data> |
|||
</openerp> |
After Width: 1012 | Height: 546 | Size: 39 KiB |
After Width: 1012 | Height: 546 | Size: 40 KiB |
After Width: 1012 | Height: 546 | Size: 39 KiB |
After Width: 890 | Height: 473 | Size: 73 KiB |
After Width: 149 | Height: 149 | Size: 1.5 KiB |
After Width: 1054 | Height: 562 | Size: 57 KiB |