Skip to content

Commit f9d62d7

Browse files
committed
Merge PR #53 into 16.0
Signed-off-by pedrobaeza
2 parents a835a1d + 13cd33e commit f9d62d7

File tree

6 files changed

+173
-8
lines changed

6 files changed

+173
-8
lines changed

spreadsheet_oca/__manifest__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"demo": ["demo/spreadsheet_spreadsheet.xml"],
2222
"assets": {
2323
"web.assets_backend": [
24+
"spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js",
25+
"spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.xml",
2426
"spreadsheet_oca/static/src/spreadsheet/spreadsheet.scss",
2527
"spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js",
2628
"spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js",

spreadsheet_oca/models/spreadsheet_spreadsheet.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import base64
55
import json
6+
import zipfile
7+
from io import BytesIO
68

79
from odoo import _, api, fields, models
810

@@ -55,3 +57,37 @@ def _inverse_spreadsheet_raw(self):
5557
record.data = base64.encodebytes(
5658
json.dumps(record.spreadsheet_raw).encode("UTF-8")
5759
)
60+
61+
def create_document_from_attachment(self, attachment_ids):
62+
attachments = self.env["ir.attachment"].browse(attachment_ids)
63+
spreadsheets = self.env["spreadsheet.spreadsheet"]
64+
for attachment in attachments:
65+
extracted = {}
66+
with zipfile.ZipFile(
67+
BytesIO(base64.b64decode(attachment.datas)), "r"
68+
) as xlsx:
69+
# List and filter for XML and REL files
70+
xml_files = [
71+
f
72+
for f in xlsx.namelist()
73+
if f.endswith(".xml") or f.endswith(".rels")
74+
]
75+
# Extract each file
76+
for xml_file in xml_files:
77+
# Read the XML file into memory
78+
with xlsx.open(xml_file) as file:
79+
extracted[xml_file] = file.read().decode("UTF8")
80+
spreadsheets |= self.create(
81+
{
82+
"spreadsheet_raw": extracted,
83+
"name": attachment.name,
84+
}
85+
)
86+
attachments.unlink()
87+
if len(spreadsheets) == 1:
88+
return spreadsheets.get_formview_action()
89+
action = self.env["ir.actions.act_window"]._for_xml_id(
90+
"spreadsheet_oca.spreadsheet_spreadsheet_act_window"
91+
)
92+
action["domain"] = [("id", "in", spreadsheets.ids)]
93+
return action

spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/** @odoo-module **/
22

3+
import {makeDynamicCols, makeDynamicRows} from "../utils/dynamic_generators.esm";
34
import ListDataSource from "@spreadsheet/list/list_data_source";
45
import PivotDataSource from "@spreadsheet/pivot/pivot_data_source";
56
import {SpreadsheetControlPanel} from "./spreadsheet_controlpanel.esm";
67
import {SpreadsheetRenderer} from "./spreadsheet_renderer.esm";
78
import {registry} from "@web/core/registry";
89
import spreadsheet from "@spreadsheet/o_spreadsheet/o_spreadsheet_extended";
910
import {useService} from "@web/core/utils/hooks";
10-
import {makeDynamicCols, makeDynamicRows} from "../utils/dynamic_generators.esm";
1111

1212
const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
1313
const actionRegistry = registry.category("actions");
@@ -28,13 +28,16 @@ export class ActionSpreadsheetOca extends Component {
2828
});
2929
});
3030
onWillStart(async () => {
31+
// We need to load in case the data comes from an XLSX
3132
this.record =
32-
(await this.orm.call(
33-
this.model,
34-
"get_spreadsheet_data",
35-
[[this.spreadsheetId]],
36-
{context: {bin_size: false}}
37-
)) || {};
33+
spreadsheet.load(
34+
await this.orm.call(
35+
this.model,
36+
"get_spreadsheet_data",
37+
[[this.spreadsheetId]],
38+
{context: {bin_size: false}}
39+
)
40+
) || {};
3841
});
3942
useSubEnv({
4043
saveRecord: this.saveRecord.bind(this),
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/** @odoo-module **/
2+
import {Component} from "@odoo/owl";
3+
import {FileUploader} from "@web/views/fields/file_handler";
4+
import {ListController} from "@web/views/list/list_controller";
5+
import {listView} from "@web/views/list/list_view";
6+
7+
import {registry} from "@web/core/registry";
8+
import {standardWidgetProps} from "@web/views/widgets/standard_widget_props";
9+
import {useService} from "@web/core/utils/hooks";
10+
11+
class SpreadsheetFileUploader extends Component {
12+
setup() {
13+
this.orm = useService("orm");
14+
this.attachmentIdsToProcess = [];
15+
this.action = useService("action");
16+
}
17+
async onFileUploaded(file) {
18+
const att_data = {
19+
name: file.name,
20+
mimetype: file.type,
21+
datas: file.data,
22+
};
23+
const att_id = await this.orm.create("ir.attachment", [att_data], {
24+
context: this.env.searchModel.context,
25+
});
26+
this.attachmentIdsToProcess.push(att_id);
27+
}
28+
async onUploadComplete() {
29+
let action = {};
30+
try {
31+
action = await this.orm.call(
32+
"spreadsheet.spreadsheet",
33+
"create_document_from_attachment",
34+
["", this.attachmentIdsToProcess],
35+
{context: this.env.searchModel.context}
36+
);
37+
} finally {
38+
// Ensures attachments are cleared on success as well as on error
39+
this.attachmentIdsToProcess = [];
40+
}
41+
if (action.context && action.context.notifications) {
42+
for (const [file, msg] of Object.entries(action.context.notifications)) {
43+
this.notification.add(msg, {
44+
title: file,
45+
type: "info",
46+
sticky: true,
47+
});
48+
}
49+
delete action.context.notifications;
50+
}
51+
this.action.doAction(action);
52+
}
53+
}
54+
SpreadsheetFileUploader.components = {
55+
FileUploader,
56+
};
57+
SpreadsheetFileUploader.template = "spreadsheet_oca.SpreadsheetFileUploader";
58+
SpreadsheetFileUploader.props = {
59+
...standardWidgetProps,
60+
acceptedFileExtensions: {type: String, optional: true},
61+
record: {type: Object, optional: true},
62+
togglerTemplate: {type: String, optional: true},
63+
slots: {type: Object, optional: true},
64+
};
65+
SpreadsheetFileUploader.defaultProps = {
66+
acceptedFileExtensions:
67+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
68+
};
69+
export class SpreadsheetListController extends ListController {}
70+
SpreadsheetListController.components = {
71+
...ListController.components,
72+
SpreadsheetFileUploader,
73+
};
74+
export const SpreadsheetListView = {
75+
...listView,
76+
Controller: SpreadsheetListController,
77+
buttonTemplate: "spreadsheet_oca.ListView.Buttons",
78+
};
79+
80+
registry.category("views").add("spreadsheet_tree", SpreadsheetListView);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
<t t-name="spreadsheet_oca.SpreadsheetFileUploader" owl="1">
4+
<div
5+
t-att-class="props.record and props.record.data ? 'oe_kanban_color_' + props.record.data.color : ''"
6+
>
7+
<FileUploader
8+
acceptedFileExtensions="props.acceptedFileExtensions"
9+
fileUploadClass="'spreadsheet_file_uploader'"
10+
multiUpload="true"
11+
onUploaded.bind="onFileUploaded"
12+
onUploadComplete.bind="onUploadComplete"
13+
>
14+
<t t-set-slot="toggler">
15+
<t
16+
t-if="props.togglerTemplate"
17+
t-call="{{ props.togglerTemplate }}"
18+
/>
19+
<t t-else="" t-slot="default" />
20+
</t>
21+
<t t-slot="extra" />
22+
</FileUploader>
23+
</div>
24+
</t>
25+
<t
26+
t-name="spreadsheet_oca.ListView.Buttons"
27+
t-inherit="web.ListView.Buttons"
28+
t-inherit-mode="primary"
29+
owl="1"
30+
>
31+
<xpath expr="//*[@class='btn btn-primary o_list_button_add']" position="after">
32+
<SpreadsheetFileUploader>
33+
<t t-set-slot="default">
34+
<button
35+
type="button"
36+
class="btn btn-secondary o_button_upload_bill"
37+
>
38+
Upload XLSX
39+
</button>
40+
</t>
41+
</SpreadsheetFileUploader>
42+
</xpath>
43+
</t>
44+
</templates>

spreadsheet_oca/views/spreadsheet_spreadsheet.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<field name="name">spreadsheet.spreadsheet.tree (in spreadsheet_oca)</field>
1818
<field name="model">spreadsheet.spreadsheet</field>
1919
<field name="arch" type="xml">
20-
<tree>
20+
<tree js_class="spreadsheet_tree">
2121
<field name="name" />
2222
<button
2323
name="open_spreadsheet"

0 commit comments

Comments
 (0)