Merge branch 'dev_odex_base' of exp:expsa/odex_30 into dev_odex_base
|
|
@ -0,0 +1,28 @@
|
|||
name: Pull Code
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev_odex_base
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Select Server'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
default: dev
|
||||
|
||||
jobs:
|
||||
|
||||
deploy_dev_server:
|
||||
name: Deploy to Dev Servers
|
||||
runs-on: odex30-runner
|
||||
if: (github.ref == 'refs/heads/dev_odex_base' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'dev'))
|
||||
steps:
|
||||
- name: Checkout And Restart Project
|
||||
run: |
|
||||
sudo chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/pull/pull_code.sh
|
||||
sudo /home/${{ secrets.CLIENT_USER }}/scripts/pull/pull_code.sh
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
name: Upgrade Module
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
database_name:
|
||||
description: 'Database Name'
|
||||
required: true
|
||||
type: string
|
||||
module_name:
|
||||
description: 'Module Name'
|
||||
required: true
|
||||
type: string
|
||||
environment:
|
||||
description: 'Select Server'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
default: dev
|
||||
|
||||
jobs:
|
||||
upgrade_master:
|
||||
name: Upgrade Dev server
|
||||
runs-on: odex30-runner
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'dev'
|
||||
steps:
|
||||
- name: Upgrade Module
|
||||
env:
|
||||
DATABASE_NAME: ${{ github.event.inputs.database_name }}
|
||||
MODULE_NAME: ${{ github.event.inputs.module_name }}
|
||||
run: |
|
||||
chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/upgrade/upgrade-module.sh
|
||||
/home/${{ secrets.CLIENT_USER }}/scripts/upgrade/upgrade-module.sh "$DATABASE_NAME" "$MODULE_NAME"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "QR Code Generator",
|
||||
'summary': """Integrated QR code generator within the odoo framework.""",
|
||||
'description': """Helps to generate QR codes for texts or large urls.""",
|
||||
'version': '18.0.1.0.0',
|
||||
'category': 'Tools',
|
||||
'author': "Kripal K",
|
||||
'website': "https://www.linkedin.com/in/kripal754/",
|
||||
'license': 'LGPL-3',
|
||||
'depends': ['base', 'web'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'qr_generator/static/src/components/qr_generator_systray_item.js',
|
||||
'qr_generator/static/src/components/qr_generator_systray_item.xml',
|
||||
'qr_generator/static/src/scss/qr_generator.scss',
|
||||
],
|
||||
},
|
||||
'images': ['static/description/banner.png'],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
import qrcode
|
||||
import base64
|
||||
import io
|
||||
|
||||
|
||||
class QRGenerator(models.Model):
|
||||
_name = 'qr.generator'
|
||||
|
||||
@api.model
|
||||
def get_qr_code(self, data):
|
||||
if data != "":
|
||||
img = qrcode.make(data)
|
||||
result = io.BytesIO()
|
||||
img.save(result, format='PNG')
|
||||
result.seek(0)
|
||||
img_bytes = result.read()
|
||||
base64_encoded_result_bytes = base64.b64encode(img_bytes)
|
||||
base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii')
|
||||
return base64_encoded_result_str
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_qr_generator,access_qr_generator,model_qr_generator,,1,1,1,1
|
||||
|
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
|
@ -0,0 +1,41 @@
|
|||
<center>
|
||||
<br/>
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan" style="color:#00A09D;">Odoo QR Code Generator</h2>
|
||||
<h3 class="oe_slogan">Integrated QR code generator within the odoo framework.</h3>
|
||||
<br/>
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="screenshot.png">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</center>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan" style="color:#00A09D;">Overview</h2>
|
||||
<h3 class="oe_slogan">Helps to generate QR codes for texts or large urls.</h3>
|
||||
<br/>
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="qr_generator.gif">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</center>
|
||||
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span6 text-justify oe_mt32">
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</center>
|
||||
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
|
@ -0,0 +1,72 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { Dropdown } from "@web/core/dropdown/dropdown";
|
||||
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export class QRGeneratorSystrayItem extends Component {
|
||||
static template = "qr_generator.QRGeneratorSystrayItem";
|
||||
static components = { Dropdown };
|
||||
static props = {};
|
||||
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.state = useState({
|
||||
inputValue: "",
|
||||
qrCodeData: null,
|
||||
showPreview: false,
|
||||
});
|
||||
}
|
||||
|
||||
onInputChange(ev) {
|
||||
this.state.inputValue = ev.target.value;
|
||||
}
|
||||
|
||||
async generateQR() {
|
||||
if (!this.state.inputValue) {
|
||||
this.state.showPreview = false;
|
||||
this.state.qrCodeData = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.orm.call(
|
||||
"qr.generator",
|
||||
"get_qr_code",
|
||||
[this.state.inputValue]
|
||||
);
|
||||
|
||||
if (result) {
|
||||
this.state.qrCodeData = `data:image/png;base64,${result}`;
|
||||
this.state.showPreview = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error generating QR code:", error);
|
||||
this.state.showPreview = false;
|
||||
}
|
||||
}
|
||||
|
||||
clearInput() {
|
||||
this.state.inputValue = "";
|
||||
this.state.qrCodeData = null;
|
||||
this.state.showPreview = false;
|
||||
}
|
||||
|
||||
downloadQR() {
|
||||
if (this.state.qrCodeData) {
|
||||
const link = document.createElement('a');
|
||||
link.href = this.state.qrCodeData;
|
||||
link.download = 'qrcode.png';
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const systrayItem = {
|
||||
Component: QRGeneratorSystrayItem,
|
||||
};
|
||||
|
||||
registry.category("systray").add("qr_generator.QRGeneratorSystrayItem", systrayItem, { sequence: 50 });
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="qr_generator.QRGeneratorSystrayItem">
|
||||
<div class="o_qr_generator_systray">
|
||||
<Dropdown position="'bottom-end'">
|
||||
<button class="btn btn-sm" title="QR Code Generator">
|
||||
<i class="fa fa-qrcode"/>
|
||||
</button>
|
||||
<t t-set-slot="content">
|
||||
<div class="o_qr_generator_dropdown p-3" style="min-width: 300px;">
|
||||
<h6 class="mb-3">QR Code Generator</h6>
|
||||
|
||||
<div class="input-group mb-2">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Enter text or URL"
|
||||
t-model="state.inputValue"
|
||||
t-on-input="onInputChange"/>
|
||||
</div>
|
||||
|
||||
<div class="btn-group w-100 mb-3">
|
||||
<button class="btn btn-primary" t-on-click="generateQR">
|
||||
Generate
|
||||
</button>
|
||||
<button class="btn btn-secondary" t-on-click="clearInput">
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div t-if="state.showPreview" class="text-center">
|
||||
<img t-att-src="state.qrCodeData"
|
||||
class="img-fluid mb-2"
|
||||
style="max-width: 200px;"/>
|
||||
<button class="btn btn-success btn-sm w-100" t-on-click="downloadQR">
|
||||
<i class="fa fa-download me-1"/> Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
select, textarea {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
label {
|
||||
padding: 12px 12px 12px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-radius: 1px;
|
||||
padding: 5px;
|
||||
height:auto;
|
||||
width:350px;
|
||||
background-color:#F9F9F9;
|
||||
margin-top: 3px;
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
margin-bottom: 3px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.col-25 {
|
||||
float: left;
|
||||
width: 25%;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.col-75 {
|
||||
float: left;
|
||||
width: 75%;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
background-color: #00A09D;
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline:none;
|
||||
cursor: pointer;
|
||||
float: center;
|
||||
}
|
||||
|
||||
input[type=button]:hover {
|
||||
background-color: #008784;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!-- No asset loading via XML in Odoo 18 - assets are loaded via __manifest__.py -->
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# Quick Language Selection
|
||||
|
||||
Quick Language Selection is a tool that adds a Quick Language Switcher to the top right-hand User Menu.
|
||||
|
||||
|
||||
# Features
|
||||
|
||||
- Adds Quick Language Switcher to the top right-hand User Menu.
|
||||
- Adds Country flags to the top right-hand User Menu.
|
||||
- Provides 78 country flags.
|
||||
|
||||
|
||||
> After installation of this module:
|
||||
If you want to Setup more flags, just rename the flag picture to local code of the country.
|
||||
You can find the pictures in "\quick_language_selection\static\src\img\flags
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Part of cube48.de. See LICENSE file for full copyright and licensing details.
|
||||
#
|
||||
##############################################################################
|
||||
{
|
||||
'name': "Quick Language Selection",
|
||||
|
||||
'summary': """
|
||||
Change the language from user preference menu with only one click.""",
|
||||
|
||||
'description': """
|
||||
Change the language from user preference menu with only one click.
|
||||
|
||||
1. Adds Quick Language Switcher to the top right-hand User Menu.
|
||||
2. Adds Country flags to the top right-hand User Menu.
|
||||
3. Provides 78 country flags.
|
||||
|
||||
""",
|
||||
|
||||
'author': "cube48 AG",
|
||||
'website': "https://www.cube48.de",
|
||||
'category': "Odex25-base",
|
||||
'version': '18.0.1.0.0',
|
||||
'depends': [
|
||||
'base',
|
||||
],
|
||||
'data': [
|
||||
'views/views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'quick_language_selection/static/src/css/app.css',
|
||||
'quick_language_selection/static/src/js/language_selector.js',
|
||||
'quick_language_selection/static/src/xml/language_selector.xml',
|
||||
],
|
||||
},
|
||||
'images': ["static/description/banner.png"],
|
||||
'license': "AGPL-3",
|
||||
'installable': True,
|
||||
'application': True,
|
||||
}
|
||||
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
|
@ -0,0 +1,23 @@
|
|||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span12">
|
||||
<h1 class="oe_slogan" style="color:#333333;">Quick Language Selection</h1>
|
||||
<div class="" style="text-align: left;">
|
||||
<h3 class="oe_slogan" style="color:black;line-height: 1.3;">If you have to change your language frequently, you will love it!</h3>
|
||||
<h3 class="oe_slogan" style="color:black;line-height: 1.3;">This app creates new entries for all active languages in the top right user menu. Select the required one with just one click. Handy for employees of multilingual companies, external users, developers, partners...</h3>
|
||||
<img style="max-width: 100%;" src="page.gif"/><br><br>
|
||||
<h3 class="oe_slogan" style="color:black;line-height: 1.3;">This module contains 78 nice flags for all Odoo standard languages. Feel free to ask if you miss your language. Not shown in mobile view.</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<img src="cube48.png" style="width: 330px;display: block;margin-left: auto;margin-right: auto;" class="center-block">
|
||||
<div class="oe_slogan" style="margin-top:-20px !important;">
|
||||
<h3><a style="color: #333333 !important;" href="https://www.cube48.de/">www.cube48.de</a> | <a style="color: #333333 !important;" href="mailto:info@cube48.de?Subject=Odoo App Store request"> info@cube48.de</a></h3>
|
||||
</div>
|
||||
<h3 class="oe_slogan" style="color:black;">Please contact us for support requests, app customizations or entire app developments.</h3>
|
||||
</section>
|
||||
|
||||
<!-- <section class="oe_container oe_separator"></section> -->
|
||||
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
|
@ -0,0 +1,7 @@
|
|||
.o_user_menu .dropdown-menu img {
|
||||
height: 20px;
|
||||
margin: 2px;
|
||||
}
|
||||
.o_burger_menu .o_burger_menu_content .o_burger_menu_user .o_user_menu_mobile a img{
|
||||
width: 30px!important;
|
||||
}
|
||||
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |