Public Access
feat(freelancer-directory): 5-axis focus profile, 3 numeric languages, OCA from the link; drop odoo_versions
The user's spec (2026-11-03): "remove the ODOO versions. people are lying anyways";
"15 points to distribute between functional system modules integration ai"; "the
languages should be self assessed with 0 can not speak and 5 native. we have the
languages english german and spanish"; "lets limit the focus on the form to 70 chars";
"lets remove the member OCA question … use the OCA link to determine if someone is a
member … show the oca link on top of all links and make it apart with a color, also
dont show the link itself just a button or a chip"; "the only quality signal we can give
and verify is how many projects the freelancer brought to our platform"; "no sorting we
keep the no rank policy"; "get the sort on the page out."
REMOVED (both forms + the filter + the hints):
- `odoo_versions` — the webhook never carried it, so every value was silently dropped
(re-verified: the payload has no `odoo_versions` field).
- `specialities` — replaced by the focus profile.
- the OCA-member question — membership is now DERIVED from `OCA_link`.
ADDED:
- Five focus sliders (functional, system, modules, integration, ai), each 0-5, from ONE
constant (`FOCUS_AXES`), on both forms. Live running total ("12 of 15 points"); the
submit is BLOCKED with an inline warning unless the five total exactly 15. The 15-point
budget of a possible 25 is what stops anyone claiming maximum everywhere, and the form
says so. No-JS: a `<noscript>` block swaps the sliders for five number inputs.
- Three language sliders (English, German, Spanish), each 0-5 (0 = cannot speak,
5 = native), as SEPARATE numeric wire fields — no CSV, no 114-name ISO dataset, no
free text. Preset to 0 (the user's decision, stated): an untouched slider records
"cannot speak" rather than a blank.
- `Focus` capped at 70 characters on both forms with a live counter; the render path
truncates a longer legacy value to 70 with a visible ellipsis.
- The card, in the user's order: photo+name · "N clients on ODOO4projects" (once, with
weight) · Focus · the freelancer's own words · the focus-profile chart (one row per
axis the payload carries, five squares) · the language line ("English 4 · German 5") ·
the links, with the OCA profile chip FIRST and APART (a label, never the raw URL;
"(as declared)") · the anonymous-contact button (JS-only — dark).
- The anonymous-contact modal: sends `{freelancers:[{id,name}], brief, email}` for the
one card, opens only when `ODOO_EXPERTS_QUOTE_WEBHOOK` is set (still empty — ships
dark), and says plainly that the email goes to us, never to the freelancer.
- OCA membership from `OCA_link`, matched on host + PATH PREFIX
(`https://apps.odoo-community.org/community/`), never the bare domain.
ORDER: the client-side `Name` sort is gone from BOTH renderers — the endpoint's order is
rendered as received, so cards reshuffle between loads (the server randomises on purpose).
Nothing is ever ordered by the client count.
Also: the count is rendered ONCE (the payload has one field for it — "clients" and
"projects" are the same number here), `0` renders (a fact) while absent/null renders
nothing, and the legacy `languages`/`specialities` fields are left in the payload but no
longer read.
QC: verify-html.py 0 · check-inline-js OK · test-directory-render.py PASS · competitor QC
exit 3, 74 site-wide pre-existing, 0 in our files · impeccable detect --no-advisory
dir 14 (0 added) / admin 7 (0 added) · 375 px 0 overflow · no form submitted by hand.
This commit is contained in:
1 parent
5ce14ea666
commit
99245764a9
2 files changed
+1125
-670
No files matched your search
@@ -228,10 +228,75 @@
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
/* ---- Focus + language sliders (2026-11-03n) ---- */
|
||||
.focus-field {
|
||||
min-width: 0;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
padding: 0.85rem 0.9rem 0.7rem;
|
||||
}
|
||||
.focus-field legend {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--midnight);
|
||||
padding: 0 0.35rem;
|
||||
}
|
||||
.focus-axis {
|
||||
display: grid;
|
||||
grid-template-columns: 6.5rem 1fr 2.2rem;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
margin: 0.3rem 0;
|
||||
}
|
||||
.focus-axis label {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
color: var(--ink);
|
||||
}
|
||||
.focus-axis input[type="range"] {
|
||||
width: 100%;
|
||||
accent-color: var(--brass-deep);
|
||||
}
|
||||
.focus-axis output {
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: 0.9rem;
|
||||
text-align: right;
|
||||
color: var(--ink);
|
||||
}
|
||||
.focus-total {
|
||||
margin: 0.6rem 0 0;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--midnight);
|
||||
}
|
||||
.focus-scale {
|
||||
margin: 0.45rem 0 0;
|
||||
font-size: 0.76rem;
|
||||
line-height: 1.55;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.focus-warn {
|
||||
margin: 0.55rem 0 0;
|
||||
font-size: 0.85rem;
|
||||
color: #b3452f;
|
||||
min-height: 1.1em;
|
||||
}
|
||||
.focus-counter {
|
||||
font-size: 0.78rem;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.focus-counter[data-over="1"] {
|
||||
color: #b3452f;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.form-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.focus-axis {
|
||||
grid-template-columns: 5.2rem 1fr 1.7rem;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -280,8 +345,9 @@
|
||||
<span class="hint">A number we record ourselves — not the freelancer's, not a rating.</span>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="adFocus">Focus</label>
|
||||
<input id="adFocus" name="Focus" type="text" />
|
||||
<label for="adFocus">Focus <span class="hint">(one line, at most 70 characters)</span></label>
|
||||
<input id="adFocus" name="Focus" type="text" maxlength="70" aria-describedby="adFocusCount" />
|
||||
<span class="focus-counter" id="adFocusCount" aria-live="polite">0 / 70</span>
|
||||
</div>
|
||||
<div class="form-field full">
|
||||
<label for="adDescription">Description</label>
|
||||
@@ -545,145 +611,64 @@
|
||||
</select>
|
||||
<span class="hint">Stored as the ISO code (e.g. DE).</span>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="adVersions">Odoo versions</label>
|
||||
<input id="adVersions" name="odoo_versions" type="text" />
|
||||
<span class="hint">Separate with commas.</span>
|
||||
<fieldset class="form-field full focus-field">
|
||||
<legend>Focus profile — five numbers, 0 to 5, totalling 15</legend>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-axis-functional">Functional</label>
|
||||
<input type="range" id="ad-axis-functional" name="functional" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-axis-functional">0</output>
|
||||
</div>
|
||||
<fieldset class="form-field full lang-field">
|
||||
<legend>Languages</legend>
|
||||
<div class="lang-list" id="adLanguages">
|
||||
<!-- LANGUAGE-OPTIONS-START -->
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-afrikaans" name="languages" value="Afrikaans" /><label for="ad-lang-afrikaans">Afrikaans</label><select class="lang-level" name="language_level" data-language="Afrikaans" aria-label="Level in Afrikaans"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-amharic" name="languages" value="Amharic" /><label for="ad-lang-amharic">Amharic</label><select class="lang-level" name="language_level" data-language="Amharic" aria-label="Level in Amharic"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-arabic" name="languages" value="Arabic" /><label for="ad-lang-arabic">Arabic</label><select class="lang-level" name="language_level" data-language="Arabic" aria-label="Level in Arabic"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-aymara" name="languages" value="Aymara" /><label for="ad-lang-aymara">Aymara</label><select class="lang-level" name="language_level" data-language="Aymara" aria-label="Level in Aymara"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-azerbaijani" name="languages" value="Azerbaijani" /><label for="ad-lang-azerbaijani">Azerbaijani</label><select class="lang-level" name="language_level" data-language="Azerbaijani" aria-label="Level in Azerbaijani"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-belarusian" name="languages" value="Belarusian" /><label for="ad-lang-belarusian">Belarusian</label><select class="lang-level" name="language_level" data-language="Belarusian" aria-label="Level in Belarusian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-bulgarian" name="languages" value="Bulgarian" /><label for="ad-lang-bulgarian">Bulgarian</label><select class="lang-level" name="language_level" data-language="Bulgarian" aria-label="Level in Bulgarian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-bislama" name="languages" value="Bislama" /><label for="ad-lang-bislama">Bislama</label><select class="lang-level" name="language_level" data-language="Bislama" aria-label="Level in Bislama"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-bengali" name="languages" value="Bengali" /><label for="ad-lang-bengali">Bengali</label><select class="lang-level" name="language_level" data-language="Bengali" aria-label="Level in Bengali"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-bosnian" name="languages" value="Bosnian" /><label for="ad-lang-bosnian">Bosnian</label><select class="lang-level" name="language_level" data-language="Bosnian" aria-label="Level in Bosnian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-catalan" name="languages" value="Catalan" /><label for="ad-lang-catalan">Catalan</label><select class="lang-level" name="language_level" data-language="Catalan" aria-label="Level in Catalan"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-chamorro" name="languages" value="Chamorro" /><label for="ad-lang-chamorro">Chamorro</label><select class="lang-level" name="language_level" data-language="Chamorro" aria-label="Level in Chamorro"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-czech" name="languages" value="Czech" /><label for="ad-lang-czech">Czech</label><select class="lang-level" name="language_level" data-language="Czech" aria-label="Level in Czech"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-danish" name="languages" value="Danish" /><label for="ad-lang-danish">Danish</label><select class="lang-level" name="language_level" data-language="Danish" aria-label="Level in Danish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-german" name="languages" value="German" /><label for="ad-lang-german">German</label><select class="lang-level" name="language_level" data-language="German" aria-label="Level in German"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-divehi" name="languages" value="Divehi" /><label for="ad-lang-divehi">Divehi</label><select class="lang-level" name="language_level" data-language="Divehi" aria-label="Level in Divehi"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-dzongkha" name="languages" value="Dzongkha" /><label for="ad-lang-dzongkha">Dzongkha</label><select class="lang-level" name="language_level" data-language="Dzongkha" aria-label="Level in Dzongkha"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-greek" name="languages" value="Greek" /><label for="ad-lang-greek">Greek</label><select class="lang-level" name="language_level" data-language="Greek" aria-label="Level in Greek"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-english" name="languages" value="English" /><label for="ad-lang-english">English</label><select class="lang-level" name="language_level" data-language="English" aria-label="Level in English"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-spanish" name="languages" value="Spanish" /><label for="ad-lang-spanish">Spanish</label><select class="lang-level" name="language_level" data-language="Spanish" aria-label="Level in Spanish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-estonian" name="languages" value="Estonian" /><label for="ad-lang-estonian">Estonian</label><select class="lang-level" name="language_level" data-language="Estonian" aria-label="Level in Estonian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-basque" name="languages" value="Basque" /><label for="ad-lang-basque">Basque</label><select class="lang-level" name="language_level" data-language="Basque" aria-label="Level in Basque"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-persian" name="languages" value="Persian" /><label for="ad-lang-persian">Persian</label><select class="lang-level" name="language_level" data-language="Persian" aria-label="Level in Persian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-peul" name="languages" value="Peul" /><label for="ad-lang-peul">Peul</label><select class="lang-level" name="language_level" data-language="Peul" aria-label="Level in Peul"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-finnish" name="languages" value="Finnish" /><label for="ad-lang-finnish">Finnish</label><select class="lang-level" name="language_level" data-language="Finnish" aria-label="Level in Finnish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-fijian" name="languages" value="Fijian" /><label for="ad-lang-fijian">Fijian</label><select class="lang-level" name="language_level" data-language="Fijian" aria-label="Level in Fijian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-faroese" name="languages" value="Faroese" /><label for="ad-lang-faroese">Faroese</label><select class="lang-level" name="language_level" data-language="Faroese" aria-label="Level in Faroese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-french" name="languages" value="French" /><label for="ad-lang-french">French</label><select class="lang-level" name="language_level" data-language="French" aria-label="Level in French"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-irish" name="languages" value="Irish" /><label for="ad-lang-irish">Irish</label><select class="lang-level" name="language_level" data-language="Irish" aria-label="Level in Irish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-galician" name="languages" value="Galician" /><label for="ad-lang-galician">Galician</label><select class="lang-level" name="language_level" data-language="Galician" aria-label="Level in Galician"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-guarani" name="languages" value="Guarani" /><label for="ad-lang-guarani">Guarani</label><select class="lang-level" name="language_level" data-language="Guarani" aria-label="Level in Guarani"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-manx" name="languages" value="Manx" /><label for="ad-lang-manx">Manx</label><select class="lang-level" name="language_level" data-language="Manx" aria-label="Level in Manx"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-hebrew" name="languages" value="Hebrew" /><label for="ad-lang-hebrew">Hebrew</label><select class="lang-level" name="language_level" data-language="Hebrew" aria-label="Level in Hebrew"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-hindi" name="languages" value="Hindi" /><label for="ad-lang-hindi">Hindi</label><select class="lang-level" name="language_level" data-language="Hindi" aria-label="Level in Hindi"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-croatian" name="languages" value="Croatian" /><label for="ad-lang-croatian">Croatian</label><select class="lang-level" name="language_level" data-language="Croatian" aria-label="Level in Croatian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-haitian" name="languages" value="Haitian" /><label for="ad-lang-haitian">Haitian</label><select class="lang-level" name="language_level" data-language="Haitian" aria-label="Level in Haitian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-hungarian" name="languages" value="Hungarian" /><label for="ad-lang-hungarian">Hungarian</label><select class="lang-level" name="language_level" data-language="Hungarian" aria-label="Level in Hungarian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-armenian" name="languages" value="Armenian" /><label for="ad-lang-armenian">Armenian</label><select class="lang-level" name="language_level" data-language="Armenian" aria-label="Level in Armenian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-indonesian" name="languages" value="Indonesian" /><label for="ad-lang-indonesian">Indonesian</label><select class="lang-level" name="language_level" data-language="Indonesian" aria-label="Level in Indonesian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-icelandic" name="languages" value="Icelandic" /><label for="ad-lang-icelandic">Icelandic</label><select class="lang-level" name="language_level" data-language="Icelandic" aria-label="Level in Icelandic"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-italian" name="languages" value="Italian" /><label for="ad-lang-italian">Italian</label><select class="lang-level" name="language_level" data-language="Italian" aria-label="Level in Italian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-japanese" name="languages" value="Japanese" /><label for="ad-lang-japanese">Japanese</label><select class="lang-level" name="language_level" data-language="Japanese" aria-label="Level in Japanese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-georgian" name="languages" value="Georgian" /><label for="ad-lang-georgian">Georgian</label><select class="lang-level" name="language_level" data-language="Georgian" aria-label="Level in Georgian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-kongo" name="languages" value="Kongo" /><label for="ad-lang-kongo">Kongo</label><select class="lang-level" name="language_level" data-language="Kongo" aria-label="Level in Kongo"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-kazakh" name="languages" value="Kazakh" /><label for="ad-lang-kazakh">Kazakh</label><select class="lang-level" name="language_level" data-language="Kazakh" aria-label="Level in Kazakh"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-greenlandic" name="languages" value="Greenlandic" /><label for="ad-lang-greenlandic">Greenlandic</label><select class="lang-level" name="language_level" data-language="Greenlandic" aria-label="Level in Greenlandic"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-cambodian" name="languages" value="Cambodian" /><label for="ad-lang-cambodian">Cambodian</label><select class="lang-level" name="language_level" data-language="Cambodian" aria-label="Level in Cambodian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-korean" name="languages" value="Korean" /><label for="ad-lang-korean">Korean</label><select class="lang-level" name="language_level" data-language="Korean" aria-label="Level in Korean"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-kurdish" name="languages" value="Kurdish" /><label for="ad-lang-kurdish">Kurdish</label><select class="lang-level" name="language_level" data-language="Kurdish" aria-label="Level in Kurdish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-kyrgyz" name="languages" value="Kyrgyz" /><label for="ad-lang-kyrgyz">Kyrgyz</label><select class="lang-level" name="language_level" data-language="Kyrgyz" aria-label="Level in Kyrgyz"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-latin" name="languages" value="Latin" /><label for="ad-lang-latin">Latin</label><select class="lang-level" name="language_level" data-language="Latin" aria-label="Level in Latin"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-luxembourgish" name="languages" value="Luxembourgish" /><label for="ad-lang-luxembourgish">Luxembourgish</label><select class="lang-level" name="language_level" data-language="Luxembourgish" aria-label="Level in Luxembourgish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-lingala" name="languages" value="Lingala" /><label for="ad-lang-lingala">Lingala</label><select class="lang-level" name="language_level" data-language="Lingala" aria-label="Level in Lingala"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-laotian" name="languages" value="Laotian" /><label for="ad-lang-laotian">Laotian</label><select class="lang-level" name="language_level" data-language="Laotian" aria-label="Level in Laotian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-lithuanian" name="languages" value="Lithuanian" /><label for="ad-lang-lithuanian">Lithuanian</label><select class="lang-level" name="language_level" data-language="Lithuanian" aria-label="Level in Lithuanian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-luba-katanga" name="languages" value="Luba-Katanga" /><label for="ad-lang-luba-katanga">Luba-Katanga</label><select class="lang-level" name="language_level" data-language="Luba-Katanga" aria-label="Level in Luba-Katanga"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-latvian" name="languages" value="Latvian" /><label for="ad-lang-latvian">Latvian</label><select class="lang-level" name="language_level" data-language="Latvian" aria-label="Level in Latvian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-malagasy" name="languages" value="Malagasy" /><label for="ad-lang-malagasy">Malagasy</label><select class="lang-level" name="language_level" data-language="Malagasy" aria-label="Level in Malagasy"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-marshallese" name="languages" value="Marshallese" /><label for="ad-lang-marshallese">Marshallese</label><select class="lang-level" name="language_level" data-language="Marshallese" aria-label="Level in Marshallese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-maori" name="languages" value="Maori" /><label for="ad-lang-maori">Maori</label><select class="lang-level" name="language_level" data-language="Maori" aria-label="Level in Maori"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-macedonian" name="languages" value="Macedonian" /><label for="ad-lang-macedonian">Macedonian</label><select class="lang-level" name="language_level" data-language="Macedonian" aria-label="Level in Macedonian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-mongolian" name="languages" value="Mongolian" /><label for="ad-lang-mongolian">Mongolian</label><select class="lang-level" name="language_level" data-language="Mongolian" aria-label="Level in Mongolian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-malay" name="languages" value="Malay" /><label for="ad-lang-malay">Malay</label><select class="lang-level" name="language_level" data-language="Malay" aria-label="Level in Malay"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-maltese" name="languages" value="Maltese" /><label for="ad-lang-maltese">Maltese</label><select class="lang-level" name="language_level" data-language="Maltese" aria-label="Level in Maltese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-burmese" name="languages" value="Burmese" /><label for="ad-lang-burmese">Burmese</label><select class="lang-level" name="language_level" data-language="Burmese" aria-label="Level in Burmese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-nauruan" name="languages" value="Nauruan" /><label for="ad-lang-nauruan">Nauruan</label><select class="lang-level" name="language_level" data-language="Nauruan" aria-label="Level in Nauruan"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-norwegian-bokmål" name="languages" value="Norwegian Bokmål" /><label for="ad-lang-norwegian-bokmål">Norwegian Bokmål</label><select class="lang-level" name="language_level" data-language="Norwegian Bokmål" aria-label="Level in Norwegian Bokmål"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-north-ndebele" name="languages" value="North Ndebele" /><label for="ad-lang-north-ndebele">North Ndebele</label><select class="lang-level" name="language_level" data-language="North Ndebele" aria-label="Level in North Ndebele"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-nepali" name="languages" value="Nepali" /><label for="ad-lang-nepali">Nepali</label><select class="lang-level" name="language_level" data-language="Nepali" aria-label="Level in Nepali"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-dutch" name="languages" value="Dutch" /><label for="ad-lang-dutch">Dutch</label><select class="lang-level" name="language_level" data-language="Dutch" aria-label="Level in Dutch"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-norwegian-nynorsk" name="languages" value="Norwegian Nynorsk" /><label for="ad-lang-norwegian-nynorsk">Norwegian Nynorsk</label><select class="lang-level" name="language_level" data-language="Norwegian Nynorsk" aria-label="Level in Norwegian Nynorsk"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-norwegian" name="languages" value="Norwegian" /><label for="ad-lang-norwegian">Norwegian</label><select class="lang-level" name="language_level" data-language="Norwegian" aria-label="Level in Norwegian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-south-ndebele" name="languages" value="South Ndebele" /><label for="ad-lang-south-ndebele">South Ndebele</label><select class="lang-level" name="language_level" data-language="South Ndebele" aria-label="Level in South Ndebele"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-chichewa" name="languages" value="Chichewa" /><label for="ad-lang-chichewa">Chichewa</label><select class="lang-level" name="language_level" data-language="Chichewa" aria-label="Level in Chichewa"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-occitan" name="languages" value="Occitan" /><label for="ad-lang-occitan">Occitan</label><select class="lang-level" name="language_level" data-language="Occitan" aria-label="Level in Occitan"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-panjabi-/-punjabi" name="languages" value="Panjabi / Punjabi" /><label for="ad-lang-panjabi-/-punjabi">Panjabi / Punjabi</label><select class="lang-level" name="language_level" data-language="Panjabi / Punjabi" aria-label="Level in Panjabi / Punjabi"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-polish" name="languages" value="Polish" /><label for="ad-lang-polish">Polish</label><select class="lang-level" name="language_level" data-language="Polish" aria-label="Level in Polish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-pashto" name="languages" value="Pashto" /><label for="ad-lang-pashto">Pashto</label><select class="lang-level" name="language_level" data-language="Pashto" aria-label="Level in Pashto"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-portuguese" name="languages" value="Portuguese" /><label for="ad-lang-portuguese">Portuguese</label><select class="lang-level" name="language_level" data-language="Portuguese" aria-label="Level in Portuguese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-quechua" name="languages" value="Quechua" /><label for="ad-lang-quechua">Quechua</label><select class="lang-level" name="language_level" data-language="Quechua" aria-label="Level in Quechua"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-kirundi" name="languages" value="Kirundi" /><label for="ad-lang-kirundi">Kirundi</label><select class="lang-level" name="language_level" data-language="Kirundi" aria-label="Level in Kirundi"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-romanian" name="languages" value="Romanian" /><label for="ad-lang-romanian">Romanian</label><select class="lang-level" name="language_level" data-language="Romanian" aria-label="Level in Romanian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-russian" name="languages" value="Russian" /><label for="ad-lang-russian">Russian</label><select class="lang-level" name="language_level" data-language="Russian" aria-label="Level in Russian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-rwandi" name="languages" value="Rwandi" /><label for="ad-lang-rwandi">Rwandi</label><select class="lang-level" name="language_level" data-language="Rwandi" aria-label="Level in Rwandi"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-sango" name="languages" value="Sango" /><label for="ad-lang-sango">Sango</label><select class="lang-level" name="language_level" data-language="Sango" aria-label="Level in Sango"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-sinhalese" name="languages" value="Sinhalese" /><label for="ad-lang-sinhalese">Sinhalese</label><select class="lang-level" name="language_level" data-language="Sinhalese" aria-label="Level in Sinhalese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-slovak" name="languages" value="Slovak" /><label for="ad-lang-slovak">Slovak</label><select class="lang-level" name="language_level" data-language="Slovak" aria-label="Level in Slovak"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-slovenian" name="languages" value="Slovenian" /><label for="ad-lang-slovenian">Slovenian</label><select class="lang-level" name="language_level" data-language="Slovenian" aria-label="Level in Slovenian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-samoan" name="languages" value="Samoan" /><label for="ad-lang-samoan">Samoan</label><select class="lang-level" name="language_level" data-language="Samoan" aria-label="Level in Samoan"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-shona" name="languages" value="Shona" /><label for="ad-lang-shona">Shona</label><select class="lang-level" name="language_level" data-language="Shona" aria-label="Level in Shona"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-somalia" name="languages" value="Somalia" /><label for="ad-lang-somalia">Somalia</label><select class="lang-level" name="language_level" data-language="Somalia" aria-label="Level in Somalia"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-albanian" name="languages" value="Albanian" /><label for="ad-lang-albanian">Albanian</label><select class="lang-level" name="language_level" data-language="Albanian" aria-label="Level in Albanian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-serbian" name="languages" value="Serbian" /><label for="ad-lang-serbian">Serbian</label><select class="lang-level" name="language_level" data-language="Serbian" aria-label="Level in Serbian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-swati" name="languages" value="Swati" /><label for="ad-lang-swati">Swati</label><select class="lang-level" name="language_level" data-language="Swati" aria-label="Level in Swati"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-southern-sotho" name="languages" value="Southern Sotho" /><label for="ad-lang-southern-sotho">Southern Sotho</label><select class="lang-level" name="language_level" data-language="Southern Sotho" aria-label="Level in Southern Sotho"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-swedish" name="languages" value="Swedish" /><label for="ad-lang-swedish">Swedish</label><select class="lang-level" name="language_level" data-language="Swedish" aria-label="Level in Swedish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-swahili" name="languages" value="Swahili" /><label for="ad-lang-swahili">Swahili</label><select class="lang-level" name="language_level" data-language="Swahili" aria-label="Level in Swahili"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tamil" name="languages" value="Tamil" /><label for="ad-lang-tamil">Tamil</label><select class="lang-level" name="language_level" data-language="Tamil" aria-label="Level in Tamil"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tajik" name="languages" value="Tajik" /><label for="ad-lang-tajik">Tajik</label><select class="lang-level" name="language_level" data-language="Tajik" aria-label="Level in Tajik"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-thai" name="languages" value="Thai" /><label for="ad-lang-thai">Thai</label><select class="lang-level" name="language_level" data-language="Thai" aria-label="Level in Thai"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tigrinya" name="languages" value="Tigrinya" /><label for="ad-lang-tigrinya">Tigrinya</label><select class="lang-level" name="language_level" data-language="Tigrinya" aria-label="Level in Tigrinya"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-turkmen" name="languages" value="Turkmen" /><label for="ad-lang-turkmen">Turkmen</label><select class="lang-level" name="language_level" data-language="Turkmen" aria-label="Level in Turkmen"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tswana" name="languages" value="Tswana" /><label for="ad-lang-tswana">Tswana</label><select class="lang-level" name="language_level" data-language="Tswana" aria-label="Level in Tswana"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tonga" name="languages" value="Tonga" /><label for="ad-lang-tonga">Tonga</label><select class="lang-level" name="language_level" data-language="Tonga" aria-label="Level in Tonga"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-turkish" name="languages" value="Turkish" /><label for="ad-lang-turkish">Turkish</label><select class="lang-level" name="language_level" data-language="Turkish" aria-label="Level in Turkish"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-tsonga" name="languages" value="Tsonga" /><label for="ad-lang-tsonga">Tsonga</label><select class="lang-level" name="language_level" data-language="Tsonga" aria-label="Level in Tsonga"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-ukrainian" name="languages" value="Ukrainian" /><label for="ad-lang-ukrainian">Ukrainian</label><select class="lang-level" name="language_level" data-language="Ukrainian" aria-label="Level in Ukrainian"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-urdu" name="languages" value="Urdu" /><label for="ad-lang-urdu">Urdu</label><select class="lang-level" name="language_level" data-language="Urdu" aria-label="Level in Urdu"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-uzbek" name="languages" value="Uzbek" /><label for="ad-lang-uzbek">Uzbek</label><select class="lang-level" name="language_level" data-language="Uzbek" aria-label="Level in Uzbek"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-venda" name="languages" value="Venda" /><label for="ad-lang-venda">Venda</label><select class="lang-level" name="language_level" data-language="Venda" aria-label="Level in Venda"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-vietnamese" name="languages" value="Vietnamese" /><label for="ad-lang-vietnamese">Vietnamese</label><select class="lang-level" name="language_level" data-language="Vietnamese" aria-label="Level in Vietnamese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-xhosa" name="languages" value="Xhosa" /><label for="ad-lang-xhosa">Xhosa</label><select class="lang-level" name="language_level" data-language="Xhosa" aria-label="Level in Xhosa"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-chinese" name="languages" value="Chinese" /><label for="ad-lang-chinese">Chinese</label><select class="lang-level" name="language_level" data-language="Chinese" aria-label="Level in Chinese"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<span class="lang-pick"><input type="checkbox" id="ad-lang-zulu" name="languages" value="Zulu" /><label for="ad-lang-zulu">Zulu</label><select class="lang-level" name="language_level" data-language="Zulu" aria-label="Level in Zulu"><option value="">—</option><option value="native">native</option><option value="fluent">fluent</option><option value="advanced">advanced</option><option value="intermediate">intermediate</option><option value="beginner">beginner</option></select></span>
|
||||
<!-- LANGUAGE-OPTIONS-END -->
|
||||
<div class="focus-axis">
|
||||
<label for="ad-axis-system">System</label>
|
||||
<input type="range" id="ad-axis-system" name="system" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-axis-system">0</output>
|
||||
</div>
|
||||
<span class="hint">Each language is stored by its standard name, so the directory filter never gets a name like “Spanish - beginners”. A level is optional.</span>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-axis-modules">Modules</label>
|
||||
<input type="range" id="ad-axis-modules" name="modules" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-axis-modules">0</output>
|
||||
</div>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-axis-integration">Integration</label>
|
||||
<input type="range" id="ad-axis-integration" name="integration" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-axis-integration">0</output>
|
||||
</div>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-axis-ai">AI</label>
|
||||
<input type="range" id="ad-axis-ai" name="ai" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-axis-ai">0</output>
|
||||
</div>
|
||||
<p class="focus-total" id="adFocusTotal" aria-live="polite">0 of 15 points</p>
|
||||
<p class="focus-warn" id="adFocusWarn" role="alert"></p>
|
||||
<p class="focus-scale">How much of the freelancer's work each area is — 0 to 5, totalling 15. Leave all five at 0 to leave the profile untouched (a save then keeps the record's current numbers); any other value must total exactly 15.</p>
|
||||
</fieldset>
|
||||
<div class="form-field">
|
||||
<label for="adSpecialities">Specialities</label>
|
||||
<input id="adSpecialities" name="specialities" type="text" />
|
||||
<span class="hint">Separate with commas.</span>
|
||||
<fieldset class="form-field full lang-field">
|
||||
<legend>Languages — 0 to 5, same scale as the public form</legend>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-lang-english">English</label>
|
||||
<input type="range" id="ad-lang-english" name="english" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-lang-english">0</output>
|
||||
</div>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-lang-german">German</label>
|
||||
<input type="range" id="ad-lang-german" name="german" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-lang-german">0</output>
|
||||
</div>
|
||||
<div class="focus-axis">
|
||||
<label for="ad-lang-spanish">Spanish</label>
|
||||
<input type="range" id="ad-lang-spanish" name="spanish" min="0" max="5" step="1" value="0" />
|
||||
<output for="ad-lang-spanish">0</output>
|
||||
</div>
|
||||
<p class="focus-scale">0 means “cannot speak it”; 5 means “native”. The applicant's own assessment.</p>
|
||||
</fieldset>
|
||||
<div class="form-field">
|
||||
<label for="adGithub">GitHub URL</label>
|
||||
<input id="adGithub" name="github" type="text" inputmode="url" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="adOca">OCA profile URL</label>
|
||||
<input id="adOca" name="oca_profile" type="text" inputmode="url" />
|
||||
<input id="adOca" name="OCA_link" type="text" inputmode="url" />
|
||||
<span class="hint">The OCA member profile link. A chip leads to it from the card when the host is apps.odoo-community.org and the path is /community/…</span>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="adLinkedin">LinkedIn URL</label>
|
||||
@@ -702,10 +687,6 @@
|
||||
<input id="adImage" name="Image" type="text" inputmode="url" />
|
||||
<span class="hint">A link (https://…). A photo shows on the card only when this is a link — an inline/base64 image is not displayed.</span>
|
||||
</div>
|
||||
<label class="form-check">
|
||||
<input type="checkbox" name="OCA_member" value="1" />
|
||||
<span>OCA member.</span>
|
||||
</label>
|
||||
<label class="form-check">
|
||||
<input type="checkbox" name="is_individual" value="1" />
|
||||
<span>Works as an individual.</span>
|
||||
@@ -731,30 +712,33 @@
|
||||
POST without an id → CREATE a new record
|
||||
Email confirmation applies to both paths.
|
||||
|
||||
READ-MODIFY-WRITE (the reason this page loads the record first): a boolean the
|
||||
READ-MODIFY-WRITE (the reason this page loads the record first): a value the
|
||||
owner did not touch must keep the record's CURRENT value. Loading the record
|
||||
syncs the checkboxes to it, so an untouched box sends what the record already
|
||||
holds instead of flipping it to false. An edit is refused until the record has
|
||||
been loaded and confirmed — a bare numeric id can no longer edit the wrong person.
|
||||
syncs every control to it, so an untouched control sends what the record already
|
||||
holds. An edit is refused until the record has been loaded and confirmed.
|
||||
|
||||
The focus block: left all-zero it is simply NOT sent (an unrelated correction
|
||||
must stay savable); any other value must total exactly 15.
|
||||
============================================================================ */
|
||||
var ODOO_EXPERTS_WEBHOOK =
|
||||
"https://n8n.odoo4projects.com/webhook/ODOO4projects/odoo_experts";
|
||||
|
||||
var MULTI_FIELDS = ["odoo_versions"]; // comma-separated → array
|
||||
// `languages` and `specialities` are COMMA-SEPARATED STRINGS on the wire
|
||||
// ("English,German"), NOT arrays. `odoo_versions` stays an array.
|
||||
var CSV_STRING_FIELDS = ["languages", "specialities"];
|
||||
var BOOL_FIELDS = ["OCA_member", "is_individual"];
|
||||
var NUM_FIELDS = ["odoo4projects_clients"];
|
||||
var FOCUS_AXES = ["functional", "system", "modules", "integration", "ai"];
|
||||
var FOCUS_TOTAL = 15;
|
||||
var FOCUS_MAX = 5;
|
||||
var FOCUS_MAX_CHARS = 70;
|
||||
var LANG_FIELDS = [["english", "English"], ["german", "German"], ["spanish", "Spanish"]];
|
||||
// Country VALUE FORMAT — what the Country select sends to the webhook.
|
||||
// "code" → the ISO 3166-1 alpha-2 code, e.g. "DE" (default; stable, exact-matchable)
|
||||
// "name" → the full English name, e.g. "Germany" (switch to this line if the
|
||||
// workflow expects names instead of codes)
|
||||
// The select always DISPLAYS the English name; this only changes the SUBMITTED value.
|
||||
// "code" → the ISO 3166-1 alpha-2 code, e.g. "DE" (default)
|
||||
// "name" → the full English name, e.g. "Germany"
|
||||
var COUNTRY_VALUE_FORMAT = "code";
|
||||
var BOOL_FIELDS = ["is_individual"];
|
||||
var NUM_FIELDS = ["odoo4projects_clients"].concat(FOCUS_AXES).concat(
|
||||
LANG_FIELDS.map(function (p) { return p[0]; })
|
||||
);
|
||||
var TEXT_FIELDS = [
|
||||
"Name", "email", "Focus", "description", "Country",
|
||||
"Linkedin", "upwork", "fiverr", "github", "oca_profile", "Image"
|
||||
"Linkedin", "upwork", "fiverr", "github", "OCA_link", "Image"
|
||||
];
|
||||
|
||||
var loadedRecord = null;
|
||||
@@ -765,7 +749,6 @@
|
||||
);
|
||||
}
|
||||
|
||||
/* Lower-case and strip accents ("Zürich" -> "zurich"). */
|
||||
function fold(text) {
|
||||
return String(text == null ? "" : text)
|
||||
.normalize("NFD")
|
||||
@@ -773,22 +756,13 @@
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
/* Comma-separated tokens from any shape of field: a text box split on commas, or the
|
||||
`languages` checklist read as its checked values. One wire shape either way. */
|
||||
function collectCsvTokens(els) {
|
||||
var out = [];
|
||||
els.forEach(function (el) {
|
||||
if (el.type === "checkbox" || el.type === "radio") {
|
||||
if (el.checked && el.value) out.push(el.value.trim());
|
||||
} else {
|
||||
(el.value || "").split(",").forEach(function (part) { out.push(part.trim()); });
|
||||
}
|
||||
});
|
||||
return out.filter(Boolean);
|
||||
function intOr(value, fallback) {
|
||||
var n = parseInt(value, 10);
|
||||
return isNaN(n) ? fallback : n;
|
||||
}
|
||||
|
||||
/* The Country value to submit: the ISO code by default, the English name when
|
||||
COUNTRY_VALUE_FORMAT is "name". Empty until the owner picks a country. */
|
||||
function clamp05(n) { return Math.max(0, Math.min(FOCUS_MAX, n)); }
|
||||
|
||||
function countryValue(form) {
|
||||
var sel = form.querySelector('select[name="Country"]');
|
||||
if (!sel || !sel.value) return "";
|
||||
@@ -806,17 +780,59 @@
|
||||
else el.removeAttribute("data-state");
|
||||
}
|
||||
|
||||
/* The webhook casing is inconsistent; read a field's value by its known names. */
|
||||
function recordField(rec, name) {
|
||||
if (rec[name] !== undefined) return rec[name];
|
||||
if (name === "Country" && rec.country !== undefined) return rec.country;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function joinMulti(value) {
|
||||
if (value == null) return "";
|
||||
if (Array.isArray(value)) return value.join(", ");
|
||||
return String(value);
|
||||
function focusSum(form) {
|
||||
return FOCUS_AXES.reduce(function (s, axis) {
|
||||
var el = form.querySelector('[name="' + axis + '"]');
|
||||
return s + (el ? intOr(el.value, 0) : 0);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function focusError(form, required) {
|
||||
var sum = focusSum(form);
|
||||
if (sum === 0) {
|
||||
return required ? "Distribute all 15 points across the five areas." : "";
|
||||
}
|
||||
if (sum !== FOCUS_TOTAL) {
|
||||
return "The five focus numbers total " + sum + ". They must total exactly " +
|
||||
FOCUS_TOTAL + " (or all be 0 to leave the profile untouched).";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function refreshFocus(form) {
|
||||
var sum = 0;
|
||||
FOCUS_AXES.forEach(function (axis) {
|
||||
var el = form.querySelector('[name="' + axis + '"]');
|
||||
if (!el) return;
|
||||
var n = clamp05(intOr(el.value, 0));
|
||||
el.value = String(n);
|
||||
sum += n;
|
||||
var out = el.parentNode ? el.parentNode.querySelector("output") : null;
|
||||
if (out) out.textContent = String(n);
|
||||
el.setAttribute("aria-valuetext", n + " of " + FOCUS_MAX);
|
||||
});
|
||||
var langs = form.querySelectorAll(".lang-field input[type=range]");
|
||||
Array.prototype.forEach.call(langs, function (el) {
|
||||
var n = clamp05(intOr(el.value, 0));
|
||||
el.value = String(n);
|
||||
var out = el.parentNode ? el.parentNode.querySelector("output") : null;
|
||||
if (out) out.textContent = String(n);
|
||||
el.setAttribute("aria-valuetext", n + " of " + FOCUS_MAX);
|
||||
});
|
||||
var total = document.getElementById("adFocusTotal");
|
||||
if (total) total.textContent = sum + " of " + FOCUS_TOTAL + " points";
|
||||
var warn = document.getElementById("adFocusWarn");
|
||||
if (warn) {
|
||||
warn.textContent = (sum === 0 || sum === FOCUS_TOTAL)
|
||||
? ""
|
||||
: "You have " + sum + " of 15. The five must total exactly 15, or all be 0 to leave the profile untouched.";
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy a loaded record into the form, so an untouched field carries the record's
|
||||
@@ -829,10 +845,6 @@
|
||||
var v = recordField(rec, name);
|
||||
el.value = v == null ? "" : String(v);
|
||||
});
|
||||
MULTI_FIELDS.forEach(function (name) {
|
||||
var el = form.querySelector('[name="' + name + '"]');
|
||||
if (el) el.value = joinMulti(recordField(rec, name));
|
||||
});
|
||||
var clients = form.querySelector('[name="odoo4projects_clients"]');
|
||||
if (clients) {
|
||||
var n = rec.odoo4projects_clients;
|
||||
@@ -845,27 +857,23 @@
|
||||
box.checked = val;
|
||||
box.dataset.loaded = val ? "true" : "false";
|
||||
});
|
||||
// Languages: the standardised checklist. A stored token ticks a box when it IS a
|
||||
// standard name or begins with one ("Spanish - beginners" -> Spanish); its level,
|
||||
// where `language_levels` records one, goes in the level select beside it.
|
||||
var langs = String(recordField(rec, "languages") || "").split(",")
|
||||
.map(function (s) { return s.trim(); }).filter(Boolean);
|
||||
var levels = {};
|
||||
String(recordField(rec, "language_levels") || "").split(",").forEach(function (pair) {
|
||||
var bits = pair.split(":");
|
||||
if (bits.length === 2) levels[fold(bits[0])] = bits[1].trim();
|
||||
// The five focus axes and the three languages — plain numbers, read off the
|
||||
// record. A field the record does not carry stays 0 (and the block is left
|
||||
// unsent unless it totals 15).
|
||||
FOCUS_AXES.forEach(function (axis) {
|
||||
var el = form.querySelector('[name="' + axis + '"]');
|
||||
if (el) el.value = String(clamp05(intOr(rec[axis], 0)));
|
||||
});
|
||||
Array.prototype.forEach.call(form.querySelectorAll('input[name="languages"]'), function (box) {
|
||||
var fb = fold(box.value);
|
||||
var on = langs.some(function (t) {
|
||||
var ft = fold(t);
|
||||
return ft === fb || ft.indexOf(fb + " ") === 0 || ft.indexOf(fb + "-") === 0 || ft.indexOf(fb + "(") === 0;
|
||||
});
|
||||
box.checked = on;
|
||||
var row = box.closest(".lang-pick");
|
||||
var sel = row ? row.querySelector("select") : null;
|
||||
if (sel) sel.value = on && levels[fb] ? levels[fb] : "";
|
||||
LANG_FIELDS.forEach(function (p) {
|
||||
var el = form.querySelector('[name="' + p[0] + '"]');
|
||||
if (el) el.value = String(clamp05(intOr(rec[p[0]], 0)));
|
||||
});
|
||||
refreshFocus(form);
|
||||
var focusInput = document.getElementById("adFocus");
|
||||
var focusCount = document.getElementById("adFocusCount");
|
||||
if (focusInput && focusCount) {
|
||||
focusCount.textContent = focusInput.value.length + " / " + FOCUS_MAX_CHARS;
|
||||
}
|
||||
}
|
||||
|
||||
function loadRecord() {
|
||||
@@ -879,9 +887,7 @@
|
||||
}
|
||||
setStatus(info, "Loading record " + idRaw + "…", null);
|
||||
fetch(ODOO_EXPERTS_WEBHOOK, { method: "GET" })
|
||||
.then(function (r) {
|
||||
return r.json();
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (payload) {
|
||||
var list = Array.isArray(payload) ? payload : (payload && payload.data) || [];
|
||||
var rec = null;
|
||||
@@ -930,47 +936,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (MULTI_FIELDS.indexOf(name) !== -1) {
|
||||
var text = els[0].value || "";
|
||||
var list = text
|
||||
.split(",")
|
||||
.map(function (s) {
|
||||
return s.trim();
|
||||
})
|
||||
.filter(Boolean);
|
||||
if (list.length) payload[name] = list; // an empty box must not wipe the field
|
||||
return;
|
||||
}
|
||||
|
||||
if (name === "language_level") {
|
||||
// Proficiency is a SEPARATE AXIS: a level rides in `language_levels`
|
||||
// ("Spanish:beginner"), never inside a language name.
|
||||
var pairs = [];
|
||||
Array.prototype.forEach.call(
|
||||
form.querySelectorAll('input[name="languages"]:checked'),
|
||||
function (box) {
|
||||
var row = box.closest(".lang-pick");
|
||||
var sel = row ? row.querySelector("select") : null;
|
||||
if (sel && sel.value) pairs.push(box.value + ":" + sel.value);
|
||||
}
|
||||
);
|
||||
if (pairs.length) payload.language_levels = pairs.join(",");
|
||||
return;
|
||||
}
|
||||
|
||||
if (CSV_STRING_FIELDS.indexOf(name) !== -1) {
|
||||
// Normalise to the wire shape: trim each entry, drop blanks, re-join. A text
|
||||
// box is split on commas; the `languages` checklist is read as its checked
|
||||
// values. Nothing selected → the field is omitted, so a save cannot wipe it.
|
||||
var norm = collectCsvTokens(els).join(",");
|
||||
if (norm) payload[name] = norm;
|
||||
return;
|
||||
}
|
||||
|
||||
if (BOOL_FIELDS.indexOf(name) !== -1) {
|
||||
var box = els[0];
|
||||
if (withId && box.dataset.loaded !== undefined) {
|
||||
// READ-MODIFY-WRITE: an untouched box keeps the record's current value.
|
||||
var original = box.dataset.loaded === "true";
|
||||
var now = !!box.checked;
|
||||
payload[name] = now === original ? original : now;
|
||||
@@ -981,8 +949,11 @@
|
||||
}
|
||||
|
||||
if (NUM_FIELDS.indexOf(name) !== -1) {
|
||||
var n = els[0].value.trim();
|
||||
if (n !== "") payload[name] = Number(n);
|
||||
// A focus block that is not a valid 15 is left unsent, so an update cannot
|
||||
// wipe it (the gate already refused a half-set block).
|
||||
if (FOCUS_AXES.indexOf(name) !== -1 && focusSum(form) !== FOCUS_TOTAL) return;
|
||||
var nv = els[0].value.trim();
|
||||
if (nv !== "") payload[name] = Number(nv);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1009,7 +980,6 @@
|
||||
|
||||
document.getElementById("adLoadBtn").addEventListener("click", loadRecord);
|
||||
|
||||
// Changing the id after a load invalidates the confirmation.
|
||||
form.querySelector('[name="id"]').addEventListener("input", function () {
|
||||
if (loadedRecord && String(loadedRecord.id) !== this.value.trim()) {
|
||||
loadedRecord = null;
|
||||
@@ -1017,6 +987,22 @@
|
||||
}
|
||||
});
|
||||
|
||||
Array.prototype.forEach.call(form.querySelectorAll(".focus-field input, .lang-field input"),
|
||||
function (el) { el.addEventListener("input", function () { refreshFocus(form); }); });
|
||||
|
||||
var focusInput = document.getElementById("adFocus");
|
||||
var focusCount = document.getElementById("adFocusCount");
|
||||
if (focusInput && focusCount) {
|
||||
var refreshCount = function () {
|
||||
var n = focusInput.value.length;
|
||||
focusCount.textContent = n + " / " + FOCUS_MAX_CHARS;
|
||||
focusCount.setAttribute("data-over", n > FOCUS_MAX_CHARS ? "1" : "0");
|
||||
};
|
||||
focusInput.addEventListener("input", refreshCount);
|
||||
refreshCount();
|
||||
}
|
||||
refreshFocus(form);
|
||||
|
||||
form.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
if (!form.reportValidity()) return;
|
||||
@@ -1024,11 +1010,17 @@
|
||||
var hasId = !!idRaw;
|
||||
|
||||
if (hasId && (!loadedRecord || String(loadedRecord.id) !== idRaw)) {
|
||||
setStatus(
|
||||
status,
|
||||
setStatus(status,
|
||||
"Load the record first (Load this record) and confirm it is the right person. Nothing was saved.",
|
||||
"err"
|
||||
);
|
||||
"err");
|
||||
return;
|
||||
}
|
||||
|
||||
var focusMsg = focusError(form, false);
|
||||
if (focusMsg) {
|
||||
setStatus(status, focusMsg, "err");
|
||||
var warn = document.getElementById("adFocusWarn");
|
||||
if (warn) warn.textContent = focusMsg;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1038,22 +1030,19 @@
|
||||
|
||||
postToWebhook(buildPayload(form, true))
|
||||
.then(function () {
|
||||
setStatus(
|
||||
status,
|
||||
setStatus(status,
|
||||
hasId
|
||||
? "Saved. Check your inbox to confirm the change before it is applied."
|
||||
: "New record sent. Check your inbox to confirm it before it goes live.",
|
||||
"ok"
|
||||
);
|
||||
"ok");
|
||||
})
|
||||
.catch(function () {
|
||||
setStatus(status, "That did not save. Please try again.", "err");
|
||||
})
|
||||
.then(function () {
|
||||
submit.disabled = false;
|
||||
});
|
||||
.then(function () { submit.disabled = false; });
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user