@@ -1502,7 +1482,7 @@
- Your OCA member profile link. Where we recognise it, a button leads to it from your card — labelled as your declaration, not as something we verified.
+ Your OCA member profile link. Where we recognise it, an OCA Member Profile badge on your card links to it — taken from your link, not checked by us.
@@ -2043,6 +2023,7 @@
var LIVE_FILTERS = [
["Country", "Country", "country", "value"],
["__langs__", "Language", "languages", "langnum"],
+ ["__oca__", "OCA member", "oca", "oca"],
["odoo4projects_clients", "Clients on ODOO4projects", "clients", "min"]
];
var LIVE_ALIASES = { Country: ["country"] };
@@ -2109,6 +2090,30 @@
return v.indexOf(OCA_MEMBER_PREFIX) === 0 ? v : "";
}
+ /* One chart block — the SHARED component for the skill profile and the languages
+ (same squares, two labels; the data sources stay separate). No digit is printed:
+ five squares per row, and the row's value lives in the squares' accessible name
+ (role="img" + aria-label), so assistive tech still reads the number. */
+ function liveChart(label, rows) {
+ var wrap = liveEl("div", "dev-profile");
+ wrap.appendChild(liveEl("p", "dev-profile-label", label));
+ var ul = liveEl("ul", "dev-axes");
+ rows.forEach(function (row) {
+ var li = liveEl("li", "dev-axis");
+ li.appendChild(liveEl("span", "dev-axis-name", row[0]));
+ var sq = liveEl("span", "dev-axis-squares");
+ sq.setAttribute("role", "img");
+ sq.setAttribute("aria-label", row[1] + " of " + FOCUS_MAX);
+ for (var i = 0; i < FOCUS_MAX; i++) {
+ sq.appendChild(liveEl("span", "dev-sq" + (i < row[1] ? " on" : "")));
+ }
+ li.appendChild(sq);
+ ul.appendChild(li);
+ });
+ wrap.appendChild(ul);
+ return wrap;
+ }
+
function liveSearchText(rec) {
return fold([
String(rec.Name || ""),
@@ -2124,6 +2129,7 @@
var n = parseInt(rec[field], 10);
return isNaN(n) ? "" : String(n);
}
+ if (kind === "oca") return liveOcaLink(rec) ? "1" : "";
if (kind === "langnum") return liveLangsDeclared(rec).map(fold).join("|");
return liveValues(rec, field).map(fold).join("|");
}
@@ -2163,11 +2169,20 @@
var head = liveEl("header", "dev-head");
var who = liveEl("div", "dev-id");
who.appendChild(liveEl("h3", "dev-name", name));
+ // The OCA Member Profile badge lives with the name. Same predicate as the filter.
+ var member = liveOcaLink(rec);
+ if (member) {
+ var badge = liveEl("a", "dev-oca-badge", "OCA Member Profile");
+ badge.href = member;
+ badge.target = "_blank";
+ badge.rel = "noopener nofollow";
+ who.appendChild(badge);
+ }
head.appendChild(avatar);
head.appendChild(who);
card.appendChild(head);
- // The count we recorded ourselves — rendered ONCE, with weight, never a score.
+ // Our own count — rendered ONCE, with weight, never a score.
var clients = parseInt(rec.odoo4projects_clients, 10);
if (!isNaN(clients)) {
var p = liveEl("p", "dev-clients");
@@ -2175,8 +2190,6 @@
p.appendChild(document.createTextNode(" "));
p.appendChild(liveEl("span", "dev-clients-w",
(clients === 1 ? "client" : "clients") + " on ODOO4projects"));
- p.appendChild(document.createTextNode(" "));
- p.appendChild(liveEl("span", "dev-clients-note", "\u2014 a number we recorded"));
card.appendChild(p);
}
@@ -2188,53 +2201,22 @@
var rows = liveAxisRows(rec);
if (rows.length) {
- var wrap = liveEl("div", "dev-profile");
- wrap.appendChild(liveEl("p", "dev-profile-label", "Focus profile, as declared"));
- var ul = liveEl("ul", "dev-axes");
- rows.forEach(function (row) {
- var li = liveEl("li", "dev-axis");
- li.appendChild(liveEl("span", "dev-axis-name",
- FOCUS_AXIS_LABELS[row[0]] || row[0]));
- var sq = liveEl("span", "dev-axis-squares");
- sq.setAttribute("aria-hidden", "true");
- for (var i = 0; i < FOCUS_MAX; i++) {
- sq.appendChild(liveEl("span", "dev-sq" + (i < row[1] ? " on" : "")));
- }
- li.appendChild(sq);
- li.appendChild(liveEl("span", "dev-axis-val", String(row[1])));
- ul.appendChild(li);
- });
- wrap.appendChild(ul);
- wrap.appendChild(liveEl("p", "dev-profile-note",
- "15 points over five areas \u2014 nobody can be maximum in everything."));
- card.appendChild(wrap);
+ card.appendChild(liveChart("Skill profile", rows.map(function (row) {
+ return [FOCUS_AXIS_LABELS[row[0]] || row[0], row[1]];
+ })));
}
var scores = liveLangScores(rec);
var declared = LANG_FIELDS.filter(function (p) { return scores[p[1]] > 0; });
if (declared.length) {
- var lp = liveEl("p", "dev-langs");
- lp.appendChild(liveEl("span", "dev-langs-label", "Languages, as declared:"));
- lp.appendChild(document.createTextNode(" " + declared.map(function (p) {
- return p[1] + " " + scores[p[1]];
- }).join(" \u00b7 ")));
- card.appendChild(lp);
+ card.appendChild(liveChart("Languages", declared.map(function (p) {
+ return [p[1], scores[p[1]]];
+ })));
}
var email = String(rec.email || "").trim();
var hasEmail = email.indexOf("@") !== -1;
var links = [];
- var member = liveOcaLink(rec);
- if (member) {
- var chip = liveEl("a", "dev-oca");
- chip.href = member;
- chip.target = "_blank";
- chip.rel = "noopener nofollow";
- chip.setAttribute("aria-label", "OCA member profile (as declared)");
- chip.appendChild(document.createTextNode("\u25cf OCA profile "));
- chip.appendChild(liveEl("span", "dev-oca-tag", "(as declared)"));
- links.push(chip);
- }
[["Linkedin", "LinkedIn"], ["github", "GitHub"], ["upwork", "Upwork"],
["fiverr", "Fiverr"]].forEach(function (pair) {
var val = String(rec[pair[0]] || "").trim();
@@ -2305,6 +2287,10 @@
if (counts.length >= 2) {
options = counts.slice(1).map(function (c) { return [String(c), c + "+ clients"]; });
}
+ } else if (kind === "oca") {
+ if (records.some(function (r) { return liveOcaLink(r); })) {
+ options = [["1", "OCA member"]];
+ }
} else if (kind === "langnum") {
var seenL = [];
records.forEach(function (r) {