Skip to content

Commit bdf4ad0

Browse files
MohammedBasionioomsveta
authored andcommitted
[IMP] t9n: list all projects in home page.
This commit adds the project list to the home page of the translations module with some useful info about projects. Task-3783071
1 parent 75e9a38 commit bdf4ad0

File tree

8 files changed

+176
-5
lines changed

8 files changed

+176
-5
lines changed

addons/t9n/models/message.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import api, fields, models
1+
from odoo import fields, models
22

33

44
class Message(models.Model):

addons/t9n/models/project.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import fields, models, api, _
1+
from odoo import _, api, fields, models
22
from odoo.exceptions import ValidationError
33

44

@@ -32,3 +32,23 @@ def _check_source_and_target_languages(self):
3232
for record in self:
3333
if record.src_lang_id in record.target_lang_ids:
3434
raise ValidationError(_("A project's target languages must be different from its source language."))
35+
36+
@api.model
37+
def get_projects(self):
38+
projects_records = self.search([])
39+
return [{
40+
"id": record.id,
41+
"name": record.name,
42+
"src_lang": {
43+
"id": record.src_lang_id.id,
44+
"name": record.src_lang_id.name if record.src_lang_id.name else "",
45+
},
46+
"resources": [{
47+
"id": resource.id,
48+
"file_name": resource.file_name,
49+
} for resource in record.resource_ids],
50+
"target_langs": [{
51+
"id": lang.id,
52+
"name": lang.name,
53+
} for lang in record.target_lang_ids],
54+
} for record in projects_records]

addons/t9n/static/src/core/app.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Component } from "@odoo/owl";
2+
import { ProjectList } from "@t9n/core/project_list";
23

34
/**
45
* The "root", the "homepage" of the translation application.
56
*/
67
export class App extends Component {
7-
static components = {};
8+
static components = { ProjectList };
89
static props = {};
910
static template = "t9n.App";
1011
}

addons/t9n/static/src/core/app.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0"?>
2-
<templates xml:space="preserve">
2+
<templates>
33

44
<t t-name="t9n.App">
5-
Hello World!
5+
<ProjectList/>
66
</t>
77

88
</templates>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Component, useState } from "@odoo/owl";
2+
3+
import { useService } from "@web/core/utils/hooks";
4+
5+
export class ProjectList extends Component {
6+
static props = {};
7+
static template = "t9n.ProjectList";
8+
9+
setup() {
10+
this.action = useService("action");
11+
this.state = useState({
12+
filters: {
13+
searchText: "",
14+
},
15+
sorting: {
16+
column: "name",
17+
order: "asc",
18+
},
19+
});
20+
this.store = useState(useService("t9n.store"));
21+
this.store.fetchProjects();
22+
}
23+
24+
get projects() {
25+
const searchTerms = this.state.filters.searchText.trim().toUpperCase();
26+
const projects = searchTerms
27+
? this.store.projects.filter((p) => p.name.toUpperCase().includes(searchTerms))
28+
: [...this.store.projects];
29+
30+
projects.sort((p1, p2) => {
31+
let p1Col = p1[this.state.sorting.column];
32+
let p2Col = p2[this.state.sorting.column];
33+
34+
if (this.state.sorting.column !== "resource_count") {
35+
p1Col = p1Col.toLowerCase();
36+
p2Col = p2Col.toLowerCase();
37+
}
38+
39+
if (p1Col < p2Col) {
40+
return this.state.sorting.order === "asc" ? -1 : 1;
41+
}
42+
if (p1Col > p2Col) {
43+
return this.state.sorting.order === "asc" ? 1 : -1;
44+
}
45+
return 0;
46+
});
47+
return projects;
48+
}
49+
50+
onClickColumnName(column) {
51+
if (this.state.sorting.column === column) {
52+
this.state.sorting.order = this.state.sorting.order === "asc" ? "desc" : "asc";
53+
} else {
54+
this.state.sorting.column = column;
55+
this.state.sorting.order = "asc";
56+
}
57+
}
58+
59+
onClickProject(id) {
60+
this.action.doAction({
61+
type: "ir.actions.act_window",
62+
res_id: id,
63+
res_model: "t9n.project",
64+
views: [[false, "form"]],
65+
target: "new",
66+
});
67+
}
68+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0"?>
2+
<templates>
3+
<t t-name="t9n.ProjectList">
4+
<div class="container mt-3">
5+
<div class="input-group">
6+
<div class="form-outline">
7+
<input type="text" class="form-control" placeholder="Search projects" t-model="state.filters.searchText"/>
8+
</div>
9+
</div>
10+
<table class="table table-hover">
11+
<thead>
12+
<tr>
13+
<th t-on-click="() => this.onClickColumnName('name')">Project Name <i t-attf-class="btn btn-link fa fa-sort-{{this.state.sorting.column === 'name' and this.state.sorting.order === 'asc' ? 'up' : 'down'}}"></i>
14+
</th>
15+
<th>Source Language</th>
16+
<th>Target Languages</th>
17+
<th>Resource Count</th>
18+
</tr>
19+
</thead>
20+
<tbody>
21+
<t t-foreach="this.projects" t-as="project" t-key="project.id">
22+
<tr>
23+
<td>
24+
<button class="btn btn-link " t-on-click="() => this.onClickProject(project.id)">
25+
<t t-esc="project.name"/>
26+
</button>
27+
</td>
28+
<td t-esc="project.srcLang"/>
29+
<td t-esc="project.formattedTargetLanguages"/>
30+
<td t-esc="project.resourceCount"/>
31+
</tr>
32+
</t>
33+
</tbody>
34+
</table>
35+
</div>
36+
</t>
37+
</templates>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { formatList } from "@web/core/l10n/utils";
2+
3+
export class Project {
4+
constructor(id, name, srcLang, targetLangs, resourceCount) {
5+
this.id = id;
6+
this.name = name;
7+
this.srcLang = srcLang;
8+
this.targetLangs = targetLangs;
9+
this.resourceCount = resourceCount;
10+
}
11+
12+
get formattedTargetLanguages() {
13+
return formatList(this.targetLangs.map(({ name }) => name));
14+
}
15+
}

addons/t9n/static/src/core/store.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { reactive } from "@odoo/owl";
2+
3+
import { Project } from "@t9n/core/project_model";
4+
5+
import { registry } from "@web/core/registry";
6+
7+
export class Store {
8+
constructor(env, { orm }) {
9+
this.env = env;
10+
this.orm = orm;
11+
this.projects = [];
12+
return reactive(this);
13+
}
14+
15+
async fetchProjects() {
16+
const projects = await this.orm.call("t9n.project", "get_projects");
17+
this.projects = projects.map((p) => {
18+
return new Project(p.id, p.name, p.src_lang.name, p.target_langs, p.resources.length);
19+
});
20+
}
21+
}
22+
23+
export const storeService = {
24+
dependencies: ["orm"],
25+
start(env, deps) {
26+
return new Store(env, deps);
27+
},
28+
};
29+
30+
registry.category("services").add("t9n.store", storeService);

0 commit comments

Comments
 (0)